// Copyright NVIDIA Corporation 2006 -- Ignacio Castano #include #include #include #include using namespace nv; // Weld trimesh vertices void nv::WeldVertices(TriMesh * mesh) { nvDebug("--- Welding vertices.\n"); nvCheck(mesh != NULL); uint count = mesh->vertexCount(); Array xrefs; Weld weld; uint newCount = weld(mesh->vertices(), xrefs); nvDebug("--- %d vertices welded\n", count - newCount); // Remap faces. const uint faceCount = mesh->faceCount(); for(uint f = 0; f < faceCount; f++) { TriMesh::Face & face = mesh->faceAt(f); face.v[0] = xrefs[face.v[0]]; face.v[1] = xrefs[face.v[1]]; face.v[2] = xrefs[face.v[2]]; } } // Weld trimesh vertices void nv::WeldVertices(QuadTriMesh * mesh) { nvDebug("--- Welding vertices.\n"); nvCheck(mesh != NULL); uint count = mesh->vertexCount(); Array xrefs; Weld weld; uint newCount = weld(mesh->vertices(), xrefs); nvDebug("--- %d vertices welded\n", count - newCount); // Remap faces. const uint faceCount = mesh->faceCount(); for(uint f = 0; f < faceCount; f++) { QuadTriMesh::Face & face = mesh->faceAt(f); face.v[0] = xrefs[face.v[0]]; face.v[1] = xrefs[face.v[1]]; face.v[2] = xrefs[face.v[2]]; if (face.isQuadFace()) { face.v[3] = xrefs[face.v[3]]; } } } // OLD code #if 0 namespace { struct VertexInfo { uint id; ///< Original vertex id. uint normal_face_group; uint tangent_face_group; uint material; uint chart; }; /// VertexInfo hash functor. struct VertexHash : public IHashFunctor { VertexHash(PiMeshPtr m) : mesh(m) { uint c = mesh->FindChannel(VS_POS); piCheck(c != PI_NULL_INDEX); channel = mesh->GetChannel(c); piCheck(channel != NULL); } uint32 operator () (const VertexInfo & v) const { return channel->data[v.id].GetHash(); } private: PiMeshPtr mesh; PiMesh::Channel * channel; }; /// VertexInfo comparator. struct VertexEqual : public IBinaryPredicate { VertexEqual(PiMeshPtr m) : mesh(m) {} bool operator () (const VertexInfo & a, const VertexInfo & b) const { bool equal = a.normal_face_group == b.normal_face_group && a.tangent_face_group == b.tangent_face_group && a.material == b.material && a.chart == b.chart; // Split vertex shared by different face types. if( !equal ) { return false; } // They were the same vertex. if( a.id == b.id ) { return true; } // Vertex equal if all the channels are equal. return mesh->IsVertexEqual(a.id, b.id); } private: PiMeshPtr mesh; }; } // namespace /// Weld the vertices. void PiMeshVertexWeld::WeldVertices(const PiMeshSmoothGroup * mesh_smooth_group, const PiMeshMaterial * mesh_material, const PiMeshAtlas * mesh_atlas ) { piDebug( "--- Welding vertices:\n" ); piDebug( "--- Expand mesh vertices.\n" ); PiArray vertex_array; const uint face_num = mesh->GetFaceNum(); const uint vertex_max = face_num * 3; vertex_array.Resize( vertex_max ); for(uint i = 0; i < vertex_max; i++) { uint f = i/3; const PiMesh::Face & face = mesh->GetFace(f); vertex_array[i].id = face.v[i%3]; // Reset face attributes. vertex_array[i].normal_face_group = PI_NULL_INDEX; vertex_array[i].tangent_face_group = PI_NULL_INDEX; vertex_array[i].material = PI_NULL_INDEX; vertex_array[i].chart = PI_NULL_INDEX; // Set available attributes. if( mesh_smooth_group != NULL ) { if( mesh_smooth_group->HasNormalFaceGroups() ) { vertex_array[i].normal_face_group = mesh_smooth_group->GetNormalFaceGroup( f ); } if( mesh_smooth_group->HasTangentFaceGroups() ) { vertex_array[i].tangent_face_group = mesh_smooth_group->GetTangentFaceGroup( f ); } } if( mesh_material != NULL ) { vertex_array[i].material = mesh_material->GetFaceMaterial( f ); } if( mesh_atlas != NULL && mesh_atlas->HasCharts() ) { vertex_array[i].chart = mesh_atlas->GetFaceChart( f ); } } piDebug( "--- %d vertices.\n", vertex_max ); piDebug( "--- Collapse vertices.\n" ); uint * xrefs = new uint[vertex_max]; VertexHash hash(mesh); VertexEqual equal(mesh); const uint vertex_num = Weld( vertex_array, xrefs, hash, equal ); piCheck(vertex_num <= vertex_max); piDebug( "--- %d vertices.\n", vertex_num ); // Remap face indices. piDebug( "--- Remapping face indices.\n" ); mesh->RemapFaceIndices(vertex_max, xrefs); // Overwrite xrefs to map new vertices to old vertices. for(uint v = 0; v < vertex_num; v++) { xrefs[v] = vertex_array[v].id; } // Update vertex order. mesh->ReorderVertices(vertex_num, xrefs); delete [] xrefs; } #endif // 0