RenderDocument() Feedback



  • On 03/02/2016 at 13:50, xxxxxxxx wrote:

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

    ---------
    Hi,

    It seems like once we execute the RenderDocument() function. We go into a sort of information blackout while it does it's thing.
    Is there a way to monitor what it's doing (like the frame it's currently rendering) while the RenderDocument() function is running?

    Do we need to use some kind of Callback for this?

    -ScottA



  • On 03/02/2016 at 14:20, xxxxxxxx wrote:

    There doesn't seem to be a callback of any kind. I think you should just
    render each frame with a separate call to RenderDocument(). Actually, I
    was surprised to read it would render multiple frames.



  • On 03/02/2016 at 14:32, xxxxxxxx wrote:

    In R17 there is this: WriteProgressHook()
    In R13 there is this: SaveCallbackImageFunc(). But it's marked private.

    I've never used these. So I have no idea if these can be used to get information from RenderDocument() or not?

    -ScottA



  • On 03/02/2016 at 18:29, xxxxxxxx wrote:

    Uh I Forgot the C++ RenderDocument() takes. a whole bunch of
    additional paramters compared to the Python version. As you point
    out, there certainly are callbacks available and my statement above
    is false.



  • On 04/02/2016 at 01:57, xxxxxxxx wrote:

    Hi,

    You can use the ProgressHook callback for the RenderDocument() call ( prog parameter).
    It gives the render progress value and type.

    WriteProgressHook is only called during the write process of RenderDocument().



  • On 04/02/2016 at 10:17, xxxxxxxx wrote:

    I need a little help with that Callback.
    Callbacks are my kryptonite. And of course there is no information on this in the forum database.

    I'm using an ASYNC GeDialog plugin with a button to execute the rendering process.
    The render settings and RenderDocument() function are in the Command() method in my plugin.
    I think I have written the callback function correctly. But I'm not 100% sure.

    template<class TYPE> void pr(Real p, RENDERPROGRESSTYPE progress_type, void *private_data)  
    {  
      GePrint(RealToString(p));  
    }
    

    But I can't figure out how to call to that Callback in my RenderDocument() function.
    This doesn't work. "pr" throws an error.

    RenderDocument(GetActiveDocument(), rdata, pr, NULL, bmp, RENDERFLAGS_EXTERNAL, NULL);
    

    I've tried various ways to create a pointer that points to the Callback. But I just can't get it right.
    What am I missing, or doing wrong?

    -ScottA



  • On 04/02/2016 at 13:28, xxxxxxxx wrote:

    Why are you declaring the function as a template? You could use
    something like pr<Int32>, that should work. Better you get rid of the
    template part at all though.



  • On 04/02/2016 at 14:08, xxxxxxxx wrote:

    Because that is how I was told to use a templated Callback.
    Here is an example of using the GeDynamicArrayCallback() which works

    //GeDynamicArrayCallback is declared as:  typedef void GeDynamicArrayCallback(VLONG index, TYPE *value, void *data);  
    //First you have to define a global callback function like this  
      
    template<class TYPE> void myArrayCallback(VLONG index, TYPE *value, void *data)  
    {   
      *value *= 2;   //value is the current value at index in the dynamic array  
    }  
      
    //Then pass that function (myArrayCallback) to the array in your method where your array is  
    Bool myDialog::Command(LONG id,const BaseContainer &msg)  //This is where the code that does something goes  
    {  
      GeDynamicArray<LONG> myarray(3);  
      myarray[0] = 100;  
      myarray[1] = 200;  
      myarray[2] = 300;  
      
      myarray.DoToAll(&myArrayCallback, NULL);  
      
      return TRUE;  
    }
    

    But this code doesn't help me with the ProgressHook callback.
    Because I have no class member to call it with.

    If the ProgressHook callback works differently then I need to know why it's different. And how to use it properly.
    I've been trying to use Google to help figure this out. But MAXON writes their callbacks using void *data. And I can't find anyone posting code like that.
    Every time I need to use a C4D SDK callback. I get entangled in this "How do I use This thing?" battle.
    The code I find on the web and in my C++ books isn't much help understanding how MAXON is doing them.

    -ScottA

    *Edit-- BTW. Thanks for the hint Niklas. This works when used with my callback function:
    RenderDocument(GetActiveDocument(), rdata, pr<Real>, NULL, bmp, RENDERFLAGS_EXTERNAL, NULL);

    Is there anything that we can do with void *private_data?



  • On 05/02/2016 at 01:41, xxxxxxxx wrote:

    Hi Scott,

    Don't mix GeDynamicArrayCallback and ProgressHook callbacks.
    GeDynamicArrayCallback is a special case because callbacks don't usually use templates.
    ProgressHook isn't a templated callback because it has no TYPE parameter.

    So here's how it can be defined:

    static void RenderProgressCallback(Float p, RENDERPROGRESSTYPE progress_type, void* private_data)
    {
    	// Show progress depending on p and progress_type
    	// Use private_data to access data from your code
    }
    

    void* private_data of the ProgressHook parameter is simply passed from the void* private_data parameter of the call to RenderDocument().
    This can be set to a pointer to an object instance so that it can be accessed from the ProgressHook.



  • On 05/02/2016 at 08:03, xxxxxxxx wrote:

    Thanks for the explanation about the callbacks Yannick.
    The SDK is so frustrating because it's full of these odd things in it that I don't normally run into out in the wild.
    But learning these things will make me a better coder.

    Can you tell me what is the benefit for pointing to an object from inside of the ProgressHook?
    I can't think of why that would be useful. But the person that wrote this must have had a good reason for putting it in there.
    I feel like I'm not taking advantage of something that might be useful to me.

    Here's a stripped down example.
    I'm fuzzy on how, and why, to use void *private_data.

    static void rpCallback(Real p, RENDERPROGRESSTYPE progress_type, void *private_data)  
    {  
      renderProg = p;   //renderProg is a global variable I'm using to communicate with the dialog  
      GePrint(RealToString(p));  
      
      BaseObject *obj = GetActiveDocument()->GetFirstObject();  
      if (!obj)return;  
      String objName = obj->GetName();  
      
      //Just doing something to the object while rendering  
      obj->SetRelRot(renderProg+10);  
      obj->Message(MSG_UPDATE);  
      
      private_data = obj;  //<---Am I using this correctly?  
    }  
      
    ...  
      
    Bool MyDialog::Command(LONG id,const BaseContainer &msg)  
    {  
      //This is in my button code  
      
      //Execute the rendering and monitor it's progress using the ProgressHook callback "rpCallback"  
      //Am I calling it correctly?  
      RenderDocument(GetActiveDocument(), rdata, rpCallback, rpCallback, bmp, RENDERFLAGS_EXTERNAL, NULL);  
      
      EventAdd();  
      return TRUE;  
    }
    

    This code works without any errors or crashes.
    But the object never gets rotated until after the rendering is finished.
    So I'm not sure if I'm using the private_data part correctly?

    -ScottA


Log in to reply