THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 15/12/2005 at 02:15, xxxxxxxx wrote:
There will be some sdk examples once hair is released.
You have some options on how to create hairs.
You could create a generator object that returns a hair object (this is how the feather object works). If doing it this way then you need to create the guides in the hair object and set the hair object to As Guides. This one is a little more involved.
The easiest way is to use the hair API message MSG_HAIR_GET_OBJECT_TYPE. If a object gets this message then it can fill in the passed structure (HairPluginMessageData). Set 'data' to pointer to HairPluginObjectData which you have filled in with the function pointers (store this in your objects class). For example, the hairsdk examples has a simple grass object, the Message function looks like this:
Bool HairGrassObject::Message(GeListNode *node, LONG type, void *data)
{
if (type==MSG_HAIR_GET_OBJECT_TYPE && data)
{
HairPluginMessageData *mdata=(HairPluginMessageData* )data;
BaseContainer *bc=((BaseList2D* )node)->GetDataInstance();
m_FnTable.calc_generate=_GenerateFn;
m_FnTable.calc_col=_GenerateColor;
m_FnTable.calc_trans=_GenerateTransparency;
if (!bc->GetBool(HAIR_GRASS_GENERATE))
m_FnTable.calc_hair=_CalcHair;
else
m_FnTable.calc_hair=NULL;
mdata->data=&m_FnTable;
return TRUE;
}
return SUPER::Message(node,type,data);
}
the calc_generate function is called to init, build and free any hair data. For example:
HairGuides *_GenerateFn(BaseDocument *doc, BaseList2D *op, HairObject *hair, BaseThread *thd, VolumeData *vd, LONG pass, void *data)
{
HairGrassObject *grass=(HairGrassObject* )op->GetNodeData();
BaseContainer *bc=op->GetDataInstance();
HairGuides *hairs=NULL;
switch (pass)
{
case HAIR_GENERATE_PASS_INIT:
{
grass->m_pPoly=(PolygonObject* )bc->GetLink(HAIR_GRASS_LINK,doc,Opolygon);
if (!grass->m_pPoly) return NULL;
grass->m_Count=bc->GetLong(HAIR_GRASS_COUNT);
grass->m_Segments=bc->GetLong(HAIR_GRASS_SEGMENTS);
grass->m_Length=bc->GetReal(HAIR_GRASS_LENGTH);
grass->m_LengthVar=bc->GetReal(HAIR_GRASS_LENGTH);
grass->m_Noise=bc->GetReal(HAIR_GRASS_NOISE);
BaseContainer *hbc=hair->GetDataInstance();
hbc->SetLink(HAIRSTYLE_LINK,grass->m_pPoly);
hbc->SetLong(HAIRSTYLE_FUR_COUNT,grass->m_Count);
break;
}
case HAIR_GENERATE_PASS_BUILD:
if (bc->GetBool(HAIR_GRASS_GENERATE))
{
hairs=HairGuides::Alloc(grass->m_Count,grass->m_Segments);
if (hairs) hair->SetGuides(hairs,FALSE);
hairs=hair->GetGuides();
if (hairs)
{
Vector *pnts=hairs->GetPoints(),n(DC),r(DC);
LONG i,scnt=(grass->m_Segments+1),l=0,ply;
Vector *padr=grass->m_pPoly->GetPoint();
CPolygon *vadr=grass->m_pPoly->GetPolygon();
LONG vcnt=grass->m_pPoly->GetPolygonCount();
Real s,t;
HairRootData hroot;
hroot.m_Type=HAIR_ROOT_TYPE_POLY;
grass->m_Rnd.Init(4729848);
for (i=0;i<grass->m_Count;i++)
{
ply=LONG(grass->m_Rnd.Get01()*Real(vcnt-1));
if (vadr[ply].c==vadr[ply].d)
{
do { s=grass->m_Rnd.Get01(),t=grass->m_Rnd.Get01(); }
while ((s+t)>1.0);
}
else
{
s=grass->m_Rnd.Get01(),t=grass->m_Rnd.Get01();
}
hroot.m_ID=ply;
hroot.m_S=s;
hroot.m_T=t;
hairs->SetRoot(0,hroot,FALSE);
hairs->GetRootData(0,&r,&n,NULL,FALSE);
Real len=grass->m_Length+grass->m_LengthVar*grass->m_Rnd.Get11();
Vector dn=n;
Matrix axis;
hairs->GetRootAxis(0,axis,FALSE,FALSE);
dn.x+=grass->m_Noise*SNoise(Vector(ply,s,t));
dn.y+=grass->m_Noise*SNoise(Vector(i,ply,t));
dn.z+=grass->m_Noise*SNoise(Vector(ply,s,i));
dn=(!dn)*len;
for (l=0;l<scnt;l++)
{
pnts[i*scnt+l]=r+dn*Real(l)/Real(scnt-1);
}
}
}
}
else
hairs=HairGuides::Alloc(1,grass->m_Segments);
break;
case HAIR_GENERATE_PASS_FREE:
break;
}
return hairs;
}
the calc_hair function is called during rendering to generate per hair if this is wanted, if you do not supply this function then during build you should create all the hairs.
This is not limited to just objects, if you create a scenehook and check for the message MSG_HAIR_GET_OBJECTS then you can fill the passed AtomArray with a list of any baselist2d based object in the document that you want to have the MSG_HAIR_GET_OBJECT_TYPE message sent to.