Polygon Crucher SDK - Documentation
Documentation
Loading...
Searching...
No Matches
CustomHeap.h
1// CostHeap class interface
2//
3// CContractionPtr: must have zero-parameter constructor and operator=;
4// must have operator<
5// CONSTRUCTION: with (a) CContractionPtr representing negative infinity
6// Copy construction of CostHeap objects is DISALLOWED
7// Deep copy is supported
8//
9// ******************PUBLIC OPERATIONS******************
10// void Insert( CContractionPtr X ) --> Insert X
11// CContractionPtr FindMin( ) --> Return smallest item
12// void DeleteMin( ) --> Remove smallest item
13// void DeleteMin( CContractionPtr & X ) --> Same, but put it in X
14// int IsEmpty( ) --> Return 1 if empty; else return 0
15// int IsFull( ) --> Return 1 if full; else return 0
16// void MakeEmpty( ) --> Remove all items
17// void Toss( CContractionPtr X ) --> Insert X (lazily)
18// void FixHeap( ) --> Reestablish heap order property
19// ******************ERRORS*****************************
20// Predefined exception is propogated if new fails
21// EXCEPTION is called for FindMin or DeleteMin when empty
22
23#ifndef __COSTHEAP_H
24#define __COSTHEAP_H
25
26#ifndef PLY_CONFIG
27#error PolygonCruncherConfig.h is not included
28#endif
29
30#include "3DFaceList.h"
31#include "3DPointList.h"
32
33BEGIN_MOOTOOLS_NAMESPACE
34
35typedef enum {
36 UNDEFINED_OPTIMAL = 0,
37 INVERSEMATRIX_OPTIMAL = 1, // This means matrix contraction is optimal
38 LINE_OPTIMAL, // This means line contraction is optimal
39 POINT1_OPTIMAL, // This means that Point1() is optimal
40 POINT2_OPTIMAL, // This means that Point2() is optimal
41 // last value is 4. It cannot be greater than 7
42} CONTRACTION_TYPE;
43
44// the type is ordered by order of priority
45typedef enum
46{
47 MINIMUM_CONTRACTION_PRIORITY = 0, // Always the first pair of the heap
48 DEFAULT_CONTRACTION_PRIORITY, // Should be removed at least
49 FLAT_TRIANGLE_CONTRACTION_PRIORITY, // Pair contraction generate a triangle which is nearly flat
50 FLIP_FACE_CONTRACTION_PRIORITY, // Make a face being flipped => very bad
51 // Very important: Last is 3 which is the maximal possible value
52 // (Look MAKE_CONTRACTION_INFO)
53} CONTRACTION_PRIORITY;
54
55typedef enum
56{
57 X = 0,
58 Y,
59 Z
60} PAIR_XYZ;
61
62// Order is a simple way found to scramble the same cost pairs
63// this avoid to make optimize around the same group of faces if they have the same cost
64// and gives better optimization results.
65// Optimization process optimizes same costs pairs regularly on the whole object
66
67// it is coded the following way: 111 111 11
68// order position priority
69#define SET_CONTRACTION_INFO(type, priority) ((unsigned char)((type << 2) + priority))
70#define SET_CONTRACTION_PRIORITY(info, priority) ((unsigned char)((info & 0xFC) | (priority & 0x03)))
71#define SET_CONTRACTION_ORDER(info, order) ((unsigned char)((info & 0x1F)|(unsigned char)((order) << 5)))
72
73#define GET_CONTRACTION_PRIORITY(info) ((unsigned char)(info & 0x03))
74#define GET_CONTRACTION_TYPE(info) ((unsigned char)((info >> 2) & 0x07))
75#define GET_CONTRACTION_ORDER(info) ((unsigned char)(info >> 5))
76
77class CContractionCost;
78class CInitialCost : public C3DEdge
79{
80 friend CContractionCost;
81
82protected:
83 real cost;
84
85 union
86 {
87 real pos[3]; // The position of the new point (GetPosition() == INVERSEMATRIX_OPTIMAL)
88 double linecoef; // The colinear factor (GetPosition() < INVERSEMATRIX_OPTIMAL), use double as sizeof(double)<real pos[3]
89 };
90
91 unsigned char info;
92
93public:
94#ifdef MOOTOOLS_PRIVATE_DEBUG
95 real exactpos[3];
96#endif
97
98#ifdef MOOTOOLS_PRIVATE_DEBUG
99 CInitialCost();
100#endif
101
102 real GetCost() const;
103 void SetCost(double newcost);
104
105 void InitContraction(CONTRACTION_TYPE type, CONTRACTION_PRIORITY priority);
106
107 CONTRACTION_TYPE GetType() const;
108 void SetPriority(CONTRACTION_PRIORITY priority);
109 CONTRACTION_PRIORITY GetPriority() const;
110 void SetOrder(unsigned char value);
111 unsigned char GetOrder() const;
112 double GetLineCoef() const;
113
114 // Linecoef is the moving coef along edge(point1, point2).
115 // Linecoef = 0.0f the new pos == point2
116 // Linecoef = 1.0f the new pos == point1
117 void SetLineCoef(double value);
118 void SetPos(const C3DPoint& pt);
119
120#ifdef MOOTOOLS_PRIVATE_DEBUG
121 // 10 01 2012 : GetRemainingIndex code change. Check everything OK. Could be removed
124#endif
125
126 // If linecoef = 0.0 (POINT2_OPTIMAL) or linecoef = 1.0f (POINT1_OPTIMAL) the point does not moves.
127 // In this case the remaining index is the point which does not moves.
128 // this allows to minimize the CTrackInfo size because we only have to update UV and normals of the faces which own the replaced index.
129 //
130 // If linecoef > 0.0 && linecoef < 1.0, the remaining index must be point1 and the replaced index must be point2
131 int GetRemainingIndex();
132 int GetReplacedIndex();
133
134 void GetPos(C3DPoint *newpos, C3DPointList *points) const;
135};
136
137#ifndef MOOTOOLS_NO_INLINE
138inline real CInitialCost::GetCost() const
139{
140 return cost;
141}
142
143inline void CInitialCost::SetCost(double newcost)
144{
145 cost = (real)newcost;
146}
147
148inline void CInitialCost::InitContraction(CONTRACTION_TYPE type, CONTRACTION_PRIORITY priority)
149{
150 info = SET_CONTRACTION_INFO(type, priority);
151 #ifdef MOOTOOLS_PRIVATE_DEBUG
152 if (type >= LINE_OPTIMAL)
153 linecoef = -1.0; // Check that it was called in GetLineCoef
154 #endif
155}
156
157inline CONTRACTION_TYPE CInitialCost::GetType() const
158{
159 MOOTOOLS_PRIVATE_ASSERT(GET_CONTRACTION_TYPE(info) >= UNDEFINED_OPTIMAL && GET_CONTRACTION_TYPE(info) <= POINT2_OPTIMAL);
160 return (CONTRACTION_TYPE)GET_CONTRACTION_TYPE(info);
161}
162
163inline void CInitialCost::SetPriority(CONTRACTION_PRIORITY priority)
164{
165 info = SET_CONTRACTION_PRIORITY(info, priority);
166}
167
168inline CONTRACTION_PRIORITY CInitialCost::GetPriority() const
169{
170 MOOTOOLS_PRIVATE_ASSERT(GET_CONTRACTION_PRIORITY(info) >= MINIMUM_CONTRACTION_PRIORITY && GET_CONTRACTION_PRIORITY(info) <= FLIP_FACE_CONTRACTION_PRIORITY);
171 return (CONTRACTION_PRIORITY)GET_CONTRACTION_PRIORITY(info);
172}
173
174inline void CInitialCost::SetOrder(unsigned char value)
175{
176 info = SET_CONTRACTION_ORDER(info, value);
177}
178
179inline unsigned char CInitialCost::GetOrder() const
180{
181 return GET_CONTRACTION_ORDER(info);
182}
183
184inline double CInitialCost::GetLineCoef() const
185{
186 MOOTOOLS_PRIVATE_ASSERT(GetType() >= LINE_OPTIMAL); // Other values give incorrect results
187 MOOTOOLS_PRIVATE_ASSERT(linecoef != -1.0 && linecoef >= 0.0 && linecoef <= 1.0); // SetLineCoef must have been called
188 return linecoef;
189}
190
191// Linecoef is the moving coef along edge(point1, point2).
192// Linecoef = 0.0f the new pos == point2
193// Linecoef = 1.0f the new pos == point1
194inline void CInitialCost::SetLineCoef(double value)
195{
196 MOOTOOLS_PRIVATE_ASSERT(GetType() >= LINE_OPTIMAL); // Need to be set only for LINE_OPTIMAL
197 MOOTOOLS_PRIVATE_ASSERT(value >= 0.0 && value <= 1.0); // SetLineCoef must have been called
198 linecoef = value;
199}
200
201inline void CInitialCost::SetPos(const C3DPoint& pt)
202{
203 MOOTOOLS_PRIVATE_ASSERT(GetType() == INVERSEMATRIX_OPTIMAL); // Need to be set only for INVERSEMATRIX_OPTIMAL
204 memcpy(pos, pt.ValPtr(), 3 * sizeof(real));
205}
206
207// If linecoef = 0.0 (POINT2_OPTIMAL) or linecoef = 1.0f (POINT1_OPTIMAL) the point does not moves.
208// In this case the remaining index is the point which does not moves.
209// this allows to minimize the CTrackInfo size because we only have to update UV and normals of the faces which own the replaced index.
210//
211// If linecoef > 0.0 && linecoef < 1.0, the remaining index must be point1 and the replaced index must be point2
212inline int CInitialCost::GetRemainingIndex()
213{
214 if (GetType() == POINT2_OPTIMAL)
215 {
216 MOOTOOLS_PRIVATE_ASSERT(linecoef == 0.0f);
217 MOOTOOLS_PRIVATE_ASSERT(point2 == PrevGetRemainingIndex());
218 return point2;
219 }
220
221 MOOTOOLS_PRIVATE_ASSERT(point1 == PrevGetRemainingIndex());
222 return point1;
223}
224
225inline int CInitialCost::GetReplacedIndex()
226{
227 if (GetType() == POINT2_OPTIMAL)
228 {
229 MOOTOOLS_PRIVATE_ASSERT(linecoef == 0.0f);
230 MOOTOOLS_PRIVATE_ASSERT(point1 == PrevGetReplacedIndex());
231 return point1;
232 }
233
234 MOOTOOLS_PRIVATE_ASSERT(point2 == PrevGetReplacedIndex());
235 return point2;
236}
237#endif // MOOTOOLS_NO_INLINE
238
239class CContractionCost : public CInitialCost
240{
241public:
242 CContractionCost **heapPtr;
243
244 bool operator < (const CContractionCost& refcost) const;
245
246#ifdef MOOTOOLS_PRIVATE_DEBUG
247 void Dump() const;
248#endif
249};
250
251#ifndef MOOTOOLS_NO_INLINE
252inline bool CContractionCost::operator < (const CContractionCost& refcost) const
253{
254 // If priority the same, compare cost
255 if (GET_CONTRACTION_PRIORITY(info) == GET_CONTRACTION_PRIORITY(refcost.info))
256 {
257 if (cost == refcost.cost)
258 {
259 if (GET_CONTRACTION_ORDER(info) == GET_CONTRACTION_ORDER(refcost.info))
260 {
261 if (GET_CONTRACTION_TYPE(info) == GET_CONTRACTION_TYPE(refcost.info))
262 {
263 // 03/21 : #669
264 // sorting on index allow to have an optimization that remains stable between different optimization on different system (max, standalone...)
265 if (point1 == refcost.point1)
266 return point2 < refcost.point2;
267
268 return point1 < refcost.point1;
269 }
270
271 return GET_CONTRACTION_TYPE(info) < GET_CONTRACTION_TYPE(refcost.info); // Element that had a matrix or line contraction are first sorted
272 }
273
274 return GET_CONTRACTION_ORDER(info) < GET_CONTRACTION_ORDER(refcost.info); // Element that were not already moved are first sorted
275 }
276
277 return cost < refcost.cost;
278 }
279
280 // Element with lower priority are first sorted
281 return GET_CONTRACTION_PRIORITY(info) < GET_CONTRACTION_PRIORITY(refcost.info);
282}
283#endif // MOOTOOLS_NO_INLINE
284
285class C3DExtObject;
286class CostHeap
287{
288 public:
289 // Constructor, destructor, and copy assignment
290 CostHeap();
291 virtual ~CostHeap();
292
293 void Free();
294
295 void InitHeap(const CContractionCost *, unsigned int, C3DExtObject *);
296
297#ifdef MOOTOOLS_PRIVATE_DEBUG
298 unsigned int GetPermutation();
299 void CheckOrder();
300 const CostHeap &CopyForDump( const CostHeap & Rhs );
301 void Dump();
302#endif
303
304 // Add an item maintaining heap order
305 CContractionCost **Insert(CContractionCost *X);
306
307 // Delete minimum item in heap
308 void DeleteMin(CContractionCost *&X );
309
310 // Remove an entry
311 unsigned int GetSize();
312 CContractionCost *GetAt(unsigned int i);
313
314 void RemoveAt(CContractionCost **X );
315
316 int IsEmpty() const;
317 int IsFull() const;
318 void MakeEmpty();
319
320 // Internal routines
321private:
322 unsigned int MaxSize; // Number of elements that can be stored (Allocate : MaxSize+1)
323 unsigned int CurrentSize; // Number of elements currently stored
324 int OrderOK; // Zero if heap order is not guaranteed
325 CContractionCost **Array; // Dynamically allocated array
326 CContractionCost lowestVal; // The smaller possible value
327
328#ifdef MOOTOOLS_PRIVATE_DEBUG
329 C3DExtObject *object; // to update cost position
330 unsigned int permutation;
331#endif
332
333 void PercolateDown( unsigned int Index );
334 void GetArray( unsigned int NewMaxSize ); // Allocate array
335};
336
337#ifndef MOOTOOLS_NO_INLINE
338inline CContractionCost *CostHeap::GetAt(unsigned int i)
339{
340 MOOTOOLS_PRIVATE_ASSERT(i < CurrentSize);
341 return Array[i];
342}
343#endif // MOOTOOLS_NO_INLINE
344
345END_MOOTOOLS_NAMESPACE
346
347#endif // __COSTHEAP_H
348
C3DFaceList class definition which is a list of C3DFace.
C3DPointList class definition for handling a list of C3DPoint.
C3DEdge is a class containing 2 point indexes that represent the edge of a face.
Definition FaceList.h:72
This class handles static optimization of an object.
Definition 3DExtObject.h:66
Definition 3DPointList.h:267
The class defines an x, y, z 3D point which can use int, float or double.
Definition 3DPoint.h:27