// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "std3d.h" #include "nel/3d/coarse_mesh_manager.h" #include "nel/3d/mesh.h" #include "nel/3d/texture_file.h" #include "nel/misc/hierarchical_timer.h" #include "nel/3d/clip_trav.h" #include "nel/misc/fast_mem.h" using namespace NLMISC; namespace NL3D { H_AUTO_DECL( NL3D_StaticLod_AddMesh ) // *************************************************************************** CCoarseMeshManager::CCoarseMeshManager() { // ** Init texture _Texture=new CTextureFile (); _TextureCategory= new ITexture::CTextureCategory("COARSE MESH MANAGER"); _Texture->setTextureCategory(_TextureCategory); // ** Init material // Double sided _Material.initUnlit (); _Material.setDoubleSided (true); _Material.setAlphaTest (true); _Material.setColor (CRGBA (255, 255, 255)); // Init blend Factors, for possible Alpha transition _Material.setSrcBlend(CMaterial::srcalpha); _Material.setDstBlend(CMaterial::invsrcalpha); // Texture _Material.setTexture (0, _Texture); // ** Init Geometry _VBuffer.setVertexFormat(NL3D_COARSEMESH_VERTEX_FORMAT_MGR); _VBuffer.setNumVertices(NL3D_COARSEMESH_VERTEXBUFFER_SIZE); _VBuffer.setName("CCoarseMeshManager"); _VBuffer.setPreferredMemory(CVertexBuffer::AGPVolatile, false); _Triangles.setFormat(NL_COARSE_MESH_INDEX_FORMAT); _Triangles.setNumIndexes(NL3D_COARSEMESH_TRIANGLE_SIZE*3); _Triangles.setPreferredMemory(CIndexBuffer::RAMVolatile, false); // TODO : see if agp index is better _CurrentNumVertices= 0; _CurrentNumTriangles= 0; NL_SET_IB_NAME(_Triangles, "CCoarseMeshManager"); } // *************************************************************************** void CCoarseMeshManager::setTextureFile (const char* file) { _Texture->setFileName (file); } // *************************************************************************** bool CCoarseMeshManager::addMesh (uint numVertices, const uint8 *vBuffer, uint numTris, const TCoarseMeshIndexType *indexBuffer) { H_AUTO_USE( NL3D_StaticLod_AddMesh ); // if 0 mesh, quit if(numTris==0 || numVertices==0) return true; // check vertex size if(_CurrentNumVertices + numVertices > NL3D_COARSEMESH_VERTEXBUFFER_SIZE) return false; // check tri size if(_CurrentNumTriangles + numTris> NL3D_COARSEMESH_TRIANGLE_SIZE) return false; CMeshInfo mi; mi.NumVertices = numVertices; mi.VBuffer = vBuffer; mi.NumTris = numTris; mi.IndexBuffer = indexBuffer; _Meshs.push_back(mi); _CurrentNumVertices+= numVertices; _CurrentNumTriangles+= numTris; return true; } // *************************************************************************** void CCoarseMeshManager::flushRender (IDriver *drv) { H_AUTO( NL3D_StaticLod_Render ); if (_Meshs.empty()) return; // if the driver is BGRA (Direct3D), then invert color format if(!_VBuffer.isResident() && drv->getVertexColorFormat()==CVertexBuffer::TBGRA) { // since actually empty, no need to swap current memory _VBuffer.setNumVertices(0); _VBuffer.setVertexColorFormat(CVertexBuffer::TBGRA); } // init _VBuffer.setNumVertices(_CurrentNumVertices); _Triangles.setNumIndexes(_CurrentNumTriangles * 3); _VBuffer.lock (_VBA); _Triangles.lock(_IBA); uint currentNumVertices = 0; uint currentNumTriangles = 0; for(std::vector::iterator it = _Meshs.begin(); it != _Meshs.end(); ++it) { // Copy Vertices to VBuffer uint baseVertex= currentNumVertices; CHECK_VBA_RANGE(_VBA, _VBA.getVertexCoordPointer(baseVertex), it->NumVertices*_VBuffer.getVertexSize()); CFastMem::memcpy(_VBA.getVertexCoordPointer(baseVertex), it->VBuffer, it->NumVertices*_VBuffer.getVertexSize()); // next currentNumVertices+= it->NumVertices; // Copy tris to triangles, adding baseVertex to index TCoarseMeshIndexType *triDst= (TCoarseMeshIndexType *) _IBA.getPtr()+currentNumTriangles*3; const TCoarseMeshIndexType *triSrc= it->IndexBuffer; uint numIdx= it->NumTris*3; // NB: for the majority of CoarseMesh (4 faces==48 bytes of indices), not interressant to use CFastMem::precache() for(;numIdx>0;numIdx--, triSrc++, triDst++) { CHECK_IBA(_IBA, triDst) *triDst= *triSrc + baseVertex; } // next currentNumTriangles+= it->NumTris; } _VBA.unlock(); _IBA.unlock(); // If not empty, render if(_CurrentNumVertices && _CurrentNumTriangles) { // Set Ident matrix drv->setupModelMatrix (CMatrix::Identity); // Set VB drv->activeVertexBuffer(_VBuffer); drv->activeIndexBuffer(_Triangles); // render drv->renderTriangles(_Material, 0, _CurrentNumTriangles); } // reset _CurrentNumVertices= 0; _CurrentNumTriangles= 0; _Meshs.clear(); } } // NL3D