Problem with code when rendering..



  • On 24/04/2014 at 16:21, xxxxxxxx wrote:

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

    ---------
    Hi,

    I have roughly the following code in my ObjectData Modifier plugin - which is inside a function which gets called from MyPlugin::ModifyObject() - and iterates through the objects in an INEXCLUDE list, checks the type of each object and does some stuff..

    void iterateObjects(BaseContainer* data)
    {	
    	BaseDocument *doc = GetActiveDocument();
    	
    	GeData d;
    	d = data->GetData(MYPLUGIN_INCLUDE);
    	objList = (InExcludeData* )d.GetCustomDataType(CUSTOMDATATYPE_INEXCLUDE_LIST);
    	
    	if (objList == NULL)
    	{
    		objCount = 0;
    	}
    	else
    	{
    		objCount = objList->GetObjectCount();
    	}
    	
    	if (objCount != 0)
    	{
    		for (LONG i=0; i<objCount; i++)
    		{
    			BaseList2D* bl = objList->ObjectFromIndex(doc, i);
    			BaseObject *curObj = (BaseObject* )bl;
    			
    			if (bl->GetTypeName() == "Cloner")
    			{
    				// Do some stuff..
    			}
    			else
    			{
    				// Do some other stuff..
    			}
    		}
    	}
    }
    

    This works perfectly until i render my scene - it immediately stops with the following:

    > MyPlugin.cdl!BaseList2D::GetTypeName()  Line 40 + 0x38 bytes C++

    Debugging my objects within VS while C4D is still running, the objCount variable is reading correctly, but the ObjList->ObjectFromIndex() result is coming up empty from what i can make out.

    Like i said this is fine when not rendering..

    Any clues why this might be happening?



  • On 25/04/2014 at 01:59, xxxxxxxx wrote:

    Try something like this.
    I think ObjectFromIndex() could return NULL in this cases.

      
    void iterateObjects(BaseContainer* data)  
    {      
      BaseDocument *doc = GetActiveDocument();  
      GeData d;  
      d = data->GetData(MYPLUGIN_INCLUDE);  
      objList = (InExcludeData* )d.GetCustomDataType(CUSTOMDATATYPE_INEXCLUDE_LIST);  
      
      objCount = 0;  
      if (objList != NULL)  
      {  
          objCount = objList->GetObjectCount();  
          for (LONG i=0; i<objCount; i++)  
          {  
              BaseList2D* bl = objList->ObjectFromIndex(doc, i);  
              if(bl == NULL) continue;  
              BaseObject *curObj = (BaseObject* )bl;  
              if (bl->GetTypeName() == "Cloner")  
              {  
              // Do some stuff..  
              }  
              else  
              {  
              // Do some other stuff..  
              }  
          }  
      }  
    }  
    


  • On 25/04/2014 at 02:54, xxxxxxxx wrote:

    Cheers Remo i`ll give that a whirl later today..



  • On 25/04/2014 at 08:09, xxxxxxxx wrote:

    This works thanks again Remotion.

    Do certain objects and functions return nothing when the render is initializing or something?



  • On 25/04/2014 at 09:24, xxxxxxxx wrote:

    _<_h5_>_In many case you should assume that NULL can be returned, so it is better to almost always test for it._<_h5_<_h5_>_h5>

    Here is what SDK docu_<_h5_<_h5_>_ <_<_h5_>_h5>
    Return

    > BaseList2D*
    >
    >> The found object, or nullptr. The document owns the pointed object.
    >>
    >>
    >
    >>
    >>
    >



  • On 26/04/2014 at 05:09, xxxxxxxx wrote:

    The problem i am having now is that it ALWAYS returns NULL when rendering.

    I thought perhaps there was an initial build-phase of the render process where it might return NULL, and then after that it would return the object as expected and render correctly..

    However it doesnt seem to return the object at any point during render - and so my deformer plugin isnt working..

    Any clues why ObjectFromIndex() is working fine in the viewport but not at rendertime??



  • On 26/04/2014 at 05:42, xxxxxxxx wrote:

    Actually it seems to run my function ( via ::ModifyObject() ) twice during rendering, but on the third time returns the object..

    Might be a priority issue.  I have tried adding -

    Bool MyPlugin::AddToExecution(BaseObject* op, PriorityList* list)
    {
    	list->Add(op, EXECUTIONPRIORITY_INITIAL, EXECUTIONFLAGS_RENDER);
    	return TRUE;
    }
    

    Which seems to have no effect in my case, playing with the different flags etc..

    I`ll keep trying anyway :/



  • On 26/04/2014 at 05:48, xxxxxxxx wrote:

    Just for reference this is roughly my code using CheckIsRunning() to test during render:

    	if (CheckIsRunning(CHECKISRUNNING_EXTERNALRENDERING)) {
    		GePrint("Is Rendering");
    		GePrint("About to check for NULL");
    	}
      
    	if(bl == NULL) continue;
      
    	if (CheckIsRunning(CHECKISRUNNING_EXTERNALRENDERING)) {
    		GePrint("Is Rendering");
    		GePrint("Post Confirmation.");
    	}
    


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

    Now the question is why do you need to do it during Rendering ?
    Actually it should be better to do all this stuff before rendering.



  • On 26/04/2014 at 07:25, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Now the question is why do you need to do it during Rendering ?
    Actually it should be better to do all this stuff before rendering.

    Well what the code is doing, is iterating through all the objects in the INEXCLUDE list, and storing their global positions in an array..  The plugin then performs a deformation to the parent object based on the list of global positions..

    The positions change every frame when the objects are animated and so it iterates the objects and checks positions each time..

    I have implemented a Bake button, which runs through the timeline and stores everything - this works fine during render..

    I could probably store the objects found with ObjectFromIndex() only from the Message - MSG_DESCRIPTION_CHECKDRAGANDDROP ( ie only when the INEXCLUDE list changes ).  Then access the objects found from within iterateObjects() function rather than accessing the INEXCLUDE list directly.  Thatd probably solve the problem actually ( rather than checking the list each time ).  But i didnt anticipate it to be an issue..



  • On 26/04/2014 at 07:53, xxxxxxxx wrote:

    Hi Eclectrik,

    get the document from your object with op->GetDocument(), not with
    GetActiveDocument(). The document that is rendered is not the active
    document. That will solve your problem with ObjectFromIndex()

    Be still aware that ObjectFromIndex() can return null. This is the case 
    when an object was added to the list and then removed from the document.
    The slot for the object is still reserved, but it can't be resolved as the object
    doesn't exist anymore.

    Also, when CheckIsRunning(CHECKISRUNNING_EXTERNALRENDERING)
    returns true, that does not mean that your object participates in the
    render process. It just means that the renderer is running and its a global
    state that will affect all of your plugin instances.

    You can listen to the MSG_MULTI_RENDERNOTIFICATION message
    instead.

    -Niklas



  • On 26/04/2014 at 08:34, xxxxxxxx wrote:

    Whoa - thanks for that Niklas.

    Yes op->GetDocument() does indeed fix the issue.

    I was aware that C4D creates a clone of the doc on render so i take it that op->GetDocument() will access the clone rather than the actual document that is exposed to the user.

    Yes i`ve read about the issue with INEXCLUDE lists and deleted objects - thanks.

    I am now in the process of trying to implement rendertime settings - ie one setting for viewport and a different one for when it is rendering.  Looking into MSG_MULTI_RENDERNOTIFICATION - thanks again for that.


Log in to reply