Newton Dynamics  4.00
ndPolyhedra.h
1 /* Copyright (c) <2003-2022> <Julio Jerez, Newton Game Dynamics>
2 *
3 * This software is provided 'as-is', without any express or implied
4 * warranty. In no event will the authors be held liable for any damages
5 * arising from the use of this software.
6 *
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 *
11 * 1. The origin of this software must not be misrepresented; you must not
12 * claim that you wrote the original software. If you use this software
13 * in a product, an acknowledgment in the product documentation would be
14 * appreciated but is not required.
15 *
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 *
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 #ifndef __ND_POLYHEDRA_H__
23 #define __ND_POLYHEDRA_H__
24 
25 #include "ndCoreStdafx.h"
26 #include "ndTypes.h"
27 #include "ndList.h"
28 #include "ndTree.h"
29 #include "ndHeap.h"
30 #include "ndHeap.h"
31 #include "ndDebug.h"
32 #include "ndClassAlloc.h"
33 
34 class ndEdge;
35 class ndMatrix;
36 class ndBigPlane;
37 class ndBigVector;
38 class ndPolyhedra;
40 
41 typedef ndInt64 ndEdgeKey;
42 
43 class ndEdge
44 {
45  public:
46  ndEdge ();
47  ndEdge (ndInt32 vertex, ndInt32 face, ndUnsigned64 userdata = 0);
48  ~ndEdge ();
49 
50  ndInt32 m_incidentVertex;
51  ndInt32 m_incidentFace;
52  ndUnsigned64 m_userData;
53  ndEdge* m_next;
54  ndEdge* m_prev;
55  ndEdge* m_twin;
56  ndInt32 m_mark;
57 } D_GCC_NEWTON_ALIGN_32 ;
58 
59 class ndPolyhedra: public ndTree <ndEdge, ndEdgeKey>
60 {
61  public:
62  class ndPairKey
63  {
64  public:
65  ndPairKey()
66  {
67  }
68 
69  ndPairKey(ndInt64 key)
70  :m_key(ndUnsigned64(key))
71  {
72  }
73 
74  ndPairKey(ndInt32 keyHigh, ndInt32 keyLow)
75  :m_keyLow(ndUnsigned32 (keyLow))
76  ,m_keyHigh(ndUnsigned32 (keyHigh))
77  {
78  }
79 
80  ndInt64 GetVal() const
81  {
82  return ndInt64(m_key);
83  }
84 
85  ndInt32 GetLowKey() const
86  {
87  return ndInt32(m_keyLow);
88  }
89 
90  ndInt32 GetHighKey() const
91  {
92  return ndInt32(m_keyHigh);
93  }
94 
95  bool operator<(const ndPairKey& key) const
96  {
97  return m_key < key.m_key;
98  }
99 
100  bool operator>(const ndPairKey& key) const
101  {
102  return m_key > key.m_key;
103  }
104 
105 
106  private:
107  union
108  {
109  ndUnsigned64 m_key;
110  struct
111  {
112  ndUnsigned32 m_keyLow;
113  ndUnsigned32 m_keyHigh;
114  };
115  };
116  };
117 
118  ndPolyhedra ();
119  D_CORE_API ndPolyhedra (const ndPolyhedra &polyhedra);
120  D_CORE_API virtual ~ndPolyhedra();
121 
122  virtual bool ReportProgress(ndFloat32) const { return true;}
123 
124  virtual void BeginFace();
125  ndEdge* AddFace (ndInt32 v0, ndInt32 v1, ndInt32 v2);
126  ndEdge* AddFace (ndInt32 count, const ndInt32* const index);
127  D_CORE_API ndEdge* AddFace (ndInt32 count, const ndInt32* const index, const ndInt64* const userdata);
128  D_CORE_API virtual bool EndFace ();
129  D_CORE_API virtual void DeleteFace(ndEdge* const edge);
130 
131  D_CORE_API ndInt32 GetFaceCount() const;
132  ndInt32 GetEdgeCount() const;
133  ndInt32 GetLastVertexIndex() const;
134 
135  ndInt32 IncLRU() const;
136  ndInt32 GetLRU() const;
137  void SetLRU(ndInt32 lru) const;
138 
139  ndEdge* FindEdge (ndInt32 v0, ndInt32 v1) const;
140  ndNode* FindEdgeNode (ndInt32 v0, ndInt32 v1) const;
141 
142  D_CORE_API ndEdge* AddHalfEdge (ndInt32 v0, ndInt32 v1);
143  D_CORE_API void DeleteEdge (ndEdge* const edge);
144  void DeleteEdge (ndInt32 v0, ndInt32 v1);
145 
146  D_CORE_API ndEdge* ConnectVertex (ndEdge* const e0, ndEdge* const e1);
147 
148  D_CORE_API bool FlipEdge (ndEdge* const edge);
149  D_CORE_API ndEdge* SpliteEdge (ndInt32 newIndex, ndEdge* const edge);
150  D_CORE_API ndBigVector FaceNormal (const ndEdge* const face, const ndFloat64* const vertex, ndInt32 strideInBytes) const;
151 
152  D_CORE_API void SavePLY(const char* const fileName, const ndFloat64* const vertex, ndInt32 strideInBytes) const;
153 
154  void BeginConectedSurface() const;
155  D_CORE_API bool GetConectedSurface (ndPolyhedra &polyhedra) const;
156  void EndConectedSurface() const;
157 
158  D_CORE_API ndMatrix CalculateSphere(ndBigVector& size, const ndFloat64* const vertex, ndInt32 strideInBytes) const;
159 
160  D_CORE_API void ChangeEdgeIncidentVertex (ndEdge* const edge, ndInt32 newIndex);
161  D_CORE_API void DeleteDegenerateFaces (const ndFloat64* const pool, ndInt32 dstStrideInBytes, ndFloat64 minArea);
162 
163  D_CORE_API bool Optimize (const ndFloat64* const pool, ndInt32 strideInBytes, ndFloat64 tol, ndInt32 maxFaceCount = 1<<28);
164  D_CORE_API void Triangulate (const ndFloat64* const vertex, ndInt32 strideInBytes, ndPolyhedra* const leftOversOut);
165  D_CORE_API void ConvexPartition (const ndFloat64* const vertex, ndInt32 strideInBytes, ndPolyhedra* const leftOversOut);
166  D_CORE_API bool IsFaceConvex(ndEdge* const face, const ndFloat64* const pool, ndInt32 strideInBytes) const;
167 
168  protected:
169  D_CORE_API ndEdge* CollapseEdge(ndEdge* const edge);
170  D_CORE_API bool PolygonizeFace(ndEdge* const face, const ndFloat64* const pool, ndInt32 stride);
171  D_CORE_API bool TriangulateFace(ndEdge* const face, const ndFloat64* const pool, ndInt32 stride);
172 
173  private:
174  void RefineTriangulation (const ndFloat64* const vertex, ndInt32 stride);
175  void RefineTriangulation (const ndFloat64* const vertex, ndInt32 stride, const ndBigVector& normal, ndInt32 perimeterCount, ndEdge** const perimeter);
176  void OptimizeTriangulation (const ndFloat64* const vertex, ndInt32 strideInBytes);
177  void RemoveInteriorEdges (ndPolyhedra& polyhedraOut, const ndFloat64* const vertex, ndInt32 strideInBytes);
178  void MarkAdjacentCoplanarFaces (ndPolyhedra& polyhedraOut, ndEdge* const face, const ndFloat64* const pool, ndInt32 strideInBytes);
179  ndEdge* FindEarTip (ndEdge* const face, const ndFloat64* const pool, ndInt32 stride, ndDownHeap<ndEdge*, ndFloat64>& heap, const ndBigVector &normal) const;
180  ndEdge* TriangulateFace (ndEdge* const face, const ndFloat64* const pool, ndInt32 stride, ndDownHeap<ndEdge*, ndFloat64>& heap, ndBigVector* const faceNormalOut);
181 
182  void RemoveHalfEdge (ndEdge* const edge);
183  ndEdge* OptimizeCollapseEdge (ndEdge* const edge);
184  bool IsOkToCollapse (const ndBigVector* const pool, ndEdge* const edge) const;
185  ndFloat64 EdgePenalty (const ndBigVector* const pool, ndEdge* const edge, ndFloat64 dist) const;
186  ndBigPlane EdgePlane (ndInt32 i0, ndInt32 i1, ndInt32 i2, const ndBigVector* const pool) const;
187  void CalculateAllMetrics (ndVertexCollapseVertexMetric* const table, const ndBigVector* const pool) const;
188  void CalculateVertexMetrics (ndVertexCollapseVertexMetric* const table, const ndBigVector* const pool, ndEdge* const edge) const;
189  ndEdge* BestEdgePolygonizeFace(const ndBigVector& normal, ndEdge* const edge, const ndFloat64* const pool, ndInt32 stride, const ndBigVector& point) const;
190 
191  static ndInt32 GetInteriorDiagonals (ndPolyhedra& polyhedra, ndEdge** const diagonals, ndInt32 maxCount);
192  static ndBigPlane UnboundedLoopPlane (ndInt32 i0, ndInt32 i1, ndInt32 i2, const ndBigVector* const pool);
193  static void RemoveOuterColinearEdges(ndPolyhedra& flatFace, const ndFloat64* const vertex, ndInt32 stride);
194  static void RemoveInteriorColinearEdges(ndPolyhedra& flatFace, const ndFloat64* const vertex, ndInt32 stride);
195  static bool IsEssensialDiagonal (ndEdge* const diagonal, const ndBigVector& normal, const ndFloat64* const pool, ndInt32 stride);
196  static bool IsEssensialPointDiagonal (ndEdge* const diagonal, const ndBigVector& normal, const ndFloat64* const pool, ndInt32 stride);
197 
198  mutable ndInt32 m_baseMark;
199  mutable ndInt32 m_edgeMark;
200  mutable ndInt32 m_faceSecuence;
201  friend class dPolyhedraDescriptor;
202 };
203 
204 inline ndEdge::ndEdge ()
205 {
206 }
207 
208 inline ndEdge::ndEdge (ndInt32 vertex, ndInt32 face, ndUnsigned64 userdata)
209  :m_incidentVertex(vertex)
210  ,m_incidentFace(face)
211  ,m_userData(userdata)
212  ,m_next(nullptr)
213  ,m_prev(nullptr)
214  ,m_twin(nullptr)
215  ,m_mark(0)
216 {
217 }
218 
219 inline ndEdge::~ndEdge ()
220 {
221 }
222 
223 inline void ndPolyhedra::BeginFace ()
224 {
225 }
226 
227 inline ndEdge* ndPolyhedra::AddFace (ndInt32 count, const ndInt32* const index)
228 {
229  return AddFace (count, index, nullptr);
230 }
231 
232 inline ndEdge* ndPolyhedra::AddFace (ndInt32 v0, ndInt32 v1, ndInt32 v2)
233 {
234  ndInt32 vertex[3];
235 
236  vertex [0] = v0;
237  vertex [1] = v1;
238  vertex [2] = v2;
239  return AddFace (3, vertex, nullptr);
240 }
241 
242 inline ndInt32 ndPolyhedra::GetEdgeCount() const
243 {
244 #ifdef _DEBUG
245  ndInt32 edgeCount = 0;
246  Iterator iter(*this);
247  for (iter.Begin(); iter; iter ++)
248  {
249  edgeCount ++;
250  }
251  ndAssert (edgeCount == GetCount());;
252 #endif
253  return GetCount();
254 }
255 
256 inline ndPolyhedra::ndPolyhedra()
257  :ndTree <ndEdge, ndInt64>()
258  ,m_baseMark(0)
259  ,m_edgeMark(0)
260  ,m_faceSecuence(0)
261 {
262 }
263 
264 inline ndInt32 ndPolyhedra::GetLastVertexIndex() const
265 {
266  ndInt32 maxVertexIndex = -1;
267  Iterator iter(*this);
268  for (iter.Begin(); iter; iter ++)
269  {
270  const ndEdge* const edge = &(*iter);
271  if (edge->m_incidentVertex > maxVertexIndex)
272  {
273  maxVertexIndex = edge->m_incidentVertex;
274  }
275  }
276  return maxVertexIndex + 1;
277 }
278 
279 inline ndInt32 ndPolyhedra::IncLRU() const
280 {
281  m_edgeMark ++;
282  ndAssert (m_edgeMark < 0x7fffffff);
283  return m_edgeMark;
284 }
285 
286 inline ndInt32 ndPolyhedra::GetLRU() const
287 {
288  return m_edgeMark;
289 }
290 
291 inline void ndPolyhedra::SetLRU(ndInt32 lru) const
292 {
293  if (lru > m_edgeMark)
294  {
295  m_edgeMark = lru;
296  }
297 }
298 
299 inline void ndPolyhedra::BeginConectedSurface() const
300 {
301  m_baseMark = IncLRU();
302 }
303 
304 inline void ndPolyhedra::EndConectedSurface() const
305 {
306 }
307 
308 inline ndPolyhedra::ndNode* ndPolyhedra::FindEdgeNode (ndInt32 i0, ndInt32 i1) const
309 {
310  ndPairKey key (i0, i1);
311  return Find (key.GetVal());
312 }
313 
314 inline ndEdge *ndPolyhedra::FindEdge (ndInt32 i0, ndInt32 i1) const
315 {
316  ndNode* const node = FindEdgeNode (i0, i1);
317  return node ? &node->GetInfo() : nullptr;
318 }
319 
320 inline void ndPolyhedra::DeleteEdge (ndInt32 v0, ndInt32 v1)
321 {
322  ndPairKey pairKey (v0, v1);
323  ndNode* const node = Find(pairKey.GetVal());
324  ndEdge* const edge = node ? &node->GetInfo() : nullptr;
325  if (!edge)
326  {
327  return;
328  }
329  DeleteEdge (edge);
330 }
331 
332 #endif
333 
ndEdge
Definition: ndPolyhedra.h:44
ndTree
Definition: ndTree.h:82
ndDownHeap
Definition: ndHeap.h:346
ndMatrix
Definition: ndMatrix.h:42
ndBigPlane
Definition: ndPlane.h:50
ndPolyhedra
Definition: ndPolyhedra.h:60
ndVertexCollapseVertexMetric
Definition: ndPolyhedra.cpp:93
ndBigVector
Definition: ndVectorArmNeon.h:463
ndPolyhedra::ndPairKey
Definition: ndPolyhedra.h:63