Create new instance of mesh every time it's required (Solves #703)
parent
86c616a545
commit
d76957ee22
|
@ -893,30 +893,12 @@ bool Client::loadMedia(const std::string &data, const std::string &filename)
|
||||||
name = removeStringEnd(filename, model_ext);
|
name = removeStringEnd(filename, model_ext);
|
||||||
if(name != "")
|
if(name != "")
|
||||||
{
|
{
|
||||||
verbosestream<<"Client: Storing model into Irrlicht: "
|
verbosestream<<"Client: Storing model into memory: "
|
||||||
<<"\""<<filename<<"\""<<std::endl;
|
<<"\""<<filename<<"\""<<std::endl;
|
||||||
scene::ISceneManager *smgr = m_device->getSceneManager();
|
if(m_mesh_data.count(filename))
|
||||||
|
errorstream<<"Multiple models with name \""<<filename.c_str()
|
||||||
//check if mesh was already cached
|
<<"\" found; replacing previous model"<<std::endl;
|
||||||
scene::IAnimatedMesh *mesh =
|
m_mesh_data[filename] = data;
|
||||||
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();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2836,3 +2818,31 @@ MtEventManager* Client::getEventManager()
|
||||||
return m_event;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -420,6 +420,7 @@ public:
|
||||||
virtual MtEventManager* getEventManager();
|
virtual MtEventManager* getEventManager();
|
||||||
virtual bool checkLocalPrivilege(const std::string &priv)
|
virtual bool checkLocalPrivilege(const std::string &priv)
|
||||||
{ return checkPrivilege(priv); }
|
{ return checkPrivilege(priv); }
|
||||||
|
virtual scene::IAnimatedMesh* getMesh(const std::string &filename);
|
||||||
|
|
||||||
// The following set of functions is used by ClientMediaDownloader
|
// The following set of functions is used by ClientMediaDownloader
|
||||||
// Insert a media file appropriately into the appropriate manager
|
// Insert a media file appropriately into the appropriate manager
|
||||||
|
@ -509,6 +510,9 @@ private:
|
||||||
// Detached inventories
|
// Detached inventories
|
||||||
// key = name
|
// key = name
|
||||||
std::map<std::string, Inventory*> m_detached_inventories;
|
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
|
#endif // !CLIENT_HEADER
|
||||||
|
|
|
@ -957,10 +957,11 @@ public:
|
||||||
}
|
}
|
||||||
else if(m_prop.visual == "mesh"){
|
else if(m_prop.visual == "mesh"){
|
||||||
infostream<<"GenericCAO::addToScene(): mesh"<<std::endl;
|
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)
|
if(mesh)
|
||||||
{
|
{
|
||||||
m_animated_meshnode = smgr->addAnimatedMeshSceneNode(mesh, NULL);
|
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->animateJoints(); // Needed for some animations
|
||||||
m_animated_meshnode->setScale(v3f(m_prop.visual_size.X,
|
m_animated_meshnode->setScale(v3f(m_prop.visual_size.X,
|
||||||
m_prop.visual_size.Y,
|
m_prop.visual_size.Y,
|
||||||
|
|
|
@ -31,6 +31,9 @@ class ISoundManager;
|
||||||
class IShaderSource;
|
class IShaderSource;
|
||||||
class MtEventManager;
|
class MtEventManager;
|
||||||
class IRollbackReportSink;
|
class IRollbackReportSink;
|
||||||
|
namespace irr { namespace scene {
|
||||||
|
class IAnimatedMesh;
|
||||||
|
}}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An interface for fetching game-global definitions like tool and
|
An interface for fetching game-global definitions like tool and
|
||||||
|
@ -58,6 +61,8 @@ public:
|
||||||
// Only usable on the client
|
// Only usable on the client
|
||||||
virtual ISoundManager* getSoundManager()=0;
|
virtual ISoundManager* getSoundManager()=0;
|
||||||
virtual MtEventManager* getEventManager()=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
|
// Only usable on the server, and NOT thread-safe. It is usable from the
|
||||||
// environment thread.
|
// environment thread.
|
||||||
|
|
Loading…
Reference in New Issue