diff options
author | Perttu Ahola <celeron55@gmail.com> | 2014-01-06 13:24:06 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2014-01-06 13:24:31 +0200 |
commit | d76957ee22c27adab89cee551e3ab1c85d8717cc (patch) | |
tree | 4facd7100f9c527203681000a1ffb14351eecc81 | |
parent | 86c616a545efcc8ed8487440d686a17358170756 (diff) | |
download | minetest-d76957ee22c27adab89cee551e3ab1c85d8717cc.tar.gz minetest-d76957ee22c27adab89cee551e3ab1c85d8717cc.tar.bz2 minetest-d76957ee22c27adab89cee551e3ab1c85d8717cc.zip |
Create new instance of mesh every time it's required (Solves #703)
-rw-r--r-- | src/client.cpp | 56 | ||||
-rw-r--r-- | src/client.h | 4 | ||||
-rw-r--r-- | src/content_cao.cpp | 3 | ||||
-rw-r--r-- | src/gamedef.h | 5 |
4 files changed, 44 insertions, 24 deletions
diff --git a/src/client.cpp b/src/client.cpp index 09c940a7a..b830bcdf3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -893,30 +893,12 @@ bool Client::loadMedia(const std::string &data, const std::string &filename) name = removeStringEnd(filename, model_ext); if(name != "") { - verbosestream<<"Client: Storing model into Irrlicht: " + verbosestream<<"Client: Storing model into memory: " <<"\""<<filename<<"\""<<std::endl; - scene::ISceneManager *smgr = m_device->getSceneManager(); - - //check if mesh was already cached - scene::IAnimatedMesh *mesh = - smgr->getMeshCache()->getMeshByName(filename.c_str()); - - if (mesh != NULL) { - errorstream << "Multiple models with name: " << filename.c_str() << - " found replacing previous model!" << std::endl; - - smgr->getMeshCache()->removeMesh(mesh); - mesh = 0; - } - - io::IFileSystem *irrfs = m_device->getFileSystem(); - io::IReadFile *rfile = irrfs->createMemoryReadFile( - *data_rw, data_rw.getSize(), filename.c_str()); - assert(rfile); - - mesh = smgr->getMesh(rfile); - smgr->getMeshCache()->addMesh(filename.c_str(), mesh); - rfile->drop(); + if(m_mesh_data.count(filename)) + errorstream<<"Multiple models with name \""<<filename.c_str() + <<"\" found; replacing previous model"<<std::endl; + m_mesh_data[filename] = data; return true; } @@ -2836,3 +2818,31 @@ MtEventManager* Client::getEventManager() return m_event; } +scene::IAnimatedMesh* Client::getMesh(const std::string &filename) +{ + std::map<std::string, std::string>::const_iterator i = + m_mesh_data.find(filename); + if(i == m_mesh_data.end()){ + errorstream<<"Client::getMesh(): Mesh not found: \""<<filename<<"\"" + <<std::endl; + return NULL; + } + const std::string &data = i->second; + scene::ISceneManager *smgr = m_device->getSceneManager(); + + // Create the mesh, remove it from cache and return it + // This allows unique vertex colors and other properties for each instance + Buffer<char> data_rw(data.c_str(), data.size()); // Const-incorrect Irrlicht + io::IFileSystem *irrfs = m_device->getFileSystem(); + io::IReadFile *rfile = irrfs->createMemoryReadFile( + *data_rw, data_rw.getSize(), filename.c_str()); + assert(rfile); + scene::IAnimatedMesh *mesh = smgr->getMesh(rfile); + rfile->drop(); + // NOTE: By playing with Irrlicht refcounts, maybe we could cache a bunch + // of uniquely named instances and re-use them + mesh->grab(); + smgr->getMeshCache()->removeMesh(mesh); + return mesh; +} + diff --git a/src/client.h b/src/client.h index a74668d5b..1ed80a2b0 100644 --- a/src/client.h +++ b/src/client.h @@ -420,6 +420,7 @@ public: virtual MtEventManager* getEventManager(); virtual bool checkLocalPrivilege(const std::string &priv) { return checkPrivilege(priv); } + virtual scene::IAnimatedMesh* getMesh(const std::string &filename); // The following set of functions is used by ClientMediaDownloader // Insert a media file appropriately into the appropriate manager @@ -509,6 +510,9 @@ private: // Detached inventories // key = name std::map<std::string, Inventory*> m_detached_inventories; + + // Storage for mesh data for creating multiple instances of the same mesh + std::map<std::string, std::string> m_mesh_data; }; #endif // !CLIENT_HEADER diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 640ab6c73..840103cc7 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -957,10 +957,11 @@ public: } else if(m_prop.visual == "mesh"){ infostream<<"GenericCAO::addToScene(): mesh"<<std::endl; - scene::IAnimatedMesh *mesh = smgr->getMesh(m_prop.mesh.c_str()); + scene::IAnimatedMesh *mesh = m_gamedef->getMesh(m_prop.mesh); if(mesh) { m_animated_meshnode = smgr->addAnimatedMeshSceneNode(mesh, NULL); + mesh->drop(); // The scene node took hold of it m_animated_meshnode->animateJoints(); // Needed for some animations m_animated_meshnode->setScale(v3f(m_prop.visual_size.X, m_prop.visual_size.Y, diff --git a/src/gamedef.h b/src/gamedef.h index 1d46b028e..6da288bad 100644 --- a/src/gamedef.h +++ b/src/gamedef.h @@ -31,6 +31,9 @@ class ISoundManager; class IShaderSource; class MtEventManager; class IRollbackReportSink; +namespace irr { namespace scene { + class IAnimatedMesh; +}} /* An interface for fetching game-global definitions like tool and @@ -58,6 +61,8 @@ public: // Only usable on the client virtual ISoundManager* getSoundManager()=0; virtual MtEventManager* getEventManager()=0; + virtual scene::IAnimatedMesh* getMesh(const std::string &filename) + { return NULL; } // Only usable on the server, and NOT thread-safe. It is usable from the // environment thread. |