HAIR API
-
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. -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 22/12/2005 at 08:50, xxxxxxxx wrote:
Thank for you reply!
Is is working now, but there is one problem.
If I create PluginTag and add this Tag with Scenehook MSG_HAIR_GET_OBJECTS to the list, then C4D do not want to render the scene.
If this tag is added with Hair Material then everething is OK.Is it possible to Create own Hair Shader?
To use Normal Mapping? -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 22/12/2005 at 15:48, xxxxxxxx wrote:
For the current version the generation only works from objects.
The hair render uses standard CINEMA shaders as set by the user in the hair material, there is an extension call for these that can be passed more information from the hair (calc_sample callback).
You can also take over the color, shadow and transparency calls (calc_col, calc_shad, calc_trans). If you create a plugin tag and add this tag to a hair object then these tags are automatically sent the MSG_HAIR_GET_OBJECT_TYPE message and can set the new functions for that hair object. If you take over control of the color function directly then the function must do the lighting and shading itself. -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 08/12/2006 at 00:28, xxxxxxxx wrote:
hello..does anyone know how to create a hair material tag using coffee to access things under hair material??
thnx
Benny -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 08/12/2006 at 07:14, xxxxxxxx wrote:
not possible in coffee. well, you can create a hair material just like any other material but there is no possibility to access the hair data via COFFEE.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 09/12/2006 at 07:42, xxxxxxxx wrote:
thanks for ur reply...so there is no way to change hair color,frizz,wave..etc using coffee??
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 11/12/2006 at 03:27, xxxxxxxx wrote:
You can access the Hair paramters through XPresso. Not sure how this will help you because I don't know what you want to achieve.
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 13/12/2006 at 08:28, xxxxxxxx wrote:
hi..thanks for ur reply...i'm trying to develop a hair plugin using coffee..and create a few default hair styles to grow hair with a click of a button..is it possible to set data for hair color,frizz,wave,curl using coffee so that i could style an object?? because i dont know how to access the hair material tag using coffee because frizz curl etc is under hair material tag...i'm having a deadline to develop this plug-in, pls do reply asap if this is possible...
thanks
benny -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 14/12/2006 at 04:40, xxxxxxxx wrote:
Ok, had another look at Hair and COFFEE and it seems Hair is supported by COFFEE.
You know that you can get the description IDs by dragging them into the COFFEE script editor? Here a little script that creates a new Hair material and switches on the Bend channel and sets the Bend strength to 100 percent.
var myhairmat = AllocMaterial(Mhair); myhairmat#HAIRMATERIAL_USE_BEND = TRUE; myhairmat#HAIRMATERIAL_BEND = 1; doc->InsertMaterial(myhairmat,NULL);
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 16/12/2006 at 07:35, xxxxxxxx wrote:
hi matthias..thanks alot for ur reply..this is what i could come up with so far to grow the hair...but i dont know how to link it to my script so that the hair material tag comes up , it gives errors.i tried to use HAIRMATERIAL_COLOR_GRADIENT,vector(0.5,0.5,0.5) to change the hair color but it doesent work, but others work, like frizz etc..would u be able to look at the script and let me know how to link the hair material u sent,into my script so that it works to change parameters under hair material tag? i'm very new to C4D and coffee and quaite lost.
var doc = GetActiveDocument();
doc->InsertMaterial(AllocMaterial(Mhair), NULL);// Activates the bump channel for a material
var mat = doc->GetFirstMaterial();
mat->SetName("Hair");
//mat->SetChannelState(CHANNEL_COLOR, TRUE);
//mat->SetChannelState(CHANNEL_BUMP, FALSE);
//mat->SetChannelState(CHANNEL_SPECULAR, TRUE);// Sets a texture for it
//var color = mat->GetChannel(CHANNEL_COLOR);
//var colorBc = color->GetContainer();
//colorBc->SetData(CH_COLOR,vector(0.5,0,0));
//color->SetContainer(colorBc);var hobj = AllocObject(oHair);
var hcon = hobj->GetContainer();
var tobj = doc->FindObject("Cube");
hcon->SetData(HAIRSTYLE_HAIR_COUNT, 40000);
hcon->SetData(HAIRSTYLE_LINK,tobj);
hcon->SetData(HAIRSTYLE_FUR,true);
hcon->SetData(HAIRSTYLE_FUR_COUNT,4800);
hobj->SetContainer(hcon);// Insert a NURBS object
if(!doc->InsertObject(hobj, NULL, NULL)) return FALSE;//new - texture
var tag,nam;
nam = hobj->GetName();
hobj->InsertTag(AllocTag(Ttexture));// Messages
GeEventAdd(NEW_ACTIVE_OBJECT);
doc->Message(MSG_UPDATE);
doc->Message(DOCUMENT_CHANGED);// var mat1 = vDoc->FindMaterial("Rail");
var mat2 = doc->FindMaterial("Hair");tag = hobj->GetFirstTag();
var ma;ma = mat2->GetMarker();
while (tag)
{if (instanceof(tag,TextureTag))
{
tag->SetMaterial(ma);
}tag = tag->GetNext();
} //while end
GeEventAdd(DOCUMENT_CHANGED);
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 18/12/2006 at 02:03, xxxxxxxx wrote:
Here a little script how to get the Hair material from the hair tag and how to set the colors of the Color gradient. Not that you can't add knots to the gradients with COFFEE, so at the moment you are restricted to the two default knots. Also the script adds Hair to a selected object ( CallCommand(1018401) ).
SetHairMat(hairmat) { hairmat#HAIRMATERIAL_COLOR_GRADIENT:10100 = vector(1,0,0); hairmat#HAIRMATERIAL_COLOR_GRADIENT:10200 = vector(0,0,1); } main(doc,op) { CallCommand(1018401); var hairtag = doc->GetActiveObject()->GetFirstTag(); while(hairtag) { if(hairtag->GetType() == Thairmaterial) { SetHairMat(hairtag#HAIRMATERIAL_TAG_LINK); break; } hairtag->GetNext(); } }
hope this helps
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 18/12/2006 at 07:32, xxxxxxxx wrote:
hi matthias..the script really helped me to set the parameters under hair material...there is just one more thing that i need to know, how do u set data to change hair length , hair count and fur count? beacuse it doesent come under hair material data, so that i could add it to the script...
thanks a million for ur help.. i really appreciate it...
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 18/12/2006 at 08:14, xxxxxxxx wrote:
hi... wanted to ask u one more thing...when i execute the script u sent using the script manager it works but it doesent work when i compile it using the compiler and put it under plug-ins?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 19/12/2006 at 02:26, xxxxxxxx wrote:
Well you have to build a plugin framework first, in your case you probably want to create a menu plugin. Check the COFFEE documentation for plugin types. There is a template framework example for each plugin type. For a menu plugin this is "menuplugin.cof".
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 19/12/2006 at 07:30, xxxxxxxx wrote:
yes...i have already created the menu plug-in frame and it works... when i try to link the main script u sent to the plug-in frame there seems to be some error...the plug-in doesent show up under the plug-in menu..what i like to know is, how do u change hair length,count , fur count and use the relax button?? becasue it doesent come under hair material...it's description id's comes as "HAIRSTYLE" pls do let me know if u know how to do that and how to link it to the above program u sent earlier without any errors so that i could change hair length , count etc...
thanks again for ur replies,really appreciate it..
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 22/12/2006 at 09:38, xxxxxxxx wrote:
hi...matthias, would u b able to assist me with this last part of the coffee script which i cant figure out...which is, how to change hair length,count, fur count and relax the hair in the same script u sent me earlier, becasue i tried changing it but since these things are not under hair material, i dont know which commands to use......i would much appreciate it,if u could help me with this as soon as possible...
thanks..
cheers -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/12/2006 at 23:26, xxxxxxxx wrote:
hi...matthias, thanks alot for ur replies...would u b able to assist me with this last part of the coffee script which i cant figure out...which is, how to change hair length,count, fur count and relax the hair in the same script u sent me earlier, becasue i tried changing it but since these things are not under hair material, i dont know which commands to use......i would much appreciate it,if u could help me with this as soon as possible...
merry x mas
cheers -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 29/12/2006 at 03:09, xxxxxxxx wrote:
Here is the modified code. I am not sure what you mean with relax, if you mean the Relax button on the dynamics page then I am sorry to tell you that you can't access it with COFFEE.
SetHairMat(hairmat) { hairmat#HAIRMATERIAL_COLOR_GRADIENT:10100 = vector(1,0,0); hairmat#HAIRMATERIAL_COLOR_GRADIENT:10200 = vector(0,0,1); } main(doc,op) { CallCommand(1018401); var hairobj = doc->GetActiveObject(); hairobj#HAIRSTYLE_LENGTH = 50; //Hair length hairobj#HAIRSTYLE_HAIR_COUNT = 2500; //Hair count hairobj#HAIRSTYLE_FUR = TRUE; //switch on Fill hairs hairobj#HAIRSTYLE_FUR_COUNT = 10000; //Fill hair count hairobj#HAIRSTYLE_DYNAMICS_FRAMES = 20; //relax frame count var hairtag = hairobj->GetFirstTag(); while(hairtag) { if(hairtag->GetType() == Thairmaterial) { SetHairMat(hairtag#HAIRMATERIAL_TAG_LINK); break; } hairtag->GetNext(); } }
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 30/12/2006 at 09:10, xxxxxxxx wrote:
hi matthias...u been a gr8 help....thanks alot for ur assistance....
happy holidays
and happy new year
cheers -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 25/01/2007 at 11:03, xxxxxxxx wrote:
Is there more Examples how to proper use Hair API inside GetVirtualObjects()?
Is there any possibility to fill RootObjectData self?
What is with GetRootObject(), why is there no SetRootObject() ?C4D SDK 6.9 do not talk a lot about Hair API...