Skip to content

Commit

Permalink
Destroy material when a mesh is deleted (gazebosim#324)
Browse files Browse the repository at this point in the history
* Destroy material when a mesh is deleted

Signed-off-by: ahcorde <[email protected]>

* Fixed issue

Signed-off-by: ahcorde <[email protected]>

* make linters happy

Signed-off-by: ahcorde <[email protected]>

* Improved implementation

Signed-off-by: ahcorde <[email protected]>

* make linters happy

Signed-off-by: ahcorde <[email protected]>

* Ogre2 texture destruction some progress

Signed-off-by: ahcorde <[email protected]>

* Remove meshes when there is no reference

Signed-off-by: ahcorde <[email protected]>

* cleanup code

Signed-off-by: ahcorde <[email protected]>

* Avoid breaking ABI

Signed-off-by: ahcorde <[email protected]>

* make linters happy

Signed-off-by: ahcorde <[email protected]>

* Fixed tests

Signed-off-by: ahcorde <[email protected]>

* Fix macos warnings

Signed-off-by: ahcorde <[email protected]>

* Added feedback

Signed-off-by: ahcorde <[email protected]>

* Doc fix

Signed-off-by: ahcorde <[email protected]>
Signed-off-by: William Lew <[email protected]>
  • Loading branch information
ahcorde authored and WilliamLewww committed Dec 7, 2021
1 parent 1c7359e commit 55eff04
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 3 deletions.
8 changes: 8 additions & 0 deletions ogre/include/ignition/rendering/ogre/OgreMeshFactory.hh
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,15 @@ namespace ignition

protected: virtual bool Validate(const MeshDescriptor &_desc);

/// \brief Remove internal material cache for a specific material
/// \param[in] _name Name of the template material to remove.
public: void ClearMaterialsCache(const std::string &_name);

protected: OgreScenePtr scene;

/// \brief Vector with the template materials, we keep the pointer to be
/// able to remove it when nobody is using it.
protected: std::vector<MaterialPtr> materialCache;
};

class IGNITION_RENDERING_OGRE_VISIBLE OgreSubMeshStoreFactory
Expand Down
4 changes: 4 additions & 0 deletions ogre/include/ignition/rendering/ogre/OgreScene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ namespace ignition

protected: virtual MaterialMapPtr Materials() const override;

/// \brief Remove internal material cache for a specific material
/// \param[in] _name Name of the template material to remove.
public: void ClearMaterialsCache(const std::string &_name);

private: void CreateContext();

private: void CreateRootVisual();
Expand Down
35 changes: 34 additions & 1 deletion ogre/src/OgreMaterial.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,18 @@ void OgreMaterial::Destroy()
{
if (!this->Scene()->IsInitialized())
return;

std::string materialName;
Ogre::MaterialManager &matManager = Ogre::MaterialManager::getSingleton();
#if OGRE_VERSION_LT_1_11_0
if (!this->ogreMaterial.isNull())
{
materialName = this->ogreMaterial->getName();

this->ogreTexState->setBlank();
auto indexUnitStateToRemove =
this->ogrePass->getTextureUnitStateIndex(this->ogreTexState);
this->ogrePass->removeTextureUnitState(indexUnitStateToRemove);

matManager.remove(this->ogreMaterial->getName());
this->ogreMaterial.setNull();
}
Expand All @@ -59,6 +66,32 @@ void OgreMaterial::Destroy()
this->ogreMaterial.reset();
}
#endif
auto &textureManager = Ogre::TextureManager::getSingleton();
auto iend = textureManager.getResourceIterator().end();
for (auto i = textureManager.getResourceIterator().begin(); i != iend;)
{
// A use count of 4 means that only RGM, RM and MeshManager have
// references RGM has one (this one) and RM has 2 (by name and by handle)
// and MeshManager keep another one int the template
Ogre::Resource* res = i->second.get();
if (i->second.useCount() == 4)
{
if (this->textureName == res->getName() &&
res->getName().find(
scene->Name() + "::RenderTexture") == std::string::npos)
{
OgreScenePtr s = std::dynamic_pointer_cast<OgreScene>(this->Scene());
s->ClearMaterialsCache(this->textureName);
this->Scene()->UnregisterMaterial(materialName);
if (i->second.useCount() == 3)
{
textureManager.remove(res->getHandle());
}
break;
}
}
++i;
}
}

//////////////////////////////////////////////////
Expand Down
22 changes: 22 additions & 0 deletions ogre/src/OgreMesh.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,28 @@ void OgreMesh::Destroy()

auto ogreScene = std::dynamic_pointer_cast<OgreScene>(this->Scene());

std::string ogreMeshName = this->ogreEntity->getMesh()->getName();

ogreScene->OgreSceneManager()->destroyEntity(this->ogreEntity);
this->ogreEntity = nullptr;

auto &meshManager = Ogre::MeshManager::getSingleton();
auto iend = meshManager.getResourceIterator().end();
for (auto i = meshManager.getResourceIterator().begin(); i != iend;)
{
// A use count of 3 means that only RGM and RM have references
// RGM has one (this one) and RM has 2 (by name and by handle)
Ogre::Resource* res = i->second.get();
if (i->second.useCount() == 3)
{
if (res->getName() == ogreMeshName)
{
Ogre::MeshManager::getSingleton().remove(ogreMeshName);
break;
}
}
i++;
}
}

//////////////////////////////////////////////////
Expand Down Expand Up @@ -284,6 +304,8 @@ Ogre::SubEntity *OgreSubMesh::OgreSubEntity() const
//////////////////////////////////////////////////
void OgreSubMesh::Destroy()
{
Ogre::MaterialManager::getSingleton().remove(
this->ogreSubEntity->getMaterialName());
OgreRTShaderSystem::Instance()->DetachEntity(this);

BaseSubMesh::Destroy();
Expand Down
20 changes: 20 additions & 0 deletions ogre/src/OgreMeshFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ bool OgreMeshFactory::IsLoaded(const MeshDescriptor &_desc)
return Ogre::MeshManager::getSingleton().resourceExists(name);
}

//////////////////////////////////////////////////
void OgreMeshFactory::ClearMaterialsCache(const std::string &_name)
{
auto it = this->materialCache.begin();
for (auto &mat : this->materialCache)
{
std::string matName = mat->Name();
std::string textureName = mat->Texture();
if (textureName == _name)
{
this->scene->UnregisterMaterial(matName);
break;
}
++it;
}
if (it != this->materialCache.end())
this->materialCache.erase(it);
}

//////////////////////////////////////////////////
bool OgreMeshFactory::LoadImpl(const MeshDescriptor &_desc)
{
Expand Down Expand Up @@ -396,6 +415,7 @@ bool OgreMeshFactory::LoadImpl(const MeshDescriptor &_desc)
if (material)
{
mat->CopyFrom(*material);
materialCache.push_back(mat);
}
else
{
Expand Down
6 changes: 6 additions & 0 deletions ogre/src/OgreScene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,12 @@ VisualStorePtr OgreScene::Visuals() const
return this->visuals;
}

//////////////////////////////////////////////////
void OgreScene::ClearMaterialsCache(const std::string &_name)
{
this->meshFactory->ClearMaterialsCache(_name);
}

//////////////////////////////////////////////////
MaterialMapPtr OgreScene::Materials() const
{
Expand Down
15 changes: 13 additions & 2 deletions ogre2/include/ignition/rendering/ogre2/Ogre2Mesh.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace ignition
//
// forward declaration
class Ogre2MeshPrivate;
class Ogre2SubMeshPrivate;

/// \brief Ogre2.x implementation of the mesh class
class IGNITION_RENDERING_OGRE2_VISIBLE Ogre2Mesh :
Expand Down Expand Up @@ -118,15 +119,22 @@ namespace ignition
/// \brief Destructor
public: virtual ~Ogre2SubMesh();

// Documentation inherited
public: virtual void Destroy() override;

/// \brief Set the name of the mesh stored in Ogre2
/// \param[in] _name Name of the mesh
public: void SetMeshName(const std::string &_name);

/// \brief Get internal ogre subitem created from this submesh
public: virtual Ogre::SubItem *Ogre2SubItem() const;

/// \brief Helper function for setting the material to use
/// \param[in] _material Material to be assigned to the submesh
protected: virtual void SetMaterialImpl(MaterialPtr _material);
protected: virtual void SetMaterialImpl(MaterialPtr _material) override;

/// \brief Initialize the submesh
protected: virtual void Init();
protected: virtual void Init() override;

/// \brief Ogre subitem representing the submesh
protected: Ogre::SubItem *ogreSubItem = nullptr;
Expand All @@ -137,6 +145,9 @@ namespace ignition
/// \brief Make submesh factory our friend so it can create an
/// ogre2 submesh
private: friend class Ogre2SubMeshStoreFactory;

/// \brief Pointer to private data
private: std::unique_ptr<Ogre2SubMeshPrivate> dataPtr;
};
}
}
Expand Down
3 changes: 3 additions & 0 deletions ogre2/include/ignition/rendering/ogre2/Ogre2MeshFactory.hh
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ namespace ignition
/// \brief Pointer to the scene object
protected: Ogre2ScenePtr scene;

/// \brief Remove internal material cache for a specific material
public: void ClearMaterialsCache(const std::string &_name);

/// \brief Pointer to private data class
private: std::unique_ptr<Ogre2MeshFactoryPrivate> dataPtr;
};
Expand Down
4 changes: 4 additions & 0 deletions ogre2/include/ignition/rendering/ogre2/Ogre2Scene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,10 @@ namespace ignition
/// \brief Create the vaiours storage objects
private: void CreateStores();

/// \brief Remove internal material cache for a specific material
/// \param[in] _name Name of the template material to remove.
public: void ClearMaterialsCache(const std::string &_name);

/// \brief Create a shared pointer to self
private: Ogre2ScenePtr SharedThis();

Expand Down
38 changes: 38 additions & 0 deletions ogre2/src/Ogre2Material.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <Hlms/Unlit/OgreHlmsUnlitDatablock.h>
#include <OgreHlmsManager.h>
#include <OgreMaterialManager.h>
#include <OgreTextureManager.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Expand All @@ -44,6 +45,9 @@
/// \brief Private data for the Ogre2Material class
class ignition::rendering::Ogre2MaterialPrivate
{
/// \brief Ogre stores the name using hashes. This variable will
/// store the material hash name
public: std::string hashName;
};

using namespace ignition;
Expand Down Expand Up @@ -87,6 +91,39 @@ void Ogre2Material::Destroy()
matManager.remove(this->ogreMaterial);
this->ogreMaterial.reset();
}

auto &textureManager = Ogre::TextureManager::getSingleton();
auto iend = textureManager.getResourceIterator().end();
for (auto i = textureManager.getResourceIterator().begin(); i != iend;)
{
// A use count of 4 means that only RGM, RM and MeshManager have references
// RGM has one (this one) and RM has 2 (by name and by handle)
// and MeshManager keep another one int the template
Ogre::Resource* res = i->second.get();
if (i->second.useCount() == 5)
{
if (this->dataPtr->hashName == res->getName() &&
res->getName().find(
scene->Name() + "::RenderTexture") == std::string::npos)
{
Ogre2ScenePtr s = std::dynamic_pointer_cast<Ogre2Scene>(this->Scene());
s->ClearMaterialsCache(this->textureName);
this->Scene()->UnregisterMaterial(this->name);
if (i->second.useCount() == 4)
{
textureManager.remove(res->getHandle());
if (!this->textureName.empty())
{
Ogre::HlmsTextureManager *hlmsTextureManager =
this->ogreHlmsPbs->getHlmsManager()->getTextureManager();
hlmsTextureManager->destroyTexture(this->textureName);
}
}
break;
}
}
++i;
}
}

//////////////////////////////////////////////////
Expand Down Expand Up @@ -538,6 +575,7 @@ void Ogre2Material::SetTextureMapImpl(const std::string &_texture,
Ogre::HlmsTextureManager::TextureLocation texLocation =
hlmsTextureManager->createOrRetrieveTexture(baseName,
this->ogreDatablock->suggestMapTypeBasedOnTextureType(_type));
this->dataPtr->hashName = texLocation.texture->getName();

Ogre::HlmsSamplerblock samplerBlockRef;
samplerBlockRef.mU = Ogre::TAM_WRAP;
Expand Down
46 changes: 46 additions & 0 deletions ogre2/src/Ogre2Mesh.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include <Hlms/Pbs/OgreHlmsPbsDatablock.h>
#include <OgreItem.h>
#include <OgreSceneManager.h>
#include <OgreMeshManager.h>
#include <OgreMeshManager2.h>
#include <OgreMaterialManager.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Expand All @@ -40,6 +43,14 @@ class ignition::rendering::Ogre2MeshPrivate
{
};

/// brief Private implementation of the Ogre2SubMesh class
class ignition::rendering::Ogre2SubMeshPrivate
{
/// \brief name of the mesh inside the mesh manager to be able to
/// remove it
public: std::string subMeshName;
};

using namespace ignition;
using namespace rendering;

Expand Down Expand Up @@ -271,6 +282,7 @@ SubMeshStorePtr Ogre2Mesh::SubMeshes() const

//////////////////////////////////////////////////
Ogre2SubMesh::Ogre2SubMesh()
: dataPtr(new Ogre2SubMeshPrivate)
{
}

Expand All @@ -280,6 +292,40 @@ Ogre2SubMesh::~Ogre2SubMesh()
this->Destroy();
}

//////////////////////////////////////////////////
void Ogre2SubMesh::SetMeshName(const std::string &_name)
{
this->dataPtr->subMeshName = _name;
}

//////////////////////////////////////////////////
void Ogre2SubMesh::Destroy()
{
auto meshManager = Ogre::MeshManager::getSingletonPtr();
if (meshManager)
{
auto iend = meshManager->getResourceIterator().end();
for (auto i = meshManager->getResourceIterator().begin(); i != iend;)
{
// A use count of 3 means that only RGM and RM have
// references RGM has one (this one) and RM has 2 (by name and by handle)
Ogre::Resource* res = i->second.get();
if (i->second.useCount() == 3)
{
if (res->getName() == this->dataPtr->subMeshName)
{
Ogre::v1::MeshManager::getSingleton().remove(
this->dataPtr->subMeshName);
Ogre::MeshManager::getSingleton().remove(this->dataPtr->subMeshName);
break;
}
}
++i;
}
}
BaseSubMesh::Destroy();
}

//////////////////////////////////////////////////
Ogre::SubItem *Ogre2SubMesh::Ogre2SubItem() const
{
Expand Down
Loading

0 comments on commit 55eff04

Please sign in to comment.