RE: [scripting] hair geometry

Date : Thu, 25 May 2006 13:00:11 -0400
To : <XSI(at)Softimage.COM>
From : "Mathieu Leclaire" <mleclair(at)hybride.com>
Subject : RE: [scripting] hair geometry
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


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.