mrm_builder.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
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 // Tools Methods.
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     // Do not use remove<> since it desn't modify size ... (???)
00059     // This doesn't seem to work.
00060     //return remove(array.begin(), array.end(), elt)!=array.end();
00061 }
00062 
00063 
00064 // ***************************************************************************
00065 // ***************************************************************************
00066 // Edge Cost methods.
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     // Init to 0.
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     // Inc count.
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     // Test open edges.
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     // return a positive value of Somme(|DeltaNormals|) / NNormals.
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     // build list sharing edge.
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     // test if faces have same material.
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     // test if faces have same wedge (for all att).
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     // build list sharing edge.
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     // test if faces are not isolated OneMaterial faces.
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     // more expensive is the edge, later it will collapse.
00247 
00248 
00249     // **** standard cost
00250 
00251     // compute size of the edge.
00252     float   cost=(TmpVertices[v1].Current-TmpVertices[v2].Current).norm();
00253 
00254     // compute "curvature" of the edge.
00255     float   faceCost= (getDeltaFaceNormals(v1)+getDeltaFaceNormals(v2));
00256     // totally plane faces (faceCost==0) must be collapsed with respect to size (and not random if cost==0).
00257     // else we may have Plane Mesh (like flags) that will collapse in a very ugly way.
00258     faceCost= max(faceCost, 0.01f);
00259 
00260     // modulate size with curvature.
00261     cost*= faceCost;
00262 
00263     // Like H.Hope, add a weight on discontinuities..
00264     if( !vertexContinue(v1) && !vertexContinue(v2) )
00265     {
00266         // Nb: don't do this on discontinuities edges, unless the unique material face will collapse (pffiou!!).
00267         if( edgeContinue(edge) || edgeNearUniqueMatFace(edge) )
00268             cost*=4;
00269     }
00270 
00271     // **** Interface Sewing cost
00272     if(_HasMeshInterfaces)
00273     {
00274         // if the 2 vertices come from a Sewing Interface mesh (must be a real interface id)
00275         sint    meshSewingId= TmpVertices[v1].InterfaceLink.InterfaceId;
00276         if( meshSewingId>=0 && TmpVertices[v2].InterfaceLink.InterfaceId>=0 )
00277         {
00278             // if the 2 vertices come from the same Sewing Interface mesh
00279             if( meshSewingId == TmpVertices[v2].InterfaceLink.InterfaceId )
00280             {
00281                 // Then the edge is one of the sewing interface mesh. must do special things for it
00282                 CMRMSewingMesh  &sewingMesh= _SewingMeshes[meshSewingId];
00283                 uint    dummy;
00284 
00285                 // get the sewing edge id
00286                 CMRMEdge    sewingEdge;
00287                 sewingEdge.v0= TmpVertices[v1].InterfaceLink.InterfaceVertexId;
00288                 sewingEdge.v1= TmpVertices[v2].InterfaceLink.InterfaceVertexId;
00289                 // if the current sewing lod want to collapse this edge
00290                 sint collapseId= sewingMesh.mustCollapseEdge(_CurrentLodComputed, sewingEdge, dummy);
00291                 if(collapseId>=0)
00292                 {
00293                     // Then set a negative priority (ie will collapse as soon as possible). from -N to -1.
00294                     // NB: sort them according to collapseId
00295                     cost= (float)(-sewingMesh.getNumCollapseEdge(_CurrentLodComputed) + collapseId);
00296                 }
00297                 else
00298                 {
00299                     // This edge must not collapse at this Lod, set an infinite priority (hope will never collapse).
00300                     cost= FLT_MAX;
00301                 }
00302             }
00303             else
00304             {
00305                 /* The edge is between 2 interfaces but not the same. If we collide it we'll have holes!
00306                     This problem arise if space beetween interfaces is small. eg: if we setup an interface beetween
00307                     hair and head, and an other one beetween head and torso, then we'll have this problem in the
00308                     back of the neck.
00309                     The solution is to make a big big cost to hope we'll never collide them (else Holes...)!!
00310                     Don't use FLT_MAX to still have a correct order if we don't have choice...
00311                 */
00312                 cost*= 10000;
00313             }
00314         }
00315     }
00316 
00317     return cost;
00318 }
00319 
00320 
00321 
00322 
00323 // ***************************************************************************
00324 // ***************************************************************************
00325 // Collapse Methods.
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     // For find().
00383     bool    operator==(const CTmpVertexWeight &o) const
00384     {
00385         return MatrixId==o.MatrixId;
00386     }
00387     // For sort().
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     // If fast interpolation.
00400     if(interValue==0)
00401         return sw1;
00402     if(interValue==1)
00403         return sw2;
00404 
00405     // else, must blend a skinWeight: must identify matrix which exist in the 2 sws, and add new ones.
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     // For all weights of sw1.
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         // if this weight is not null.
00420         if(vw.Weight>0)
00421         {
00422             // add it to the list.
00423             sws.push_back(vw);
00424         }
00425         // For skinning reduction.
00426         if(sw1.Weights[i]>0)
00427             nbMats1++;
00428     }
00429 
00430 
00431     // For all weights of sw1.
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         // if this weight is not null.
00438         if(vw.Weight>0)
00439         {
00440             // add it or add influence to the matrix.
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         // For skinning reduction.
00448         if(sw2.Weights[i]>0)
00449             nbMats2++;
00450     }
00451 
00452 
00453     // Then keep just the best.
00454     // sort by Weight decreasing order.
00455     sort(sws.begin(), sws.end());
00456 
00457     // clamp the result to the wanted max matrix.
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     // For security.
00474     nbMatsOut= min(nbMatsOut, (uint)sws.size());
00475     nlassert(nbMatsOut<=NL3D_MESH_SKINNING_MAX_MATRIX);
00476 
00477 
00478     // Then output the result to the skinWeight, normalizing.
00479     float   sumWeight=0;
00480     for(i= 0; i<nbMatsOut; i++)
00481     {
00482         sumWeight+= sws[i].Weight;
00483     }
00484 
00485     CMesh::CSkinWeight  ret;
00486     // Fill only needed matrix (other are rested in CMesh::CSkinWeight ctor).
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     // 0. collapse the vertices.
00506     //==========================
00507 
00508     // edge.Vertex1 kept, but morphed.
00509     // edge.Vertex2 deleted, and must know on which vertex it collapse.
00510     CMRMVertex  &Vertex1=TmpVertices[edgeV1], &Vertex2=TmpVertices[edgeV2];
00511 
00512     // Interpolation choice.
00513     // Default is to interpolate vertex 0 to the middle of the edge.
00514     InterValue=0.5;
00515     //InterValue=1;
00516     // **** If at least one vertex of the edge is on a mesh sewing interface, must change InterValue
00517     if( _HasMeshInterfaces && (Vertex1.InterfaceLink.InterfaceId>=0 || Vertex2.InterfaceLink.InterfaceId>=0) )
00518     {
00519         // If this is an edge of a mesh sewing interface
00520         if(Vertex1.InterfaceLink.InterfaceId==Vertex2.InterfaceLink.InterfaceId)
00521         {
00522             // Then the edge is one of the sewing interface mesh. must do special things for it
00523             CMRMSewingMesh  &sewingMesh= _SewingMeshes[Vertex1.InterfaceLink.InterfaceId];
00524 
00525             // get the sewing edge id
00526             CMRMEdge    sewingEdge;
00527             sewingEdge.v0= Vertex1.InterfaceLink.InterfaceVertexId;
00528             sewingEdge.v1= Vertex2.InterfaceLink.InterfaceVertexId;
00529 
00530             // Get the edge in the sewing mesh which is said to be collapsed
00531             uint    vertToCollapse;
00532             sint collapseId= sewingMesh.mustCollapseEdge(_CurrentLodComputed, sewingEdge, vertToCollapse);
00533             // if exist
00534             if(collapseId>=0)
00535             {
00536                 // if it is v0 which must collapse, then InterValue=1
00537                 if(vertToCollapse==(uint)sewingEdge.v0)
00538                     InterValue= 1;
00539                 else
00540                     InterValue= 0;
00541 
00542             }
00543             else
00544             {
00545                 // This should not happens. But it is still possible if this edge don't want to collapse but if their
00546                 // is no more choice. Take a default value
00547                 InterValue= 0;
00548             }
00549         }
00550         else
00551         {
00552             // must collapse to the vertex on the sewing interface (as if it was open)
00553             if(Vertex1.InterfaceLink.InterfaceId>=0)
00554             {
00555                 // NB: it is possible that both vertices are on a different sewing interface... still collapse (must have to)
00556                 InterValue= 0;
00557             }
00558             else
00559             {
00560                 // Then Vertex2 is on a sewing interface, collapse to it
00561                 InterValue= 1;
00562             }
00563         }
00564     }
00565     // **** Else, on special cases, it is much more efficient to interpolate at start or at end of edge.
00566     else
00567     {
00568         // If one vertex is "open", ie his shared faces do not represent a closed Fan, then interpolate to this one,
00569         // so the mesh has the same silhouette.
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             // Do the same test but with vertex continue: it is preferable to not move the boundaries
00577             // of a material, or a mapping.
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     /*BENCH_TotalCollapses++;
00585     if(InterValue==0.5)
00586         BENCH_MiddleCollapses++;*/
00587 
00588     // Collapse the Vertex.
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     // \todo yoyo: TODO_BUG: Don't know why, but vertices may point on deleted faces.
00600     // Temp: we destroy here thoses face from SharedFaces...
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     // Build Neighbor faces.
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     // Build faces which will be destroyed (may 1 or 2, maybe more for non conventionnal meshes).
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     // 1. Collapse the wedges.
00642     //========================
00643 
00644     // For ALL Attributes.
00645     for(sint attId=0;attId<NumAttributes;attId++)
00646     {
00647         // a/ Stock the wedge interpolation in each destroyed face.
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         // b/ Build wedge list to be modify.
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         // c/ Count numFaces which point on those wedges. (- deleted faces).
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             // Count total ref count.
00706             for(j=0;j<(sint)neighboorFaces.size();j++)
00707             {
00708                 if(TmpFaces[neighboorFaces[j]].hasWedge(attId, numWedge))
00709                     wedge.NbSharedFaces++;
00710             }
00711 
00712             // Minus deleted faces.
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         // d/ Collapse wedge following 3 possibles cases.
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             // if wedge not shared...
00735             if(!wedge.Shared)
00736             {
00737                 // We've got an "exterior wedge" which lost no corner => do not merge it nor delete it.
00738                 // Leave it as the same value (extrapolate it may not be a good solution).
00739             }
00740             else
00741             {
00742                 // if wedge dissapears, notify.
00743                 if(wedge.NbSharedFaces==0)
00744                 {
00745                     wedge.CollapsedTo=-2;
00746                     // Do not change his value. (as specified in Hope article).
00747                 }
00748                 else
00749                 {
00750                     CMRMFaceBuild   &face= TmpFaces[wedge.InterpolatedFace];
00751 
00752                     // Must interpolate it.
00753                     wedge.Current= face.InterpolatedAttribute;
00754                     wedge.BSCurrent = face.BSInterpolated;
00755 
00756                     // Must merge the wedge of the second vertex on first
00757                     // ONLY IF 2 interpolated wedges are shared and NbSharedFaces!=0.
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     // 3. collapse faces.
00770     //===================
00771 
00772     // delete face shared by edge.
00773     for(i=0;i<(sint)deletedFaces.size();i++)
00774     {
00775         sint    numFace= deletedFaces[i];
00776         TmpFaces[numFace].Deleted=true;
00777 
00778         // release edges from list.
00779         removeFaceFromEdgeList(TmpFaces[numFace]);
00780         // invalid all it!!
00781         TmpFaces[numFace].invalidAllIts(EdgeCollapses);
00782 
00783 
00784         // delete from vertex1 and 2 the deleted faces.
00785         deleteElement( Vertex1.SharedFaces, numFace);
00786         deleteElement( Vertex2.SharedFaces, numFace);
00787     }
00788 
00789 
00790     // must ref correctly the faces.
00791     for(i=0;i<(sint)neighboorFaces.size();i++)
00792     {
00793         CMRMFaceBuild       &face=TmpFaces[neighboorFaces[i]];
00794 
00795         // good vertices
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         // nb: doesn't matter if deletedFaces are modified...
00800 
00801         // good wedges
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         // good edges.
00814         /* Those ones are updated in collapseEdges(): they are removed from the edgeCollapseList,
00815             then they are re-inserted with good Vertex indices.
00816         */
00817     }
00818 
00819 
00820     // The vertex1 has now the shared env of vertex2.
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 // Mesh Level method.
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     // First clear ALL.
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     // resize.
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     // Then copy.
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     // Create vertices sharedFaces.
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     // Compute EdgeCost.
00932     for(i=0;i<(sint)TmpFaces.size();i++)
00933     {
00934         CMRMFaceBuild       &f= TmpFaces[i];
00935         // At start, valid all edges.
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         // 0. Look if edge already deleted
00959         //================================
00960         CMRMEdge    edge=(*EdgeIt).second;
00961 
00962         // Is it valid?? (ie his vertices exist yet??).
00963         if(TmpVertices[ edge.v0 ].CollapsedTo>=0
00964             || TmpVertices[ edge.v1 ].CollapsedTo>=0)
00965         {
00966             // \todo yoyo: TODO_BUG: potential bug here...
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         // \todo yoyo: TODO_BUG: potential bug here...
00975         // If a mesh is "open" it will crash if a "hole collapse"...
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         // 1. else, OK, collapse it!!
00988         //===========================
00989         sint    vertexCollapsed= edge.v0;
00990         nCurrentFaces-= collapseEdge(edge);
00991 
00992 
00993         // 2. Must reorder all his neighborhood.
00994         //======================================
00995         CMRMVertex  &vert=TmpVertices[vertexCollapsed];
00996         sint    i;
00997         // we delete from list modified edges, and we re-add them with their new value.
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     // First clear ALL.
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     // Vertices.
01023     //==========
01024     index=0;
01025     for(i=0;i<(sint)TmpVertices.size();i++)
01026     {
01027         CMRMVertex  &vert=TmpVertices[i];
01028         if(vert.CollapsedTo==-1)    // if exist yet.
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;   // indicate that this vertex no more exist and is to be geomorphed to an other.
01041     }
01042 
01043 
01044     // Attributes.
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)   // if exist yet.
01053             {
01054                 wedge.CoarserIndex=index;
01055                 coarserMesh.Attributes[attId].push_back(wedge.Current);
01056                 index++;
01057             }
01058             else if(wedge.CollapsedTo==-2)  // else if totaly destroyed.
01059             {
01060                 // Insert this wedge in the coarser mesh.
01061                 // NB: the coarser mesh faces do not use it anymore, but FinerMesh use it
01062                 // for geomorph (LODMesh.CoarserFaces may point to it).
01063                 // NB: look at buildFinalMRM(), it works fine for all cases.
01064                 wedge.CoarserIndex=index;
01065                 coarserMesh.Attributes[attId].push_back(wedge.Current);
01066                 index++;
01067             }
01068             else
01069                 wedge.CoarserIndex=-1;  // indicate that this wedge no more exist and is to be geomorphed to an other.
01070         }
01071     }
01072 
01073     // Faces.
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             // Material.
01082             newFace.MaterialId= face.MaterialId;
01083             for(sint j=0;j<3;j++)
01084             {
01085                 // Vertex.
01086                 newFace.Corner[j].Vertex= TmpVertices[face.Corner[j].Vertex].CoarserIndex;
01087                 nlassert(newFace.Corner[j].Vertex>=0);
01088                 // Attributes.
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     // for all faces of this mesh, find target in the coarser mesh.
01111     for(i=0;i<(sint)lodMesh.CoarserFaces.size();i++)
01112     {
01113         CMRMFace    &face= lodMesh.CoarserFaces[i];
01114 
01115         // For 3 corners.
01116         for(j=0;j<3;j++)
01117         {
01118             // Vertex.
01119             // The index is yet the index in the finer mesh.
01120             index= face.Corner[j].Vertex;
01121             // the index in the coarser mesh is vert.CoarserIndex.
01122             coidx= TmpVertices[index].CoarserIndex;
01123             // but if this vertex is collapsed, must find the good index (yet in the finer mesh)
01124             if(coidx==-1)
01125             {
01126                 // find to which we must collapse.
01127                 index= followVertex(index);
01128                 // and so we have the coarser index. this one must be valid.
01129                 coidx= TmpVertices[index].CoarserIndex;
01130                 nlassert(coidx>=0);
01131             }
01132             // update corner of CoarserFace.
01133             face.Corner[j].Vertex= coidx;
01134 
01135 
01136             // Do exactly same thing for all attributes.
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 // Transform source blend shapes to source blend shapes modified (just calculate new vertex/attr position)
01156 /*void  CMRMBuilder::computeBsVerticesAttributes(vector<CMRMMesh> &srcBsMeshs, vector<CMRMMesh> &bsMeshsMod)
01157 {
01158     sint    i, j, k, attId;
01159 
01160     bsMeshsMod.resize (srcBsMeshs.size());
01161     for (k = 0; k < (sint)srcBsMeshs.size(); ++k)
01162     {
01163         CMRMMesh &rBsMesh = srcBsMeshs[k];
01164         CMRMMesh &rBsMeshMod = bsMeshsMod[k];
01165 
01166         // Calculate modified vertices with the linear equation back tracking help
01167         rBsMeshMod.Vertices.resize (rBsMesh.Vertices.size());
01168         for (i = 0; i < (sint)rBsMesh.Vertices.size(); ++i)
01169         {
01170             CLinearEquation &LinEq = TmpVertices[i].CurrentLinEq;
01171             rBsMeshMod.Vertices[i] = CVector(0.0f, 0.0f, 0.0f);
01172             for (j = 0; j < (sint)LinEq.Elts.size(); ++j)
01173             {
01174                 rBsMeshMod.Vertices[i] += LinEq.Elts[j].factor * rBsMesh.Vertices[LinEq.Elts[j].index];
01175             }
01176         }
01177 
01178         // All attributes
01179         rBsMeshMod.NumAttributes = NumAttributes;
01180         for (attId = 0; attId < NumAttributes; attId++)
01181         {
01182             rBsMeshMod.Attributes[attId].resize (rBsMesh.Attributes[attId].size());
01183             for (i = 0; i < (sint)rBsMesh.Attributes[attId].size(); ++i)
01184             {
01185                 CLinearEquation &LinEq = TmpAttributes[attId][i].CurrentLinEq;
01186                 rBsMeshMod.Attributes[attId][i] = CVectorH(0.0f, 0.0f, 0.0f, 0.0f);
01187                 for (j = 0; j < (sint)LinEq.Elts.size(); ++j)
01188                 {
01189                     rBsMeshMod.Attributes[attId][i].x += LinEq.Elts[j].factor * rBsMesh.Attributes[attId][LinEq.Elts[j].index].x;
01190                     rBsMeshMod.Attributes[attId][i].y += LinEq.Elts[j].factor * rBsMesh.Attributes[attId][LinEq.Elts[j].index].y;
01191                     rBsMeshMod.Attributes[attId][i].z += LinEq.Elts[j].factor * rBsMesh.Attributes[attId][LinEq.Elts[j].index].z;
01192                     rBsMeshMod.Attributes[attId][i].w += LinEq.Elts[j].factor * rBsMesh.Attributes[attId][LinEq.Elts[j].index].w;
01193                 }
01194             }
01195         }
01196     }
01197 }*/
01198 
01199 // ***************************************************************************
01200 // Transform source Blend Shape Meshes Modified into coarser blend shape mesh (compact vertices)
01201 void    CMRMBuilder::makeCoarserBS (vector<CMRMBlendShape> &csBsMeshs)
01202 {
01203     uint32 i, k;
01204     sint32 nSizeVert, nSizeAttr, attId;
01205 
01206     // Calculate size of vertices array
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         // Vertices
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             // Calculate size of attribute attId array
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     // Init Tmp values in MRM builder.
01257     init(baseMesh);
01258 
01259     // compute MRM too next tgt face.
01260     collapseEdges(nWantedFaces);
01261 
01262     // save the coarser mesh.
01263     saveCoarserMesh(coarserMesh);
01264     // Build coarser BlendShapes.
01265     coarserMesh.BlendShapes.resize(baseMesh.BlendShapes.size());
01266     makeCoarserBS(coarserMesh.BlendShapes);
01267 
01268     // build the lodMesh (baseMesh, with vertex/Attributes collapse infos).
01269     lodMesh= baseMesh;
01270     makeLODMesh(lodMesh);
01271 
01272     // end for this level.
01273 }
01274 
01275 
01276 
01277 // ***************************************************************************
01278 // ***************************************************************************
01279 // Global MRM Level method.
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     // coarsest LOD will have those number of faces.
01294     nBaseFaces=nFaces/divisor;
01295     nBaseFaces=max(nBaseFaces,4);
01296 
01297     // must have at least 2 LOD to be really intersting. But the rest of the process work too with only one Lod!!
01298     nlassert(nWantedLods>=1);
01299     lodMeshs.resize(nWantedLods);
01300 
01301     // If only one lod asked, must init some Tmp Global values (like NumAttributes)
01302     if(nWantedLods==1)
01303     {
01304         _CurrentLodComputed= 0;
01305         init(baseMesh);
01306     }
01307 
01308     // must fill all LODs, from end to start. do not proces last lod since it will be the coarsest mesh.
01309     for(i=nWantedLods-1;i>0;i--)
01310     {
01311         sint    nbWantedFaces;
01312 
01313         // for sewing computing
01314         _CurrentLodComputed= i;
01315 
01316         // Linear.
01317         nbWantedFaces= nBaseFaces + (nFaces-nBaseFaces) * (i-1)/(nWantedLods-1);
01318         nbWantedFaces=max(nbWantedFaces,4);
01319 
01320         // Build this LOD.
01321         CMRMMesh    csMesh;
01322         // The mesh
01323         makeFromMesh(srcMesh, lodMeshs[i], csMesh, nbWantedFaces);
01324 
01325         // next mesh to process is csMesh.
01326         srcMesh = csMesh;
01327     }
01328     // the first lodMedsh gets the coarsest mesh.
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     // Init.
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     // Build Wedges, and faces index.
01351     // ===============
01352     // for all lods.
01353     for(lodId=0; lodId<nLods; lodId++)
01354     {
01355         CMRMMeshGeom    &lodMesh= lodMeshs[lodId];
01356         CMRMMeshGeom    &lodMeshPrec= lodMeshs[lodId==0?0:lodId-1];
01357         // for all face corner.
01358         for(i=0; i<(sint)lodMesh.Faces.size();i++)
01359         {
01360             // The current face.
01361             CMRMFace    &face= lodMesh.Faces[i];
01362             // the current face, but which points to the prec LOD vertices/attributes.
01363             CMRMFace    &faceCoarser= lodMesh.CoarserFaces[i];
01364             // for 3 corners.
01365             for(j=0;j<3;j++)
01366             {
01367                 CMRMCorner  &corner= face.Corner[j];
01368                 CMRMCorner  &cornerCoarser= faceCoarser.Corner[j];
01369                 // start and end wedge (geomorph), maybe same.
01370                 CMRMMeshFinal::CWedge       wedgeStart;
01371                 CMRMMeshFinal::CWedge       wedgeEnd;
01372 
01373                 // fill wedgeStart with values from lodMesh.
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                 // if geomorph possible (ie not lod 0).
01383                 if(lodId>0)
01384                 {
01385                     // fill wedgeEnd with values from coarser lodMesh.
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                     // no geomorph.
01397                     wedgeEnd= wedgeStart;
01398                 }
01399 
01400                 // find/insert wedge, and get Ids. NB: if start/end same, same indices.
01401                 sint    wedgeStartId= finalMRM.findInsertWedge(wedgeStart);
01402                 sint    wedgeEndId= finalMRM.findInsertWedge(wedgeEnd);
01403 
01404                 // store in TmpCorner.
01405                 corner.WedgeStartId= wedgeStartId;
01406                 corner.WedgeEndId= wedgeEndId;
01407             }
01408         }
01409 
01410         // Here, the number of wedge indicate the max number of wedge this LOD needs.
01411         finalMRM.Lods[lodId].NWedges= finalMRM.Wedges.size();
01412     }
01413 
01414 
01415     // Count NBWedges necessary for geomorph, and compute Dest geomorph wedges ids.
01416     // ===============
01417     // the number of geomorph required for one LOD.
01418     sint    sglmGeom;
01419     // the number of geomorph required for all LOD (max of sglmGeom).
01420     sint    sglmGeomMax= 0;
01421 
01422     // Do not process lod 0, since no geomorph.
01423     for(lodId=1; lodId<nLods; lodId++)
01424     {
01425         CMRMMeshGeom    &lodMesh= lodMeshs[lodId];
01426 
01427         // reset the GeomMap, the one which indicate if we have already inserted a geomorph.
01428         _GeomMap.clear();
01429         sglmGeom= 0;
01430 
01431         // for all face corner.
01432         for(i=0; i<(sint)lodMesh.Faces.size();i++)
01433         {
01434             // The current face.
01435             CMRMFace    &face= lodMesh.Faces[i];
01436             // for 3 corners.
01437             for(j=0;j<3;j++)
01438             {
01439                 CMRMCorner  &corner= face.Corner[j];
01440 
01441                 // if not same wedge Ids, this is a geomorphed wedge.
01442                 if(corner.WedgeStartId != corner.WedgeEndId)
01443                 {
01444                     // search if it exist yet in the set.
01445                     CMRMWedgeGeom   geom;
01446                     geom.Start= corner.WedgeStartId;
01447                     geom.End= corner.WedgeEndId;
01448                     sint    geomDest= sglmGeom;
01449                     // if don't find this geom in the set, then it is a new one.
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                     // store this Geom Id in the corner.
01460                     corner.WedgeGeomId= geomDest;
01461                 }
01462             }
01463         }
01464 
01465         // take the max.
01466         sglmGeomMax= max(sglmGeomMax, sglmGeom);
01467     }
01468 
01469 
01470     // inform the finalMRM.
01471     finalMRM.NGeomSpace= sglmGeomMax;
01472 
01473 
01474     // decal all wedges/ face index.
01475     // ===============
01476     // insert an empty space for dest geomorph.
01477     finalMRM.Wedges.insert(finalMRM.Wedges.begin(), sglmGeomMax, CMRMMeshFinal::CWedge());
01478 
01479     // Parse all faces corner of All lods, and decal Start/End Wedge index.
01480     for(lodId=0; lodId<nLods; lodId++)
01481     {
01482         CMRMMeshGeom    &lodMesh= lodMeshs[lodId];
01483 
01484         // for all face corner.
01485         for(i=0; i<(sint)lodMesh.Faces.size();i++)
01486         {
01487             // The current face.
01488             CMRMFace    &face= lodMesh.Faces[i];
01489             // for 3 corners.
01490             for(j=0;j<3;j++)
01491             {
01492                 CMRMCorner  &corner= face.Corner[j];
01493 
01494                 // decal indices.
01495                 corner.WedgeStartId+= sglmGeomMax;
01496                 corner.WedgeEndId+= sglmGeomMax;
01497             }
01498         }
01499 
01500         // increment too the number of wedge required for this Lod.
01501         finalMRM.Lods[lodId].NWedges+= sglmGeomMax;
01502     }
01503 
01504 
01505     // fill faces.
01506     // ===============
01507     // Parse all faces corner of All lods, and build Faces/Geomorphs..
01508     for(lodId=0; lodId<nLods; lodId++)
01509     {
01510         CMRMMeshGeom            &lodMesh= lodMeshs[lodId];
01511         CMRMMeshFinal::CLod     &lodDest= finalMRM.Lods[lodId];
01512 
01513         // alloc final faces of this LOD.
01514         lodDest.Faces.resize(lodMesh.Faces.size());
01515 
01516         // reset the GeomMap, the one which indicate if we have already inserted a geomorph.
01517         _GeomMap.clear();
01518 
01519         // for all face corner.
01520         for(i=0; i<(sint)lodMesh.Faces.size();i++)
01521         {
01522             // The current face.
01523             CMRMFace    &face= lodMesh.Faces[i];
01524             // The dest face.
01525             CMRMMeshFinal::CFace        &faceDest= lodDest.Faces[i];
01526             // fill good material.
01527             faceDest.MaterialId= face.MaterialId;
01528 
01529             // for 3 corners.
01530             for(j=0;j<3;j++)
01531             {
01532                 CMRMCorner  &corner= face.Corner[j];
01533 
01534                 // if not same wedge Ids, this is a geomorphed wedge.
01535                 if(corner.WedgeStartId != corner.WedgeEndId)
01536                 {
01537                     // geomorph, so point to geomorphed wedge.
01538                     faceDest.WedgeId[j]= corner.WedgeGeomId;
01539 
01540                     // Build the geomorph, add it to the list (if not yet inserted).
01541                     CMRMWedgeGeom   geom;
01542                     geom.Start= corner.WedgeStartId;
01543                     geom.End=   corner.WedgeEndId;
01544                     // if don't find this geom in the set, then it is a new one.
01545                     TGeomMap::const_iterator    it= _GeomMap.find(geom);
01546                     if(it == _GeomMap.end())
01547                     {
01548                         // mark it as inserted.
01549                         _GeomMap.insert( make_pair(geom, corner.WedgeGeomId) );
01550                         // and we must insert this geom in the array.
01551                         nlassert( corner.WedgeGeomId==(sint)lodDest.Geomorphs.size() );
01552                         lodDest.Geomorphs.push_back(geom);
01553                     }
01554                 }
01555                 else
01556                 {
01557                     // no geomorph, so just point to good wedge.
01558                     faceDest.WedgeId[j]= corner.WedgeStartId;
01559                 }
01560             }
01561         }
01562     }
01563 
01564 
01565     // process all wedges, and compute NSkinMatUsed, skipping geomorphs.
01566     // ===============
01567     // NB: this works because weights are sorted from biggest to lowest.
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     // Blend Shape Stuff
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         // for all face corner.
01591         for (i = 0; i < (sint)lodMesh.Faces.size(); ++i)
01592         {
01593             // The current face.
01594             CMRMFace &face = lodMesh.Faces[i];
01595             // the current face, but which points to the prec LOD vertices/attributes.
01596             CMRMFace &faceCoarser = lodMesh.CoarserFaces[i];
01597             // for 3 corners.
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                     // Fill WedgeStart used by this corner.
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                     // If geomorph, must fill the end too
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 // Interface to MeshBuild Part.
01640 // ***************************************************************************
01641 // ***************************************************************************
01642 
01643 
01644 
01645 // ***************************************************************************
01646 sint            CMRMBuilder::findInsertAttributeInBaseMesh(CMRMMesh &baseMesh, sint attId, sint vertexId, const CVectorH &att)
01647 {
01648     // find this attribute in the map.
01649     CAttributeKey   key;
01650     key.VertexId= vertexId;
01651     key.Attribute= att;
01652     TAttributeMap::iterator     it= _AttributeMap[attId].find(key);
01653 
01654     // if attribute not found in the map, then insert a new one.
01655     if(it==_AttributeMap[attId].end())
01656     {
01657         sint    idx= baseMesh.Attributes[attId].size();
01658         // insert into the array.
01659         baseMesh.Attributes[attId].push_back(att);
01660         // insert into the map.
01661         _AttributeMap[attId].insert(make_pair(key, idx));
01662         return idx;
01663     }
01664     else
01665     {
01666         // return the one found.
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     // build the supported VertexFormat.
01738     uint32      retVbFlags= CVertexBuffer::PositionFlag;
01739 
01740 
01741     // reset the baseMesh.
01742     baseMesh= CMRMMesh();
01743     // reset Tmp.
01744     for(attId=0; attId<NL3D_MRM_MAX_ATTRIB;attId++)
01745         _AttributeMap[attId].clear();
01746 
01747 
01748     // Compute number of attributes used by the MeshBuild.
01749     // ========================
01750     // Compute too
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     // Fill basics: Vertices and Faces materials / index to vertices.
01779     // ========================
01780     // Just copy vertices.
01781     baseMesh.Vertices= mbuild.Vertices;
01782     // Just copy SkinWeights.
01783     if(_Skinned)
01784         baseMesh.SkinWeights= mbuild.SkinWeights;
01785     // Just copy InterfaceLinks
01786     if(_HasMeshInterfaces)
01787         baseMesh.InterfaceLinks= mbuild.InterfaceLinks;
01788     // Resize faces.
01789     nFaces= mbuild.Faces.size();
01790     baseMesh.Faces.resize(nFaces);
01791     for(i=0; i<nFaces; i++)
01792     {
01793         // copy material Id.
01794         baseMesh.Faces[i].MaterialId= mbuild.Faces[i].MaterialId;
01795         // Copy Vertex index.
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     // Resolve attributes discontinuities and Fill attributes of the baseMesh.
01803     // ========================
01804     // For all corners.
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             // For all activated attributes in mbuild, find/insert the attribute in the baseMesh.
01814             // NB: 2 attributes are said to be different if they have not the same value OR if they don't lie
01815             // on the same vertex. This is very important for MRM computing.
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     // End. clear Tmp infos.
01845     // ========================
01846     // reset Tmp.
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     // For all weights of sw1.
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         // if this weight is not null.
01871         if(vw.Weight>0)
01872         {
01873             // add it to the list.
01874             sws.push_back(vw);
01875             nbMats++;
01876         }
01877     }
01878 
01879     // sort by Weight decreasing order.
01880     sort(sws.begin(), sws.end());
01881 
01882 
01883     // Then output the result to the skinWeight, normalizing.
01884     float   sumWeight=0;
01885     for(i= 0; i<nbMats; i++)
01886     {
01887         sumWeight+= sws[i].Weight;
01888     }
01889 
01890     CMesh::CSkinWeight  ret;
01891     // Fill only needed matrix (other are rested in CMesh::CSkinWeight ctor).
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     // reset the mbuild.
01922     mbuild= CMeshMRMGeom::CMeshBuildMRM();
01923     // Setup VB.
01924 
01925     bool useFormatExt = false;
01926     // Check whether there are texture coordinates with more than 2 compnents, which force us to use an extended vertex format
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         // setup standard format
01952         mbuild.VBuffer.setVertexFormat(vbFlags);
01953     }
01954     else // setup extended format
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     // Copy the UVRouting
01987     for (i=0; i<CVertexBuffer::MaxStage; i++)
01988     {
01989         mbuild.VBuffer.setUVRouting (i, mb.UVRouting[i]);
01990     }
01991 
01992     // Setup the VertexBuffer.
01993     // ========================
01994     // resize the VB.
01995     mbuild.VBuffer.setNumVertices(finalMRM.Wedges.size());
01996     // Setup SkinWeights.
01997     if(_Skinned)
01998         mbuild.SkinWeights.resize(finalMRM.Wedges.size());
01999 
02000     CVertexBufferReadWrite vba;
02001     mbuild.VBuffer.lock (vba);
02002 
02003     // fill the VB.
02004     for(i=0; i<(sint)finalMRM.Wedges.size(); i++)
02005     {
02006         const CMRMMeshFinal::CWedge &wedge= finalMRM.Wedges[i];
02007 
02008         // setup Vertex.
02009         vba.setVertexCoord(i, wedge.Vertex);
02010 
02011         // seutp attributes.
02012         attId= 0;
02013 
02014         // For all activated attributes in mbuild, retriev the attribute from the finalMRM.
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         // Setup SkinWeights.
02054         if(_Skinned)
02055         {
02056             mbuild.SkinWeights[i]= wedge.VertexSkin;
02057         }
02058     }
02059 
02060 
02061     // Build Lods.
02062     // ========================
02063     // resize
02064     mbuild.Lods.resize(finalMRM.Lods.size());
02065     // fill.
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         // Basic.
02072         //---------
02073 
02074         // Copy NWedges infos.
02075         destLod.NWedges= srcLod.NWedges;
02076         // Copy Geomorphs infos.
02077         destLod.Geomorphs= srcLod.Geomorphs;
02078 
02079 
02080         // Reorder faces by rdrpass.
02081         //---------
02082 
02083         // First count the number of faces used by this LOD for each material
02084         vector<sint>    matCount;
02085         // resize, and reset to 0.
02086         matCount.clear();
02087         matCount.resize(nbMats, 0);
02088         // For each face of this Lods, incr the mat face counter.
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             // increment the refcount of this material by this LOD.
02095             matCount[matId]++;
02096         }
02097 
02098         // Then for each material not empty, create a rdrPass, and ref it for this material.
02099         vector<sint>    rdrPassIndex;   // material to rdrPass map.
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                 // map material to rdrPass.
02108                 sint    idRdrPass= destLod.RdrPass.size();
02109                 rdrPassIndex[j]= idRdrPass;
02110                 // create a rdrPass.
02111                 destLod.RdrPass.push_back(CMeshMRMGeom::CRdrPass());
02112                 // assign the good materialId to this rdrPass.
02113                 destLod.RdrPass[idRdrPass].MaterialId= j;
02114                 // reserve the array of faces of this rdrPass.
02115                 destLod.RdrPass[idRdrPass].PBlock.reserve(3*matCount[j]);
02116             }
02117         }
02118 
02119         // Then for each face, add it to the good rdrPass of this Lod.
02120         for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02121         {
02122             sint    matId= srcLod.Faces[j].MaterialId;
02123             sint    idRdrPass= rdrPassIndex[matId];
02124             // add this face to the good rdrPass.
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         // Build skin info for this Lod.
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             // This is the set which tell what wedge has already been inserted.
02147             set<uint>   wedgeInfSet;
02148 
02149             // First, build the list of vertices influenced by this Lod.
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                     // If it is a geomorph
02156                     if(wedgeId<finalMRM.NGeomSpace)
02157                     {
02158                         // add the start and end to the list (if not here). NB: wedgeId is both the id
02159                         // of the dest wedge, and the id of the geomorph.
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                         // if insertion in the set work, add to the good array.
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                         // just add this wedge to the list (if not here).
02176                         // if insertion in the set work, add to the array.
02177                         if( wedgeInfSet.insert(wedgeId).second )
02178                             destLod.InfluencedVertices[nMatUsed-1].push_back(wedgeId);
02179                     }
02180                 }
02181             }
02182 
02183             // Optimisation: for better cache, sort the destLod.InfluencedVertices in increasing order.
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             // Then Build the MatrixInfluences array, for all thoses Influenced Vertices only.
02191             // This is the map MatrixId -> MatrixInfId.
02192             map<uint, uint>     matrixInfMap;
02193 
02194             // For all influenced vertices, flags matrix they use.
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                     // take the original wedge.
02203                     const CMRMMeshFinal::CWedge &wedge= finalMRM.Wedges[wedgeId];
02204                     // For all matrix with not null influence...
02205                     for(k= 0; k<NL3D_MESH_SKINNING_MAX_MATRIX; k++)
02206                     {
02207                         float   matWeight= wedge.VertexSkin.Weights[k];
02208 
02209                         // This check the validity of skin weights sort. If false, problem before in the algo.
02210                         if((uint)k<iSkinMat+1)
02211                         {
02212                             nlassert( matWeight>0 );
02213                         }
02214                         else
02215                         {
02216                             nlassert( matWeight==0 );
02217                         }
02218                         // if not null influence.
02219                         if(matWeight>0)
02220                         {
02221                             uint    matId= wedge.VertexSkin.MatrixId[k];
02222 
02223                             // search/insert the matrixInfId.
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                                 // create the new MatrixInfluence.
02230                                 destLod.MatrixInfluences.push_back(matId);
02231                             }
02232                         }
02233                     }
02234                 }
02235             }
02236 
02237         }
02238 
02239     }
02240 
02241     // Indicate Skinning.
02242     mbuild.Skinned= _Skinned;
02243 
02244 
02245 
02246     bool useTgSpace = mb.MeshVertexProgram != NULL ? mb.MeshVertexProgram->needTangentSpace() : false;
02247 
02248     // Construct Blend Shapes
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             {   // Nothing to do !
02322                 attId++;
02323             }
02324 
02325             // Do that only for the UV0
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         } // End of all vertices added in blend shape
02359 
02360         // Delete unused items and calculate the number of vertex used (blended)
02361 
02362         sint32 nNbVertUsed = nNbVertVB;
02363         sint32 nDstPos = 0;
02364         for (j = 0; j < nNbVertVB; ++j)
02365         {
02366             if (rBS.VertRefs[j] == 0xffffffff) // Is vertex UNused
02367             {
02368                 --nNbVertUsed;
02369             }
02370             else // Vertex used
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     // reset the mbuild.
02426     mbuild= CMeshMRMSkinnedGeom::CMeshBuildMRM();
02427     // Setup VB.
02428 
02429     bool useFormatExt = false;
02430     // Check whether there are texture coordinates with more than 2 compnents, which force us to use an extended vertex format
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         // setup standard format
02456         mbuild.VBuffer.setVertexFormat(vbFlags);
02457     }
02458     else // setup extended format
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     // Copy the UVRouting
02491     for (i=0; i<CVertexBuffer::MaxStage; i++)
02492     {
02493         mbuild.VBuffer.setUVRouting (i, mb.UVRouting[i]);
02494     }
02495 
02496     // Setup the VertexBuffer.
02497     // ========================
02498     // resize the VB.
02499     mbuild.VBuffer.setNumVertices(finalMRM.Wedges.size());
02500 
02501     CVertexBufferReadWrite vba;
02502     mbuild.VBuffer.lock (vba);
02503 
02504     // Setup SkinWeights.
02505     if(_Skinned)
02506         mbuild.SkinWeights.resize(finalMRM.Wedges.size());
02507 
02508     // fill the VB.
02509     for(i=0; i<(sint)finalMRM.Wedges.size(); i++)
02510     {
02511         const CMRMMeshFinal::CWedge &wedge= finalMRM.Wedges[i];
02512 
02513         // setup Vertex.
02514         vba.setVertexCoord(i, wedge.Vertex);
02515 
02516         // seutp attributes.
02517         attId= 0;
02518 
02519         // For all activated attributes in mbuild, retrieve the attribute from the finalMRM.
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         // Setup SkinWeights.
02559         if(_Skinned)
02560         {
02561             mbuild.SkinWeights[i]= wedge.VertexSkin;
02562         }
02563     }
02564 
02565 
02566     // Build Lods.
02567     // ========================
02568     // resize
02569     mbuild.Lods.resize(finalMRM.Lods.size());
02570     // fill.
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         // Basic.
02577         //---------
02578 
02579         // Copy NWedges infos.
02580         destLod.NWedges= srcLod.NWedges;
02581         // Copy Geomorphs infos.
02582         destLod.Geomorphs= srcLod.Geomorphs;
02583 
02584 
02585         // Reorder faces by rdrpass.
02586         //---------
02587 
02588         // First count the number of faces used by this LOD for each material
02589         vector<sint>    matCount;
02590         // resize, and reset to 0.
02591         matCount.clear();
02592         matCount.resize(nbMats, 0);
02593         // For each face of this Lods, incr the mat face counter.
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             // increment the refcount of this material by this LOD.
02600             matCount[matId]++;
02601         }
02602 
02603         // Then for each material not empty, create a rdrPass, and ref it for this material.
02604         vector<sint>    rdrPassIndex;   // material to rdrPass map.
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                 // map material to rdrPass.
02613                 sint    idRdrPass= destLod.RdrPass.size();
02614                 rdrPassIndex[j]= idRdrPass;
02615                 // create a rdrPass.
02616                 destLod.RdrPass.push_back(CMeshMRMSkinnedGeom::CRdrPass());
02617                 // assign the good materialId to this rdrPass.
02618                 destLod.RdrPass[idRdrPass].MaterialId= j;
02619                 // reserve the array of faces of this rdrPass.
02620                 destLod.RdrPass[idRdrPass].PBlock.reserve(3*matCount[j]);
02621             }
02622         }
02623 
02624         // Then for each face, add it to the good rdrPass of this Lod.
02625         for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02626         {
02627             sint    matId= srcLod.Faces[j].MaterialId;
02628             sint    idRdrPass= rdrPassIndex[matId];
02629             // add this face to the good rdrPass.
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         // Build skin info for this Lod.
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             // This is the set which tell what wedge has already been inserted.
02649             set<uint>   wedgeInfSet;
02650 
02651             // First, build the list of vertices influenced by this Lod.
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                     // If it is a geomorph
02658                     if(wedgeId<finalMRM.NGeomSpace)
02659                     {
02660                         // add the start and end to the list (if not here). NB: wedgeId is both the id
02661                         // of the dest wedge, and the id of the geomorph.
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                         // if insertion in the set work, add to the good array.
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                         // just add this wedge to the list (if not here).
02678                         // if insertion in the set work, add to the array.
02679                         if( wedgeInfSet.insert(wedgeId).second )
02680                             destLod.InfluencedVertices[nMatUsed-1].push_back(wedgeId);
02681                     }
02682                 }
02683             }
02684 
02685             // Optimisation: for better cache, sort the destLod.InfluencedVertices in increasing order.
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             // Then Build the MatrixInfluences array, for all thoses Influenced Vertices only.
02693             // This is the map MatrixId -> MatrixInfId.
02694             map<uint, uint>     matrixInfMap;
02695 
02696             // For all influenced vertices, flags matrix they use.
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                     // take the original wedge.
02705                     const CMRMMeshFinal::CWedge &wedge= finalMRM.Wedges[wedgeId];
02706                     // For all matrix with not null influence...
02707                     for(k= 0; k<NL3D_MESH_SKINNING_MAX_MATRIX; k++)
02708                     {
02709                         float   matWeight= wedge.VertexSkin.Weights[k];
02710 
02711                         // This check the validity of skin weights sort. If false, problem before in the algo.
02712                         if((uint)k<iSkinMat+1)
02713                         {
02714                             nlassert( matWeight>0 );
02715                         }
02716                         else
02717                         {
02718                             nlassert( matWeight==0 );
02719                         }
02720                         // if not null influence.
02721                         if(matWeight>0)
02722                         {
02723                             uint    matId= wedge.VertexSkin.MatrixId[k];
02724 
02725                             // search/insert the matrixInfId.
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                                 // create the new MatrixInfluence.
02732                                 destLod.MatrixInfluences.push_back(matId);
02733                             }
02734                         }
02735                     }
02736                 }
02737             }
02738 
02739         }
02740 
02741     }
02742 
02743     // Indicate Skinning.
02744     mbuild.Skinned= _Skinned;
02745 
02746 
02747 
02748     bool useTgSpace = mb.MeshVertexProgram != NULL ? mb.MeshVertexProgram->needTangentSpace() : false;
02749 
02750     // Construct Blend Shapes
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             {   // Nothing to do !
02824                 attId++;
02825             }
02826 
02827             // Do that only for the UV0
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         } // End of all vertices added in blend shape
02861 
02862         // Delete unused items and calculate the number of vertex used (blended)
02863 
02864         sint32 nNbVertUsed = nNbVertVB;
02865         sint32 nDstPos = 0;
02866         for (j = 0; j < nNbVertVB; ++j)
02867         {
02868             if (rBS.VertRefs[j] == 0xffffffff) // Is vertex UNused
02869             {
02870                 --nNbVertUsed;
02871             }
02872             else // Vertex used
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         // Construct a blend shape like a mrm mesh
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         // For all corners parse the faces (given by the baseMesh) and construct blend shape mrm meshes
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 &params, CMeshMRMGeom::CMeshBuildMRM &mrmMesh,
03003                                 uint numMaxMaterial)
03004 {
03005     // Temp data.
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     // Copy some parameters.
03019     _SkinReduction= params.SkinReduction;
03020 
03021     // Skinning??
03022     _Skinned= ((mbuild.VertexFlags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag);
03023     // Skinning is OK only if SkinWeights are of same size as vertices.
03024     _Skinned= _Skinned && ( mbuild.Vertices.size()==mbuild.SkinWeights.size() );
03025 
03026     // MeshInterface setuped ?
03027     _HasMeshInterfaces= buildMRMSewingMeshes(mbuild, params.NLods, params.Divisor);
03028 
03029     // from mbuild, build an internal MRM mesh representation.
03030     // vbFlags returned is the VBuffer format supported by CMRMBuilder.
03031     // NB: skinning is removed because skinning is made in software in CMeshMRMGeom.
03032     vbFlags= buildMrmBaseMesh(mbuild, baseMesh);
03033 
03034     // Construct all blend shapes in the same way we have constructed the basemesh mrm
03035     buildBlendShapes (baseMesh, bsList, vbFlags);
03036 
03037     // If skinned, must ensure that skin weights have weights in ascending order.
03038     if(_Skinned)
03039     {
03040         normalizeBaseMeshSkin(baseMesh);
03041     }
03042 
03043     // from this baseMesh, builds all LODs of the MRM, with geomorph info. NB: vertices/wedges are duplicated.
03044     buildAllLods (  baseMesh, lodMeshs, params.NLods, params.Divisor );
03045 
03046     // From this array of LOD, build a finalMRM, by regrouping identical vertices/wedges, and compute index geomorphs.
03047     buildFinalMRM(lodMeshs, finalMRM);
03048 
03049     // From this finalMRM, build output: a CMeshBuildMRM.
03050     buildMeshBuildMrm(finalMRM, mrmMesh, vbFlags, numMaxMaterial, mbuild);
03051 
03052     // Copy degradation control params.
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 &params, CMeshMRMSkinnedGeom::CMeshBuildMRM &mrmMesh,
03062                                 uint numMaxMaterial)
03063 {
03064     // Temp data.
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     // Copy some parameters.
03078     _SkinReduction= params.SkinReduction;
03079 
03080     // Skinning??
03081     _Skinned= ((mbuild.VertexFlags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag);
03082     // Skinning is OK only if SkinWeights are of same size as vertices.
03083     _Skinned= _Skinned && ( mbuild.Vertices.size()==mbuild.SkinWeights.size() );
03084 
03085     // MeshInterface setuped ?
03086     _HasMeshInterfaces= buildMRMSewingMeshes(mbuild, params.NLods, params.Divisor);
03087 
03088     // from mbuild, build an internal MRM mesh representation.
03089     // vbFlags returned is the VBuffer format supported by CMRMBuilder.
03090     // NB: skinning is removed because skinning is made in software in CMeshMRMGeom.
03091     vbFlags= buildMrmBaseMesh(mbuild, baseMesh);
03092 
03093     // Construct all blend shapes in the same way we have constructed the basemesh mrm
03094     buildBlendShapes (baseMesh, bsList, vbFlags);
03095 
03096     // If skinned, must ensure that skin weights have weights in ascending order.
03097     if(_Skinned)
03098     {
03099         normalizeBaseMeshSkin(baseMesh);
03100     }
03101 
03102     // from this baseMesh, builds all LODs of the MRM, with geomorph info. NB: vertices/wedges are duplicated.
03103     buildAllLods (  baseMesh, lodMeshs, params.NLods, params.Divisor );
03104 
03105     // From this array of LOD, build a finalMRM, by regrouping identical vertices/wedges, and compute index geomorphs.
03106     buildFinalMRM(lodMeshs, finalMRM);
03107 
03108     // From this finalMRM, build output: a CMeshBuildMRM.
03109     buildMeshBuildMrm(finalMRM, mrmMesh, vbFlags, numMaxMaterial, mbuild);
03110 
03111     // Copy degradation control params.
03112     mrmMesh.DistanceFinest= params.DistanceFinest;
03113     mrmMesh.DistanceMiddle= params.DistanceMiddle;
03114     mrmMesh.DistanceCoarsest= params.DistanceCoarsest;
03115 }
03116 
03117 
03118 // ***************************************************************************
03119 // ***************************************************************************
03120 // MRM Interface system
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     // must have same size
03132     if(mbuild.InterfaceLinks.size()!=mbuild.Vertices.size())
03133         return false;
03134 
03135     // **** For each interface, MRM-ize it and store.
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 } // NL3D

Generated on Thu Jan 7 08:26:27 2010 for NeL by  doxygen 1.6.1