1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Change material sharing for CMeshSceneNode

This commit is contained in:
sfan5 2025-01-15 16:06:53 +01:00
parent e51221d247
commit 5a8720a484
4 changed files with 35 additions and 34 deletions

View file

@ -34,16 +34,16 @@ public:
/** \return Pointer to mesh which is displayed by this node. */ /** \return Pointer to mesh which is displayed by this node. */
virtual IMesh *getMesh(void) = 0; virtual IMesh *getMesh(void) = 0;
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them directly.
/** In this way it is possible to change the materials of a mesh /** In this way it is possible to change the materials of a mesh
causing all mesh scene nodes referencing this mesh to change, too. causing all mesh scene nodes referencing this mesh to change, too.
\param readonly Flag if the materials shall be read-only. */ \param shared Flag if the materials shall be shared. */
virtual void setReadOnlyMaterials(bool readonly) = 0; virtual void setSharedMaterials(bool shared) = 0;
//! Check if the scene node should not copy the materials of the mesh but use them in a read only style //! Check if the scene node does not copy the materials of the mesh but uses them directly.
/** This flag can be set by setReadOnlyMaterials(). /** This flag can be set by setSharedMaterials().
\return Whether the materials are read-only. */ \return Whether the materials are shared. */
virtual bool isReadOnlyMaterials() const = 0; virtual bool isSharedMaterials() const = 0;
}; };
} // end namespace scene } // end namespace scene

View file

@ -21,7 +21,7 @@ CMeshSceneNode::CMeshSceneNode(IMesh *mesh, ISceneNode *parent, ISceneManager *m
const core::vector3df &scale) : const core::vector3df &scale) :
IMeshSceneNode(parent, mgr, id, position, rotation, scale), IMeshSceneNode(parent, mgr, id, position, rotation, scale),
Mesh(0), Mesh(0),
PassCount(0), ReadOnlyMaterials(false) PassCount(0), SharedMaterials(false)
{ {
setMesh(mesh); setMesh(mesh);
} }
@ -49,9 +49,9 @@ void CMeshSceneNode::OnRegisterSceneNode()
int solidCount = 0; int solidCount = 0;
// count transparent and solid materials in this scene node // count transparent and solid materials in this scene node
const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size(); const u32 numMaterials = SharedMaterials ? Mesh->getMeshBufferCount() : Materials.size();
for (u32 i = 0; i < numMaterials; ++i) { for (u32 i = 0; i < numMaterials; ++i) {
const video::SMaterial &material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i]; const auto &material = SharedMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
if (driver->needsTransparentRenderPass(material)) if (driver->needsTransparentRenderPass(material))
++transparentCount; ++transparentCount;
@ -93,7 +93,7 @@ void CMeshSceneNode::render()
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) {
scene::IMeshBuffer *mb = Mesh->getMeshBuffer(i); scene::IMeshBuffer *mb = Mesh->getMeshBuffer(i);
if (mb) { if (mb) {
const video::SMaterial &material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; const auto &material = SharedMaterials ? mb->getMaterial() : Materials[i];
const bool transparent = driver->needsTransparentRenderPass(material); const bool transparent = driver->needsTransparentRenderPass(material);
@ -164,14 +164,10 @@ const core::aabbox3d<f32> &CMeshSceneNode::getBoundingBox() const
//! returns the material based on the zero based index i. To get the amount //! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount(). //! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hierarchy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial &CMeshSceneNode::getMaterial(u32 i) video::SMaterial &CMeshSceneNode::getMaterial(u32 i)
{ {
if (Mesh && ReadOnlyMaterials && i < Mesh->getMeshBufferCount()) { if (Mesh && SharedMaterials && i < Mesh->getMeshBufferCount()) {
ReadOnlyMaterial = Mesh->getMeshBuffer(i)->getMaterial(); return Mesh->getMeshBuffer(i)->getMaterial();
return ReadOnlyMaterial;
} }
if (i >= Materials.size()) if (i >= Materials.size())
@ -183,7 +179,7 @@ video::SMaterial &CMeshSceneNode::getMaterial(u32 i)
//! returns amount of materials used by this scene node. //! returns amount of materials used by this scene node.
u32 CMeshSceneNode::getMaterialCount() const u32 CMeshSceneNode::getMaterialCount() const
{ {
if (Mesh && ReadOnlyMaterials) if (Mesh && SharedMaterials)
return Mesh->getMeshBufferCount(); return Mesh->getMeshBufferCount();
return Materials.size(); return Materials.size();
@ -206,9 +202,10 @@ void CMeshSceneNode::copyMaterials()
{ {
Materials.clear(); Materials.clear();
if (Mesh) { if (Mesh && !SharedMaterials) {
video::SMaterial mat; video::SMaterial mat;
Materials.reserve(Mesh->getMeshBufferCount());
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) {
IMeshBuffer *mb = Mesh->getMeshBuffer(i); IMeshBuffer *mb = Mesh->getMeshBuffer(i);
if (mb) if (mb)
@ -222,15 +219,18 @@ void CMeshSceneNode::copyMaterials()
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes /* In this way it is possible to change the materials a mesh causing all mesh scene nodes
referencing this mesh to change too. */ referencing this mesh to change too. */
void CMeshSceneNode::setReadOnlyMaterials(bool readonly) void CMeshSceneNode::setSharedMaterials(bool shared)
{ {
ReadOnlyMaterials = readonly; if (SharedMaterials != shared) {
SharedMaterials = shared;
copyMaterials();
}
} }
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
bool CMeshSceneNode::isReadOnlyMaterials() const bool CMeshSceneNode::isSharedMaterials() const
{ {
return ReadOnlyMaterials; return SharedMaterials;
} }
//! Creates a clone of this scene node and its children. //! Creates a clone of this scene node and its children.
@ -245,7 +245,7 @@ ISceneNode *CMeshSceneNode::clone(ISceneNode *newParent, ISceneManager *newManag
newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale); newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale);
nb->cloneMembers(this, newManager); nb->cloneMembers(this, newManager);
nb->ReadOnlyMaterials = ReadOnlyMaterials; nb->SharedMaterials = SharedMaterials;
nb->Materials = Materials; nb->Materials = Materials;
if (newParent) if (newParent)

View file

@ -52,13 +52,16 @@ public:
//! Returns the current mesh //! Returns the current mesh
IMesh *getMesh(void) override { return Mesh; } IMesh *getMesh(void) override { return Mesh; }
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. //! Sets if the scene node should not copy the materials of the mesh but use them directly.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes /** In this way it is possible to change the materials of a mesh
referencing this mesh to change too. */ causing all mesh scene nodes referencing this mesh to change, too.
void setReadOnlyMaterials(bool readonly) override; \param shared Flag if the materials shall be shared. */
void setSharedMaterials(bool shared) override;
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style //! Check if the scene node does not copy the materials of the mesh but uses them directly.
bool isReadOnlyMaterials() const override; /** This flag can be set by setSharedMaterials().
\return Whether the materials are shared. */
bool isSharedMaterials() const override;
//! Creates a clone of this scene node and its children. //! Creates a clone of this scene node and its children.
ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override; ISceneNode *clone(ISceneNode *newParent = 0, ISceneManager *newManager = 0) override;
@ -71,14 +74,13 @@ public:
protected: protected:
void copyMaterials(); void copyMaterials();
core::array<video::SMaterial> Materials; std::vector<video::SMaterial> Materials;
core::aabbox3d<f32> Box{{0, 0, 0}}; core::aabbox3d<f32> Box{{0, 0, 0}};
video::SMaterial ReadOnlyMaterial;
IMesh *Mesh; IMesh *Mesh;
s32 PassCount; s32 PassCount;
bool ReadOnlyMaterials; bool SharedMaterials;
}; };
} // end namespace scene } // end namespace scene

View file

@ -204,7 +204,6 @@ WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id):
// Create the child scene node // Create the child scene node
scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube(); scene::IMesh *dummymesh = g_extrusion_mesh_cache->createCube();
m_meshnode = SceneManager->addMeshSceneNode(dummymesh, this, -1); m_meshnode = SceneManager->addMeshSceneNode(dummymesh, this, -1);
m_meshnode->setReadOnlyMaterials(false);
m_meshnode->setVisible(false); m_meshnode->setVisible(false);
dummymesh->drop(); // m_meshnode grabbed it dummymesh->drop(); // m_meshnode grabbed it