00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00042 MapBitmapDesc desc;
00043 if (buildBitmap (coarseMeshes, bitmap, stats, desc, mulArea)==false)
00044 return false;
00045
00046
00047 remapCoordinates (coarseMeshes, desc);
00048
00049
00050 return true;
00051 }
00052
00053
00054
00055
00056 class CInsertedBitmap
00057 {
00058 public:
00059
00060 uint Width;
00061 uint Height;
00062
00063
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
00073 uint totalArea=0;
00074
00075
00076
00077
00078 typedef std::multimap<uint, CBitmapDesc> MapAreaBitmap;
00079 MapAreaBitmap mapArea;
00080 uint mesh;
00081 for (mesh=0; mesh<coarseMeshes.size(); mesh++)
00082 {
00083
00084 CMeshGeom *meshGeom=coarseMeshes[mesh].MeshGeom;
00085
00086
00087 const CMeshBase *meshBase=coarseMeshes[mesh].MeshBase;
00088
00089
00090 uint matrixBlock;
00091 uint nbMatrixBlock=meshGeom->getNbMatrixBlock();
00092 for (matrixBlock=0; matrixBlock<nbMatrixBlock; matrixBlock++)
00093 {
00094
00095 uint renderPass;
00096 uint numRenderPass=meshGeom->getNbRdrPass(matrixBlock);
00097 for (renderPass=0; renderPass<numRenderPass; renderPass++)
00098 {
00099
00100 uint32 matId=meshGeom->getRdrPassMaterial(matrixBlock, renderPass);
00101
00102
00103 nlassert (matId<meshBase->getNbMaterial());
00104
00105
00106 const CMaterial &material=meshBase->getMaterial(matId);
00107
00108
00109 ITexture *texture=material.getTexture(0);
00110 if (texture)
00111 {
00112
00113 std::string name;
00114 if (texture->supportSharing())
00115 {
00116
00117 name=texture->getShareName();
00118 }
00119 else
00120 {
00121
00122 name=toString ((uint)texture);
00123 }
00124
00125
00126 if (desc.find (name)==desc.end())
00127 {
00128
00129
00130
00131 texture->generate();
00132
00133
00134 texture->convertToType (CBitmap::RGBA);
00135
00136
00137 float originalWidth = (float)texture->getWidth();
00138 float originalHeight = (float)texture->getHeight();
00139
00140
00141 expand (*texture);
00142
00143
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
00152 desc.insert (MapBitmapDesc::value_type (name, descBitmap));
00153 mapArea.insert (MapAreaBitmap::value_type(area, descBitmap));
00154
00155
00156 totalArea+=area;
00157 }
00158 }
00159 }
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168 uint newArea=getPowerOf2 (raiseToNextPowerOf2 (totalArea));
00169 while ((1<<newArea)<(sint)(mulArea*(float)totalArea))
00170 {
00171 newArea++;
00172 }
00173
00174
00175 uint width=1<<(newArea/2);
00176 uint height=1<<(newArea/2 + (newArea&1));
00177
00178
00179 bitmap.resize (width, height, CBitmap::RGBA);
00180
00181
00182 if (totalArea==0)
00183 {
00184
00185 stats.TextureUsed=1;
00186
00187 return true;
00188 }
00189
00190
00191
00192
00193 typedef std::multimap<sint, CInsertedBitmap> mapInsertedBitmap;
00194
00195
00196 MapAreaBitmap::iterator ite=mapArea.end();
00197
00198
00199 mapInsertedBitmap inserted;
00200
00201
00202 uint maxTexHeight=0;
00203
00204 do
00205 {
00206 ite--;
00207 nlassert (ite!=mapArea.end());
00208
00209
00210 ITexture *texture=ite->second.Texture;
00211
00212
00213 uint widthTex=texture->getWidth();
00214 uint heightTex=texture->getHeight();
00215
00216
00217 uint widthMax=width-widthTex;
00218 uint heightMax=height-heightTex;
00219
00220
00221 bool enter=false;
00222
00223
00224 for (uint v=0; v<heightMax; v++)
00225 {
00226 for (uint u=0; u<widthMax; u++)
00227 {
00228
00229 enter=true;
00230
00231
00232 mapInsertedBitmap::iterator toTest=inserted.lower_bound ((sint)v-(sint)maxTexHeight);
00233 while (toTest!=inserted.end())
00234 {
00235
00236 if ((sint)(v+heightTex)<=(toTest->first))
00237 {
00238
00239 break;
00240 }
00241
00242
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
00251 enter=false;
00252 u=toTest->second.U+otherWidth-1;
00253 break;
00254 }
00255
00256
00257 toTest++;
00258 }
00259
00260
00261 if (enter)
00262 {
00263
00264
00265
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
00274 if (heightTex>maxTexHeight)
00275 maxTexHeight=heightTex;
00276
00277
00278 bitmap.blit (texture, u, v);
00279
00280
00281 MapBitmapDesc::iterator iteInserted=desc.find (ite->second.Name);
00282 nlassert (iteInserted!=desc.end());
00283
00284
00285 iteInserted->second.U=(float)(u+1)/(float)width;
00286 iteInserted->second.V=(float)(v+1)/(float)height;
00287
00288
00289 iteInserted->second.FactorU /= (float)width;
00290 iteInserted->second.FactorV /= (float)height;
00291
00292
00293 break;
00294 }
00295
00296
00297 }
00298
00299
00300 if (enter)
00301 break;
00302 }
00303
00304
00305 if (!enter)
00306
00307 return false;
00308 }
00309 while (ite!=mapArea.begin());
00310
00311
00312 stats.TextureUsed=(float)totalArea/(float)(width*height);
00313
00314 return true;
00315 }
00316
00317
00318
00319 void CCoarseMeshBuild::expand (CBitmap& bitmap)
00320 {
00321
00322 uint width=bitmap.getWidth();
00323 uint height=bitmap.getHeight();
00324
00325
00326 if ((width!=0) && (height!=0))
00327 {
00328
00329 CBitmap copy=bitmap;
00330
00331
00332 bitmap.resize (width+2, height+2);
00333
00334
00335 bitmap.blit (©, 1, 1);
00336
00337
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
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
00354 *leftDest=*leftSrc;
00355 *rightDest=*rightSrc;
00356
00357
00358 leftDest+=width+2;
00359 rightDest+=width+2;
00360 leftSrc+=width;
00361 rightSrc+=width;
00362 }
00363
00364
00365
00366
00367 *(uint32*)&(bitmap.getPixels()[0])=*(uint32*)&(copy.getPixels()[0]);
00368
00369
00370 *(((uint32*)&(bitmap.getPixels()[0]))+width+1)=*(((uint32*)&(copy.getPixels()[0]))+width-1);
00371
00372
00373 *(((uint32*)&(bitmap.getPixels()[0]))+(width+2)*(height+2)-1)=*(((uint32*)&(copy.getPixels()[0]))+width*height-1);
00374
00375
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
00385 typedef std::multimap<float, CBitmapDesc> MapAreaBitmap;
00386 MapAreaBitmap mapArea;
00387 uint mesh;
00388 for (mesh=0; mesh<coarseMeshes.size(); mesh++)
00389 {
00390
00391 CMeshGeom *meshGeom=coarseMeshes[mesh].MeshGeom;
00392
00393
00394 const CMeshBase *meshBase=coarseMeshes[mesh].MeshBase;
00395
00396
00397 CVertexBuffer &vertexBuffer=const_cast<CVertexBuffer&> (meshGeom->getVertexBuffer());
00398
00399
00400 uint matrixBlock;
00401 uint nbMatrixBlock=meshGeom->getNbMatrixBlock();
00402 for (matrixBlock=0; matrixBlock<nbMatrixBlock; matrixBlock++)
00403 {
00404
00405 uint renderPass;
00406 uint numRenderPass=meshGeom->getNbRdrPass(matrixBlock);
00407 for (renderPass=0; renderPass<numRenderPass; renderPass++)
00408 {
00409
00410 uint32 matId=meshGeom->getRdrPassMaterial(matrixBlock, renderPass);
00411
00412
00413 nlassert (matId<meshBase->getNbMaterial());
00414
00415
00416 const CMaterial &material=meshBase->getMaterial(matId);
00417
00418
00419 ITexture *texture=material.getTexture(0);
00420 if (texture)
00421 {
00422
00423 std::string name;
00424 if (texture->supportSharing())
00425 {
00426
00427 name=texture->getShareName();
00428 }
00429 else
00430 {
00431
00432 name=toString ((uint)texture);
00433 }
00434
00435
00436 MapBitmapDesc::const_iterator ite=desc.find (name);
00437 nlassert (ite!=desc.end());
00438
00439
00440 const CBitmapDesc& descBitmap=ite->second;
00441
00442
00443 const CPrimitiveBlock &primitiveBlock=meshGeom->getRdrPassPrimitiveBlock(matrixBlock,renderPass);
00444
00445
00446 std::set<uint> vertexToRemap;
00447
00448
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
00456 indexPtr=primitiveBlock.getQuadPointer();
00457 numIndex=4*primitiveBlock.getNumQuad();
00458 for (index=0; index<numIndex; index++)
00459 vertexToRemap.insert (indexPtr[index]);
00460
00461
00462 std::set<uint>::iterator iteRemap=vertexToRemap.begin();
00463 while (iteRemap!=vertexToRemap.end())
00464 {
00465
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
00471 iteRemap++;
00472 }
00473 }
00474 }
00475 }
00476 }
00477 }
00478
00479
00480
00481 }