NL3D::CCoarseMeshBuild Class Reference

#include <coarse_mesh_build.h>


Detailed Description

Class used to build the coarse meshes

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.

Author:
Cyril 'Hulud' Corvazier

Nevrax France

Date:
2001

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)


Member Typedef Documentation

typedef std::map<std::string, CBitmapDesc> NL3D::CCoarseMeshBuild::MapBitmapDesc [private]
 

Definition at line 132 of file coarse_mesh_build.h.

Referenced by build(), buildBitmap(), and remapCoordinates().


Member Function Documentation

bool NL3D::CCoarseMeshBuild::build const std::vector< CCoarseMeshDesc > &  coarseMeshes,
std::vector< NLMISC::CBitmap > &  bitmaps,
CStats stats,
float  mulArea
 

The build method. This method will build a single texture and adjuste the UV texture coordinates of each mesh geom.

Parameters:
coarseMeshes is a vector of coarse mesh to compute.
bitmap will receive the final bitmap.
start will receive various statistics about the build process.
mulArea is the mul factor used to increase to theorical global texture size.

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 }

bool NL3D::CCoarseMeshBuild::buildBitmap const std::vector< CCoarseMeshDesc > &  coarseMeshes,
std::vector< NLMISC::CBitmap > &  bitmaps,
CStats stats,
MapBitmapDesc desc,
float  mulArea
[private]
 

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 }

void NL3D::CCoarseMeshBuild::expand NLMISC::CBitmap bitmap  )  [private]
 

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 (&copy, 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 }

void NL3D::CCoarseMeshBuild::remapCoordinates const std::vector< CCoarseMeshDesc > &  coarseMeshes,
const MapBitmapDesc desc,
uint  outputBitmapCount
[private]
 

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 }


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 06:45:23 2004 for NeL by doxygen 1.3.6