From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/a02951.html | 5176 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 5176 insertions(+) create mode 100644 docs/doxygen/nel/a02951.html (limited to 'docs/doxygen/nel/a02951.html') diff --git a/docs/doxygen/nel/a02951.html b/docs/doxygen/nel/a02951.html new file mode 100644 index 00000000..6aee51ac --- /dev/null +++ b/docs/doxygen/nel/a02951.html @@ -0,0 +1,5176 @@ + + +NeL: NL3D::CMRMBuilder class Reference + + + +
+

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
+ + -- cgit v1.2.1