RenderDocument() Feedback

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

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


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?


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?


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:


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)  

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?


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.


*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  
  BaseObject *obj = GetActiveDocument()->GetFirstObject();  
  if (!obj)return;  
  String objName = obj->GetName();  
  //Just doing something to the object while rendering  
  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);  
  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?