PoseMorph tag always increases GetDirty() counter



  • On 14/08/2017 at 09:38, xxxxxxxx wrote:

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

    ---------
    Hi all!

    Look at the minimal scene with problem: 
    https://www.dropbox.com/s/pwczovkyg408r1g/GetDirty always increase counter.c4d?dl=0

    It's a part of bulb sent by one user. If the Pose Morph tag is assigned to the "spline" object (that is visible in object manager) then the value spline->GetDirty(DIRTYFLAGS_DATA) is increased after each user mouse click in C4D area: either selecting the active object in OM or selecting some tool or even clicks in the custom GUI for image processing.

    Also for bulb (Lathe Object) which rotates the spline around the cache is always rebuilt after each such click (as described above). The value bulb->GetHDirty(HDIRTYFLAGS_OBJECT) is increased, the respective obj->GetDeformCache() points to different address (different cache object).

    All this happens with no change in object parameters. Only minor mouse clicks.
    In this case I don't know what Pose Morph is doing here. But it can be a valuable tool and we don't like if it always forces interactive rendering during modeling to force instant updates.

    How to woraround this? Or in other words how to listen for scene updates that don't force unnessary work.

    Best regards,
    Aaron



  • On 14/08/2017 at 09:53, xxxxxxxx wrote:

    Just a wild guess. Is the tag in edit mode?



  • On 14/08/2017 at 10:07, xxxxxxxx wrote:

    Minimal code:

    void DoRecursion(BaseObject *op, BaseDocument * doc)
    {
    	if (!op) return;
      
    	UInt32 dirty_x = op->GetHDirty(HDIRTYFLAGS_OBJECT);
    	UInt32 dirty_y = op->GetDirty(DIRTYFLAGS_DATA);
    	UInt32 dirty_z = op->GetDirty(DIRTYFLAGS_CACHE);
      
    	BaseObject * tp1 = op->GetDeformCache();
    	BaseObject * tp2 = op->GetCache();
      
    	LONG pcnt = 0;
    	if (op->IsInstanceOf(Opolygon))	{
    		PolygonObject * pobj = ToPoly(op);
    		pcnt = pobj->GetPolygonCount();
    	}
      
    	BaseContainer * icnt = op->GetDataInstance();
    	BaseObject * ires = icnt != 0 ? icnt->GetObjectLink(INSTANCEOBJECT_LINK, doc) : 0;
      
    	printf("\n [%3d]:%4d dirty [%3d:%3d:%3d] tp %3d %3d %3d %3d name [%s] n %d",
    		int(op) % 1000,
    		op->GetType() % 10000,
    		dirty_x,
    		dirty_y,
    		dirty_z,
    		int(tp1) % 1000,
    		int(tp2) % 1000,
    		int(op->GetDown()) % 1000,
    		int(ires) % 1000,
    		op->GetName().GetCStringCopy(), pcnt);
      
    	if (tp1)  
    	{ 
    		DoRecursion(tp1, doc); 
    	} 
    	else  
    	{ 
    		if (tp2)    
    		{ 
    			DoRecursion(tp2, doc); 
    		} 
    		else    
    		{ 
    			if (!op->GetBit(BIT_CONTROLOBJECT))     
    			{ 
    			//	if (op->IsInstanceOf(Opolygon))        
    			//	{ ... } 
    			} 
    		} 
    	}  
    	
    	for (BaseObject * tp = op->GetDown(); tp; tp = tp->GetNext())  
    		DoRecursion(tp, doc);
    }
      
    void test_on_timer()
    {
    	BaseDocument * doc = GetActiveDocument();
    	if (!doc) return;
      
    	for (BaseObject * tp = doc->GetFirstObject(); tp; tp = tp->GetNext()) {
    		if (tp != 0)
    			DoRecursion(tp, doc);
    	}
    }
    

    Printf result:
    https://www.dropbox.com/s/vzlzfh6viiqjjme/printf.jpg?dl=0

    As you see the caches are changed (their dirty flags) and pointers to them. All this happens after mouse clicks without object changes. How to fix?



  • On 14/08/2017 at 11:38, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Just a wild guess. Is the tag in edit mode?

    Yes. It's in Edit mode. In Edit mode any click in a scene (or any selection of any object) forces the dirty flags to update. Most bad is update of spline->GetDirty(DIRTYFLAGS_DATA).
    If not in Edit mode the situation is a little bit better. Only when user clicks on the spline object (makes it selected) then the spline->GetDirty(DIRTYFLAGS_DATA) is also updated.

    I rely on these dirty flags as I need o make robust interactive rendering process while modeling whithout reloading geometry when it's not really needed (when nothing really changed).



  • On 14/08/2017 at 11:42, xxxxxxxx wrote:

    Just a quick tip (aside from your problem)
    I'd recommend you to use the active object dialog (it comes with the c4dsdk)
    There you'll find pointers, handles, flags, etc. in a nicely sorted way.



  • On 14/08/2017 at 12:13, xxxxxxxx wrote:

    Thanks for reminding me about this sample from SDK. I have already remoted from it and fogotten. But still it shows the same thing. Addresses and dirty flags of the scene. 
    I have tested a couple of render engines with IPR modes and it's the same. They restart render on mouse click on any object :)



  • On 23/08/2017 at 09:41, xxxxxxxx wrote:

    Hi Aaron, sorry for getting back so late here.

    I confirm the behavior you mentioned and I also spotted similar behavior in other renderers. The PoseMorph Tag actually delivers this behavior by-design in order to achieve the desired functionality.

    At the same time you can consider on computing the CRC32 checksum (look at ZipFile::CalcCRC32()) of the array storing the vertexes of the cache in order to avoid false-positive updates.
    I've tested here and I'd say it plays good enough although you should expect some marginal overheads in terms of interactivity.

    Best, Riccardo



  • On 20/09/2017 at 13:40, xxxxxxxx wrote:

    Hi Riccardo, thanks for advice, I use a similar thing (with a different implementation) for different other things as the last method in the world. It's hard to avoid this method for matrix updates in a highly dynamic scene graph with many possible connections and dependecies. But certainly we wanted to avoid such a not very elegant method for mesh data which could contain millions (dozens of millions) of vertices/normals/UVs and etc. 
    I suggest C4D developers to fix this issue and make Cinema a bit more clever on dirty/updates department.

    Thanks, 
    Aaron



  • On 20/09/2017 at 14:09, xxxxxxxx wrote:

    Btw, how to get the array of UVWStructs as elements of UVWTag? 
    From what I have seen the usage is UVWStruct uvw = uvwtag->GetSlow(i). This is not array but a class member call for each element (i.e. slow).



  • On 21/09/2017 at 03:11, xxxxxxxx wrote:

    Hi Aaron, with reference to the UVWTag I suggest to have a look  at the UVWTag Manual where fast access to UVWTag is explained in detail.

    Best, Riccardo



  • On 21/09/2017 at 05:36, xxxxxxxx wrote:

    It works like this:

    uvwData = UVWTag::Get(handle, i);
    UVWTag::Set(handle, i, uvwData);

    But do you have some access to array of UVs?
    uvwData = uvw_array[4 * i + poly_id]?

    There are such arrays for vertices, polygon_to_vertex indices, normals and no UVW. Why?



  • On 27/09/2017 at 05:24, xxxxxxxx wrote:

    Hi Aaron94, thanks for writing us.

    I partially disagree because although vertices and polygon-to-vertex indices are stored as plain arrays, normals and UVW are actually residing in tags which among all the things let the user define multiple set of values rather than a single one (as for vertices and poly-vertex indexes). On top of that even using the VariableTag::GetLowLevelDataAddressR() or (VariableTag::GetLowLevelDataAddressW()) makes no real difference since to retrieve the desired values you should invoke UVWTag::Get().

    Long story short the existing API (to access the UVWStruct) is the only (and best)-way to go.
    Best, Riccardo

    PS: For the future I also warmly invite you to post questions on subjects different from the topic on a new thread.



  • On 29/09/2017 at 08:30, xxxxxxxx wrote:

    Thanks Riccardo! I just analize all possible opportunities of C4D API to improve solutions to our tasks.

    As for not openning other thread, then excuse me please. Here you have offered a workaround that can be directly applicable to some data of mesh (vertices, polygons) and I have asked if the similar solution is hidden in API for UVs. No, ok. Then we can collect data into own array.

    Why I think accessing UVs through the wrapper is not efficient? Simply because I care about tiny performance bits too after I had practice with asm coding :)


Log in to reply