weird behavior in MaterialData Init() [SOLVED]
-
On 29/06/2015 at 16:51, xxxxxxxx wrote:
thanks Andreas, I will rely on constructor then "for local class members".
-
On 29/06/2015 at 22:23, xxxxxxxx wrote:
well. doing it in constructor didn't work "simply because it is calling Alloc() ..."
so what I want to achieve:
store some data inside the material "is this possible with local variables? or I have to use descriptions" -
On 01/07/2015 at 06:02, xxxxxxxx wrote:
Hi Mohamed,
you already found out, that the constructor is a bad idea.
But why not use Init()? If you have a problem with multiple initializations, you could simply have a flag in your class, which gets set after the initialization is done. Next time you enter Init() you simply check the flag and exit. -
On 01/07/2015 at 07:58, xxxxxxxx wrote:
this is horrible!!!, the class is constructed multiple times, how will the flag work?
I wanted to create a singleton flag for any purpose inside the class, but as the class is created everytime it calls matpreview, it doesn't work "all class members are thrown away and I can't rely on Init()"for example:
Init() { m_update_preview = TRUE;}
and in the mat preview render:
if(m_update_preview) { m_update_preview = FALSE; render();}this is totally won't work, no class members are working as it is initialized multiple times, what should I do?
-
On 01/07/2015 at 08:00, xxxxxxxx wrote:
So you have global data, that is used by all instances your material class?
In such cases I tend to use a globally static variable as a flag. -
On 01/07/2015 at 08:37, xxxxxxxx wrote:
not global.
-
On 02/07/2015 at 05:30, xxxxxxxx wrote:
???
You don't want a global flag? Then, why not?
You have no global data? Fine.
But your problem are those repeated Init() calls, right?Regarding my suggestion of a flag as member variable. This could still work, if you correctly implement it in Read()/Write() and CopyTo().
-
On 02/07/2015 at 09:23, xxxxxxxx wrote:
I see, so descriptions can solve this? "trying to avoid overriding Read()/Write()"
-
On 02/07/2015 at 17:45, xxxxxxxx wrote:
to some extent, the problem is half solved, here is what I did:
used CopyTo() , which solved how the buttons work "in the video, I have 2 buttons, one that sets the flag to TRUE and one sets it to FALSE"now the problem is: I want to set the flag to FALSE after the render, some code:
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 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; } }
so with the 2 commands, it works fine, but it doesn't change to FALSE in the MATPREVIEW_GENERATE_IMAGE message, any ideas?
-
On 03/07/2015 at 05:45, xxxxxxxx wrote:
Hm? My questions may be stupid...
Are those cases in the same switch? Then why do you access m_update_preview directly in MSG_DESCRIPTION_COMMAND and via a node in MATPREVIEW_GENERATE_IMAGE?
Otherwise without knowing your class layout it's difficult to tell. Maybe you are resetting the flag in a copy? -
On 03/07/2015 at 07:47, xxxxxxxx wrote:
not via a node
this: ((SevenPhotonsMaterial* )node)->m_update_preview = FALSE;
is the same as this: m_update_preview = FALSE;
it is a class member.
what I wanted to achieve is: when I hit update button,it renders "only once" //this one didn't work,
as it is perma updating, that's why I tried setting the flag to false once it enters "old singleton style"
when I hit cancel button,it breaks any rendering. //I achieved this -
On 06/07/2015 at 09:01, xxxxxxxx wrote:
Hi Mohamed,
the reason you can't reset the flag is indeed, that you are working on a copy. MATPREVIEW_GENERATE_IMAGE is send to a clone of your material for rendering purposes.
That being said, I have to say, I have no solution, yet. I'm currently looking into MATPREVIEW_GET_DIRTY_COUNT and MATPREVIEW_COPY_USERDATA, if these might offer a solution. I will also discuss your case with the rest of the team tomorrow.
I'm sorry, this thread is taking so long and I still can't offer a solution. But I'm still optimistic, we'll find a solution.
-
On 23/07/2015 at 08:21, xxxxxxxx wrote:
Hi Mohamed,
finally I found the time to play around with this. Sorry, it took so long.
As said before, the problem is, that MATPREVIEW_GENERATE_IMAGE is send to a clone of your material. So you can't reset the flag, because you only reset it in the clone, not the original material.My admittedly quite hacky approach is to have a BaseLink member (_linkOrig) in the material. Plus another boolean member (_flagRequestPreview) storing the "render request" flag.
In Init() I initialize as follows:
_linkOrig->SetLink(nullptr); _flagRequestPreview = true; // assuming that a first initial preview is always wanted
When the material is copied (CopyTo()), I set the link. Either to the source material (if not previously set) or to the stored link. Like so:
MaterialPreviewExample* sdata = static_cast<MaterialPreviewExample*>(snode->GetNodeData()); BaseList2D* bl2d = sdata->_linkOrig->GetLink(snode->GetDocument()); if (bl2d) static_cast<MaterialPreviewExample*>(dest)->_linkOriginalMaterial->SetLink(bl2d); else static_cast<MaterialPreviewExample*>(dest)->_linkOriginalMaterial->SetLink(snode);
In MSG_DESCRIPTION_COMMAND I do basically the same as you, simply setting _flagRequestPreview. Of course one could use a checkbox instead of two buttons, but that may be a matter of taste.
Then on MATPREVIEW_GENERATE_IMAGE I simply evaluate the link and use/reset the flag of the original material. Like so:
BaseList2D* bl2d = _linkOrig->GetLink(node->GetDocument()); if (!bl2d) bl2d = _linkOrig->ForceGetLink(); // this will be the most probable path, as preview is rendered in another document Bool flagRender; if (bl2d) { MaterialPreviewExample* dOrig = static_cast<MaterialPreviewExample*>(bl2d->GetNodeData()); flagRender = dOrig->_flagRequestPreview; dOrig->_flagRequestPreview = false; } else { flagRender = _flagRequestPreview; _flagRequestPreview = false; } // Here: flagRender is true, only once after the button got pushed
As I said, it's a bit hacky. But as it is only used for rendering of previews, I think, it should work ok.
Let me know, what you think.Another option would be the use of message MATPREVIEW_PREPARE_SCENE. As far as I can see, this message is still send to the original material. But if you get this message, heavily depends on your preview implementation.
-
On 23/07/2015 at 09:01, xxxxxxxx wrote:
Hi Andreas,
thanks a lot for the help
I will check them tonight and see , most probably the link approach looks good "I will need that link for other stuff later -
On 23/07/2015 at 22:18, xxxxxxxx wrote:
it works very well, thanks Andreas
you can consider this solved.