How does GetAndCheckHierarchyClone work?



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

    On 19/05/2004 at 03:10, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   8.503 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hi forum,

    I have some very basic questions. At the moment I'm trying to understand how C4D handles internal caches and how it decides wether an objet is dirty or not. Furthermore I want to know how DependenceLists work, and what they are :-) I think by understanding GetAndCheckHierarchyClone all this will be much clearer for me and other beginners.

    So here is the function as found in c4d_baseobject.cpp. I try to comment it as far as my little understanding goes. Maybe one of you may help me further.

    Thanx in advance

      
    BaseObject *PluginObject::GetAndCheckHierarchyClone(HierarchyHelp *hh, BaseObject *op, LONG flags, Bool *dirty, AliasTrans *trans, Bool allchilds)  
    {  
         BaseObject *res=NULL,*tp=NULL,*dp=NULL;  
      
    /* here the cache and the data is checked. If the cache doesn't represent the objects current state or the data was modified the variable dirty gets TRUE. That means CheckCache() returns TRUE if the Cache is not valid, correct?*/  
      
         *dirty = *dirty || CheckCache(hh) || IsDirty(DIRTY_DATA);  
      
    /* if dirty is FALSE this code is executed. That means it's only executed if everything's OK and C4D can use the cache instead of generating the object again.*/  
      
         if (!(*dirty))  
         {  
      
    /* A new DependenceList is created. Some questions arise here. Where is it created as the function doesn't return anything? Is it correct that every ObjectPlugin Object has only one DependenceList and this commands resets it to the defaults? I've no real clue.*/  
      
              NewDependenceList();  
      
    /* the if statement decides wether the whole hierarchy has to be browsed. But what does GetHierarchyClone here, as the returned clone is not stored or used anywhere. My first idea was, that the function only modifies the dirty variable, correct?*/  
      
      
              if (!allchilds)  
                   GetHierarchyClone(hh,op,flags,dirty,trans);  
              else  
              {  
                   for (tp=op;tp;tp=tp->GetNext())  
                        GetHierarchyClone(hh,tp,flags,dirty,trans);  
              }  
         }  
      
    /* after doing all the stuff above dirty is checked again. But this time using the inverted result of CompareDependenceList(); So wich list is compared to wich here? The one that exists by default with the one we created above? In wich case does CompareDependenceList return true?*/  
      
         *dirty = *dirty || !CompareDependenceList();  
      
    /* dirty gets TRUE if it was TRUE already or if CompareDependanceList returns false. The code below is only executed if dirty is FALSE*/  
      
         if (!(*dirty))  
         {  
      
    /* what does TouchDependenceList do? I thougt it marks all childs of my PluginObject as belonging to the Object. This causes them to get invisible as they're replaced by my plugin.*/  
      
              TouchDependenceList();  
      
    /* here the Cache is returned instead of building new Hierarchy Clones as dirty is FALSE. Where does this cache come from and what does the HierarchyHelp structure store or do? Is it correct, that every C4D object has a cache attached and cinema cares of building it internally?*/  
      
              return GetCache(hh);  
         }  
      
    /* OK, if the statements above were not executed as dirty is TRUE we have to rebuild the Clones. Execution continues here. Here NewDependenceList occurs again. What does it do exactly?*/  
      
         NewDependenceList();  
      
    /* The child object/objects is/are cloned and passed to the parent Generator (this is my plugin, right?). Is it correct that one has to use GetHirarchyClone instead of using the input object directly. If so, why?*/  
      
         if (!allchilds)  
              res = GetHierarchyClone(hh,op,flags,NULL,trans);  
         else  
         {  
              res = BaseObject::Alloc(Onull); if (!res) return NULL;  
              res->SetName(op->GetName());  
              for (tp=op;tp;tp=tp->GetNext())  
              {  
                   dp = GetHierarchyClone(hh,tp,flags,NULL,trans);  
                   if (dp) dp->InsertUnderLast(res);  
              }  
         }  
      
    /*The generated clones are returned*/  
      
         return res;  
    }  
    


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

    On 19/05/2004 at 05:48, xxxxxxxx wrote:

    This is hard stuff of which even I haven't grasped the full picture, but I'll try to answer your questions.
    Yes, the description for CheckCache() seems to be wrong. Your interpretation is right.
    Yes, there's only one dependence list.
    That's right. This is a subtle thing about GetHierarchyClone() : if a dirty pointer is passed, the function doesn't do anything except updating the dirty status and adding to the dependence list.
    So we check with CompareDependenceList() if any of the touched objects (added by GetHierarchyClone()) have changed. I don't know when this would happen and dirty would still be FALSE.
    Yeah, that's the main purpose of touching. From what I understand it just sets some flag and reset the cached checksum of the object.
    The cache is simply what you returned the last time in GetVirtualObjects().
    It just clears the dependence list.
    Yeah, you have to use GetHierarchyClone(). It cannot be emulated by plugin code. (I'm not really sure what the difference is though.)
    I hope you came out of this at least a bit wiser (I'm not sure if I did). Otherwise, please continue asking.



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

    On 19/05/2004 at 06:57, xxxxxxxx wrote:

    Hi Mikael,

    thank you very much. I think I'm a little bit wiser now ;-) Nevertheless some questions remain.

    Is it right that I add objects to a DependenceList by using TouchDependenceList()? And: Is it right that GetHierarchyClone() automatically adds the generated clone to the Dependence List?

    And what exactly is HierarchyHelp? I know how to use the class but I don't understand neither what it is nor wich data it stores internally?

    And another question: Is it possible to add objects to my DependenceList() that are not children of my Plugin. e. g. object I get through using a Link?

    And what exactly is an AliasTranslator? I know it takes care of resolving the BaseLinks correctly when an object is copied or cloned, but what does it internally?

    You see, questions, questions and even more questions. Unfortunately the documentation isn't very helpful to understand the basics, what goes on under the hood. So I cannot do anything but asking here ;-)

    Thank you again for your help, best mnu



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

    On 20/05/2004 at 04:30, xxxxxxxx wrote:

    No, adding is done by AddDependence(). And yes, this is also done by GetHierarchyClone().
    HierarchyHelp is just a helper class so that we don't have to pass the doc etv. separately for each function. I don't know if it contains anything else internally (that's kind-of the point of encapsulation not having to know).
    I don't think adding objects outside of your object to the dependence list is a good idea, but I haven't checked if it works.
    I don't know how the alias translator does it work, but I would guess that it keeps a list of all clone operations performed and then fixes the links accordingly when you call Translate().



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

    On 20/05/2004 at 08:29, xxxxxxxx wrote:

    Hi Mikael,

    thank you again. Slowly I'm getting a vague impression of the big picture. Next step to play with this stuff in my current plugin.

    I'll post again with new questions soon ;-)

    cheers mnu



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

    On 04/06/2004 at 07:54, xxxxxxxx wrote:

    Hi
    i 've just seen this thread ( thank god :)  I have had exactly the same questions as you have, and still have them.
    I am trying to do a deformer/generator that uses the UV-Map to project objects to the surface of another object.
    So i need input objects: 
    Object M , polygonized , with UV-Map , used for projection
    Objects Oi , as is, to be placed on the surface of object M
    Since i failed with using object links to reference object M ( dirty checking  doesn't work well, and calling CurrentStateToObject ModelingCommand disturbs the correct cache generation, i might check this again )  i wanted put object M as well as Objects Oi as childs under my PluginObject. The problem is that Object M has to be polygonized, while objects Oi must be cloned as they are. Here dirty checking doesn't work at all, i always must rebuild the cache.
    I've wasted many hours on this, and i hope someday i will succeede. If so i will post again.



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

    On 08/06/2004 at 04:46, xxxxxxxx wrote:

    It possibly sacrifices some cachability, but I'm having no problem using MCOMMAND_CURRENTSTATETOOBJECT on HCLONE_ASISed objects in MSA.



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

    On 13/06/2004 at 01:36, xxxxxxxx wrote:

    Thanks Mikael
    meanwhile i found a nice solution.
    It is possible to make a modified GetAndCheckHierarchyClone function, where the flag-Parameter varies for each input object. So one Object get's polygonized and others are cloned as is. This seems to work so far.
    You suggestion is also nice. I've tried using MCOMMAND_CURRENTSTATETOOBJECT on an object that i got from a BaseLink ( during GetVirtualObjects ). But it produces wired results, InputObjects are drawn twice, and such things,.. can't remember exactly. Maybe it was a threading thing.
    best regards
     
    Michael


Log in to reply