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/mrm_builder.h"
00029 #include "3d/mrm_parameters.h"
00030 using namespace NLMISC;
00031 using namespace std;
00032
00033
00034 namespace NL3D
00035 {
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 static bool findElement(vector<sint> &array, sint elt)
00047 {
00048 return find(array.begin(), array.end(), elt) != array.end();
00049 }
00050
00051 static bool deleteElement(vector<sint> &array, sint elt)
00052 {
00053 bool found=false;
00054 vector<sint>::iterator it=array.begin();
00055
00056 while( (it=find(array.begin(), array.end(), elt)) != array.end() )
00057 found=true, array.erase(it);
00058
00059 return found;
00060
00061
00062
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 bool CMRMBuilder::vertexHasOneWedge(sint numvertex)
00075 {
00076 CMRMVertex &vert= TmpVertices[numvertex];
00077 for(sint attId=0;attId<NumAttributes;attId++)
00078 {
00079 sint numwedge=-1;
00080 for(sint i=0;i<(sint)vert.SharedFaces.size();i++)
00081 {
00082 sint w= TmpFaces[vert.SharedFaces[i]].getAssociatedWedge(attId, numvertex);
00083 if(numwedge>=0 && numwedge!=w) return false;
00084 else numwedge=w;
00085 }
00086 }
00087 return true;
00088 }
00089
00090 bool CMRMBuilder::vertexHasOneMaterial(sint numvertex)
00091 {
00092 sint matId=-1;
00093 CMRMVertex &vert= TmpVertices[numvertex];
00094 for(sint i=0;i<(sint)vert.SharedFaces.size();i++)
00095 {
00096 sint m= TmpFaces[vert.SharedFaces[i]].MaterialId;
00097 if(matId>=0 && matId!=m) return false;
00098 else matId=m;
00099 }
00100 return true;
00101 }
00102
00103 bool CMRMBuilder::vertexContinue(sint numvertex)
00104 {
00105 return vertexHasOneWedge(numvertex) && vertexHasOneMaterial(numvertex);
00106 }
00107
00108 bool CMRMBuilder::vertexClosed(sint numvertex)
00109 {
00110 CMRMVertex &vert= TmpVertices[numvertex];
00111 map<CMRMEdge, sint> EdgeShare;
00112
00113 sint i;
00114 for(i=0;i<(sint)vert.SharedFaces.size();i++)
00115 {
00116 CMRMFaceBuild &f=TmpFaces[vert.SharedFaces[i]];
00117 EdgeShare[f.getEdge(0)]= 0;
00118 EdgeShare[f.getEdge(1)]= 0;
00119 EdgeShare[f.getEdge(2)]= 0;
00120 }
00121
00122 for(i=0;i<(sint)vert.SharedFaces.size();i++)
00123 {
00124 CMRMFaceBuild &f=TmpFaces[vert.SharedFaces[i]];
00125 EdgeShare[f.getEdge(0)]++;
00126 EdgeShare[f.getEdge(1)]++;
00127 EdgeShare[f.getEdge(2)]++;
00128 }
00129
00130 for(i=0;i<(sint)vert.SharedFaces.size();i++)
00131 {
00132 CMRMFaceBuild &f=TmpFaces[vert.SharedFaces[i]];
00133 sint v0= f.Corner[0].Vertex;
00134 sint v1= f.Corner[1].Vertex;
00135 sint v2= f.Corner[2].Vertex;
00136 if(EdgeShare[f.getEdge(0)]<2 && (v0==numvertex || v1==numvertex)) return false;
00137 if(EdgeShare[f.getEdge(1)]<2 && (v1==numvertex || v2==numvertex)) return false;
00138 if(EdgeShare[f.getEdge(2)]<2 && (v0==numvertex || v2==numvertex)) return false;
00139 }
00140 return true;
00141 }
00142
00143 float CMRMBuilder::getDeltaFaceNormals(sint numvertex)
00144 {
00145
00146 CMRMVertex &vert= TmpVertices[numvertex];
00147 float delta=0;
00148 CVector refNormal;
00149 sint nfaces=vert.SharedFaces.size();
00150 for(sint i=0;i<nfaces;i++)
00151 {
00152 CVector normal;
00153 CVector &v0= TmpVertices[TmpFaces[i].Corner[0].Vertex].Current;
00154 CVector &v1= TmpVertices[TmpFaces[i].Corner[1].Vertex].Current;
00155 CVector &v2= TmpVertices[TmpFaces[i].Corner[2].Vertex].Current;
00156 normal= (v1-v0)^(v2-v0);
00157 normal.normalize();
00158 if(i==0)
00159 refNormal=normal;
00160 else
00161 delta+=(1-refNormal*normal);
00162 }
00163 if(nfaces<2)
00164 return 0;
00165 else
00166 return delta/(nfaces-1);
00167 }
00168
00169 bool CMRMBuilder::edgeContinue(const CMRMEdge &edge)
00170 {
00171 sint v0= edge.v0;
00172 sint v1= edge.v1;
00173 CMRMVertex &Vertex1=TmpVertices[v0];
00174
00175
00176 vector<sint> deletedFaces;
00177 sint i;
00178 for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00179 {
00180 sint numFace= Vertex1.SharedFaces[i];
00181 if(TmpFaces[numFace].hasVertex(v1))
00182 deletedFaces.push_back(numFace);
00183 }
00184
00185 sint matId=-1;
00186
00187 for(i=0;i<(sint)deletedFaces.size();i++)
00188 {
00189 sint m;
00190 m= TmpFaces[deletedFaces[i]].MaterialId;
00191 if(matId>=0 && matId!=m) return false;
00192 else matId=m;
00193 }
00194
00195
00196 for(sint attId=0;attId<NumAttributes;attId++)
00197 {
00198 sint numwedge1=-1,numwedge2=-1;
00199 for(i=0;i<(sint)deletedFaces.size();i++)
00200 {
00201 sint w;
00202 w= TmpFaces[deletedFaces[i]].getAssociatedWedge(attId, v0);
00203 if(numwedge1>=0 && numwedge1!=w) return false;
00204 else numwedge1=w;
00205 w= TmpFaces[deletedFaces[i]].getAssociatedWedge(attId, v1);
00206 if(numwedge2>=0 && numwedge2!=w) return false;
00207 else numwedge2=w;
00208 }
00209 }
00210
00211 return true;
00212 }
00213
00214 bool CMRMBuilder::edgeNearUniqueMatFace(const CMRMEdge &edge)
00215 {
00216 sint v0= edge.v0;
00217 sint v1= edge.v1;
00218 CMRMVertex &Vertex1=TmpVertices[v0];
00219
00220
00221 vector<sint> deletedFaces;
00222 sint i;
00223 for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00224 {
00225 sint numFace= Vertex1.SharedFaces[i];
00226 if(TmpFaces[numFace].hasVertex(v1))
00227 deletedFaces.push_back(numFace);
00228 }
00229
00230
00231 for(i=0;i<(sint)deletedFaces.size();i++)
00232 {
00233 CMRMFaceBuild &f=TmpFaces[deletedFaces[i]];
00234 if( !edgeContinue(f.getEdge(0)) &&
00235 !edgeContinue(f.getEdge(1)) &&
00236 !edgeContinue(f.getEdge(2)))
00237 return true;
00238 }
00239
00240 return false;
00241 }
00242
00243
00244 float CMRMBuilder::computeEdgeCost(const CMRMEdge &edge)
00245 {
00246 sint v1= edge.v0;
00247 sint v2= edge.v1;
00248
00249
00250
00251
00252
00253
00254 float cost=(TmpVertices[v1].Current-TmpVertices[v2].Current).norm();
00255
00256
00257 float faceCost= (getDeltaFaceNormals(v1)+getDeltaFaceNormals(v2));
00258
00259
00260 faceCost= max(faceCost, 0.01f);
00261
00262
00263 cost*= faceCost;
00264
00265
00266 if( !vertexContinue(v1) && !vertexContinue(v2) )
00267 {
00268
00269 if( edgeContinue(edge) || edgeNearUniqueMatFace(edge) )
00270 cost*=4;
00271 }
00272
00273
00274 if(_HasMeshInterfaces)
00275 {
00276
00277 sint meshSewingId= TmpVertices[v1].InterfaceLink.InterfaceId;
00278 if( meshSewingId>=0 && meshSewingId == TmpVertices[v2].InterfaceLink.InterfaceId)
00279 {
00280
00281 CMRMSewingMesh &sewingMesh= _SewingMeshes[meshSewingId];
00282 uint dummy;
00283
00284
00285 CMRMEdge sewingEdge;
00286 sewingEdge.v0= TmpVertices[v1].InterfaceLink.InterfaceVertexId;
00287 sewingEdge.v1= TmpVertices[v2].InterfaceLink.InterfaceVertexId;
00288
00289 sint collapseId= sewingMesh.mustCollapseEdge(_CurrentLodComputed, sewingEdge, dummy);
00290 if(collapseId>=0)
00291 {
00292
00293
00294 cost= (float)(-sewingMesh.getNumCollapseEdge(_CurrentLodComputed) + collapseId);
00295 }
00296 else
00297 {
00298
00299 cost= FLT_MAX;
00300 }
00301 }
00302 }
00303
00304 return cost;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 bool CMRMBuilder::faceShareWedges(CMRMFaceBuild *face, sint attribId, sint numVertex1, sint numVertex2)
00319 {
00320 sint numWedge1= face->getAssociatedWedge(attribId, numVertex1);
00321 sint numWedge2= face->getAssociatedWedge(attribId, numVertex2);
00322 if(numWedge1<0) return false;
00323 if(numWedge2<0) return false;
00324
00325 CMRMAttribute &w1= TmpAttributes[attribId][numWedge1];
00326 CMRMAttribute &w2= TmpAttributes[attribId][numWedge2];
00327 return w1.Shared && w2.Shared && w1.NbSharedFaces>0 && w2.NbSharedFaces>0;
00328 }
00329
00330
00331
00332 void CMRMBuilder::insertFaceIntoEdgeList(CMRMFaceBuild &f)
00333 {
00334 float len;
00335 if(f.ValidIt0)
00336 {
00337 len= computeEdgeCost(f.getEdge(0));
00338 f. It0= EdgeCollapses.insert( TEdgeMap::value_type( len, CMRMEdgeFace(f.getEdge(0),&f) ) );
00339 }
00340 if(f.ValidIt1)
00341 {
00342 len= computeEdgeCost(f.getEdge(1));
00343 f. It1= EdgeCollapses.insert( TEdgeMap::value_type( len, CMRMEdgeFace(f.getEdge(1),&f) ) );
00344 }
00345 if(f.ValidIt2)
00346 {
00347 len= computeEdgeCost(f.getEdge(2));
00348 f. It2= EdgeCollapses.insert( TEdgeMap::value_type( len, CMRMEdgeFace(f.getEdge(2),&f) ) );
00349 }
00350 }
00351
00352 void CMRMBuilder::removeFaceFromEdgeList(CMRMFaceBuild &f)
00353 {
00354 if(f.ValidIt0)
00355 EdgeCollapses.erase(f.It0);
00356 if(f.ValidIt1)
00357 EdgeCollapses.erase(f.It1);
00358 if(f.ValidIt2)
00359 EdgeCollapses.erase(f.It2);
00360 }
00361
00362
00363
00364
00365 struct CTmpVertexWeight
00366 {
00367 uint32 MatrixId;
00368 float Weight;
00369
00370 bool operator==(const CTmpVertexWeight &o) const
00371 {
00372 return MatrixId==o.MatrixId;
00373 }
00374
00375 bool operator<(const CTmpVertexWeight &o) const
00376 {
00377 return Weight>o.Weight;
00378 }
00379
00380 };
00381
00382
00383
00384 CMesh::CSkinWeight CMRMBuilder::collapseSkinWeight(const CMesh::CSkinWeight &sw1, const CMesh::CSkinWeight &sw2, float interValue) const
00385 {
00386
00387 if(interValue==0)
00388 return sw1;
00389 if(interValue==1)
00390 return sw2;
00391
00392
00393 uint nbMats1=0;
00394 uint nbMats2=0;
00395 static vector<CTmpVertexWeight> sws;
00396 sws.reserve(NL3D_MESH_SKINNING_MAX_MATRIX * 2);
00397 sws.clear();
00398
00399
00400 uint i;
00401 for(i=0; i<NL3D_MESH_SKINNING_MAX_MATRIX; i++)
00402 {
00403 CTmpVertexWeight vw;
00404 vw.MatrixId= sw1.MatrixId[i];
00405 vw.Weight= sw1.Weights[i]*(1-interValue);
00406
00407 if(vw.Weight>0)
00408 {
00409
00410 sws.push_back(vw);
00411 }
00412
00413 if(sw1.Weights[i]>0)
00414 nbMats1++;
00415 }
00416
00417
00418
00419 for(i=0; i<NL3D_MESH_SKINNING_MAX_MATRIX; i++)
00420 {
00421 CTmpVertexWeight vw;
00422 vw.MatrixId= sw2.MatrixId[i];
00423 vw.Weight= sw2.Weights[i]*(interValue);
00424
00425 if(vw.Weight>0)
00426 {
00427
00428 vector<CTmpVertexWeight>::iterator it= find(sws.begin(), sws.end(), vw);
00429 if(it== sws.end())
00430 sws.push_back(vw);
00431 else
00432 it->Weight+= vw.Weight;
00433 }
00434
00435 if(sw2.Weights[i]>0)
00436 nbMats2++;
00437 }
00438
00439
00440
00441
00442 sort(sws.begin(), sws.end());
00443
00444
00445 uint nbMatsOut;
00446 switch(_SkinReduction)
00447 {
00448 case CMRMParameters::SkinReductionMin:
00449 nbMatsOut= min(nbMats1, nbMats2);
00450 break;
00451 case CMRMParameters::SkinReductionMax:
00452 nbMatsOut= max(nbMats1, nbMats2);
00453 break;
00454 case CMRMParameters::SkinReductionBest:
00455 nbMatsOut= min( sws.size(), (uint)NL3D_MESH_SKINNING_MAX_MATRIX );
00456 break;
00457 default:
00458 nlstop;
00459 };
00460
00461 nbMatsOut= min(nbMatsOut, sws.size());
00462 nlassert(nbMatsOut<=NL3D_MESH_SKINNING_MAX_MATRIX);
00463
00464
00465
00466 float sumWeight=0;
00467 for(i= 0; i<nbMatsOut; i++)
00468 {
00469 sumWeight+= sws[i].Weight;
00470 }
00471
00472 CMesh::CSkinWeight ret;
00473
00474 for(i= 0; i<nbMatsOut; i++)
00475 {
00476 ret.MatrixId[i]= sws[i].MatrixId;
00477 ret.Weights[i]= sws[i].Weight / sumWeight;
00478 }
00479
00480 return ret;
00481 }
00482
00483
00484 sint CMRMBuilder::collapseEdge(const CMRMEdge &edge)
00485 {
00486 sint i,j;
00487 float InterValue;
00488 sint edgeV1=edge.v0;
00489 sint edgeV2=edge.v1;
00490
00491
00492
00493
00494
00495
00496
00497 CMRMVertex &Vertex1=TmpVertices[edgeV1], &Vertex2=TmpVertices[edgeV2];
00498
00499
00500
00501 InterValue=0.5;
00502
00503
00504 if( _HasMeshInterfaces && (Vertex1.InterfaceLink.InterfaceId>=0 || Vertex2.InterfaceLink.InterfaceId>=0) )
00505 {
00506
00507 if(Vertex1.InterfaceLink.InterfaceId==Vertex2.InterfaceLink.InterfaceId)
00508 {
00509
00510 CMRMSewingMesh &sewingMesh= _SewingMeshes[Vertex1.InterfaceLink.InterfaceId];
00511
00512
00513 CMRMEdge sewingEdge;
00514 sewingEdge.v0= Vertex1.InterfaceLink.InterfaceVertexId;
00515 sewingEdge.v1= Vertex2.InterfaceLink.InterfaceVertexId;
00516
00517
00518 uint vertToCollapse;
00519 sint collapseId= sewingMesh.mustCollapseEdge(_CurrentLodComputed, sewingEdge, vertToCollapse);
00520
00521 if(collapseId>=0)
00522 {
00523
00524 if(vertToCollapse==(uint)sewingEdge.v0)
00525 InterValue= 1;
00526 else
00527 InterValue= 0;
00528
00529 }
00530 else
00531 {
00532
00533
00534 InterValue= 0;
00535 }
00536 }
00537 else
00538 {
00539
00540 if(Vertex1.InterfaceLink.InterfaceId>=0)
00541 {
00542
00543 InterValue= 0;
00544 }
00545 else
00546 {
00547
00548 InterValue= 1;
00549 }
00550 }
00551 }
00552
00553 else
00554 {
00555
00556
00557 bool vc1= vertexClosed(edgeV1);
00558 bool vc2= vertexClosed(edgeV2);
00559 if(!vc1 && vc2) InterValue=0;
00560 else if(vc1 && !vc2) InterValue=1;
00561 else
00562 {
00563
00564
00565 bool vc1= vertexContinue(edgeV1);
00566 bool vc2= vertexContinue(edgeV2);
00567 if(!vc1 && vc2) InterValue=0;
00568 if(vc1 && !vc2) InterValue=1;
00569 }
00570 }
00571
00572
00573
00574
00575
00576
00577 Vertex1.Current= Vertex1.Current*(1-InterValue) + Vertex2.Current*InterValue;
00578 for (i = 0; i < (sint)Vertex1.BSCurrent.size(); ++i)
00579 Vertex1.BSCurrent[i] = Vertex1.BSCurrent[i]*(1-InterValue) + Vertex2.BSCurrent[i]*InterValue;
00580 Vertex2.CollapsedTo= edgeV1;
00581 if(_Skinned)
00582 Vertex1.CurrentSW= collapseSkinWeight(Vertex1.CurrentSW, Vertex2.CurrentSW, InterValue);
00583 if( _HasMeshInterfaces )
00584 Vertex1.InterfaceLink= InterValue<0.5f? Vertex1.InterfaceLink : Vertex2.InterfaceLink;
00585
00586
00587
00588 for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00589 {
00590 sint numFace= Vertex1.SharedFaces[i];
00591 if(TmpFaces[numFace].Deleted)
00592 deleteElement(Vertex1.SharedFaces, numFace), i--;
00593 }
00594 for(i=0;i<(sint)Vertex2.SharedFaces.size();i++)
00595 {
00596 sint numFace= Vertex2.SharedFaces[i];
00597 if(TmpFaces[numFace].Deleted)
00598 deleteElement(Vertex2.SharedFaces, numFace), i--;
00599 }
00600
00601
00602
00603 vector<sint> neighboorFaces;
00604 for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00605 {
00606 sint numFace= Vertex1.SharedFaces[i];
00607 if(!findElement(neighboorFaces, numFace))
00608 neighboorFaces.push_back(numFace);
00609 }
00610 for(i=0;i<(sint)Vertex2.SharedFaces.size();i++)
00611 {
00612 sint numFace= Vertex2.SharedFaces[i];
00613 if(!findElement(neighboorFaces, numFace))
00614 neighboorFaces.push_back(numFace);
00615 }
00616
00617
00618 vector<sint> deletedFaces;
00619 for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00620 {
00621 sint numFace= Vertex1.SharedFaces[i];
00622 nlassert(!TmpFaces[numFace].Deleted);
00623 if(TmpFaces[numFace].hasVertex(edgeV2))
00624 deletedFaces.push_back(numFace);
00625 }
00626
00627
00628
00629
00630
00631
00632 for(sint attId=0;attId<NumAttributes;attId++)
00633 {
00634
00635
00636 for(i=0;i<(sint)deletedFaces.size();i++)
00637 {
00638 CMRMFaceBuild &face= TmpFaces[deletedFaces[i]];
00639
00640 CVectorH &w0= TmpAttributes[attId][ face.getAssociatedWedge(attId, edgeV1) ].Current;
00641 CVectorH &w1= TmpAttributes[attId][ face.getAssociatedWedge(attId, edgeV2) ].Current;
00642
00643 CVectorH &itp= face.InterpolatedAttribute;
00644 itp.x= w0.x*(1-InterValue) + w1.x*InterValue;
00645 itp.y= w0.y*(1-InterValue) + w1.y*InterValue;
00646 itp.z= w0.z*(1-InterValue) + w1.z*InterValue;
00647 itp.w= w0.w*(1-InterValue) + w1.w*InterValue;
00648
00649 for (j = 0; j < (sint)face.BSInterpolated.size(); ++j)
00650 {
00651 CVectorH &w0 = TmpAttributes[attId][face.getAssociatedWedge(attId, edgeV1)].BSCurrent[j];
00652 CVectorH &w1 = TmpAttributes[attId][face.getAssociatedWedge(attId, edgeV2)].BSCurrent[j];
00653 CVectorH &itb = face.BSInterpolated[j];
00654 itb.x = w0.x*(1-InterValue) + w1.x*InterValue;
00655 itb.y = w0.y*(1-InterValue) + w1.y*InterValue;
00656 itb.z = w0.z*(1-InterValue) + w1.z*InterValue;
00657 itb.w = w0.w*(1-InterValue) + w1.w*InterValue;
00658 }
00659 }
00660
00661
00662
00663
00664 vector<sint> wedges;
00665
00666 for(i=0;i<(sint)neighboorFaces.size();i++)
00667 {
00668 CMRMFaceBuild &face= TmpFaces[neighboorFaces[i]];
00669 sint numWedge;
00670
00671 numWedge= face.getAssociatedWedge(attId, edgeV1);
00672 if(numWedge>=0 && !findElement(wedges, numWedge))
00673 wedges.push_back(numWedge);
00674
00675 numWedge= face.getAssociatedWedge(attId, edgeV2);
00676 if(numWedge>=0 && !findElement(wedges, numWedge))
00677 wedges.push_back(numWedge);
00678 }
00679
00680
00681
00682
00683
00684 for(i=0;i<(sint)wedges.size();i++)
00685 {
00686 sint numWedge= wedges[i];
00687 CMRMAttribute &wedge= TmpAttributes[attId][numWedge];
00688
00689 wedge.NbSharedFaces=0;
00690 wedge.Shared=false;
00691
00692
00693 for(j=0;j<(sint)neighboorFaces.size();j++)
00694 {
00695 if(TmpFaces[neighboorFaces[j]].hasWedge(attId, numWedge))
00696 wedge.NbSharedFaces++;
00697 }
00698
00699
00700 for(j=0;j<(sint)deletedFaces.size();j++)
00701 {
00702 if(TmpFaces[deletedFaces[j]].hasWedge(attId, numWedge))
00703 {
00704 wedge.NbSharedFaces--;
00705 wedge.Shared=true;
00706 wedge.InterpolatedFace=deletedFaces[j];
00707 }
00708 }
00709 }
00710
00711
00712
00713
00714
00715
00716 for(i=0;i<(sint)wedges.size();i++)
00717 {
00718 sint numWedge= wedges[i];
00719 CMRMAttribute &wedge= TmpAttributes[attId][numWedge];
00720
00721
00722 if(!wedge.Shared)
00723 {
00724
00725
00726 }
00727 else
00728 {
00729
00730 if(wedge.NbSharedFaces==0)
00731 {
00732 wedge.CollapsedTo=-2;
00733
00734 }
00735 else
00736 {
00737 CMRMFaceBuild &face= TmpFaces[wedge.InterpolatedFace];
00738
00739
00740 wedge.Current= face.InterpolatedAttribute;
00741 wedge.BSCurrent = face.BSInterpolated;
00742
00743
00744
00745 if( numWedge==face.getAssociatedWedge(attId, edgeV2) &&
00746 faceShareWedges(&face, attId, edgeV1, edgeV2) )
00747 {
00748 wedge.CollapsedTo= face.getAssociatedWedge(attId, edgeV1);
00749 }
00750 }
00751 }
00752 }
00753
00754 }
00755
00756
00757
00758
00759
00760 for(i=0;i<(sint)deletedFaces.size();i++)
00761 {
00762 sint numFace= deletedFaces[i];
00763 TmpFaces[numFace].Deleted=true;
00764
00765
00766 removeFaceFromEdgeList(TmpFaces[numFace]);
00767
00768 TmpFaces[numFace].invalidAllIts(EdgeCollapses);
00769
00770
00771
00772 deleteElement( Vertex1.SharedFaces, numFace);
00773 deleteElement( Vertex2.SharedFaces, numFace);
00774 }
00775
00776
00777
00778 for(i=0;i<(sint)neighboorFaces.size();i++)
00779 {
00780 CMRMFaceBuild &face=TmpFaces[neighboorFaces[i]];
00781
00782
00783 if(face.Corner[0].Vertex ==edgeV2) face.Corner[0].Vertex=edgeV1;
00784 if(face.Corner[1].Vertex ==edgeV2) face.Corner[1].Vertex=edgeV1;
00785 if(face.Corner[2].Vertex ==edgeV2) face.Corner[2].Vertex=edgeV1;
00786
00787
00788
00789 for(sint attId=0;attId<NumAttributes;attId++)
00790 {
00791 sint newWedge;
00792 newWedge= TmpAttributes[attId][ face.Corner[0].Attributes[attId] ].CollapsedTo;
00793 if(newWedge>=0) face.Corner[0].Attributes[attId]= newWedge;
00794 newWedge= TmpAttributes[attId][ face.Corner[1].Attributes[attId] ].CollapsedTo;
00795 if(newWedge>=0) face.Corner[1].Attributes[attId]= newWedge;
00796 newWedge= TmpAttributes[attId][ face.Corner[2].Attributes[attId] ].CollapsedTo;
00797 if(newWedge>=0) face.Corner[2].Attributes[attId]= newWedge;
00798 }
00799
00800
00801
00802
00803
00804 }
00805
00806
00807
00808 Vertex1.SharedFaces.insert(Vertex1.SharedFaces.end(), Vertex2.SharedFaces.begin(),
00809 Vertex2.SharedFaces.end());
00810
00811
00812 return deletedFaces.size();
00813 }
00814
00815
00816
00817 sint CMRMBuilder::followVertex(sint i)
00818 {
00819 CMRMVertex &vert=TmpVertices[i];
00820 if(vert.CollapsedTo>=0)
00821 return followVertex(vert.CollapsedTo);
00822 else
00823 return i;
00824 }
00825
00826 sint CMRMBuilder::followWedge(sint attribId, sint i)
00827 {
00828 CMRMAttribute &wedge= TmpAttributes[attribId][i];
00829 if(wedge.CollapsedTo>=0)
00830 return followWedge(attribId, wedge.CollapsedTo);
00831 else
00832 return i;
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 CMRMBuilder::CMRMBuilder()
00845 {
00846 NumAttributes= 0;
00847 _Skinned= false;
00848 _HasMeshInterfaces= false;
00849 }
00850
00851
00852 void CMRMBuilder::init(const CMRMMesh &baseMesh)
00853 {
00854 sint i, attId;
00855
00856
00857
00858 TmpVertices.clear();
00859 for(attId=0;attId<NL3D_MRM_MAX_ATTRIB;attId++)
00860 {
00861 TmpAttributes[attId].clear();
00862 }
00863 TmpFaces.clear();
00864 EdgeCollapses.clear();
00865
00866
00867
00868 NumAttributes= baseMesh.NumAttributes;
00869 TmpVertices.resize(baseMesh.Vertices.size());
00870 for(attId=0;attId<NumAttributes;attId++)
00871 {
00872 TmpAttributes[attId].resize(baseMesh.Attributes[attId].size());
00873 }
00874 TmpFaces.resize(baseMesh.Faces.size());
00875
00876
00877
00878 for(i=0;i<(sint)baseMesh.Vertices.size();i++)
00879 {
00880 TmpVertices[i].Current= TmpVertices[i].Original= baseMesh.Vertices[i];
00881 TmpVertices[i].BSCurrent.resize(baseMesh.BlendShapes.size());
00882 for(uint32 j = 0; j <baseMesh.BlendShapes.size() ;++j)
00883 TmpVertices[i].BSCurrent[j]= baseMesh.BlendShapes[j].Vertices[i];
00884 if(_Skinned)
00885 TmpVertices[i].CurrentSW= TmpVertices[i].OriginalSW= baseMesh.SkinWeights[i];
00886 if(_HasMeshInterfaces)
00887 TmpVertices[i].InterfaceLink= baseMesh.InterfaceLinks[i];
00888 }
00889 for(attId=0;attId<NumAttributes;attId++)
00890 {
00891 for(i=0;i<(sint)baseMesh.Attributes[attId].size();i++)
00892 {
00893 TmpAttributes[attId][i].Current= TmpAttributes[attId][i].Original=
00894 baseMesh.Attributes[attId][i];
00895 TmpAttributes[attId][i].BSCurrent.resize(baseMesh.BlendShapes.size());
00896 for(uint32 j = 0; j <baseMesh.BlendShapes.size() ;++j)
00897 TmpAttributes[attId][i].BSCurrent[j]= baseMesh.BlendShapes[j].Attributes[attId][i];
00898 }
00899 }
00900 for(i=0;i<(sint)baseMesh.Faces.size();i++)
00901 {
00902 TmpFaces[i]= baseMesh.Faces[i];
00903 TmpFaces[i].BSInterpolated.resize(baseMesh.BlendShapes.size());
00904 }
00905
00906
00907
00908 for(i=0;i<(sint)TmpFaces.size();i++)
00909 {
00910 CMRMFaceBuild &face= TmpFaces[i];
00911
00912 TmpVertices[face.Corner[0].Vertex].SharedFaces.push_back(i);
00913 TmpVertices[face.Corner[1].Vertex].SharedFaces.push_back(i);
00914 TmpVertices[face.Corner[2].Vertex].SharedFaces.push_back(i);
00915 }
00916
00917
00918
00919 for(i=0;i<(sint)TmpFaces.size();i++)
00920 {
00921 CMRMFaceBuild &f= TmpFaces[i];
00922
00923 f. ValidIt0= true;
00924 f. ValidIt1= true;
00925 f. ValidIt2= true;
00926 insertFaceIntoEdgeList(f);
00927 }
00928 }
00929
00930 void CMRMBuilder::collapseEdges(sint nWantedFaces)
00931 {
00932 ItEdgeMap EdgeIt;
00933
00934 sint nCurrentFaces=TmpFaces.size();
00935 sint bug0=0,bug2=0,bug3=0;
00936
00937 while(nCurrentFaces>nWantedFaces)
00938 {
00939 bug0++;
00940 EdgeIt= EdgeCollapses.begin();
00941
00942 if(EdgeIt== EdgeCollapses.end())
00943 break;
00944
00945
00946
00947 CMRMEdge edge=(*EdgeIt).second;
00948
00949
00950 if(TmpVertices[ edge.v0 ].CollapsedTo>=0
00951 || TmpVertices[ edge.v1 ].CollapsedTo>=0)
00952 {
00953
00954 CMRMFaceBuild &f= *(EdgeIt->second.Face);
00955 nlassert(f.validEdgeIt(EdgeIt->second));
00956 f.invalidEdgeIt(EdgeIt->second, EdgeCollapses);
00957 EdgeCollapses.erase(EdgeIt);
00958 bug2++;
00959 continue;
00960 }
00961
00962
00963 if(edge.v0==edge.v1)
00964 {
00965 CMRMFaceBuild &f= *(EdgeIt->second.Face);
00966 nlassert(f.validEdgeIt(EdgeIt->second));
00967 f.invalidEdgeIt(EdgeIt->second, EdgeCollapses);
00968 EdgeCollapses.erase(EdgeIt);
00969 bug3++;
00970 continue;
00971 }
00972
00973
00974
00975
00976 sint vertexCollapsed= edge.v0;
00977 nCurrentFaces-= collapseEdge(edge);
00978
00979
00980
00981
00982 CMRMVertex &vert=TmpVertices[vertexCollapsed];
00983 sint i;
00984
00985 for(i=0;i<(sint)vert.SharedFaces.size();i++)
00986 {
00987 CMRMFaceBuild &f= TmpFaces[vert.SharedFaces[i]];
00988 removeFaceFromEdgeList(f);
00989 insertFaceIntoEdgeList(f);
00990 }
00991
00992 }
00993 }
00994
00995 void CMRMBuilder::saveCoarserMesh(CMRMMesh &coarserMesh)
00996 {
00997 sint i,attId,index;
00998
00999 coarserMesh.Vertices.clear();
01000 coarserMesh.SkinWeights.clear();
01001 coarserMesh.InterfaceLinks.clear();
01002 for(attId=0;attId<NL3D_MRM_MAX_ATTRIB;attId++)
01003 {
01004 coarserMesh.Attributes[attId].clear();
01005 }
01006 coarserMesh.Faces.clear();
01007 coarserMesh.NumAttributes= NumAttributes;
01008
01009
01010
01011 index=0;
01012 for(i=0;i<(sint)TmpVertices.size();i++)
01013 {
01014 CMRMVertex &vert=TmpVertices[i];
01015 if(vert.CollapsedTo==-1)
01016 {
01017 vert.CoarserIndex=index;
01018 coarserMesh.Vertices.push_back(vert.Current);
01019 if(_Skinned)
01020 coarserMesh.SkinWeights.push_back(vert.CurrentSW);
01021 if(_HasMeshInterfaces)
01022 coarserMesh.InterfaceLinks.push_back(vert.InterfaceLink);
01023
01024 index++;
01025 }
01026 else
01027 vert.CoarserIndex=-1;
01028 }
01029
01030
01031
01032
01033 for(attId=0;attId<NumAttributes;attId++)
01034 {
01035 index=0;
01036 for(i=0;i<(sint)TmpAttributes[attId].size();i++)
01037 {
01038 CMRMAttribute &wedge= TmpAttributes[attId][i];
01039 if(wedge.CollapsedTo==-1)
01040 {
01041 wedge.CoarserIndex=index;
01042 coarserMesh.Attributes[attId].push_back(wedge.Current);
01043 index++;
01044 }
01045 else if(wedge.CollapsedTo==-2)
01046 {
01047
01048
01049
01050
01051 wedge.CoarserIndex=index;
01052 coarserMesh.Attributes[attId].push_back(wedge.Current);
01053 index++;
01054 }
01055 else
01056 wedge.CoarserIndex=-1;
01057 }
01058 }
01059
01060
01061
01062 for(i=0;i<(sint)TmpFaces.size();i++)
01063 {
01064 CMRMFaceBuild &face=TmpFaces[i];
01065 if(!face.Deleted)
01066 {
01067 CMRMFace newFace;
01068
01069 newFace.MaterialId= face.MaterialId;
01070 for(sint j=0;j<3;j++)
01071 {
01072
01073 newFace.Corner[j].Vertex= TmpVertices[face.Corner[j].Vertex].CoarserIndex;
01074 nlassert(newFace.Corner[j].Vertex>=0);
01075
01076 for(attId=0;attId<NumAttributes;attId++)
01077 {
01078 sint oldidx= face.Corner[j].Attributes[attId];
01079 newFace.Corner[j].Attributes[attId]= TmpAttributes[attId][oldidx].CoarserIndex;
01080 nlassert(newFace.Corner[j].Attributes[attId]>=0);
01081 }
01082
01083 }
01084
01085 coarserMesh.Faces.push_back(newFace);
01086 }
01087 }
01088
01089 }
01090
01091
01092
01093 void CMRMBuilder::makeLODMesh(CMRMMeshGeom &lodMesh)
01094 {
01095 sint i,j,attId,index,coidx;
01096
01097
01098 for(i=0;i<(sint)lodMesh.CoarserFaces.size();i++)
01099 {
01100 CMRMFace &face= lodMesh.CoarserFaces[i];
01101
01102
01103 for(j=0;j<3;j++)
01104 {
01105
01106
01107 index= face.Corner[j].Vertex;
01108
01109 coidx= TmpVertices[index].CoarserIndex;
01110
01111 if(coidx==-1)
01112 {
01113
01114 index= followVertex(index);
01115
01116 coidx= TmpVertices[index].CoarserIndex;
01117 nlassert(coidx>=0);
01118 }
01119
01120 face.Corner[j].Vertex= coidx;
01121
01122
01123
01124 for(attId=0;attId<NumAttributes;attId++)
01125 {
01126 index= face.Corner[j].Attributes[attId];
01127 coidx= TmpAttributes[attId][index].CoarserIndex;
01128 if(coidx==-1)
01129 {
01130 index= followWedge(attId, index);
01131 coidx= TmpAttributes[attId][index].CoarserIndex;
01132 nlassert(coidx>=0);
01133 }
01134 face.Corner[j].Attributes[attId]= coidx;
01135 }
01136 }
01137 }
01138
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188 void CMRMBuilder::makeCoarserBS (vector<CMRMBlendShape> &csBsMeshs)
01189 {
01190 uint32 i, k;
01191 sint32 nSizeVert, nSizeAttr, attId;
01192
01193
01194 nSizeVert = 0;
01195 for (i = 0; i < TmpVertices.size(); ++i)
01196 if(TmpVertices[i].CoarserIndex > nSizeVert)
01197 nSizeVert = TmpVertices[i].CoarserIndex;
01198 ++nSizeVert;
01199
01200 for (k = 0; k < csBsMeshs.size(); ++k)
01201 {
01202 CMRMBlendShape &rBsCoarserMesh = csBsMeshs[k];
01203
01204 rBsCoarserMesh.Vertices.resize (nSizeVert);
01205 rBsCoarserMesh.NumAttributes = NumAttributes;
01206
01207
01208 for(i = 0; i < TmpVertices.size(); ++i)
01209 {
01210 CMRMVertex &vert = TmpVertices[i];
01211 if (vert.CoarserIndex != -1)
01212 {
01213 rBsCoarserMesh.Vertices[vert.CoarserIndex] = vert.BSCurrent[k];
01214 }
01215 }
01216
01217 for (attId = 0; attId < NumAttributes; attId++)
01218 {
01219
01220 nSizeAttr = 0;
01221 for(i = 0; i < TmpAttributes[attId].size(); i++)
01222 if (TmpAttributes[attId][i].CoarserIndex > nSizeAttr)
01223 nSizeAttr = TmpAttributes[attId][i].CoarserIndex;
01224 ++nSizeAttr;
01225
01226 rBsCoarserMesh.Attributes[attId].resize (nSizeAttr);
01227
01228 for (i = 0; i < TmpAttributes[attId].size(); i++)
01229 {
01230 CMRMAttribute &wedge = TmpAttributes[attId][i];
01231 if (wedge.CoarserIndex != -1)
01232 {
01233 rBsCoarserMesh.Attributes[attId][wedge.CoarserIndex] = wedge.BSCurrent[k];
01234 }
01235 }
01236 }
01237 }
01238 }
01239
01240
01241 void CMRMBuilder::makeFromMesh(const CMRMMesh &baseMesh, CMRMMeshGeom &lodMesh, CMRMMesh &coarserMesh, sint nWantedFaces)
01242 {
01243
01244 init(baseMesh);
01245
01246
01247 collapseEdges(nWantedFaces);
01248
01249
01250 saveCoarserMesh(coarserMesh);
01251
01252 coarserMesh.BlendShapes.resize(baseMesh.BlendShapes.size());
01253 makeCoarserBS(coarserMesh.BlendShapes);
01254
01255
01256 lodMesh= baseMesh;
01257 makeLODMesh(lodMesh);
01258
01259
01260 }
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 void CMRMBuilder::buildAllLods(const CMRMMesh &baseMesh, std::vector<CMRMMeshGeom> &lodMeshs,
01273 uint nWantedLods, uint divisor)
01274 {
01275 sint nFaces= baseMesh.Faces.size();
01276 sint nBaseFaces;
01277 sint i;
01278 CMRMMesh srcMesh = baseMesh;
01279
01280
01281 nBaseFaces=nFaces/divisor;
01282 nBaseFaces=max(nBaseFaces,4);
01283
01284
01285 nlassert(nWantedLods>=1);
01286 lodMeshs.resize(nWantedLods);
01287
01288
01289 if(nWantedLods==1)
01290 {
01291 _CurrentLodComputed= 0;
01292 init(baseMesh);
01293 }
01294
01295
01296 for(i=nWantedLods-1;i>0;i--)
01297 {
01298 sint nbWantedFaces;
01299
01300
01301 _CurrentLodComputed= i;
01302
01303
01304 nbWantedFaces= nBaseFaces + (nFaces-nBaseFaces) * (i-1)/(nWantedLods-1);
01305 nbWantedFaces=max(nbWantedFaces,4);
01306
01307
01308 CMRMMesh csMesh;
01309
01310 makeFromMesh(srcMesh, lodMeshs[i], csMesh, nbWantedFaces);
01311
01312
01313 srcMesh = csMesh;
01314 }
01315
01316 lodMeshs[0]= srcMesh;
01317 }
01318
01319
01320
01321 void CMRMBuilder::buildFinalMRM(std::vector<CMRMMeshGeom> &lodMeshs, CMRMMeshFinal &finalMRM)
01322 {
01323 sint i,j;
01324 sint lodId, attId;
01325 sint nLods= lodMeshs.size();
01326
01327
01328
01329 finalMRM.reset();
01330 finalMRM.NumAttributes= NumAttributes;
01331 finalMRM.Skinned= _Skinned;
01332 CMRMMeshFinal::CWedge::NumAttributesToCompare= NumAttributes;
01333 CMRMMeshFinal::CWedge::CompareSkinning= _Skinned;
01334 finalMRM.Lods.resize(nLods);
01335
01336
01337
01338
01339
01340 for(lodId=0; lodId<nLods; lodId++)
01341 {
01342 CMRMMeshGeom &lodMesh= lodMeshs[lodId];
01343 CMRMMeshGeom &lodMeshPrec= lodMeshs[lodId==0?0:lodId-1];
01344
01345 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01346 {
01347
01348 CMRMFace &face= lodMesh.Faces[i];
01349
01350 CMRMFace &faceCoarser= lodMesh.CoarserFaces[i];
01351
01352 for(j=0;j<3;j++)
01353 {
01354 CMRMCorner &corner= face.Corner[j];
01355 CMRMCorner &cornerCoarser= faceCoarser.Corner[j];
01356
01357 CMRMMeshFinal::CWedge wedgeStart;
01358 CMRMMeshFinal::CWedge wedgeEnd;
01359
01360
01361 wedgeStart.Vertex= lodMesh.Vertices[corner.Vertex];
01362 if(_Skinned)
01363 wedgeStart.VertexSkin= lodMesh.SkinWeights[corner.Vertex];
01364 for(attId=0; attId<NumAttributes; attId++)
01365 {
01366 wedgeStart.Attributes[attId]= lodMesh.Attributes[attId][corner.Attributes[attId]];
01367 }
01368
01369
01370 if(lodId>0)
01371 {
01372
01373 wedgeEnd.Vertex= lodMeshPrec.Vertices[cornerCoarser.Vertex];
01374 if(_Skinned)
01375 wedgeEnd.VertexSkin= lodMeshPrec.SkinWeights[cornerCoarser.Vertex];
01376 for(attId=0; attId<NumAttributes; attId++)
01377 {
01378 wedgeEnd.Attributes[attId]= lodMeshPrec.Attributes[attId][cornerCoarser.Attributes[attId]];
01379 }
01380 }
01381 else
01382 {
01383
01384 wedgeEnd= wedgeStart;
01385 }
01386
01387
01388 sint wedgeStartId= finalMRM.findInsertWedge(wedgeStart);
01389 sint wedgeEndId= finalMRM.findInsertWedge(wedgeEnd);
01390
01391
01392 corner.WedgeStartId= wedgeStartId;
01393 corner.WedgeEndId= wedgeEndId;
01394 }
01395 }
01396
01397
01398 finalMRM.Lods[lodId].NWedges= finalMRM.Wedges.size();
01399 }
01400
01401
01402
01403
01404
01405 sint sglmGeom;
01406
01407 sint sglmGeomMax= 0;
01408
01409
01410 for(lodId=1; lodId<nLods; lodId++)
01411 {
01412 CMRMMeshGeom &lodMesh= lodMeshs[lodId];
01413
01414
01415 _GeomMap.clear();
01416 sglmGeom= 0;
01417
01418
01419 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01420 {
01421
01422 CMRMFace &face= lodMesh.Faces[i];
01423
01424 for(j=0;j<3;j++)
01425 {
01426 CMRMCorner &corner= face.Corner[j];
01427
01428
01429 if(corner.WedgeStartId != corner.WedgeEndId)
01430 {
01431
01432 CMRMWedgeGeom geom;
01433 geom.Start= corner.WedgeStartId;
01434 geom.End= corner.WedgeEndId;
01435 sint geomDest= sglmGeom;
01436
01437 TGeomMap::const_iterator it= _GeomMap.find(geom);
01438 if(it == _GeomMap.end())
01439 {
01440 _GeomMap.insert( make_pair(geom, geomDest) );
01441 sglmGeom++;
01442 }
01443 else
01444 geomDest= it->second;
01445
01446
01447 corner.WedgeGeomId= geomDest;
01448 }
01449 }
01450 }
01451
01452
01453 sglmGeomMax= max(sglmGeomMax, sglmGeom);
01454 }
01455
01456
01457
01458 finalMRM.NGeomSpace= sglmGeomMax;
01459
01460
01461
01462
01463
01464 finalMRM.Wedges.insert(finalMRM.Wedges.begin(), sglmGeomMax, CMRMMeshFinal::CWedge());
01465
01466
01467 for(lodId=0; lodId<nLods; lodId++)
01468 {
01469 CMRMMeshGeom &lodMesh= lodMeshs[lodId];
01470
01471
01472 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01473 {
01474
01475 CMRMFace &face= lodMesh.Faces[i];
01476
01477 for(j=0;j<3;j++)
01478 {
01479 CMRMCorner &corner= face.Corner[j];
01480
01481
01482 corner.WedgeStartId+= sglmGeomMax;
01483 corner.WedgeEndId+= sglmGeomMax;
01484 }
01485 }
01486
01487
01488 finalMRM.Lods[lodId].NWedges+= sglmGeomMax;
01489 }
01490
01491
01492
01493
01494
01495 for(lodId=0; lodId<nLods; lodId++)
01496 {
01497 CMRMMeshGeom &lodMesh= lodMeshs[lodId];
01498 CMRMMeshFinal::CLod &lodDest= finalMRM.Lods[lodId];
01499
01500
01501 lodDest.Faces.resize(lodMesh.Faces.size());
01502
01503
01504 _GeomMap.clear();
01505
01506
01507 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01508 {
01509
01510 CMRMFace &face= lodMesh.Faces[i];
01511
01512 CMRMMeshFinal::CFace &faceDest= lodDest.Faces[i];
01513
01514 faceDest.MaterialId= face.MaterialId;
01515
01516
01517 for(j=0;j<3;j++)
01518 {
01519 CMRMCorner &corner= face.Corner[j];
01520
01521
01522 if(corner.WedgeStartId != corner.WedgeEndId)
01523 {
01524
01525 faceDest.WedgeId[j]= corner.WedgeGeomId;
01526
01527
01528 CMRMWedgeGeom geom;
01529 geom.Start= corner.WedgeStartId;
01530 geom.End= corner.WedgeEndId;
01531
01532 TGeomMap::const_iterator it= _GeomMap.find(geom);
01533 if(it == _GeomMap.end())
01534 {
01535
01536 _GeomMap.insert( make_pair(geom, corner.WedgeGeomId) );
01537
01538 nlassert( corner.WedgeGeomId==(sint)lodDest.Geomorphs.size() );
01539 lodDest.Geomorphs.push_back(geom);
01540 }
01541 }
01542 else
01543 {
01544
01545 faceDest.WedgeId[j]= corner.WedgeStartId;
01546 }
01547 }
01548 }
01549 }
01550
01551
01552
01553
01554
01555 if(_Skinned)
01556 {
01557 for(i=finalMRM.NGeomSpace; i<(sint)finalMRM.Wedges.size();i++)
01558 {
01559 CMRMMeshFinal::CWedge &wedge= finalMRM.Wedges[i];
01560 for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
01561 {
01562 if(wedge.VertexSkin.Weights[j]==0)
01563 break;
01564 }
01565 nlassert(j>0);
01566 wedge.NSkinMatUsed= j;
01567 }
01568 }
01569
01570
01571 finalMRM.MRMBlendShapesFinals.resize (lodMeshs[0].BlendShapes.size());
01572 for (lodId = 0; lodId < nLods; ++lodId)
01573 {
01574 CMRMMeshGeom &lodMesh= lodMeshs[lodId];
01575 CMRMMeshGeom &lodMeshPrec= lodMeshs[lodId==0?0:lodId-1];
01576
01577
01578 for (i = 0; i < (sint)lodMesh.Faces.size(); ++i)
01579 {
01580
01581 CMRMFace &face = lodMesh.Faces[i];
01582
01583 CMRMFace &faceCoarser = lodMesh.CoarserFaces[i];
01584
01585 for (j = 0; j < 3; ++j)
01586 {
01587 CMRMCorner &corner = face.Corner[j];
01588 CMRMCorner &cornerCoarser = faceCoarser.Corner[j];
01589
01590 sint startDestIndex = corner.WedgeStartId;
01591
01592 for (sint k = 0; k < (sint)finalMRM.MRMBlendShapesFinals.size(); ++k)
01593 {
01594 CMRMMeshFinal::CMRMBlendShapeFinal &rBSFinal = finalMRM.MRMBlendShapesFinals[k];
01595
01596 rBSFinal.Wedges.resize (finalMRM.Wedges.size());
01597
01598 rBSFinal.Wedges[startDestIndex].Vertex = lodMesh.BlendShapes[k].Vertices[corner.Vertex];
01599 for (attId = 0; attId < NumAttributes; ++attId)
01600 {
01601 rBSFinal.Wedges[startDestIndex].Attributes[attId] = lodMesh.BlendShapes[k].Attributes[attId][corner.Attributes[attId]];
01602 }
01603
01604
01605 if(lodId>0 && corner.WedgeStartId != corner.WedgeEndId)
01606 {
01607 sint endDestIndex = corner.WedgeEndId;
01608
01609 rBSFinal.Wedges[endDestIndex].Vertex = lodMeshPrec.BlendShapes[k].Vertices[cornerCoarser.Vertex];
01610 for (attId = 0; attId < NumAttributes; ++attId)
01611 {
01612 rBSFinal.Wedges[endDestIndex].Attributes[attId] = lodMeshPrec.BlendShapes[k].Attributes[attId][cornerCoarser.Attributes[attId]];
01613 }
01614 }
01615 }
01616
01617 }
01618 }
01619 }
01620 }
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 sint CMRMBuilder::findInsertAttributeInBaseMesh(CMRMMesh &baseMesh, sint attId, sint vertexId, const CVectorH &att)
01634 {
01635
01636 CAttributeKey key;
01637 key.VertexId= vertexId;
01638 key.Attribute= att;
01639 TAttributeMap::iterator it= _AttributeMap[attId].find(key);
01640
01641
01642 if(it==_AttributeMap[attId].end())
01643 {
01644 sint idx= baseMesh.Attributes[attId].size();
01645
01646 baseMesh.Attributes[attId].push_back(att);
01647
01648 _AttributeMap[attId].insert(make_pair(key, idx));
01649 return idx;
01650 }
01651 else
01652 {
01653
01654 return it->second;
01655 }
01656 }
01657
01658
01659
01660 sint CMRMBuilder::findInsertNormalInBaseMesh(CMRMMesh &baseMesh, sint attId, sint vertexId, const CVector &normal)
01661 {
01662 CVectorH att;
01663 att= normal;
01664 att.w= 0;
01665 return findInsertAttributeInBaseMesh(baseMesh, attId, vertexId, att);
01666 }
01667
01668
01669
01670 sint CMRMBuilder::findInsertColorInBaseMesh(CMRMMesh &baseMesh, sint attId, sint vertexId, CRGBA col)
01671 {
01672 CVectorH att;
01673 att.x= col.R;
01674 att.y= col.G;
01675 att.z= col.B;
01676 att.w= col.A;
01677 return findInsertAttributeInBaseMesh(baseMesh, attId, vertexId, att);
01678 }
01679
01680
01681
01682 sint CMRMBuilder::findInsertUvwInBaseMesh(CMRMMesh &baseMesh, sint attId, sint vertexId, const NLMISC::CUVW &uvw)
01683 {
01684 CVectorH att;
01685 att.x= uvw.U;
01686 att.y= uvw.V;
01687 att.z= uvw.W;
01688 att.w= 0;
01689 return findInsertAttributeInBaseMesh(baseMesh, attId, vertexId, att);
01690 }
01691
01692
01693
01694 CRGBA CMRMBuilder::attToColor(const CVectorH &att) const
01695 {
01696 CRGBA ret;
01697 float tmp;
01698 tmp= att.x; clamp(tmp, 0, 255);
01699 ret.R= (uint8)(uint)tmp;
01700 tmp= att.y; clamp(tmp, 0, 255);
01701 ret.G= (uint8)(uint)tmp;
01702 tmp= att.z; clamp(tmp, 0, 255);
01703 ret.B= (uint8)(uint)tmp;
01704 tmp= att.w; clamp(tmp, 0, 255);
01705 ret.A= (uint8)(uint)tmp;
01706
01707 return ret;
01708 }
01709
01710
01711
01712 NLMISC::CUVW CMRMBuilder::attToUvw(const CVectorH &att) const
01713 {
01714 return CUVW(att.x, att.y, att.z);
01715 }
01716
01717
01718
01719 uint32 CMRMBuilder::buildMrmBaseMesh(const CMesh::CMeshBuild &mbuild, CMRMMesh &baseMesh)
01720 {
01721 sint i,j,k;
01722 sint nFaces;
01723 sint attId;
01724
01725 uint32 retVbFlags= CVertexBuffer::PositionFlag;
01726
01727
01728
01729 baseMesh= CMRMMesh();
01730
01731 for(attId=0; attId<NL3D_MRM_MAX_ATTRIB;attId++)
01732 _AttributeMap[attId].clear();
01733
01734
01735
01736
01737
01738 if(mbuild.VertexFlags & CVertexBuffer::NormalFlag)
01739 {
01740 baseMesh.NumAttributes++;
01741 retVbFlags|= CVertexBuffer::NormalFlag;
01742 }
01743 if(mbuild.VertexFlags & CVertexBuffer::PrimaryColorFlag)
01744 {
01745 baseMesh.NumAttributes++;
01746 retVbFlags|= CVertexBuffer::PrimaryColorFlag;
01747 }
01748 if(mbuild.VertexFlags & CVertexBuffer::SecondaryColorFlag)
01749 {
01750 baseMesh.NumAttributes++;
01751 retVbFlags|= CVertexBuffer::SecondaryColorFlag;
01752 }
01753 for(k=0; k<CVertexBuffer::MaxStage;k++)
01754 {
01755 uint flag=CVertexBuffer::TexCoord0Flag<<k;
01756 if(mbuild.VertexFlags & flag)
01757 {
01758 baseMesh.NumAttributes++;
01759 retVbFlags|=flag;
01760 }
01761 }
01762 nlassert(baseMesh.NumAttributes<=NL3D_MRM_MAX_ATTRIB);
01763
01764
01765
01766
01767
01768 baseMesh.Vertices= mbuild.Vertices;
01769
01770 if(_Skinned)
01771 baseMesh.SkinWeights= mbuild.SkinWeights;
01772
01773 if(_HasMeshInterfaces)
01774 baseMesh.InterfaceLinks= mbuild.InterfaceLinks;
01775
01776 nFaces= mbuild.Faces.size();
01777 baseMesh.Faces.resize(nFaces);
01778 for(i=0; i<nFaces; i++)
01779 {
01780
01781 baseMesh.Faces[i].MaterialId= mbuild.Faces[i].MaterialId;
01782
01783 for(j=0; j<3; j++)
01784 {
01785 baseMesh.Faces[i].Corner[j].Vertex= mbuild.Faces[i].Corner[j].Vertex;
01786 }
01787 }
01788
01789
01790
01791
01792 for(i=0; i<nFaces; i++)
01793 {
01794 for(j=0; j<3; j++)
01795 {
01796 const CMesh::CCorner &srcCorner= mbuild.Faces[i].Corner[j];
01797 CMRMCorner &destCorner= baseMesh.Faces[i].Corner[j];
01798 attId= 0;
01799
01800
01801
01802
01803 if(mbuild.VertexFlags & CVertexBuffer::NormalFlag)
01804 {
01805 destCorner.Attributes[attId]= findInsertNormalInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Normal);
01806 attId++;
01807 }
01808 if(mbuild.VertexFlags & CVertexBuffer::PrimaryColorFlag)
01809 {
01810 destCorner.Attributes[attId]= findInsertColorInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Color);
01811 attId++;
01812 }
01813 if(mbuild.VertexFlags & CVertexBuffer::SecondaryColorFlag)
01814 {
01815 destCorner.Attributes[attId]= findInsertColorInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Specular);
01816 attId++;
01817 }
01818 for(k=0; k<CVertexBuffer::MaxStage;k++)
01819 {
01820 if(mbuild.VertexFlags & (CVertexBuffer::TexCoord0Flag<<k))
01821 {
01822 destCorner.Attributes[attId]= findInsertUvwInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Uvws[k]);
01823 attId++;
01824 }
01825 }
01826 }
01827 }
01828
01829
01830
01831
01832
01833
01834 for(attId=0; attId<NL3D_MRM_MAX_ATTRIB;attId++)
01835 _AttributeMap[attId].clear();
01836
01837 return retVbFlags;
01838 }
01839
01840
01841
01842
01843 CMesh::CSkinWeight CMRMBuilder::normalizeSkinWeight(const CMesh::CSkinWeight &sw) const
01844 {
01845 uint nbMats= 0;
01846 static vector<CTmpVertexWeight> sws;
01847 sws.reserve(NL3D_MESH_SKINNING_MAX_MATRIX);
01848 sws.clear();
01849
01850
01851 uint i;
01852 for(i=0; i<NL3D_MESH_SKINNING_MAX_MATRIX; i++)
01853 {
01854 CTmpVertexWeight vw;
01855 vw.MatrixId= sw.MatrixId[i];
01856 vw.Weight= sw.Weights[i];
01857
01858 if(vw.Weight>0)
01859 {
01860
01861 sws.push_back(vw);
01862 nbMats++;
01863 }
01864 }
01865
01866
01867 sort(sws.begin(), sws.end());
01868
01869
01870
01871 float sumWeight=0;
01872 for(i= 0; i<nbMats; i++)
01873 {
01874 sumWeight+= sws[i].Weight;
01875 }
01876
01877 CMesh::CSkinWeight ret;
01878
01879 for(i= 0; i<nbMats; i++)
01880 {
01881 ret.MatrixId[i]= sws[i].MatrixId;
01882 ret.Weights[i]= sws[i].Weight / sumWeight;
01883 }
01884
01885 return ret;
01886 }
01887
01888
01889
01890 void CMRMBuilder::normalizeBaseMeshSkin(CMRMMesh &baseMesh) const
01891 {
01892 nlassert(_Skinned);
01893
01894 for(uint i=0; i<baseMesh.SkinWeights.size(); i++)
01895 {
01896 baseMesh.SkinWeights[i]= normalizeSkinWeight(baseMesh.SkinWeights[i]);
01897 }
01898 }
01899
01900
01901
01902
01903 void CMRMBuilder::buildMeshBuildMrm(const CMRMMeshFinal &finalMRM, CMeshMRMGeom::CMeshBuildMRM &mbuild, uint32 vbFlags, uint32 nbMats, const CMesh::CMeshBuild &mb)
01904 {
01905 sint i,j,k;
01906 sint attId;
01907
01908
01909 mbuild= CMeshMRMGeom::CMeshBuildMRM();
01910
01911
01912 bool useFormatExt = false;
01913
01914 for (k = 0; k < CVertexBuffer::MaxStage; ++k)
01915 {
01916 if (
01917 (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
01918 && mb.NumCoords[k] != 2)
01919 {
01920 useFormatExt = true;
01921 break;
01922 }
01923 }
01924
01925 uint numTexCoordUsed = 0;
01926
01927
01928 for (k = 0; k < CVertexBuffer::MaxStage; ++k)
01929 {
01930 if (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
01931 {
01932 numTexCoordUsed = k;
01933 }
01934 }
01935
01936 if (!useFormatExt)
01937 {
01938
01939 mbuild.VBuffer.setVertexFormat(vbFlags);
01940 }
01941 else
01942 {
01943 mbuild.VBuffer.clearValueEx();
01944 if (vbFlags & CVertexBuffer::PositionFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Position, CVertexBuffer::Float3);
01945 if (vbFlags & CVertexBuffer::NormalFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Normal, CVertexBuffer::Float3);
01946 if (vbFlags & CVertexBuffer::PrimaryColorFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::PrimaryColor, CVertexBuffer::UChar4);
01947 if (vbFlags & CVertexBuffer::SecondaryColorFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::SecondaryColor, CVertexBuffer::UChar4);
01948 if (vbFlags & CVertexBuffer::WeightFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Weight, CVertexBuffer::Float4);
01949 if (vbFlags & CVertexBuffer::PaletteSkinFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::PaletteSkin, CVertexBuffer::UChar4);
01950 if (vbFlags & CVertexBuffer::FogFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Fog, CVertexBuffer::Float1);
01951
01952 for (k = 0; k < CVertexBuffer::MaxStage; ++k)
01953 {
01954 if (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
01955 {
01956 switch(mb.NumCoords[k])
01957 {
01958 case 2:
01959 mbuild.VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float2);
01960 break;
01961 case 3:
01962 mbuild.VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float3);
01963 break;
01964 default:
01965 nlassert(0);
01966 break;
01967 }
01968 }
01969 }
01970 mbuild.VBuffer.initEx();
01971 }
01972
01973
01974
01975
01976
01977
01978
01979 mbuild.VBuffer.setNumVertices(finalMRM.Wedges.size());
01980
01981 if(_Skinned)
01982 mbuild.SkinWeights.resize(finalMRM.Wedges.size());
01983
01984
01985 for(i=0; i<(sint)finalMRM.Wedges.size(); i++)
01986 {
01987 const CMRMMeshFinal::CWedge &wedge= finalMRM.Wedges[i];
01988
01989
01990 mbuild.VBuffer.setVertexCoord(i, wedge.Vertex);
01991
01992
01993 attId= 0;
01994
01995
01996 if(vbFlags & CVertexBuffer::NormalFlag)
01997 {
01998 mbuild.VBuffer.setNormalCoord(i, wedge.Attributes[attId] );
01999 attId++;
02000 }
02001 if(vbFlags & CVertexBuffer::PrimaryColorFlag)
02002 {
02003 mbuild.VBuffer.setColor(i, attToColor(wedge.Attributes[attId]) );
02004 attId++;
02005 }
02006 if(vbFlags & CVertexBuffer::SecondaryColorFlag)
02007 {
02008 mbuild.VBuffer.setSpecular(i, attToColor(wedge.Attributes[attId]) );
02009 attId++;
02010 }
02011 for(k=0; k<CVertexBuffer::MaxStage;k++)
02012 {
02013 if(vbFlags & (CVertexBuffer::TexCoord0Flag<<k))
02014 {
02015 switch(mb.NumCoords[k])
02016 {
02017 case 2:
02018 mbuild.VBuffer.setTexCoord(i, k, (CUV) attToUvw(wedge.Attributes[attId]) );
02019 break;
02020 case 3:
02021 {
02022 CUVW uvw = attToUvw(wedge.Attributes[attId]);
02023 mbuild.VBuffer.setValueFloat3Ex((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), i, uvw.U, uvw.V, uvw.W);
02024 }
02025 break;
02026 default:
02027 nlassert(0);
02028 break;
02029 }
02030 attId++;
02031 }
02032 }
02033
02034
02035 if(_Skinned)
02036 {
02037 mbuild.SkinWeights[i]= wedge.VertexSkin;
02038 }
02039 }
02040
02041
02042
02043
02044
02045 mbuild.Lods.resize(finalMRM.Lods.size());
02046
02047 for(i=0; i<(sint)finalMRM.Lods.size(); i++)
02048 {
02049 const CMRMMeshFinal::CLod &srcLod= finalMRM.Lods[i];
02050 CMeshMRMGeom::CLod &destLod= mbuild.Lods[i];
02051
02052
02053
02054
02055
02056 destLod.NWedges= srcLod.NWedges;
02057
02058 destLod.Geomorphs= srcLod.Geomorphs;
02059
02060
02061
02062
02063
02064
02065 vector<sint> matCount;
02066
02067 matCount.clear();
02068 matCount.resize(nbMats, 0);
02069
02070 for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02071 {
02072 sint matId= srcLod.Faces[j].MaterialId;
02073 nlassert(matId>=0);
02074 nlassert(matId<(sint)nbMats);
02075
02076 matCount[matId]++;
02077 }
02078
02079
02080 vector<sint> rdrPassIndex;
02081 rdrPassIndex.resize(nbMats);
02082 for(j=0; j<(sint)nbMats; j++)
02083 {
02084 if(matCount[j]==0)
02085 rdrPassIndex[j]= -1;
02086 else
02087 {
02088
02089 sint idRdrPass= destLod.RdrPass.size();
02090 rdrPassIndex[j]= idRdrPass;
02091
02092 destLod.RdrPass.push_back(CMeshMRMGeom::CRdrPass());
02093
02094 destLod.RdrPass[idRdrPass].MaterialId= j;
02095
02096 destLod.RdrPass[idRdrPass].PBlock.reserveTri(matCount[j]);
02097 }
02098 }
02099
02100
02101 for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02102 {
02103 sint matId= srcLod.Faces[j].MaterialId;
02104 sint idRdrPass= rdrPassIndex[matId];
02105
02106 sint w0= srcLod.Faces[j].WedgeId[0];
02107 sint w1= srcLod.Faces[j].WedgeId[1];
02108 sint w2= srcLod.Faces[j].WedgeId[2];
02109 destLod.RdrPass[idRdrPass].PBlock.addTri(w0, w1, w2);
02110 }
02111
02112
02113
02114
02115 for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
02116 {
02117 destLod.InfluencedVertices[j].clear();
02118 }
02119 destLod.MatrixInfluences.clear();
02120 if(_Skinned)
02121 {
02122
02123 set<uint> wedgeInfSet;
02124
02125
02126 for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02127 {
02128 for(k=0; k<3; k++)
02129 {
02130 sint wedgeId= srcLod.Faces[j].WedgeId[k];
02131
02132 if(wedgeId<finalMRM.NGeomSpace)
02133 {
02134
02135
02136 sint wedgeStartId= destLod.Geomorphs[wedgeId].Start;
02137 sint wedgeEndId= destLod.Geomorphs[wedgeId].End;
02138 uint nMatUsedStart= finalMRM.Wedges[wedgeStartId].NSkinMatUsed;
02139 uint nMatUsedEnd= finalMRM.Wedges[wedgeEndId].NSkinMatUsed;
02140
02141
02142 if( wedgeInfSet.insert(wedgeStartId).second )
02143 destLod.InfluencedVertices[nMatUsedStart-1].push_back(wedgeStartId);
02144 if( wedgeInfSet.insert(wedgeEndId).second )
02145 destLod.InfluencedVertices[nMatUsedEnd-1].push_back(wedgeEndId);
02146 }
02147 else
02148 {
02149 uint nMatUsed= finalMRM.Wedges[wedgeId].NSkinMatUsed;
02150
02151
02152
02153 if( wedgeInfSet.insert(wedgeId).second )
02154 destLod.InfluencedVertices[nMatUsed-1].push_back(wedgeId);
02155 }
02156 }
02157 }
02158
02159
02160 for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
02161 {
02162 sort(destLod.InfluencedVertices[j].begin(), destLod.InfluencedVertices[j].end());
02163 }
02164
02165
02166
02167
02168 map<uint, uint> matrixInfMap;
02169
02170
02171 uint iSkinMat;
02172 for(iSkinMat= 0; iSkinMat<NL3D_MESH_SKINNING_MAX_MATRIX; iSkinMat++)
02173 {
02174 for(j= 0; j<(sint)destLod.InfluencedVertices[iSkinMat].size(); j++)
02175 {
02176 uint wedgeId= destLod.InfluencedVertices[iSkinMat][j];
02177
02178
02179 const CMRMMeshFinal::CWedge &wedge= finalMRM.Wedges[wedgeId];
02180
02181 for(k= 0; k<NL3D_MESH_SKINNING_MAX_MATRIX; k++)
02182 {
02183 float matWeight= wedge.VertexSkin.Weights[k];
02184
02185
02186 if((uint)k<iSkinMat+1)
02187 {
02188 nlassert( matWeight>0 );
02189 }
02190 else
02191 {
02192 nlassert( matWeight==0 );
02193 }
02194
02195 if(matWeight>0)
02196 {
02197 uint matId= wedge.VertexSkin.MatrixId[k];
02198
02199
02200 map<uint, uint>::iterator it= matrixInfMap.find(matId);
02201 if( it==matrixInfMap.end() )
02202 {
02203 uint matInfId= destLod.MatrixInfluences.size();
02204 matrixInfMap.insert( make_pair(matId, matInfId) );
02205
02206 destLod.MatrixInfluences.push_back(matId);
02207 }
02208 }
02209 }
02210 }
02211 }
02212
02213 }
02214
02215 }
02216
02217
02218 mbuild.Skinned= _Skinned;
02219
02220
02221
02222 bool useTgSpace = mb.MeshVertexProgram != NULL ? mb.MeshVertexProgram->needTangentSpace() : false;
02223
02224
02226
02227 for (k = 0; k < (sint)mbuild.BlendShapes.size(); ++k)
02228 {
02229 CBlendShape &rBS = mbuild.BlendShapes[k];
02230 sint32 nNbVertVB = finalMRM.Wedges.size();
02231 bool bIsDeltaPos = false;
02232 rBS.deltaPos.resize (nNbVertVB, CVector(0.0f,0.0f,0.0f));
02233 bool bIsDeltaNorm = false;
02234 rBS.deltaNorm.resize (nNbVertVB, CVector(0.0f,0.0f,0.0f));
02235 bool bIsDeltaUV = false;
02236 rBS.deltaUV.resize (nNbVertVB, CUV(0.0f,0.0f));
02237 bool bIsDeltaCol = false;
02238 rBS.deltaCol.resize (nNbVertVB, CRGBAF(0.0f,0.0f,0.0f,0.0f));
02239 bool bIsDeltaTgSpace = false;
02240 if (useTgSpace)
02241 {
02242 rBS.deltaTgSpace.resize(nNbVertVB, CVector::Null);
02243 }
02244
02245 rBS.VertRefs.resize (nNbVertVB, 0xffffffff);
02246
02247 for (i = 0; i < nNbVertVB; i++)
02248 {
02249 const CMRMMeshFinal::CWedge &rWedgeRef = finalMRM.Wedges[i];
02250 const CMRMMeshFinal::CWedge &rWedgeTar = finalMRM.MRMBlendShapesFinals[k].Wedges[i];
02251
02252 CVector delta = rWedgeTar.Vertex - rWedgeRef.Vertex;
02253 CVectorH attr;
02254
02255 if (delta.norm() > 0.001f)
02256 {
02257 rBS.deltaPos[i] = delta;
02258 rBS.VertRefs[i] = i;
02259 bIsDeltaPos = true;
02260 }
02261
02262 attId = 0;
02263 if (vbFlags & CVertexBuffer::NormalFlag)
02264 {
02265 attr = rWedgeRef.Attributes[attId];
02266 CVector NormRef = CVector(attr.x, attr.y, attr.z);
02267 attr = rWedgeTar.Attributes[attId];
02268 CVector NormTar = CVector(attr.x, attr.y, attr.z);
02269 delta = NormTar - NormRef;
02270 if (delta.norm() > 0.001f)
02271 {
02272 rBS.deltaNorm[i] = delta;
02273 rBS.VertRefs[i] = i;
02274 bIsDeltaNorm = true;
02275 }
02276 attId++;
02277 }
02278
02279 if (vbFlags & CVertexBuffer::PrimaryColorFlag)
02280 {
02281 attr = rWedgeRef.Attributes[attId];
02282 CRGBAF RGBARef = CRGBAF(attr.x/255.0f, attr.y/255.0f, attr.z/255.0f, attr.w/255.0f);
02283 attr = rWedgeTar.Attributes[attId];
02284 CRGBAF RGBATar = CRGBAF(attr.x/255.0f, attr.y/255.0f, attr.z/255.0f, attr.w/255.0f);
02285 CRGBAF deltaRGBA = RGBATar - RGBARef;
02286 if ((deltaRGBA.R*deltaRGBA.R + deltaRGBA.G*deltaRGBA.G +
02287 deltaRGBA.B*deltaRGBA.B + deltaRGBA.A*deltaRGBA.A) > 0.0001f)
02288 {
02289 rBS.deltaCol[i] = deltaRGBA;
02290 rBS.VertRefs[i] = i;
02291 bIsDeltaCol = true;
02292 }
02293 attId++;
02294 }
02295
02296 if (vbFlags & CVertexBuffer::SecondaryColorFlag)
02297 {
02298 attId++;
02299 }
02300
02301
02302 if (vbFlags & CVertexBuffer::TexCoord0Flag)
02303 {
02304 attr = rWedgeRef.Attributes[attId];
02305 CUV UVRef = CUV(attr.x, attr.y);
02306 attr = rWedgeTar.Attributes[attId];
02307 CUV UVTar = CUV(attr.x, attr.y);
02308 CUV deltaUV = UVTar - UVRef;
02309 if ((deltaUV.U*deltaUV.U + deltaUV.V*deltaUV.V) > 0.0001f)
02310 {
02311 rBS.deltaUV[i] = deltaUV;
02312 rBS.VertRefs[i] = i;
02313 bIsDeltaUV = true;
02314 }
02315 attId++;
02316 }
02317
02318 if (useTgSpace)
02319 {
02320 attr = rWedgeRef.Attributes[attId];
02321 CVector TgSpaceRef = CVector(attr.x, attr.y, attr.z);
02322 attr = rWedgeTar.Attributes[attId];
02323 CVector TgSpaceTar = CVector(attr.x, attr.y, attr.z);
02324 delta = TgSpaceTar - TgSpaceRef;
02325 if (delta.norm() > 0.001f)
02326 {
02327 rBS.deltaTgSpace[i] = delta;
02328 rBS.VertRefs[i] = i;
02329 bIsDeltaTgSpace = true;
02330 }
02331 attId++;
02332 }
02333
02334 }
02335
02336
02337
02338 sint32 nNbVertUsed = nNbVertVB;
02339 sint32 nDstPos = 0;
02340 for (j = 0; j < nNbVertVB; ++j)
02341 {
02342 if (rBS.VertRefs[j] == 0xffffffff)
02343 {
02344 --nNbVertUsed;
02345 }
02346 else
02347 {
02348 if (nDstPos != j)
02349 {
02350 rBS.VertRefs[nDstPos] = rBS.VertRefs[j];
02351 rBS.deltaPos[nDstPos] = rBS.deltaPos[j];
02352 rBS.deltaNorm[nDstPos] = rBS.deltaNorm[j];
02353 rBS.deltaUV[nDstPos] = rBS.deltaUV[j];
02354 rBS.deltaCol[nDstPos] = rBS.deltaCol[j];
02355 if (useTgSpace)
02356 {
02357 rBS.deltaTgSpace[nDstPos] = rBS.deltaTgSpace[j];
02358 }
02359 }
02360 ++nDstPos;
02361 }
02362 }
02363
02364 if (bIsDeltaPos)
02365 rBS.deltaPos.resize (nNbVertUsed);
02366 else
02367 rBS.deltaPos.resize (0);
02368
02369 if (bIsDeltaNorm)
02370 rBS.deltaNorm.resize (nNbVertUsed);
02371 else
02372 rBS.deltaNorm.resize (0);
02373
02374 if (bIsDeltaUV)
02375 rBS.deltaUV.resize (nNbVertUsed);
02376 else
02377 rBS.deltaUV.resize (0);
02378
02379 if (bIsDeltaCol)
02380 rBS.deltaCol.resize (nNbVertUsed);
02381 else
02382 rBS.deltaCol.resize (0);
02383
02384 if (bIsDeltaTgSpace)
02385 rBS.deltaTgSpace.resize (nNbVertUsed);
02386 else
02387 rBS.deltaTgSpace.resize (0);
02388
02389
02390 rBS.VertRefs.resize (nNbVertUsed);
02391
02392 }
02393 }
02394
02395
02396 void CMRMBuilder::buildBlendShapes (CMRMMesh& baseMesh,
02397 std::vector<CMesh::CMeshBuild*> &bsList, uint32 VertexFlags)
02398 {
02399 uint32 i, j, k, m, destIndex;
02400 uint32 attId;
02401 CVectorH vh;
02402 vector<CMRMBlendShape> &bsMeshes= baseMesh.BlendShapes;
02403
02404 bsMeshes.resize (bsList.size());
02405
02406 for (i = 0; i < bsList.size(); ++i)
02407 {
02408
02409 nlassert (baseMesh.Vertices.size() == bsList[i]->Vertices.size());
02410 bsMeshes[i].Vertices.resize (baseMesh.Vertices.size());
02411 bsMeshes[i].Vertices = bsList[i]->Vertices;
02412
02413 bsMeshes[i].NumAttributes = baseMesh.NumAttributes;
02414 for (j = 0; j < (uint32)bsMeshes[i].NumAttributes; ++j)
02415 bsMeshes[i].Attributes[j].resize(baseMesh.Attributes[j].size());
02416
02417
02418 for (j = 0; j < baseMesh.Faces.size(); ++j)
02419 for (k = 0; k < 3; ++k)
02420 {
02421 const CMesh::CCorner &srcCorner = bsList[i]->Faces[j].Corner[k];
02422 CMRMCorner &neutralCorner = baseMesh.Faces[j].Corner[k];
02423
02424 attId= 0;
02425
02426 if (VertexFlags & CVertexBuffer::NormalFlag)
02427 {
02428 destIndex = neutralCorner.Attributes[attId];
02429 vh.x = srcCorner.Normal.x;
02430 vh.y = srcCorner.Normal.y;
02431 vh.z = srcCorner.Normal.z;
02432 vh.w = 0.0f;
02433 bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02434 attId++;
02435 }
02436 if (VertexFlags & CVertexBuffer::PrimaryColorFlag)
02437 {
02438 destIndex = neutralCorner.Attributes[attId];
02439 vh.x = srcCorner.Color.R;
02440 vh.y = srcCorner.Color.G;
02441 vh.z = srcCorner.Color.B;
02442 vh.w = srcCorner.Color.A;
02443 bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02444 attId++;
02445 }
02446 if (VertexFlags & CVertexBuffer::SecondaryColorFlag)
02447 {
02448 destIndex = neutralCorner.Attributes[attId];
02449 vh.x = srcCorner.Specular.R;
02450 vh.y = srcCorner.Specular.G;
02451 vh.z = srcCorner.Specular.B;
02452 vh.w = srcCorner.Specular.A;
02453 bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02454 attId++;
02455 }
02456 for (m = 0; m < CVertexBuffer::MaxStage; ++m)
02457 {
02458 if (VertexFlags & (CVertexBuffer::TexCoord0Flag<<m))
02459 {
02460 destIndex = neutralCorner.Attributes[attId];
02461 vh.x = srcCorner.Uvws[m].U;
02462 vh.y = srcCorner.Uvws[m].V;
02463 vh.z = srcCorner.Uvws[m].W;
02464 vh.w = 0.0f;
02465 bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02466 attId++;
02467 }
02468 }
02469 }
02470 }
02471 }
02472
02473
02474
02475 void CMRMBuilder::compileMRM(const CMesh::CMeshBuild &mbuild, std::vector<CMesh::CMeshBuild*> &bsList,
02476 const CMRMParameters ¶ms, CMeshMRMGeom::CMeshBuildMRM &mrmMesh,
02477 uint numMaxMaterial)
02478 {
02479
02480 CMRMMesh baseMesh;
02481 vector<CMRMMeshGeom> lodMeshs;
02482 CMRMMeshFinal finalMRM;
02483 vector<CMRMMeshFinal> finalBsMRM;
02484 uint32 vbFlags;
02485
02486
02487 nlassert(params.DistanceFinest>=0);
02488 nlassert(params.DistanceMiddle > params.DistanceFinest);
02489 nlassert(params.DistanceCoarsest > params.DistanceMiddle);
02490
02491
02492
02493 _SkinReduction= params.SkinReduction;
02494
02495
02496 _Skinned= ((mbuild.VertexFlags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag);
02497
02498 _Skinned= _Skinned && ( mbuild.Vertices.size()==mbuild.SkinWeights.size() );
02499
02500
02501 _HasMeshInterfaces= buildMRMSewingMeshes(mbuild, params.NLods, params.Divisor);
02502
02503
02504
02505
02506 vbFlags= buildMrmBaseMesh(mbuild, baseMesh);
02507
02508
02509 buildBlendShapes (baseMesh, bsList, vbFlags);
02510
02511
02512 if(_Skinned)
02513 {
02514 normalizeBaseMeshSkin(baseMesh);
02515 }
02516
02517
02518 buildAllLods ( baseMesh, lodMeshs, params.NLods, params.Divisor );
02519
02520
02521 buildFinalMRM(lodMeshs, finalMRM);
02522
02523
02524 buildMeshBuildMrm(finalMRM, mrmMesh, vbFlags, numMaxMaterial, mbuild);
02525
02526
02527 mrmMesh.DistanceFinest= params.DistanceFinest;
02528 mrmMesh.DistanceMiddle= params.DistanceMiddle;
02529 mrmMesh.DistanceCoarsest= params.DistanceCoarsest;
02530 }
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540 bool CMRMBuilder::buildMRMSewingMeshes(const CMesh::CMeshBuild &mbuild, uint nWantedLods, uint divisor)
02541 {
02542 nlassert(nWantedLods>=1);
02543 nlassert(divisor>=1);
02544 if(mbuild.Interfaces.size()==0)
02545 return false;
02546
02547 if(mbuild.InterfaceLinks.size()!=mbuild.Vertices.size())
02548 return false;
02549
02550
02551 _SewingMeshes.resize(mbuild.Interfaces.size());
02552 for(uint i=0;i<mbuild.Interfaces.size();i++)
02553 {
02554 _SewingMeshes[i].build(mbuild.Interfaces[i], nWantedLods, divisor);
02555 }
02556
02557
02558 return true;
02559 }
02560
02561
02562 }