Here is the code for my MaterialData plugin:
#include "DL_NodeMaterial.h"
#include "customgui_matpreview.h"
GvNodeMaster* DL_NodeMaterial::GetNodeMaster() {
return node_master;
}
Bool DL_NodeMaterial::Init(GeListNode* node) {
node_master = GvGetWorld()->AllocNodeMaster((BaseList2D*)(this->Get()));
//Create a terminal node for this material
node_master->CreateNode(node_master->GetRoot(), DL_TERMINAL, nullptr, 200,200);
DL_SetDefaultMatpreview((BaseMaterial*)node);
return node_master != nullptr;
}
void DL_NodeMaterial::Free(GeListNode* node) {
GvGetWorld()->FreeNodeMaster(node_master);
}
Bool DL_NodeMaterial::Read(GeListNode *node, HyperFile *hf, Int32 level) {
return node_master->ReadObject(hf,true);
}
Bool DL_NodeMaterial::Write(GeListNode *node, HyperFile *hf) {
return node_master->WriteObject(hf);
}
Bool DL_NodeMaterial::CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, COPYFLAGS flags, AliasTrans *trn) {
DL_NodeMaterial* dst = (DL_NodeMaterial*)dest;
return node_master->CopyTo(dst->GetNodeMaster(), flags, trn);
}
Bool DL_NodeMaterial::Message(GeListNode *node, Int32 type, void *data){
if (GeIsMainThread()) {
ApplicationOutput("Main thread"_s);
}
else {
ApplicationOutput("Not main thread"_s);
}
GvCalcError err = node_master->Execute(GeGetCurrentThread())
ApplicationOutput("Errorcode: "_s);
ApplicationOutput(String::IntToString(err));
if (err == GV_CALC_ERR_INIT_FAILED) {
ApplicationOutput("Init failed"_s);
}
if (err == GV_CALC_ERR_NOT_INITIALIZED) {
ApplicationOutput("Not initialized"_s);
}
return MaterialData::Message(node, type, data);
}
//Initializes resources for rendering.
INITRENDERRESULT DL_NodeMaterial::InitRender(BaseMaterial* mat, const InitRenderStruct& irs)
{
return INITRENDERRESULT::OK;
}
void DL_NodeMaterial::CalcSurface(BaseMaterial* mat, VolumeData* vd)
{
Vector diff, spec;
vd->IlluminanceSimple(&diff, &spec, 0, 0, 0);
vd->col = 0.8*diff;
}
Bool RegisterDLNodeMaterial(void)
{
return RegisterMaterialPlugin(ID_DL_NODEMATERIAL, "DL_NodeMaterial"_s, 0, DL_NodeMaterial::Alloc, "DL_NodeMaterial"_s, 0);
}
As you can see, it does not do much besides store and maintain a GvNodeMaster, which is then displayed and edited in a separate GeDialog.
In the Message() method, I try to update the XPRESSO calculations of the stored GvNodeMaster, but without success. I tried your suggestions of passing a null-pointer for the thread, but this made no difference.
I am assuming this about 3Delight and that you are trying to implement your own GraphView
based material system? If that is the case there can be countless reasons why this is failing for you and we cannot really help you without your code.
Yes, correct! I have functioning implementation of a basic node material system. When rendering, I parse the GvNodeMaster attached to a material and generate a corresponding OSL-shader graph for the renderer. This works as intended (and I am quite exited about it! ). That part does not require the actual XPRESSO nodes to be evaluated (Execute() :ed), since I am doing the parsing myself.
The reason I am asking about Execute() and performing the XPRESSO calculations is that it would be really nice to be able to drive shader parameters via the existing Cinema 4d xpresso nodes! I understood from the Redshift docs that this is supported for that renderer, so it appears possible. If not, it is not a dealbreaker for me, but it would be a really nice feature to support.
So, any ideas on why the execution of the XPRESSO graph does not work would be really appreciated! In the final implementation, I am not sure that the graph execution would happen in the Message() function of the MaterialData, this is just my first step of trying to get it to work somewhere in the code.
Cheers
/Filip