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