Cache does not work



  • On 04/08/2013 at 22:25, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   r14 
    Platform:      Mac OSX  ; 
    Language(s) :     C++  ;

    ---------
    I am trying to understand how to use the cache properly, and am using a simplest useful code for that purpose. My plugin node has two children, I then create two respective clones using GetAndCheckHierarchyClone, and then return null. I am not doing any calculations, I am not generating any objects, yet GetAndCheckHierarchyClone is always changing the dirty boolean to true.  What am I doing wrong? Here is the code:

    BaseObject *TSPData::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)
    {
        
    BaseObject *orig = op->GetDown();
        
    if (!orig) return NULL;
        
        BaseObject *origSibling = orig->GetNext();
        if (!origSibling) return NULL;

    Bool			dirty=FALSE;
    Matrix			ml;
    BaseObject \*child = op->GetAndCheckHierarchyClone(hh,orig,HIERARCHYCLONEFLAGS_ASPOLY,&dirty,NULL,FALSE);
    

    Bool dirtyS = FALSE;    
        BaseObject *sibling = op->GetAndCheckHierarchyClone(hh,origSibling,HIERARCHYCLONEFLAGS_ASPOLY,&dirtyS,NULL,FALSE);
        dirty = dirty || dirtyS;
    if (!dirty) dirty = op->CheckCache(hh);
    if (!dirty) dirty = op->IsDirty(DIRTYFLAGS_DATA);
        op->TouchDependenceList();
    if (!dirty) return op->GetCache(hh);
        op->AddDependence(hh, child);
        op->AddDependence(hh, sibling);
        return NULL;
    }

    The problem is that if (!dirty) return op->GetCache (hh);  never returns cache, as the dirty is always set to true in the GetAndCheckHierarchyClone.
    Reading the forum I suspect the problem is in the dependence list, and I don't quite understand what am I supposed to add to the dependence list. My original children? Their clones? It seems that GetAndCheckHierarchyClone creates a new list for each call/child. Is it OK, or I should prevent that?
    Would appreciate _any_ reaction from this list.

    Thanks.

    --8



  • On 05/08/2013 at 03:25, xxxxxxxx wrote:

    The problem seems to be that you don't have any data in your cache since you always return NULL.
    Try to return something useful from your function like a nullobject or an empty polygonobject and only return NULL in the case of an error.



  • On 05/08/2013 at 07:16, xxxxxxxx wrote:

    Hi Satara,

    Thanks for your suggestion. If I _return  _BaseObject::Alloc(Onull ); cache's _ _ behavior is the same -- it is never used.

    --8



  • On 05/08/2013 at 08:36, xxxxxxxx wrote:

    I removed a second child handling to simplify this case, but I still get dirty flag always set to true. Here is my code, which demonstrates that cache is never used

    BaseObject *TSPData::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)
    {
    BaseObject *orig = op->GetDown();
        
    if (!orig) return NULL; 
    Bool dirty=FALSE;
    BaseObject *child = op->GetAndCheckHierarchyClone(hh,orig,HIERARCHYCLONEFLAGS_ASPOLY,&dirty,NULL,FALSE);
        op->TouchDependenceList();
        if (!dirty) return op->GetCache(hh);
        op->AddDependence(hh, child);
        return BaseObject::Alloc(Onull);
    }

    What's wrong with it?

    Thanks.

    --8



  • On 05/08/2013 at 09:56, xxxxxxxx wrote:

    You are adding the clone of your input object to the depence list, that does not make sense.
    If you only want to check if any object in the hierachy of op (including op) then using GetAndCheckHierarchyClone() should be enough since it's internally already creating a new depencelist with op and it's children.
    If you make two calls to GetAndCheckHierarchyClone() as in your first listing it probably doesn't work either because the second call will override the first depencelist.
    This would mean that you have to create your depencelist manually. Check the MorphMixer Example to see how to properly use the depencelist. You can also have a look at the implementation of the GetAndCheckHierarchyClone() in c4d_baseobject.cpp.



  • On 05/08/2013 at 10:32, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    You are adding the clone of your input object to the depence list, that does not make sense.
    If you only want to check if any object in the hierachy of op (including op) then using GetAndCheckHierarchyClone() should be enough since it's internally already creating a new depencelist with op and it's children.
    If you make two calls to GetAndCheckHierarchyClone() as in your first listing it probably doesn't work either because the second call will override the first depencelist.
    This would mean that you have to create your depencelist manually. Check the MorphMixer Example to see how to properly use the depencelist. You can also have a look at the implementation of the GetAndCheckHierarchyClone() in c4d_baseobject.cpp.

    Hi Satara,

    Thanks a lot: removing AddDependence call fixed it. However, I did not see the dependence added in the GetAndCheckHierarchyClone, therefore I was adding it myself. How is it added in the GetAndCheckHierarchyClone, by what call? Also GetAndCheckHierarchyClone itself calls NewDependenceList() twice in some cases –– its logic is extremely hard to understand.

    --8



  • On 05/08/2013 at 11:54, xxxxxxxx wrote:

    I suppose the objects are added in GetHierarchyClone(). Yes indeed it's quite complicated to understand what's going on :)



  • On 05/08/2013 at 13:35, xxxxxxxx wrote:

    OK. So to close this issue, this is the code I ended up with, which is a combination of the morphmixer.cpp and GetAndCheckHierarchyClone in c4d_baseobject.cpp

    BaseObject * TSPData::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)
    __
    {
    _ BaseObject *orig = op->GetDown();  _
    _ if (!orig) return NULL;_
    // start new list
    _ op->NewDependenceList();_
    _ // check cache for validity and check master object for changes_
    _ Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS_DATA);_
    _    BaseObject* pp=NULL;_
    _    LONG child_cnt =0;_
    _    BaseObject* children[MAXTARGETS];_
    _ for (pp=orig; pp; pp=pp->GetNext())_
    _ {_
    _        children[child_cnt++]=op->GetHierarchyClone(hh,pp,HIERARCHYCLONEFLAGS_ASPOLY,FALSE,NULL);_
    _ }_
    _ // no child object found_
    _ if (!child_cnt) return NULL;    _
    if (!dirty) dirty = !op- >CompareDependenceList();    _
    _ // mark child objects as processed

    _ op->TouchDependenceList();_
    _ // if no change has been detected, return original cache_
    _ if (!dirty) return op->GetCache(hh);_
    _    std::cout<<"no cache"<<std::endl;_
    _  //CONTINUE WITH GENERATION OF YOUR STUFF HERE_
    }

    Due to  GetHierarchyClone (hh,pp,HIERARCHYCLONEFLAGS_ASPOLY,FALSE,NULL ) call above it works with both polygonal and non-polygonal children (unlike morphmixer.cpp, which only works with polygonal children). GetHierarchyClone also encapsulates addition of the dependencies to the DependenceList.

    Thanks, Satara, for your help.

    --8


Log in to reply