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