MatPreview not matching camera view [SOLVED]



  • On 22/06/2015 at 22:09, xxxxxxxx wrote:

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

    ---------
    I have a custom renderer, it renders fine in viewport and picture viewer "the same exact as viewed from camera"

    problem is: in material MatPreview, the view is not matching "it is zoomed a little" , similar to view the scene with field of view = 45, and rendering with field of view = 35. "but as I said in viewport and picture viewer they are matched, so problem is somewhere with MatPreview preparation, and I don't know which part exactly!!"



  • On 29/06/2015 at 06:28, xxxxxxxx wrote:

    Hello,

    you could try to render the preview scenes of the material preview directly with your renderer. You find the scene files under resource\modules\xtensions\preview_scenes. Also, you can modify the preview scene catching the MATPREVIEW_MODIFY_CACHE_SCENE message.

    Best wishes,
    Sebastian



  • On 29/06/2015 at 21:26, xxxxxxxx wrote:

    here is what happens:
    a- if I open the scene file "cinema4d folder/library/materialpreview/anyscene.c4d"
    I can render the scene correctly in viewport, picture viewer.
    IF I create a material inside this document, I can see the matpreview CORRECTLY!!

    b- any other document: the matpreview appears zoomed "wrong".



  • On 02/07/2015 at 18:06, xxxxxxxx wrote:

    I found the problem, but I'm not sure how to fix it.

      
    		case MATPREVIEW_GENERATE_IMAGE:
    			{
    				MatPreviewGenerateImage* image = (MatPreviewGenerateImage* )data;
    				if (image->pDoc)
    				{
    					Int32					w = image->pDest->GetBw();
    					Int32					h = image->pDest->GetBh();
      
    					RenderData* rdata = image->pDoc->GetActiveRenderData();
    					BaseContainer bcRender = rdata->GetData();
      
    					bcRender.SetFloat(RDATA_XRES, w);
    					bcRender.SetFloat(RDATA_YRES, h);
    					bcRender.SetInt32(RDATA_ANTIALIASING, ANTI_GEOMETRY);
    					
    					image->pDest->Clear(0, 0, 0);
    					GePrint("m_update_preview = " + String::IntToString(m_update_preview));
    					if(image->bLowQuality)
    					{
    						bcRender.SetBool(RDATA_RENDERENGINE, RDATA_RENDERENGINE_PREVIEWSOFTWARE);
    						image->lResult = RenderDocument(image->pDoc, bcRender, nullptr, nullptr, image->pDest,
    															 RENDERFLAGS_EXTERNAL | RENDERFLAGS_PREVIEWRENDER, image->pThread);
    					}
    					else if(m_update_preview == TRUE)
    					{
    						((SevenPhotonsMaterial* )node)->m_update_preview = FALSE;
    						BaseVideoPost* myRenderer = BaseVideoPost::Alloc(ID_SEVENPHOTONS);
    						rdata->InsertVideoPost(myRenderer);
    						bcRender.SetInt32(RDATA_RENDERENGINE, ID_SEVENPHOTONS);
      
    						image->lResult = RenderDocument(image->pDoc, bcRender, nullptr, nullptr, image->pDest,
    															 RENDERFLAGS_EXTERNAL, image->pThread);
    					}
    				}
    				break;
    			}
    

    here it gets the image size, and sets it for the render, the image size by default is 800 x 600, but I thought it should be the preview size "which I set to 256 x 256" , what should I do here?



  • On 03/07/2015 at 05:47, xxxxxxxx wrote:

    Hello,

    do you mean with "image size" the dimensions of the pDest bitmap? I cannot confirm any strange values for that bitmap's dimensions. How do you set the preview size and how do you create the preview GUI element?

    Best wishes,
    Sebastian



  • On 03/07/2015 at 07:38, xxxxxxxx wrote:

    yes I mean the dimensions of pDest bitmap, that's why I don't know what is gone wrong.

    here is the whole message code:

      
    Bool SevenPhotonsMaterial::Message(GeListNode* node, Int32 type, void* data)
    {
    	if (type == MSG_UPDATE)
    		updatecount++;
      
    	switch (type)
    	{
    		case MATPREVIEW_GET_OBJECT_INFO:
    			{
    				MatPreviewObjectInfo* info = (MatPreviewObjectInfo* )data;
    				info->bHandlePreview = true;		// own preview handling
    				info->bNeedsOwnScene = true;		// we need our own entry in the preview scene cache
    				info->bNoStandardScene = false;	// we modify the standard scene
    				info->lFlags = 0;
    				break;
    			}
    		case MATPREVIEW_MODIFY_CACHE_SCENE:
    			// modify the preview scene here. We have a pointer to a scene inside the preview scene cache.
    			// our scene contains the object
    			{
    				MatPreviewModifyCacheScene* scene = (MatPreviewModifyCacheScene* )data;
    				// get the striped plane from the preview
    				BaseObject* plane = scene->pDoc->SearchObject("Polygon");
    				if (plane)
    				{
    					plane->SetRelScale(Vector(0.1));	// scale it a bit
    					//update the singleton scene renderer here, also with pushbutton
    					//GePrint("change called");
    				}
    				break;
    			}
    		case MATPREVIEW_PREPARE_SCENE:
    			// let the preview handle the rest...
    			//return true;
    			break;
    		case MATPREVIEW_GENERATE_IMAGE:
    			{
    				MatPreviewGenerateImage* image = (MatPreviewGenerateImage* )data;
    				if (image->pDoc)
    				{
    					Int32					w = image->pDest->GetBw();
    					Int32					h = image->pDest->GetBh();
      
    					RenderData* rdata = image->pDoc->GetActiveRenderData();
    					BaseContainer bcRender = rdata->GetData();
      
    					bcRender.SetFloat(RDATA_XRES, w);
    					bcRender.SetFloat(RDATA_YRES, h);
    					bcRender.SetInt32(RDATA_ANTIALIASING, ANTI_GEOMETRY);
    					
    					image->pDest->Clear(0, 0, 0);
    					GePrint("m_update_preview = " + String::IntToString(m_update_preview));
    					if(image->bLowQuality)
    					{
    						bcRender.SetBool(RDATA_RENDERENGINE, RDATA_RENDERENGINE_PREVIEWSOFTWARE);
    						image->lResult = RenderDocument(image->pDoc, bcRender, nullptr, nullptr, image->pDest,
    															 RENDERFLAGS_EXTERNAL | RENDERFLAGS_PREVIEWRENDER, image->pThread);
    					}
    					else if(m_update_preview == TRUE)
    					{
    						((SevenPhotonsMaterial* )node)->m_update_preview = FALSE;
    						BaseVideoPost* myRenderer = BaseVideoPost::Alloc(ID_SEVENPHOTONS);
    						rdata->InsertVideoPost(myRenderer);
    						bcRender.SetInt32(RDATA_RENDERENGINE, ID_SEVENPHOTONS);
      
    						image->lResult = RenderDocument(image->pDoc, bcRender, nullptr, nullptr, image->pDest,
    															 RENDERFLAGS_EXTERNAL, image->pThread);
    					}
    				}
    				break;
    			}
    		case MATPREVIEW_GET_PREVIEW_ID:
    			{
    				*((Int32* )data) = SEVENPHOTONS_MAT_PREVIEW;
    				break;
    			}
    		case MSG_MATERIALDRAGANDDROP:
    			{
    				BaseMaterial* mat = static_cast<BaseMaterial*>(node);
    				MaterialDragAndDrop* mdd = static_cast<MaterialDragAndDrop*>(data);
    				mdd->result = mdd->op->MakeTag(Ttexture);
    				mdd->result->SetParameter(TEXTURETAG_MATERIAL, mat, DESCFLAGS_SET_0);
    				mdd->result->SetParameter(TEXTURETAG_PROJECTION, TEXTURETAG_PROJECTION_UVW, DESCFLAGS_SET_0);
    				break;
    			}
    		case MSG_DESCRIPTION_COMMAND:
    			{
    				DescriptionCommand* dc = (DescriptionCommand* )data;
    				if (dc->id[0].id == SEVENPHOTONS_MAT_PREVIEW_UPDATE)
    				{
    					m_update_preview = TRUE;
    					break;
    				}
    				else if (dc->id[0].id == SEVENPHOTONS_MAT_PREVIEW_UPDATE_STOP)
    				{
    					m_update_preview = FALSE;
    					break;
    				}
    			}
    	}
    	return MaterialData::Message(node, type, data);
    }  
    

    and the GUI is created using resources

      
    CONTAINER Msevenphotons
    {
    	NAME Msevenphotons;
    	GROUP
    	{
    		MATPREVIEW SEVENPHOTONS_MAT_PREVIEW { OPEN; MIN_WIDTH 288; MIN_HEIGHT 288; NO_SIZE_POPUP; NO_SCENESETTINGS;}
    	}
      
    	INCLUDE Mbase;
    }
    

    and in Init()

      
    	GeData previewData(CUSTOMDATATYPE_MATPREVIEW, DEFAULTVALUE);
    	MaterialPreviewData* preview = (MaterialPreviewData* )previewData.GetCustomDataType(CUSTOMDATATYPE_MATPREVIEW);
    	if (!preview)
    		return false;
      
    	data->SetData(SEVENPHOTONS_MAT_PREVIEW, previewData);
    

    and GetDParameter()

      
    	if(id[0].id == SEVENPHOTONS_MAT_PREVIEW)
    	{
    		return GetDParameterPreview(data, (GeData* )&t_data, flags, SEVENPHOTONS_MAT_PREVIEW, updatecount, (BaseMaterial* )node);
    	}  
    

    SetDParameter()

      
    	if(id[0].id == SEVENPHOTONS_MAT_PREVIEW)
    	{
    		return SetDParameterPreview(data, &t_data, flags, SEVENPHOTONS_MAT_PREVIEW);
    	}
    


  • On 08/07/2015 at 10:43, xxxxxxxx wrote:

    Hello,

    using your code and resource files the dimensions of the bitmap are 288 x 288 pixel. Exactly as defined in the resource file. Where do you change the resolution to 256 x 256?

    best wishes,
    Sebastian



  • On 08/07/2015 at 11:05, xxxxxxxx wrote:

    sorry I meant 288 x 288, the size should be 288 x 288 "or whatever  is written in the resource file" , I mistyped 256 x 256 in the previous reply, but the problem remains the same, it uses wrong dimensions "or possibly wrong aspect ratio?"



  • On 13/07/2015 at 19:15, xxxxxxxx wrote:

    any solution for this? I see the camera frustum is somehow affected by the current document image size



  • On 14/07/2015 at 00:29, xxxxxxxx wrote:

    Hello,

    as I said, I cannot reproduce any problems using the code you posted. Maybe it is related to the code of your renderer video post.

    Best wishes,
    Sebastian



  • On 14/07/2015 at 04:37, xxxxxxxx wrote:

    here is the problem:

      
    		RayCamera *RCam = vps->vd->GetRayCamera();
    		CameraObject* mCam = static_cast<CameraObject*>(RCam->link);
    		GeData fov_h;
    		mCam->GetParameter(DescID(CAMERAOBJECT_FOV), fov_h, (DTYPE_REAL, DESCFLAGS_GET_0));
      
    		GeData fov_v;
    		mCam->GetParameter(DescID(CAMERAOBJECT_FOV_VERTICAL), fov_v, (DTYPE_REAL, DESCFLAGS_GET_0));
    		float fov = (fov_v.GetFloat() < fov_h.GetFloat())? fov_v.GetFloat() : fov_h.GetFloat();
    

    this code gets the wrong fov, I consider this a bug, you may confirm or tell me how to fix, here is what happens:
    1- open any material preview scene "for example Sphere(GI).c4d"
    2- the scene by default is set to width = 90, height = 90, camera focal length = 190, sensor size = 36
    and fov_h = fov_v = 10.824 ° = 0.18891f
    3- if I render from MatPreview, with my scene standard settings (width = 800, height = 600) "the document which contains the material", I read this:
    fov_h = 10.824 ° = 0.18891f
    fov_v = 8.128 ° = 0.14186f   // how is this<<<<<-------- it SHOULD be affected by MatPreview width and height which are printed = 288, 288

    hope this clarifies where the problem is, the MatPreview camera fov somehow affected by the current document NOT the MatPreview document.



  • On 14/07/2015 at 10:07, xxxxxxxx wrote:

    Hello,

    why do you include "DTYPE_REAL" in your call of GetParameter()? I cannot see how this makes any sense.

    Best wishes,
    Sebastian



  • On 14/07/2015 at 10:53, xxxxxxxx wrote:

    I copy pasted it from somewhere when I was searching, but this doesn't change any result after removing "DTYPE_REAL"



  • On 15/07/2015 at 08:27, xxxxxxxx wrote:

    Hello,

    as commented in the header file, both CAMERAOBJECT_FOV and CAMERAOBJECT_FOV_VERTICAL are "virtual" parameters that are not stored in the camera's base container (and thus should not be used this way).

    In the case of CAMERAOBJECT_FOV_VERTICAL it indeed accesses the active object. It seems this parameter is only used in certain internal cases. So you have to calculate this value on your own using the current film aspect and CAMERAOBJECT_APERTURE.

    Best wishes,
    Sebastian



  • On 15/07/2015 at 09:31, xxxxxxxx wrote:

    so I consider this a "bad behavior" which is not anticipated.
    thanks Sebastian for clarification, I will handle it.



  • On 19/07/2015 at 00:24, xxxxxxxx wrote:

    here is what I did, works fine, but I need to confirm that it is safe "I'm using BaseVideoPost node's document"

      
    		BaseContainer bcRender = node->GetDocument()->GetActiveRenderData()->GetData();
      
    		float w;
    		float h;
      
    		w = bcRender.GetFloat(RDATA_XRES);
    		h = bcRender.GetFloat(RDATA_YRES);
      
    		float fov_h = 2.f * atanf((ap) / (2.f * focus));
    		float fov_v = 2.f * atanf((ap / (w / h)) / (2.f * focus));
      
    		float fov = (fov_v < fov_h)? fov_v : fov_h;  
    


  • On 20/07/2015 at 01:39, xxxxxxxx wrote:

    Hello,

    RenderDocument() has a parameter for the used render settings. These render settings can be accessed with Render::GetRenderData(), so if you want to get the resolution you should use:

      
    BaseContainer rdata = vps->render->GetRenderData();  
    

    best wishes,
    Sebastian



  • On 20/07/2015 at 02:31, xxxxxxxx wrote:

    true, but...
    the SDK got a bug at this point, let me explain where the problem occurs:
    1- let's consider I used the old approach "CAMERAOBJECT_FOV_VERTICAL and CAMERAOBJECT_FOV" as you mentioned, these are virtual,
    so they fail in MatPreview "as they use the current Document camera, NOT the MatPreview Document camera"

    2- I already tested vps->render->GetRenderData(), works fine in MatPreview and picture viewer
    but it fails in viewport "guess what? camera horizontal and vertical FOV are represented by the virtual descriptions!!!
    which doesn't match Document dimensions" for example: Document image = 1280 x 720, viewport image = 1100 x 500,
    camera got FOV calculated from the 1280 x 720 image "not the correct width, height values"



  • On 20/07/2015 at 11:04, xxxxxxxx wrote:

    Hello,

    you could check the renderflags if RENDERFLAGS_EXTERNAL is set and react accordingly.

    Best wishes,
    Sebastian



  • On 20/07/2015 at 11:06, xxxxxxxx wrote:

    this looks great!!. so RENDERFLAGS_EXTERNAL means non viewport render?


Log in to reply