#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(). |