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/coarse_mesh_manager.h"
00029 #include "3d/mesh.h"
00030 #include "3d/texture_file.h"
00031 #include "nel/misc/hierarchical_timer.h"
00032 #include "3d/clip_trav.h"
00033
00034
00035 namespace NL3D
00036 {
00037
00038
00039 H_AUTO_DECL( NL3D_StaticLod_AddDelMesh )
00040 H_AUTO_DECL( NL3D_StaticLod_UpdateMesh )
00041
00042
00043
00044
00045 void CCoarseMeshManager::registerBasic()
00046 {
00047 CMOT::registerModel (CoarseMeshManagerId, TransformId, CCoarseMeshManager::creator);
00048 CMOT::registerObs (ClipTravId, CoarseMeshManagerId, CCoarseMeshClipObs::creator);
00049 }
00050
00051
00052
00053 CCoarseMeshManager::CCoarseMeshManager()
00054 {
00055
00056 setTransparency (false);
00057 setOpacity (true);
00058
00059
00060
00061 _Texture=new CTextureFile ();
00062
00063
00064
00065
00066 _Material.initUnlit ();
00067 _Material.setDoubleSided (true);
00068 _Material.setAlphaTest (true);
00069 _Material.setColor (CRGBA (255, 255, 255));
00070
00071 _Material.setSrcBlend(CMaterial::srcalpha);
00072 _Material.setDstBlend(CMaterial::invsrcalpha);
00073
00074
00075 _Material.setTexture (0, _Texture);
00076 }
00077
00078
00079
00080 void CCoarseMeshManager::setTextureFile (const char* file)
00081 {
00082 _Texture->setFileName (file);
00083 }
00084
00085
00086
00087 uint64 CCoarseMeshManager::addMesh (const CMeshGeom& geom)
00088 {
00089 H_AUTO_USE( NL3D_StaticLod_AddDelMesh );
00090
00091
00092 const CVertexBuffer &vertexBuffer=geom.getVertexBuffer();
00093
00094
00095
00096
00097 uint32 renderPass = vertexBuffer.getNumVertices () / NL3D_COARSEMESH_VERTEXBUFFER_GRANULARITY;
00098 if (NL3D_COARSEMESH_VERTEXBUFFER_GRANULARITY_MASK&vertexBuffer.getNumVertices ())
00099 renderPass++;
00100
00101
00102 TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00103
00104
00105 if ( ite==_RenderPass.end() )
00106 {
00107
00108 _RenderPass.insert (TRenderingPassMap::value_type (renderPass, CRenderPass()));
00109 ite=_RenderPass.find (renderPass);
00110 ite->second.init (renderPass*NL3D_COARSEMESH_VERTEXBUFFER_GRANULARITY);
00111 }
00112
00113
00114 uint32 id=ite->second.addMesh (geom);
00115 if (id==CRenderPass::CantAddMesh)
00116 return CantAddCoarseMesh;
00117 else
00118
00119 return buildId (renderPass, id);
00120 }
00121
00122
00123
00124 void CCoarseMeshManager::removeMesh (uint64 id)
00125 {
00126 H_AUTO_USE( NL3D_StaticLod_AddDelMesh );
00127
00128
00129 uint32 renderPass = getRenderPassId (id);
00130
00131
00132 TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00133
00134
00135 nlassert ( ite!=_RenderPass.end() );
00136
00137
00138 ite->second.removeMesh (getRenderPassMeshId (id));
00139 }
00140
00141
00142
00143 void CCoarseMeshManager::setMatrixMesh (uint64 id, const CMeshGeom& geom, const CMatrix& matrix)
00144 {
00145 H_AUTO_USE( NL3D_StaticLod_UpdateMesh );
00146
00147
00148 uint32 renderPass = getRenderPassId (id);
00149
00150
00151 TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00152
00153
00154 nlassert ( ite!=_RenderPass.end() );
00155
00156
00157 ite->second.setMatrixMesh (getRenderPassMeshId (id), geom, matrix);
00158 }
00159
00160
00161
00162 void CCoarseMeshManager::setColorMesh (uint64 id, const CMeshGeom& geom, NLMISC::CRGBA color)
00163 {
00164 H_AUTO_USE( NL3D_StaticLod_UpdateMesh );
00165
00166
00167 uint32 renderPass = getRenderPassId (id);
00168
00169
00170 TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00171
00172
00173 nlassert ( ite!=_RenderPass.end() );
00174
00175
00176 ite->second.setColorMesh (getRenderPassMeshId (id), geom.getVertexBuffer().getNumVertices(), color);
00177 }
00178
00179
00180
00181 void CCoarseMeshManager::render (IDriver *drv)
00182 {
00183 H_AUTO( NL3D_StaticLod_Render );
00184
00185
00186 drv->setupModelMatrix (CMatrix::Identity);
00187
00188
00189 TRenderingPassMap::iterator ite=_RenderPass.begin ();
00190 while (ite!=_RenderPass.end())
00191 {
00192
00193 ite->second.render (drv, _Material);
00194
00195
00196 ite++;
00197 }
00198 }
00199
00200
00201
00202 void CCoarseMeshManager::CRenderPass::init (uint blockSize)
00203 {
00204
00205 VBlockSize = blockSize;
00206
00207
00208 VBuffer.setVertexFormat (NL3D_COARSEMESH_VERTEX_FORMAT_MGR);
00209
00210
00211 VBuffer.reserve (NL3D_COARSEMESH_VERTEXBUFFER_RESERVE*VBlockSize);
00212 }
00213
00214
00215
00216 uint32 CCoarseMeshManager::CRenderPass::addMesh (const CMeshGeom& geom)
00217 {
00218
00219 uint16 vertexBufferId;
00220 std::list< uint16 >::iterator iteBegin=FreeVBlock.begin();
00221 if (iteBegin != FreeVBlock.end())
00222 {
00223
00224 vertexBufferId=*iteBegin;
00225 FreeVBlock.erase (iteBegin);
00226 }
00227 else
00228 {
00229
00230 uint vertexCount=VBuffer.getNumVertices ();
00231
00232
00233 if (VBuffer.capacity () == vertexCount)
00234 {
00235
00236 VBuffer.reserve (vertexCount*2);
00237 }
00238
00239
00240
00241
00242 VBuffer.setNumVertices (vertexCount+VBlockSize);
00243
00244
00245 vertexBufferId = vertexCount / VBlockSize;
00246 }
00247
00248
00249
00250
00251 const CVertexBuffer &vbSrc=geom.getVertexBuffer();
00252
00253
00254 nlassert (vbSrc.getVertexFormat() & (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag) );
00255
00256
00257 uint32 nbVSrc = vbSrc.getNumVertices();
00258 nlassert (nbVSrc<=VBlockSize);
00259
00260
00261 uint firstVertex=vertexBufferId*VBlockSize;
00262
00263
00264 const void *vSrc = vbSrc.getVertexCoordPointer (0);
00265 void *vDest = VBuffer.getVertexCoordPointer (firstVertex);
00266
00267
00268 for(uint i=0; i<nbVSrc;i++)
00269 {
00270 CVector &dstPos= *(CVector*)vDest;
00271 CUV &dstUV= *(CUV*) ((uint8*)vDest + VBuffer.getTexCoordOff() );
00272 CRGBA &dstRGBA= *(CRGBA*) ((uint8*)vDest + VBuffer.getColorOff() );
00273 CVector &srcPos= *(CVector*)vSrc;
00274 CUV &srcUV= *(CUV*) ((uint8*)vSrc + VBuffer.getTexCoordOff() );
00275
00276
00277 dstPos= srcPos;
00278 dstUV= srcUV;
00279
00280 dstRGBA= CRGBA::White;
00281
00282
00283 vSrc= (uint8*)vSrc + vbSrc.getVertexSize();
00284 vDest= (uint8*)vDest + VBuffer.getVertexSize();
00285 }
00286
00287
00288
00289
00290 uint triCount=getTriCount (geom);
00291
00292
00293 bool added=false;
00294 uint16 primitiveBlockId=0;
00295 std::list< CPrimitiveBlockInfo >::iterator ite=PrimitiveBlockInfoList.begin();
00296 while (ite!=PrimitiveBlockInfoList.end())
00297 {
00298
00299 if ( (ite->addMesh (vertexBufferId, geom, firstVertex, triCount)) != CPrimitiveBlockInfo::Failed )
00300 {
00301 added=true;
00302 break;
00303 }
00304
00305
00306 ite++;
00307 primitiveBlockId++;
00308 }
00309
00310
00311 if (ite==PrimitiveBlockInfoList.end())
00312 {
00313
00314 PrimitiveBlockInfoList.push_back (CPrimitiveBlockInfo());
00315 ite=PrimitiveBlockInfoList.end();
00316 ite--;
00317
00318
00319 ite->init (NL3D_COARSEMESH_PRIMITIVE_BLOCK_SIZE);
00320
00321
00322 if (ite->addMesh (vertexBufferId, geom, firstVertex, triCount)!=CPrimitiveBlockInfo::Failed)
00323 added=true;
00324 }
00325
00326
00327 if (!added)
00328
00329 return CantAddMesh;
00330
00331
00332 return buildId (primitiveBlockId, vertexBufferId);
00333 }
00334
00335
00336
00337 uint CCoarseMeshManager::CRenderPass::getTriCount (const CMeshGeom& geom)
00338 {
00339
00340 uint count = 0;
00341
00342
00343 uint numMatrixBlock=geom.getNbMatrixBlock();
00344 uint matrixBlock;
00345 for (matrixBlock=0; matrixBlock<numMatrixBlock; matrixBlock++)
00346 {
00347
00348 uint numRenderPass=geom.getNbRdrPass (matrixBlock);
00349 uint renderPass;
00350 for (renderPass=0; renderPass<numRenderPass; renderPass++)
00351 {
00352
00353 const CPrimitiveBlock &pBlock=geom.getRdrPassPrimitiveBlock (matrixBlock, renderPass);
00354
00355
00356 uint renderPassNumTri=pBlock.getNumTri ();
00357 count+=renderPassNumTri;
00358 }
00359 }
00360
00361
00362 return count;
00363 }
00364
00365
00366
00367 void CCoarseMeshManager::CRenderPass::removeMesh (uint32 id)
00368 {
00369
00370 uint16 primitiveBlockId=getPrimitiveblockId (id);
00371 uint16 vertexBufferId=getVertexBufferId (id);
00372
00373
00374 FreeVBlock.push_back (vertexBufferId);
00375
00376
00377
00378
00379 std::list< CPrimitiveBlockInfo >::iterator ite=PrimitiveBlockInfoList.begin();
00380 for (uint i=0; i<primitiveBlockId; i++)
00381 ite++;
00382
00383
00384 nlassert (ite!=PrimitiveBlockInfoList.end());
00385
00386
00387 ite->removeMesh (vertexBufferId);
00388 }
00389
00390
00391
00392 void CCoarseMeshManager::CRenderPass::setMatrixMesh (uint32 id, const CMeshGeom& geom, const CMatrix& matrix)
00393 {
00394
00395 uint16 vertexBufferId=getVertexBufferId (id);
00396
00397
00398
00399
00400 const CVertexBuffer &vbSrc=geom.getVertexBuffer();
00401
00402
00403 nlassert (vbSrc.getVertexFormat() & (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag) );
00404
00405
00406 uint32 nbVSrc = vbSrc.getNumVertices();
00407 nlassert (nbVSrc<=VBlockSize);
00408
00409
00410
00411 uint vtSrcSize=vbSrc.getVertexSize ();
00412 uint vtDstSize=VBuffer.getVertexSize ();
00413
00414
00415 const uint8 *vSrc = (const uint8 *)vbSrc.getVertexCoordPointer (0);
00416 uint8 *vDest = (uint8 *)VBuffer.getVertexCoordPointer (vertexBufferId*VBlockSize);
00417
00418
00419 for (uint i=0; i<nbVSrc; i++)
00420 {
00421
00422 *(CVector*)vDest = matrix.mulPoint (*(const CVector*)vSrc);
00423
00424
00425
00426
00427
00428 vSrc+=vtSrcSize;
00429 vDest+=vtDstSize;
00430 }
00431 }
00432
00433
00434
00435 void CCoarseMeshManager::CRenderPass::setColorMesh (uint32 id, uint nVertices, CRGBA color)
00436 {
00437
00438 uint16 vertexBufferId=getVertexBufferId (id);
00439
00440
00441
00442
00443 uint32 nbVSrc = nVertices;
00444 nlassert (nbVSrc<=VBlockSize);
00445
00446
00447 uint vtDstSize=VBuffer.getVertexSize ();
00448
00449
00450 uint8 *vDest = (uint8 *)VBuffer.getVertexCoordPointer (vertexBufferId*VBlockSize);
00451 vDest+= VBuffer.getColorOff();
00452
00453
00454 for (uint i=0; i<nbVSrc; i++)
00455 {
00456
00457 *(CRGBA*)vDest = color;
00458
00459
00460 vDest+=vtDstSize;
00461 }
00462 }
00463
00464
00465
00466 void CCoarseMeshManager::CRenderPass::render (IDriver *drv, CMaterial& mat)
00467 {
00468
00469 drv->activeVertexBuffer (VBuffer);
00470
00471
00472 std::list< CPrimitiveBlockInfo >::iterator ite=PrimitiveBlockInfoList.begin();
00473 while (ite!=PrimitiveBlockInfoList.end())
00474 {
00475
00476 drv->render (ite->PrimitiveBlock, mat);
00477
00478
00479 ite++;
00480 }
00481 }
00482
00483
00484
00485 uint CCoarseMeshManager::CRenderPass::CPrimitiveBlockInfo::addMesh (uint16 vertexBufferId, const CMeshGeom& geom, uint32 firstVertexIndex, uint triCount)
00486 {
00487
00488 uint oldNumTri=PrimitiveBlock.getNumTri();
00489
00490
00491 if ( triCount <= (PrimitiveBlock.capacityTri()-oldNumTri) )
00492 {
00493 #ifdef NL_DEBUG
00494
00495 uint checkCount = 0;
00496 #endif // NL_DEBUG
00497
00498
00499 PrimitiveBlock.setNumTri (oldNumTri+triCount);
00500
00501
00502 uint32 *pTriDest=PrimitiveBlock.getTriPointer ()+3*oldNumTri;
00503
00504
00505 uint firstIndex=firstVertexIndex;
00506
00507
00508 uint numMatrixBlock=geom.getNbMatrixBlock();
00509 uint matrixBlock;
00510 for (matrixBlock=0; matrixBlock<numMatrixBlock; matrixBlock++)
00511 {
00512
00513 uint numRenderPass=geom.getNbRdrPass (matrixBlock);
00514 uint renderPass;
00515 for (renderPass=0; renderPass<numRenderPass; renderPass++)
00516 {
00517
00518 const CPrimitiveBlock &pBlock=geom.getRdrPassPrimitiveBlock (matrixBlock, renderPass);
00519
00520
00521 uint renderPassNumIndex=3*pBlock.getNumTri ();
00522 #ifdef NL_DEBUG
00523 checkCount+=pBlock.getNumTri ();
00524 #endif // NL_DEBUG
00525
00526
00527 const uint32 *pTriSrc=pBlock.getTriPointer ();
00528
00529
00530 for (uint index=0; index<renderPassNumIndex; index++)
00531 {
00532
00533 *pTriDest=pTriSrc[index]+firstIndex;
00534 pTriDest++;
00535 }
00536 }
00537 }
00538
00539 #ifdef NL_DEBUG
00540
00541 nlassert (checkCount==triCount);
00542 #endif // NL_DEBUG
00543
00544
00545 MeshIdList.push_back (CMeshInfo (oldNumTri, triCount, vertexBufferId));
00546
00547 return Success;
00548 }
00549 else
00550 return Failed;
00551 }
00552
00553
00554
00555 void CCoarseMeshManager::CRenderPass::CPrimitiveBlockInfo::removeMesh (uint16 vertexBufferId)
00556 {
00557
00558 std::list< CMeshInfo >::iterator ite=MeshIdList.begin();
00559 while (ite!=MeshIdList.end())
00560 {
00561
00562 if (ite->VertexBufferId == vertexBufferId)
00563 {
00564
00565 uint numIndexLeft=(PrimitiveBlock.getNumTri()-(ite->Offset+ite->Length))*3;
00566
00567
00568 const uint32 *pTriSrc=PrimitiveBlock.getTriPointer ()+3*(ite->Offset+ite->Length);
00569
00570
00571 uint32 *pTriDest=PrimitiveBlock.getTriPointer ()+3*ite->Offset;
00572
00573
00574 for (uint index=0; index<numIndexLeft; index++)
00575 {
00576 pTriDest[index]=pTriSrc[index];
00577 }
00578
00579
00580 PrimitiveBlock.setNumTri (PrimitiveBlock.getNumTri()-ite->Length);
00581
00582
00583 std::list< CMeshInfo >::iterator iteOther=ite;
00584
00585
00586 while (iteOther!=MeshIdList.end())
00587 {
00588
00589 iteOther->Offset-=ite->Length;
00590
00591
00592 iteOther++;
00593 }
00594
00595
00596 MeshIdList.erase (ite);
00597
00598
00599 return;
00600 }
00601
00602
00603 ite++;
00604 }
00605
00606
00607 nlassert (ite!=MeshIdList.end());
00608 }
00609
00610
00611
00612 void CCoarseMeshManager::CRenderPass::CPrimitiveBlockInfo::init (uint size)
00613 {
00614
00615 PrimitiveBlock.reserveTri (size);
00616 }
00617
00618
00619
00620 bool CCoarseMeshClipObs::clip(IBaseClipObs *caller)
00621 {
00622 return false;
00623 }
00624
00625
00626
00627 }