How to get material preview my renderer



  • On 21/03/2018 at 01:33, xxxxxxxx wrote:

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

    ---------
    I'm trying to implement my own renderer, And I creating a material plugin for own renderer.
    Now, I'm doing some simple test, most of the code is referenced on the simplematerial.cpp plugin.

    I want to display the rendered result of the custom renderer in the preview of my material plugin.
    I found some similar topic.

    https://plugincafe.maxon.net/topic/9639/12945_render-material-preview-in-custom-renderer&KW=custom+render&PID=51246#51246
    https://plugincafe.maxon.net/topic/9094/12074_matpreview-popup-show-custom-scenes&KW=AddUserPreviewScene&PID=47829#47829
    https://plugincafe.maxon.net/topic/8833/11670_matpreviewgenerateimage-with-custom-renderer&KW=material+preview&PID=46019#46019
    https://plugincafe.maxon.net/topic/9639/12945_render-material-preview-in-custom-renderer&KW=MATPREVIEW_MODIFY_CACHE_SCENE&PID=51274#51274

    MATPREVIEW_GET_OBJECT_INFO
    MATPREVIEW_MODIFY_CACHE_SCENE
    MATPREVIEW_PREPARE_SCENE
    MATPREVIEW_GENERATE_IMAGE

    I'm changing these codes.
    In the MATPREVIEW_GET_OBJECT_INFO, bNoStandardScene is set to True and the scene is being rebuilt within MATPREVIEW_MODIFY_CACHE_SCENE.

    Here, just add a sphere and set to texture tag, and add a camera.

    Next, MATPREVIEW_PREPARE_SCENE sets the material as a sphere texture tag's material link.

    Code here.

    switch (type)
    {
        case MATPREVIEW_GET_OBJECT_INFO:
        {
            GePrint("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 = true;   // we modify the standard scene
            info->lFlags = 0;
            return true;
            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
        {
            GePrint("MATPREVIEW_MODIFY_CACHE_SCENE");
            MatPreviewModifyCacheScene* scene = (MatPreviewModifyCacheScene* )data;
      
            BaseObject* obj = BaseObject::Alloc(Osphere);
            obj->GetDataInstance()->SetParameter(DescID(PRIM_SPHERE_TYPE), 4);
            obj->GetDataInstance()->SetInt32(PRIM_SPHERE_SUB, 12);
            obj->GetDataInstance()->SetBool(PRIM_SPHERE_PERFECT, false);
            obj->SetName("Object");
    			
            BaseTag* mattag = obj->MakeTag(Ttexture);
            if (!mattag) { return false; }
            scene->pDoc->InsertObject(obj, nullptr, nullptr);
            BaseObject* camera = BaseObject::Alloc(Ocamera);
            Matrix dir = Matrix(Vector(0, 0, -300),Vector(0, 0, 0),Vector(0, 0, 0),Vector(0, 0, 0));
            camera->SetMg(dir);
            scene->pDoc->InsertObject(camera, nullptr, nullptr);
            BaseDraw*    bd = scene->pDoc->GetRenderBaseDraw();
            bd->SetSceneCamera(camera, 0);
            return true;
            break;
        }
        case MATPREVIEW_PREPARE_SCENE:
        {
            // let the preview handle the rest...
            GePrint("MATPREVIEW_PREPARE_SCENE");
      
            MatPreviewPrepareScene* preparescene = (MatPreviewPrepareScene* )data;
      
            AutoAlloc<AliasTrans> trans;
            if (!trans) { return false; }
            if (!trans->Init(GetActiveDocument())) { return false; }
    			
            BaseMaterial* matclone = (BaseMaterial* )(Get()->GetClone(COPYFLAGS_0, trans));
            preparescene->pDoc->InsertMaterial(matclone);
            trans->Translate(true);
            if (preparescene->pLink)
                preparescene->pLink->SetLink(matclone);		// necessary
      
            // find the environment object and set the material
            BaseObject* obj = preparescene->pDoc->SearchObject("Object");
            if (obj)
            {
                TextureTag* textag = (TextureTag* )obj->GetTag(Ttexture);
                if (textag) { textag->SetMaterial(matclone); }
            }
            preparescene->bScenePrepared = true;	// inform the preview that the scene is prepared now
            return TRUE;
            break;
        }
        case MATPREVIEW_GENERATE_IMAGE:
        {
            GePrint("MATPREVIEW_GENERATE_IMAGE");
            MatPreviewGenerateImage* image = (MatPreviewGenerateImage* )data;
            if (image->pDoc)
            {
                RenderData* rd = image->pDoc->GetActiveRenderData();
                if (!rd) { return true; }
      
                BaseVideoPost* post = BaseVideoPost::Alloc(ID_VPMYENGINE);
                if (post)
                {
                    rd->InsertVideoPost(post);
                    post->DelBit(BIT_VPDISABLED);
                }
    				
                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);
                bcRender.SetInt32(RDATA_RENDERENGINE, ID_VPMYENGINE);
                image->pDest->Clear(0, 0, 0);
                image->lResult = RenderDocument(image->pDoc, bcRender, nullptr, nullptr, image->pDest,
                RENDERFLAGS_EXTERNAL | RENDERFLAGS_PREVIEWRENDER, image->pThread);
                }
            return true;
            break;
        }
        case MATPREVIEW_GET_PREVIEW_ID:
        {
            *((Int32* )data) = MYMATERIAL_MAT_PREVIEW;
            return true;
        }
    

    However, when creating a new my material, render the open scene file and set the result to the material preview image.

    When I set the MATPREVIEW_GENERATE_IMAGE renderer to Software, Standart, or Physical etc, I get a material preview the sphere in MATPREVIEW_MODIFY_CACHE_SCENE.

    The issue is that my renderer does not render MATPREVIEW_MODIFY_CACHE_SCENE, but renders the scene I am editing and returns it to the material preview.
    I maybe that the description of the custom renderer itself is wrong.
    How to call, conditions of VideoPost::Exexcute, etc ...

    RENDERRESULT VpMyEngine::Execute(BaseVideoPost* node, VideoPostStruct* vps) {
        if (vps->vp == VIDEOPOSTCALL_RENDER && !vps->open && *vps->error == RENDERRESULT_OK && !vps->thread->TestBreak())
        {
            GePrint("call to Execute");
            vps->vd->SkipRenderProcess();
            // Start my renderer...
        }
        return RENDERRESULT_OK;
    }
    

    Could I get advice on where is wrong and whether it is highly likely?
    Or, Could I know if the mistake is Material::Message side or VideoPost side?

    Best Regards,
    Makoto



  • On 22/03/2018 at 23:53, xxxxxxxx wrote:

    Hi Makoto, thanks for writing us.

    With reference to the issue reported and considering the code shared, I suppose the issue is likely to be related to what your rendering engine receives (in terms of scene) when attempting to generate a material preview. What scene actually are you passing to your render in the videopost data? Have you tried to close the active document and try to generate the material preview?

    Looking forward your answer, give best.
    Riccardo



  • On 23/03/2018 at 11:28, xxxxxxxx wrote:

    Thank you knickknack.
    In your advice, I noticed my mistake!

    I used GetActiveDocument () on VideoPost Execute.
    I was stupid...

    Just I did clean up my code and it worked well.

    Really thanks a million!!

    Cheers🍺
    Makoto


Log in to reply