hkMeshSimplifier.h
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:11k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* 
  2.  * Confidential Information of Telekinesys Research Limited (t/a Havok). Not for disclosure or distribution without Havok's
  3.  * prior written consent. This software contains code, techniques and know-how which is confidential and proprietary to Havok.
  4.  * Level 2 and Level 3 source code contains trade secrets of Havok. Havok Software (C) Copyright 1999-2009 Telekinesys Research Limited t/a Havok. All Rights Reserved. Use of this software is subject to the terms of an end user license agreement.
  5.  * 
  6.  */
  7. #include <Common/Base/Container/Array/hkObjectArray.h>
  8. #include <Common/Base/Types/Geometry/Aabb/hkAabb.h>
  9. #ifndef HK_MESH_SIMPLIFIER_H
  10. #define HK_MESH_SIMPLIFIER_H
  11. /// A utility for simplifying meshes
  12. /// After the hkQemMeshSimplifier is initialized with an hkQemMutableMesh, edges from the mesh are collapsed,
  13. /// and then edges and faces are patched up.
  14. /// The edges to be collapsed are selected based on a heuristic that attempts to minimize the error introduced to the mesh.
  15. /// Thus, small details like thin triangles or coincident vertices are removed first.
  16. /// This can be a useful tool for generating reduced-complexity physics representations from render meshes
  17. /// NOTES
  18. /// 1) The algorithm used may end up removing edges that a human might think it shouldn't.
  19. /// You should inspect the output meshes to make sure that no large errors are introduced.
  20. /// 2) The algorithm is CPU and memory intensive. A large mesh may take several seconds to process.
  21. /// Thus it should NOT be used at runtime.
  22. /// 3) Materials in the mesh are tracked during simplification, but no attempt is made to avoid merging traingles with
  23. /// different materials. Support for this will be improved in the future.
  24. /// See MeshSimplificationDemo.cpp for more examples on the usage.
  25. struct hkQemPairContraction;
  26. struct hkQemVertexPair;
  27. /// A mesh representation that allows vertices to be remapped to each other
  28. class hkQemMutableMesh
  29. {
  30. public:
  31. typedef int FaceIndex;
  32. typedef int VertexIndex;
  33. typedef hkArray<VertexIndex> VertexList;
  34. typedef hkArray<FaceIndex> FaceList;
  35. friend class hkQemMeshSimplifier;
  36. struct Face
  37. {
  38. VertexIndex m_vertexIndices[3];
  39. /// Material ID that is preserved during merges. Defaults to hkUlong(-1)
  40. hkUlong m_materialId; 
  41. hkBool m_isValid;
  42. Face( VertexIndex i, VertexIndex j, VertexIndex k);
  43. // Replaces instances of "from" with "to" and return the # of changed values
  44. int remapVertices(VertexIndex from, VertexIndex to);
  45. };
  46. /// Append the array of vertices to the mesh's vertices. May be called multiple times.
  47. void addVertices( const hkArray<hkVector4>& verts );
  48. /// Add a triangle with the specificed vertex indices. The material for the face defaults to hkUlong(-1)
  49. void addTriangle( VertexIndex i, VertexIndex j, VertexIndex k);
  50. /// Add a triangle with the specificed vertex indices and material index
  51. void addTriangleWithMaterial( VertexIndex i, VertexIndex j, VertexIndex k, hkUlong mat);
  52. void validate() const;
  53. /// Approximates the vertex normal based on the surrounding faces.
  54. void calcVertexNormal( VertexIndex vIdx, hkVector4& normalOut) const;
  55. /// Computes all the vertex normals using calcVertexNormal
  56. void getVertexNormals(hkArray<hkVector4>& normals) const;
  57. /// Accessor methods
  58. const hkArray<hkVector4>& getVertices() const { return m_vertices; }
  59. const hkArray<Face>& getFaces() const { return m_faces; }
  60. protected:
  61. void collectEdgeNeighbors(VertexIndex i, VertexIndex j, FaceList& neighbors) const;
  62. void collectDistanceNeighbors(hkArray<hkQemVertexPair>& neighbors, hkReal tolerance);
  63. void collectDistanceNeighbors1AxisSweep(hkArray<hkQemVertexPair>& neighbors, hkReal tolerance);
  64. void collectNormalAndBoundaryEdges(hkArray<hkQemVertexPair>& normal, hkArray<hkQemVertexPair>& boundary) const;
  65. void pruneDuplicateEdges(hkArray<hkQemVertexPair>& pairs);
  66. FaceList& getNeighbors(VertexIndex i) { return m_neighorhoods[i]; }
  67. const FaceList& getNeighbors(VertexIndex i) const { return m_neighorhoods[i]; }
  68. void computeContraction(VertexIndex v1, VertexIndex v2, hkQemPairContraction& conx, hkVector4Parameter vNew) const;
  69. int applyContraction(const hkQemPairContraction& conx);
  70. int unlinkFace(FaceIndex fid);
  71. // Removes vertices that don't belong to any neighborhoods
  72. void compact();
  73. void calcPlaneNormalForFace( FaceIndex fix, hkVector4& planeOut ) const;
  74. protected:
  75. void getNeighborhoodUnion(VertexIndex i, VertexIndex j, FaceList& un) const;
  76. void getNeighborhoodIntersection(VertexIndex i, VertexIndex j, FaceList& intersect) const;
  77. // Returns the "pivot" point - everything from 0..pivot is in neighborhood of vertex i
  78. int getNeighborhoodSymDifference(VertexIndex i, VertexIndex j, FaceList& symdiff) const;
  79. static hkBool isSorted(const FaceList& list);
  80. // Each neighborhood is sorted to make set operations faster
  81. hkObjectArray< hkArray<FaceIndex> > m_neighorhoods;
  82. hkArray<hkVector4> m_vertices;
  83. hkArray<Face> m_faces;
  84. };
  85. struct hkQemPairContraction
  86. {
  87. typedef int FaceIndex;
  88. typedef int VertexIndex;
  89. typedef hkArray<VertexIndex> VertexList;
  90. typedef hkArray<FaceIndex> FaceList;
  91. VertexIndex m_v1;
  92. VertexIndex m_v2;
  93. hkVector4 m_delta1;
  94. hkVector4 m_delta2;
  95. FaceList m_deadFaces;
  96. // This is how the thesis implements it. Easier with 2 arrays?
  97. FaceList m_deltaFaces;
  98. int m_deltaFacesPivot;
  99. };
  100. // Candidates for merging. Not strictly edges in the mesh, can be "close" vertices too
  101. struct hkQemVertexPair
  102. {
  103. enum PairType
  104. {
  105. BOUNDARY_PAIR, // Special case of an edge pair; an edge only associated with one face
  106. EDGE_PAIR, // Edge that existed in the original mesh
  107. PROXIMITY_PAIR, // Artificial edge based on vertex proximity
  108. };
  109. hkQemMutableMesh::VertexIndex m_v1;
  110. hkQemMutableMesh::VertexIndex m_v2;
  111. hkQemMutableMesh::FaceIndex m_faceIndex; // Only used for constraining boundaries
  112. hkReal m_errorCost; // Used for heap
  113. int m_heapIndex; // index into heap array
  114. hkEnum<PairType, hkUint8> m_pairType;
  115. hkVector4 m_target;
  116. // Assumes that v1 < v2
  117. // This is true initially, but may be violated as vertices are remapped
  118. static hkBool PairIndexLess(const hkQemVertexPair& pairA, const hkQemVertexPair& pairB)
  119. {
  120. const hkBool v1LessThan = (pairA.m_v1 < pairB.m_v1);
  121. const hkBool v1Equals = (pairA.m_v1 == pairB.m_v1);
  122. const hkBool v2LessThan = (pairA.m_v2 < pairB.m_v2);
  123. const hkBool v2Equals = (pairA.m_v2 == pairB.m_v2);
  124. const hkBool typeLessThan = (pairA.m_pairType) < (pairB.m_pairType);
  125. return v1LessThan || ( v1Equals && v2LessThan ) || (v2Equals && typeLessThan);
  126. }
  127. static hkBool ErrorLess(const hkQemVertexPair& pairA, const hkQemVertexPair& pairB)
  128. {
  129. return pairA.m_errorCost < pairB.m_errorCost;
  130. }
  131. hkBool operator==(const hkQemVertexPair& other)
  132. {
  133. return ((m_v1 == other.m_v1) && (m_v2 == other.m_v2))
  134. || ((m_v1 == other.m_v2) && (m_v2 == other.m_v1));
  135. }
  136. void remap(hkQemMutableMesh::VertexIndex to, hkQemMutableMesh::VertexIndex from)
  137. {
  138. HK_ASSERT(0x268f06a3, m_v1 == from || m_v2 == from);
  139. if (m_v1 == from) { m_v1 = to;}
  140. if (m_v2 == from) { m_v2 = to;}
  141. }
  142. void invalidate()
  143. {
  144. m_v1 = -1;
  145. m_v2 = -1;
  146. }
  147. };
  148. struct hkQemQuadric
  149. {
  150. public:
  151. hkMatrix4 m_matrix;
  152. void initFromPlaneEquation( hkVector4Parameter plane );
  153. void combineQuadrics( const hkQemQuadric& other, hkQemVertexPair::PairType );
  154. hkSimdReal calcErrorForVector(hkVector4Parameter v) const;
  155. };
  156. class hkQemMeshSimplifier
  157. {
  158. public:
  159. enum SimplificationStatus
  160. {
  161. STATUS_INVALID,
  162. /// vertices and triangles being passed in
  163. STATUS_SETUP,
  164. /// simplification started
  165. STATUS_PROCESSING,
  166. // simplification ended, vertices and triangles are read-only
  167. STATUS_DONE
  168. };
  169. hkQemMeshSimplifier();
  170. ~hkQemMeshSimplifier();
  171. typedef int FaceIndex;
  172. typedef int VertexIndex;
  173. typedef hkArray<VertexIndex> VertexList;
  174. typedef hkArray<FaceIndex> FaceList;
  175. /// Set up the simplifier.
  176. /// This maps the mesh to a fixed-size AABB
  177. void initialize( hkQemMutableMesh* mesh );
  178. /// Remove one edge from the mesh.
  179. void doSingleContraction();
  180. /// Removes redundant vertices from the mesh, and remaps the vertices to their original space
  181. void finalize();
  182. // Driver routines - removes the specified fraction of vertices or edges from the mesh
  183. void removeFractionOfVertices(hkReal fract);
  184. void removeFractionOfFaces(hkReal fract);
  185. struct Parameters
  186. {
  187. /// Vertices closer than distance will be considered as candidates for merging. Set negative to disable.
  188. hkReal m_vertexMergeDistance;
  189. /// Weighting applied to boundary edges, making them less likely to be contracted
  190. hkReal m_boundaryPenalty;
  191. /// Epsilon value for matrix inversion
  192. hkReal m_inversionEpsilon;
  193. /// New vertices are constrained to be within this distance of the segment containing the original vertices
  194. hkReal m_newVertexMaxDistance;
  195. /// All vertices are remapped to a cube with extents this size
  196. hkReal m_remapExtentSize;
  197. Parameters()
  198. : m_vertexMergeDistance(.1f),
  199. m_boundaryPenalty(10000.0f),
  200. m_inversionEpsilon(1e-3f),
  201. m_newVertexMaxDistance(.1f),
  202. m_remapExtentSize(500.0f)
  203. {
  204. }
  205. };
  206. Parameters m_params;
  207. protected:
  208. void constrainBoundaries( hkArray<hkQemVertexPair>& edges, hkReal penalty);
  209. void processEdges( hkArray<hkQemVertexPair>& edges );
  210. void computeEdgeInfo( hkQemVertexPair& pair );
  211. // Removes the pair with lowest cost from the heap, and copies it to pairOut
  212. void popBestPair(hkQemVertexPair& pairOut);
  213. void applyContraction(const hkQemPairContraction& contraction, hkQemVertexPair::PairType pairType);
  214. void remapVerticesInPairs(VertexIndex v1, VertexIndex v2, hkArray<int>& remappedPairs);
  215. void collectQuadrics();
  216. void verifyEdges();
  217. void removeEdgeAt(int removeIndex);
  218. // Map and unmap vertices to a cube specified by Parameters::m_remapExtentSize
  219. void mapVertices();
  220. void unmapVertices();
  221. struct HeapEntry
  222. {
  223. int m_index; // index into pair array
  224. hkReal m_cost;
  225. };
  226. hkArray<HeapEntry> m_heap;
  227. void heapSwapEntries(int i, int j);
  228. int heapGetParent(int i) {return (i-1) / 2;}
  229. int heapGetLeftChild(int i) {return (2*i + 1);}
  230. int heapGetRightChild(int i) {return (2*i + 2);}
  231. int heapGetSmallerChild(int i);
  232. void heapDeleteEntry(int i);
  233. void upHeap(int i);
  234. void downHeap(int i);
  235. void verifyHeap();
  236. public:
  237. hkQemMutableMesh* m_mesh;
  238. // These decrease as we contract vertex pairs
  239. int m_numFaces;
  240. int m_numVertices;
  241. protected:
  242. hkArray<hkQemQuadric> m_quadrics;
  243. hkObjectArray< hkArray<int> > m_edgeMapping;
  244. hkEnum<SimplificationStatus, hkUint8> m_status;
  245. hkAabb m_originalAabb;
  246. hkArray<hkQemVertexPair> m_pairs;
  247. };
  248. #endif // HK_MESH_SIMPLIFIER_H
  249. /*
  250. * Havok SDK - NO SOURCE PC DOWNLOAD, BUILD(#20090216)
  251. * Confidential Information of Havok.  (C) Copyright 1999-2009
  252. * Telekinesys Research Limited t/a Havok. All Rights Reserved. The Havok
  253. * Logo, and the Havok buzzsaw logo are trademarks of Havok.  Title, ownership
  254. * rights, and intellectual property rights in the Havok software remain in
  255. * Havok and/or its suppliers.
  256. * Use of this software for evaluation purposes is subject to and indicates
  257. * acceptance of the End User licence Agreement for this product. A copy of
  258. * the license is included with this software and is also available at www.havok.com/tryhavok.
  259. */