I’m looking into developing a custom Hlms for a port of an ocean simulation from Gazebo11 to Ignition and would like to understand the recommended way to incorporate custom materials and other rendering classes when the code sits outside the main Ignition code base (in a plugin library for example).
The first question is how to switch a visual to use a different Hlms in a nice way, for example using HlmsUnlit rather than HlmPbs. Here is a work-around approach that renders a sphere using Unlit and the rest of the scene using Pbs (with a custom shader using ShaderParams)
// create red material
MaterialPtr red = _scene->CreateMaterial();
red->SetAmbient(0.5, 0.0, 0.0);
red->SetDiffuse(1.0, 0.0, 0.0);
red->SetSpecular(0.5, 0.5, 0.5);
red->SetShininess(50);
red->SetReflectivity(0);
red->SetRenderOrder(3);
// create sphere geometry
auto sphereGeometry = _scene->CreateSphere();
sphereGeometry->SetMaterial(red);
#if 1
// UNLIT MATERIAL - BIT HACKY...
// ogre2 material
auto redOgreMat = std::dynamic_pointer_cast<Ogre2Material>(red);
auto redOgreUnlit = redOgreMat->UnlitDatablock();
// switch to unlit material
MaterialPtr matUnlit;
matUnlit = _scene->CreateMaterial();
auto ogreMat = std::dynamic_pointer_cast<Ogre2Material>(matUnlit);
auto ogreDatablock = ogreMat->UnlitDatablock();
ogreDatablock->setUseColour(true);
ogreDatablock->setColour(Ogre::ColourValue(M_PI, 0.0, 0.0, 1.0));
// igndbg << "Unlit material name [" << *ogreDatablock->getNameStr() << "]\n";
auto ogreGeom = std::dynamic_pointer_cast<Ogre2Geometry>(sphereGeometry);
auto ogreObject = ogreGeom->OgreObject();
auto ogreItem = dynamic_cast<Ogre::Item *>(ogreObject);
ogreItem->setDatablock(ogreDatablock);
// ...UNLIT MATERIAL
#endif
// create sphere visual
VisualPtr sphere = _scene->CreateVisual();
sphere->AddGeometry(sphereGeometry);
sphere->SetOrigin(0.0, -0.5, 0.0);
sphere->SetLocalPosition(20, 0, 5);
sphere->SetLocalRotation(0, 0, 0);
sphere->SetLocalScale(10, 10, 10);
root->AddChild(sphere);
There’s a couple of probs with the approach:
- It’s by-passing almost all the Ignition rendering machinery and all the lifetime control of objects that comes with that.
- There is a some less than robust link library path additions to the CMakeLists.txt to located the render engine plugin headers and libraries for include and link deps.
It would be nice to be able to specify a new HlmsDatablock (or an Ignition equivalent abstraction of this) on the material and set it on the Geometry or Visual directly rather than burrow down to the Ogre2 internals.
The second question has to do with extending the various rendering types and how you then add them to the scene. Most of the object types: Visual, Geometry, Material etc can be (and are) subclassed to create specific types. However the Scene and BaseScene<> need to know about these types because the methods to add / register an object are not accessible outside the Scene class (specifically the method that gets a new object id) . This makes it difficult to add new extension objects defined in a plugin library to the scene. It’s possible by a few workarounds (you can subclass objects to get access to protected members and so on) but it feels like you’re working against the design rather than with it.