ModifyObject - Use Previous Cache?



  • On 27/04/2014 at 14:50, xxxxxxxx wrote:

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

    ---------
    In an ObjectData plugin, as a deformer, is it possible to re-use the previously built deform cache - instead of re-doing the whole deform operation?  Say for example if nothing has actually changed and there is no point in re-doing the deform..



  • On 29/04/2014 at 02:20, xxxxxxxx wrote:

    Anyone help with a way of achieving this?

    I thought about maybe cloning the deform cache but as it`s a deformer no idea how to return that, not really keen on doing hacky object swapping/hiding or similar either..



  • On 30/04/2014 at 06:26, xxxxxxxx wrote:

    Howdy,

    Are you using the ObjectData::CheckDirty() function?

    Adios,
    Cactus Dan



  • On 30/04/2014 at 06:37, xxxxxxxx wrote:

    Hi Dan,

    Yeah im using that for custom dirty stuff..  There are other things in the scene which throw dirties that i dont think can be controlled - so ObjectData::ModifyObject() is going to be called regularly anyway..



  • On 01/05/2014 at 13:56, xxxxxxxx wrote:

    Anyone have any suggestions on this?



  • On 01/05/2014 at 14:34, xxxxxxxx wrote:

    Howdy,

    Well, I've never created a deformer plugin before, but in a Generator object, I use BaseObject::GetAndCheckHierarchyClone() inside the ObjectData::GetVirtualObjects() function to check if anything has changed, and if not, return the BaseObject that is returned by the GetAndCheckHierarchyClone() function like this:

    Bool dirty = false;
    BaseObject *hCln = op->GetAndCheckHierarchyClone(hh,orig,HIERARCHYCLONEFLAGS_ASPOLY|HIERARCHYCLONEFLAGS_ASSPLINE,&dirty,NULL,false);
      
    if(!dirty) return hCln; // if !dirty object doesn't need to be rebuilt
    if(!hCln) return NULL;
    

    I don't know if it's usable in ObjectData::ModifyObject() or not, though.

    Adios,
    Cactus Dan



  • On 01/05/2014 at 17:59, xxxxxxxx wrote:

    Yeah i dont think thatd work..  ModifyObject() doesn`t return anything and is different from GetVirtualObjects() etc..

    I`ve also tried setting the dirty flag to op->SetDirty(DIRTYFLAGS_0); within my CheckDirty() override but no joy..

    :/



  • On 02/05/2014 at 06:19, xxxxxxxx wrote:

    Howdy,

    Well, it does return true or false, so on the line:

    if(!dirty) return hCln;
    

    ... you could try this instead:

    if(!dirty) return true;
    

    ... that is if the BaseObject::GetAndCheckHierarchyClone() function does the same job in ObjectData::ModifyObject() as it does in ObjectData::GetVirtualObjects().

    Otherwise, maybe you could do a check to see if the deformer object's parameters have changed?

    Adios,
    Cactus Dan



  • On 02/05/2014 at 06:30, xxxxxxxx wrote:

    CheckDirty() is called to ask your deformer if something has changed. If you return true, ModifyObject()
    on yours and the other required deformers is called. Return false if you determined that nothing has
    changed. It could still be called though, if another deformer in the chain decides that an updated 
    is required.

    -Niklas



  • On 02/05/2014 at 12:42, xxxxxxxx wrote:

    Unless i`m missing something, CheckDirty() returns nothing..?  According to the docs ( R14 ) :

    virtual void CheckDirty([BaseObject](file:///C:/Users/Tangerine/Desktop/C++%20Docs/help/pages/c4d_baseobject/class_BaseObject75.html)* op, [BaseDocument](file:///C:/Users/Tangerine/Desktop/C++%20Docs/help/pages/c4d_basedocument/class_BaseDocument65.html)* doc)_<_h4_>_

    You can override this function to check for a change in a deformer object manually. This example will make your deformer update every frame:
    void CheckDirty(BaseObject \*op, BaseDocument \*doc) {   if (doc->GetTime()!=cached_time)   {     cached_time=doc->GetTime();     op->SetDirty(DIRTYFLAGS_DATA);   } }

    So basically, it provides an opportunity to check manually for any custom changes, and you then set the op with op->SetDirty(FLAG)..
    Pretty sure i tried returning TRUE / FALSE and it threw an error..
    [edit]  Just reading over the last couple of posts, i wrongly said to Dan that ModifyObject() returns nothing, in actual fact it does return a Bool but returning FALSE on that only had the effect of my modified object being reset to it`s original state..



  • On 06/05/2014 at 14:00, xxxxxxxx wrote:

    Dont mean to be a pain - any further insights into this?  Unless im missing something obvious i think i`ve tried everything..



  • On 06/05/2014 at 15:08, xxxxxxxx wrote:

    Hi,

    sorry I remembered this wrong. What you quoted from the documentation is what I was 
    referring to. Unfortunately, I can't really conclude from your postings what the exact
    behavior is as I don't know the state of the code you use. You should call op->SetDirty(...)
    when you want your deformer to be updated, and not call it if you want it not to. It could
    still be re-evaluated, as I mentioned in my previous post.

    -Niklas



  • On 06/05/2014 at 15:54, xxxxxxxx wrote:

    Well at the moment it updates every frame ( i think when the timeline advances it sets dirty automatically ) - so what i`d like is to avoid that if possible ( or force it to use the previous deformer cache if none of the parameters within my plugin have changed ), which would be much more efficient..

    Thanks for all the help thus far it`s much appreciated!



  • On 06/05/2014 at 17:19, xxxxxxxx wrote:

    ( i think when the timeline advances it sets dirty automatically )

    What is the code for your CheckDirty() method? It is not by any chance the exact same code that
    is shown in the SDK Documentation (which you quoted)?



  • On 07/05/2014 at 01:14, xxxxxxxx wrote:

    Nah it aint the code in the docs.  All my CheckDirty() code is doing, is comparing the GetDirty(DIRTYFLAGS_MATRIX) of some objects with previous, and if different, doing op->SetDirty(DIRTYFLAGS_DATA)..

    Ive even tried commenting out my entire CheckDirty() code, so im now thinking that maybe something else in the code is triggering the cache rebuild / ModifyObject() ..

    Will get back to you on this :/

    Either way if there is some way to force the previous deformer cache from within the ModifyObject() function, i`d like to know about it!



  • On 07/05/2014 at 05:18, xxxxxxxx wrote:

    No there is no way to "force" the cache to be re-used instead of doing recalculations.
    I'll try to set up an example, and maybe even verify the behaviour you describe. But it
    sounds a little strange to me at the moment.

    Best,
    -Niklas



  • On 07/05/2014 at 06:14, xxxxxxxx wrote:

    Howdy,

    I suspect that the deform cache is not saved and must always be rebuilt. I made a simple little test in the cinema4dsdk project's spherify.cpp example.

    I added this code:

    if(!mod->IsDirty(DIRTYFLAGS_MATRIX|DIRTYFLAGS_DATA)) return true;
    

    ... and it caused the deformer to not deform the object.

    So, then I changed the code by removing the "!" (not) operator:

    if(mod->IsDirty(DIRTYFLAGS_MATRIX|DIRTYFLAGS_DATA)) return true;
    

    ... and the deformer worked again.

    That leads me to believe that if ObjectData::ModifyObject() returns without making the modification calculations to the object's points, the object doesn't get deformed.

    Adios,
    Cactus Dan



  • On 07/05/2014 at 15:09, xxxxxxxx wrote:

    CactusDan - are you saying that ObjectData deformer rebuilds the cache or does nothing ( no deform ) - ie there`s no obvious way of retaining the previous cache?



  • On 07/05/2014 at 16:23, xxxxxxxx wrote:

    Howdy,

    Hmmmm, looking at the code again I'm not so sure, because the "not" version never builds the deform cache in the first place. 😊

    Adios,
    Cactus Dan



  • On 07/05/2014 at 16:53, xxxxxxxx wrote:

    Howdy,

    OK, I tried another test where I added a global boolean variable "checkDirtyModifyer" set it to false in the PluginStart() function, and changed the code in ObjectData::ModifyObject() to this:

    if(checkDirtyModifyer && !mod->IsDirty(DIRTYFLAGS_MATRIX|DIRTYFLAGS_DATA)) return true;
    

    ...then I created a simple CommandData plugin that set the checkDirtyModifyer global to true so I can invoke that command after the deformer object has already deformed the object and created a deform cache.

    Here's what happened:
    When the deformer is first applied to the object it works as normal. After the command is invoked to set the global variable to true, nothing happens. The moment I move the deformer or change the strength parameter the deformer stops working.

    So maybe my sus**cion was partially correct?

    Adios,
    Cactus Dan


Log in to reply