# 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  

mesh_block_manager.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000-2002 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/mesh_block_manager.h"
00029 #include "nel/misc/hierarchical_timer.h"
00030 
00031 using namespace NLMISC;
00032 
00033 namespace NL3D 
00034 {
00035 
00036 
00037 #define NL3D_MBM_MAX_VBHEAP                     255
00038 #define NL3D_MBM_VBHEAP_MESH_SHIFT      8
00039 #define NL3D_MBM_VBHEAP_MESH_MASK       0xFFFFFF00
00040 #define NL3D_MBM_VBHEAP_HEAP_MASK       0x000000FF
00041 
00042 
00043 // ***************************************************************************
00044 CMeshBlockManager::CMeshBlockManager()
00045 {
00046         _RenderCtx.Driver= NULL;
00047         _RenderCtx.Scene= NULL;
00048         _RenderCtx.RenderTrav= NULL;
00049 
00050         // Allocate at least the 0th heap
00051         _VBHeapBlocks.resize(1);
00052         _VBHeapBlocks[0]= new CVBHeapBlock;
00053         // some reserve, avoiding first reallocation.
00054         _VBHeapBlocks[0]->RdrInstances.reserve(100);
00055         _VBHeapBlocks[0]->RdrMeshGeoms.reserve(100);
00056 }
00057 
00058 // ***************************************************************************
00059 CMeshBlockManager::~CMeshBlockManager()
00060 {
00061         // must release any user heap.
00062         releaseVBHeaps();
00063         // Release the 0th one.
00064         delete _VBHeapBlocks[0];
00065         _VBHeapBlocks.clear();
00066 }
00067 
00068 // ***************************************************************************
00069 void                    CMeshBlockManager::addInstance(IMeshGeom *meshGeom, CMeshBaseInstance *inst, float polygonCount)
00070 {
00071         // If the meshGeom has never been added to the manager, may do some precalc
00072         if(meshGeom->_MeshBlockManager==NULL)
00073         {
00074                 // Fill 
00075                 meshGeom->_MeshBlockManager= this;
00076                 // try to fit the meshGeom in one of our VBHeap.
00077                 allocateMeshVBHeap(meshGeom);
00078         }
00079 
00080         // TestYoyo
00081         /*extern uint   TEMP_Yoyo_NInstVBHeap;
00082         extern uint     TEMP_Yoyo_NInstNoVBHeap;
00083         if( meshGeom->_MeshVBHeapId & NL3D_MBM_VBHEAP_HEAP_MASK )
00084                 TEMP_Yoyo_NInstVBHeap++; 
00085         else
00086                 TEMP_Yoyo_NInstNoVBHeap++;*/
00087         // End TestYoyo
00088 
00089         // Choose the HeapBlock to fit in.
00090         CVBHeapBlock    *hb= _VBHeapBlocks[meshGeom->_MeshVBHeapId & NL3D_MBM_VBHEAP_HEAP_MASK];
00091 
00092         // If the mesh geom is not added to this manager, add it.
00093         if(meshGeom->_RootInstanceId==-1)
00094         {
00095                 hb->RdrMeshGeoms.push_back(meshGeom);
00096         }
00097 
00098         // setup the instance.
00099         CInstanceInfo           instInfo;
00100         instInfo.MeshGeom= meshGeom;
00101         instInfo.MBI= inst;
00102         instInfo.PolygonCount= polygonCount;
00103 
00104         // link to the head of the list.
00105         instInfo.NextInstance= meshGeom->_RootInstanceId;
00106         meshGeom->_RootInstanceId= hb->RdrInstances.size();
00107 
00108         // add this instance
00109         hb->RdrInstances.push_back(instInfo);
00110 
00111 }
00112 
00113 // ***************************************************************************
00114 void                    CMeshBlockManager::flush(IDriver *drv, CScene *scene, CRenderTrav *renderTrav)
00115 {
00116         uint    i,j;
00117 
00118         H_AUTO( NL3D_MeshBlockManager );
00119 
00120         // setup the manager
00121         nlassert(drv && scene && renderTrav);
00122         _RenderCtx.Driver= drv;
00123         _RenderCtx.Scene= scene;
00124         _RenderCtx.RenderTrav= renderTrav;
00125         
00126 
00127         // render
00128         //==========
00129 
00130         // sort by Heap first => small setup of VBs.
00131         for(j=0; j<_VBHeapBlocks.size();j++)
00132         {
00133                 CVBHeapBlock    *hb= _VBHeapBlocks[j];
00134                 // if not the special 0th heap, must activate VB.
00135                 if(j==0)
00136                 {
00137                         _RenderCtx.RenderThroughVBHeap= false;
00138                 }
00139                 else
00140                 {
00141                         // set to true => avoid mesh to setup their own VB.
00142                         _RenderCtx.RenderThroughVBHeap= true;
00143                         // activate current VB in driver
00144                         hb->VBHeap.activate();
00145                 }
00146 
00147 
00148                 // Always sort by MeshGeom, in this heap
00149                 for(i=0; i<hb->RdrMeshGeoms.size();i++)
00150                 {
00151                         // render the meshGeom and his instances
00152                         render(hb->RdrMeshGeoms[i], hb->RdrInstances);
00153                 }
00154         }
00155 
00156 
00157         // reset.
00158         //==========
00159 
00160         // For all vb heaps
00161         for(j=0; j<_VBHeapBlocks.size();j++)
00162         {
00163                 CVBHeapBlock    *hb= _VBHeapBlocks[j];
00164 
00165                 // Parse all MehsGeoms, and flag them as Not Added to me
00166                 for(i=0; i<hb->RdrMeshGeoms.size();i++)
00167                 {
00168                         hb->RdrMeshGeoms[i]->_RootInstanceId= -1;
00169                 }
00170 
00171                 // clear rdr arrays
00172                 hb->RdrInstances.clear();
00173                 hb->RdrMeshGeoms.clear();
00174         }
00175 }
00176 
00177 
00178 // ***************************************************************************
00179 void                    CMeshBlockManager::render(IMeshGeom *meshGeom, std::vector<CInstanceInfo> &rdrInstances)
00180 {
00181         // TestYoyo
00182         /*extern uint TEMP_Yoyo_NMeshVBHeap;
00183         extern uint TEMP_Yoyo_NMeshNoVBHeap;
00184         if( _RenderCtx.RenderThroughVBHeap )
00185                 TEMP_Yoyo_NMeshVBHeap++;
00186         else
00187                 TEMP_Yoyo_NMeshNoVBHeap++;*/
00188         // End TestYoyo
00189 
00190         // Start for this mesh.
00191         meshGeom->beginMesh(_RenderCtx);
00192 
00193         // number of renderPasses for this mesh.
00194         uint    numRdrPass= meshGeom->getNumRdrPasses();
00195 
00196         // sort per material first?
00197         if( meshGeom->sortPerMaterial() )
00198         {
00199                 // for all material.
00200                 for(uint rdrPass=0;rdrPass<numRdrPass;rdrPass++)
00201                 {
00202                         // for all instance.
00203                         sint32  instId= meshGeom->_RootInstanceId;
00204                         while( instId!=-1 )
00205                         {
00206                                 CInstanceInfo           &instInfo= rdrInstances[instId];
00207 
00208                                 // activate this instance
00209                                 meshGeom->activeInstance(_RenderCtx, instInfo.MBI, instInfo.PolygonCount);
00210 
00211                                 // render the pass.
00212                                 meshGeom->renderPass(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, rdrPass);
00213 
00214                                 // next instance
00215                                 instId= instInfo.NextInstance;
00216                         }
00217                 }
00218         }
00219         // else sort per instance first
00220         else
00221         {
00222                 // for all instance.
00223                 sint32  instId= meshGeom->_RootInstanceId;
00224                 while( instId!=-1 )
00225                 {
00226                         CInstanceInfo           &instInfo= rdrInstances[instId];
00227 
00228                         // activate this instance
00229                         meshGeom->activeInstance(_RenderCtx, instInfo.MBI, instInfo.PolygonCount);
00230 
00231                         // for all material.
00232                         for(uint rdrPass=0;rdrPass<numRdrPass;rdrPass++)
00233                         {
00234                                 // render the pass.
00235                                 meshGeom->renderPass(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, rdrPass);
00236                         }
00237 
00238                         // next instance
00239                         instId= instInfo.NextInstance;
00240                 }
00241         }
00242 
00243         // End for this mesh.
00244         meshGeom->endMesh(_RenderCtx);
00245 }
00246 
00247 
00248 // ***************************************************************************
00249 // ***************************************************************************
00250 // VBHeap mgt
00251 // ***************************************************************************
00252 // ***************************************************************************
00253 
00254 
00255 // ***************************************************************************
00256 void                    CMeshBlockManager::allocateMeshVBHeap(IMeshGeom *mesh)
00257 {
00258         // Get info from mesh. 
00259         uint vertexFormat, numVertices;
00260         // if the mesh do not support VBHeap, quit.
00261         if( !mesh->getVBHeapInfo(vertexFormat, numVertices) )
00262                 return;
00263 
00264         // In case of ...
00265         if( numVertices==0 )
00266                 return;
00267 
00268         // try to find a VBHeap with this vertexFormat.
00269         TVBHeapMap::iterator    it= _VBHeapMap.find(vertexFormat);
00270         // if not found, abort
00271         if(it==_VBHeapMap.end())
00272                 return;
00273 
00274         // access to this VBHeap.
00275         uint    vbHeapId= it->second;
00276         CVBHeapBlock    *vbHeapBlock= _VBHeapBlocks[vbHeapId];
00277         // try to allocate sapce into the heap. Fail=> abort.
00278         uint    indexStart;
00279         if( !vbHeapBlock->VBHeap.allocate(numVertices, indexStart) )
00280                 return;
00281 
00282         // All is Ok here => setup infos.
00283         //==================
00284 
00285         // Keep track of the mesh => allocate.
00286         uint    meshId;
00287         // try to get a free id.
00288         if( !vbHeapBlock->FreeIds.empty() )
00289         {
00290                 meshId= vbHeapBlock->FreeIds.back();
00291                 vbHeapBlock->FreeIds.pop_back();
00292                 vbHeapBlock->AllocatedMeshGeoms[meshId]= mesh;
00293         }
00294         // else, must add to the array
00295         else
00296         {
00297                 meshId= vbHeapBlock->AllocatedMeshGeoms.size();
00298                 vbHeapBlock->AllocatedMeshGeoms.push_back(mesh);
00299         }
00300 
00301         // info for delete in mesh
00302         mesh->_MeshVBHeapIndexStart= indexStart;
00303         mesh->_MeshVBHeapId= vbHeapId + (meshId<<NL3D_MBM_VBHEAP_MESH_SHIFT);
00304 
00305 
00306         // Fill VB.
00307         //==================
00308         uint8   *dst= vbHeapBlock->VBHeap.lock(indexStart);
00309         mesh->computeMeshVBHeap(dst, indexStart);
00310         // unlock only what vertices have changed (ATI problem)
00311         vbHeapBlock->VBHeap.unlock(indexStart, indexStart+numVertices);
00312 }
00313 
00314 // ***************************************************************************
00315 void                    CMeshBlockManager::freeMeshVBHeap(IMeshGeom *mesh)
00316 {
00317         nlassert(mesh->_MeshVBHeapId);
00318 
00319         // unpack heap and mesh id.
00320         uint    vbHeapId= mesh->_MeshVBHeapId & NL3D_MBM_VBHEAP_HEAP_MASK;
00321         uint    meshId= (mesh->_MeshVBHeapId & NL3D_MBM_VBHEAP_MESH_MASK) >> NL3D_MBM_VBHEAP_MESH_SHIFT;
00322 
00323         // access to this VBHeap.
00324         CVBHeapBlock    *vbHeapBlock= _VBHeapBlocks[vbHeapId];
00325 
00326         // free VB memory.
00327         vbHeapBlock->VBHeap.free(mesh->_MeshVBHeapIndexStart);
00328 
00329         // free this space
00330         nlassert(meshId<vbHeapBlock->AllocatedMeshGeoms.size());
00331         vbHeapBlock->AllocatedMeshGeoms[meshId]= NULL;
00332         vbHeapBlock->FreeIds.push_back(meshId);
00333 
00334         // reset mesh info.
00335         mesh->_MeshVBHeapId= 0;
00336         mesh->_MeshVBHeapIndexStart= 0;
00337 }
00338 
00339 // ***************************************************************************
00340 void                    CMeshBlockManager::releaseVBHeaps()
00341 {
00342         uint    i,j;
00343 
00344         // For all blocks but the 0th
00345         for(j=1; j<_VBHeapBlocks.size();j++)
00346         {
00347                 CVBHeapBlock    *hb= _VBHeapBlocks[j];
00348 
00349                 // For all allocated mesh of this heap.
00350                 for(i=0;i<hb->AllocatedMeshGeoms.size();i++)
00351                 {
00352                         IMeshGeom       *mesh= hb->AllocatedMeshGeoms[i];
00353                         // if the mesh exist.
00354                         if(mesh)
00355                         {
00356                                 // free his VBHeap Data.
00357                                 freeMeshVBHeap(mesh);
00358                                 nlassert( hb->AllocatedMeshGeoms[i] == NULL );
00359                         }
00360                 }
00361 
00362                 // delete the block. NB: VBHeap auto released
00363                 delete hb;
00364         }
00365 
00366         // erase all blocks but 0th
00367         _VBHeapBlocks.resize(1);
00368 
00369         // clear the map.
00370         contReset(_VBHeapMap);
00371 }
00372 
00373 // ***************************************************************************
00374 bool                    CMeshBlockManager::addVBHeap(IDriver *drv, uint vertexFormat, uint maxVertices)
00375 {
00376         // if find an existing vertexFormat, abort.
00377         TVBHeapMap::iterator    it= _VBHeapMap.find(vertexFormat);
00378         // if found, abort
00379         if( it!=_VBHeapMap.end() )
00380                 return false;
00381 
00382         // create the block
00383         CVBHeapBlock    *hb= new CVBHeapBlock;
00384 
00385         // allocate vertex space
00386         hb->VBHeap.init(drv, vertexFormat, maxVertices);
00387 
00388         // add an entry to the array, and the map.
00389         _VBHeapBlocks.push_back(hb);
00390         _VBHeapMap[vertexFormat]= _VBHeapBlocks.size()-1;
00391 
00392         return true;
00393 }
00394 
00395 
00396 } // NL3D