HAIR API



  • 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...



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 26/01/2007 at 03:54, xxxxxxxx wrote:

    I'll give a quick outline of how to create guides for a hair object in GetVirtualObjects, if you have anything specific you need to know then ask and I'll reply asap.

    First allocate a hair object with HairObject::Alloc(), then before you can modify or create guides you must use the Lock() function, as this is a newly created object you don't need it to run a validate (so set that to FALSE). The validate option ensures that any guides are still valid (checking the roots and root object). Just pass 0 for flags.

    Now you can start adding guides. To do this use the HairGuides::Alloc() function, passing the number of guides and segments per guide. You then need to set the guides into the hair object, so call SetGuides() from the hair object passing the guides pointer. Set clone to FALSE (otherwise it will just copy the guides leaving you to free the guides you allocated).

    Next you need to set the guides world matrix, so call SetMg() from the guides pointer. This matrix is used to transform the guides to the world origin whenever they need to be styled or transformed to a new coordinate system. This is only needed if you are creating your guides relative to something else (like a surface of an object).

    Now you can fill in the guides points, call GetPoints() from the guides pointer.

    When you have finished setting the points for the guides you just call Unlock() for the hair object.

    Before you exit GetVirtualObjects() you need to call the Update() function from the hairobject, this just runs the hair objects Execute() so that the hair updates to any changes made to the guides/parameters. Update must never be called in a lock.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 26/01/2007 at 04:47, xxxxxxxx wrote:

    Thanks David for you fast reply!

    Well this is that what I have do but without Lock() and Update(), will try wit it now.

    Actually my Guides are in most cases relative an Object. So do I need to link this object to Hair Object in some way except of SetMg()?

    Will the Hair Dynamics work now in this way?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 26/01/2007 at 06:02, xxxxxxxx wrote:

    So I have done all this and the Hair do not want to render now.
    If hair->Update(doc); will be removed then hair will be rendered but the Hair Material do not affect them.
    What is wrong?

      
    HairObject *hair = HairObject::Alloc(); if(!hair) return NULL;  
    hair->Lock(doc,thread,FALSE,0); // Loock Hair  
      
    HairGuides *hairGuides = HairGuides::Alloc(m_Count,m_Segments);  
    if (hairGuides) hair->SetGuides(hairGuides,FALSE);  
    hairGuides->SetMg(mg);  
      
    Vector     *pnts = hairGuides->GetPoints();  
      
      
    //... Create Guides ...  
      
      
    hair->Unlock(); // Unlock Hair  
    hair->Update(doc);  
    return hair;  
    


  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/01/2007 at 08:56, xxxxxxxx wrote:

    If creating a hair object from a generator as the cache will be destroyed at various times dynamics won't work as any previous data is lost. You would need to hold a copy of the hair object and update it in Execute (with Update(), this does the dynamics also).

    As for not rendering, I added a quick SDK example and this works fine (code below). Had you added the Hair Renderer? Also you would need to copy any tags from your generator to the created hair object for any materials to be used at render time.

    This is the sdk example code and seems fine:

      
    /////////////////////////////////////////////////////////////  
    // CINEMA 4D SDK                                           //  
    /////////////////////////////////////////////////////////////  
    // (c) 1989-2007 MAXON Computer GmbH, all rights reserved //  
    /////////////////////////////////////////////////////////////  
      
    // example code for creating a generator that creates Hair  
      
    //////////////////////////////////////////////////////////////////////////  
      
    #include "c4d.h"  
    #include "c4d_symbols.h"  
    #include "lib_hair.h"  
    #include "ohairsdkgen.h"  
      
    //////////////////////////////////////////////////////////////////////////  
      
    class HairGeneratorObject : public ObjectData  
    {  
         INSTANCEOF(HairGeneratorObject,ObjectData)  
      
    public:  
      
         virtual Bool Init(GeListNode *node);  
         virtual void Free(GeListNode *node);  
      
         virtual Bool Message(GeListNode *node, LONG type, void *data);  
         virtual Bool Draw(PluginObject* op, LONG drawpass, BaseDraw* bd, BaseDrawHelp* bh);  
         virtual BaseObject* GetVirtualObjects(PluginObject *op, HierarchyHelp *hh);  
      
         virtual Bool AddToExecution(PluginObject* op, PriorityList* list);  
         virtual LONG Execute(PluginObject* op, BaseDocument* doc, BaseThread* bt, LONG priority, LONG flags);  
      
         static NodeData *Alloc(void) { return gNew HairGeneratorObject; }  
    };  
      
    //////////////////////////////////////////////////////////////////////////  
      
    Bool HairGeneratorObject::Init(GeListNode *node)  
    {  
         BaseContainer *bc=((BaseList2D* )node)->GetDataInstance();  
           
         bc->SetLong(HAIR_GEN_COUNT,5000);  
         bc->SetLong(HAIR_GEN_SEGMENTS,6);  
         bc->SetReal(HAIR_GEN_LENGTH,15);  
         bc->SetReal(HAIR_GEN_LENGTH_VAR,5);  
         bc->SetReal(HAIR_GEN_NOISE,0.2);  
         bc->SetBool(HAIR_GEN_GENERATE,FALSE);  
      
         return TRUE;  
    }  
      
    void HairGeneratorObject::Free(GeListNode *node)  
    {  
    }  
      
    Bool HairGeneratorObject::Message(GeListNode *node, LONG type, void *data)  
    {  
         return SUPER::Message(node,type,data);  
    }  
      
    Bool HairGeneratorObject::Draw(PluginObject* op, LONG drawpass, BaseDraw* bd, BaseDrawHelp* bh)  
    {  
         return TRUE;  
    }  
      
    Bool HairGeneratorObject::AddToExecution(PluginObject* op, PriorityList* list)  
    {  
         list->Add(op,EXECUTION_GENERATOR,-1);  
         return TRUE;  
    }  
      
    static void RunExecute(BaseObject *op, BaseDocument *doc)  
    {  
         while (op)  
         {  
              if (op->IsInstanceOf(Ohair)) ((HairObject* )op)->Update(doc);  
              RunExecute(op->GetDown(),doc);  
              op=op->GetNext();  
         }  
    }  
      
    LONG HairGeneratorObject::Execute(PluginObject* op, BaseDocument* doc, BaseThread* bt, LONG priority, LONG flags)  
    {  
         RunExecute(op->GetCache(),doc);  
         return EXECUTION_RESULT_OK;  
    }  
      
    BaseObject *HairGeneratorObject::GetVirtualObjects(PluginObject *pObject, HierarchyHelp *hh)  
    {  
         Bool bDirty = pObject->CheckCache(hh);  
         HairObject *main=NULL;  
      
         if (!bDirty) bDirty = pObject->IsDirty(DIRTY_DATA|DIRTY_MATRIX);  
         if (!bDirty) return pObject->GetCache(hh);  
      
         BaseContainer *bc=pObject->GetDataInstance();  
      
         main = HairObject::Alloc();  
         if (!main) goto Error;  
      
         main->Lock(hh->GetDocument(),hh->GetThread(),FALSE,0);  
      
         HairGuides *guides = HairGuides::Alloc(1000,8);  
         if (!guides) goto Error;  
      
         main->SetGuides(guides,FALSE);  
         //guides->SetMg(mg);  
      
         Vector *pnts = guides->GetPoints();  
      
         LONG i,l;  
      
         for (i=0;i<1000;i++)  
         {  
              for (l=0;l<=8;l++)  
              {  
                   pnts[i*9+l]=Vector(i,l*20.0,0.0);  
              }  
         }  
      
         main->Unlock();  
      
         if (!pObject->CopyTagsTo(main,TRUE,FALSE,FALSE,NULL)) goto Error;  
      
         main->Update(hh->GetDocument());  
      
         return main;  
      
    Error:  
      
         HairObject::Free(main);  
      
         return BaseObject::Alloc(Onull);  
    }  
      
    //////////////////////////////////////////////////////////////////////////  
      
    #define ID_HAIR_GENERATOR_EXAMPLE 1020787  
      
    Bool RegisterGeneratorObject()  
    {  
         return RegisterObjectPlugin(ID_HAIR_GENERATOR_EXAMPLE,GeLoadString(IDS_HAIR_GENERATOR_EXAMPLE),OBJECT_GENERATOR|OBJECT_INPUT,HairGeneratorObject::Alloc,"Ohairsdkgen","hairgen.tif",0);  
    }  
      
    


  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/01/2007 at 14:19, xxxxxxxx wrote:

    Thanks David now it working.
    The rendering problem was becouse I still have used hairGuides->SetRoot(0,hroot,FALSE); probably with wrong HairRootData.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/03/2007 at 04:55, xxxxxxxx wrote:

    Hello,

    is there a way to access the actual polygons / points of a HairObject?

    Thank you

    P.S.: Are there any SDK Examples for Hair available by now?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/03/2007 at 07:20, xxxxxxxx wrote:

    The new 10.102 update for Cinema 4D includes some Hair specific SDK examples (thanks David).

    cheers,
    Matthias



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/03/2007 at 05:11, xxxxxxxx wrote:

    I still haven't found a way to access the actual (generated) polygons and points of HairObjects. I want to access them per frame since they are part of an animation (linked to a another mesh).

    Any idea, how I could access theses points?

    Furthermore I would like to access per frame the points of other objects driven by a skeleton. But when I advance time, the object's points don't change (so the animation seems to have no effect). Advancing the time of the skeleton doesn't change this.

      
    BaseTime time;  
    time.SetDenominator(doc->GetFps());  
    for(INT f=anim->getStartFrame(); f<=anim->getEndFrame(); f++) {  
    time.SetNominator(f);  
    doc->AnimateObject(object,time,ANIMATE_NO_PARTICLES);  
    Vector* point_array=object->GetPointW();  
    

    Any suggestions?

    Thank you



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/04/2007 at 08:46, xxxxxxxx wrote:

    I am know able to access the points of a mesh animated by a skeleton by executing the following steps:
    - animate whole skeleton hierarchy (including the mesh I want to export) using AnimateObject
    - Current state to object on the animated hierarchy using SendModelingCommand
    - GetPointW on the mesh to export in the newly created hierarchy, that know contains the animated points of this frame

    Unfortunately, this procedure doesn't work with clothes and hair...
    Points of cloth and hair objects "attached" to my mesh in the skeleton hierarchy don't seem to advance in time.

    I'm still trying...



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 12/04/2007 at 11:47, xxxxxxxx wrote:

    Points of cloth and hair objects "attached" to my mesh in the skeleton hierarchy don't seem to advance in time.

    That sounds exactly right. The points attached to the mesh aren't animated (!). They are *being* animated by the that to which they are attached. You have to apply the parent's global matrix to the points to retain the animation on them:

    // Apply parent animation to points  
    points =           defd->GetPointW();  
    lpoints =          points+pointCount;  
    for (; points != lpoints; ++points)     (*points) *= parent->GetMg();
    

    This may not be the case for cloth and hair, but it looks suspiciously so. :)



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/04/2007 at 00:31, xxxxxxxx wrote:

    Try the GetCache and GetDeformCache functions.

    You have to test GetCache for NULL. If not NULL use the pointer of GetCache then for GetDeformCache.

    if (pObject->GetCache()) pObject=pObject->GetCache();
    if (pObject->GetDeformCache()) pObject=pObject->GetDeformCache();

    cheers,
    Matthias



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/04/2007 at 07:41, xxxxxxxx wrote:

    My HairObjects and ClothObjects aren't children of Meshes in the skeleton hierarchy, but linked to them via Guide Links and Belt Tags - as far as I can see.

    - Null Object
    -- Hair Object (Guide Link -> Head)
    -- ...

    - Null Object
    -- Cloth Nurbs Object
    --- Pants (Belt Tag -> Body)
    -- ...

    - Null Object
    -- Skeleton Hierarchy
    -- Body
    -- Head
    -- ...

    I animate the whole Null Object containing the skeleton hierarchy and meshes animated by it.

    I tried the GetCache and GetDeformCache functions. Only with Cloth Nurbs Objects the GetCache functions returns a value not NULL, but GetDeformCache is always NULL...

    I also tried to apply the global matrix of Body (created per frame via setcurrentstatetoobject and actually holding animated points) to the Pants object. But it had no effect...

    Thank you for your patience.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 13/04/2007 at 08:52, xxxxxxxx wrote:

    If I apply the matrix of Body to the associated Cloth Object, only position, scale and rotation of the whole Body object are applied to the whole Cloth Object.
    The single points aren't effected in their position - so this procedure doesn't seem appropriate.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 16/04/2007 at 06:49, xxxxxxxx wrote:

    Finally it works for Hair! I just have to call

      
    doc->SetTime(time);  
    doc->AnimateDocument(NULL, TRUE, TRUE);                             EventAdd(EVENT_ANIMATE|EVENT_FORCEREDRAW);  
    

    and with current state to object I reveive the polygonized frame state of my hair object. No idea why it didn't work earlier...

    Yet there's still the problem with clothes. In this case there seems to exist a difference between dragging the timeline in c4d manually (object state is visibly updated) and calling SetTime, AnimateDocument and EventAdd programmatically (object state doesn't change)


Log in to reply