RE: [scripting] hair geometry

Date : Thu, 25 May 2006 17:17:05 +0000
To : XSI(at)Softimage.COM
From : "brad" <brad(at)cg-soup.com>
Subject : RE: [scripting] hair geometry
Time to summon the Wiki fairy... 

>  Here is a more in-depth JScript of how to play with hair... it's a JScript
>  so you will need to convert it to Python but it shows a lot of examples of
>  how to access different elements and how to find the right connected point
>  from the emmitting geometry. I hope it can help out and if you have anymore
>  questions, let us know! I'm assuming in this script you have allready
>  created a hair object and it is named "hair" and that it has at least 4
>  guide hairs...
>  
>  
>  
>  
>  //Get hair object
>  var oHair = Dictionary.GetObject( "Hair", false );
>  
>  //Get hair points
>  var oPoints = oHair.Activeprimitive.Geometry.Points;
>  
>  //get count and position array
>  var nb_HairPts = oPoints.count;
>  var nb_HairGuides = nb_HairPts/14;
>  var oPointsPositionArray = oPoints.PositionArray.toArray();
>  
>  //To get global transform for point positions
>  var oMatrix = XSIMath.CreateMatrix4();
>  var oPt = XSIMath.CreateVector3();
>  oHair.Kinematics.Global.Transform.GetMatrix4(oMatrix);
>  
>  //log position information
>  for ( var i=0; i<oPointsPositionArray.length; i+=3 ) {
>  var no_hair = parseInt(oPoints(i/3).index/14); //the same as
>  "parseInt((i/3)/14)" or "parseInt(i/42)"
>  var guidePtNb = oPoints(i/3).index%14;
>  LogMessage(oHair.fullname+".pnt[("+no_hair+","+guidePtNb+")] has local
>  position of ("
>  +oPointsPositionArray[i]+","+oPointsPositionArray[i+1]+","+oPointsPositio
>  nArray[i+2]+")");
>  
>  oPt.Set(oPointsPositionArray[i], oPointsPositionArray[i+1],
>  oPointsPositionArray[i+2]);
>  oPt.MulByMatrix4InPlace(oMatrix);
>  LogMessage(oHair.fullname+".pnt[("+no_hair+","+guidePtNb+")] has global
>  position of ("
>  +oPt.x+","+oPt.y+","+oPt.z+")");
>  }
>  
>  //select a hair point
>  SelectGeometryComponents("Hair.pnt[(3,13)]");
>  var oPtSel = Selection(0);
>  var oPtColl = oPtSel.SubComponent.ComponentCollection;
>  
>  logmessage("number of hair points: "+nb_HairPts);
>  logmessage("number of guide hairs: "+nb_HairGuides);
>  logmessage("number of selected points: "+oPtColl.count);
>  logmessage("index of first point selected: "+oPtColl(0).index);
>  
>  //reselects the same point... just for demonstration reasons
>  SelectGeometryComponents(oHair.fullname+".pnt["+oPtColl(0).index+"]");
>  
>  var no_hair = parseInt(oPtColl(0).index/14); //get the guide hair number
>  var guidePtNb = oPtColl(0).index%14; //get the point along the guide hair
>  strand (0 = root (not geometry but hair root), 13 = hair tip)
>  SelectGeometryComponents(oHair.fullname+".pnt[("+no_hair+","+guidePtNb+")]")
>  ; //yet another way to select
>  
>  
>  //to find the connected point from the hair root to the geometry, we need to
>  find the cluster if it exist:
>  var oConstructionHistory = oHair.Activeprimitive.ConstructionHistory;
>  var oHairGenOp;
>  oEnum = new Enumerator( oConstructionHistory  );
>  for (;!oEnum.atEnd();oEnum.moveNext())
>  {
>     // Print the name of the operator
>     if (oEnum.item().name == "Hair Generator Operator") {
>  oHairGenOp = oEnum.item();
>     	 	 break;
>     	 }
>  }
>  var oCluster = FindCluster(oHairGenOp);
>  if (oCluster) {
>  LogMessage("Hair is applied on a cluster!!");
>  
>  //create a index table array that maps the hair guide index to the parent
>  polymest point index
>  var IdxMap = MapIdx_PolyCls_To_HairVtxCls(oCluster,
>  oHair.parent.ActivePrimitive.Geometry);
>  
>  //selects the polymesh point index connected to hair guide point (3,13)
>  SelectGeometryComponents(oHair.parent.fullname+".pnt["+IdxMap[no_hair]+"]")
>  ;
>  
>  //or get the point directly in object model
>  var oPt = oHair.parent.ActivePrimitive.Geometry.Points(IdxMap[no_hair]);
>  }
>  else {
>  LogMessage("Hair is applied directly on object!!");
>  
>  //no cluster, the polymesh point indices are the same as the guide hair
>  indices
>  SelectGeometryComponents(oHair.parent.fullname+".pnt["+no_hair+"]");
>  var oPt = oHair.parent.ActivePrimitive.Geometry.Points(no_hair);
>  }
>  
>  
>  function FindCluster(op)
>  {
>  // for each port group
>  for ( var idxGroup = 0; idxGroup < op.GetNumPortGroups(); idxGroup++ )
>  {
>      // for each instance in a port group
>      for ( var idxInstance = 0; idxInstance < op.GetNumInstancesInGroup(
>  idxGroup ); idxInstance++ )
>      {
>          // for each port in a  port group instance
>          for ( var idxPort = 0; idxPort < op.GetNumPortsInGroup( idxGroup );
>  idxPort++ )
>          {
>             // get a specific port
>             var port = op.PortAt( idxPort, idxGroup, idxInstance );
>             var target = port.target2;
>             if (target != null){
>  if (target.type == "poly")
>  {
>  //poly cluster found...
>  return target;
>  }
>  }
>  
>          }
>      }
>  }
>  //no poly cluster found...
>  return null;
>  }
>  
>  
>  function MapIdx_PolyCls_To_HairVtxCls(polyCls, mesh)
>  {
>  var polysIdx = polyCls.Elements.Array.toArray();
>      var polys = mesh.Polygons;
>      var nbPolys = polysIdx.length;
>  var nbVertices = mesh.points.count;
>      var taken = new Array();
>      for (var i=0; i<nbVertices; i++) taken[i] = false;
>      var indices = new Array();
>      for (i=0; i<nbPolys; i++){
>          var face = polys(polysIdx[i]);
>          var neighs = face.Points;
>          var nbNeighs = neighs.count;
>          for (var j=0; j<nbNeighs; j++){
>              var idx = neighs(j).index;
>              if (!taken[idx]){
>                  taken[idx] = true;
>                  indices.push( idx );
>              }
>          }
>      }
>  return indices;
>  }
>  
>  -----Original Message-----
>  From: owner-xsi(at)Softimage.COM [mailto:owner-xsi(at)Softimage.COM]On Behalf
>  Of kim aldis
>  Sent: Thursday, May 25, 2006 2:46 AM
>  To: XSI(at)Softimage.COM
>  Subject: RE: [scripting] hair geometry
>  
>  
>  You can access hair point data in the same way as you do point data on a
>  poly mesh.
>  
>  var aPoints =
>  oObj.Activeprimitive.Geometry.Points.PositionArray.toArray();
>  
>  for ( var i=0; i<aPoints.length; i+=3 ) {
>  }
>  
>  The number of strands is the count of points divided by 14. It's the only
>  way to get the strand count.
>  
>  The root point of a hair strand doesn't exist in the hair point data, you
>  have to retrieve it from the emitting geometry by looping through face nodes
>  in a unique way:-
>  
>  Istrand = 0;
>  
>  For each face
>  for each node on face
>  if ( ! (point is visited) )
>  iStrand ++
>  
>  
>  Kind of thing. I usually push the point position onto an array so I can
>  index it directly.
>  
>  > -----Original Message-----
>  > From: owner-xsi(at)Softimage.COM
>  > [mailto:owner-xsi(at)Softimage.COM] On Behalf Of Greg Smith
>  > Sent: 24-May-2006 23:30
>  > To: XSI_MailingList
>  > Subject: [scripting] hair geometry
>  >
>  > Okay so I cracked my knuckles, and started to get into the
>  > nuts and bolts of the hair geometry primitive and so far I am
>  > a little frustrated. Maybe its because I am still a little
>  > wet behind the ears when tinkering with the internals of xsi,
>  > I don't know.
>  >
>  > So down to the nitty gritty. Using python, I am trying to get
>  > access at components of hair geometry object. one of the
>  > things I am having an issue with is finding a direct method
>  > in finding the total amount of guide hairs live on the hair
>  > object. Thus far I haven't found a direct method. The only
>  > thing I have come up with so far is dividing the total number
>  > of points found in the hair object by the total amount of
>  > points found in a guid hair. This gives me the appropriate
>  > number, but I would prefer something a little more elegent.
>  >
>  > Is there any way to grab the 2d array index of a point using
>  > the object model?
>  > when I select a point on one of the guide hairs, I get this
>  > line in the history log.
>  >
>  > 	 Application.SelectGeometryComponents("Hair.pnt[(27,3)]")
>  >
>  > However I don't want to use a string argument, I'd much
>  > rather use an object method, however when I try, I can't
>  > figure out how to access a point component in that method. I
>  > can gain access of a point by index number from the
>  > pointcollection using the code below.
>  >
>  > 	 xsi = Application
>  > 	 hr = xsi.ActiveSceneRoot.FindChild('Hair')
>  > 	 ohair = hr.ActivePrimitive.Geometry
>  > 	 oPnts = ohair.Points
>  >
>  > I tried appending .SubComponent to oPnts and work from there,
>  > but I can't figure out where I am supposed to proceed.
>  >
>  > any Ideas?
>  >
>  > Thanks,
>  >
>  > Greg
>  >
>  >
>  >
>  > ---
>  > Unsubscribe? Mail Majordomo(at)Softimage.COM with the following
>  > text in body:
>  > unsubscribe xsi
>  >
>  >
>  
>  ---
>  Unsubscribe? Mail Majordomo(at)Softimage.COM with the following text in body:
>  unsubscribe xsi
>  
>  
>  
>  ---
>  Unsubscribe? Mail Majordomo(at)Softimage.COM with the following text in body:
>  unsubscribe xsi
>  
---
Unsubscribe? Mail Majordomo(at)Softimage.COM with the following text in body:
unsubscribe xsi


Search the XSI List archives here or use the advanced search form to search across mailing lists. Searching help is available.
This site supposedly brought to you by Benjamin Grosser and the Imaging Technology Group.