# 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  

coarse_mesh_manager.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 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/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         // Set as opaque
00056         setTransparency (false);
00057         setOpacity (true);
00058 
00059         // ** Init texture
00060 
00061         _Texture=new CTextureFile ();
00062 
00063         // ** Init material
00064 
00065         // Double sided
00066         _Material.initUnlit ();
00067         _Material.setDoubleSided (true);
00068         _Material.setAlphaTest (true);
00069         _Material.setColor (CRGBA (255, 255, 255));
00070         // Init blend Factors, for possible Alpha transition
00071         _Material.setSrcBlend(CMaterial::srcalpha);
00072         _Material.setDstBlend(CMaterial::invsrcalpha);
00073 
00074         // Texture
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         // Get vertex buffer ref
00092         const CVertexBuffer &vertexBuffer=geom.getVertexBuffer();
00093 
00094         // *** Find the good render pass
00095 
00096         // Normalized number of vertex
00097         uint32 renderPass = vertexBuffer.getNumVertices () / NL3D_COARSEMESH_VERTEXBUFFER_GRANULARITY;
00098         if (NL3D_COARSEMESH_VERTEXBUFFER_GRANULARITY_MASK&vertexBuffer.getNumVertices ())
00099                 renderPass++;
00100 
00101         // Look for the good rendering pass
00102         TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00103 
00104         // Not found ?
00105         if ( ite==_RenderPass.end() )
00106         {
00107                 // Add the rendering pass
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         // Ok, add the mesh
00114         uint32 id=ite->second.addMesh (geom);
00115         if (id==CRenderPass::CantAddMesh)
00116                 return CantAddCoarseMesh;
00117         else
00118                 // Return an id
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         // Get the render pass id
00129         uint32 renderPass = getRenderPassId (id);
00130 
00131         // Find the render pass
00132         TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00133 
00134         // Not found ?
00135         nlassert ( ite!=_RenderPass.end() );
00136 
00137         // remove it
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         // Get the render pass id
00148         uint32 renderPass = getRenderPassId (id);
00149 
00150         // Find the render pass
00151         TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00152 
00153         // Not found ?
00154         nlassert ( ite!=_RenderPass.end() );
00155 
00156         // remove it
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         // Get the render pass id
00167         uint32 renderPass = getRenderPassId (id);
00168 
00169         // Find the render pass
00170         TRenderingPassMap::iterator ite=_RenderPass.find (renderPass);
00171 
00172         // Not found ?
00173         nlassert ( ite!=_RenderPass.end() );
00174 
00175         // remove it
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         // Set Ident matrix
00186         drv->setupModelMatrix (CMatrix::Identity);
00187 
00188         // Render each render pass
00189         TRenderingPassMap::iterator ite=_RenderPass.begin ();
00190         while (ite!=_RenderPass.end())
00191         {
00192                 // Render the rendering pass
00193                 ite->second.render (drv, _Material);
00194 
00195                 // Next render pass
00196                 ite++;
00197         }
00198 }
00199 
00200 // ***************************************************************************
00201 
00202 void CCoarseMeshManager::CRenderPass::init (uint blockSize)
00203 {
00204         // Block size
00205         VBlockSize = blockSize;
00206 
00207         // Set vertex type
00208         VBuffer.setVertexFormat (NL3D_COARSEMESH_VERTEX_FORMAT_MGR);
00209 
00210         // Reserve the vertex buffer
00211         VBuffer.reserve (NL3D_COARSEMESH_VERTEXBUFFER_RESERVE*VBlockSize);
00212 }
00213 
00214 // ***************************************************************************
00215 
00216 uint32 CCoarseMeshManager::CRenderPass::addMesh (const CMeshGeom& geom)
00217 {
00218         // Is there a free vertex buffer ?
00219         uint16 vertexBufferId;
00220         std::list< uint16 >::iterator iteBegin=FreeVBlock.begin();
00221         if (iteBegin != FreeVBlock.end())
00222         {
00223                 // Get a free id
00224                 vertexBufferId=*iteBegin;
00225                 FreeVBlock.erase (iteBegin);
00226         }
00227         else
00228         {
00229                 // Number of vertex in the vertex buffer
00230                 uint vertexCount=VBuffer.getNumVertices ();
00231 
00232                 // Is the vertex buffer filled ?
00233                 if (VBuffer.capacity () == vertexCount)
00234                 {
00235                         // Double it's capacity
00236                         VBuffer.reserve (vertexCount*2);
00237                 }
00238 
00239                 // *** Make a new block
00240 
00241                 // Resize the vertex buffer
00242                 VBuffer.setNumVertices (vertexCount+VBlockSize);
00243 
00244                 // Set mesh id
00245                 vertexBufferId = vertexCount / VBlockSize;
00246         }
00247 
00248         // *** Copy the vertices
00249 
00250         // Src vertex buffer
00251         const CVertexBuffer &vbSrc=geom.getVertexBuffer();
00252 
00253         // Check the vertex format
00254         nlassert (vbSrc.getVertexFormat() & (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag) );
00255 
00256         // Number of source vertex
00257         uint32 nbVSrc = vbSrc.getNumVertices();
00258         nlassert (nbVSrc<=VBlockSize);
00259 
00260         // First vertex index
00261         uint firstVertex=vertexBufferId*VBlockSize;
00262 
00263         // Copy vector
00264         const void *vSrc = vbSrc.getVertexCoordPointer (0);
00265         void *vDest = VBuffer.getVertexCoordPointer (firstVertex);
00266         
00267         // Copy it
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                 // copy color/uv
00277                 dstPos= srcPos;
00278                 dstUV= srcUV;
00279                 // init color to full white
00280                 dstRGBA= CRGBA::White;
00281 
00282                 // next
00283                 vSrc= (uint8*)vSrc + vbSrc.getVertexSize();
00284                 vDest= (uint8*)vDest + VBuffer.getVertexSize();
00285         }
00286 
00287         // *** Setup primitives indexes
00288 
00289         // Get number of tri in this geom
00290         uint triCount=getTriCount (geom);
00291 
00292         // Try to add the primitive in a primitive blocks
00293         bool added=false;
00294         uint16 primitiveBlockId=0;
00295         std::list< CPrimitiveBlockInfo >::iterator ite=PrimitiveBlockInfoList.begin();
00296         while (ite!=PrimitiveBlockInfoList.end())
00297         {
00298                 // Add it
00299                 if ( (ite->addMesh (vertexBufferId, geom, firstVertex, triCount)) != CPrimitiveBlockInfo::Failed )
00300                 {
00301                         added=true;
00302                         break;
00303                 }
00304 
00305                 // Next primitive block
00306                 ite++;
00307                 primitiveBlockId++;
00308         }
00309 
00310         // Can't be added ?
00311         if (ite==PrimitiveBlockInfoList.end())
00312         {
00313                 // Add a primitive block
00314                 PrimitiveBlockInfoList.push_back (CPrimitiveBlockInfo());
00315                 ite=PrimitiveBlockInfoList.end();
00316                 ite--;
00317 
00318                 // Resize it
00319                 ite->init (NL3D_COARSEMESH_PRIMITIVE_BLOCK_SIZE);
00320 
00321                 // Add the mesh
00322                 if (ite->addMesh (vertexBufferId, geom, firstVertex, triCount)!=CPrimitiveBlockInfo::Failed)
00323                         added=true;
00324         }
00325 
00326         // Can be added ?
00327         if (!added)
00328                 // Return error
00329                 return CantAddMesh;
00330 
00331         // Return an id
00332         return buildId (primitiveBlockId, vertexBufferId);
00333 }
00334 
00335 // ***************************************************************************
00336 
00337 uint CCoarseMeshManager::CRenderPass::getTriCount (const CMeshGeom& geom)
00338 {
00339         // Check count
00340         uint count = 0;
00341 
00342         // Count number of triangles
00343         uint numMatrixBlock=geom.getNbMatrixBlock();
00344         uint matrixBlock;
00345         for (matrixBlock=0; matrixBlock<numMatrixBlock; matrixBlock++)
00346         {
00347                 // One render pass
00348                 uint numRenderPass=geom.getNbRdrPass (matrixBlock);
00349                 uint renderPass;
00350                 for (renderPass=0; renderPass<numRenderPass; renderPass++)
00351                 {
00352                         // Get the render pass
00353                         const CPrimitiveBlock &pBlock=geom.getRdrPassPrimitiveBlock (matrixBlock, renderPass);
00354 
00355                         // Check there is enought room to insert this primitives
00356                         uint renderPassNumTri=pBlock.getNumTri ();
00357                         count+=renderPassNumTri;
00358                 }
00359         }
00360 
00361         // Return count
00362         return count;
00363 }
00364 
00365 // ***************************************************************************
00366 
00367 void CCoarseMeshManager::CRenderPass::removeMesh (uint32 id)
00368 {
00369         // Get ids
00370         uint16 primitiveBlockId=getPrimitiveblockId (id);
00371         uint16 vertexBufferId=getVertexBufferId (id);
00372 
00373         // *** Free the vertex buffer
00374         FreeVBlock.push_back (vertexBufferId);
00375 
00376         // *** Remove the primitive block
00377 
00378         // Find the primitive block
00379         std::list< CPrimitiveBlockInfo >::iterator ite=PrimitiveBlockInfoList.begin();
00380         for (uint i=0; i<primitiveBlockId; i++)
00381                 ite++;
00382 
00383         // Some checks
00384         nlassert (ite!=PrimitiveBlockInfoList.end());
00385 
00386         // Remove from there
00387         ite->removeMesh (vertexBufferId);
00388 }
00389 
00390 // ***************************************************************************
00391 
00392 void CCoarseMeshManager::CRenderPass::setMatrixMesh (uint32 id, const CMeshGeom& geom, const CMatrix& matrix)
00393 {
00394         // Is there a free vertex buffer ?
00395         uint16 vertexBufferId=getVertexBufferId (id);
00396 
00397         // *** Transform the vertices
00398 
00399         // Src vertex buffer
00400         const CVertexBuffer &vbSrc=geom.getVertexBuffer();
00401 
00402         // Check the vertex format
00403         nlassert (vbSrc.getVertexFormat() & (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag) );
00404 
00405         // Number of source vertices
00406         uint32 nbVSrc = vbSrc.getNumVertices();
00407         nlassert (nbVSrc<=VBlockSize);
00408         //int normalOffset = vbSrc.getNormalOff();
00409 
00410         // Vertex size
00411         uint vtSrcSize=vbSrc.getVertexSize ();
00412         uint vtDstSize=VBuffer.getVertexSize ();
00413 
00414         // Copy vector
00415         const uint8 *vSrc = (const uint8 *)vbSrc.getVertexCoordPointer (0);
00416         uint8 *vDest = (uint8 *)VBuffer.getVertexCoordPointer (vertexBufferId*VBlockSize);
00417         
00418         // Transform it
00419         for (uint i=0; i<nbVSrc; i++)
00420         {
00421                 // Transform position
00422                 *(CVector*)vDest = matrix.mulPoint (*(const CVector*)vSrc);
00423 
00424                 // Transform normal
00425 //              *(CVector*)(vDest+normalOffset) = matrix.mulVector (*(const CVector*)(vSrc+normalOffset));
00426 
00427                 // Next point
00428                 vSrc+=vtSrcSize;
00429                 vDest+=vtDstSize;
00430         }
00431 }
00432 
00433 // ***************************************************************************
00434 
00435 void CCoarseMeshManager::CRenderPass::setColorMesh (uint32 id, uint nVertices, CRGBA color)
00436 {
00437         // Is there a free vertex buffer ?
00438         uint16 vertexBufferId=getVertexBufferId (id);
00439 
00440         // *** Copy color to vertices
00441 
00442         // Number of source vertices
00443         uint32 nbVSrc = nVertices;
00444         nlassert (nbVSrc<=VBlockSize);
00445 
00446         // Vertex size
00447         uint vtDstSize=VBuffer.getVertexSize ();
00448 
00449         // Copy vector
00450         uint8 *vDest = (uint8 *)VBuffer.getVertexCoordPointer (vertexBufferId*VBlockSize);
00451         vDest+= VBuffer.getColorOff();
00452         
00453         // Transform it
00454         for (uint i=0; i<nbVSrc; i++)
00455         {
00456                 // Transform position
00457                 *(CRGBA*)vDest = color;
00458 
00459                 // Next point
00460                 vDest+=vtDstSize;
00461         }
00462 }
00463 
00464 // ***************************************************************************
00465 
00466 void CCoarseMeshManager::CRenderPass::render (IDriver *drv, CMaterial& mat)
00467 {
00468         // Active the vertex buffer
00469         drv->activeVertexBuffer (VBuffer);
00470 
00471         // For each primitive block
00472         std::list< CPrimitiveBlockInfo >::iterator ite=PrimitiveBlockInfoList.begin();
00473         while (ite!=PrimitiveBlockInfoList.end())
00474         {
00475                 // Render it
00476                 drv->render (ite->PrimitiveBlock, mat);
00477 
00478                 // Next primitive block
00479                 ite++;
00480         }
00481 }
00482 
00483 // ***************************************************************************
00484 
00485 uint CCoarseMeshManager::CRenderPass::CPrimitiveBlockInfo::addMesh (uint16 vertexBufferId, const CMeshGeom& geom, uint32 firstVertexIndex, uint triCount)
00486 {
00487         // Get num tri in the primitive block
00488         uint oldNumTri=PrimitiveBlock.getNumTri();
00489 
00490         // Check capacity
00491         if ( triCount <= (PrimitiveBlock.capacityTri()-oldNumTri) )
00492         {
00493 #ifdef NL_DEBUG
00494                 // Check count
00495                 uint checkCount = 0;
00496 #endif // NL_DEBUG
00497 
00498                 // Resize pblock
00499                 PrimitiveBlock.setNumTri (oldNumTri+triCount);
00500 
00501                 // Destination pointer 
00502                 uint32 *pTriDest=PrimitiveBlock.getTriPointer ()+3*oldNumTri;
00503 
00504                 // First index for the object
00505                 uint firstIndex=firstVertexIndex;
00506 
00507                 // Count number of triangles
00508                 uint numMatrixBlock=geom.getNbMatrixBlock();
00509                 uint matrixBlock;
00510                 for (matrixBlock=0; matrixBlock<numMatrixBlock; matrixBlock++)
00511                 {
00512                         // One render pass
00513                         uint numRenderPass=geom.getNbRdrPass (matrixBlock);
00514                         uint renderPass;
00515                         for (renderPass=0; renderPass<numRenderPass; renderPass++)
00516                         {
00517                                 // Get the render pass
00518                                 const CPrimitiveBlock &pBlock=geom.getRdrPassPrimitiveBlock (matrixBlock, renderPass);
00519 
00520                                 // Check there is enought room to insert this primitives
00521                                 uint renderPassNumIndex=3*pBlock.getNumTri ();
00522 #ifdef NL_DEBUG
00523                                 checkCount+=pBlock.getNumTri ();
00524 #endif // NL_DEBUG
00525 
00526                                 // Tri pointer
00527                                 const uint32 *pTriSrc=pBlock.getTriPointer ();
00528 
00529                                 // Insert and remap indexes
00530                                 for (uint index=0; index<renderPassNumIndex; index++)
00531                                 {
00532                                         // Copy and remap the vertex indexes
00533                                         *pTriDest=pTriSrc[index]+firstIndex;
00534                                         pTriDest++;
00535                                 }
00536                         }
00537                 }
00538 
00539 #ifdef NL_DEBUG
00540                 // Checks
00541                 nlassert (checkCount==triCount);
00542 #endif // NL_DEBUG
00543 
00544                 // Add a mesh info in the list
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         // Get mesh info
00558         std::list< CMeshInfo >::iterator ite=MeshIdList.begin();
00559         while (ite!=MeshIdList.end())
00560         {
00561                 // Good geom ?
00562                 if (ite->VertexBufferId == vertexBufferId)
00563                 {
00564                         // Remove indexes of this primitive
00565                         uint numIndexLeft=(PrimitiveBlock.getNumTri()-(ite->Offset+ite->Length))*3;
00566 
00567                         // Source triangles
00568                         const uint32 *pTriSrc=PrimitiveBlock.getTriPointer ()+3*(ite->Offset+ite->Length);
00569 
00570                         // Destination triangles
00571                         uint32 *pTriDest=PrimitiveBlock.getTriPointer ()+3*ite->Offset;
00572 
00573                         // Copy indexes
00574                         for (uint index=0; index<numIndexLeft; index++)
00575                         {
00576                                 pTriDest[index]=pTriSrc[index];
00577                         }
00578 
00579                         // Resize primitive block
00580                         PrimitiveBlock.setNumTri (PrimitiveBlock.getNumTri()-ite->Length);
00581 
00582                         // Backup iterator
00583                         std::list< CMeshInfo >::iterator iteOther=ite;
00584 
00585                         // Patch offset for each others meshes in the primitive block
00586                         while (iteOther!=MeshIdList.end())
00587                         {
00588                                 // Remap offset
00589                                 iteOther->Offset-=ite->Length;
00590 
00591                                 // Next mesh
00592                                 iteOther++;
00593                         }
00594 
00595                         // Remove info from list
00596                         MeshIdList.erase (ite);
00597 
00598                         // Exit
00599                         return;
00600                 }
00601 
00602                 // Next 
00603                 ite++;
00604         }
00605 
00606         // Check it has been found
00607         nlassert (ite!=MeshIdList.end());
00608 }
00609 
00610 // ***************************************************************************
00611 
00612 void CCoarseMeshManager::CRenderPass::CPrimitiveBlockInfo::init (uint size)
00613 {
00614         // Reserve triangles
00615         PrimitiveBlock.reserveTri (size);
00616 }
00617 
00618 // ***************************************************************************
00619 
00620 bool    CCoarseMeshClipObs::clip(IBaseClipObs *caller)
00621 {
00622         return false;
00623 }
00624 
00625 // ***************************************************************************
00626 
00627 } // NL3D