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