00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00051 _VBHeapBlocks.resize(1);
00052 _VBHeapBlocks[0]= new CVBHeapBlock;
00053
00054 _VBHeapBlocks[0]->RdrInstances.reserve(100);
00055 _VBHeapBlocks[0]->RdrMeshGeoms.reserve(100);
00056 }
00057
00058
00059 CMeshBlockManager::~CMeshBlockManager()
00060 {
00061
00062 releaseVBHeaps();
00063
00064 delete _VBHeapBlocks[0];
00065 _VBHeapBlocks.clear();
00066 }
00067
00068
00069 void CMeshBlockManager::addInstance(IMeshGeom *meshGeom, CMeshBaseInstance *inst, float polygonCount)
00070 {
00071
00072 if(meshGeom->_MeshBlockManager==NULL)
00073 {
00074
00075 meshGeom->_MeshBlockManager= this;
00076
00077 allocateMeshVBHeap(meshGeom);
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 CVBHeapBlock *hb= _VBHeapBlocks[meshGeom->_MeshVBHeapId & NL3D_MBM_VBHEAP_HEAP_MASK];
00091
00092
00093 if(meshGeom->_RootInstanceId==-1)
00094 {
00095 hb->RdrMeshGeoms.push_back(meshGeom);
00096 }
00097
00098
00099 CInstanceInfo instInfo;
00100 instInfo.MeshGeom= meshGeom;
00101 instInfo.MBI= inst;
00102 instInfo.PolygonCount= polygonCount;
00103
00104
00105 instInfo.NextInstance= meshGeom->_RootInstanceId;
00106 meshGeom->_RootInstanceId= hb->RdrInstances.size();
00107
00108
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
00121 nlassert(drv && scene && renderTrav);
00122 _RenderCtx.Driver= drv;
00123 _RenderCtx.Scene= scene;
00124 _RenderCtx.RenderTrav= renderTrav;
00125
00126
00127
00128
00129
00130
00131 for(j=0; j<_VBHeapBlocks.size();j++)
00132 {
00133 CVBHeapBlock *hb= _VBHeapBlocks[j];
00134
00135 if(j==0)
00136 {
00137 _RenderCtx.RenderThroughVBHeap= false;
00138 }
00139 else
00140 {
00141
00142 _RenderCtx.RenderThroughVBHeap= true;
00143
00144 hb->VBHeap.activate();
00145 }
00146
00147
00148
00149 for(i=0; i<hb->RdrMeshGeoms.size();i++)
00150 {
00151
00152 render(hb->RdrMeshGeoms[i], hb->RdrInstances);
00153 }
00154 }
00155
00156
00157
00158
00159
00160
00161 for(j=0; j<_VBHeapBlocks.size();j++)
00162 {
00163 CVBHeapBlock *hb= _VBHeapBlocks[j];
00164
00165
00166 for(i=0; i<hb->RdrMeshGeoms.size();i++)
00167 {
00168 hb->RdrMeshGeoms[i]->_RootInstanceId= -1;
00169 }
00170
00171
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
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 meshGeom->beginMesh(_RenderCtx);
00192
00193
00194 uint numRdrPass= meshGeom->getNumRdrPasses();
00195
00196
00197 if( meshGeom->sortPerMaterial() )
00198 {
00199
00200 for(uint rdrPass=0;rdrPass<numRdrPass;rdrPass++)
00201 {
00202
00203 sint32 instId= meshGeom->_RootInstanceId;
00204 while( instId!=-1 )
00205 {
00206 CInstanceInfo &instInfo= rdrInstances[instId];
00207
00208
00209 meshGeom->activeInstance(_RenderCtx, instInfo.MBI, instInfo.PolygonCount);
00210
00211
00212 meshGeom->renderPass(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, rdrPass);
00213
00214
00215 instId= instInfo.NextInstance;
00216 }
00217 }
00218 }
00219
00220 else
00221 {
00222
00223 sint32 instId= meshGeom->_RootInstanceId;
00224 while( instId!=-1 )
00225 {
00226 CInstanceInfo &instInfo= rdrInstances[instId];
00227
00228
00229 meshGeom->activeInstance(_RenderCtx, instInfo.MBI, instInfo.PolygonCount);
00230
00231
00232 for(uint rdrPass=0;rdrPass<numRdrPass;rdrPass++)
00233 {
00234
00235 meshGeom->renderPass(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, rdrPass);
00236 }
00237
00238
00239 instId= instInfo.NextInstance;
00240 }
00241 }
00242
00243
00244 meshGeom->endMesh(_RenderCtx);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 void CMeshBlockManager::allocateMeshVBHeap(IMeshGeom *mesh)
00257 {
00258
00259 uint vertexFormat, numVertices;
00260
00261 if( !mesh->getVBHeapInfo(vertexFormat, numVertices) )
00262 return;
00263
00264
00265 if( numVertices==0 )
00266 return;
00267
00268
00269 TVBHeapMap::iterator it= _VBHeapMap.find(vertexFormat);
00270
00271 if(it==_VBHeapMap.end())
00272 return;
00273
00274
00275 uint vbHeapId= it->second;
00276 CVBHeapBlock *vbHeapBlock= _VBHeapBlocks[vbHeapId];
00277
00278 uint indexStart;
00279 if( !vbHeapBlock->VBHeap.allocate(numVertices, indexStart) )
00280 return;
00281
00282
00283
00284
00285
00286 uint meshId;
00287
00288 if( !vbHeapBlock->FreeIds.empty() )
00289 {
00290 meshId= vbHeapBlock->FreeIds.back();
00291 vbHeapBlock->FreeIds.pop_back();
00292 vbHeapBlock->AllocatedMeshGeoms[meshId]= mesh;
00293 }
00294
00295 else
00296 {
00297 meshId= vbHeapBlock->AllocatedMeshGeoms.size();
00298 vbHeapBlock->AllocatedMeshGeoms.push_back(mesh);
00299 }
00300
00301
00302 mesh->_MeshVBHeapIndexStart= indexStart;
00303 mesh->_MeshVBHeapId= vbHeapId + (meshId<<NL3D_MBM_VBHEAP_MESH_SHIFT);
00304
00305
00306
00307
00308 uint8 *dst= vbHeapBlock->VBHeap.lock(indexStart);
00309 mesh->computeMeshVBHeap(dst, indexStart);
00310
00311 vbHeapBlock->VBHeap.unlock(indexStart, indexStart+numVertices);
00312 }
00313
00314
00315 void CMeshBlockManager::freeMeshVBHeap(IMeshGeom *mesh)
00316 {
00317 nlassert(mesh->_MeshVBHeapId);
00318
00319
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
00324 CVBHeapBlock *vbHeapBlock= _VBHeapBlocks[vbHeapId];
00325
00326
00327 vbHeapBlock->VBHeap.free(mesh->_MeshVBHeapIndexStart);
00328
00329
00330 nlassert(meshId<vbHeapBlock->AllocatedMeshGeoms.size());
00331 vbHeapBlock->AllocatedMeshGeoms[meshId]= NULL;
00332 vbHeapBlock->FreeIds.push_back(meshId);
00333
00334
00335 mesh->_MeshVBHeapId= 0;
00336 mesh->_MeshVBHeapIndexStart= 0;
00337 }
00338
00339
00340 void CMeshBlockManager::releaseVBHeaps()
00341 {
00342 uint i,j;
00343
00344
00345 for(j=1; j<_VBHeapBlocks.size();j++)
00346 {
00347 CVBHeapBlock *hb= _VBHeapBlocks[j];
00348
00349
00350 for(i=0;i<hb->AllocatedMeshGeoms.size();i++)
00351 {
00352 IMeshGeom *mesh= hb->AllocatedMeshGeoms[i];
00353
00354 if(mesh)
00355 {
00356
00357 freeMeshVBHeap(mesh);
00358 nlassert( hb->AllocatedMeshGeoms[i] == NULL );
00359 }
00360 }
00361
00362
00363 delete hb;
00364 }
00365
00366
00367 _VBHeapBlocks.resize(1);
00368
00369
00370 contReset(_VBHeapMap);
00371 }
00372
00373
00374 bool CMeshBlockManager::addVBHeap(IDriver *drv, uint vertexFormat, uint maxVertices)
00375 {
00376
00377 TVBHeapMap::iterator it= _VBHeapMap.find(vertexFormat);
00378
00379 if( it!=_VBHeapMap.end() )
00380 return false;
00381
00382
00383 CVBHeapBlock *hb= new CVBHeapBlock;
00384
00385
00386 hb->VBHeap.init(drv, vertexFormat, maxVertices);
00387
00388
00389 _VBHeapBlocks.push_back(hb);
00390 _VBHeapMap[vertexFormat]= _VBHeapBlocks.size()-1;
00391
00392 return true;
00393 }
00394
00395
00396 }