NL3D::CMRMBuilder Class Reference

#include <mrm_builder.h>


Detailed Description

The class for building MRMs.
Author:
Lionel Berenguier

Nevrax France

Date:
2000

Definition at line 52 of file mrm_builder.h.

Top Level methods.

typedef std::map< CAttributeKey,
sint
TAttributeMap
CRGBA attToColor (const CVectorH &att) const
NLMISC::CUVW attToUvw (const CVectorH &att) const
void buildMeshBuildMrm (const CMRMMeshFinal &finalMRM, CMeshMRMSkinnedGeom::CMeshBuildMRM &mbuild, uint32 vbFlags, uint32 nbMats, const CMesh::CMeshBuild &mb)
void buildMeshBuildMrm (const CMRMMeshFinal &finalMRM, CMeshMRMGeom::CMeshBuildMRM &mbuild, uint32 vbFlags, uint32 nbMats, const CMesh::CMeshBuild &mb)
uint32 buildMrmBaseMesh (const CMesh::CMeshBuild &mbuild, CMRMMesh &baseMesh)
sint findInsertAttributeInBaseMesh (CMRMMesh &baseMesh, sint attId, sint vertexId, const CVectorH &att)
sint findInsertColorInBaseMesh (CMRMMesh &baseMesh, sint attId, sint vertexId, CRGBA col)
sint findInsertNormalInBaseMesh (CMRMMesh &baseMesh, sint attId, sint vertexId, const CVector &normal)
sint findInsertUvwInBaseMesh (CMRMMesh &baseMesh, sint attId, sint vertexId, const NLMISC::CUVW &uvw)
void normalizeBaseMeshSkin (CMRMMesh &baseMesh) const
CMesh::CSkinWeight normalizeSkinWeight (const CMesh::CSkinWeight &sw) const
TAttributeMap _AttributeMap [NL3D_MRM_MAX_ATTRIB]

MRM Level Variables.

typedef std::map< CMRMWedgeGeom,
sint, CGeomPred
TGeomMap
TGeomMap _GeomMap

Mesh Interfaces computing

bool buildMRMSewingMeshes (const CMesh::CMeshBuild &mbuild, uint nWantedLods, uint divisor)
uint _CurrentLodComputed
bool _HasMeshInterfaces
std::vector< CMRMSewingMesh_SewingMeshes

Public Member Functions

 CMRMBuilder ()
 Constructor.

void compileMRM (const CMesh::CMeshBuild &mbuild, std::vector< CMesh::CMeshBuild * > &bsList, const CMRMParameters &params, CMeshMRMSkinnedGeom::CMeshBuildMRM &mrmMesh, uint numMaxMaterial)
void compileMRM (const CMesh::CMeshBuild &mbuild, std::vector< CMesh::CMeshBuild * > &bsList, const CMRMParameters &params, CMeshMRMGeom::CMeshBuildMRM &mrmMesh, uint numMaxMaterial)

Private Member Functions

void computeBsVerticesAttributes (std::vector< CMRMMesh > &srcBsMeshs, std::vector< CMRMMesh > &srcBsMeshsMod)
void makeCoarserBS (std::vector< CMRMBlendShape > &csBsMeshs)
MRM Level Methods.
void buildAllLods (const CMRMMesh &baseMesh, std::vector< CMRMMeshGeom > &lodMeshs, uint nWantedLods=10, uint divisor=50)
void buildBlendShapes (CMRMMesh &baseMesh, std::vector< CMesh::CMeshBuild * > &bsList, uint32 VertexFlags)
void buildFinalMRM (std::vector< CMRMMeshGeom > &lodMeshs, CMRMMeshFinal &finalMRM)
Collapse methods.
sint collapseEdge (const CMRMEdge &edge)
CMesh::CSkinWeight collapseSkinWeight (const CMesh::CSkinWeight &sw1, const CMesh::CSkinWeight &sw2, float InterValue) const
bool faceShareWedges (CMRMFaceBuild *face, sint attribId, sint numVertex1, sint numVertex2)
sint followVertex (sint i)
sint followWedge (sint attribId, sint i)
void insertFaceIntoEdgeList (CMRMFaceBuild &tmpf)
void removeFaceFromEdgeList (CMRMFaceBuild &f)
Mesh Level methods.
void collapseEdges (sint nWantedFaces)
void init (const CMRMMesh &baseMesh)
void makeFromMesh (const CMRMMesh &baseMesh, CMRMMeshGeom &lodMesh, CMRMMesh &coarserMesh, sint nWantedFaces)
 this is the root call to compute a single lodMesh and the coarserMesh from a baseMesh.

void makeLODMesh (CMRMMeshGeom &lodMesh)
void saveCoarserMesh (CMRMMesh &coarserMesh)
Edge Cost methods.
float computeEdgeCost (const CMRMEdge &edge)
bool edgeContinue (const CMRMEdge &edge)
bool edgeNearUniqueMatFace (const CMRMEdge &edge)
float getDeltaFaceNormals (sint numvertex)
bool vertexClosed (sint numvertex)
bool vertexContinue (sint numvertex)
bool vertexHasOneMaterial (sint numvertex)
bool vertexHasOneWedge (sint numvertex)

Private Attributes

Mesh Level Tmp Values.
bool _Skinned
CMRMParameters::TSkinReduction _SkinReduction
 If the current build is skinned, control the quality of the skinning redcution.

TEdgeMap EdgeCollapses
sint NumAttributes
std::vector< CMRMAttributeTmpAttributes [NL3D_MRM_MAX_ATTRIB]
std::vector< CMRMFaceBuildTmpFaces
std::vector< CMRMVertexTmpVertices


Member Typedef Documentation

typedef std::map<CAttributeKey, sint> NL3D::CMRMBuilder::TAttributeMap [private]
 

Definition at line 228 of file mrm_builder.h.

typedef std::map<CMRMWedgeGeom, sint, CGeomPred> NL3D::CMRMBuilder::TGeomMap [private]
 

Definition at line 179 of file mrm_builder.h.


Constructor & Destructor Documentation

NL3D::CMRMBuilder::CMRMBuilder  ) 
 

Constructor.

Definition at line 859 of file mrm_builder.cpp.

References _HasMeshInterfaces, and NumAttributes.

00860 {
00861         NumAttributes= 0;
00862         _Skinned= false;
00863         _HasMeshInterfaces= false;
00864 }


Member Function Documentation

CRGBA NL3D::CMRMBuilder::attToColor const CVectorH att  )  const [private]
 

Definition at line 1709 of file mrm_builder.cpp.

References NLMISC::CRGBA::A, NLMISC::CRGBA::B, NLMISC::clamp(), NLMISC::CRGBA::G, NLMISC::CRGBA::R, uint, uint8, NLMISC::CVectorH::w, NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z.

Referenced by buildMeshBuildMrm().

01710 {
01711         CRGBA   ret;
01712         float   tmp;
01713         tmp= att.x; clamp(tmp, 0, 255);
01714         ret.R= (uint8)(uint)tmp;
01715         tmp= att.y; clamp(tmp, 0, 255);
01716         ret.G= (uint8)(uint)tmp;
01717         tmp= att.z; clamp(tmp, 0, 255);
01718         ret.B= (uint8)(uint)tmp;
01719         tmp= att.w; clamp(tmp, 0, 255);
01720         ret.A= (uint8)(uint)tmp;
01721 
01722         return ret;
01723 }

NLMISC::CUVW NL3D::CMRMBuilder::attToUvw const CVectorH att  )  const [private]
 

Definition at line 1727 of file mrm_builder.cpp.

References NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z.

Referenced by buildMeshBuildMrm().

01728 {
01729         return CUVW(att.x, att.y, att.z);
01730 }

void NL3D::CMRMBuilder::buildAllLods const CMRMMesh baseMesh,
std::vector< CMRMMeshGeom > &  lodMeshs,
uint  nWantedLods = 10,
uint  divisor = 50
[private]
 

build all LODs from a baseMesh. NB: the coarsestMesh is stored in lodMeshs[0], and has no geomorph info since it is the coarsest mesh. nWantedLods are created (including the coarsestMesh).

Parameters:
lodMeshs array created by the function (size of nWantedlods).
nWantedLods number of LODs wanted.
divisor the coarsestMesh will have baseMesh.Faces.size()/divisor faces.

Definition at line 1287 of file mrm_builder.cpp.

References _CurrentLodComputed, NL3D::CMRMMesh::Faces, init(), makeFromMesh(), nlassert, sint, and uint.

Referenced by compileMRM().

01289 {
01290         sint    nFaces= baseMesh.Faces.size();
01291         sint    nBaseFaces;
01292         sint    i;
01293         CMRMMesh srcMesh = baseMesh;
01294 
01295         // coarsest LOD will have those number of faces.
01296         nBaseFaces=nFaces/divisor;
01297         nBaseFaces=max(nBaseFaces,4);
01298 
01299         // must have at least 2 LOD to be really intersting. But the rest of the process work too with only one Lod!!
01300         nlassert(nWantedLods>=1);
01301         lodMeshs.resize(nWantedLods);
01302 
01303         // If only one lod asked, must init some Tmp Global values (like NumAttributes)
01304         if(nWantedLods==1)
01305         {
01306                 _CurrentLodComputed= 0;
01307                 init(baseMesh);
01308         }
01309 
01310         // must fill all LODs, from end to start. do not proces last lod since it will be the coarsest mesh.
01311         for(i=nWantedLods-1;i>0;i--)
01312         {
01313                 sint    nbWantedFaces;
01314 
01315                 // for sewing computing
01316                 _CurrentLodComputed= i;
01317 
01318                 // Linear.
01319                 nbWantedFaces= nBaseFaces + (nFaces-nBaseFaces) * (i-1)/(nWantedLods-1);
01320                 nbWantedFaces=max(nbWantedFaces,4);
01321 
01322                 // Build this LOD.
01323                 CMRMMesh        csMesh;
01324                 // The mesh
01325                 makeFromMesh(srcMesh, lodMeshs[i], csMesh, nbWantedFaces);
01326 
01327                 // next mesh to process is csMesh.
01328                 srcMesh = csMesh;
01329         }
01330         // the first lodMedsh gets the coarsest mesh.
01331         lodMeshs[0]= srcMesh;
01332 }

void NL3D::CMRMBuilder::buildBlendShapes CMRMMesh baseMesh,
std::vector< CMesh::CMeshBuild * > &  bsList,
uint32  VertexFlags
[private]
 

build the blend shapes in the same way we constructed the base mesh mrm

Definition at line 2912 of file mrm_builder.cpp.

References NLMISC::CRGBA::A, NL3D::CMRMCorner::Attributes, NL3D::CMRMMesh::Attributes, NLMISC::CRGBA::B, NL3D::CMRMMesh::BlendShapes, NL3D::CMesh::CCorner::Color, NL3D::CMRMMesh::Faces, NLMISC::CRGBA::G, nlassert, NL3D::CMesh::CCorner::Normal, NL3D::CMRMMesh::NumAttributes, NLMISC::CRGBA::R, NL3D::CMesh::CCorner::Specular, NLMISC::CUVW::U, uint32, NL3D::CMesh::CCorner::Uvws, NLMISC::CUVW::V, NL3D::CMRMMesh::Vertices, NLMISC::CUVW::W, NLMISC::CVectorH::w, NLMISC::CVector::x, NLMISC::CVectorH::x, NLMISC::CVector::y, NLMISC::CVectorH::y, NLMISC::CVector::z, and NLMISC::CVectorH::z.

Referenced by compileMRM().

02914 {
02915         uint32 i, j, k, m, destIndex;
02916         uint32 attId;
02917         CVectorH vh;
02918         vector<CMRMBlendShape>  &bsMeshes= baseMesh.BlendShapes;
02919 
02920         bsMeshes.resize (bsList.size());
02921 
02922         for (i = 0; i < bsList.size(); ++i)
02923         {
02924                 // Construct a blend shape like a mrm mesh
02925                 nlassert (baseMesh.Vertices.size() == bsList[i]->Vertices.size());
02926                 bsMeshes[i].Vertices.resize (baseMesh.Vertices.size());
02927                 bsMeshes[i].Vertices = bsList[i]->Vertices;
02928 
02929                 bsMeshes[i].NumAttributes = baseMesh.NumAttributes;
02930                 for (j = 0; j < (uint32)bsMeshes[i].NumAttributes; ++j)
02931                         bsMeshes[i].Attributes[j].resize(baseMesh.Attributes[j].size());
02932 
02933                 // For all corners parse the faces (given by the baseMesh) and construct blend shape mrm meshes
02934                 for (j = 0; j < baseMesh.Faces.size(); ++j)
02935                 for (k = 0; k < 3; ++k)
02936                 {
02937                         const CMesh::CCorner &srcCorner = bsList[i]->Faces[j].Corner[k];
02938                         CMRMCorner      &neutralCorner = baseMesh.Faces[j].Corner[k];
02939                         
02940                         attId= 0;
02941 
02942                         if (VertexFlags & CVertexBuffer::NormalFlag)
02943                         {
02944                                 destIndex = neutralCorner.Attributes[attId];
02945                                 vh.x = srcCorner.Normal.x;
02946                                 vh.y = srcCorner.Normal.y;
02947                                 vh.z = srcCorner.Normal.z;
02948                                 vh.w = 0.0f;
02949                                 bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02950                                 attId++;
02951                         }
02952                         if (VertexFlags & CVertexBuffer::PrimaryColorFlag)
02953                         {
02954                                 destIndex = neutralCorner.Attributes[attId];
02955                                 vh.x = srcCorner.Color.R;
02956                                 vh.y = srcCorner.Color.G;
02957                                 vh.z = srcCorner.Color.B;
02958                                 vh.w = srcCorner.Color.A;
02959                                 bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02960                                 attId++;
02961                         }
02962                         if (VertexFlags & CVertexBuffer::SecondaryColorFlag)
02963                         {
02964                                 destIndex = neutralCorner.Attributes[attId];
02965                                 vh.x = srcCorner.Specular.R;
02966                                 vh.y = srcCorner.Specular.G;
02967                                 vh.z = srcCorner.Specular.B;
02968                                 vh.w = srcCorner.Specular.A;
02969                                 bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02970                                 attId++;
02971                         }
02972                         for (m = 0; m < CVertexBuffer::MaxStage; ++m)
02973                         {
02974                                 if (VertexFlags & (CVertexBuffer::TexCoord0Flag<<m))
02975                                 {
02976                                         destIndex = neutralCorner.Attributes[attId];
02977                                         vh.x = srcCorner.Uvws[m].U;
02978                                         vh.y = srcCorner.Uvws[m].V;
02979                                         vh.z = srcCorner.Uvws[m].W;
02980                                         vh.w = 0.0f;
02981                                         bsMeshes[i].Attributes[attId].operator[](destIndex) = vh;
02982                                         attId++;
02983                                 }
02984                         }
02985                 }
02986         }
02987 }

void NL3D::CMRMBuilder::buildFinalMRM std::vector< CMRMMeshGeom > &  lodMeshs,
CMRMMeshFinal finalMRM
[private]
 

given a list of LODs, compress/reorganize data, and store in finalMRM mesh.

Definition at line 1336 of file mrm_builder.cpp.

References _GeomMap, NL3D::CMRMCorner::Attributes, NL3D::CMRMMesh::Attributes, NL3D::CMRMMeshFinal::CWedge::Attributes, NL3D::CMRMMesh::BlendShapes, NL3D::CMRMMeshGeom::CoarserFaces, NL3D::CMRMFace::Corner, NL3D::CMRMWedgeGeom::End, NL3D::CMRMMeshFinal::CLod::Faces, NL3D::CMRMMesh::Faces, NL3D::CMRMMeshFinal::findInsertWedge(), NL3D::CMRMMeshFinal::CLod::Geomorphs, NL3D::CMRMMeshFinal::Lods, NL3D::CMRMFace::MaterialId, NL3D::CMRMMeshFinal::CFace::MaterialId, NL3D::CMRMMeshFinal::MRMBlendShapesFinals, NL3D::CMRMMeshFinal::NGeomSpace, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, NL3D::CMRMMeshFinal::CWedge::NSkinMatUsed, NumAttributes, NL3D::CMRMMeshFinal::NumAttributes, NL3D::CMRMMeshFinal::reset(), sint, NL3D::CMRMMeshFinal::Skinned, NL3D::CMRMMesh::SkinWeights, NL3D::CMRMWedgeGeom::Start, NL3D::CMRMCorner::Vertex, NL3D::CMRMMeshFinal::CWedge::Vertex, NL3D::CMRMMeshFinal::CWedge::VertexSkin, NL3D::CMRMMesh::Vertices, NL3D::CMRMCorner::WedgeEndId, NL3D::CMRMCorner::WedgeGeomId, NL3D::CMRMMeshFinal::CFace::WedgeId, NL3D::CMRMMeshFinal::CMRMBlendShapeFinal::Wedges, NL3D::CMRMMeshFinal::Wedges, NL3D::CMRMCorner::WedgeStartId, and NL3D::CMesh::CSkinWeight::Weights.

Referenced by compileMRM().

01337 {
01338         sint    i,j;
01339         sint    lodId, attId;
01340         sint    nLods= lodMeshs.size();
01341 
01342         // Init.
01343         // ===============
01344         finalMRM.reset();
01345         finalMRM.NumAttributes= NumAttributes;
01346         finalMRM.Skinned= _Skinned;
01347         CMRMMeshFinal::CWedge::NumAttributesToCompare= NumAttributes;
01348         CMRMMeshFinal::CWedge::CompareSkinning= _Skinned;
01349         finalMRM.Lods.resize(nLods);
01350 
01351 
01352         // Build Wedges, and faces index.
01353         // ===============
01354         // for all lods.
01355         for(lodId=0; lodId<nLods; lodId++)
01356         {
01357                 CMRMMeshGeom    &lodMesh= lodMeshs[lodId];
01358                 CMRMMeshGeom    &lodMeshPrec= lodMeshs[lodId==0?0:lodId-1];
01359                 // for all face corner.
01360                 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01361                 {
01362                         // The current face.
01363                         CMRMFace        &face= lodMesh.Faces[i];
01364                         // the current face, but which points to the prec LOD vertices/attributes.
01365                         CMRMFace        &faceCoarser= lodMesh.CoarserFaces[i];
01366                         // for 3 corners.
01367                         for(j=0;j<3;j++)
01368                         {
01369                                 CMRMCorner      &corner= face.Corner[j];
01370                                 CMRMCorner      &cornerCoarser= faceCoarser.Corner[j];
01371                                 // start and end wedge (geomorph), maybe same.
01372                                 CMRMMeshFinal::CWedge           wedgeStart;
01373                                 CMRMMeshFinal::CWedge           wedgeEnd;
01374 
01375                                 // fill wedgeStart with values from lodMesh.
01376                                 wedgeStart.Vertex= lodMesh.Vertices[corner.Vertex];
01377                                 if(_Skinned)
01378                                         wedgeStart.VertexSkin= lodMesh.SkinWeights[corner.Vertex];
01379                                 for(attId=0; attId<NumAttributes; attId++)
01380                                 {
01381                                         wedgeStart.Attributes[attId]= lodMesh.Attributes[attId][corner.Attributes[attId]];
01382                                 }
01383 
01384                                 // if geomorph possible (ie not lod 0).
01385                                 if(lodId>0)
01386                                 {
01387                                         // fill wedgeEnd with values from coarser lodMesh.
01388                                         wedgeEnd.Vertex= lodMeshPrec.Vertices[cornerCoarser.Vertex];
01389                                         if(_Skinned)
01390                                                 wedgeEnd.VertexSkin= lodMeshPrec.SkinWeights[cornerCoarser.Vertex];
01391                                         for(attId=0; attId<NumAttributes; attId++)
01392                                         {
01393                                                 wedgeEnd.Attributes[attId]= lodMeshPrec.Attributes[attId][cornerCoarser.Attributes[attId]];
01394                                         }
01395                                 }
01396                                 else
01397                                 {
01398                                         // no geomorph.
01399                                         wedgeEnd= wedgeStart;
01400                                 }
01401 
01402                                 // find/insert wedge, and get Ids. NB: if start/end same, same indices.
01403                                 sint    wedgeStartId= finalMRM.findInsertWedge(wedgeStart);
01404                                 sint    wedgeEndId= finalMRM.findInsertWedge(wedgeEnd);
01405 
01406                                 // store in TmpCorner.
01407                                 corner.WedgeStartId= wedgeStartId;
01408                                 corner.WedgeEndId= wedgeEndId;
01409                         }
01410                 }
01411 
01412                 // Here, the number of wedge indicate the max number of wedge this LOD needs.
01413                 finalMRM.Lods[lodId].NWedges= finalMRM.Wedges.size();
01414         }
01415 
01416 
01417         // Count NBWedges necessary for geomorph, and compute Dest geomorph wedges ids.
01418         // ===============
01419         // the number of geomorph required for one LOD.
01420         sint    sglmGeom;
01421         // the number of geomorph required for all LOD (max of sglmGeom).
01422         sint    sglmGeomMax= 0;
01423 
01424         // Do not process lod 0, since no geomorph.
01425         for(lodId=1; lodId<nLods; lodId++)
01426         {
01427                 CMRMMeshGeom    &lodMesh= lodMeshs[lodId];
01428 
01429                 // reset the GeomMap, the one which indicate if we have already inserted a geomorph.
01430                 _GeomMap.clear();
01431                 sglmGeom= 0;
01432 
01433                 // for all face corner.
01434                 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01435                 {
01436                         // The current face.
01437                         CMRMFace        &face= lodMesh.Faces[i];
01438                         // for 3 corners.
01439                         for(j=0;j<3;j++)
01440                         {
01441                                 CMRMCorner      &corner= face.Corner[j];
01442 
01443                                 // if not same wedge Ids, this is a geomorphed wedge.
01444                                 if(corner.WedgeStartId != corner.WedgeEndId)
01445                                 {
01446                                         // search if it exist yet in the set.
01447                                         CMRMWedgeGeom   geom;
01448                                         geom.Start= corner.WedgeStartId;
01449                                         geom.End= corner.WedgeEndId;
01450                                         sint    geomDest= sglmGeom;
01451                                         // if don't find this geom in the set, then it is a new one.
01452                                         TGeomMap::const_iterator        it= _GeomMap.find(geom);
01453                                         if(it == _GeomMap.end())
01454                                         {
01455                                                 _GeomMap.insert( make_pair(geom, geomDest) );
01456                                                 sglmGeom++;
01457                                         }
01458                                         else
01459                                                 geomDest= it->second;
01460 
01461                                         // store this Geom Id in the corner.
01462                                         corner.WedgeGeomId= geomDest;
01463                                 }
01464                         }
01465                 }
01466 
01467                 // take the max.
01468                 sglmGeomMax= max(sglmGeomMax, sglmGeom);
01469         }
01470 
01471         
01472         // inform the finalMRM.
01473         finalMRM.NGeomSpace= sglmGeomMax;
01474 
01475 
01476         // decal all wedges/ face index.
01477         // ===============
01478         // insert an empty space for dest geomorph.
01479         finalMRM.Wedges.insert(finalMRM.Wedges.begin(), sglmGeomMax, CMRMMeshFinal::CWedge());
01480 
01481         // Parse all faces corner of All lods, and decal Start/End Wedge index.
01482         for(lodId=0; lodId<nLods; lodId++)
01483         {
01484                 CMRMMeshGeom    &lodMesh= lodMeshs[lodId];
01485 
01486                 // for all face corner.
01487                 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01488                 {
01489                         // The current face.
01490                         CMRMFace        &face= lodMesh.Faces[i];
01491                         // for 3 corners.
01492                         for(j=0;j<3;j++)
01493                         {
01494                                 CMRMCorner      &corner= face.Corner[j];
01495 
01496                                 // decal indices.
01497                                 corner.WedgeStartId+= sglmGeomMax;
01498                                 corner.WedgeEndId+= sglmGeomMax;
01499                         }
01500                 }
01501 
01502                 // increment too the number of wedge required for this Lod.
01503                 finalMRM.Lods[lodId].NWedges+= sglmGeomMax;
01504         }
01505 
01506 
01507         // fill faces.
01508         // ===============
01509         // Parse all faces corner of All lods, and build Faces/Geomorphs..
01510         for(lodId=0; lodId<nLods; lodId++)
01511         {
01512                 CMRMMeshGeom                    &lodMesh= lodMeshs[lodId];
01513                 CMRMMeshFinal::CLod             &lodDest= finalMRM.Lods[lodId];
01514 
01515                 // alloc final faces of this LOD.
01516                 lodDest.Faces.resize(lodMesh.Faces.size());
01517 
01518                 // reset the GeomMap, the one which indicate if we have already inserted a geomorph.
01519                 _GeomMap.clear();
01520 
01521                 // for all face corner.
01522                 for(i=0; i<(sint)lodMesh.Faces.size();i++)
01523                 {
01524                         // The current face.
01525                         CMRMFace        &face= lodMesh.Faces[i];
01526                         // The dest face.
01527                         CMRMMeshFinal::CFace            &faceDest= lodDest.Faces[i];
01528                         // fill good material.
01529                         faceDest.MaterialId= face.MaterialId;
01530 
01531                         // for 3 corners.
01532                         for(j=0;j<3;j++)
01533                         {
01534                                 CMRMCorner      &corner= face.Corner[j];
01535 
01536                                 // if not same wedge Ids, this is a geomorphed wedge.
01537                                 if(corner.WedgeStartId != corner.WedgeEndId)
01538                                 {
01539                                         // geomorph, so point to geomorphed wedge.
01540                                         faceDest.WedgeId[j]= corner.WedgeGeomId;
01541 
01542                                         // Build the geomorph, add it to the list (if not yet inserted).
01543                                         CMRMWedgeGeom   geom;
01544                                         geom.Start= corner.WedgeStartId;
01545                                         geom.End=       corner.WedgeEndId;
01546                                         // if don't find this geom in the set, then it is a new one.
01547                                         TGeomMap::const_iterator        it= _GeomMap.find(geom);
01548                                         if(it == _GeomMap.end())
01549                                         {
01550                                                 // mark it as inserted.
01551                                                 _GeomMap.insert( make_pair(geom, corner.WedgeGeomId) );
01552                                                 // and we must insert this geom in the array.
01553                                                 nlassert( corner.WedgeGeomId==(sint)lodDest.Geomorphs.size() );
01554                                                 lodDest.Geomorphs.push_back(geom);
01555                                         }
01556                                 }
01557                                 else
01558                                 {
01559                                         // no geomorph, so just point to good wedge.
01560                                         faceDest.WedgeId[j]= corner.WedgeStartId;
01561                                 }
01562                         }
01563                 }
01564         }
01565 
01566 
01567         // process all wedges, and compute NSkinMatUsed, skipping geomorphs.
01568         // ===============
01569         // NB: this works because weights are sorted from biggest to lowest.
01570         if(_Skinned)
01571         {
01572                 for(i=finalMRM.NGeomSpace; i<(sint)finalMRM.Wedges.size();i++)
01573                 {
01574                         CMRMMeshFinal::CWedge   &wedge= finalMRM.Wedges[i];
01575                         for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
01576                         {
01577                                 if(wedge.VertexSkin.Weights[j]==0)
01578                                         break;
01579                         }
01580                         nlassert(j>0);
01581                         wedge.NSkinMatUsed= j;
01582                 }
01583         }
01584 
01585         // Blend Shape Stuff
01586         finalMRM.MRMBlendShapesFinals.resize (lodMeshs[0].BlendShapes.size());
01587         for (lodId = 0; lodId < nLods; ++lodId)
01588         {
01589                 CMRMMeshGeom &lodMesh= lodMeshs[lodId];
01590                 CMRMMeshGeom &lodMeshPrec= lodMeshs[lodId==0?0:lodId-1];
01591 
01592                 // for all face corner.
01593                 for (i = 0; i < (sint)lodMesh.Faces.size(); ++i)
01594                 {
01595                         // The current face.
01596                         CMRMFace &face = lodMesh.Faces[i];
01597                         // the current face, but which points to the prec LOD vertices/attributes.
01598                         CMRMFace &faceCoarser = lodMesh.CoarserFaces[i];
01599                         // for 3 corners.
01600                         for (j = 0; j < 3; ++j)
01601                         {
01602                                 CMRMCorner &corner = face.Corner[j];
01603                                 CMRMCorner &cornerCoarser = faceCoarser.Corner[j];
01604 
01605                                 sint startDestIndex = corner.WedgeStartId;
01606 
01607                                 for (sint k = 0; k < (sint)finalMRM.MRMBlendShapesFinals.size(); ++k)
01608                                 {
01609                                         CMRMMeshFinal::CMRMBlendShapeFinal &rBSFinal = finalMRM.MRMBlendShapesFinals[k];
01610 
01611                                         rBSFinal.Wedges.resize (finalMRM.Wedges.size());
01612                                         // Fill WedgeStart used by this corner.
01613                                         rBSFinal.Wedges[startDestIndex].Vertex = lodMesh.BlendShapes[k].Vertices[corner.Vertex];
01614                                         for (attId = 0; attId < NumAttributes; ++attId)
01615                                         {
01616                                                 rBSFinal.Wedges[startDestIndex].Attributes[attId] = lodMesh.BlendShapes[k].Attributes[attId][corner.Attributes[attId]];
01617                                         }
01618 
01619                                         // If geomorph, must fill the end too
01620                                         if(lodId>0 && corner.WedgeStartId != corner.WedgeEndId)
01621                                         {
01622                                                 sint endDestIndex = corner.WedgeEndId;
01623 
01624                                                 rBSFinal.Wedges[endDestIndex].Vertex = lodMeshPrec.BlendShapes[k].Vertices[cornerCoarser.Vertex];
01625                                                 for (attId = 0; attId < NumAttributes; ++attId)
01626                                                 {
01627                                                         rBSFinal.Wedges[endDestIndex].Attributes[attId] = lodMeshPrec.BlendShapes[k].Attributes[attId][cornerCoarser.Attributes[attId]];
01628                                                 }
01629                                         }
01630                                 }
01631 
01632                         }
01633                 }
01634         }
01635 }

void NL3D::CMRMBuilder::buildMeshBuildMrm const CMRMMeshFinal finalMRM,
CMeshMRMSkinnedGeom::CMeshBuildMRM mbuild,
uint32  vbFlags,
uint32  nbMats,
const CMesh::CMeshBuild mb
[private]
 

from a final MRM Mesh representation, compute a CMeshBuildMRM. This is the last stage of the algo.

Parameters:
vbFlags the vertex format returned by earlier call too buildMrmBaseMesh().
nbMats the number of materials of original MeshBuild.

Definition at line 2414 of file mrm_builder.cpp.

References NLMISC::CRGBAF::A, NL3D::CVertexBuffer::addValueEx(), NL3D::CMRMMeshFinal::CWedge::Attributes, attToColor(), attToUvw(), NLMISC::CRGBAF::B, NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::BlendShapes, NL3D::CVertexBuffer::clearValueEx(), NL3D::CBlendShape::deltaCol, NL3D::CBlendShape::deltaNorm, NL3D::CBlendShape::deltaPos, NL3D::CBlendShape::deltaTgSpace, NL3D::CBlendShape::deltaUV, NL3D::CMRMMeshFinal::CLod::Faces, NLMISC::CRGBAF::G, NL3D::CMRMMeshFinal::CLod::Geomorphs, NL3D::CMeshMRMSkinnedGeom::CLod::Geomorphs, NL3D::CMeshMRMSkinnedGeom::CLod::InfluencedVertices, NL3D::CVertexBuffer::initEx(), NL3D::CMRMMeshFinal::Lods, NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::Lods, NL3D::CMesh::CSkinWeight::MatrixId, NL3D::CMeshMRMSkinnedGeom::CLod::MatrixInfluences, NL3D::CMesh::CMeshBuild::MeshVertexProgram, NL3D::CMRMMeshFinal::MRMBlendShapesFinals, NL3D::CMRMMeshFinal::NGeomSpace, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, NLMISC::CVector::norm(), NL3D::CMesh::CMeshBuild::NumCoords, NL3D::CMRMMeshFinal::CLod::NWedges, NL3D::CMeshMRMSkinnedGeom::CLod::NWedges, NLMISC::CRGBAF::R, NL3D::CMeshMRMSkinnedGeom::CLod::RdrPass, NL3D::CVertexBuffer::setColor(), NL3D::CVertexBuffer::setNormalCoord(), NL3D::CVertexBuffer::setNumVertices(), NL3D::CVertexBuffer::setSpecular(), NL3D::CVertexBuffer::setTexCoord(), NL3D::CVertexBuffer::setUVRouting(), NL3D::CVertexBuffer::setValueFloat3Ex(), NL3D::CVertexBuffer::setVertexCoord(), NL3D::CVertexBuffer::setVertexFormat(), sint, sint32, NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::Skinned, NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::SkinWeights, NLMISC::CUV::U, NLMISC::CUVW::U, uint, uint32, NL3D::CMesh::CMeshBuild::UVRouting, NLMISC::CUV::V, NLMISC::CUVW::V, NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::VBuffer, NL3D::CMRMMeshFinal::CWedge::Vertex, NL3D::CMRMMeshFinal::CWedge::VertexSkin, NL3D::CBlendShape::VertRefs, NLMISC::CVectorH::w, NLMISC::CUVW::W, NL3D::CMRMMeshFinal::Wedges, NL3D::CMesh::CSkinWeight::Weights, NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z.

02415 {
02416         sint    i,j,k;
02417         sint    attId;
02418 
02419         // reset the mbuild.
02420         mbuild= CMeshMRMSkinnedGeom::CMeshBuildMRM();
02421         // Setup VB.
02422 
02423         bool useFormatExt = false;
02424         // Check wether there are texture coordinates with more than 2 compnents, which force us to use an extended vertex format
02425         for (k = 0; k < CVertexBuffer::MaxStage; ++k)
02426         {
02427                 if (
02428                         (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
02429                         && mb.NumCoords[k] != 2)
02430                 {
02431                         useFormatExt = true;
02432                         break;
02433                 }
02434         }
02435 
02436         uint numTexCoordUsed = 0;
02437 
02438 
02439         for (k = 0; k < CVertexBuffer::MaxStage; ++k)
02440         {
02441                 if (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
02442                 {
02443                         numTexCoordUsed = k;
02444                 }
02445         }
02446 
02447         if (!useFormatExt)
02448         {
02449                 // setup standard format
02450                 mbuild.VBuffer.setVertexFormat(vbFlags);
02451         }
02452         else // setup extended format
02453         {
02454                 mbuild.VBuffer.clearValueEx();
02455                 if (vbFlags & CVertexBuffer::PositionFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Position, CVertexBuffer::Float3);
02456                 if (vbFlags & CVertexBuffer::NormalFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Normal, CVertexBuffer::Float3);
02457                 if (vbFlags & CVertexBuffer::PrimaryColorFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::PrimaryColor, CVertexBuffer::UChar4);
02458                 if (vbFlags & CVertexBuffer::SecondaryColorFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::SecondaryColor, CVertexBuffer::UChar4);
02459                 if (vbFlags & CVertexBuffer::WeightFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Weight, CVertexBuffer::Float4);
02460                 if (vbFlags & CVertexBuffer::PaletteSkinFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::PaletteSkin, CVertexBuffer::UChar4);
02461                 if (vbFlags & CVertexBuffer::FogFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Fog, CVertexBuffer::Float1);
02462 
02463                 for (k = 0; k < CVertexBuffer::MaxStage; ++k)
02464                 {
02465                         if (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
02466                         {
02467                                 switch(mb.NumCoords[k])
02468                                 {       
02469                                         case 2:
02470                                                 mbuild.VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float2);
02471                                         break;
02472                                         case 3:
02473                                                 mbuild.VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float3);
02474                                         break;
02475                                         default:
02476                                                 nlassert(0);
02477                                         break;
02478                                 }
02479                         }
02480                 }
02481                 mbuild.VBuffer.initEx();
02482         }
02483 
02484         // Copy the UVRouting
02485         for (i=0; i<CVertexBuffer::MaxStage; i++)
02486         {
02487                 mbuild.VBuffer.setUVRouting (i, mb.UVRouting[i]);
02488         }
02489 
02490         // Setup the VertexBuffer.
02491         // ========================
02492         // resize the VB.
02493         mbuild.VBuffer.setNumVertices(finalMRM.Wedges.size());
02494         // Setup SkinWeights.
02495         if(_Skinned)
02496                 mbuild.SkinWeights.resize(finalMRM.Wedges.size());
02497 
02498         // fill the VB.
02499         for(i=0; i<(sint)finalMRM.Wedges.size(); i++)
02500         {
02501                 const CMRMMeshFinal::CWedge     &wedge= finalMRM.Wedges[i];
02502 
02503                 // setup Vertex.
02504                 mbuild.VBuffer.setVertexCoord(i, wedge.Vertex);
02505 
02506                 // seutp attributes.
02507                 attId= 0;
02508 
02509                 // For all activated attributes in mbuild, retriev the attribute from the finalMRM.
02510                 if(vbFlags & CVertexBuffer::NormalFlag)
02511                 {
02512                         mbuild.VBuffer.setNormalCoord(i, wedge.Attributes[attId] );
02513                         attId++;
02514                 }
02515                 if(vbFlags & CVertexBuffer::PrimaryColorFlag)
02516                 {
02517                         mbuild.VBuffer.setColor(i, attToColor(wedge.Attributes[attId]) );
02518                         attId++;
02519                 }
02520                 if(vbFlags & CVertexBuffer::SecondaryColorFlag)
02521                 {
02522                         mbuild.VBuffer.setSpecular(i, attToColor(wedge.Attributes[attId]) );
02523                         attId++;
02524                 }
02525                 for(k=0; k<CVertexBuffer::MaxStage;k++)
02526                 {
02527                         if(vbFlags & (CVertexBuffer::TexCoord0Flag<<k))
02528                         {
02529                                 switch(mb.NumCoords[k])
02530                                 {
02531                                         case 2:                         
02532                                                 mbuild.VBuffer.setTexCoord(i, k, (CUV) attToUvw(wedge.Attributes[attId]) );
02533                                         break;
02534                                         case 3:
02535                                         {
02536                                                 CUVW uvw = attToUvw(wedge.Attributes[attId]);
02537                                                 mbuild.VBuffer.setValueFloat3Ex((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), i, uvw.U, uvw.V, uvw.W);
02538                                         }
02539                                         break;
02540                                         default:
02541                                                 nlassert(0);
02542                                         break;
02543                                 }
02544                                 attId++;
02545                         }
02546                 }
02547 
02548                 // Setup SkinWeights.
02549                 if(_Skinned)
02550                 {
02551                         mbuild.SkinWeights[i]= wedge.VertexSkin;
02552                 }
02553         }
02554 
02555 
02556         // Build Lods.
02557         // ========================
02558         // resize
02559         mbuild.Lods.resize(finalMRM.Lods.size());
02560         // fill.
02561         for(i=0; i<(sint)finalMRM.Lods.size(); i++)
02562         {
02563                 const CMRMMeshFinal::CLod       &srcLod= finalMRM.Lods[i];
02564                 CMeshMRMSkinnedGeom::CLod                       &destLod= mbuild.Lods[i];
02565 
02566                 // Basic.
02567                 //---------
02568 
02569                 // Copy NWedges infos.
02570                 destLod.NWedges= srcLod.NWedges;
02571                 // Copy Geomorphs infos.
02572                 destLod.Geomorphs= srcLod.Geomorphs;
02573 
02574 
02575                 // Reorder faces by rdrpass.
02576                 //---------
02577 
02578                 // First count the number of faces used by this LOD for each material 
02579                 vector<sint>    matCount;
02580                 // resize, and reset to 0.
02581                 matCount.clear();
02582                 matCount.resize(nbMats, 0);
02583                 // For each face of this Lods, incr the mat face counter.
02584                 for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02585                 {
02586                         sint    matId= srcLod.Faces[j].MaterialId;
02587                         nlassert(matId>=0);
02588                         nlassert(matId<(sint)nbMats);
02589                         // increment the refcount of this material by this LOD.
02590                         matCount[matId]++;
02591                 }
02592 
02593                 // Then for each material not empty, create a rdrPass, and ref it for this material.
02594                 vector<sint>    rdrPassIndex;   // material to rdrPass map.
02595                 rdrPassIndex.resize(nbMats);
02596                 for(j=0; j<(sint)nbMats; j++)
02597                 {
02598                         if(matCount[j]==0)
02599                                 rdrPassIndex[j]= -1;
02600                         else
02601                         {
02602                                 // map material to rdrPass.
02603                                 sint    idRdrPass= destLod.RdrPass.size();
02604                                 rdrPassIndex[j]= idRdrPass;
02605                                 // create a rdrPass.
02606                                 destLod.RdrPass.push_back(CMeshMRMSkinnedGeom::CRdrPass());
02607                                 // assign the good materialId to this rdrPass.
02608                                 destLod.RdrPass[idRdrPass].MaterialId= j;
02609                                 // reserve the array of faces of this rdrPass.
02610                                 destLod.RdrPass[idRdrPass].PBlock.reserve(3*matCount[j]);
02611                         }
02612                 }
02613 
02614                 // Then for each face, add it to the good rdrPass of this Lod.
02615                 for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02616                 {
02617                         sint    matId= srcLod.Faces[j].MaterialId;
02618                         sint    idRdrPass= rdrPassIndex[matId];
02619                         // add this face to the good rdrPass.
02620                         sint    w0= srcLod.Faces[j].WedgeId[0];
02621                         sint    w1= srcLod.Faces[j].WedgeId[1];
02622                         sint    w2= srcLod.Faces[j].WedgeId[2];
02623                         destLod.RdrPass[idRdrPass].PBlock.push_back (w0);
02624                         destLod.RdrPass[idRdrPass].PBlock.push_back (w1);
02625                         destLod.RdrPass[idRdrPass].PBlock.push_back (w2);
02626                 }
02627 
02628 
02629                 // Build skin info for this Lod.
02630                 //---------
02631                 for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
02632                 {
02633                         destLod.InfluencedVertices[j].clear();
02634                 }
02635                 destLod.MatrixInfluences.clear();
02636                 if(_Skinned)
02637                 {
02638                         // This is the set which tell what wedge has already been inserted.
02639                         set<uint>       wedgeInfSet;
02640 
02641                         // First, build the list of vertices influenced by this Lod.
02642                         for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02643                         {
02644                                 for(k=0; k<3; k++)
02645                                 {
02646                                         sint    wedgeId= srcLod.Faces[j].WedgeId[k];
02647                                         // If it is a geomorph
02648                                         if(wedgeId<finalMRM.NGeomSpace)
02649                                         {
02650                                                 // add the start and end to the list (if not here). NB: wedgeId is both the id 
02651                                                 // of the dest wedge, and the id of the geomorph.
02652                                                 sint    wedgeStartId= destLod.Geomorphs[wedgeId].Start;
02653                                                 sint    wedgeEndId= destLod.Geomorphs[wedgeId].End;
02654                                                 uint    nMatUsedStart= finalMRM.Wedges[wedgeStartId].NSkinMatUsed;
02655                                                 uint    nMatUsedEnd= finalMRM.Wedges[wedgeEndId].NSkinMatUsed;
02656 
02657                                                 // if insertion in the set work, add to the good array.
02658                                                 if( wedgeInfSet.insert(wedgeStartId).second )
02659                                                         destLod.InfluencedVertices[nMatUsedStart-1].push_back(wedgeStartId);
02660                                                 if( wedgeInfSet.insert(wedgeEndId).second )
02661                                                         destLod.InfluencedVertices[nMatUsedEnd-1].push_back(wedgeEndId);
02662                                         }
02663                                         else
02664                                         {
02665                                                 uint    nMatUsed= finalMRM.Wedges[wedgeId].NSkinMatUsed;
02666 
02667                                                 // just add this wedge to the list (if not here).
02668                                                 // if insertion in the set work, add to the array.
02669                                                 if( wedgeInfSet.insert(wedgeId).second )
02670                                                         destLod.InfluencedVertices[nMatUsed-1].push_back(wedgeId);
02671                                         }
02672                                 }
02673                         }
02674 
02675                         // Optimisation: for better cache, sort the destLod.InfluencedVertices in increasing order.
02676                         for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
02677                         {
02678                                 sort(destLod.InfluencedVertices[j].begin(), destLod.InfluencedVertices[j].end());
02679                         }
02680 
02681 
02682                         // Then Build the MatrixInfluences array, for all thoses Influenced Vertices only.
02683                         // This is the map MatrixId -> MatrixInfId.
02684                         map<uint, uint>         matrixInfMap;
02685 
02686                         // For all influenced vertices, flags matrix they use.
02687                         uint    iSkinMat;
02688                         for(iSkinMat= 0; iSkinMat<NL3D_MESH_SKINNING_MAX_MATRIX; iSkinMat++)
02689                         {
02690                                 for(j= 0; j<(sint)destLod.InfluencedVertices[iSkinMat].size(); j++)
02691                                 {
02692                                         uint    wedgeId= destLod.InfluencedVertices[iSkinMat][j];
02693 
02694                                         // take the original wedge.
02695                                         const CMRMMeshFinal::CWedge     &wedge= finalMRM.Wedges[wedgeId];
02696                                         // For all matrix with not null influence...
02697                                         for(k= 0; k<NL3D_MESH_SKINNING_MAX_MATRIX; k++)
02698                                         {
02699                                                 float   matWeight= wedge.VertexSkin.Weights[k];
02700 
02701                                                 // This check the validity of skin weights sort. If false, problem before in the algo.
02702                                                 if((uint)k<iSkinMat+1)
02703                                                 {
02704                                                         nlassert( matWeight>0 );
02705                                                 }
02706                                                 else
02707                                                 {
02708                                                         nlassert( matWeight==0 );
02709                                                 }
02710                                                 // if not null influence.
02711                                                 if(matWeight>0)
02712                                                 {
02713                                                         uint    matId= wedge.VertexSkin.MatrixId[k];
02714 
02715                                                         // search/insert the matrixInfId.
02716                                                         map<uint, uint>::iterator       it= matrixInfMap.find(matId);
02717                                                         if( it==matrixInfMap.end() )
02718                                                         {
02719                                                                 uint matInfId= destLod.MatrixInfluences.size();
02720                                                                 matrixInfMap.insert( make_pair(matId, matInfId) );
02721                                                                 // create the new MatrixInfluence.
02722                                                                 destLod.MatrixInfluences.push_back(matId);
02723                                                         }
02724                                                 }
02725                                         }
02726                                 }
02727                         }
02728 
02729                 }
02730 
02731         }
02732 
02733         // Indicate Skinning.
02734         mbuild.Skinned= _Skinned;
02735 
02736 
02737 
02738         bool useTgSpace = mb.MeshVertexProgram != NULL ? mb.MeshVertexProgram->needTangentSpace() : false;
02739 
02740         // Construct Blend Shapes
02742         mbuild.BlendShapes.resize (finalMRM.MRMBlendShapesFinals.size());
02743         for (k = 0; k < (sint)mbuild.BlendShapes.size(); ++k)
02744         {
02745                 CBlendShape &rBS = mbuild.BlendShapes[k];
02746                 sint32 nNbVertVB = finalMRM.Wedges.size();
02747                 bool bIsDeltaPos = false;
02748                 rBS.deltaPos.resize (nNbVertVB, CVector(0.0f,0.0f,0.0f));
02749                 bool bIsDeltaNorm = false;
02750                 rBS.deltaNorm.resize (nNbVertVB, CVector(0.0f,0.0f,0.0f));
02751                 bool bIsDeltaUV = false;
02752                 rBS.deltaUV.resize (nNbVertVB, CUV(0.0f,0.0f));
02753                 bool bIsDeltaCol = false;
02754                 rBS.deltaCol.resize (nNbVertVB, CRGBAF(0.0f,0.0f,0.0f,0.0f));
02755                 bool bIsDeltaTgSpace = false;
02756                 if (useTgSpace)
02757                 {
02758                         rBS.deltaTgSpace.resize(nNbVertVB, CVector::Null);
02759                 }
02760 
02761                 rBS.VertRefs.resize (nNbVertVB, 0xffffffff);
02762 
02763                 for (i = 0; i < nNbVertVB; i++)
02764                 {
02765                         const CMRMMeshFinal::CWedge     &rWedgeRef = finalMRM.Wedges[i];
02766                         const CMRMMeshFinal::CWedge     &rWedgeTar = finalMRM.MRMBlendShapesFinals[k].Wedges[i];
02767 
02768                         CVector delta = rWedgeTar.Vertex - rWedgeRef.Vertex;
02769                         CVectorH attr;
02770 
02771                         if (delta.norm() > 0.001f)
02772                         {
02773                                 rBS.deltaPos[i] = delta;
02774                                 rBS.VertRefs[i] = i;
02775                                 bIsDeltaPos = true;
02776                         }
02777 
02778                         attId = 0;
02779                         if (vbFlags & CVertexBuffer::NormalFlag)
02780                         {
02781                                 attr = rWedgeRef.Attributes[attId];
02782                                 CVector NormRef = CVector(attr.x, attr.y, attr.z);
02783                                 attr = rWedgeTar.Attributes[attId];
02784                                 CVector NormTar = CVector(attr.x, attr.y, attr.z);
02785                                 delta = NormTar - NormRef;
02786                                 if (delta.norm() > 0.001f)
02787                                 {
02788                                         rBS.deltaNorm[i] = delta;
02789                                         rBS.VertRefs[i] = i;
02790                                         bIsDeltaNorm = true;
02791                                 }
02792                                 attId++;
02793                         }               
02794 
02795                         if (vbFlags & CVertexBuffer::PrimaryColorFlag)
02796                         {
02797                                 attr = rWedgeRef.Attributes[attId];
02798                                 CRGBAF RGBARef = CRGBAF(attr.x/255.0f, attr.y/255.0f, attr.z/255.0f, attr.w/255.0f);
02799                                 attr = rWedgeTar.Attributes[attId];
02800                                 CRGBAF RGBATar = CRGBAF(attr.x/255.0f, attr.y/255.0f, attr.z/255.0f, attr.w/255.0f);
02801                                 CRGBAF deltaRGBA = RGBATar - RGBARef;
02802                                 if ((deltaRGBA.R*deltaRGBA.R + deltaRGBA.G*deltaRGBA.G +
02803                                         deltaRGBA.B*deltaRGBA.B + deltaRGBA.A*deltaRGBA.A) > 0.0001f)
02804                                 {
02805                                         rBS.deltaCol[i] = deltaRGBA;
02806                                         rBS.VertRefs[i] = i;
02807                                         bIsDeltaCol = true;
02808                                 }
02809                                 attId++;
02810                         }
02811 
02812                         if (vbFlags & CVertexBuffer::SecondaryColorFlag)
02813                         {       // Nothing to do !
02814                                 attId++;
02815                         }
02816 
02817                         // Do that only for the UV0
02818                         if (vbFlags & CVertexBuffer::TexCoord0Flag)
02819                         {
02820                                 attr = rWedgeRef.Attributes[attId];
02821                                 CUV UVRef = CUV(attr.x, attr.y);
02822                                 attr = rWedgeTar.Attributes[attId];
02823                                 CUV UVTar = CUV(attr.x, attr.y);
02824                                 CUV deltaUV = UVTar - UVRef;
02825                                 if ((deltaUV.U*deltaUV.U + deltaUV.V*deltaUV.V) > 0.0001f)
02826                                 {
02827                                         rBS.deltaUV[i] = deltaUV;
02828                                         rBS.VertRefs[i] = i;
02829                                         bIsDeltaUV = true;
02830                                 }
02831                                 attId++;
02832                         }
02833 
02834                         if (useTgSpace)
02835                         {
02836                                 attr = rWedgeRef.Attributes[attId];
02837                                 CVector TgSpaceRef = CVector(attr.x, attr.y, attr.z);
02838                                 attr = rWedgeTar.Attributes[attId];
02839                                 CVector TgSpaceTar = CVector(attr.x, attr.y, attr.z);
02840                                 delta = TgSpaceTar - TgSpaceRef;
02841                                 if (delta.norm() > 0.001f)
02842                                 {
02843                                         rBS.deltaTgSpace[i] = delta;
02844                                         rBS.VertRefs[i] = i;
02845                                         bIsDeltaTgSpace = true;
02846                                 }
02847                                 attId++;
02848                         }
02849                         
02850                 } // End of all vertices added in blend shape
02851 
02852                 // Delete unused items and calculate the number of vertex used (blended)
02853 
02854                 sint32 nNbVertUsed = nNbVertVB;
02855                 sint32 nDstPos = 0;
02856                 for (j = 0; j < nNbVertVB; ++j)
02857                 {
02858                         if (rBS.VertRefs[j] == 0xffffffff) // Is vertex UNused
02859                         {
02860                                 --nNbVertUsed;
02861                         }
02862                         else // Vertex used
02863                         {
02864                                 if (nDstPos != j)
02865                                 {
02866                                         rBS.VertRefs[nDstPos]   = rBS.VertRefs[j];
02867                                         rBS.deltaPos[nDstPos]   = rBS.deltaPos[j];
02868                                         rBS.deltaNorm[nDstPos]  = rBS.deltaNorm[j];
02869                                         rBS.deltaUV[nDstPos]    = rBS.deltaUV[j];
02870                                         rBS.deltaCol[nDstPos]   = rBS.deltaCol[j];
02871                                         if (useTgSpace)
02872                                         {
02873                                                 rBS.deltaTgSpace[nDstPos]       = rBS.deltaTgSpace[j];
02874                                         }
02875                                 }
02876                                 ++nDstPos;
02877                         }
02878                 }
02879 
02880                 if (bIsDeltaPos)
02881                         rBS.deltaPos.resize (nNbVertUsed);
02882                 else
02883                         rBS.deltaPos.resize (0);
02884 
02885                 if (bIsDeltaNorm)
02886                         rBS.deltaNorm.resize (nNbVertUsed);
02887                 else
02888                         rBS.deltaNorm.resize (0);
02889 
02890                 if (bIsDeltaUV)
02891                         rBS.deltaUV.resize (nNbVertUsed);
02892                 else
02893                         rBS.deltaUV.resize (0);
02894 
02895                 if (bIsDeltaCol)
02896                         rBS.deltaCol.resize (nNbVertUsed);
02897                 else
02898                         rBS.deltaCol.resize (0);
02899 
02900                 if (bIsDeltaTgSpace)
02901                         rBS.deltaTgSpace.resize (nNbVertUsed);
02902                 else
02903                         rBS.deltaTgSpace.resize (0);
02904 
02905 
02906                 rBS.VertRefs.resize (nNbVertUsed);
02907 
02908         }
02909 }

void NL3D::CMRMBuilder::buildMeshBuildMrm const CMRMMeshFinal finalMRM,
CMeshMRMGeom::CMeshBuildMRM mbuild,
uint32  vbFlags,
uint32  nbMats,
const CMesh::CMeshBuild mb
[private]
 

from a final MRM Mesh representation, compute a CMeshBuildMRM. This is the last stage of the algo.

Parameters:
vbFlags the vertex format returned by earlier call too buildMrmBaseMesh().
nbMats the number of materials of original MeshBuild.

Definition at line 1918 of file mrm_builder.cpp.

References NLMISC::CRGBAF::A, NL3D::CVertexBuffer::addValueEx(), NL3D::CMRMMeshFinal::CWedge::Attributes, attToColor(), attToUvw(), NLMISC::CRGBAF::B, NL3D::CMeshMRMGeom::CMeshBuildMRM::BlendShapes, NL3D::CVertexBuffer::clearValueEx(), NL3D::CBlendShape::deltaCol, NL3D::CBlendShape::deltaNorm, NL3D::CBlendShape::deltaPos, NL3D::CBlendShape::deltaTgSpace, NL3D::CBlendShape::deltaUV, NL3D::CMRMMeshFinal::CLod::Faces, NLMISC::CRGBAF::G, NL3D::CMRMMeshFinal::CLod::Geomorphs, NL3D::CMeshMRMGeom::CLod::Geomorphs, NL3D::CMeshMRMGeom::CLod::InfluencedVertices, NL3D::CVertexBuffer::initEx(), NL3D::CMRMMeshFinal::Lods, NL3D::CMeshMRMGeom::CMeshBuildMRM::Lods, NL3D::CMesh::CSkinWeight::MatrixId, NL3D::CMeshMRMGeom::CLod::MatrixInfluences, NL3D::CMesh::CMeshBuild::MeshVertexProgram, NL3D::CMRMMeshFinal::MRMBlendShapesFinals, NL3D::CMRMMeshFinal::NGeomSpace, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, NLMISC::CVector::norm(), NL3D::CMesh::CMeshBuild::NumCoords, NL3D::CMRMMeshFinal::CLod::NWedges, NL3D::CMeshMRMGeom::CLod::NWedges, NLMISC::CRGBAF::R, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::CVertexBuffer::setColor(), NL3D::CVertexBuffer::setNormalCoord(), NL3D::CVertexBuffer::setNumVertices(), NL3D::CVertexBuffer::setSpecular(), NL3D::CVertexBuffer::setTexCoord(), NL3D::CVertexBuffer::setUVRouting(), NL3D::CVertexBuffer::setValueFloat3Ex(), NL3D::CVertexBuffer::setVertexCoord(), NL3D::CVertexBuffer::setVertexFormat(), sint, sint32, NL3D::CMeshMRMGeom::CMeshBuildMRM::Skinned, NL3D::CMeshMRMGeom::CMeshBuildMRM::SkinWeights, NLMISC::CUV::U, NLMISC::CUVW::U, uint, uint32, NL3D::CMesh::CMeshBuild::UVRouting, NLMISC::CUV::V, NLMISC::CUVW::V, NL3D::CMeshMRMGeom::CMeshBuildMRM::VBuffer, NL3D::CMRMMeshFinal::CWedge::Vertex, NL3D::CMRMMeshFinal::CWedge::VertexSkin, NL3D::CBlendShape::VertRefs, NLMISC::CVectorH::w, NLMISC::CUVW::W, NL3D::CMRMMeshFinal::Wedges, NL3D::CMesh::CSkinWeight::Weights, NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z.

Referenced by compileMRM().

01919 {
01920         sint    i,j,k;
01921         sint    attId;
01922 
01923         // reset the mbuild.
01924         mbuild= CMeshMRMGeom::CMeshBuildMRM();
01925         // Setup VB.
01926 
01927         bool useFormatExt = false;
01928         // Check wether there are texture coordinates with more than 2 compnents, which force us to use an extended vertex format
01929         for (k = 0; k < CVertexBuffer::MaxStage; ++k)
01930         {
01931                 if (
01932                         (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
01933                         && mb.NumCoords[k] != 2)
01934                 {
01935                         useFormatExt = true;
01936                         break;
01937                 }
01938         }
01939 
01940         uint numTexCoordUsed = 0;
01941 
01942 
01943         for (k = 0; k < CVertexBuffer::MaxStage; ++k)
01944         {
01945                 if (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
01946                 {
01947                         numTexCoordUsed = k;
01948                 }
01949         }
01950 
01951         if (!useFormatExt)
01952         {
01953                 // setup standard format
01954                 mbuild.VBuffer.setVertexFormat(vbFlags);
01955         }
01956         else // setup extended format
01957         {
01958                 mbuild.VBuffer.clearValueEx();
01959                 if (vbFlags & CVertexBuffer::PositionFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Position, CVertexBuffer::Float3);
01960                 if (vbFlags & CVertexBuffer::NormalFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Normal, CVertexBuffer::Float3);
01961                 if (vbFlags & CVertexBuffer::PrimaryColorFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::PrimaryColor, CVertexBuffer::UChar4);
01962                 if (vbFlags & CVertexBuffer::SecondaryColorFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::SecondaryColor, CVertexBuffer::UChar4);
01963                 if (vbFlags & CVertexBuffer::WeightFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Weight, CVertexBuffer::Float4);
01964                 if (vbFlags & CVertexBuffer::PaletteSkinFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::PaletteSkin, CVertexBuffer::UChar4);
01965                 if (vbFlags & CVertexBuffer::FogFlag) mbuild.VBuffer.addValueEx(CVertexBuffer::Fog, CVertexBuffer::Float1);
01966 
01967                 for (k = 0; k < CVertexBuffer::MaxStage; ++k)
01968                 {
01969                         if (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
01970                         {
01971                                 switch(mb.NumCoords[k])
01972                                 {       
01973                                         case 2:
01974                                                 mbuild.VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float2);
01975                                         break;
01976                                         case 3:
01977                                                 mbuild.VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float3);
01978                                         break;
01979                                         default:
01980                                                 nlassert(0);
01981                                         break;
01982                                 }
01983                         }
01984                 }
01985                 mbuild.VBuffer.initEx();
01986         }
01987 
01988         // Copy the UVRouting
01989         for (i=0; i<CVertexBuffer::MaxStage; i++)
01990         {
01991                 mbuild.VBuffer.setUVRouting (i, mb.UVRouting[i]);
01992         }
01993 
01994         // Setup the VertexBuffer.
01995         // ========================
01996         // resize the VB.
01997         mbuild.VBuffer.setNumVertices(finalMRM.Wedges.size());
01998         // Setup SkinWeights.
01999         if(_Skinned)
02000                 mbuild.SkinWeights.resize(finalMRM.Wedges.size());
02001 
02002         // fill the VB.
02003         for(i=0; i<(sint)finalMRM.Wedges.size(); i++)
02004         {
02005                 const CMRMMeshFinal::CWedge     &wedge= finalMRM.Wedges[i];
02006 
02007                 // setup Vertex.
02008                 mbuild.VBuffer.setVertexCoord(i, wedge.Vertex);
02009 
02010                 // seutp attributes.
02011                 attId= 0;
02012 
02013                 // For all activated attributes in mbuild, retriev the attribute from the finalMRM.
02014                 if(vbFlags & CVertexBuffer::NormalFlag)
02015                 {
02016                         mbuild.VBuffer.setNormalCoord(i, wedge.Attributes[attId] );
02017                         attId++;
02018                 }
02019                 if(vbFlags & CVertexBuffer::PrimaryColorFlag)
02020                 {
02021                         mbuild.VBuffer.setColor(i, attToColor(wedge.Attributes[attId]) );
02022                         attId++;
02023                 }
02024                 if(vbFlags & CVertexBuffer::SecondaryColorFlag)
02025                 {
02026                         mbuild.VBuffer.setSpecular(i, attToColor(wedge.Attributes[attId]) );
02027                         attId++;
02028                 }
02029                 for(k=0; k<CVertexBuffer::MaxStage;k++)
02030                 {
02031                         if(vbFlags & (CVertexBuffer::TexCoord0Flag<<k))
02032                         {
02033                                 switch(mb.NumCoords[k])
02034                                 {
02035                                         case 2:                         
02036                                                 mbuild.VBuffer.setTexCoord(i, k, (CUV) attToUvw(wedge.Attributes[attId]) );
02037                                         break;
02038                                         case 3:
02039                                         {
02040                                                 CUVW uvw = attToUvw(wedge.Attributes[attId]);
02041                                                 mbuild.VBuffer.setValueFloat3Ex((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), i, uvw.U, uvw.V, uvw.W);
02042                                         }
02043                                         break;
02044                                         default:
02045                                                 nlassert(0);
02046                                         break;
02047                                 }
02048                                 attId++;
02049                         }
02050                 }
02051 
02052                 // Setup SkinWeights.
02053                 if(_Skinned)
02054                 {
02055                         mbuild.SkinWeights[i]= wedge.VertexSkin;
02056                 }
02057         }
02058 
02059 
02060         // Build Lods.
02061         // ========================
02062         // resize
02063         mbuild.Lods.resize(finalMRM.Lods.size());
02064         // fill.
02065         for(i=0; i<(sint)finalMRM.Lods.size(); i++)
02066         {
02067                 const CMRMMeshFinal::CLod       &srcLod= finalMRM.Lods[i];
02068                 CMeshMRMGeom::CLod                      &destLod= mbuild.Lods[i];
02069 
02070                 // Basic.
02071                 //---------
02072 
02073                 // Copy NWedges infos.
02074                 destLod.NWedges= srcLod.NWedges;
02075                 // Copy Geomorphs infos.
02076                 destLod.Geomorphs= srcLod.Geomorphs;
02077 
02078 
02079                 // Reorder faces by rdrpass.
02080                 //---------
02081 
02082                 // First count the number of faces used by this LOD for each material 
02083                 vector<sint>    matCount;
02084                 // resize, and reset to 0.
02085                 matCount.clear();
02086                 matCount.resize(nbMats, 0);
02087                 // For each face of this Lods, incr the mat face counter.
02088                 for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02089                 {
02090                         sint    matId= srcLod.Faces[j].MaterialId;
02091                         nlassert(matId>=0);
02092                         nlassert(matId<(sint)nbMats);
02093                         // increment the refcount of this material by this LOD.
02094                         matCount[matId]++;
02095                 }
02096 
02097                 // Then for each material not empty, create a rdrPass, and ref it for this material.
02098                 vector<sint>    rdrPassIndex;   // material to rdrPass map.
02099                 rdrPassIndex.resize(nbMats);
02100                 for(j=0; j<(sint)nbMats; j++)
02101                 {
02102                         if(matCount[j]==0)
02103                                 rdrPassIndex[j]= -1;
02104                         else
02105                         {
02106                                 // map material to rdrPass.
02107                                 sint    idRdrPass= destLod.RdrPass.size();
02108                                 rdrPassIndex[j]= idRdrPass;
02109                                 // create a rdrPass.
02110                                 destLod.RdrPass.push_back(CMeshMRMGeom::CRdrPass());
02111                                 // assign the good materialId to this rdrPass.
02112                                 destLod.RdrPass[idRdrPass].MaterialId= j;
02113                                 // reserve the array of faces of this rdrPass.
02114                                 destLod.RdrPass[idRdrPass].PBlock.reserveTri(matCount[j]);
02115                         }
02116                 }
02117 
02118                 // Then for each face, add it to the good rdrPass of this Lod.
02119                 for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02120                 {
02121                         sint    matId= srcLod.Faces[j].MaterialId;
02122                         sint    idRdrPass= rdrPassIndex[matId];
02123                         // add this face to the good rdrPass.
02124                         sint    w0= srcLod.Faces[j].WedgeId[0];
02125                         sint    w1= srcLod.Faces[j].WedgeId[1];
02126                         sint    w2= srcLod.Faces[j].WedgeId[2];
02127                         destLod.RdrPass[idRdrPass].PBlock.addTri(w0, w1, w2);
02128                 }
02129 
02130 
02131                 // Build skin info for this Lod.
02132                 //---------
02133                 for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
02134                 {
02135                         destLod.InfluencedVertices[j].clear();
02136                 }
02137                 destLod.MatrixInfluences.clear();
02138                 if(_Skinned)
02139                 {
02140                         // This is the set which tell what wedge has already been inserted.
02141                         set<uint>       wedgeInfSet;
02142 
02143                         // First, build the list of vertices influenced by this Lod.
02144                         for(j= 0; j<(sint)srcLod.Faces.size(); j++)
02145                         {
02146                                 for(k=0; k<3; k++)
02147                                 {
02148                                         sint    wedgeId= srcLod.Faces[j].WedgeId[k];
02149                                         // If it is a geomorph
02150                                         if(wedgeId<finalMRM.NGeomSpace)
02151                                         {
02152                                                 // add the start and end to the list (if not here). NB: wedgeId is both the id 
02153                                                 // of the dest wedge, and the id of the geomorph.
02154                                                 sint    wedgeStartId= destLod.Geomorphs[wedgeId].Start;
02155                                                 sint    wedgeEndId= destLod.Geomorphs[wedgeId].End;
02156                                                 uint    nMatUsedStart= finalMRM.Wedges[wedgeStartId].NSkinMatUsed;
02157                                                 uint    nMatUsedEnd= finalMRM.Wedges[wedgeEndId].NSkinMatUsed;
02158 
02159                                                 // if insertion in the set work, add to the good array.
02160                                                 if( wedgeInfSet.insert(wedgeStartId).second )
02161                                                         destLod.InfluencedVertices[nMatUsedStart-1].push_back(wedgeStartId);
02162                                                 if( wedgeInfSet.insert(wedgeEndId).second )
02163                                                         destLod.InfluencedVertices[nMatUsedEnd-1].push_back(wedgeEndId);
02164                                         }
02165                                         else
02166                                         {
02167                                                 uint    nMatUsed= finalMRM.Wedges[wedgeId].NSkinMatUsed;
02168 
02169                                                 // just add this wedge to the list (if not here).
02170                                                 // if insertion in the set work, add to the array.
02171                                                 if( wedgeInfSet.insert(wedgeId).second )
02172                                                         destLod.InfluencedVertices[nMatUsed-1].push_back(wedgeId);
02173                                         }
02174                                 }
02175                         }
02176 
02177                         // Optimisation: for better cache, sort the destLod.InfluencedVertices in increasing order.
02178                         for(j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
02179                         {
02180                                 sort(destLod.InfluencedVertices[j].begin(), destLod.InfluencedVertices[j].end());
02181                         }
02182 
02183 
02184                         // Then Build the MatrixInfluences array, for all thoses Influenced Vertices only.
02185                         // This is the map MatrixId -> MatrixInfId.
02186                         map<uint, uint>         matrixInfMap;
02187 
02188                         // For all influenced vertices, flags matrix they use.
02189                         uint    iSkinMat;
02190                         for(iSkinMat= 0; iSkinMat<NL3D_MESH_SKINNING_MAX_MATRIX; iSkinMat++)
02191                         {
02192                                 for(j= 0; j<(sint)destLod.InfluencedVertices[iSkinMat].size(); j++)
02193                                 {
02194                                         uint    wedgeId= destLod.InfluencedVertices[iSkinMat][j];
02195 
02196                                         // take the original wedge.
02197                                         const CMRMMeshFinal::CWedge     &wedge= finalMRM.Wedges[wedgeId];
02198                                         // For all matrix with not null influence...
02199                                         for(k= 0; k<NL3D_MESH_SKINNING_MAX_MATRIX; k++)
02200                                         {
02201                                                 float   matWeight= wedge.VertexSkin.Weights[k];
02202 
02203                                                 // This check the validity of skin weights sort. If false, problem before in the algo.
02204                                                 if((uint)k<iSkinMat+1)
02205                                                 {
02206                                                         nlassert( matWeight>0 );
02207                                                 }
02208                                                 else
02209                                                 {
02210                                                         nlassert( matWeight==0 );
02211                                                 }
02212                                                 // if not null influence.
02213                                                 if(matWeight>0)
02214                                                 {
02215                                                         uint    matId= wedge.VertexSkin.MatrixId[k];
02216 
02217                                                         // search/insert the matrixInfId.
02218                                                         map<uint, uint>::iterator       it= matrixInfMap.find(matId);
02219                                                         if( it==matrixInfMap.end() )
02220                                                         {
02221                                                                 uint matInfId= destLod.MatrixInfluences.size();
02222                                                                 matrixInfMap.insert( make_pair(matId, matInfId) );
02223                                                                 // create the new MatrixInfluence.
02224                                                                 destLod.MatrixInfluences.push_back(matId);
02225                                                         }
02226                                                 }
02227                                         }
02228                                 }
02229                         }
02230 
02231                 }
02232 
02233         }
02234 
02235         // Indicate Skinning.
02236         mbuild.Skinned= _Skinned;
02237 
02238 
02239 
02240         bool useTgSpace = mb.MeshVertexProgram != NULL ? mb.MeshVertexProgram->needTangentSpace() : false;
02241 
02242         // Construct Blend Shapes
02244         mbuild.BlendShapes.resize (finalMRM.MRMBlendShapesFinals.size());
02245         for (k = 0; k < (sint)mbuild.BlendShapes.size(); ++k)
02246         {
02247                 CBlendShape &rBS = mbuild.BlendShapes[k];
02248                 sint32 nNbVertVB = finalMRM.Wedges.size();
02249                 bool bIsDeltaPos = false;
02250                 rBS.deltaPos.resize (nNbVertVB, CVector(0.0f,0.0f,0.0f));
02251                 bool bIsDeltaNorm = false;
02252                 rBS.deltaNorm.resize (nNbVertVB, CVector(0.0f,0.0f,0.0f));
02253                 bool bIsDeltaUV = false;
02254                 rBS.deltaUV.resize (nNbVertVB, CUV(0.0f,0.0f));
02255                 bool bIsDeltaCol = false;
02256                 rBS.deltaCol.resize (nNbVertVB, CRGBAF(0.0f,0.0f,0.0f,0.0f));
02257                 bool bIsDeltaTgSpace = false;
02258                 if (useTgSpace)
02259                 {
02260                         rBS.deltaTgSpace.resize(nNbVertVB, CVector::Null);
02261                 }
02262 
02263                 rBS.VertRefs.resize (nNbVertVB, 0xffffffff);
02264 
02265                 for (i = 0; i < nNbVertVB; i++)
02266                 {
02267                         const CMRMMeshFinal::CWedge     &rWedgeRef = finalMRM.Wedges[i];
02268                         const CMRMMeshFinal::CWedge     &rWedgeTar = finalMRM.MRMBlendShapesFinals[k].Wedges[i];
02269 
02270                         CVector delta = rWedgeTar.Vertex - rWedgeRef.Vertex;
02271                         CVectorH attr;
02272 
02273                         if (delta.norm() > 0.001f)
02274                         {
02275                                 rBS.deltaPos[i] = delta;
02276                                 rBS.VertRefs[i] = i;
02277                                 bIsDeltaPos = true;
02278                         }
02279 
02280                         attId = 0;
02281                         if (vbFlags & CVertexBuffer::NormalFlag)
02282                         {
02283                                 attr = rWedgeRef.Attributes[attId];
02284                                 CVector NormRef = CVector(attr.x, attr.y, attr.z);
02285                                 attr = rWedgeTar.Attributes[attId];
02286                                 CVector NormTar = CVector(attr.x, attr.y, attr.z);
02287                                 delta = NormTar - NormRef;
02288                                 if (delta.norm() > 0.001f)
02289                                 {
02290                                         rBS.deltaNorm[i] = delta;
02291                                         rBS.VertRefs[i] = i;
02292                                         bIsDeltaNorm = true;
02293                                 }
02294                                 attId++;
02295                         }               
02296 
02297                         if (vbFlags & CVertexBuffer::PrimaryColorFlag)
02298                         {
02299                                 attr = rWedgeRef.Attributes[attId];
02300                                 CRGBAF RGBARef = CRGBAF(attr.x/255.0f, attr.y/255.0f, attr.z/255.0f, attr.w/255.0f);
02301                                 attr = rWedgeTar.Attributes[attId];
02302                                 CRGBAF RGBATar = CRGBAF(attr.x/255.0f, attr.y/255.0f, attr.z/255.0f, attr.w/255.0f);
02303                                 CRGBAF deltaRGBA = RGBATar - RGBARef;
02304                                 if ((deltaRGBA.R*deltaRGBA.R + deltaRGBA.G*deltaRGBA.G +
02305                                         deltaRGBA.B*deltaRGBA.B + deltaRGBA.A*deltaRGBA.A) > 0.0001f)
02306                                 {
02307                                         rBS.deltaCol[i] = deltaRGBA;
02308                                         rBS.VertRefs[i] = i;
02309                                         bIsDeltaCol = true;
02310                                 }
02311                                 attId++;
02312                         }
02313 
02314                         if (vbFlags & CVertexBuffer::SecondaryColorFlag)
02315                         {       // Nothing to do !
02316                                 attId++;
02317                         }
02318 
02319                         // Do that only for the UV0
02320                         if (vbFlags & CVertexBuffer::TexCoord0Flag)
02321                         {
02322                                 attr = rWedgeRef.Attributes[attId];
02323                                 CUV UVRef = CUV(attr.x, attr.y);
02324                                 attr = rWedgeTar.Attributes[attId];
02325                                 CUV UVTar = CUV(attr.x, attr.y);
02326                                 CUV deltaUV = UVTar - UVRef;
02327                                 if ((deltaUV.U*deltaUV.U + deltaUV.V*deltaUV.V) > 0.0001f)
02328                                 {
02329                                         rBS.deltaUV[i] = deltaUV;
02330                                         rBS.VertRefs[i] = i;
02331                                         bIsDeltaUV = true;
02332                                 }
02333                                 attId++;
02334                         }
02335 
02336                         if (useTgSpace)
02337                         {
02338                                 attr = rWedgeRef.Attributes[attId];
02339                                 CVector TgSpaceRef = CVector(attr.x, attr.y, attr.z);
02340                                 attr = rWedgeTar.Attributes[attId];
02341                                 CVector TgSpaceTar = CVector(attr.x, attr.y, attr.z);
02342                                 delta = TgSpaceTar - TgSpaceRef;
02343                                 if (delta.norm() > 0.001f)
02344                                 {
02345                                         rBS.deltaTgSpace[i] = delta;
02346                                         rBS.VertRefs[i] = i;
02347                                         bIsDeltaTgSpace = true;
02348                                 }
02349                                 attId++;
02350                         }
02351                         
02352                 } // End of all vertices added in blend shape
02353 
02354                 // Delete unused items and calculate the number of vertex used (blended)
02355 
02356                 sint32 nNbVertUsed = nNbVertVB;
02357                 sint32 nDstPos = 0;
02358                 for (j = 0; j < nNbVertVB; ++j)
02359                 {
02360                         if (rBS.VertRefs[j] == 0xffffffff) // Is vertex UNused
02361                         {
02362                                 --nNbVertUsed;
02363                         }
02364                         else // Vertex used
02365                         {
02366                                 if (nDstPos != j)
02367                                 {
02368                                         rBS.VertRefs[nDstPos]   = rBS.VertRefs[j];
02369                                         rBS.deltaPos[nDstPos]   = rBS.deltaPos[j];
02370                                         rBS.deltaNorm[nDstPos]  = rBS.deltaNorm[j];
02371                                         rBS.deltaUV[nDstPos]    = rBS.deltaUV[j];
02372                                         rBS.deltaCol[nDstPos]   = rBS.deltaCol[j];
02373                                         if (useTgSpace)
02374                                         {
02375                                                 rBS.deltaTgSpace[nDstPos]       = rBS.deltaTgSpace[j];
02376                                         }
02377                                 }
02378                                 ++nDstPos;
02379                         }
02380                 }
02381 
02382                 if (bIsDeltaPos)
02383                         rBS.deltaPos.resize (nNbVertUsed);
02384                 else
02385                         rBS.deltaPos.resize (0);
02386 
02387                 if (bIsDeltaNorm)
02388                         rBS.deltaNorm.resize (nNbVertUsed);
02389                 else
02390                         rBS.deltaNorm.resize (0);
02391 
02392                 if (bIsDeltaUV)
02393                         rBS.deltaUV.resize (nNbVertUsed);
02394                 else
02395                         rBS.deltaUV.resize (0);
02396 
02397                 if (bIsDeltaCol)
02398                         rBS.deltaCol.resize (nNbVertUsed);
02399                 else
02400                         rBS.deltaCol.resize (0);
02401 
02402                 if (bIsDeltaTgSpace)
02403                         rBS.deltaTgSpace.resize (nNbVertUsed);
02404                 else
02405                         rBS.deltaTgSpace.resize (0);
02406 
02407 
02408                 rBS.VertRefs.resize (nNbVertUsed);
02409 
02410         }
02411 }

uint32 NL3D::CMRMBuilder::buildMrmBaseMesh const CMesh::CMeshBuild mbuild,
CMRMMesh baseMesh
[private]
 

from a meshBuild, compute a CMRMMesh. This is the first stage of the algo.

Returns:
the vertexFormat supported by CMRMBuilder.

Definition at line 1734 of file mrm_builder.cpp.

References _AttributeMap, _HasMeshInterfaces, NL3D::CMRMCorner::Attributes, NL3D::CMesh::CCorner::Color, NL3D::CMRMMesh::Faces, NL3D::CMesh::CMeshBuild::Faces, findInsertColorInBaseMesh(), findInsertNormalInBaseMesh(), findInsertUvwInBaseMesh(), NL3D::CMesh::CMeshBuild::InterfaceLinks, NL3D::CMRMMesh::InterfaceLinks, NL3D_MRM_MAX_ATTRIB, nlassert, NL3D::CMesh::CCorner::Normal, NL3D::CMRMMesh::NumAttributes, sint, NL3D::CMesh::CMeshBuild::SkinWeights, NL3D::CMRMMesh::SkinWeights, NL3D::CMesh::CCorner::Specular, uint, uint32, NL3D::CMesh::CCorner::Uvws, NL3D::CMRMCorner::Vertex, NL3D::CMesh::CMeshBuild::VertexFlags, NL3D::CMesh::CMeshBuild::Vertices, and NL3D::CMRMMesh::Vertices.

Referenced by compileMRM().

01735 {
01736         sint            i,j,k;
01737         sint            nFaces;
01738         sint            attId;
01739         // build the supported VertexFormat.
01740         uint32          retVbFlags= CVertexBuffer::PositionFlag;
01741 
01742 
01743         // reset the baseMesh.
01744         baseMesh= CMRMMesh();
01745         // reset Tmp.
01746         for(attId=0; attId<NL3D_MRM_MAX_ATTRIB;attId++)
01747                 _AttributeMap[attId].clear();
01748 
01749 
01750         // Compute number of attributes used by the MeshBuild.
01751         // ========================
01752         // Compute too 
01753         if(mbuild.VertexFlags & CVertexBuffer::NormalFlag)
01754         {
01755                 baseMesh.NumAttributes++;
01756                 retVbFlags|= CVertexBuffer::NormalFlag;
01757         }
01758         if(mbuild.VertexFlags & CVertexBuffer::PrimaryColorFlag)
01759         {
01760                 baseMesh.NumAttributes++;
01761                 retVbFlags|= CVertexBuffer::PrimaryColorFlag;
01762         }
01763         if(mbuild.VertexFlags & CVertexBuffer::SecondaryColorFlag)
01764         {
01765                 baseMesh.NumAttributes++;
01766                 retVbFlags|= CVertexBuffer::SecondaryColorFlag;
01767         }
01768         for(k=0; k<CVertexBuffer::MaxStage;k++)
01769         {
01770                 uint flag=CVertexBuffer::TexCoord0Flag<<k;
01771                 if(mbuild.VertexFlags & flag)
01772                 {
01773                         baseMesh.NumAttributes++;
01774                         retVbFlags|=flag;
01775                 }
01776         }
01777         nlassert(baseMesh.NumAttributes<=NL3D_MRM_MAX_ATTRIB);
01778 
01779 
01780         // Fill basics: Vertices and Faces materials / index to vertices.
01781         // ========================
01782         // Just copy vertices.
01783         baseMesh.Vertices= mbuild.Vertices;
01784         // Just copy SkinWeights.
01785         if(_Skinned)
01786                 baseMesh.SkinWeights= mbuild.SkinWeights;
01787         // Just copy InterfaceLinks
01788         if(_HasMeshInterfaces)
01789                 baseMesh.InterfaceLinks= mbuild.InterfaceLinks;
01790         // Resize faces.
01791         nFaces= mbuild.Faces.size();
01792         baseMesh.Faces.resize(nFaces);
01793         for(i=0; i<nFaces; i++)
01794         {
01795                 // copy material Id.
01796                 baseMesh.Faces[i].MaterialId= mbuild.Faces[i].MaterialId;
01797                 // Copy Vertex index.
01798                 for(j=0; j<3; j++)
01799                 {
01800                         baseMesh.Faces[i].Corner[j].Vertex= mbuild.Faces[i].Corner[j].Vertex;
01801                 }
01802         }
01803 
01804         // Resolve attributes discontinuities and Fill attributes of the baseMesh.
01805         // ========================
01806         // For all corners.
01807         for(i=0; i<nFaces; i++)
01808         {
01809                 for(j=0; j<3; j++)
01810                 {
01811                         const CMesh::CCorner    &srcCorner= mbuild.Faces[i].Corner[j];
01812                         CMRMCorner                              &destCorner= baseMesh.Faces[i].Corner[j];
01813                         attId= 0;
01814 
01815                         // For all activated attributes in mbuild, find/insert the attribute in the baseMesh.
01816                         // NB: 2 attributes are said to be different if they have not the same value OR if they don't lie 
01817                         // on the same vertex. This is very important for MRM computing.
01818                         if(mbuild.VertexFlags & CVertexBuffer::NormalFlag)
01819                         {
01820                                 destCorner.Attributes[attId]= findInsertNormalInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Normal);
01821                                 attId++;
01822                         }
01823                         if(mbuild.VertexFlags & CVertexBuffer::PrimaryColorFlag)
01824                         {
01825                                 destCorner.Attributes[attId]= findInsertColorInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Color);
01826                                 attId++;
01827                         }
01828                         if(mbuild.VertexFlags & CVertexBuffer::SecondaryColorFlag)
01829                         {
01830                                 destCorner.Attributes[attId]= findInsertColorInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Specular);
01831                                 attId++;
01832                         }
01833                         for(k=0; k<CVertexBuffer::MaxStage;k++)
01834                         {
01835                                 if(mbuild.VertexFlags & (CVertexBuffer::TexCoord0Flag<<k))
01836                                 {
01837                                         destCorner.Attributes[attId]= findInsertUvwInBaseMesh(baseMesh, attId, destCorner.Vertex, srcCorner.Uvws[k]);
01838                                         attId++;
01839                                 }
01840                         }
01841                 }
01842         }
01843 
01844 
01845 
01846         // End. clear Tmp infos.
01847         // ========================
01848         // reset Tmp.
01849         for(attId=0; attId<NL3D_MRM_MAX_ATTRIB;attId++)
01850                 _AttributeMap[attId].clear();
01851 
01852         return  retVbFlags;
01853 }

bool NL3D::CMRMBuilder::buildMRMSewingMeshes const CMesh::CMeshBuild mbuild,
uint  nWantedLods,
uint  divisor
[private]
 

Definition at line 3115 of file mrm_builder.cpp.

References _SewingMeshes, NL3D::CMesh::CMeshBuild::InterfaceLinks, NL3D::CMesh::CMeshBuild::Interfaces, nlassert, uint, and NL3D::CMesh::CMeshBuild::Vertices.

Referenced by compileMRM().

03116 {
03117         nlassert(nWantedLods>=1);
03118         nlassert(divisor>=1);
03119         if(mbuild.Interfaces.size()==0)
03120                 return false;
03121         // must have same size
03122         if(mbuild.InterfaceLinks.size()!=mbuild.Vertices.size())
03123                 return false;
03124 
03125         // **** For each interface, MRM-ize it and store.
03126         _SewingMeshes.resize(mbuild.Interfaces.size());
03127         for(uint i=0;i<mbuild.Interfaces.size();i++)
03128         {
03129                 _SewingMeshes[i].build(mbuild.Interfaces[i], nWantedLods, divisor);
03130         }
03131 
03132 
03133         return true;
03134 }

sint NL3D::CMRMBuilder::collapseEdge const CMRMEdge edge  )  [private]
 

Definition at line 499 of file mrm_builder.cpp.

References _CurrentLodComputed, _HasMeshInterfaces, _SewingMeshes, NL3D::CMRMCorner::Attributes, NL3D::CMRMAttribute::BSCurrent, NL3D::CMRMVertex::BSCurrent, NL3D::CMRMFaceBuild::BSInterpolated, NL3D::CMRMAttribute::CollapsedTo, NL3D::CMRMVertex::CollapsedTo, collapseSkinWeight(), NL3D::CMRMFace::Corner, NL3D::CMRMAttribute::Current, NL3D::CMRMVertex::Current, NL3D::CMRMVertex::CurrentSW, NL3D::deleteElement(), EdgeCollapses, faceShareWedges(), NL3D::findElement(), NL3D::CMRMFaceBuild::getAssociatedWedge(), NL3D::CMesh::CInterfaceLink::InterfaceId, NL3D::CMRMVertex::InterfaceLink, NL3D::CMesh::CInterfaceLink::InterfaceVertexId, NL3D::CMRMFaceBuild::InterpolatedAttribute, NL3D::CMRMAttribute::InterpolatedFace, NL3D::CMRMSewingMesh::mustCollapseEdge(), NL3D::CMRMAttribute::NbSharedFaces, nlassert, NumAttributes, removeFaceFromEdgeList(), NL3D::CMRMAttribute::Shared, NL3D::CMRMVertex::SharedFaces, sint, TmpAttributes, TmpFaces, TmpVertices, uint, NL3D::CMRMEdge::v0, NL3D::CMRMEdge::v1, NL3D::CMRMCorner::Vertex, vertexClosed(), vertexContinue(), NLMISC::CVectorH::w, NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z.

Referenced by collapseEdges().

00500 {
00501         sint    i,j;
00502         float   InterValue;
00503         sint    edgeV1=edge.v0;
00504         sint    edgeV2=edge.v1;
00505 
00506 
00507         // 0. collapse the vertices.
00508         //==========================
00509 
00510         // edge.Vertex1 kept, but morphed.
00511         // edge.Vertex2 deleted, and must know on which vertex it collapse.
00512         CMRMVertex      &Vertex1=TmpVertices[edgeV1], &Vertex2=TmpVertices[edgeV2];
00513 
00514         // Interpolation choice.
00515         // Default is to interpolate vertex 0 to the middle of the edge.
00516         InterValue=0.5;
00517         //InterValue=1;
00518         // **** If at least one vertex of the edge is on a mesh sewing interface, must change InterValue
00519         if( _HasMeshInterfaces && (Vertex1.InterfaceLink.InterfaceId>=0 || Vertex2.InterfaceLink.InterfaceId>=0) )
00520         {
00521                 // If this is an edge of a mesh sewing interface
00522                 if(Vertex1.InterfaceLink.InterfaceId==Vertex2.InterfaceLink.InterfaceId)
00523                 {
00524                         // Then the edge is one of the sewing interface mesh. must do special things for it
00525                         CMRMSewingMesh  &sewingMesh= _SewingMeshes[Vertex1.InterfaceLink.InterfaceId];
00526 
00527                         // get the sewing edge id
00528                         CMRMEdge        sewingEdge;
00529                         sewingEdge.v0= Vertex1.InterfaceLink.InterfaceVertexId;
00530                         sewingEdge.v1= Vertex2.InterfaceLink.InterfaceVertexId;
00531 
00532                         // Get the edge in the sewing mesh which is said to be collapsed
00533                         uint    vertToCollapse;
00534                         sint collapseId= sewingMesh.mustCollapseEdge(_CurrentLodComputed, sewingEdge, vertToCollapse);
00535                         // if exist
00536                         if(collapseId>=0)
00537                         {
00538                                 // if it is v0 which must collapse, then InterValue=1
00539                                 if(vertToCollapse==(uint)sewingEdge.v0)
00540                                         InterValue= 1;
00541                                 else
00542                                         InterValue= 0;
00543 
00544                         }
00545                         else
00546                         {
00547                                 // This should not happens. But it is still possible if this edge don't want to collapse but if their
00548                                 // is no more choice. Take a default value
00549                                 InterValue= 0;
00550                         }
00551                 }
00552                 else
00553                 {
00554                         // must collapse to the vertex on the sewing interface (as if it was open)
00555                         if(Vertex1.InterfaceLink.InterfaceId>=0)
00556                         {
00557                                 // NB: it is possible that both vertices are on a different sewing interface... still collapse (must have to)
00558                                 InterValue= 0;
00559                         }
00560                         else
00561                         {
00562                                 // Then Vertex2 is on a sewing interface, collapse to it
00563                                 InterValue= 1;
00564                         }
00565                 }
00566         }
00567         // **** Else, on special cases, it is much more efficient to interpolate at start or at end of edge.
00568         else
00569         {
00570                 // If one vertex is "open", ie his shared faces do not represent a closed Fan, then interpolate to this one, 
00571                 // so the mesh has the same silhouette.
00572                 bool    vc1= vertexClosed(edgeV1);
00573                 bool    vc2= vertexClosed(edgeV2);
00574                 if(!vc1 && vc2) InterValue=0;
00575                 else if(vc1 && !vc2) InterValue=1;
00576                 else
00577                 {
00578                         // Do the same test but with vertex continue: it is preferable to not move the boundaries 
00579                         // of a material, or a mapping.
00580                         bool    vc1= vertexContinue(edgeV1);
00581                         bool    vc2= vertexContinue(edgeV2);
00582                         if(!vc1 && vc2) InterValue=0;
00583                         if(vc1 && !vc2) InterValue=1;
00584                 }
00585         }
00586         /*BENCH_TotalCollapses++;
00587         if(InterValue==0.5)
00588                 BENCH_MiddleCollapses++;*/
00589 
00590         // Collapse the Vertex.
00591         //========================
00592         Vertex1.Current= Vertex1.Current*(1-InterValue) + Vertex2.Current*InterValue;
00593         for (i = 0; i < (sint)Vertex1.BSCurrent.size(); ++i)
00594                 Vertex1.BSCurrent[i] = Vertex1.BSCurrent[i]*(1-InterValue) + Vertex2.BSCurrent[i]*InterValue;
00595         Vertex2.CollapsedTo= edgeV1;
00596         if(_Skinned)
00597                 Vertex1.CurrentSW= collapseSkinWeight(Vertex1.CurrentSW, Vertex2.CurrentSW, InterValue);
00598         if( _HasMeshInterfaces )
00599                 Vertex1.InterfaceLink= InterValue<0.5f? Vertex1.InterfaceLink : Vertex2.InterfaceLink;
00600 
00601         // \todo yoyo: TODO_BUG: Don't know why, but vertices may point on deleted faces.
00602         // Temp: we destroy here thoses face from SharedFaces...
00603         for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00604         {
00605                 sint    numFace= Vertex1.SharedFaces[i];
00606                 if(TmpFaces[numFace].Deleted)
00607                         deleteElement(Vertex1.SharedFaces, numFace), i--;
00608         }
00609         for(i=0;i<(sint)Vertex2.SharedFaces.size();i++)
00610         {
00611                 sint    numFace= Vertex2.SharedFaces[i];
00612                 if(TmpFaces[numFace].Deleted)
00613                         deleteElement(Vertex2.SharedFaces, numFace), i--;
00614         }
00615 
00616 
00617         // Build Neighbor faces.
00618         vector<sint>    neighboorFaces;
00619         for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00620         {
00621                 sint    numFace= Vertex1.SharedFaces[i];
00622                 if(!findElement(neighboorFaces, numFace))
00623                         neighboorFaces.push_back(numFace);
00624         }
00625         for(i=0;i<(sint)Vertex2.SharedFaces.size();i++)
00626         {
00627                 sint    numFace= Vertex2.SharedFaces[i];
00628                 if(!findElement(neighboorFaces, numFace))
00629                         neighboorFaces.push_back(numFace);
00630         }
00631 
00632         // Build faces which will be destroyed (may 1 or 2, maybe more for non conventionnal meshes).
00633         vector<sint>    deletedFaces;
00634         for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00635         {
00636                 sint    numFace= Vertex1.SharedFaces[i];
00637                 nlassert(!TmpFaces[numFace].Deleted);
00638                 if(TmpFaces[numFace].hasVertex(edgeV2))
00639                         deletedFaces.push_back(numFace);
00640         }
00641 
00642 
00643         // 1. Collapse the wedges.
00644         //========================
00645 
00646         // For ALL Attributes.
00647         for(sint attId=0;attId<NumAttributes;attId++)
00648         {
00649                 // a/ Stock the wedge interpolation in each destroyed face.
00650                 //------------------------------------------------------
00651                 for(i=0;i<(sint)deletedFaces.size();i++)
00652                 {
00653                         CMRMFaceBuild           &face= TmpFaces[deletedFaces[i]];
00654 
00655                         CVectorH        &w0= TmpAttributes[attId][ face.getAssociatedWedge(attId, edgeV1) ].Current;
00656                         CVectorH        &w1= TmpAttributes[attId][ face.getAssociatedWedge(attId, edgeV2) ].Current;
00657 
00658                         CVectorH        &itp= face.InterpolatedAttribute;
00659                         itp.x= w0.x*(1-InterValue) + w1.x*InterValue;
00660                         itp.y= w0.y*(1-InterValue) + w1.y*InterValue;
00661                         itp.z= w0.z*(1-InterValue) + w1.z*InterValue;
00662                         itp.w= w0.w*(1-InterValue) + w1.w*InterValue;
00663 
00664                         for (j = 0; j < (sint)face.BSInterpolated.size(); ++j)
00665                         {
00666                                 CVectorH &w0 = TmpAttributes[attId][face.getAssociatedWedge(attId, edgeV1)].BSCurrent[j];
00667                                 CVectorH &w1 = TmpAttributes[attId][face.getAssociatedWedge(attId, edgeV2)].BSCurrent[j];
00668                                 CVectorH &itb = face.BSInterpolated[j];
00669                                 itb.x = w0.x*(1-InterValue) + w1.x*InterValue;
00670                                 itb.y = w0.y*(1-InterValue) + w1.y*InterValue;
00671                                 itb.z = w0.z*(1-InterValue) + w1.z*InterValue;
00672                                 itb.w = w0.w*(1-InterValue) + w1.w*InterValue;
00673                         }
00674                 }
00675 
00676 
00677                 // b/ Build wedge list to be modify.
00678                 //----------------------------------
00679                 vector<sint>    wedges;
00680 
00681                 for(i=0;i<(sint)neighboorFaces.size();i++)
00682                 {
00683                         CMRMFaceBuild   &face= TmpFaces[neighboorFaces[i]];
00684                         sint    numWedge;
00685 
00686                         numWedge= face.getAssociatedWedge(attId, edgeV1);
00687                         if(numWedge>=0 && !findElement(wedges, numWedge))
00688                                 wedges.push_back(numWedge);
00689 
00690                         numWedge= face.getAssociatedWedge(attId, edgeV2);
00691                         if(numWedge>=0 && !findElement(wedges, numWedge))
00692                                 wedges.push_back(numWedge);
00693                 }
00694 
00695 
00696                 // c/ Count numFaces which point on those wedges. (- deleted faces).
00697                 //------------------------------------------------------------------
00698 
00699                 for(i=0;i<(sint)wedges.size();i++)
00700                 {
00701                         sint                    numWedge= wedges[i];
00702                         CMRMAttribute   &wedge= TmpAttributes[attId][numWedge];
00703 
00704                         wedge.NbSharedFaces=0;
00705                         wedge.Shared=false;
00706 
00707                         // Count total ref count.
00708                         for(j=0;j<(sint)neighboorFaces.size();j++)
00709                         {
00710                                 if(TmpFaces[neighboorFaces[j]].hasWedge(attId, numWedge))
00711                                         wedge.NbSharedFaces++;
00712                         }
00713 
00714                         // Minus deleted faces.
00715                         for(j=0;j<(sint)deletedFaces.size();j++)
00716                         {
00717                                 if(TmpFaces[deletedFaces[j]].hasWedge(attId, numWedge))
00718                                 {
00719                                         wedge.NbSharedFaces--;
00720                                         wedge.Shared=true;
00721                                         wedge.InterpolatedFace=deletedFaces[j];
00722                                 }
00723                         }
00724                 }
00725 
00726 
00727                 // d/ Collapse wedge following 3 possibles cases.
00728                 //-----------------------------------------------
00729 
00730 
00731                 for(i=0;i<(sint)wedges.size();i++)
00732                 {
00733                         sint                    numWedge= wedges[i];
00734                         CMRMAttribute   &wedge= TmpAttributes[attId][numWedge];
00735 
00736                         // if wedge not shared...
00737                         if(!wedge.Shared)
00738                         {
00739                                 // We've got an "exterior wedge" which lost no corner => do not merge it nor delete it. 
00740                                 // Leave it as the same value (extrapolate it may not be a good solution).
00741                         }
00742                         else
00743                         {
00744                                 // if wedge dissapears, notify.
00745                                 if(wedge.NbSharedFaces==0)
00746                                 {
00747                                         wedge.CollapsedTo=-2;
00748                                         // Do not change his value. (as specified in Hope article).
00749                                 }
00750                                 else
00751                                 {
00752                                         CMRMFaceBuild   &face= TmpFaces[wedge.InterpolatedFace];
00753 
00754                                         // Must interpolate it.
00755                                         wedge.Current= face.InterpolatedAttribute;
00756                                         wedge.BSCurrent = face.BSInterpolated;
00757                                         
00758                                         // Must merge the wedge of the second vertex on first
00759                                         // ONLY IF 2 interpolated wedges are shared and NbSharedFaces!=0.
00760                                         if(     numWedge==face.getAssociatedWedge(attId, edgeV2) && 
00761                                                 faceShareWedges(&face, attId, edgeV1, edgeV2) )
00762                                         {
00763                                                 wedge.CollapsedTo= face.getAssociatedWedge(attId, edgeV1);
00764                                         }
00765                                 }
00766                         }
00767                 }
00768 
00769         }
00770 
00771         // 3. collapse faces.
00772         //===================
00773         
00774         // delete face shared by edge.
00775         for(i=0;i<(sint)deletedFaces.size();i++)
00776         {
00777                 sint    numFace= deletedFaces[i];
00778                 TmpFaces[numFace].Deleted=true;
00779 
00780                 // release edges from list.
00781                 removeFaceFromEdgeList(TmpFaces[numFace]);
00782                 // ivalid all it!!
00783                 TmpFaces[numFace].invalidAllIts(EdgeCollapses);
00784 
00785 
00786                 // delete from vertex1 and 2 the deleted faces.
00787                 deleteElement( Vertex1.SharedFaces, numFace);
00788                 deleteElement( Vertex2.SharedFaces, numFace);
00789         }
00790 
00791 
00792         // must ref correctly the faces.
00793         for(i=0;i<(sint)neighboorFaces.size();i++)
00794         {
00795                 CMRMFaceBuild           &face=TmpFaces[neighboorFaces[i]];
00796 
00797                 // good vertices
00798                 if(face.Corner[0].Vertex ==edgeV2)      face.Corner[0].Vertex=edgeV1;
00799                 if(face.Corner[1].Vertex ==edgeV2)      face.Corner[1].Vertex=edgeV1;
00800                 if(face.Corner[2].Vertex ==edgeV2)      face.Corner[2].Vertex=edgeV1;
00801                 // nb: doesn't matter if deletedFaces are modified...
00802 
00803                 // good wedges
00804                 for(sint attId=0;attId<NumAttributes;attId++)
00805                 {
00806                         sint    newWedge;
00807                         newWedge= TmpAttributes[attId][ face.Corner[0].Attributes[attId] ].CollapsedTo;
00808                         if(newWedge>=0) face.Corner[0].Attributes[attId]= newWedge;
00809                         newWedge= TmpAttributes[attId][ face.Corner[1].Attributes[attId] ].CollapsedTo;
00810                         if(newWedge>=0) face.Corner[1].Attributes[attId]= newWedge;
00811                         newWedge= TmpAttributes[attId][ face.Corner[2].Attributes[attId] ].CollapsedTo;
00812                         if(newWedge>=0) face.Corner[2].Attributes[attId]= newWedge;
00813                 }
00814 
00815                 // good edges.
00816                 /* Those ones are updated in collapseEdges(): they are removed from the edgeCollapseList, 
00817                         then they are re-inserted with good Vertex indices.
00818                 */
00819         }
00820 
00821 
00822         // The vertex1 has now the shared env of vertex2.
00823         Vertex1.SharedFaces.insert(Vertex1.SharedFaces.end(), Vertex2.SharedFaces.begin(), 
00824                 Vertex2.SharedFaces.end());
00825         
00826 
00827         return deletedFaces.size();
00828 }

void NL3D::CMRMBuilder::collapseEdges sint  nWantedFaces  )  [private]
 

Definition at line 945 of file mrm_builder.cpp.

References collapseEdge(), EdgeCollapses, insertFaceIntoEdgeList(), NL3D::CMRMFaceBuild::invalidEdgeIt(), NL3D::ItEdgeMap, nlassert, removeFaceFromEdgeList(), NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, TmpVertices, NL3D::CMRMEdge::v0, NL3D::CMRMEdge::v1, and NL3D::CMRMFaceBuild::validEdgeIt().

Referenced by makeFromMesh().

00946 {
00947         ItEdgeMap               EdgeIt;
00948 
00949         sint    nCurrentFaces=TmpFaces.size();
00950         sint    bug0=0,bug2=0,bug3=0;
00951 
00952         while(nCurrentFaces>nWantedFaces)
00953         {
00954                 bug0++;
00955                 EdgeIt= EdgeCollapses.begin();
00956 
00957                 if(EdgeIt== EdgeCollapses.end())
00958                         break;
00959 
00960                 // 0. Look if edge already deleted
00961                 //================================
00962                 CMRMEdge        edge=(*EdgeIt).second;
00963 
00964                 // Is it valid?? (ie his vertices exist yet??).
00965                 if(TmpVertices[ edge.v0 ].CollapsedTo>=0
00966                         || TmpVertices[ edge.v1 ].CollapsedTo>=0)
00967                 {
00968                         // \todo yoyo: TODO_BUG: potential bug here...
00969                         CMRMFaceBuild           &f= *(EdgeIt->second.Face);
00970                         nlassert(f.validEdgeIt(EdgeIt->second));
00971                         f.invalidEdgeIt(EdgeIt->second, EdgeCollapses);
00972                         EdgeCollapses.erase(EdgeIt);
00973                         bug2++;
00974                         continue;
00975                 }
00976                 // \todo yoyo: TODO_BUG: potential bug here...
00977                 // If a mesh is "open" it will crash if a "hole collapse"...
00978                 if(edge.v0==edge.v1)
00979                 {
00980                         CMRMFaceBuild           &f= *(EdgeIt->second.Face);
00981                         nlassert(f.validEdgeIt(EdgeIt->second));
00982                         f.invalidEdgeIt(EdgeIt->second, EdgeCollapses);
00983                         EdgeCollapses.erase(EdgeIt);
00984                         bug3++;
00985                         continue;
00986                 }
00987 
00988 
00989                 // 1. else, OK, collapse it!!
00990                 //===========================
00991                 sint    vertexCollapsed= edge.v0;
00992                 nCurrentFaces-= collapseEdge(edge);
00993 
00994 
00995                 // 2. Must reorder all his neighborhood.
00996                 //======================================
00997                 CMRMVertex      &vert=TmpVertices[vertexCollapsed];
00998                 sint    i;
00999                 // we delete from list modified edges, and we re-add them with their new value.
01000                 for(i=0;i<(sint)vert.SharedFaces.size();i++)
01001                 {
01002                         CMRMFaceBuild           &f= TmpFaces[vert.SharedFaces[i]];
01003                         removeFaceFromEdgeList(f);
01004                         insertFaceIntoEdgeList(f);
01005                 }
01006 
01007         }
01008 }

CMesh::CSkinWeight NL3D::CMRMBuilder::collapseSkinWeight const CMesh::CSkinWeight sw1,
const CMesh::CSkinWeight sw2,
float  InterValue
const [private]
 

Definition at line 399 of file mrm_builder.cpp.

References _SkinReduction, NL3D::CMesh::CSkinWeight::MatrixId, NL3D::CTmpVertexWeight::MatrixId, min, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, nlstop, uint, NL3D::CTmpVertexWeight::Weight, and NL3D::CMesh::CSkinWeight::Weights.

Referenced by collapseEdge().

00400 {
00401         // If fast interpolation.
00402         if(interValue==0)
00403                 return sw1;
00404         if(interValue==1)
00405                 return sw2;
00406 
00407         // else, must blend a skinWeight: must identify matrix which exist in the 2 sws, and add new ones.
00408         uint    nbMats1=0;
00409         uint    nbMats2=0;
00410         static vector<CTmpVertexWeight>         sws;
00411         sws.reserve(NL3D_MESH_SKINNING_MAX_MATRIX * 2);
00412         sws.clear();
00413 
00414         // For all weights of sw1.
00415         uint i;
00416         for(i=0; i<NL3D_MESH_SKINNING_MAX_MATRIX; i++)
00417         {
00418                 CTmpVertexWeight        vw;
00419                 vw.MatrixId= sw1.MatrixId[i];
00420                 vw.Weight= sw1.Weights[i]*(1-interValue);
00421                 // if this weight is not null.
00422                 if(vw.Weight>0)
00423                 {
00424                         // add it to the list.
00425                         sws.push_back(vw);
00426                 }
00427                 // For skinning reduction.
00428                 if(sw1.Weights[i]>0)
00429                         nbMats1++;
00430         }
00431 
00432 
00433         // For all weights of sw1.
00434         for(i=0; i<NL3D_MESH_SKINNING_MAX_MATRIX; i++)
00435         {
00436                 CTmpVertexWeight        vw;
00437                 vw.MatrixId= sw2.MatrixId[i];
00438                 vw.Weight= sw2.Weights[i]*(interValue);
00439                 // if this weight is not null.
00440                 if(vw.Weight>0)
00441                 {
00442                         // add it or add influence to the matrix.
00443                         vector<CTmpVertexWeight>::iterator              it= find(sws.begin(), sws.end(), vw);
00444                         if(it== sws.end())
00445                                 sws.push_back(vw);
00446                         else
00447                                 it->Weight+= vw.Weight;
00448                 }
00449                 // For skinning reduction.
00450                 if(sw2.Weights[i]>0)
00451                         nbMats2++;
00452         }
00453 
00454 
00455         // Then keep just the best.
00456         // sort by Weight decreasing order.
00457         sort(sws.begin(), sws.end());
00458 
00459         // clamp the result to the wanted max matrix.
00460         uint    nbMatsOut;
00461         switch(_SkinReduction)
00462         {
00463         case CMRMParameters::SkinReductionMin:
00464                 nbMatsOut= min(nbMats1, nbMats2);
00465                 break;
00466         case CMRMParameters::SkinReductionMax:
00467                 nbMatsOut= max(nbMats1, nbMats2);
00468                 break;
00469         case CMRMParameters::SkinReductionBest:
00470                 nbMatsOut= min( (uint)sws.size(), (uint)NL3D_MESH_SKINNING_MAX_MATRIX );
00471                 break;
00472         default:
00473                 nlstop;
00474         };
00475         // For security.
00476         nbMatsOut= min(nbMatsOut, (uint)sws.size());
00477         nlassert(nbMatsOut<=NL3D_MESH_SKINNING_MAX_MATRIX);
00478 
00479 
00480         // Then output the result to the skinWeight, normalizing.
00481         float   sumWeight=0;
00482         for(i= 0; i<nbMatsOut; i++)
00483         {
00484                 sumWeight+= sws[i].Weight;
00485         }
00486 
00487         CMesh::CSkinWeight      ret;
00488         // Fill only needed matrix (other are rested in CMesh::CSkinWeight ctor).
00489         for(i= 0; i<nbMatsOut; i++)
00490         {
00491                 ret.MatrixId[i]= sws[i].MatrixId;
00492                 ret.Weights[i]= sws[i].Weight / sumWeight;
00493         }
00494 
00495         return ret;
00496 }

void NL3D::CMRMBuilder::compileMRM const CMesh::CMeshBuild mbuild,
std::vector< CMesh::CMeshBuild * > &  bsList,
const CMRMParameters params,
CMeshMRMSkinnedGeom::CMeshBuildMRM mrmMesh,
uint  numMaxMaterial
 

Compile a MRM skinned mesh info.

Parameters:
mbuild the input mesh
params the parameters of MRM process.
mrmMesh the result MRM mesh.

Definition at line 3050 of file mrm_builder.cpp.

References _HasMeshInterfaces, _SkinReduction, buildAllLods(), buildBlendShapes(), buildFinalMRM(), buildMeshBuildMrm(), buildMrmBaseMesh(), buildMRMSewingMeshes(), NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::DistanceCoarsest, NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::DistanceFinest, NL3D::CMeshMRMSkinnedGeom::CMeshBuildMRM::DistanceMiddle, nlassert, normalizeBaseMeshSkin(), params, NL3D::CMesh::CMeshBuild::SkinWeights, uint, uint32, NL3D::CMesh::CMeshBuild::VertexFlags, and NL3D::CMesh::CMeshBuild::Vertices.

03053 {
03054         // Temp data.
03055         CMRMMesh                                                baseMesh;
03056         vector<CMRMMeshGeom>                    lodMeshs;
03057         CMRMMeshFinal                                   finalMRM;
03058         vector<CMRMMeshFinal>                   finalBsMRM;
03059         uint32  vbFlags;
03060 
03061 
03062         nlassert(params.DistanceFinest>=0);
03063         nlassert(params.DistanceMiddle > params.DistanceFinest);
03064         nlassert(params.DistanceCoarsest > params.DistanceMiddle);
03065 
03066 
03067         // Copy some parameters.
03068         _SkinReduction= params.SkinReduction;
03069 
03070         // Skinning??
03071         _Skinned= ((mbuild.VertexFlags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag);
03072         // Skinning is OK only if SkinWeights are of same size as vertices.
03073         _Skinned= _Skinned && ( mbuild.Vertices.size()==mbuild.SkinWeights.size() );
03074         
03075         // MeshInterface setuped ?
03076         _HasMeshInterfaces= buildMRMSewingMeshes(mbuild, params.NLods, params.Divisor);
03077 
03078         // from mbuild, build an internal MRM mesh representation.
03079         // vbFlags returned is the VBuffer format supported by CMRMBuilder.
03080         // NB: skinning is removed because skinning is made in software in CMeshMRMGeom.
03081         vbFlags= buildMrmBaseMesh(mbuild, baseMesh);
03082 
03083         // Construct all blend shapes in the same way we have constructed the basemesh mrm
03084         buildBlendShapes (baseMesh, bsList, vbFlags);
03085 
03086         // If skinned, must ensure that skin weights have weights in ascending order.
03087         if(_Skinned)
03088         {
03089                 normalizeBaseMeshSkin(baseMesh);
03090         }
03091 
03092         // from this baseMesh, builds all LODs of the MRM, with geomorph info. NB: vertices/wedges are duplicated.
03093         buildAllLods (  baseMesh, lodMeshs, params.NLods, params.Divisor );
03094 
03095         // From this array of LOD, build a finalMRM, by regrouping identical vertices/wedges, and compute index geomorphs.
03096         buildFinalMRM(lodMeshs, finalMRM);
03097 
03098         // From this finalMRM, build output: a CMeshBuildMRM.
03099         buildMeshBuildMrm(finalMRM, mrmMesh, vbFlags, numMaxMaterial, mbuild);
03100 
03101         // Copy degradation control params.
03102         mrmMesh.DistanceFinest= params.DistanceFinest;
03103         mrmMesh.DistanceMiddle= params.DistanceMiddle;
03104         mrmMesh.DistanceCoarsest= params.DistanceCoarsest;
03105 }

void NL3D::CMRMBuilder::compileMRM const CMesh::CMeshBuild mbuild,
std::vector< CMesh::CMeshBuild * > &  bsList,
const CMRMParameters params,
CMeshMRMGeom::CMeshBuildMRM mrmMesh,
uint  numMaxMaterial
 

Compile a MRM mesh info.

Parameters:
mbuild the input mesh
params the parameters of MRM process.
mrmMesh the result MRM mesh.

Definition at line 2991 of file mrm_builder.cpp.

References _HasMeshInterfaces, _SkinReduction, buildAllLods(), buildBlendShapes(), buildFinalMRM(), buildMeshBuildMrm(), buildMrmBaseMesh(), buildMRMSewingMeshes(), NL3D::CMeshMRMGeom::CMeshBuildMRM::DistanceCoarsest, NL3D::CMeshMRMGeom::CMeshBuildMRM::DistanceFinest, NL3D::CMeshMRMGeom::CMeshBuildMRM::DistanceMiddle, nlassert, normalizeBaseMeshSkin(), params, NL3D::CMesh::CMeshBuild::SkinWeights, uint, uint32, NL3D::CMesh::CMeshBuild::VertexFlags, and NL3D::CMesh::CMeshBuild::Vertices.

Referenced by NL3D::CMeshMRMSkinnedGeom::build(), and NL3D::CMeshMRMGeom::build().

02994 {
02995         // Temp data.
02996         CMRMMesh                                                baseMesh;
02997         vector<CMRMMeshGeom>                    lodMeshs;
02998         CMRMMeshFinal                                   finalMRM;
02999         vector<CMRMMeshFinal>                   finalBsMRM;
03000         uint32  vbFlags;
03001 
03002 
03003         nlassert(params.DistanceFinest>=0);
03004         nlassert(params.DistanceMiddle > params.DistanceFinest);
03005         nlassert(params.DistanceCoarsest > params.DistanceMiddle);
03006 
03007 
03008         // Copy some parameters.
03009         _SkinReduction= params.SkinReduction;
03010 
03011         // Skinning??
03012         _Skinned= ((mbuild.VertexFlags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag);
03013         // Skinning is OK only if SkinWeights are of same size as vertices.
03014         _Skinned= _Skinned && ( mbuild.Vertices.size()==mbuild.SkinWeights.size() );
03015         
03016         // MeshInterface setuped ?
03017         _HasMeshInterfaces= buildMRMSewingMeshes(mbuild, params.NLods, params.Divisor);
03018 
03019         // from mbuild, build an internal MRM mesh representation.
03020         // vbFlags returned is the VBuffer format supported by CMRMBuilder.
03021         // NB: skinning is removed because skinning is made in software in CMeshMRMGeom.
03022         vbFlags= buildMrmBaseMesh(mbuild, baseMesh);
03023 
03024         // Construct all blend shapes in the same way we have constructed the basemesh mrm
03025         buildBlendShapes (baseMesh, bsList, vbFlags);
03026 
03027         // If skinned, must ensure that skin weights have weights in ascending order.
03028         if(_Skinned)
03029         {
03030                 normalizeBaseMeshSkin(baseMesh);
03031         }
03032 
03033         // from this baseMesh, builds all LODs of the MRM, with geomorph info. NB: vertices/wedges are duplicated.
03034         buildAllLods (  baseMesh, lodMeshs, params.NLods, params.Divisor );
03035 
03036         // From this array of LOD, build a finalMRM, by regrouping identical vertices/wedges, and compute index geomorphs.
03037         buildFinalMRM(lodMeshs, finalMRM);
03038 
03039         // From this finalMRM, build output: a CMeshBuildMRM.
03040         buildMeshBuildMrm(finalMRM, mrmMesh, vbFlags, numMaxMaterial, mbuild);
03041 
03042         // Copy degradation control params.
03043         mrmMesh.DistanceFinest= params.DistanceFinest;
03044         mrmMesh.DistanceMiddle= params.DistanceMiddle;
03045         mrmMesh.DistanceCoarsest= params.DistanceCoarsest;
03046 }

void NL3D::CMRMBuilder::computeBsVerticesAttributes std::vector< CMRMMesh > &  srcBsMeshs,
std::vector< CMRMMesh > &  srcBsMeshsMod
[private]
 

float NL3D::CMRMBuilder::computeEdgeCost const CMRMEdge edge  )  [private]
 

Definition at line 244 of file mrm_builder.cpp.

References _CurrentLodComputed, _HasMeshInterfaces, _SewingMeshes, edgeContinue(), edgeNearUniqueMatFace(), getDeltaFaceNormals(), NL3D::CMRMSewingMesh::getNumCollapseEdge(), NL3D::CMRMSewingMesh::mustCollapseEdge(), sint, TmpVertices, uint, NL3D::CMRMEdge::v0, NL3D::CMRMEdge::v1, and vertexContinue().

Referenced by insertFaceIntoEdgeList().

00245 {
00246         sint    v1= edge.v0;
00247         sint    v2= edge.v1;
00248         // more expensive is the edge, later it will collapse.
00249 
00250 
00251         // **** standard cost
00252 
00253         // compute size of the edge.
00254         float   cost=(TmpVertices[v1].Current-TmpVertices[v2].Current).norm();
00255 
00256         // compute "curvature" of the edge.
00257         float   faceCost= (getDeltaFaceNormals(v1)+getDeltaFaceNormals(v2));
00258         // totally plane faces (faceCost==0) must be collapsed with respect to size (and not random if cost==0).
00259         // else we may have Plane Mesh (like flags) that will collapse in a very ugly way.
00260         faceCost= max(faceCost, 0.01f);
00261 
00262         // modulate size with curvature.
00263         cost*= faceCost;
00264 
00265         // Like H.Hope, add a weight on discontinuities..
00266         if( !vertexContinue(v1) && !vertexContinue(v2) )
00267         {
00268                 // Nb: don't do this on discontinuities edges, unless the unique material face will collapse (pffiou!!).
00269                 if( edgeContinue(edge) || edgeNearUniqueMatFace(edge) )
00270                         cost*=4;
00271         }
00272 
00273         // **** Interface Sewing cost
00274         if(_HasMeshInterfaces)
00275         {
00276                 // if the 2 vertices comes from a Sewing Interface mesh (must be a real interface id)
00277                 sint    meshSewingId= TmpVertices[v1].InterfaceLink.InterfaceId;
00278                 if( meshSewingId>=0 && TmpVertices[v2].InterfaceLink.InterfaceId>=0 )
00279                 {
00280                         // if the 2 vertices comes from the same Sewing Interface mesh
00281                         if( meshSewingId == TmpVertices[v2].InterfaceLink.InterfaceId )
00282                         {
00283                                 // Then the edge is one of the sewing interface mesh. must do special things for it
00284                                 CMRMSewingMesh  &sewingMesh= _SewingMeshes[meshSewingId];
00285                                 uint    dummy;
00286 
00287                                 // get the sewing edge id
00288                                 CMRMEdge        sewingEdge;
00289                                 sewingEdge.v0= TmpVertices[v1].InterfaceLink.InterfaceVertexId;
00290                                 sewingEdge.v1= TmpVertices[v2].InterfaceLink.InterfaceVertexId;
00291                                 // if the current sewing lod want to collapse this edge
00292                                 sint collapseId= sewingMesh.mustCollapseEdge(_CurrentLodComputed, sewingEdge, dummy);
00293                                 if(collapseId>=0)
00294                                 {
00295                                         // Then set a negative priority (ie will collapse as soon as possible). from -N to -1.
00296                                         // NB: sort them according to collapseId
00297                                         cost= (float)(-sewingMesh.getNumCollapseEdge(_CurrentLodComputed) + collapseId);
00298                                 }
00299                                 else
00300                                 {
00301                                         // This edge must not collapse at this Lod, set an infinite priority (hope will never collapse).
00302                                         cost= FLT_MAX;
00303                                 }
00304                         }
00305                         else
00306                         {
00307                                 /* The edge is between 2 interfaces but not the same. If we collide it we'll have holes!
00308                                         This problem arise if space beetween interfaces is small. eg: if we setup an interface beetween 
00309                                         hair and head, and an other one beetween head and torso, then we'll have this problem in the
00310                                         back of the neck.
00311                                         The solution is to make a big big cost to hope we'll never collide them (else Holes...)!!
00312                                         Don't use FLT_MAX to still have a correct order if we don't have choice...
00313                                 */
00314                                 cost*= 10000;
00315                         }
00316                 }
00317         }
00318 
00319         return cost;
00320 }

bool NL3D::CMRMBuilder::edgeContinue const CMRMEdge edge  )  [private]
 

Definition at line 169 of file mrm_builder.cpp.

References NumAttributes, NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, TmpVertices, NL3D::CMRMEdge::v0, NL3D::CMRMEdge::v1, and w.

Referenced by computeEdgeCost(), and edgeNearUniqueMatFace().

00170 {
00171         sint v0= edge.v0;
00172         sint v1= edge.v1;
00173         CMRMVertex      &Vertex1=TmpVertices[v0];
00174 
00175         // build list sharing edge.
00176         vector<sint>    deletedFaces;
00177         sint i;
00178         for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00179         {
00180                 sint    numFace= Vertex1.SharedFaces[i];
00181                 if(TmpFaces[numFace].hasVertex(v1))
00182                         deletedFaces.push_back(numFace);
00183         }
00184 
00185         sint    matId=-1;
00186         // test if faces have same material.
00187         for(i=0;i<(sint)deletedFaces.size();i++)
00188         {
00189                 sint    m;
00190                 m= TmpFaces[deletedFaces[i]].MaterialId;
00191                 if(matId>=0 && matId!=m)        return false;
00192                 else    matId=m;
00193         }
00194 
00195         // test if faces have same wedge (for all att).
00196         for(sint attId=0;attId<NumAttributes;attId++)
00197         {
00198                 sint    numwedge1=-1,numwedge2=-1;
00199                 for(i=0;i<(sint)deletedFaces.size();i++)
00200                 {
00201                         sint    w;
00202                         w= TmpFaces[deletedFaces[i]].getAssociatedWedge(attId, v0);
00203                         if(numwedge1>=0 && numwedge1!=w)        return false;
00204                         else    numwedge1=w;
00205                         w= TmpFaces[deletedFaces[i]].getAssociatedWedge(attId, v1);
00206                         if(numwedge2>=0 && numwedge2!=w)        return false;
00207                         else    numwedge2=w;
00208                 }
00209         }
00210 
00211         return true;
00212 }

bool NL3D::CMRMBuilder::edgeNearUniqueMatFace const CMRMEdge edge  )  [private]
 

Definition at line 214 of file mrm_builder.cpp.

References edgeContinue(), NL3D::CMRMFaceBuild::getEdge(), NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, TmpVertices, NL3D::CMRMEdge::v0, and NL3D::CMRMEdge::v1.

Referenced by computeEdgeCost().

00215 {
00216         sint v0= edge.v0;
00217         sint v1= edge.v1;
00218         CMRMVertex      &Vertex1=TmpVertices[v0];
00219 
00220         // build list sharing edge.
00221         vector<sint>    deletedFaces;
00222         sint i;
00223         for(i=0;i<(sint)Vertex1.SharedFaces.size();i++)
00224         {
00225                 sint    numFace= Vertex1.SharedFaces[i];
00226                 if(TmpFaces[numFace].hasVertex(v1))
00227                         deletedFaces.push_back(numFace);
00228         }
00229 
00230         // test if faces are not isolated OneMaterial faces.
00231         for(i=0;i<(sint)deletedFaces.size();i++)
00232         {
00233                 CMRMFaceBuild   &f=TmpFaces[deletedFaces[i]];
00234                 if( !edgeContinue(f.getEdge(0)) && 
00235                         !edgeContinue(f.getEdge(1)) && 
00236                         !edgeContinue(f.getEdge(2)))
00237                         return true;
00238         }
00239 
00240         return false;
00241 }

bool NL3D::CMRMBuilder::faceShareWedges CMRMFaceBuild face,
sint  attribId,
sint  numVertex1,
sint  numVertex2
[private]
 

Definition at line 333 of file mrm_builder.cpp.

References NL3D::CMRMFaceBuild::getAssociatedWedge(), NL3D::CMRMAttribute::NbSharedFaces, NL3D::CMRMAttribute::Shared, sint, and TmpAttributes.

Referenced by collapseEdge().

00334 {
00335         sint    numWedge1= face->getAssociatedWedge(attribId, numVertex1);
00336         sint    numWedge2= face->getAssociatedWedge(attribId, numVertex2);
00337         if(numWedge1<0) return false;
00338         if(numWedge2<0) return false;
00339 
00340         CMRMAttribute   &w1= TmpAttributes[attribId][numWedge1];
00341         CMRMAttribute   &w2= TmpAttributes[attribId][numWedge2];
00342         return w1.Shared && w2.Shared && w1.NbSharedFaces>0 && w2.NbSharedFaces>0;
00343 }

sint NL3D::CMRMBuilder::findInsertAttributeInBaseMesh CMRMMesh baseMesh,
sint  attId,
sint  vertexId,
const CVectorH att
[private]
 

Definition at line 1648 of file mrm_builder.cpp.

References _AttributeMap, NL3D::CMRMBuilder::CAttributeKey::Attribute, NL3D::CMRMMesh::Attributes, sint, and NL3D::CMRMBuilder::CAttributeKey::VertexId.

Referenced by findInsertColorInBaseMesh(), findInsertNormalInBaseMesh(), and findInsertUvwInBaseMesh().

01649 {
01650         // find this attribute in the map.
01651         CAttributeKey   key;
01652         key.VertexId= vertexId;
01653         key.Attribute= att;
01654         TAttributeMap::iterator         it= _AttributeMap[attId].find(key);
01655 
01656         // if attribute not found in the map, then insert a new one.
01657         if(it==_AttributeMap[attId].end())
01658         {
01659                 sint    idx= baseMesh.Attributes[attId].size();
01660                 // insert into the array.
01661                 baseMesh.Attributes[attId].push_back(att);
01662                 // insert into the map.
01663                 _AttributeMap[attId].insert(make_pair(key, idx));
01664                 return idx;
01665         }
01666         else
01667         {
01668                 // return the one found.
01669                 return it->second;
01670         }
01671 }

sint NL3D::CMRMBuilder::findInsertColorInBaseMesh CMRMMesh baseMesh,
sint  attId,
sint  vertexId,
CRGBA  col
[private]
 

Definition at line 1685 of file mrm_builder.cpp.

References NLMISC::CRGBA::A, NLMISC::CRGBA::B, findInsertAttributeInBaseMesh(), NLMISC::CRGBA::G, NLMISC::CRGBA::R, sint, NLMISC::CVectorH::w, NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z.

Referenced by buildMrmBaseMesh().

01686 {
01687         CVectorH        att;
01688         att.x= col.R;
01689         att.y= col.G;
01690         att.z= col.B;
01691         att.w= col.A;
01692         return findInsertAttributeInBaseMesh(baseMesh, attId, vertexId, att);
01693 }

sint NL3D::CMRMBuilder::findInsertNormalInBaseMesh CMRMMesh baseMesh,
sint  attId,
sint  vertexId,
const CVector normal
[private]
 

Definition at line 1675 of file mrm_builder.cpp.

References findInsertAttributeInBaseMesh(), sint, and NLMISC::CVectorH::w.

Referenced by buildMrmBaseMesh().

01676 {
01677         CVectorH        att;
01678         att= normal;
01679         att.w= 0;
01680         return findInsertAttributeInBaseMesh(baseMesh, attId, vertexId, att);
01681 }

sint NL3D::CMRMBuilder::findInsertUvwInBaseMesh CMRMMesh baseMesh,
sint  attId,
sint  vertexId,
const NLMISC::CUVW uvw
[private]
 

Definition at line 1697 of file mrm_builder.cpp.

References findInsertAttributeInBaseMesh(), sint, NLMISC::CUVW::U, NLMISC::CUVW::V, NLMISC::CVectorH::w, NLMISC::CUVW::W, NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z.

Referenced by buildMrmBaseMesh().

01698 {
01699         CVectorH        att;
01700         att.x= uvw.U;
01701         att.y= uvw.V;
01702         att.z= uvw.W;
01703         att.w= 0;
01704         return findInsertAttributeInBaseMesh(baseMesh, attId, vertexId, att);
01705 }

sint NL3D::CMRMBuilder::followVertex sint  i  )  [private]
 

Definition at line 832 of file mrm_builder.cpp.

References NL3D::CMRMVertex::CollapsedTo, sint, and TmpVertices.

Referenced by makeLODMesh().

00833 {
00834         CMRMVertex      &vert=TmpVertices[i];
00835         if(vert.CollapsedTo>=0)
00836                 return followVertex(vert.CollapsedTo);
00837         else
00838                 return i;
00839 }

sint NL3D::CMRMBuilder::followWedge sint  attribId,
sint  i
[private]
 

Definition at line 841 of file mrm_builder.cpp.

References NL3D::CMRMAttribute::CollapsedTo, sint, and TmpAttributes.

Referenced by makeLODMesh().

00842 {
00843         CMRMAttribute   &wedge= TmpAttributes[attribId][i];
00844         if(wedge.CollapsedTo>=0)
00845                 return followWedge(attribId, wedge.CollapsedTo);
00846         else
00847                 return i;
00848 }

float NL3D::CMRMBuilder::getDeltaFaceNormals sint  numvertex  )  [private]
 

Definition at line 143 of file mrm_builder.cpp.

References NL3D::CMRMVertex::Current, NLMISC::CVector::normalize(), NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, and TmpVertices.

Referenced by computeEdgeCost().

00144 {
00145         // return a positive value of Somme(|DeltaNormals|) / NNormals.
00146         CMRMVertex      &vert= TmpVertices[numvertex];
00147         float   delta=0;
00148         CVector refNormal;
00149         sint    nfaces=vert.SharedFaces.size();
00150         for(sint i=0;i<nfaces;i++)
00151         {
00152                 CVector normal;
00153                 CVector &v0= TmpVertices[TmpFaces[i].Corner[0].Vertex].Current;
00154                 CVector &v1= TmpVertices[TmpFaces[i].Corner[1].Vertex].Current;
00155                 CVector &v2= TmpVertices[TmpFaces[i].Corner[2].Vertex].Current;
00156                 normal= (v1-v0)^(v2-v0);
00157                 normal.normalize();
00158                 if(i==0)
00159                         refNormal=normal;
00160                 else
00161                         delta+=(1-refNormal*normal);
00162         }
00163         if(nfaces<2)
00164                 return 0;
00165         else
00166                 return delta/(nfaces-1);
00167 }

void NL3D::CMRMBuilder::init const CMRMMesh baseMesh  )  [private]
 

Definition at line 867 of file mrm_builder.cpp.

References _HasMeshInterfaces, NL3D::CMRMMesh::Attributes, NL3D::CMRMMesh::BlendShapes, NL3D::CMRMFace::Corner, EdgeCollapses, NL3D::CMRMMesh::Faces, insertFaceIntoEdgeList(), NL3D::CMRMMesh::InterfaceLinks, NL3D_MRM_MAX_ATTRIB, NL3D::CMRMMesh::NumAttributes, NumAttributes, sint, NL3D::CMRMMesh::SkinWeights, TmpAttributes, TmpFaces, TmpVertices, uint32, NL3D::CMRMCorner::Vertex, and NL3D::CMRMMesh::Vertices.

Referenced by buildAllLods(), and makeFromMesh().

00868 {
00869         sint    i, attId;
00870 
00871 
00872         // First clear ALL.
00873         TmpVertices.clear();
00874         for(attId=0;attId<NL3D_MRM_MAX_ATTRIB;attId++)
00875         {
00876                 TmpAttributes[attId].clear();
00877         }
00878         TmpFaces.clear();
00879         EdgeCollapses.clear();
00880 
00881 
00882         // resize.
00883         NumAttributes= baseMesh.NumAttributes;
00884         TmpVertices.resize(baseMesh.Vertices.size());
00885         for(attId=0;attId<NumAttributes;attId++)
00886         {
00887                 TmpAttributes[attId].resize(baseMesh.Attributes[attId].size());
00888         }
00889         TmpFaces.resize(baseMesh.Faces.size());
00890 
00891 
00892         // Then copy.
00893         for(i=0;i<(sint)baseMesh.Vertices.size();i++)
00894         {
00895                 TmpVertices[i].Current= TmpVertices[i].Original= baseMesh.Vertices[i];
00896                 TmpVertices[i].BSCurrent.resize(baseMesh.BlendShapes.size());
00897                 for(uint32 j = 0; j <baseMesh.BlendShapes.size() ;++j)
00898                         TmpVertices[i].BSCurrent[j]= baseMesh.BlendShapes[j].Vertices[i];
00899                 if(_Skinned)
00900                         TmpVertices[i].CurrentSW= TmpVertices[i].OriginalSW= baseMesh.SkinWeights[i];
00901                 if(_HasMeshInterfaces)
00902                         TmpVertices[i].InterfaceLink= baseMesh.InterfaceLinks[i];
00903         }
00904         for(attId=0;attId<NumAttributes;attId++)
00905         {
00906                 for(i=0;i<(sint)baseMesh.Attributes[attId].size();i++)
00907                 {
00908                         TmpAttributes[attId][i].Current= TmpAttributes[attId][i].Original= 
00909                         baseMesh.Attributes[attId][i];
00910                         TmpAttributes[attId][i].BSCurrent.resize(baseMesh.BlendShapes.size());
00911                         for(uint32 j = 0; j <baseMesh.BlendShapes.size() ;++j)
00912                                 TmpAttributes[attId][i].BSCurrent[j]= baseMesh.BlendShapes[j].Attributes[attId][i];
00913                 }
00914         }
00915         for(i=0;i<(sint)baseMesh.Faces.size();i++)
00916         {
00917                 TmpFaces[i]= baseMesh.Faces[i];
00918                 TmpFaces[i].BSInterpolated.resize(baseMesh.BlendShapes.size());
00919         }
00920 
00921 
00922         // Create vertices sharedFaces.
00923         for(i=0;i<(sint)TmpFaces.size();i++)
00924         {
00925                 CMRMFaceBuild           &face= TmpFaces[i];
00926 
00927                 TmpVertices[face.Corner[0].Vertex].SharedFaces.push_back(i);
00928                 TmpVertices[face.Corner[1].Vertex].SharedFaces.push_back(i);
00929                 TmpVertices[face.Corner[2].Vertex].SharedFaces.push_back(i);
00930         }
00931 
00932 
00933         // Compute EdgeCost.
00934         for(i=0;i<(sint)TmpFaces.size();i++)
00935         {
00936                 CMRMFaceBuild           &f= TmpFaces[i];
00937                 // At start, valid all edges.
00938                 f. ValidIt0= true;
00939                 f. ValidIt1= true;
00940                 f. ValidIt2= true;
00941                 insertFaceIntoEdgeList(f);
00942         }
00943 }

void NL3D::CMRMBuilder::insertFaceIntoEdgeList CMRMFaceBuild tmpf  )  [private]
 

Definition at line 347 of file mrm_builder.cpp.

References computeEdgeCost(), EdgeCollapses, NL3D::CMRMFaceBuild::getEdge(), len, NL3D::CMRMFaceBuild::ValidIt0, NL3D::CMRMFaceBuild::ValidIt1, and NL3D::CMRMFaceBuild::ValidIt2.

Referenced by collapseEdges(), and init().

00348 {
00349         float   len;
00350         if(f.ValidIt0)
00351         {
00352                 len= computeEdgeCost(f.getEdge(0));
00353                 f. It0= EdgeCollapses.insert( TEdgeMap::value_type( len, CMRMEdgeFace(f.getEdge(0),&f) ) );
00354         }
00355         if(f.ValidIt1)
00356         {
00357                 len= computeEdgeCost(f.getEdge(1));
00358                 f. It1= EdgeCollapses.insert( TEdgeMap::value_type( len, CMRMEdgeFace(f.getEdge(1),&f) ) );
00359         }
00360         if(f.ValidIt2)
00361         {
00362                 len= computeEdgeCost(f.getEdge(2));
00363                 f. It2= EdgeCollapses.insert( TEdgeMap::value_type( len, CMRMEdgeFace(f.getEdge(2),&f) ) );
00364         }
00365 }

void NL3D::CMRMBuilder::makeCoarserBS std::vector< CMRMBlendShape > &  csBsMeshs  )  [private]
 

Definition at line 1203 of file mrm_builder.cpp.

References NL3D::CMRMBlendShape::Attributes, NL3D::CMRMAttribute::BSCurrent, NL3D::CMRMVertex::BSCurrent, NL3D::CMRMAttribute::CoarserIndex, NL3D::CMRMVertex::CoarserIndex, NumAttributes, NL3D::CMRMBlendShape::NumAttributes, sint32, TmpAttributes, TmpVertices, uint32, and NL3D::CMRMBlendShape::Vertices.

Referenced by makeFromMesh().

01204 {
01205         uint32 i, k;
01206         sint32 nSizeVert, nSizeAttr, attId;
01207 
01208         // Calculate size of vertices array
01209         nSizeVert = 0;
01210         for (i = 0; i < TmpVertices.size(); ++i)
01211                 if(TmpVertices[i].CoarserIndex > nSizeVert)
01212                         nSizeVert = TmpVertices[i].CoarserIndex;
01213         ++nSizeVert;
01214 
01215         for (k = 0; k < csBsMeshs.size(); ++k)
01216         {
01217                 CMRMBlendShape &rBsCoarserMesh = csBsMeshs[k];
01218 
01219                 rBsCoarserMesh.Vertices.resize (nSizeVert);
01220                 rBsCoarserMesh.NumAttributes = NumAttributes;
01221 
01222                 // Vertices
01223                 for(i = 0; i < TmpVertices.size(); ++i)
01224                 {
01225                         CMRMVertex &vert = TmpVertices[i];
01226                         if (vert.CoarserIndex != -1)
01227                         {
01228                                 rBsCoarserMesh.Vertices[vert.CoarserIndex] = vert.BSCurrent[k];
01229                         }
01230                 }
01231 
01232                 for (attId = 0; attId < NumAttributes; attId++)
01233                 {
01234                         // Calculate size of attribute attId array
01235                         nSizeAttr = 0;
01236                         for(i = 0; i < TmpAttributes[attId].size(); i++)
01237                                 if (TmpAttributes[attId][i].CoarserIndex > nSizeAttr)
01238                                         nSizeAttr = TmpAttributes[attId][i].CoarserIndex;
01239                         ++nSizeAttr;
01240 
01241                         rBsCoarserMesh.Attributes[attId].resize (nSizeAttr);
01242 
01243                         for (i = 0; i < TmpAttributes[attId].size(); i++)
01244                         {
01245                                 CMRMAttribute &wedge = TmpAttributes[attId][i];
01246                                 if (wedge.CoarserIndex != -1)
01247                                 {
01248                                         rBsCoarserMesh.Attributes[attId][wedge.CoarserIndex] = wedge.BSCurrent[k];
01249                                 }
01250                         }
01251                 }
01252         }
01253 }

void NL3D::CMRMBuilder::makeFromMesh const CMRMMesh baseMesh,
CMRMMeshGeom lodMesh,
CMRMMesh coarserMesh,
sint  nWantedFaces
[private]
 

this is the root call to compute a single lodMesh and the coarserMesh from a baseMesh.

Definition at line 1256 of file mrm_builder.cpp.

References NL3D::CMRMMesh::BlendShapes, collapseEdges(), init(), makeCoarserBS(), makeLODMesh(), saveCoarserMesh(), and sint.

Referenced by buildAllLods().

01257 {
01258         // Init Tmp values in MRM builder.
01259         init(baseMesh);
01260 
01261         // compute MRM too next tgt face.
01262         collapseEdges(nWantedFaces);
01263 
01264         // save the coarser mesh.
01265         saveCoarserMesh(coarserMesh);
01266         // Build coarser BlendShapes.
01267         coarserMesh.BlendShapes.resize(baseMesh.BlendShapes.size());
01268         makeCoarserBS(coarserMesh.BlendShapes);
01269 
01270         // build the lodMesh (baseMesh, with vertex/Attributes collapse infos).
01271         lodMesh= baseMesh;
01272         makeLODMesh(lodMesh);
01273 
01274         // end for this level.
01275 }

void NL3D::CMRMBuilder::makeLODMesh CMRMMeshGeom lodMesh  )  [private]
 

Definition at line 1108 of file mrm_builder.cpp.

References NL3D::CMRMCorner::Attributes, NL3D::CMRMMeshGeom::CoarserFaces, NL3D::CMRMFace::Corner, followVertex(), followWedge(), index, nlassert, NumAttributes, sint, TmpAttributes, TmpVertices, and NL3D::CMRMCorner::Vertex.

Referenced by makeFromMesh().

01109 {
01110         sint    i,j,attId,index,coidx;
01111 
01112         // for all faces of this mesh, find target in the coarser mesh.
01113         for(i=0;i<(sint)lodMesh.CoarserFaces.size();i++)
01114         {
01115                 CMRMFace        &face= lodMesh.CoarserFaces[i];
01116 
01117                 // For 3 corners.
01118                 for(j=0;j<3;j++)
01119                 {
01120                         // Vertex.
01121                         // The index is yet the index in the finer mesh.
01122                         index= face.Corner[j].Vertex;
01123                         // the index in the coarser mesh is vert.CoarserIndex.
01124                         coidx= TmpVertices[index].CoarserIndex;
01125                         // but if this vertex is collapsed, must find the good index (yet in the finer mesh)
01126                         if(coidx==-1)
01127                         {
01128                                 // find to which we must collapse.
01129                                 index= followVertex(index);
01130                                 // and so we have the coarser index. this one must be valid.
01131                                 coidx= TmpVertices[index].CoarserIndex;
01132                                 nlassert(coidx>=0);
01133                         }
01134                         // update corner of CoarserFace.
01135                         face.Corner[j].Vertex= coidx;
01136 
01137 
01138                         // Do exactly same thing for all attributes.
01139                         for(attId=0;attId<NumAttributes;attId++)
01140                         {
01141                                 index= face.Corner[j].Attributes[attId];
01142                                 coidx= TmpAttributes[attId][index].CoarserIndex;
01143                                 if(coidx==-1)
01144                                 {
01145                                         index= followWedge(attId, index);
01146                                         coidx= TmpAttributes[attId][index].CoarserIndex;
01147                                         nlassert(coidx>=0);
01148                                 }
01149                                 face.Corner[j].Attributes[attId]= coidx;
01150                         }
01151                 }
01152         }
01153 
01154 }

void NL3D::CMRMBuilder::normalizeBaseMeshSkin CMRMMesh baseMesh  )  const [private]
 

Definition at line 1905 of file mrm_builder.cpp.

References nlassert, normalizeSkinWeight(), NL3D::CMRMMesh::SkinWeights, and uint.

Referenced by compileMRM().

01906 {
01907         nlassert(_Skinned);
01908 
01909         for(uint i=0; i<baseMesh.SkinWeights.size(); i++)
01910         {
01911                 baseMesh.SkinWeights[i]= normalizeSkinWeight(baseMesh.SkinWeights[i]);
01912         }
01913 }

CMesh::CSkinWeight NL3D::CMRMBuilder::normalizeSkinWeight const CMesh::CSkinWeight sw  )  const [private]
 

Definition at line 1858 of file mrm_builder.cpp.

References NL3D::CMesh::CSkinWeight::MatrixId, NL3D::CTmpVertexWeight::MatrixId, NL3D_MESH_SKINNING_MAX_MATRIX, uint, NL3D::CTmpVertexWeight::Weight, and NL3D::CMesh::CSkinWeight::Weights.

Referenced by normalizeBaseMeshSkin().

01859 {
01860         uint    nbMats= 0;
01861         static vector<CTmpVertexWeight>         sws;
01862         sws.reserve(NL3D_MESH_SKINNING_MAX_MATRIX);
01863         sws.clear();
01864 
01865         // For all weights of sw1.
01866         uint i;
01867         for(i=0; i<NL3D_MESH_SKINNING_MAX_MATRIX; i++)
01868         {
01869                 CTmpVertexWeight        vw;
01870                 vw.MatrixId= sw.MatrixId[i];
01871                 vw.Weight= sw.Weights[i];
01872                 // if this weight is not null.
01873                 if(vw.Weight>0)
01874                 {
01875                         // add it to the list.
01876                         sws.push_back(vw);
01877                         nbMats++;
01878                 }
01879         }
01880 
01881         // sort by Weight decreasing order.
01882         sort(sws.begin(), sws.end());
01883 
01884 
01885         // Then output the result to the skinWeight, normalizing.
01886         float   sumWeight=0;
01887         for(i= 0; i<nbMats; i++)
01888         {
01889                 sumWeight+= sws[i].Weight;
01890         }
01891 
01892         CMesh::CSkinWeight      ret;
01893         // Fill only needed matrix (other are rested in CMesh::CSkinWeight ctor).
01894         for(i= 0; i<nbMats; i++)
01895         {
01896                 ret.MatrixId[i]= sws[i].MatrixId;
01897                 ret.Weights[i]= sws[i].Weight / sumWeight;
01898         }
01899 
01900         return ret;
01901 }

void NL3D::CMRMBuilder::removeFaceFromEdgeList CMRMFaceBuild f  )  [private]
 

Definition at line 367 of file mrm_builder.cpp.

References EdgeCollapses, NL3D::CMRMFaceBuild::It0, NL3D::CMRMFaceBuild::It1, NL3D::CMRMFaceBuild::It2, NL3D::CMRMFaceBuild::ValidIt0, NL3D::CMRMFaceBuild::ValidIt1, and NL3D::CMRMFaceBuild::ValidIt2.

Referenced by collapseEdge(), and collapseEdges().

00368 {
00369         if(f.ValidIt0)
00370                 EdgeCollapses.erase(f.It0);
00371         if(f.ValidIt1)
00372                 EdgeCollapses.erase(f.It1);
00373         if(f.ValidIt2)
00374                 EdgeCollapses.erase(f.It2);
00375 }

void NL3D::CMRMBuilder::saveCoarserMesh CMRMMesh coarserMesh  )  [private]
 

Definition at line 1010 of file mrm_builder.cpp.

References _HasMeshInterfaces, NL3D::CMRMCorner::Attributes, NL3D::CMRMMesh::Attributes, NL3D::CMRMAttribute::CoarserIndex, NL3D::CMRMVertex::CoarserIndex, NL3D::CMRMAttribute::CollapsedTo, NL3D::CMRMVertex::CollapsedTo, NL3D::CMRMFace::Corner, NL3D::CMRMAttribute::Current, NL3D::CMRMVertex::Current, NL3D::CMRMVertex::CurrentSW, NL3D::CMRMFaceBuild::Deleted, NL3D::CMRMMesh::Faces, index, NL3D::CMRMVertex::InterfaceLink, NL3D::CMRMMesh::InterfaceLinks, NL3D::CMRMFace::MaterialId, NL3D_MRM_MAX_ATTRIB, nlassert, NumAttributes, NL3D::CMRMMesh::NumAttributes, sint, NL3D::CMRMMesh::SkinWeights, TmpAttributes, TmpFaces, TmpVertices, NL3D::CMRMCorner::Vertex, and NL3D::CMRMMesh::Vertices.

Referenced by makeFromMesh().

01011 {
01012         sint    i,attId,index;
01013         // First clear ALL.
01014         coarserMesh.Vertices.clear();
01015         coarserMesh.SkinWeights.clear();
01016         coarserMesh.InterfaceLinks.clear();
01017         for(attId=0;attId<NL3D_MRM_MAX_ATTRIB;attId++)
01018         {
01019                 coarserMesh.Attributes[attId].clear();
01020         }
01021         coarserMesh.Faces.clear();
01022         coarserMesh.NumAttributes= NumAttributes;
01023 
01024         // Vertices.
01025         //==========
01026         index=0;
01027         for(i=0;i<(sint)TmpVertices.size();i++)
01028         {
01029                 CMRMVertex      &vert=TmpVertices[i];
01030                 if(vert.CollapsedTo==-1)        // if exist yet.
01031                 {
01032                         vert.CoarserIndex=index;
01033                         coarserMesh.Vertices.push_back(vert.Current);
01034                         if(_Skinned)
01035                                 coarserMesh.SkinWeights.push_back(vert.CurrentSW);
01036                         if(_HasMeshInterfaces)
01037                                 coarserMesh.InterfaceLinks.push_back(vert.InterfaceLink);
01038 
01039                         index++;
01040                 }
01041                 else
01042                         vert.CoarserIndex=-1;   // indicate that this vertex no more exist and is to be geomorphed to an other.
01043         }
01044 
01045 
01046         // Attributes.
01047         //============
01048         for(attId=0;attId<NumAttributes;attId++)
01049         {
01050                 index=0;
01051                 for(i=0;i<(sint)TmpAttributes[attId].size();i++)
01052                 {
01053                         CMRMAttribute   &wedge= TmpAttributes[attId][i];
01054                         if(wedge.CollapsedTo==-1)       // if exist yet.
01055                         {
01056                                 wedge.CoarserIndex=index;
01057                                 coarserMesh.Attributes[attId].push_back(wedge.Current);
01058                                 index++;
01059                         }
01060                         else if(wedge.CollapsedTo==-2)  // else if totaly destroyed.
01061                         {
01062                                 // Insert this wedge in the coarser mesh.
01063                                 // NB: the coarser mesh faces do not use it anymore, but FinerMesh use it
01064                                 // for geomorph (LODMesh.CoarserFaces may point to it).
01065                                 // NB: look at buildFinalMRM(), it works fine for all cases.
01066                                 wedge.CoarserIndex=index;
01067                                 coarserMesh.Attributes[attId].push_back(wedge.Current);
01068                                 index++;
01069                         }
01070                         else
01071                                 wedge.CoarserIndex=-1;  // indicate that this wedge no more exist and is to be geomorphed to an other.
01072                 }
01073         }
01074 
01075         // Faces.
01076         //=======
01077         for(i=0;i<(sint)TmpFaces.size();i++)
01078         {
01079                 CMRMFaceBuild   &face=TmpFaces[i];
01080                 if(!face.Deleted)
01081                 {
01082                         CMRMFace        newFace;
01083                         // Material.
01084                         newFace.MaterialId= face.MaterialId;
01085                         for(sint j=0;j<3;j++)
01086                         {
01087                                 // Vertex.
01088                                 newFace.Corner[j].Vertex= TmpVertices[face.Corner[j].Vertex].CoarserIndex;
01089                                 nlassert(newFace.Corner[j].Vertex>=0);
01090                                 // Attributes.
01091                                 for(attId=0;attId<NumAttributes;attId++)
01092                                 {
01093                                         sint    oldidx= face.Corner[j].Attributes[attId];
01094                                         newFace.Corner[j].Attributes[attId]= TmpAttributes[attId][oldidx].CoarserIndex;
01095                                         nlassert(newFace.Corner[j].Attributes[attId]>=0);
01096                                 }
01097 
01098                         }
01099 
01100                         coarserMesh.Faces.push_back(newFace);
01101                 }
01102         }
01103 
01104 }

bool NL3D::CMRMBuilder::vertexClosed sint  numvertex  )  [private]
 

Definition at line 108 of file mrm_builder.cpp.

References NL3D::CMRMFace::Corner, NL3D::CMRMFaceBuild::getEdge(), NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, TmpVertices, and NL3D::CMRMCorner::Vertex.

Referenced by collapseEdge().

00109 {
00110         CMRMVertex      &vert= TmpVertices[numvertex];
00111         map<CMRMEdge, sint>             EdgeShare;
00112         // Init to 0.
00113         sint i;
00114         for(i=0;i<(sint)vert.SharedFaces.size();i++)
00115         {
00116                 CMRMFaceBuild           &f=TmpFaces[vert.SharedFaces[i]];
00117                 EdgeShare[f.getEdge(0)]= 0;
00118                 EdgeShare[f.getEdge(1)]= 0;
00119                 EdgeShare[f.getEdge(2)]= 0;
00120         }
00121         // Inc count.
00122         for(i=0;i<(sint)vert.SharedFaces.size();i++)
00123         {
00124                 CMRMFaceBuild           &f=TmpFaces[vert.SharedFaces[i]];
00125                 EdgeShare[f.getEdge(0)]++;
00126                 EdgeShare[f.getEdge(1)]++;
00127                 EdgeShare[f.getEdge(2)]++;
00128         }
00129         // Test open edges.
00130         for(i=0;i<(sint)vert.SharedFaces.size();i++)
00131         {
00132                 CMRMFaceBuild           &f=TmpFaces[vert.SharedFaces[i]];
00133                 sint    v0= f.Corner[0].Vertex;
00134                 sint    v1= f.Corner[1].Vertex;
00135                 sint    v2= f.Corner[2].Vertex;
00136                 if(EdgeShare[f.getEdge(0)]<2 && (v0==numvertex || v1==numvertex)) return false;
00137                 if(EdgeShare[f.getEdge(1)]<2 && (v1==numvertex || v2==numvertex)) return false;
00138                 if(EdgeShare[f.getEdge(2)]<2 && (v0==numvertex || v2==numvertex)) return false;
00139         }
00140         return true;
00141 }

bool NL3D::CMRMBuilder::vertexContinue sint  numvertex  )  [private]
 

Definition at line 103 of file mrm_builder.cpp.

References sint, vertexHasOneMaterial(), and vertexHasOneWedge().

Referenced by collapseEdge(), and computeEdgeCost().

00104 {
00105         return vertexHasOneWedge(numvertex) && vertexHasOneMaterial(numvertex);
00106 }

bool NL3D::CMRMBuilder::vertexHasOneMaterial sint  numvertex  )  [private]
 

Definition at line 90 of file mrm_builder.cpp.

References NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, and TmpVertices.

Referenced by vertexContinue().

00091 {
00092         sint    matId=-1;
00093         CMRMVertex      &vert= TmpVertices[numvertex];
00094         for(sint i=0;i<(sint)vert.SharedFaces.size();i++)
00095         {
00096                 sint    m= TmpFaces[vert.SharedFaces[i]].MaterialId;
00097                 if(matId>=0 && matId!=m)        return false;
00098                 else    matId=m;
00099         }
00100         return true;
00101 }

bool NL3D::CMRMBuilder::vertexHasOneWedge sint  numvertex  )  [private]
 

Definition at line 74 of file mrm_builder.cpp.

References NumAttributes, NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, TmpVertices, and w.

Referenced by vertexContinue().

00075 {
00076         CMRMVertex      &vert= TmpVertices[numvertex];
00077         for(sint attId=0;attId<NumAttributes;attId++)
00078         {
00079                 sint    numwedge=-1;
00080                 for(sint i=0;i<(sint)vert.SharedFaces.size();i++)
00081                 {
00082                         sint    w= TmpFaces[vert.SharedFaces[i]].getAssociatedWedge(attId, numvertex);
00083                         if(numwedge>=0 && numwedge!=w)  return false;
00084                         else    numwedge=w;
00085                 }
00086         }
00087         return true;
00088 }


Field Documentation

TAttributeMap NL3D::CMRMBuilder::_AttributeMap[NL3D_MRM_MAX_ATTRIB] [private]
 

Definition at line 229 of file mrm_builder.h.

Referenced by buildMrmBaseMesh(), and findInsertAttributeInBaseMesh().

uint NL3D::CMRMBuilder::_CurrentLodComputed [private]
 

Definition at line 154 of file mrm_builder.h.

Referenced by buildAllLods(), collapseEdge(), and computeEdgeCost().

TGeomMap NL3D::CMRMBuilder::_GeomMap [private]
 

Definition at line 180 of file mrm_builder.h.

Referenced by buildFinalMRM().

bool NL3D::CMRMBuilder::_HasMeshInterfaces [private]
 

Definition at line 150 of file mrm_builder.h.

Referenced by buildMrmBaseMesh(), CMRMBuilder(), collapseEdge(), compileMRM(), computeEdgeCost(), init(), and saveCoarserMesh().

std::vector<CMRMSewingMesh> NL3D::CMRMBuilder::_SewingMeshes [private]
 

Definition at line 152 of file mrm_builder.h.

Referenced by buildMRMSewingMeshes(), collapseEdge(), and computeEdgeCost().

bool NL3D::CMRMBuilder::_Skinned [private]
 

Definition at line 101 of file mrm_builder.h.

CMRMParameters::TSkinReduction NL3D::CMRMBuilder::_SkinReduction [private]
 

If the current build is skinned, control the quality of the skinning redcution.

Definition at line 103 of file mrm_builder.h.

Referenced by collapseSkinWeight(), and compileMRM().

TEdgeMap NL3D::CMRMBuilder::EdgeCollapses [private]
 

Definition at line 98 of file mrm_builder.h.

Referenced by collapseEdge(), collapseEdges(), init(), insertFaceIntoEdgeList(), and removeFaceFromEdgeList().

sint NL3D::CMRMBuilder::NumAttributes [private]
 

Definition at line 94 of file mrm_builder.h.

Referenced by buildFinalMRM(), CMRMBuilder(), collapseEdge(), edgeContinue(), init(), makeCoarserBS(), makeLODMesh(), saveCoarserMesh(), and vertexHasOneWedge().

std::vector<CMRMAttribute> NL3D::CMRMBuilder::TmpAttributes[NL3D_MRM_MAX_ATTRIB] [private]
 

Definition at line 92 of file mrm_builder.h.

Referenced by collapseEdge(), faceShareWedges(), followWedge(), init(), makeCoarserBS(), makeLODMesh(), and saveCoarserMesh().

std::vector<CMRMFaceBuild> NL3D::CMRMBuilder::TmpFaces [private]
 

Definition at line 96 of file mrm_builder.h.

Referenced by collapseEdge(), collapseEdges(), edgeContinue(), edgeNearUniqueMatFace(), getDeltaFaceNormals(), init(), saveCoarserMesh(), vertexClosed(), vertexHasOneMaterial(), and vertexHasOneWedge().

std::vector<CMRMVertex> NL3D::CMRMBuilder::TmpVertices [private]
 

Definition at line 90 of file mrm_builder.h.

Referenced by collapseEdge(), collapseEdges(), computeEdgeCost(), edgeContinue(), edgeNearUniqueMatFace(), followVertex(), getDeltaFaceNormals(), init(), makeCoarserBS(), makeLODMesh(), saveCoarserMesh(), vertexClosed(), vertexHasOneMaterial(), and vertexHasOneWedge().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 06:56:45 2004 for NeL by doxygen 1.3.6