How to access the ObjectPlugin child objects.
-
Hello,
I have ObjectPlugin that contain a sphere object with texture tag, and from the NodeData.Message() I want to run my "Texture Baker" CommandData plugin to bake the sphere object texture.
The Texture Baker work on default sphere object but on plugin object I don't know how to do to access the sphere object inside the plugin object cache.BaseObject* MyObject::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh) { if (!op) return BaseObject::Alloc(Onull); Bool bIsDirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS_DATA); if (!bIsDirty) return op->GetCache(hh); BaseContainer* objectData = op->GetDataInstance(); if (!objectData) return BaseObject::Alloc(Onull); BaseObject* container = BaseObject::Alloc(Onull); BaseObject* sphere = BaseObject::Alloc(Osphere); if (!container || !sphere) return BaseObject::Alloc(Onull); container->SetName("Container"); sphere->SetName("BakerObject"); Float rad = objectData->GetFloat(HDRISGBAKEROBJECT_RAD); sphere->SetParameter(PRIM_SPHERE_TYPE, 2, DESCFLAGS_SET_0); BaseTag* phongTag = sphere->MakeTag(Tphong); phongTag->SetParameter(PHONGTAG_PHONG_ANGLELIMIT, Bool(true), DESCFLAGS_SET_0); // create the texture tag TextureTag* const textureTag = static_cast<TextureTag*>(sphere->MakeTag(Ttexture)); if (textureTag == nullptr) return container; // apply material BaseDocument* doc = hh->GetDocument(); BaseMaterial* material = doc->SearchMaterial("My Material"); if (!material) return container; textureTag->SetMaterial(material); sphere->InsertUnder(container); return container; }
I found this Topic and I wanted to try the suggested solution, but this crashing the c4d application.
Here how I use it
Bool MyObject::Message(GeListNode* node, Int32 type, void* data) { switch (type) { case MSG_DESCRIPTION_COMMAND: { DescriptionCommand* dc = (DescriptionCommand*)data; const Int32 id = dc->id[0].id; switch (id) { case MYOBJECT_TEXTURE_BAKER: { // allocate a temp doc AutoAlloc<BaseDocument> tempDoc; if (!tempDoc) return false; const Filename path = GeGetStartupWritePath() + Filename("tex") + Filename("texture_baker"); tempDoc->SetDocumentPath(path); // allocate a primitive sphere BaseObject* primSphere = BaseObject::Alloc(Osphere); if (!primSphere) return false; // obtain the polygon representation PolygonObject* polygonSphere = ToPoly(primSphere); // insert into the temp doc tempDoc->InsertObject(polygonSphere, nullptr, nullptr); // allocate a texture tag TextureTag* sphereTextureTag = TextureTag::Alloc(); if (!sphereTextureTag) return false; // set the texture tag params sphereTextureTag->SetParameter(DescID(TEXTURETAG_PROJECTION), TEXTURETAG_PROJECTION_CUBIC, DESCFLAGS_SET_0); // insert into the polygonSphere polygonSphere->InsertTag(sphereTextureTag); // allocate a material AutoAlloc<Material> sphereMaterial; if (!sphereMaterial) return false; // get the BaseContainer of the material BaseContainer *sphereMaterialBC = sphereMaterial->GetDataInstance(); if (!sphereMaterialBC) return false; // allocate the colorizer shader AutoAlloc<BaseShader> colorizerShader(Xcolorizer); if (!colorizerShader) return false; // retrieve the BaseContainer of the colorizer BaseContainer* colorizerShaderBC = colorizerShader->GetDataInstance(); if (!colorizerShaderBC) return false; // allocate the bitmap shader AutoAlloc<BaseShader> bitmapShader(Xbitmap); if (!bitmapShader) return false; // retrieve the BaseContainer of the bitmap BaseContainer* bitmapShaderBC = bitmapShader->GetDataInstance(); if (!bitmapShaderBC) return false; Filename bitmapFilename("bitmap.jpg"); // set the filename of the bitmap shader // NOTE: the file should reside in the application directory if the project files has not been // saved on disk or inside the /tex folder where the project files resides bitmapShaderBC->SetFilename(BITMAPSHADER_FILENAME, bitmapFilename); // set the texture link of the colorizer shader to the bitmapShader colorizerShaderBC->SetLink(SLA_COLORIZER_TEXTURE, bitmapShader); colorizerShader->InsertShader(bitmapShader.Release()); // set the color link of the material to the colorizer shader sphereMaterialBC->SetLink(MATERIAL_COLOR_SHADER, colorizerShader); sphereMaterial->InsertShader(colorizerShader.Release()); // update sphereMaterial->Message(MSG_UPDATE); sphereMaterial->Update(true, true); // insert the material and set the texture tag to use this material sphereTextureTag->SetMaterial(sphereMaterial); tempDoc->InsertMaterial(sphereMaterial.Release()); // allocate a BaseContainer for the texture baking settings and set a few meaningful values BaseContainer textureBakingBC; textureBakingBC.SetInt32(BAKE_TEX_WIDTH, 512); textureBakingBC.SetInt32(BAKE_TEX_HEIGHT, 512); textureBakingBC.SetBool(BAKE_TEX_COLOR, true); // get the UVW tag from the sphere - it's not required to run GenerateUVW() to get the proper // UVW representation because it's done internally by the InitBakeTexture UVWTag* sphereUVWTag = (UVWTag *)polygonSphere->GetTag(Tuvw); // proceed to bake the texture assigned in the color slot BAKE_TEX_ERR initBakingRes = BAKE_TEX_ERR_NONE, bakingRes = BAKE_TEX_ERR_NONE; // init the baking process BaseDocument* bakingDoc = InitBakeTexture(tempDoc, sphereTextureTag, sphereUVWTag, NULL, textureBakingBC, &initBakingRes, NULL); if (initBakingRes != BAKE_TEX_ERR_NONE) { GePrint("Failed to init texture baking[" + String::IntToString(initBakingRes) + "]"); BaseDocument::Free(bakingDoc); return false; } // allocate the bitmap used for storing and saving the baking computations AutoAlloc<BaseBitmap> bakingBmp; if (!bakingBmp) { BaseDocument::Free(bakingDoc); return false; } // execute the texture baking bakingRes = BakeTexture(bakingDoc, textureBakingBC, bakingBmp, NULL, NULL, NULL); if (bakingRes != BAKE_TEX_ERR_NONE) { GePrint("Failed to bake the texture[" + String::IntToString(bakingRes) + "]"); BaseDocument::Free(bakingDoc); return false; } GePrint("Texture baking accomplished"); // free the baking document because we're still owning it BaseDocument::Free(bakingDoc); // save the bitmap on disk Filename bakingBmpFilename("TextureBackingOutput.jpg"); Filename bakingBmpFullFilename = tempDoc->GetDocumentPath() + bakingBmpFilename; IMAGERESULT bakingBmpRes = bakingBmp->Save(bakingBmpFullFilename, FILTER_JPG, nullptr, SAVEBIT_0); if (bakingBmpRes != IMAGERESULT_OK) { GePrint("Failed to save baked texture bitmap [" + String::IntToString(bakingBmpRes) + "]"); return false; } GePrint("Texture baking saved on " + bakingBmpFullFilename.GetString()); break; } } break; } } return true; }
-
Hi,
- All
NodeData
instances have aGeListNode
that represents them somewhere in the scene graph. For anObjectData
instance this is aBaseObject
for example. It is crucial to understand that yourNodeData
type is not instantiated into in the scene graph, but is living its life happily as aBaseData
somewhere else. - To most methods of
NodeData
and its derived types this representing node is passed as an argument (with annoyingly inconsistent naming: node inNodeData
methods, op inObjectData
methods, and the list goes on). You can also get this node with by invokingNodeData::Get()
(really expressive method name, I know). - As described above, your
ObjectData
plugin is represented by aBaseObject
in the scene graph.BaseObject
has multiple methods to access its caches. Most importantlyGetCache()
andGetDeformCache()
. You should always use the second one (the cache of your object after deformers have been applied) unless you are certain that you have to ignore deformers. Note that caches can be empty. In this case you have to fall back to lower caches or do nothing.
Cheers
zipit - All
-
@zipit
Hi,
Thank you, and have a nice day. -
Hi @mfersaoui in the future try to split as much as possible your topic in order to help other users to find relevant information.
I've forked all your discussion about baking in this post Bake Texture within ObjectData.And please mark this topic as solved if your original question is answered (which I think is the case by the good answers from @zipit).
Cheers,
Maxime.