aboutsummaryrefslogtreecommitdiff
path: root/tool_src/BspLib/Polygon.h
blob: d83de32480cf240d9f1d60cdf3f1f90ed47e4b5d (plain)
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_