36 template <
typename VertexType>
38 :m_pInputMesh(pInputMesh)
39 ,m_pOutputMesh(pOutputMesh)
40 ,m_fMinDotProductForCollapse(fEdgeCollapseThreshold)
42 *m_pOutputMesh = *m_pInputMesh;
45 template <
typename VertexType>
49 if((m_pOutputMesh->m_vecVertices.empty()) || (m_pOutputMesh->m_vecTriangleIndices.empty()))
54 buildConnectivityData();
55 fillInitialVertexMetadata(m_vecInitialVertexMetadata);
57 uint32_t noOfEdgesCollapsed;
60 noOfEdgesCollapsed = performDecimationPass(m_fMinDotProductForCollapse);
61 m_pOutputMesh->removeDegenerateTris();
62 if(noOfEdgesCollapsed > 0)
66 buildConnectivityData();
68 }
while(noOfEdgesCollapsed > 0);
70 m_pOutputMesh->removeUnusedVertices();
73 m_pOutputMesh->m_vecLodRecords.clear();
76 lodRecord.
endIndex = m_pOutputMesh->getNoOfIndices();
77 m_pOutputMesh->m_vecLodRecords.push_back(lodRecord);
80 template <
typename VertexType>
84 m_vecTriangles.clear();
85 m_vecTriangles.resize(m_pOutputMesh->m_vecTriangleIndices.size() / 3);
86 for(uint32_t triCt = 0; triCt < m_vecTriangles.size(); triCt++)
88 m_vecTriangles[triCt].v0 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 0];
89 m_vecTriangles[triCt].v1 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 1];
90 m_vecTriangles[triCt].v2 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 2];
92 Vector3DFloat v0Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v0].position;
93 Vector3DFloat v1Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v1].position;
94 Vector3DFloat v2Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v2].position;
101 m_vecTriangles[triCt].normal = normal;
105 trianglesUsingVertex.clear();
106 trianglesUsingVertex.resize(m_pOutputMesh->m_vecVertices.size());
107 for(uint32_t ct = 0; ct < trianglesUsingVertex.size(); ct++)
109 trianglesUsingVertex[ct].reserve(6);
111 for(uint32_t ct = 0; ct < m_vecTriangles.size(); ct++)
113 trianglesUsingVertex[m_vecTriangles[ct].v0].push_back(ct);
114 trianglesUsingVertex[m_vecTriangles[ct].v1].push_back(ct);
115 trianglesUsingVertex[m_vecTriangles[ct].v2].push_back(ct);
119 template <
typename VertexType>
120 uint32_t MeshDecimator<VertexType>::performDecimationPass(
float )
123 uint32_t noOfEdgesCollapsed = 0;
126 vertexMapper.clear();
127 vertexMapper.resize(m_pOutputMesh->m_vecVertices.size());
133 vertexLocked.clear();
134 vertexLocked.resize(m_pOutputMesh->m_vecVertices.size());
137 for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++)
140 vertexMapper[ct] = ct;
142 vertexLocked[ct] =
false;
146 for(uint32_t ctIter = 0; ctIter < m_vecTriangles.size(); ctIter++)
148 if(attemptEdgeCollapse(m_vecTriangles[ctIter].v0, m_vecTriangles[ctIter].v1))
150 ++noOfEdgesCollapsed;
153 if(attemptEdgeCollapse(m_vecTriangles[ctIter].v1, m_vecTriangles[ctIter].v2))
155 ++noOfEdgesCollapsed;
158 if(attemptEdgeCollapse(m_vecTriangles[ctIter].v2, m_vecTriangles[ctIter].v0))
160 ++noOfEdgesCollapsed;
164 if(noOfEdgesCollapsed > 0)
167 for(uint32_t triCt = 0; triCt < m_pOutputMesh->m_vecTriangleIndices.size(); triCt++)
169 uint32_t before = m_pOutputMesh->m_vecTriangleIndices[triCt];
170 uint32_t after = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]];
173 m_pOutputMesh->m_vecTriangleIndices[triCt] = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]];
178 return noOfEdgesCollapsed;
181 template <
typename VertexType>
182 bool MeshDecimator<VertexType>::attemptEdgeCollapse(uint32_t uSrc, uint32_t uDst)
185 if(vertexLocked[uSrc] || vertexLocked[uDst])
190 if(canCollapseEdge(uSrc, uDst))
193 vertexMapper[uSrc] = uDst;
194 vertexLocked[uSrc] =
true;
195 vertexLocked[uDst] =
true;
204 template <
typename VertexType>
205 bool MeshDecimator<VertexType>::canCollapseEdge(uint32_t uSrc, uint32_t uDst)
207 bool bCanCollapse =
true;
209 if(m_vecInitialVertexMetadata[uSrc].isOnMaterialEdge)
211 bCanCollapse &= canCollapseMaterialEdge(uSrc, uDst);
214 if(m_vecInitialVertexMetadata[uSrc].isOnRegionFace.any())
216 bCanCollapse &= canCollapseRegionEdge(uSrc, uDst);
221 bCanCollapse &= canCollapseNormalEdge(uSrc, uDst);
227 template <
typename VertexType>
228 bool MeshDecimator<VertexType>::canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst)
233 if(isSubset(m_vecInitialVertexMetadata[uSrc].isOnRegionFace, m_vecInitialVertexMetadata[uDst].isOnRegionFace) ==
false)
242 if(m_vecInitialVertexMetadata[uSrc].normal.
dot(m_vecInitialVertexMetadata[uDst].normal) < 0.999f)
250 template <
typename VertexType>
251 bool MeshDecimator<VertexType>::canCollapseMaterialEdge(uint32_t , uint32_t )
258 template <
typename VertexType>
259 bool MeshDecimator<VertexType>::collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst,
float fThreshold)
261 bool faceFlipped =
false;
262 std::vector<uint32_t>& triangles = trianglesUsingVertex[uSrc];
264 for(std::vector<uint32_t>::iterator triIter = triangles.begin(); triIter != triangles.end(); triIter++)
266 uint32_t tri = *triIter;
268 const uint32_t& v0Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3];
269 const uint32_t& v1Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 1];
270 const uint32_t& v2Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 2];
273 if((v0Old == v1Old) || (v1Old == v2Old) || (v2Old == v0Old))
278 uint32_t v0New = v0Old;
279 uint32_t v1New = v1Old;
280 uint32_t v2New = v2Old;
290 if((v0New == v1New) || (v1New == v2New) || (v2New == v0New))
295 const Vector3DFloat& v0OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition();
296 const Vector3DFloat& v1OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1Old]].getPosition();
297 const Vector3DFloat& v2OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition();
299 const Vector3DFloat& v0NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0New]].getPosition();
300 const Vector3DFloat& v1NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1New]].getPosition();
301 const Vector3DFloat& v2NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2New]].getPosition();
303 Vector3DFloat OldNormal = (v1OldPos - v0OldPos).cross(v2OldPos - v1OldPos);
304 Vector3DFloat NewNormal = (v1NewPos - v0NewPos).cross(v2NewPos - v1NewPos);
307 NewNormal.normalise();
309 float dotProduct = OldNormal.dot(NewNormal);
311 if(dotProduct < fThreshold)
328 template <
typename VertexType>
329 bool MeshDecimator<VertexType>::isSubset(std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> a, std::bitset<RFF_NO_OF_REGION_FACE_FLAGS> b)
333 for(
int ct = 0; ct < RFF_NO_OF_REGION_FACE_FLAGS; ct++)
337 if(b.test(ct) ==
false)