Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / async_file_manager_3d.cpp
blobcbb3f5e5dfd0baf27019846a07751f00d62291b9
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/async_file_manager_3d.h"
20 #include "nel/3d/shape.h"
21 #include "nel/3d/mesh.h"
22 #include "nel/3d/texture_file.h"
23 #include "nel/3d/scene_group.h"
25 #include "nel/3d/instance_group_user.h"
27 #include "nel/misc/file.h"
28 #include "nel/misc/path.h"
31 using namespace std;
32 using namespace NLMISC;
34 #ifdef DEBUG_NEW
35 #define new DEBUG_NEW
36 #endif
38 namespace NL3D
41 //CAsyncFileManager3D *CAsyncFileManager3D::_Singleton = NULL;
42 NLMISC_SAFE_SINGLETON_IMPL(CAsyncFileManager3D);
44 // ***************************************************************************
46 CAsyncFileManager3D::CAsyncFileManager3D()
50 // ***************************************************************************
52 /*CAsyncFileManager3D &CAsyncFileManager3D::getInstance()
54 if (_Singleton == NULL)
56 _Singleton = new CAsyncFileManager3D();
58 return *_Singleton;
61 // ***************************************************************************
63 void CAsyncFileManager3D::terminate ()
65 if (_Instance != NULL)
67 CAsyncFileManager3D *afm = _Instance;
68 INelContext::getInstance().releaseSingletonPointer("CAsyncFileManager3D", _Instance);
69 _Instance = NULL;
70 delete afm;
74 // ***************************************************************************
76 void CAsyncFileManager3D::loadMesh(const std::string& meshName, IShape **ppShp, IDriver *pDriver, const CVector &position, uint textureSlot)
78 if (meshName.empty())
79 nlwarning ("Can't load an empty filename");
80 CAsyncFileManager::getInstance().addLoadTask(new CMeshLoad(meshName, ppShp, pDriver, position, textureSlot));
83 // ***************************************************************************
85 // Callback class for canceling a loadMesh
86 class CLoadMeshCancel : public NLMISC::CAsyncFileManager::ICancelCallback
88 public:
89 CLoadMeshCancel (const std::string &meshName)
90 : _MeshName(meshName)
92 virtual ~CLoadMeshCancel() { }
94 private:
95 std::string _MeshName;
97 bool callback(const NLMISC::IRunnable *prunnable) const
99 const CAsyncFileManager3D::CMeshLoad *pML = dynamic_cast<const CAsyncFileManager3D::CMeshLoad*>(prunnable);
100 if (pML != NULL)
102 if (pML->MeshName == _MeshName)
104 return true;
107 return false;
110 void getName (std::string &result) const
112 result = "LoadMeshCancel (" + _MeshName + ")";
116 bool CAsyncFileManager3D::cancelLoadMesh(const std::string& sMeshName)
118 return CAsyncFileManager::getInstance().cancelLoadTask(CLoadMeshCancel(sMeshName));
121 // ***************************************************************************
123 void CAsyncFileManager3D::loadIG (const std::string& IGName, CInstanceGroup **ppIG)
125 CAsyncFileManager::getInstance().addLoadTask(new CIGLoad(IGName, ppIG));
128 // ***************************************************************************
130 void CAsyncFileManager3D::loadIGUser (const std::string& IGName, UInstanceGroup **ppIG)
132 CAsyncFileManager::getInstance().addLoadTask (new CIGLoadUser(IGName, ppIG));
135 // ***************************************************************************
136 void CAsyncFileManager3D::loadTexture (CTextureFile *textureFile, bool *pSgn, const NLMISC::CVector &position)
138 nlassert(textureFile && pSgn);
139 CAsyncFileManager::getInstance().addLoadTask(new CTextureLoad(textureFile, pSgn, position));
142 // Callback class for canceling a load texture
143 class CLoadTextureCancel : public NLMISC::CAsyncFileManager::ICancelCallback
145 public:
146 CLoadTextureCancel (CTextureFile *ptextureFile)
147 : _TextureFile(ptextureFile)
150 virtual ~CLoadTextureCancel() {}
152 private:
153 CTextureFile *_TextureFile;
155 bool callback(const NLMISC::IRunnable *prunnable) const
157 const CAsyncFileManager3D::CTextureLoad *pTL = dynamic_cast<const CAsyncFileManager3D::CTextureLoad*>(prunnable);
158 if (pTL != NULL)
160 if (pTL->TextureFile == _TextureFile)
162 return true;
165 return false;
168 void getName (std::string &result) const
170 result = "LoadTextureCancel (" + _TextureFile->getFileName() + ")";
175 // ***************************************************************************
176 bool CAsyncFileManager3D::cancelLoadTexture (CTextureFile *textFile)
178 return CAsyncFileManager::getInstance().cancelLoadTask(CLoadTextureCancel(textFile));
182 // ***************************************************************************
184 void CAsyncFileManager3D::loadFile (const std::string& sFileName, uint8 **ppFile)
186 CAsyncFileManager::getInstance().loadFile (sFileName, ppFile);
189 // ***************************************************************************
191 void CAsyncFileManager3D::loadFiles (const std::vector<std::string> &vFileNames, const std::vector<uint8**> &vPtrs)
193 CAsyncFileManager::getInstance().loadFiles (vFileNames, vPtrs);
196 // ***************************************************************************
198 void CAsyncFileManager3D::signal (bool *pSgn)
200 CAsyncFileManager::getInstance().signal(pSgn);
203 // ***************************************************************************
205 void CAsyncFileManager3D::cancelSignal (bool *pSgn)
207 CAsyncFileManager::getInstance().cancelSignal(pSgn);
210 // ***************************************************************************
211 // TASKS
212 // ***************************************************************************
214 // ***************************************************************************
215 // MeshLoad
216 // ***************************************************************************
218 CAsyncFileManager3D::CMeshLoad::CMeshLoad(const std::string& sMeshName, IShape** ppShp, IDriver *pDriver, const CVector &position, uint selectedTexture)
220 _pDriver = pDriver;
221 MeshName = sMeshName;
222 _ppShp = ppShp;
223 Position = position;
224 _SelectedTexture = selectedTexture;
227 // ***************************************************************************
229 void CAsyncFileManager3D::CMeshLoad::run()
231 // This set represent the texture already loaded in memory
232 // We have to have this set because the driver load the textures only on the
233 // setupTexture, done in CShapeBank::isPresent. This must be done in the main
234 // thread because setupTexture upload texture to VRAM.
235 typedef set<string> TAlreadyPresentTextureSet;
236 TAlreadyPresentTextureSet AlreadyPresentTextureSet;
240 // Load from file the mesh
241 CShapeStream mesh;
242 CIFile meshfile;
243 meshfile.setAsyncLoading (true);
244 meshfile.setCacheFileOnOpen (true);
245 meshfile.open (CPath::lookup(MeshName));
246 meshfile.serial (mesh);
247 meshfile.close ();
249 // Is the pointer is invalid return -1
250 if (mesh.getShapePointer() == NULL)
252 nlwarning ("Couldn't load '%s'", MeshName.c_str());
253 *_ppShp = (IShape*)-1;
254 delete this;
255 return;
258 CMeshBase *pMesh = dynamic_cast<CMeshBase *>(mesh.getShapePointer());
260 // If the shape is a mesh but the driver is not given or if the shape is not a mesh
261 // then do not try to load the textures
263 if ((pMesh == NULL) || ((pMesh != NULL) && (_pDriver == NULL)))
265 if (_pDriver == NULL || mesh.getShapePointer() == NULL)
267 nlwarning ("mesh or driver is NULL for file '%s'", MeshName.c_str());
270 *_ppShp = mesh.getShapePointer();
271 delete this;
272 return;
275 // Here we are sure that the shape is a mesh and the driver is not null
276 // Parse all materials of the mesh
277 uint i, j;
278 uint nNbMat = pMesh->getNbMaterial();
279 ITexture *pText;
281 for(i = 0; i < nNbMat; ++i)
283 const CMaterial &rMat = pMesh->getMaterial(i);
284 // Parse all textures from this material and generate them
285 for(j = 0; j < IDRV_MAT_MAXTEXTURES; ++j)
286 if (rMat.texturePresent(uint8(j)))
288 pText = rMat.getTexture (uint8(j));
290 // Does this texture is a texture file ?
291 if ((pText != NULL) && (pText->supportSharing()))
293 // Set texture slot
294 pText->selectTexture(_SelectedTexture);
296 // Yes -> Does the texture is already present in the driver ?
297 if( ! _pDriver->isTextureExist(*pText) )
299 // No -> So we have perhaps to load it
300 TAlreadyPresentTextureSet::iterator aptmIt = AlreadyPresentTextureSet.find (pText->getShareName());
301 // Is the texture already loaded ?
302 if(aptmIt == AlreadyPresentTextureSet.end())
304 // Texture not already present
305 // add it
306 AlreadyPresentTextureSet.insert (pText->getShareName());
307 // And load it (to RAM only (upload in VRAM is done in the shape bank))
308 pText->generate(true);
314 // Do the same with lightmaps
315 if (rMat.getShader() == CMaterial::LightMap)
317 j = 0; pText = rMat.getLightMap (j);
318 while (pText != NULL)
320 // Does this texture is a texture file ?
321 if ((pText != NULL) && (pText->supportSharing()))
323 // Yes -> Does the texture is already present in the driver ?
324 if (!_pDriver->isTextureExist(*pText))
326 // No -> So we have perhaps to load it
327 TAlreadyPresentTextureSet::iterator aptmIt = AlreadyPresentTextureSet.find (pText->getShareName());
328 // Is the texture already loaded ?
329 if(aptmIt == AlreadyPresentTextureSet.end())
331 // Texture not already present -> add it and load it to RAM
332 AlreadyPresentTextureSet.insert (pText->getShareName());
333 pText->generate(true);
337 ++j; pText = rMat.getLightMap (j);
341 // Finally affect the pointer (Trans-Thread operation -> this operation must be atomic)
342 *_ppShp = mesh.getShapePointer();
344 catch(const EPathNotFound &)
346 nlwarning ("Couldn't load '%s'", MeshName.c_str());
347 *_ppShp = (IShape*)-1;
348 delete this;
349 return;
351 delete this;
354 // ***************************************************************************
355 void CAsyncFileManager3D::CMeshLoad::getName (std::string &result) const
357 result = "LoadMesh (" + MeshName + ")";
362 // ***************************************************************************
363 // IGLoad
364 // ***************************************************************************
366 // ***************************************************************************
367 CAsyncFileManager3D::CIGLoad::CIGLoad (const std::string &IGName, CInstanceGroup **ppIG)
369 _IGName = IGName;
370 _ppIG = ppIG;
373 // ***************************************************************************
374 void CAsyncFileManager3D::CIGLoad::run (void)
378 CIFile igfile;
379 igfile.setAsyncLoading (true);
380 igfile.setCacheFileOnOpen (true);
381 igfile.open (CPath::lookup (_IGName));
382 CInstanceGroup *pIG = new CInstanceGroup();
383 pIG->serial (igfile);
384 igfile.close();
386 *_ppIG = pIG;
388 catch(const EPathNotFound &)
390 nlwarning ("Couldn't load '%s'", _IGName.c_str());
391 *_ppIG = (CInstanceGroup*)-1;
392 delete this;
393 return;
395 delete this;
398 // ***************************************************************************
399 void CAsyncFileManager3D::CIGLoad::getName (std::string &result) const
401 result = "LoadIG(" + _IGName + ")";
405 // ***************************************************************************
406 // IGLoadUser
407 // ***************************************************************************
409 // ***************************************************************************
410 CAsyncFileManager3D::CIGLoadUser::CIGLoadUser (const std::string &IGName, UInstanceGroup **ppIG)
412 _IGName = IGName;
413 _ppIG = ppIG;
416 // ***************************************************************************
417 void CAsyncFileManager3D::CIGLoadUser::run (void)
419 CInstanceGroupUser *pIG = new CInstanceGroupUser();
422 if (pIG->init (_IGName, true))
424 *_ppIG = pIG;
426 else
428 nlwarning ("Couldn't init '%s'", _IGName.c_str());
429 delete pIG;
430 *_ppIG = (UInstanceGroup*)-1;
431 delete this;
432 return;
435 catch(const EPathNotFound &)
437 nlwarning ("Couldn't load '%s'", _IGName.c_str());
438 delete pIG;
439 *_ppIG = (UInstanceGroup*)-1;
440 delete this;
441 return;
443 delete this;
446 // ***************************************************************************
447 void CAsyncFileManager3D::CIGLoadUser::getName (std::string &result) const
449 result = "LoadIGUser(" + _IGName + ")";
452 // ***************************************************************************
453 // CTextureLoad
454 // ***************************************************************************
456 // ***************************************************************************
457 void CAsyncFileManager3D::CTextureLoad::run()
459 // Load the texture.
460 TextureFile->generate(true);
461 // Ok
462 *Signal= true;
464 delete this;
467 // ***************************************************************************
468 void CAsyncFileManager3D::CTextureLoad::getName (std::string &result) const
470 if (TextureFile)
471 result = "LoadTexture(" + TextureFile->getFileName() + ")";
472 else
473 result = "LoadTexture(NULL)";
476 } // NL3D