#include <mrm_builder.h>
Nevrax France
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 ¶ms, CMeshMRMSkinnedGeom::CMeshBuildMRM &mrmMesh, uint numMaxMaterial) |
| void | compileMRM (const CMesh::CMeshBuild &mbuild, std::vector< CMesh::CMeshBuild * > &bsList, const CMRMParameters ¶ms, 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< CMRMAttribute > | TmpAttributes [NL3D_MRM_MAX_ATTRIB] |
| std::vector< CMRMFaceBuild > | TmpFaces |
| std::vector< CMRMVertex > | TmpVertices |
|
|
Definition at line 228 of file mrm_builder.h. |
|
|
Definition at line 179 of file mrm_builder.h. |
|
|
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 }
|
|
|
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 }
|
|
|
Definition at line 1727 of file mrm_builder.cpp. References NLMISC::CVectorH::x, NLMISC::CVectorH::y, and NLMISC::CVectorH::z. Referenced by buildMeshBuildMrm().
|
|
||||||||||||||||||||
|
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).
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
from a final MRM Mesh representation, compute a CMeshBuildMRM. This is the last stage of the algo.
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 }
|
|
||||||||||||||||||||||||
|
from a final MRM Mesh representation, compute a CMeshBuildMRM. This is the last stage of the algo.
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 }
|
|
||||||||||||
|
from a meshBuild, compute a CMRMMesh. This is the first stage of the algo.
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 }
|
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
Compile a MRM skinned mesh info.
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 }
|
|
||||||||||||||||||||||||
|
Compile a MRM mesh info.
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 }
|
|
||||||||||||
|
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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().
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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().
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
Definition at line 90 of file mrm_builder.cpp. References NL3D::CMRMVertex::SharedFaces, sint, TmpFaces, and TmpVertices. Referenced by vertexContinue().
|
|
|
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 }
|
|
|
Definition at line 229 of file mrm_builder.h. Referenced by buildMrmBaseMesh(), and findInsertAttributeInBaseMesh(). |
|
|
Definition at line 154 of file mrm_builder.h. Referenced by buildAllLods(), collapseEdge(), and computeEdgeCost(). |
|
|
Definition at line 180 of file mrm_builder.h. Referenced by buildFinalMRM(). |
|
|
Definition at line 150 of file mrm_builder.h. Referenced by buildMrmBaseMesh(), CMRMBuilder(), collapseEdge(), compileMRM(), computeEdgeCost(), init(), and saveCoarserMesh(). |
|
|
Definition at line 152 of file mrm_builder.h. Referenced by buildMRMSewingMeshes(), collapseEdge(), and computeEdgeCost(). |
|
|
Definition at line 101 of file mrm_builder.h. |
|
|
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(). |
|
|
Definition at line 98 of file mrm_builder.h. Referenced by collapseEdge(), collapseEdges(), init(), insertFaceIntoEdgeList(), and removeFaceFromEdgeList(). |
|
|
Definition at line 94 of file mrm_builder.h. Referenced by buildFinalMRM(), CMRMBuilder(), collapseEdge(), edgeContinue(), init(), makeCoarserBS(), makeLODMesh(), saveCoarserMesh(), and vertexHasOneWedge(). |
|
|
Definition at line 92 of file mrm_builder.h. Referenced by collapseEdge(), faceShareWedges(), followWedge(), init(), makeCoarserBS(), makeLODMesh(), and saveCoarserMesh(). |
|
|
Definition at line 96 of file mrm_builder.h. Referenced by collapseEdge(), collapseEdges(), edgeContinue(), edgeNearUniqueMatFace(), getDeltaFaceNormals(), init(), saveCoarserMesh(), vertexClosed(), vertexHasOneMaterial(), and vertexHasOneWedge(). |
|
|
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(). |
1.3.6