# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

async_file_manager_3d.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/async_file_manager_3d.h"
00029 #include "3d/shape.h"
00030 #include "3d/mesh.h"
00031 #include "3d/texture_file.h"
00032 #include "3d/scene_group.h"
00033 
00034 #include "3d/instance_group_user.h"
00035 
00036 #include "nel/misc/file.h"
00037 #include "nel/misc/path.h"
00038 
00039 
00040 using namespace std;
00041 using namespace NLMISC;
00042 
00043 #define NL3D_MEM_INSTANCE                                       NL_ALLOC_CONTEXT( 3dInst )
00044 #define NL3D_MEM_IG                                                     NL_ALLOC_CONTEXT( 3dIg )
00045 
00046 namespace NL3D
00047 {
00048 
00049 CAsyncFileManager3D *CAsyncFileManager3D::_Singleton = NULL;
00050 
00051 // ***************************************************************************
00052 
00053 CAsyncFileManager3D::CAsyncFileManager3D()
00054 {
00055 }
00056 
00057 // ***************************************************************************
00058 
00059 CAsyncFileManager3D &CAsyncFileManager3D::getInstance()
00060 {
00061         if (_Singleton == NULL)
00062         {
00063                 _Singleton = new CAsyncFileManager3D();
00064         }
00065         return *_Singleton;
00066 }
00067 
00068 // ***************************************************************************
00069 
00070 void CAsyncFileManager3D::terminate ()
00071 {
00072         if (_Singleton != NULL)
00073         {
00074                 delete &getInstance();
00075                 _Singleton = NULL;
00076         }
00077 }
00078 
00079 // ***************************************************************************
00080         
00081 void CAsyncFileManager3D::loadMesh(const std::string& meshName, IShape **ppShp, IDriver *pDriver)
00082 {
00083         CAsyncFileManager::getInstance().addLoadTask(new CMeshLoad(meshName, ppShp, pDriver));
00084 }
00085 
00086 // ***************************************************************************
00087 
00088 // Callback class for canceling a loadMesh
00089 class CLoadMeshCancel : public NLMISC::CAsyncFileManager::ICancelCallback
00090 {
00091 public:
00092         CLoadMeshCancel (const std::string &meshName)
00093                 : _MeshName(meshName)
00094         {}
00095 
00096 private:        
00097         std::string     _MeshName;
00098 
00099         bool callback(const NLMISC::IRunnable *prunnable) const
00100         {
00101                 const CAsyncFileManager3D::CMeshLoad *pML = dynamic_cast<const CAsyncFileManager3D::CMeshLoad*>(prunnable);
00102                 if (pML != NULL)
00103                 {
00104                         if (pML->MeshName == _MeshName)
00105                         {
00106                                 return true;
00107                         }
00108                 }
00109                 return false;
00110         }
00111 };
00112 
00113 bool CAsyncFileManager3D::cancelLoadMesh(const std::string& sMeshName)
00114 {
00115         return CAsyncFileManager::getInstance().cancelLoadTask(CLoadMeshCancel(sMeshName));
00116 }
00117 
00118 // ***************************************************************************
00119         
00120 void CAsyncFileManager3D::loadIG (const std::string& IGName, CInstanceGroup **ppIG)
00121 {
00122         CAsyncFileManager::getInstance().addLoadTask(new CIGLoad(IGName, ppIG));
00123 }
00124 
00125 // ***************************************************************************
00126         
00127 void CAsyncFileManager3D::loadIGUser (const std::string& IGName, UInstanceGroup **ppIG)
00128 {
00129         CAsyncFileManager::getInstance().addLoadTask (new CIGLoadUser(IGName, ppIG));
00130 }
00131 
00132 // ***************************************************************************
00133 void CAsyncFileManager3D::loadTexture (CTextureFile *textureFile, bool *pSgn)
00134 {
00135         nlassert(textureFile && pSgn);
00136         CAsyncFileManager::getInstance().addLoadTask(new CTextureLoad(textureFile, pSgn));
00137 }
00138 
00139 // Callback class for canceling a load texture 
00140 class CLoadTextureCancel : public NLMISC::CAsyncFileManager::ICancelCallback
00141 {
00142 public:
00143         CLoadTextureCancel (CTextureFile *ptextureFile)
00144                 : _TextureFile(ptextureFile)
00145         {}
00146 
00147 private:        
00148         CTextureFile    *_TextureFile;
00149 
00150         bool callback(const NLMISC::IRunnable *prunnable) const
00151         {
00152                 const CAsyncFileManager3D::CTextureLoad *pTL = dynamic_cast<const CAsyncFileManager3D::CTextureLoad*>(prunnable);
00153                 if (pTL != NULL)
00154                 {
00155                         if (pTL->TextureFile == _TextureFile)
00156                         {
00157                                 return true;
00158                         }
00159                 }
00160                 return false;
00161         }
00162 };
00163 
00164 
00165 // ***************************************************************************
00166 bool CAsyncFileManager3D::cancelLoadTexture (CTextureFile *textFile)
00167 {
00168         return CAsyncFileManager::getInstance().cancelLoadTask(CLoadTextureCancel(textFile));
00169 }
00170 
00171 
00172 // ***************************************************************************
00173         
00174 void CAsyncFileManager3D::loadFile (const std::string& sFileName, uint8 **ppFile)
00175 {
00176         CAsyncFileManager::getInstance().loadFile (sFileName, ppFile);
00177 }
00178 
00179 // ***************************************************************************
00180 
00181 void CAsyncFileManager3D::loadFiles (const std::vector<std::string> &vFileNames, const std::vector<uint8**> &vPtrs)
00182 {
00183         CAsyncFileManager::getInstance().loadFiles (vFileNames, vPtrs);
00184 }
00185 
00186 // ***************************************************************************
00187 
00188 void CAsyncFileManager3D::signal (bool *pSgn)
00189 {
00190         CAsyncFileManager::getInstance().signal(pSgn);
00191 }
00192 
00193 // ***************************************************************************
00194 
00195 void CAsyncFileManager3D::cancelSignal (bool *pSgn)
00196 {
00197         CAsyncFileManager::getInstance().cancelSignal(pSgn);
00198 }
00199 
00200 // ***************************************************************************
00201 // TASKS
00202 // ***************************************************************************
00203 
00204 // ***************************************************************************
00205 // MeshLoad
00206 // ***************************************************************************
00207 
00208 CAsyncFileManager3D::CMeshLoad::CMeshLoad(const std::string& sMeshName, IShape** ppShp, IDriver *pDriver)
00209 {
00210         _pDriver = pDriver;
00211         MeshName = sMeshName;
00212         _ppShp = ppShp;
00213 }
00214 
00215 // ***************************************************************************
00216 
00217 void CAsyncFileManager3D::CMeshLoad::run()
00218 {
00219         NL3D_MEM_INSTANCE
00220         // This set represent the texture already loaded in memory
00221         // We have to have this set because the driver load the textures only on the 
00222         // setupTexture, done in CShapeBank::isPresent. This must be done in the main
00223         // thread because setupTexture upload texture to VRAM.
00224         typedef set<string> TAlreadyPresentTextureSet;
00225         TAlreadyPresentTextureSet AlreadyPresentTextureSet;
00226 
00227         try
00228         {
00229                 // Load from file the mesh
00230                 CShapeStream mesh;
00231                 CIFile meshfile;
00232                 meshfile.setAsyncLoading (true);
00233                 meshfile.setCacheFileOnOpen (true);
00234                 meshfile.open (CPath::lookup(MeshName));
00235                 meshfile.serial (mesh);
00236                 meshfile.close ();
00237 
00238                 // Is the pointer is invalid return -1
00239                 if (mesh.getShapePointer() == NULL)
00240                 {
00241                         nlwarning ("Couldn't load '%s'", MeshName.c_str());
00242                         *_ppShp = (IShape*)-1;
00243                         delete this;
00244                         return;
00245                 }
00246 
00247                 CMeshBase *pMesh = dynamic_cast<CMeshBase *>(mesh.getShapePointer());
00248 
00249                 // If the shape is a mesh but the driver is not given or if the shape is not a mesh 
00250                 // so do not try to load the textures
00251 
00252                 if ((pMesh == NULL) || ((pMesh != NULL) && (_pDriver == NULL)))
00253                 {
00254                         if (_pDriver == NULL || mesh.getShapePointer() == NULL)
00255                         {                       
00256                                 nlwarning ("mesh or driver is NULL for file '%s'", MeshName.c_str());
00257                         }
00258                         
00259                         *_ppShp = mesh.getShapePointer();
00260                         delete this;
00261                         return;
00262                 }
00263                 // Here we are sure that the shape is a mesh and the driver is not null
00264                 // Parse all materials of the mesh
00265                 uint i, j;
00266                 uint nNbMat = pMesh->getNbMaterial();
00267                 ITexture *pText;
00268 
00269                 for(i = 0; i < nNbMat; ++i)
00270                 {
00271                         const CMaterial &rMat = pMesh->getMaterial(i);
00272                         // Parse all textures from this material and generate them
00273                         for(j = 0; j < IDRV_MAT_MAXTEXTURES; ++j)
00274                         if (rMat.texturePresent(j))
00275                         {
00276                                 pText = rMat.getTexture (j);
00277                                 // For all texture that are texture file we have to load them
00278                                 CTextureFile *pTextFile = dynamic_cast<CTextureFile*>(pText);
00279                                 // Does this texture is a texture file ?
00280                                 if(pTextFile != NULL)
00281                                 // Yes -> Does the texture is already present in the driver ?
00282                                 if( ! _pDriver->isTextureExist(*pTextFile) )
00283                                 {
00284                                         // No -> So we have perhaps to load it
00285                                         TAlreadyPresentTextureSet::iterator aptmIt = AlreadyPresentTextureSet.find (pTextFile->getFileName());
00286                                         // Is the texture already loaded ?
00287                                         if(aptmIt == AlreadyPresentTextureSet.end())
00288                                         {
00289                                                 // Texture not already present
00290                                                 // add it
00291                                                 AlreadyPresentTextureSet.insert (pTextFile->getFileName());
00292                                                 // And load it (to RAM only (upload in VRAM is done in the shape bank))
00293                                                 pTextFile->setAsyncLoading (true);
00294                                                 pTextFile->generate();
00295                                                 pTextFile->setAsyncLoading (false);
00296                                         }
00297                                 }
00298                         }
00299 
00300                         // Do the same with lightmaps
00301                         if (rMat.getShader() == CMaterial::LightMap)
00302                         {
00303                                 j = 0; pText = rMat.getLightMap (j);
00304                                 while (pText != NULL)
00305                                 {
00306                                         CTextureFile *pTextFile = dynamic_cast<CTextureFile*>(pText);
00307                                         // Does this texture is a texture file ?
00308                                         if(pTextFile != NULL)
00309                                         // Yes -> Does the texture is already present in the driver ?
00310                                         if (!_pDriver->isTextureExist(*pTextFile))
00311                                         {
00312                                                 // No -> So we have perhaps to load it
00313                                                 TAlreadyPresentTextureSet::iterator aptmIt = AlreadyPresentTextureSet.find (pTextFile->getFileName());
00314                                                 // Is the texture already loaded ?
00315                                                 if(aptmIt == AlreadyPresentTextureSet.end())
00316                                                 {
00317                                                         // Texture not already present -> add it and load it to RAM
00318                                                         AlreadyPresentTextureSet.insert (pTextFile->getFileName());
00319                                                         pTextFile->setAsyncLoading (true);
00320                                                         pTextFile->generate();
00321                                                         pTextFile->setAsyncLoading (false);
00322                                                 }
00323                                         }                               
00324                                         ++j; pText = rMat.getLightMap (j);
00325                                 }
00326                         }
00327                 }
00328                 // Finally affect the pointer (Trans-Thread operation -> this operation must be atomic)
00329                 *_ppShp = mesh.getShapePointer();
00330         }
00331         catch(EPathNotFound &)
00332         {
00333                 nlwarning ("Couldn't load '%s'", MeshName.c_str());
00334                 *_ppShp = (IShape*)-1;
00335                 delete this;
00336                 return;
00337         }
00338         delete this;
00339 }
00340 
00341 // ***************************************************************************
00342 // IGLoad
00343 // ***************************************************************************
00344 
00345 // ***************************************************************************
00346 CAsyncFileManager3D::CIGLoad::CIGLoad (const std::string &IGName, CInstanceGroup **ppIG)
00347 {
00348         _IGName = IGName;
00349         _ppIG = ppIG;
00350 }
00351 
00352 // ***************************************************************************
00353 void CAsyncFileManager3D::CIGLoad::run (void)
00354 {
00355         try
00356         {
00357                 CIFile igfile;
00358                 igfile.setAsyncLoading (true);
00359                 igfile.setCacheFileOnOpen (true);
00360                 igfile.open (CPath::lookup (_IGName));
00361                 CInstanceGroup *pIG = new CInstanceGroup();
00362                 pIG->serial (igfile);
00363                 igfile.close();
00364 
00365                 *_ppIG = pIG;
00366         }
00367         catch(EPathNotFound &)
00368         {
00369                 nlwarning ("Couldn't load '%s'", _IGName.c_str());
00370                 *_ppIG = (CInstanceGroup*)-1;
00371                 delete this;
00372                 return;
00373         }
00374         delete this;
00375 }
00376 
00377 // ***************************************************************************
00378 // IGLoadUser
00379 // ***************************************************************************
00380 
00381 // ***************************************************************************
00382 CAsyncFileManager3D::CIGLoadUser::CIGLoadUser (const std::string &IGName, UInstanceGroup **ppIG)
00383 {
00384         _IGName = IGName;
00385         _ppIG = ppIG;
00386 }
00387 
00388 // ***************************************************************************
00389 void CAsyncFileManager3D::CIGLoadUser::run (void)
00390 {
00391         NL3D_MEM_IG
00392         try
00393         {
00394                 CInstanceGroupUser *pIG = new CInstanceGroupUser();
00395                 if (pIG->init (_IGName))
00396                 {               
00397                         *_ppIG = pIG;
00398                 }
00399                 else
00400                 {
00401                         nlwarning ("Couldn't init '%s'", _IGName.c_str());
00402                         *_ppIG = (UInstanceGroup*)-1;
00403                         delete this;
00404                         return;
00405                 }
00406         }
00407         catch(EPathNotFound &)
00408         {
00409                 nlwarning ("Couldn't load '%s'", _IGName.c_str());
00410                 *_ppIG = (UInstanceGroup*)-1;
00411                 delete this;
00412                 return;
00413         }
00414         delete this;
00415 }
00416 
00417 // ***************************************************************************
00418 // CTextureLoad
00419 // ***************************************************************************
00420 
00421 // ***************************************************************************
00422 void    CAsyncFileManager3D::CTextureLoad::run()
00423 {
00424         // Load the texture.
00425         TextureFile->setAsyncLoading (true);
00426         TextureFile->generate();
00427         TextureFile->setAsyncLoading (false);
00428         // Ok
00429         *Signal= true;
00430 
00431         delete this;
00432 }
00433 
00434 } // NL3D
00435 
00436