1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
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"
32 using namespace NLMISC
;
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();
61 // ***************************************************************************
63 void CAsyncFileManager3D::terminate ()
65 if (_Instance
!= NULL
)
67 CAsyncFileManager3D
*afm
= _Instance
;
68 INelContext::getInstance().releaseSingletonPointer("CAsyncFileManager3D", _Instance
);
74 // ***************************************************************************
76 void CAsyncFileManager3D::loadMesh(const std::string
& meshName
, IShape
**ppShp
, IDriver
*pDriver
, const CVector
&position
, uint textureSlot
)
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
89 CLoadMeshCancel (const std::string
&meshName
)
92 virtual ~CLoadMeshCancel() { }
95 std::string _MeshName
;
97 bool callback(const NLMISC::IRunnable
*prunnable
) const
99 const CAsyncFileManager3D::CMeshLoad
*pML
= dynamic_cast<const CAsyncFileManager3D::CMeshLoad
*>(prunnable
);
102 if (pML
->MeshName
== _MeshName
)
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
146 CLoadTextureCancel (CTextureFile
*ptextureFile
)
147 : _TextureFile(ptextureFile
)
150 virtual ~CLoadTextureCancel() {}
153 CTextureFile
*_TextureFile
;
155 bool callback(const NLMISC::IRunnable
*prunnable
) const
157 const CAsyncFileManager3D::CTextureLoad
*pTL
= dynamic_cast<const CAsyncFileManager3D::CTextureLoad
*>(prunnable
);
160 if (pTL
->TextureFile
== _TextureFile
)
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 // ***************************************************************************
212 // ***************************************************************************
214 // ***************************************************************************
216 // ***************************************************************************
218 CAsyncFileManager3D::CMeshLoad::CMeshLoad(const std::string
& sMeshName
, IShape
** ppShp
, IDriver
*pDriver
, const CVector
&position
, uint selectedTexture
)
221 MeshName
= sMeshName
;
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
243 meshfile
.setAsyncLoading (true);
244 meshfile
.setCacheFileOnOpen (true);
245 meshfile
.open (CPath::lookup(MeshName
));
246 meshfile
.serial (mesh
);
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;
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();
275 // Here we are sure that the shape is a mesh and the driver is not null
276 // Parse all materials of the mesh
278 uint nNbMat
= pMesh
->getNbMaterial();
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()))
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
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;
354 // ***************************************************************************
355 void CAsyncFileManager3D::CMeshLoad::getName (std::string
&result
) const
357 result
= "LoadMesh (" + MeshName
+ ")";
362 // ***************************************************************************
364 // ***************************************************************************
366 // ***************************************************************************
367 CAsyncFileManager3D::CIGLoad::CIGLoad (const std::string
&IGName
, CInstanceGroup
**ppIG
)
373 // ***************************************************************************
374 void CAsyncFileManager3D::CIGLoad::run (void)
379 igfile
.setAsyncLoading (true);
380 igfile
.setCacheFileOnOpen (true);
381 igfile
.open (CPath::lookup (_IGName
));
382 CInstanceGroup
*pIG
= new CInstanceGroup();
383 pIG
->serial (igfile
);
388 catch(const EPathNotFound
&)
390 nlwarning ("Couldn't load '%s'", _IGName
.c_str());
391 *_ppIG
= (CInstanceGroup
*)-1;
398 // ***************************************************************************
399 void CAsyncFileManager3D::CIGLoad::getName (std::string
&result
) const
401 result
= "LoadIG(" + _IGName
+ ")";
405 // ***************************************************************************
407 // ***************************************************************************
409 // ***************************************************************************
410 CAsyncFileManager3D::CIGLoadUser::CIGLoadUser (const std::string
&IGName
, UInstanceGroup
**ppIG
)
416 // ***************************************************************************
417 void CAsyncFileManager3D::CIGLoadUser::run (void)
419 CInstanceGroupUser
*pIG
= new CInstanceGroupUser();
422 if (pIG
->init (_IGName
, true))
428 nlwarning ("Couldn't init '%s'", _IGName
.c_str());
430 *_ppIG
= (UInstanceGroup
*)-1;
435 catch(const EPathNotFound
&)
437 nlwarning ("Couldn't load '%s'", _IGName
.c_str());
439 *_ppIG
= (UInstanceGroup
*)-1;
446 // ***************************************************************************
447 void CAsyncFileManager3D::CIGLoadUser::getName (std::string
&result
) const
449 result
= "LoadIGUser(" + _IGName
+ ")";
452 // ***************************************************************************
454 // ***************************************************************************
456 // ***************************************************************************
457 void CAsyncFileManager3D::CTextureLoad::run()
460 TextureFile
->generate(true);
467 // ***************************************************************************
468 void CAsyncFileManager3D::CTextureLoad::getName (std::string
&result
) const
471 result
= "LoadTexture(" + TextureFile
->getFileName() + ")";
473 result
= "LoadTexture(NULL)";