Preview Image is not generated correctly

On 07/09/2015 at 00:59, xxxxxxxx wrote:

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

Greetings !

I need to implement a Preview image for a material Data plugin.
So, inside message method of material data, i use the MATPREVIEW_GENERATE_IMAGE case to generate the image. The generated image might take 2-3 seconds to be calculated.

So instead of freezing the gui i run the implementation in a different thread and i use RENDERRESULT_OK 
or RENDERRESULT_USERBREAK depending on whether it is ready or not.

There are 2 cases the MATPREVIEW_GENERATE_IMAGE  is executed. The first one is when modify a material parameter and the preview has to be recalculated. It enters multiple times in MATPREVIEW_GENERATE_IMAGE until the image has been generated completed. In this case i return RENDERRESULT_OK to indicate that it has been completed. Everything works fine.

The other case this code (MATPREVIEW_GENERATE_IMAGE) is executed is when you create a new material and the material icon on the bottom left of cinema 4D has to be calculated. In this case, even if i use RENDERRESULT_USERBREAK flag, it won't enter again.

What do i have to do to allow the newly added material to generate it's icon in this specific menu, the way it does as a preview paramater in the Attribute section.

Thank you for your time.

On 07/09/2015 at 09:05, xxxxxxxx wrote:


the material preview image in the Material Editor is rendered using a different system as the preview image in the Material Manager. The Material Editor will retry to render the image, the Material Manager will not.

To avoid freezing the GUI you should check if the host thread stopped and abort rendering if that happens.

for (Int i = 0; i < 50; ++i)  
     image->lResult = RENDERRESULT_USERBREAK;  
     return true;  
 GeSleep(100); // simulate rendering  

best wishes,

On 07/09/2015 at 13:14, xxxxxxxx wrote:


To be honest i don't understand it quite well.
Considering Message is executed in the GUI thread, how can i avoid freezing if i use 50 loops and GeSleep ?

From what you said about material editor and material manager, i understand that my code that calculates the preview image must not run in a different thread since image->lResult = RENDERRESULT_USERBREAK; will not cause Message to rerun (talking about material manager).

So how can i avoid the gui freezing and use a 5 second algorithm without the usage of a different thread OR
how can i notify the MATPREVIEW_GENERATE_IMAGE case to run when the preview calculation in a different thread is completed ?

Also, the code inside if(image->pThread->TestBreak()) block never runs.

Thank you very much for your time.

On 07/09/2015 at 15:35, xxxxxxxx wrote:

@peterakos , I guess you are doing it something wrong.
here is what happens:
1- you have a renderer (running in the execute of a video post plugin)
2- this renderer can have a cancel call for sure "user wants to stop rendering, quit, crash, ..."
3- connect your renderer cancel function with a callback to the function that Sebastian wrote. "without the for loop and GeSleep"
4- now when you call the material preview, it will call your renderer, any cancel call will exit automatically.

On 08/09/2015 at 00:37, xxxxxxxx wrote:


you are not supposed to render the preview image in another thread. You should render it in the given thread but abort the render process if the thread stops. You can check this with TestBreak(). The above code simulates activity with its loop but does not block the GUI since it stops when the thread is stopped. If you use RenderDocument() simple hand over the given thread to that function.

Best wishes,

On 08/09/2015 at 07:02, xxxxxxxx wrote:


I don't have access to the implementation of the function that takes care the rendering of the Preview image (it's an external lib). That means i can't add hooks to it.

Is there another way ?


On 08/09/2015 at 07:54, xxxxxxxx wrote:

if the implementation got a cancel already "so if you render in picture viewer and can exit at any time without problems" , then just calling RenderDocument() and passing the image thread will be sufficient for what you want.

code from simplematerial.cpp

			MatPreviewGenerateImage* image = (MatPreviewGenerateImage* )data;
			if (image->pDoc)
				Int32					w = image->pDest->GetBw();
				Int32					h = image->pDest->GetBh();
				BaseContainer bcRender = image->pDoc->GetActiveRenderData()->GetData();
				bcRender.SetFloat(RDATA_XRES, w);
				bcRender.SetFloat(RDATA_YRES, h);
				if (image->bLowQuality)
				image->pDest->Clear(0, 0, 0);
				image->lResult = RenderDocument(image->pDoc, bcRender, nullptr, nullptr, image->pDest,
			return true;

On 08/09/2015 at 09:43, xxxxxxxx wrote:


I'm afraid there is no other way to handle the material preview image.

Best wishes,