#include <coarse_mesh_build.h>
The build method take an array of CMeshGeom an a bitmap. This class will compute a single texture used to map every coarse mesh passed in the array.
Each mesh geom should be a coarse mesh.
The uv texture coodinates of those coarse meshes will be adjusted to fit in a single texture.
Nevrax France
Definition at line 62 of file coarse_mesh_build.h.
Public Member Functions | |
bool | build (const std::vector< CCoarseMeshDesc > &coarseMeshes, std::vector< NLMISC::CBitmap > &bitmaps, CStats &stats, float mulArea) |
Private Types | |
typedef std::map< std::string, CBitmapDesc > | MapBitmapDesc |
Private Member Functions | |
bool | buildBitmap (const std::vector< CCoarseMeshDesc > &coarseMeshes, std::vector< NLMISC::CBitmap > &bitmaps, CStats &stats, MapBitmapDesc &desc, float mulArea) |
void | expand (NLMISC::CBitmap &bitmap) |
void | remapCoordinates (const std::vector< CCoarseMeshDesc > &coarseMeshes, const MapBitmapDesc &desc, uint outputBitmapCount) |
|
Definition at line 132 of file coarse_mesh_build.h. Referenced by build(), buildBitmap(), and remapCoordinates(). |
|
The build method. This method will build a single texture and adjuste the UV texture coordinates of each mesh geom.
Definition at line 39 of file coarse_mesh_build.cpp. References buildBitmap(), MapBitmapDesc, and remapCoordinates().
00040 { 00041 // 1. build the bitmap 00042 MapBitmapDesc desc; 00043 if (buildBitmap (coarseMeshes, bitmaps, stats, desc, mulArea)==false) 00044 return false; 00045 00046 // 2. remap coordinates 00047 remapCoordinates (coarseMeshes, desc, bitmaps.size ()); 00048 00049 // 3. ok 00050 return true; 00051 } |
|
Definition at line 70 of file coarse_mesh_build.cpp. References NL3D::CCoarseMeshBuild::CBitmapDesc::Bitmaps, NLMISC::CBitmap::convertToType(), expand(), NL3D::CCoarseMeshBuild::CBitmapDesc::FactorU, NL3D::CCoarseMeshBuild::CBitmapDesc::FactorV, NL3D::ITexture::generate(), NLMISC::CBitmap::getHeight(), NL3D::CMeshBase::getMaterial(), NL3D::CMeshGeom::getNbMatrixBlock(), NL3D::CMeshGeom::getNbRdrPass(), NLMISC::getPowerOf2(), NL3D::CMeshGeom::getRdrPassMaterial(), NL3D::ITexture::getShareName(), NL3D::CMaterial::getTexture(), NLMISC::CBitmap::getWidth(), NL3D::CInsertedBitmap::Height, height, MapBitmapDesc, NL3D::CCoarseMeshBuild::CBitmapDesc::Name, nlassert, NLMISC::raiseToNextPowerOf2(), NLMISC::CBitmap::resample(), NL3D::ITexture::selectTexture(), sint, NLMISC::strlwr(), NL3D::ITexture::supportSharing(), NL3D::CCoarseMeshBuild::CStats::TextureUsed, NLMISC::toString(), NL3D::CInsertedBitmap::U, uint, uint32, NL3D::CInsertedBitmap::V, v, NL3D::CInsertedBitmap::Width, and width. Referenced by build().
00071 { 00072 // Total area used by texture 00073 uint totalArea=0; 00074 00075 // *************************************************************************** 00076 00077 // 1. scan each bitmap: calc the area of the bitmap and it its name in the maps sorted by area 00078 typedef std::multimap<uint, CBitmapDesc*> MapAreaBitmap; 00079 MapAreaBitmap mapArea; 00080 uint mesh; 00081 for (mesh=0; mesh<coarseMeshes.size(); mesh++) 00082 { 00083 // Geom mesh pointer 00084 CMeshGeom *meshGeom=coarseMeshes[mesh].MeshGeom; 00085 00086 // Base mesh pointer 00087 const CMeshBase *meshBase=coarseMeshes[mesh].MeshBase; 00088 00089 // For each matrix block 00090 uint matrixBlock; 00091 uint nbMatrixBlock=meshGeom->getNbMatrixBlock(); 00092 for (matrixBlock=0; matrixBlock<nbMatrixBlock; matrixBlock++) 00093 { 00094 // For each render pass 00095 uint renderPass; 00096 uint numRenderPass=meshGeom->getNbRdrPass(matrixBlock); 00097 for (renderPass=0; renderPass<numRenderPass; renderPass++) 00098 { 00099 // Render pass material 00100 uint32 matId=meshGeom->getRdrPassMaterial(matrixBlock, renderPass); 00101 00102 // Checks 00103 nlassert (matId<meshBase->getNbMaterial()); 00104 00105 // Get the material 00106 const CMaterial &material=meshBase->getMaterial(matId); 00107 00108 // Get the texture 00109 ITexture *texture=material.getTexture(0); 00110 if (texture) 00111 { 00112 // For each bitmaps 00113 uint i; 00114 std::string name; 00115 for (i=0; i<bitmaps.size (); i++) 00116 { 00117 // Select the good slot 00118 texture->selectTexture (i); 00119 00120 // Get its name 00121 if (texture->supportSharing()) 00122 { 00123 // Get sharing name 00124 name+=strlwr(texture->getShareName()); 00125 } 00126 else 00127 { 00128 // Build a name 00129 name+=toString ((uint)texture); 00130 } 00131 } 00132 00133 // Already added ? 00134 if (desc.find (name)==desc.end()) 00135 { 00136 // Add it.. 00137 00138 // Insert it in the maps 00139 MapBitmapDesc::iterator ite = desc.insert (MapBitmapDesc::value_type (name, CBitmapDesc ())).first; 00140 00141 // Descriptor for this texture 00142 CBitmapDesc &descBitmap = ite->second; 00143 00144 // Backup original size 00145 uint originalWidth; 00146 uint originalHeight; 00147 00148 // For each bitmaps 00149 uint i; 00150 descBitmap.Bitmaps.resize (bitmaps.size ()); 00151 for (i=0; i<bitmaps.size (); i++) 00152 { 00153 // Select the good slot 00154 texture->selectTexture (i); 00155 00156 // Generate the texture 00157 texture->generate(); 00158 00159 // Convert to RGBA 00160 texture->convertToType (CBitmap::RGBA); 00161 00162 // First texture ? 00163 if (i == 0) 00164 { 00165 // Backup original size 00166 originalWidth = texture->getWidth(); 00167 originalHeight = texture->getHeight(); 00168 } 00169 00170 // Resample, if needed 00171 if (i != 0) 00172 { 00173 // New size 00174 if ( ( originalWidth != texture->getWidth () ) || originalHeight != texture->getHeight () ) 00175 { 00176 texture->resample (originalWidth, originalHeight); 00177 } 00178 } 00179 00180 // Copy the texture 00181 descBitmap.Bitmaps[i] = *texture; 00182 00183 // Expand the texture 00184 expand (descBitmap.Bitmaps[i]); 00185 } 00186 00187 // Texture area 00188 uint area = descBitmap.Bitmaps[0].getWidth() * descBitmap.Bitmaps[0].getHeight(); 00189 descBitmap.Name = name; 00190 descBitmap.FactorU = (float)originalWidth; 00191 descBitmap.FactorV = (float)originalHeight; 00192 00193 // Insert in the map area 00194 mapArea.insert (MapAreaBitmap::value_type(area, &(ite->second))); 00195 00196 // Sum area if added 00197 totalArea+=area; 00198 } 00199 } 00200 } 00201 } 00202 } 00203 00204 // *************************************************************************** 00205 00206 // 2. Calc the best area for the dest texture and resize the bitmap 00207 00208 // Total area used by the textures + a little more 00209 uint newArea=getPowerOf2 (raiseToNextPowerOf2 (totalArea)); 00210 while ((1<<newArea)<(sint)(mulArea*(float)totalArea)) 00211 { 00212 newArea++; 00213 } 00214 00215 // Calc width and height with HEIGHT==WIDTH or HEIGHT=2*WIDTH 00216 uint width=1<<(newArea/2); 00217 uint height=1<<(newArea/2 + (newArea&1)); 00218 00219 // Resize the bitmap and set the pixel format 00220 uint i; 00221 for (i=0; i<bitmaps.size (); i++) 00222 bitmaps[i].resize (width, height, CBitmap::RGBA); 00223 00224 // Checks 00225 if (totalArea==0) 00226 { 00227 // No texture, ok computed. 00228 stats.TextureUsed=1; 00229 00230 return true; 00231 } 00232 00233 // *************************************************************************** 00234 00235 // 3. Place each texture in the bitmap in uncreasing order 00236 typedef std::multimap<sint, CInsertedBitmap> mapInsertedBitmap; 00237 00238 // For each texture 00239 MapAreaBitmap::iterator ite=mapArea.end(); 00240 00241 // Inserted bitmap desc 00242 mapInsertedBitmap inserted; 00243 00244 // Max texture height 00245 uint maxTexHeight=0; 00246 00247 do 00248 { 00249 ite--; 00250 nlassert (ite!=mapArea.end()); 00251 00252 // Size of the texture 00253 uint widthTex=ite->second->Bitmaps[0].getWidth(); 00254 uint heightTex=ite->second->Bitmaps[0].getHeight(); 00255 00256 // Some checks 00257 nlassert (bitmaps.size () == ite->second->Bitmaps.size ()); 00258 00259 // Width and height max 00260 uint widthMax=width-widthTex; 00261 uint heightMax=height-heightTex; 00262 00263 // Test against others.. 00264 bool enter=false; 00265 00266 // For each row and each column 00267 for (uint v=0; v<heightMax; v++) 00268 { 00269 for (uint u=0; u<widthMax; u++) 00270 { 00271 // Test against others.. 00272 enter=true; 00273 00274 // Get the first to test 00275 mapInsertedBitmap::iterator toTest=inserted.lower_bound ((sint)v-(sint)maxTexHeight); 00276 while (toTest!=inserted.end()) 00277 { 00278 // Make a test ? 00279 if ((sint)(v+heightTex)<=(toTest->first)) 00280 { 00281 // Ok, end test 00282 break; 00283 } 00284 00285 // Test it 00286 uint otherU=toTest->second.U; 00287 uint otherV=toTest->second.V; 00288 uint otherWidth=toTest->second.Width; 00289 uint otherHeight=toTest->second.Height; 00290 if ((v<otherV+otherHeight) && (v+heightTex>otherV) && 00291 (u<otherU+otherWidth) && (u+widthTex>otherU)) 00292 { 00293 // Collision 00294 enter=false; 00295 u=toTest->second.U+otherWidth-1; 00296 break; 00297 } 00298 00299 // Next to test 00300 toTest++; 00301 } 00302 00303 // Enter ? 00304 if (enter) 00305 { 00306 // Ok, enter 00307 00308 // Insert an inserted descriptor 00309 CInsertedBitmap descInserted; 00310 descInserted.Width=widthTex; 00311 descInserted.Height=heightTex; 00312 descInserted.U=u; 00313 descInserted.V=v; 00314 inserted.insert (mapInsertedBitmap::value_type (v, descInserted)); 00315 00316 // Max height 00317 if (heightTex>maxTexHeight) 00318 maxTexHeight=heightTex; 00319 00320 // Blit in the texture 00321 uint i; 00322 for (i=0; i<bitmaps.size (); i++) 00323 { 00324 // Check.. 00325 nlassert ( (ite->second->Bitmaps[0].getWidth () == ite->second->Bitmaps[i].getWidth ()) && 00326 (ite->second->Bitmaps[0].getHeight () == ite->second->Bitmaps[i].getHeight ()) ); 00327 00328 // Blit it 00329 bitmaps[i].blit (&(ite->second->Bitmaps[i]), u, v); 00330 } 00331 00332 // Set the U and V texture coordinates 00333 ite->second->U=(float)(u+1)/(float)width; 00334 ite->second->V=(float)(v+1)/(float)height; 00335 00336 // Set ratio 00337 ite->second->FactorU /= (float)width; 00338 ite->second->FactorV /= (float)height; 00339 00340 // End 00341 break; 00342 } 00343 00344 // next.. 00345 } 00346 00347 // Enter ? 00348 if (enter) 00349 break; 00350 } 00351 00352 // Not enter ? 00353 if (!enter) 00354 // Texture too small.. 00355 return false; 00356 } 00357 while (ite!=mapArea.begin()); 00358 00359 // Some stats 00360 stats.TextureUsed=(float)totalArea/(float)(width*height); 00361 00362 return true; 00363 } |
|
Definition at line 367 of file coarse_mesh_build.cpp. References NLMISC::CBitmap::blit(), NLMISC::CBitmap::getHeight(), NLMISC::CBitmap::getPixels(), NLMISC::CBitmap::getWidth(), height, NLMISC::CBitmap::resize(), uint, uint32, and width. Referenced by buildBitmap().
00368 { 00369 // Get size 00370 uint width=bitmap.getWidth(); 00371 uint height=bitmap.getHeight(); 00372 00373 // Valid size ? 00374 if ((width!=0) && (height!=0)) 00375 { 00376 // Copy the bitmap 00377 CBitmap copy=bitmap; 00378 00379 // Resize the bitmap 00380 bitmap.resize (width+2, height+2); 00381 00382 // Copy old bitmap 00383 bitmap.blit (©, 1, 1); 00384 00385 // Make a top and bottom border 00386 uint32 *topSrc=(uint32*)&(copy.getPixels()[0]); 00387 uint32 *topDest=((uint32*)&(bitmap.getPixels()[0]))+1; 00388 memcpy (topDest, topSrc, 4*width); 00389 uint32 *bottomSrc=topSrc+width*(height-1); 00390 uint32 *bottomDest=((uint32*)&(bitmap.getPixels()[0]))+(width+2)*(height+1)+1; 00391 memcpy (bottomDest, bottomSrc, 4*width); 00392 00393 // Make a left and right border 00394 uint32 *leftSrc=(uint32*)&(copy.getPixels()[0]); 00395 uint32 *leftDest=((uint32*)&(bitmap.getPixels()[0]))+width+2; 00396 uint32 *rightSrc=leftSrc+width-1; 00397 uint32 *rightDest=leftDest+width+1; 00398 uint i; 00399 for (i=0; i<height; i++) 00400 { 00401 // Copy the borders 00402 *leftDest=*leftSrc; 00403 *rightDest=*rightSrc; 00404 00405 // Move pointers 00406 leftDest+=width+2; 00407 rightDest+=width+2; 00408 leftSrc+=width; 00409 rightSrc+=width; 00410 } 00411 00412 // Make corners 00413 00414 // Left top 00415 *(uint32*)&(bitmap.getPixels()[0])=*(uint32*)&(copy.getPixels()[0]); 00416 00417 // Rigth top 00418 *(((uint32*)&(bitmap.getPixels()[0]))+width+1)=*(((uint32*)&(copy.getPixels()[0]))+width-1); 00419 00420 // Rigth bottom 00421 *(((uint32*)&(bitmap.getPixels()[0]))+(width+2)*(height+2)-1)=*(((uint32*)&(copy.getPixels()[0]))+width*height-1); 00422 00423 // Left bottom 00424 *(((uint32*)&(bitmap.getPixels()[0]))+(width+2)*(height+1))=*(((uint32*)&(copy.getPixels()[0]))+width*(height-1)); 00425 } 00426 } |
|
Definition at line 430 of file coarse_mesh_build.cpp. References NL3D::CCoarseMeshBuild::CBitmapDesc::FactorU, NL3D::CCoarseMeshBuild::CBitmapDesc::FactorV, NL3D::CMeshBase::getMaterial(), NL3D::CMeshGeom::getNbMatrixBlock(), NL3D::CMeshGeom::getNbRdrPass(), NL3D::CPrimitiveBlock::getNumQuad(), NL3D::CPrimitiveBlock::getNumTri(), NL3D::CPrimitiveBlock::getQuadPointer(), NL3D::CMeshGeom::getRdrPassMaterial(), NL3D::CMeshGeom::getRdrPassPrimitiveBlock(), NL3D::ITexture::getShareName(), NL3D::CVertexBuffer::getTexCoordPointer(), NL3D::CMaterial::getTexture(), NL3D::CPrimitiveBlock::getTriPointer(), NL3D::CMeshGeom::getVertexBuffer(), index, MapBitmapDesc, nlassert, NL3D::ITexture::selectTexture(), NLMISC::strlwr(), NL3D::ITexture::supportSharing(), NLMISC::toString(), NL3D::CCoarseMeshBuild::CBitmapDesc::U, uint, uint32, and NL3D::CCoarseMeshBuild::CBitmapDesc::V. Referenced by build().
00431 { 00432 // 1. scan each bitmap: calc the area of the bitmap and it its name in the maps sorted by area 00433 typedef std::multimap<float, CBitmapDesc> MapAreaBitmap; 00434 MapAreaBitmap mapArea; 00435 uint mesh; 00436 for (mesh=0; mesh<coarseMeshes.size(); mesh++) 00437 { 00438 // Geom mesh pointer 00439 CMeshGeom *meshGeom=coarseMeshes[mesh].MeshGeom; 00440 00441 // Base mesh pointer 00442 const CMeshBase *meshBase=coarseMeshes[mesh].MeshBase; 00443 00444 // The vertex buffer 00445 CVertexBuffer &vertexBuffer=const_cast<CVertexBuffer&> (meshGeom->getVertexBuffer()); 00446 00447 // For each matrix block 00448 uint matrixBlock; 00449 uint nbMatrixBlock=meshGeom->getNbMatrixBlock(); 00450 for (matrixBlock=0; matrixBlock<nbMatrixBlock; matrixBlock++) 00451 { 00452 // For each render pass 00453 uint renderPass; 00454 uint numRenderPass=meshGeom->getNbRdrPass(matrixBlock); 00455 for (renderPass=0; renderPass<numRenderPass; renderPass++) 00456 { 00457 // Render pass material 00458 uint32 matId=meshGeom->getRdrPassMaterial(matrixBlock, renderPass); 00459 00460 // Checks 00461 nlassert (matId<meshBase->getNbMaterial()); 00462 00463 // Get the material 00464 const CMaterial &material=meshBase->getMaterial(matId); 00465 00466 // Get the texture 00467 ITexture *texture=material.getTexture(0); 00468 if (texture) 00469 { 00470 // Get its name 00471 std::string name; 00472 uint i; 00473 for (i=0; i<outputBitmapCount; i++) 00474 { 00475 // Select the good slot 00476 texture->selectTexture (i); 00477 00478 // Get its name 00479 if (texture->supportSharing()) 00480 { 00481 // Get sharing name 00482 name+=strlwr(texture->getShareName()); 00483 } 00484 else 00485 { 00486 // Build a name 00487 name+=toString ((uint)texture); 00488 } 00489 } 00490 00491 // Find the texture 00492 MapBitmapDesc::const_iterator ite=desc.find (name); 00493 nlassert (ite!=desc.end()); 00494 00495 // Descriptor ref 00496 const CBitmapDesc& descBitmap=ite->second; 00497 00498 // Get primitives 00499 const CPrimitiveBlock &primitiveBlock=meshGeom->getRdrPassPrimitiveBlock(matrixBlock,renderPass); 00500 00501 // Set of vertex to remap 00502 std::set<uint> vertexToRemap; 00503 00504 // Remap triangles 00505 uint index; 00506 const uint32 *indexPtr=primitiveBlock.getTriPointer(); 00507 uint32 numIndex=3*primitiveBlock.getNumTri(); 00508 for (index=0; index<numIndex; index++) 00509 vertexToRemap.insert (indexPtr[index]); 00510 00511 // Remap quad 00512 indexPtr=primitiveBlock.getQuadPointer(); 00513 numIndex=4*primitiveBlock.getNumQuad(); 00514 for (index=0; index<numIndex; index++) 00515 vertexToRemap.insert (indexPtr[index]); 00516 00517 // Remap the vertex 00518 std::set<uint>::iterator iteRemap=vertexToRemap.begin(); 00519 while (iteRemap!=vertexToRemap.end()) 00520 { 00521 // Remap the vertex 00522 float *UVCoordinate=(float*)vertexBuffer.getTexCoordPointer(*iteRemap); 00523 UVCoordinate[0]=UVCoordinate[0]*descBitmap.FactorU+descBitmap.U; 00524 UVCoordinate[1]=UVCoordinate[1]*descBitmap.FactorV+descBitmap.V; 00525 00526 // Next vertex 00527 iteRemap++; 00528 } 00529 } 00530 } 00531 } 00532 } 00533 } |