# 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_build.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_build.h"
00029 
00030 #include "3d/mesh.h"
00031 
00032 using namespace NLMISC;
00033 
00034 namespace NL3D 
00035 {
00036 
00037 // ***************************************************************************
00038 
00039 bool CCoarseMeshBuild::build (const std::vector<CCoarseMeshDesc>& coarseMeshes, CBitmap& bitmap, CStats& stats, float mulArea)
00040 {
00041         // 1. build the bitmap
00042         MapBitmapDesc desc;
00043         if (buildBitmap (coarseMeshes, bitmap, stats, desc, mulArea)==false)
00044                 return false;
00045 
00046         // 2. remap coordinates
00047         remapCoordinates (coarseMeshes, desc);
00048 
00049         // 3. ok
00050         return true;
00051 }
00052 
00053 // ***************************************************************************
00054 
00055 // Class descriptor for bitmap inserted
00056 class CInsertedBitmap
00057 {
00058 public:
00059         // Width and height
00060         uint Width;
00061         uint Height;
00062 
00063         // Coordinates
00064         uint U;
00065         uint V;
00066 };
00067 
00068 // ***************************************************************************
00069 
00070 bool CCoarseMeshBuild::buildBitmap (const std::vector<CCoarseMeshDesc>& coarseMeshes, CBitmap& bitmap, CStats& stats, MapBitmapDesc& desc, float mulArea)
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                                         // Get its name
00113                                         std::string name;
00114                                         if (texture->supportSharing())
00115                                         {
00116                                                 // Get sharing name
00117                                                 name=texture->getShareName();
00118                                         }
00119                                         else
00120                                         {
00121                                                 // Build a name
00122                                                 name=toString ((uint)texture);
00123                                         }
00124 
00125                                         // Already added ?
00126                                         if (desc.find (name)==desc.end())
00127                                         {
00128                                                 // Add it..
00129 
00130                                                 // Generate the texture
00131                                                 texture->generate();
00132 
00133                                                 // Convert to RGBA
00134                                                 texture->convertToType (CBitmap::RGBA);
00135 
00136                                                 // Backup original size
00137                                                 float originalWidth = (float)texture->getWidth();
00138                                                 float originalHeight = (float)texture->getHeight();
00139 
00140                                                 // Expand the texture
00141                                                 expand (*texture);
00142 
00143                                                 // Descriptor for this texture
00144                                                 CBitmapDesc descBitmap;
00145                                                 uint area = texture->getWidth() * texture->getHeight();
00146                                                 descBitmap.Texture = texture;
00147                                                 descBitmap.Name = name;
00148                                                 descBitmap.FactorU = originalWidth;
00149                                                 descBitmap.FactorV = originalHeight;
00150 
00151                                                 // Insert it in the maps
00152                                                 desc.insert (MapBitmapDesc::value_type (name, descBitmap));
00153                                                 mapArea.insert (MapAreaBitmap::value_type(area, descBitmap));
00154 
00155                                                 // Sum area if added
00156                                                 totalArea+=area;
00157                                         }
00158                                 }
00159                         }
00160                 }
00161         }
00162 
00163         // ***************************************************************************
00164 
00165         // 2. Calc the best area for the dest texture and resize the bitmap
00166         
00167         // Total area used by the textures + a little more
00168         uint newArea=getPowerOf2 (raiseToNextPowerOf2 (totalArea));
00169         while ((1<<newArea)<(sint)(mulArea*(float)totalArea))
00170         {
00171                 newArea++;
00172         }
00173 
00174         // Calc width and height with HEIGHT==WIDTH or HEIGHT=2*WIDTH
00175         uint width=1<<(newArea/2);
00176         uint height=1<<(newArea/2 + (newArea&1));
00177 
00178         // Resize the bitmap and set the pixel format
00179         bitmap.resize (width, height, CBitmap::RGBA);
00180 
00181         // Checks
00182         if (totalArea==0)
00183         {
00184                 // No texture, ok computed.
00185                 stats.TextureUsed=1;
00186 
00187                 return true;
00188         }
00189 
00190         // ***************************************************************************
00191 
00192         // 3. Place each texture in the bitmap in uncreasing order
00193         typedef std::multimap<sint, CInsertedBitmap> mapInsertedBitmap;
00194         
00195         // For each texture
00196         MapAreaBitmap::iterator ite=mapArea.end();
00197 
00198         // Inserted bitmap desc
00199         mapInsertedBitmap inserted;
00200 
00201         // Max texture height
00202         uint maxTexHeight=0;
00203 
00204         do 
00205         {
00206                 ite--;
00207                 nlassert (ite!=mapArea.end());
00208 
00209                 // Texture
00210                 ITexture *texture=ite->second.Texture;
00211 
00212                 // Size of the texture
00213                 uint widthTex=texture->getWidth();
00214                 uint heightTex=texture->getHeight();
00215 
00216                 // Width and height max
00217                 uint widthMax=width-widthTex;
00218                 uint heightMax=height-heightTex;
00219 
00220                 // Test against others..
00221                 bool enter=false;
00222 
00223                 // For each row and each column
00224                 for (uint v=0; v<heightMax; v++)
00225                 {
00226                         for (uint u=0; u<widthMax; u++)
00227                         {
00228                                 // Test against others..
00229                                 enter=true;
00230 
00231                                 // Get the first to test
00232                                 mapInsertedBitmap::iterator toTest=inserted.lower_bound ((sint)v-(sint)maxTexHeight);
00233                                 while (toTest!=inserted.end())
00234                                 {
00235                                         // Make a test ?
00236                                         if ((sint)(v+heightTex)<=(toTest->first))
00237                                         {
00238                                                 // Ok, end test
00239                                                 break;
00240                                         }
00241 
00242                                         // Test it
00243                                         uint otherU=toTest->second.U;
00244                                         uint otherV=toTest->second.V;
00245                                         uint otherWidth=toTest->second.Width;
00246                                         uint otherHeight=toTest->second.Height;
00247                                         if ((v<otherV+otherHeight) && (v+heightTex>otherV) &&
00248                                                 (u<otherU+otherWidth) && (u+widthTex>otherU))
00249                                         {
00250                                                 // Collision
00251                                                 enter=false;
00252                                                 u=toTest->second.U+otherWidth-1;
00253                                                 break;
00254                                         }
00255 
00256                                         // Next to test
00257                                         toTest++;
00258                                 }
00259 
00260                                 // Enter ?
00261                                 if (enter)
00262                                 {
00263                                         // Ok, enter
00264 
00265                                         // Insert an inserted descriptor
00266                                         CInsertedBitmap descInserted;
00267                                         descInserted.Width=widthTex;
00268                                         descInserted.Height=heightTex;
00269                                         descInserted.U=u;
00270                                         descInserted.V=v;
00271                                         inserted.insert (mapInsertedBitmap::value_type (v, descInserted));
00272         
00273                                         // Max height
00274                                         if (heightTex>maxTexHeight)
00275                                                 maxTexHeight=heightTex;
00276 
00277                                         // Blit in the texture
00278                                         bitmap.blit (texture, u, v);
00279 
00280                                         // Get the descriptor by the name
00281                                         MapBitmapDesc::iterator iteInserted=desc.find (ite->second.Name);
00282                                         nlassert (iteInserted!=desc.end());
00283 
00284                                         // Set the U and V texture coordinates
00285                                         iteInserted->second.U=(float)(u+1)/(float)width;
00286                                         iteInserted->second.V=(float)(v+1)/(float)height;
00287 
00288                                         // Set ratio
00289                                         iteInserted->second.FactorU /= (float)width;
00290                                         iteInserted->second.FactorV /= (float)height;
00291 
00292                                         // End
00293                                         break;
00294                                 }
00295 
00296                                 // next..
00297                         }
00298 
00299                         // Enter ?
00300                         if (enter)
00301                                 break;
00302                 }
00303 
00304                 // Not enter ?
00305                 if (!enter)
00306                         // Texture too small..
00307                         return false;
00308         }
00309         while (ite!=mapArea.begin());
00310 
00311         // Some stats
00312         stats.TextureUsed=(float)totalArea/(float)(width*height);
00313 
00314         return true;
00315 }
00316 
00317 // ***************************************************************************
00318 
00319 void CCoarseMeshBuild::expand (CBitmap& bitmap)
00320 {
00321         // Get size
00322         uint width=bitmap.getWidth();
00323         uint height=bitmap.getHeight();
00324 
00325         // Valid size ?
00326         if ((width!=0) && (height!=0))
00327         {
00328                 // Copy the bitmap
00329                 CBitmap copy=bitmap;
00330 
00331                 // Resize the bitmap
00332                 bitmap.resize (width+2, height+2);
00333 
00334                 // Copy old bitmap
00335                 bitmap.blit (&copy, 1, 1);
00336 
00337                 // Make a top and bottom border
00338                 uint32 *topSrc=(uint32*)&(copy.getPixels()[0]);
00339                 uint32 *topDest=((uint32*)&(bitmap.getPixels()[0]))+1;
00340                 memcpy (topDest, topSrc, 4*width);
00341                 uint32 *bottomSrc=topSrc+width*(height-1);
00342                 uint32 *bottomDest=((uint32*)&(bitmap.getPixels()[0]))+(width+2)*(height+1)+1;
00343                 memcpy (bottomDest, bottomSrc, 4*width);
00344 
00345                 // Make a left and right border
00346                 uint32 *leftSrc=(uint32*)&(copy.getPixels()[0]);
00347                 uint32 *leftDest=((uint32*)&(bitmap.getPixels()[0]))+width+2;
00348                 uint32 *rightSrc=leftSrc+width-1;
00349                 uint32 *rightDest=leftDest+width+1;
00350                 uint i;
00351                 for (i=0; i<height; i++)
00352                 {
00353                         // Copy the borders
00354                         *leftDest=*leftSrc;
00355                         *rightDest=*rightSrc;
00356 
00357                         // Move pointers
00358                         leftDest+=width+2;
00359                         rightDest+=width+2;
00360                         leftSrc+=width;
00361                         rightSrc+=width;
00362                 }
00363 
00364                 // Make corners
00365 
00366                 // Left top
00367                 *(uint32*)&(bitmap.getPixels()[0])=*(uint32*)&(copy.getPixels()[0]);
00368 
00369                 // Rigth top
00370                 *(((uint32*)&(bitmap.getPixels()[0]))+width+1)=*(((uint32*)&(copy.getPixels()[0]))+width-1);
00371 
00372                 // Rigth bottom
00373                 *(((uint32*)&(bitmap.getPixels()[0]))+(width+2)*(height+2)-1)=*(((uint32*)&(copy.getPixels()[0]))+width*height-1);
00374 
00375                 // Left bottom
00376                 *(((uint32*)&(bitmap.getPixels()[0]))+(width+2)*(height+1))=*(((uint32*)&(copy.getPixels()[0]))+width*(height-1));
00377         }
00378 }
00379 
00380 // ***************************************************************************
00381 
00382 void CCoarseMeshBuild::remapCoordinates (const std::vector<CCoarseMeshDesc>& coarseMeshes, const MapBitmapDesc& desc)
00383 {
00384         // 1. scan each bitmap: calc the area of the bitmap and it its name in the maps sorted by area
00385         typedef std::multimap<float, CBitmapDesc> MapAreaBitmap;
00386         MapAreaBitmap mapArea;
00387         uint mesh;
00388         for (mesh=0; mesh<coarseMeshes.size(); mesh++)
00389         {
00390                 // Geom mesh pointer
00391                 CMeshGeom *meshGeom=coarseMeshes[mesh].MeshGeom;
00392 
00393                 // Base mesh pointer
00394                 const CMeshBase *meshBase=coarseMeshes[mesh].MeshBase;
00395 
00396                 // The vertex buffer
00397                 CVertexBuffer &vertexBuffer=const_cast<CVertexBuffer&> (meshGeom->getVertexBuffer());
00398 
00399                 // For each matrix block
00400                 uint matrixBlock;
00401                 uint nbMatrixBlock=meshGeom->getNbMatrixBlock();
00402                 for (matrixBlock=0; matrixBlock<nbMatrixBlock; matrixBlock++)
00403                 {
00404                         // For each render pass
00405                         uint renderPass;
00406                         uint numRenderPass=meshGeom->getNbRdrPass(matrixBlock);
00407                         for (renderPass=0; renderPass<numRenderPass; renderPass++)
00408                         {
00409                                 // Render pass material
00410                                 uint32 matId=meshGeom->getRdrPassMaterial(matrixBlock, renderPass);
00411 
00412                                 // Checks
00413                                 nlassert (matId<meshBase->getNbMaterial());
00414 
00415                                 // Get the material
00416                                 const CMaterial &material=meshBase->getMaterial(matId);
00417 
00418                                 // Get the texture
00419                                 ITexture *texture=material.getTexture(0);
00420                                 if (texture)
00421                                 {
00422                                         // Get its name
00423                                         std::string name;
00424                                         if (texture->supportSharing())
00425                                         {
00426                                                 // Get sharing name
00427                                                 name=texture->getShareName();
00428                                         }
00429                                         else
00430                                         {
00431                                                 // Build a name
00432                                                 name=toString ((uint)texture);
00433                                         }
00434 
00435                                         // Find the texture
00436                                         MapBitmapDesc::const_iterator ite=desc.find (name);
00437                                         nlassert (ite!=desc.end());
00438 
00439                                         // Descriptor ref
00440                                         const CBitmapDesc& descBitmap=ite->second;
00441 
00442                                         // Get primitives
00443                                         const CPrimitiveBlock &primitiveBlock=meshGeom->getRdrPassPrimitiveBlock(matrixBlock,renderPass);
00444 
00445                                         // Set of vertex to remap
00446                                         std::set<uint> vertexToRemap;
00447 
00448                                         // Remap triangles
00449                                         uint index;
00450                                         const uint32 *indexPtr=primitiveBlock.getTriPointer();
00451                                         uint32 numIndex=3*primitiveBlock.getNumTri();
00452                                         for (index=0; index<numIndex; index++)
00453                                                 vertexToRemap.insert (indexPtr[index]);
00454 
00455                                         // Remap quad
00456                                         indexPtr=primitiveBlock.getQuadPointer();
00457                                         numIndex=4*primitiveBlock.getNumQuad();
00458                                         for (index=0; index<numIndex; index++)
00459                                                 vertexToRemap.insert (indexPtr[index]);
00460 
00461                                         // Remap the vertex
00462                                         std::set<uint>::iterator iteRemap=vertexToRemap.begin();
00463                                         while (iteRemap!=vertexToRemap.end())
00464                                         {
00465                                                 // Remap the vertex
00466                                                 float *UVCoordinate=(float*)vertexBuffer.getTexCoordPointer(*iteRemap);
00467                                                 UVCoordinate[0]=UVCoordinate[0]*descBitmap.FactorU+descBitmap.U;
00468                                                 UVCoordinate[1]=UVCoordinate[1]*descBitmap.FactorV+descBitmap.V;
00469 
00470                                                 // Next vertex
00471                                                 iteRemap++;
00472                                         }                                       
00473                                 }
00474                         }
00475                 }
00476         }
00477 }
00478 
00479 // ***************************************************************************
00480 
00481 } // NL3D