1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
|
//-----------------------------------------------------------------------------
// BSPLIB HEADER: Polygon.h
//
// Copyright (c) 1996-1998 by Markus Hadwiger
// All Rights Reserved.
//-----------------------------------------------------------------------------
#ifndef _POLYGON_H_
#define _POLYGON_H_
// bsplib header files
#include "BspLibDefs.h"
#include "Chunk.h"
#include "Face.h"
#include "Plane.h"
#include "SystemIO.h"
BSPLIB_NAMESPACE_BEGIN
class BoundingBox;
// vertex index (element of vertex index list) --------------------------------
//
class VIndx {
public:
VIndx( int indx = -1, VIndx *next = NULL ) { vertindx = indx; nextvertindx = next; }
~VIndx() { delete nextvertindx; }
int getIndx() const { return vertindx; }
void setIndx( int indx ) { vertindx = indx; }
VIndx* getNext() const { return nextvertindx; }
void setNext( VIndx *next ) { nextvertindx = next; }
private:
int vertindx; // -1 means end of list, regardless of nextvertindx
VIndx* nextvertindx; // pointer to next VIndx in singly linked list
};
class BSPNode;
class BspObject;
// single polygon (element of polygon list) -----------------------------------
//
class Polygon : public virtual SystemIO {
friend class PolygonListRep;
void Error() const;
// possible classifications of polygon with respect to splitting plane
enum {
POLY_IN_FRONT_SUBSPACE,
POLY_IN_BACK_SUBSPACE,
POLY_STRADDLES_SPLITTER,
POLY_IN_SAME_PLANE,
};
// frontsubspace/backsubspace identifiers
enum {
FRONT_SUBSPACE = 1,
BACK_SUBSPACE = -1
};
public:
// splitter selection criteria
enum {
SPLITTERCRIT_FIRST_POLY = 0x0000, // always choose first polygon in list
SPLITTERCRIT_SAMPLE_FIRST_N = 0x0101, // test first n polygons in list
SPLITTERCRIT_SAMPLE_ALL = 0x0002, // test entire list and choose best
SPLITTERCRIT_RANDOM_SAMPLE = 0x0103, // sample n polygons randomly
SPLITTERCRITMASK_SAMPLESIZ = 0x0100, // flagmask if samplesize (n) needed
};
// message flags
enum {
MESSAGE_SPLITTING_POLYGON = 0x0001,
MESSAGE_STARTVERTEX_IN_SPLITTER_PLANE = 0x0002,
MESSAGE_VERTEX_IN_SPLITTER_PLANE = 0x0004,
MESSAGE_NEW_SPLITVERTEX = 0x0008,
MESSAGE_REUSING_SPLITVERTEX = 0x0010,
MESSAGE_TRACEVERTEX_INSERTED = 0x0020,
MESSAGE_SPLITTING_QUADRILATERAL = 0x0040,
MESSAGE_INVOCATION = 0x0080,
MESSAGE_CHECKING_POLYGON_PLANES = 0x0100,
MESSAGEMASK_DISPLAY_ALL = 0xffff
};
public:
Polygon( BspObject *bobj, int pno = 0, int fno = 0, Polygon *next = NULL, int num = 1 );
~Polygon() { delete vertindxs; delete nextpolygon; }
Polygon* NewPolygon(); // create new polygon with sequential id as head of list
Polygon* InsertPolygon( Polygon *poly ); // insert existing polygon as head of list
Polygon* DeleteHead(); // delete this, return rest of list (DANGEROUS!)
Polygon* FindPolygon( int id ); // return polygon in list having specified id
int SumVertexNumsEntireList(); // sum up vertex numbers for all polygons of list
void PrependNewVIndx( int indx ); // create new VIndx and prepend it to list (vertindxs)
void AppendNewVIndx( int indx = -1 ); // create new VIndx and append it to list (vertindxs)
void AppendVIndx( VIndx *vindx ); // append existing VIndx to list (vertindxs)
VIndx* UnlinkLastVIndx(); // return last VIndx in list after unlinking it
void CalcPlaneNormals(); // calc normals for all polygons in list
void CheckEdges(); // check edges for contained vertices (scans list!)
Polygon* CheckPlanesAndMappings(); // check planes and mappings of all polygons in list
// calculate bounding box encompassing all polygons in list
void CalcBoundingBox( BoundingBox* &boundingbox );
// classify polygon with respect to this polygon
int CheckIntersection( Polygon *testpoly );
// check if other polygon's normal is contained in this one's positive halfspace (predicate)
int NormalDirectionSimilar( Polygon *testpoly );
// split other polygon along this polygon; insert split pieces into their respective halfspaces
void SplitPolygon( Polygon *poly, Polygon* &frontsubspace, Polygon* &backsubspace );
// partition space encompassing entire polygon list; return created BSP tree's root
BSPNode* PartitionSpace();
// correct numberings (polygon-id, face-id, and vertex indexes) to new base
void CorrectBase( BspObject *newbaseobj, int vertexindxbase, int faceidbase, int polygonidbase );
void CorrectBaseByTable( BspObject *newbaseobj, int *vtxindxmap, int faceidbase, int polygonidbase );
int getId() const { return polygonno; }
void setId( int pno ) { polygonno = pno; }
int getFaceId() const { return faceno; }
void setFaceId( int fno ) { faceno = fno; }
int getNumPolygons() const { return numpolygons; }
void setNumPolygons( int len ) { numpolygons = len; }
Polygon* getNext() const { return nextpolygon; }
void setNext( Polygon *next ) { nextpolygon = next; }
int getNumVertices() const { return numvertindxs; }
VIndx* getVList() const { return vertindxs; }
BspObject* getBaseObject() const { return baseobject; }
VertexChunk& getVertexList();
FaceChunk& getFaceList();
int HasArea() const;
int getFirstVertexIndx() const;
int getSecondVertexIndx() const;
int getThirdVertexIndx() const;
Vertex3 getFirstVertex() const;
Vertex3 getSecondVertex() const;
Vertex3 getThirdVertex() const;
Plane getPlane() const { return ((Polygon *const)this)->getFaceList()[ faceno ].getPlane(); }
Vector3 getPlaneNormal() const { return ((Polygon *const)this)->getFaceList()[ faceno ].getPlaneNormal(); }
void FillVertexIndexArray( dword *arr ) const; // write list of vertices into array
void WriteVertexList( FILE *fp, int cr ) const; // write list of vertices to file
void WritePolyList( FILE *fp ) const; // write list of polygon ids to file
int CalcSplitterTestProbability();
public:
static int getSplitterSelection() { return splitter_crit; }
static void setSplitterSelection( int criterion ) { splitter_crit = criterion; }
static int getSampleSize() { return sample_size; }
static void setSampleSize( int siz ) { sample_size = siz; }
static int getTriangulationFlag() { return triangulate_all; }
static void setTriangulationFlag( int flag ) { triangulate_all = flag; }
static int getNormalizeVectorsFlag() { return normalize_vectors; }
static void setNormalizeVectorsFlag( int flag ) { normalize_vectors = flag; }
static int getDisplayMessagesFlag() { return display_messages; }
static void setDisplayMessagesFlag( int flag ) { display_messages = flag; }
static void ResetCallCount() { partition_callcount = 0; }
private:
static int splitter_crit; // splitter selection criterion to use
static int sample_size; // sample size for splitter sampling
static int triangulate_all; // triangulate polygons with more than three vertices
static int normalize_vectors; // always normalize direction vectors
static int display_messages; // display a message every time PartitionSpace() is invoked
static int partition_callcount;// call counter for PartitionSpace()
static int test_probability; // probability to test single polygon if SPLITTERCRIT_RANDOM_SAMPLE
static char str_scratchpad[]; // string scratch pad
private:
int polygonno; // global number of this polygon
int faceno; // global number of face this polygon is contained in
int numpolygons; // length of singly linked polygon list
int numvertindxs; // number of entries in vertex index list attached to this polygon
VIndx* vertindxs; // pointer to first VIndx
VIndx* vindxinsertpos; // pointer to last VIndx (NULL means insert-position is at head)
BspObject* baseobject; // pointer to object this polygon belongs to
Polygon* nextpolygon; // pointer to next polygon in list
};
// determine if the polygon has area ------------------------------------------
inline int Polygon::HasArea() const
{
// collinear vertices are not checked here, the polygon need only have
// at least three vertices to count as having area!
return ( vertindxs && vertindxs->getNext() && vertindxs->getNext()->getNext() );
}
// get first vertex of polygon ------------------------------------------------
inline int Polygon::getFirstVertexIndx() const
{
CHECK_DEREFERENCING(
if ( vertindxs == NULL )
Error();
);
return vertindxs->getIndx();
}
inline Vertex3 Polygon::getFirstVertex() const
{
CHECK_DEREFERENCING(
if ( vertindxs == NULL )
Error();
);
return ((Polygon *const)this)->getVertexList()[ vertindxs->getIndx() ];
}
// get second vertex of polygon -----------------------------------------------
inline int Polygon::getSecondVertexIndx() const
{
CHECK_DEREFERENCING(
if ( ( vertindxs == NULL ) || ( vertindxs->getNext() == NULL ) )
Error();
);
return vertindxs->getNext()->getIndx();
}
inline Vertex3 Polygon::getSecondVertex() const
{
CHECK_DEREFERENCING(
if ( ( vertindxs == NULL ) || ( vertindxs->getNext() == NULL ) )
Error();
);
return ((Polygon *const)this)->getVertexList()[ vertindxs->getNext()->getIndx() ];
}
// get third vertex of polygon ------------------------------------------------
inline int Polygon::getThirdVertexIndx() const
{
CHECK_DEREFERENCING(
if ( ( vertindxs == NULL ) ||
( vertindxs->getNext() == NULL ) ||
( vertindxs->getNext()->getNext() == NULL ) )
Error();
);
return vertindxs->getNext()->getNext()->getIndx();
}
inline Vertex3 Polygon::getThirdVertex() const
{
CHECK_DEREFERENCING(
if ( ( vertindxs == NULL ) ||
( vertindxs->getNext() == NULL ) ||
( vertindxs->getNext()->getNext() == NULL ) )
Error();
);
return ((Polygon *const)this)->getVertexList()[ vertindxs->getNext()->getNext()->getIndx() ];
}
BSPLIB_NAMESPACE_END
#endif // _POLYGON_H_
|