1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 /*
30 ===============================================================================
31 
32 	Trace model vs. polygonal model collision detection.
33 
34 ===============================================================================
35 */
36 
37 #include "idlib/math/Pluecker.h"
38 #include "cm/CollisionModel.h"
39 
40 #define MIN_NODE_SIZE						64.0f
41 #define MAX_NODE_POLYGONS					128
42 #define CM_MAX_POLYGON_EDGES				64
43 #define CIRCLE_APPROXIMATION_LENGTH			64.0f
44 
45 #define	MAX_SUBMODELS						2048
46 #define	TRACE_MODEL_HANDLE					MAX_SUBMODELS
47 
48 #define VERTEX_HASH_BOXSIZE					(1<<6)	// must be power of 2
49 #define VERTEX_HASH_SIZE					(VERTEX_HASH_BOXSIZE*VERTEX_HASH_BOXSIZE)
50 #define EDGE_HASH_SIZE						(1<<14)
51 
52 #define NODE_BLOCK_SIZE_SMALL				8
53 #define NODE_BLOCK_SIZE_LARGE				256
54 #define REFERENCE_BLOCK_SIZE_SMALL			8
55 #define REFERENCE_BLOCK_SIZE_LARGE			256
56 
57 #define MAX_WINDING_LIST					128		// quite a few are generated at times
58 #define INTEGRAL_EPSILON					0.01f
59 #define VERTEX_EPSILON						0.1f
60 #define CHOP_EPSILON						0.1f
61 
62 
63 typedef struct cm_windingList_s {
64 	int					numWindings;			// number of windings
65 	idFixedWinding		w[MAX_WINDING_LIST];	// windings
66 	idVec3				normal;					// normal for all windings
67 	idBounds			bounds;					// bounds of all windings in list
68 	idVec3				origin;					// origin for radius
69 	float				radius;					// radius relative to origin for all windings
70 	int					contents;				// winding surface contents
71 	int					primitiveNum;			// number of primitive the windings came from
72 } cm_windingList_t;
73 
74 /*
75 ===============================================================================
76 
77 Collision model
78 
79 ===============================================================================
80 */
81 
82 typedef struct cm_vertex_s {
83 	idVec3					p;					// vertex point
84 	int						checkcount;			// for multi-check avoidance
85 	unsigned int			side;				// each bit tells at which side this vertex passes one of the trace model edges
86 	unsigned int			sideSet;			// each bit tells if sidedness for the trace model edge has been calculated yet
87 } cm_vertex_t;
88 
89 typedef struct cm_edge_s {
90 	int						checkcount;			// for multi-check avoidance
91 	unsigned short			internal;			// a trace model can never collide with internal edges
92 	unsigned short			numUsers;			// number of polygons using this edge
93 	unsigned int			side;				// each bit tells at which side of this edge one of the trace model vertices passes
94 	unsigned int			sideSet;			// each bit tells if sidedness for the trace model vertex has been calculated yet
95 	int						vertexNum[2];		// start and end point of edge
96 	idVec3					normal;				// edge normal
97 } cm_edge_t;
98 
99 typedef struct cm_polygonBlock_s {
100 	int						bytesRemaining;
101 	byte *					next;
102 } cm_polygonBlock_t;
103 
104 typedef struct cm_polygon_s {
105 	idBounds				bounds;				// polygon bounds
106 	int						checkcount;			// for multi-check avoidance
107 	int						contents;			// contents behind polygon
108 	const idMaterial *		material;			// material
109 	idPlane					plane;				// polygon plane
110 	int						numEdges;			// number of edges
111 	int						edges[1];			// variable sized, indexes into cm_edge_t list
112 } cm_polygon_t;
113 
114 typedef struct cm_polygonRef_s {
115 	cm_polygon_t *			p;					// pointer to polygon
116 	struct cm_polygonRef_s *next;				// next polygon in chain
117 } cm_polygonRef_t;
118 
119 typedef struct cm_polygonRefBlock_s {
120 	cm_polygonRef_t *		nextRef;			// next polygon reference in block
121 	struct cm_polygonRefBlock_s *next;			// next block with polygon references
122 } cm_polygonRefBlock_t;
123 
124 typedef struct cm_brushBlock_s {
125 	int						bytesRemaining;
126 	byte *					next;
127 } cm_brushBlock_t;
128 
129 typedef struct cm_brush_s {
130 	int						checkcount;			// for multi-check avoidance
131 	idBounds				bounds;				// brush bounds
132 	int						contents;			// contents of brush
133 	const idMaterial *		material;			// material
134 	int						primitiveNum;		// number of brush primitive
135 	int						numPlanes;			// number of bounding planes
136 	idPlane					planes[1];			// variable sized
137 } cm_brush_t;
138 
139 typedef struct cm_brushRef_s {
140 	cm_brush_t *			b;					// pointer to brush
141 	struct cm_brushRef_s *	next;				// next brush in chain
142 } cm_brushRef_t;
143 
144 typedef struct cm_brushRefBlock_s {
145 	cm_brushRef_t *			nextRef;			// next brush reference in block
146 	struct cm_brushRefBlock_s *next;			// next block with brush references
147 } cm_brushRefBlock_t;
148 
149 typedef struct cm_node_s {
150 	int						planeType;			// node axial plane type
151 	float					planeDist;			// node plane distance
152 	cm_polygonRef_t *		polygons;			// polygons in node
153 	cm_brushRef_t *			brushes;			// brushes in node
154 	struct cm_node_s *		parent;				// parent of this node
155 	struct cm_node_s *		children[2];		// node children
156 } cm_node_t;
157 
158 typedef struct cm_nodeBlock_s {
159 	cm_node_t *				nextNode;			// next node in block
160 	struct cm_nodeBlock_s *next;				// next block with nodes
161 } cm_nodeBlock_t;
162 
163 typedef struct cm_model_s {
164 	idStr					name;				// model name
165 	idBounds				bounds;				// model bounds
166 	int						contents;			// all contents of the model ored together
167 	bool					isConvex;			// set if model is convex
168 	// model geometry
169 	int						maxVertices;		// size of vertex array
170 	int						numVertices;		// number of vertices
171 	cm_vertex_t *			vertices;			// array with all vertices used by the model
172 	int						maxEdges;			// size of edge array
173 	int						numEdges;			// number of edges
174 	cm_edge_t *				edges;				// array with all edges used by the model
175 	cm_node_t *				node;				// first node of spatial subdivision
176 	// blocks with allocated memory
177 	cm_nodeBlock_t *		nodeBlocks;			// list with blocks of nodes
178 	cm_polygonRefBlock_t *	polygonRefBlocks;	// list with blocks of polygon references
179 	cm_brushRefBlock_t *	brushRefBlocks;		// list with blocks of brush references
180 	cm_polygonBlock_t *		polygonBlock;		// memory block with all polygons
181 	cm_brushBlock_t *		brushBlock;			// memory block with all brushes
182 	// statistics
183 	int						numPolygons;
184 	int						polygonMemory;
185 	int						numBrushes;
186 	int						brushMemory;
187 	int						numNodes;
188 	int						numBrushRefs;
189 	int						numPolygonRefs;
190 	int						numInternalEdges;
191 	int						numSharpEdges;
192 	int						numRemovedPolys;
193 	int						numMergedPolys;
194 	int						usedMemory;
195 } cm_model_t;
196 
197 /*
198 ===============================================================================
199 
200 Data used during collision detection calculations
201 
202 ===============================================================================
203 */
204 
205 typedef struct cm_trmVertex_s {
206 	int used;										// true if this vertex is used for collision detection
207 	idVec3 p;										// vertex position
208 	idVec3 endp;									// end point of vertex after movement
209 	int polygonSide;								// side of polygon this vertex is on (rotational collision)
210 	idPluecker pl;									// pluecker coordinate for vertex movement
211 	idVec3 rotationOrigin;							// rotation origin for this vertex
212 	idBounds rotationBounds;						// rotation bounds for this vertex
213 } cm_trmVertex_t;
214 
215 typedef struct cm_trmEdge_s {
216 	int used;										// true when vertex is used for collision detection
217 	idVec3 start;									// start of edge
218 	idVec3 end;										// end of edge
219 	int vertexNum[2];								// indexes into cm_traceWork_t->vertices
220 	idPluecker pl;									// pluecker coordinate for edge
221 	idVec3 cross;									// (z,-y,x) of cross product between edge dir and movement dir
222 	idBounds rotationBounds;						// rotation bounds for this edge
223 	idPluecker plzaxis;								// pluecker coordinate for rotation about the z-axis
224 	unsigned short bitNum;							// vertex bit number
225 } cm_trmEdge_t;
226 
227 typedef struct cm_trmPolygon_s {
228 	int used;
229 	idPlane plane;									// polygon plane
230 	int numEdges;									// number of edges
231 	int edges[MAX_TRACEMODEL_POLYEDGES];			// index into cm_traceWork_t->edges
232 	idBounds rotationBounds;						// rotation bounds for this polygon
233 } cm_trmPolygon_t;
234 
235 typedef struct cm_traceWork_s {
236 	int numVerts;
237 	cm_trmVertex_t vertices[MAX_TRACEMODEL_VERTS];	// trm vertices
238 	int numEdges;
239 	cm_trmEdge_t edges[MAX_TRACEMODEL_EDGES+1];		// trm edges
240 	int numPolys;
241 	cm_trmPolygon_t polys[MAX_TRACEMODEL_POLYS];	// trm polygons
242 	cm_model_t *model;								// model colliding with
243 	idVec3 start;									// start of trace
244 	idVec3 end;										// end of trace
245 	idVec3 dir;										// trace direction
246 	idBounds bounds;								// bounds of full trace
247 	idBounds size;									// bounds of transformed trm relative to start
248 	idVec3 extents;									// largest of abs(size[0]) and abs(size[1]) for BSP trace
249 	int contents;									// ignore polygons that do not have any of these contents flags
250 	trace_t trace;									// collision detection result
251 
252 	bool rotation;									// true if calculating rotational collision
253 	bool pointTrace;								// true if only tracing a point
254 	bool positionTest;								// true if not tracing but doing a position test
255 	bool isConvex;									// true if the trace model is convex
256 	bool axisIntersectsTrm;							// true if the rotation axis intersects the trace model
257 	bool getContacts;								// true if retrieving contacts
258 	bool quickExit;									// set to quickly stop the collision detection calculations
259 
260 	idVec3 origin;									// origin of rotation in model space
261 	idVec3 axis;									// rotation axis in model space
262 	idMat3 matrix;									// rotates axis of rotation to the z-axis
263 	float angle;									// angle for rotational collision
264 	float maxTan;									// max tangent of half the positive angle used instead of fraction
265 	float radius;									// rotation radius of trm start
266 	idRotation modelVertexRotation;					// inverse rotation for model vertices
267 
268 	contactInfo_t *contacts;						// array with contacts
269 	int maxContacts;								// max size of contact array
270 	int numContacts;								// number of contacts found
271 
272 	idPlane heartPlane1;							// polygons should be near anough the trace heart planes
273 	float maxDistFromHeartPlane1;
274 	idPlane heartPlane2;
275 	float maxDistFromHeartPlane2;
276 	idPluecker polygonEdgePlueckerCache[CM_MAX_POLYGON_EDGES];
277 	idPluecker polygonVertexPlueckerCache[CM_MAX_POLYGON_EDGES];
278 	idVec3 polygonRotationOriginCache[CM_MAX_POLYGON_EDGES];
279 } cm_traceWork_t;
280 
281 /*
282 ===============================================================================
283 
284 Collision Map
285 
286 ===============================================================================
287 */
288 
289 typedef struct cm_procNode_s {
290 	idPlane plane;
291 	int children[2];				// negative numbers are (-1 - areaNumber), 0 = solid
292 } cm_procNode_t;
293 
294 class idCollisionModelManagerLocal : public idCollisionModelManager {
295 public:
296 	// load collision models from a map file
297 	void			LoadMap( const idMapFile *mapFile );
298 	// frees all the collision models
299 	void			FreeMap( void );
300 
301 	// get clip handle for model
302 	cmHandle_t		LoadModel( const char *modelName, const bool precache );
303 	// sets up a trace model for collision with other trace models
304 	cmHandle_t		SetupTrmModel( const idTraceModel &trm, const idMaterial *material );
305 	// create trace model from a collision model, returns true if succesfull
306 	bool			TrmFromModel( const char *modelName, idTraceModel &trm );
307 
308 	// name of the model
309 	const char *	GetModelName( cmHandle_t model ) const;
310 	// bounds of the model
311 	bool			GetModelBounds( cmHandle_t model, idBounds &bounds ) const;
312 	// all contents flags of brushes and polygons ored together
313 	bool			GetModelContents( cmHandle_t model, int &contents ) const;
314 	// get the vertex of a model
315 	bool			GetModelVertex( cmHandle_t model, int vertexNum, idVec3 &vertex ) const;
316 	// get the edge of a model
317 	bool			GetModelEdge( cmHandle_t model, int edgeNum, idVec3 &start, idVec3 &end ) const;
318 	// get the polygon of a model
319 	bool			GetModelPolygon( cmHandle_t model, int polygonNum, idFixedWinding &winding ) const;
320 
321 	// translates a trm and reports the first collision if any
322 	void			Translation( trace_t *results, const idVec3 &start, const idVec3 &end,
323 								const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
324 								cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
325 	// rotates a trm and reports the first collision if any
326 	void			Rotation( trace_t *results, const idVec3 &start, const idRotation &rotation,
327 								const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
328 								cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
329 	// returns the contents the trm is stuck in or 0 if the trm is in free space
330 	int				Contents( const idVec3 &start,
331 								const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
332 								cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
333 	// stores all contact points of the trm with the model, returns the number of contacts
334 	int				Contacts( contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth,
335 								const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
336 								cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
337 	// test collision detection
338 	void			DebugOutput( const idVec3 &origin );
339 	// draw a model
340 	void			DrawModel( cmHandle_t model, const idVec3 &origin, const idMat3 &axis,
341 											const idVec3 &viewOrigin, const float radius );
342 	// print model information, use -1 handle for accumulated model info
343 	void			ModelInfo( cmHandle_t model );
344 	// list all loaded models
345 	void			ListModels( void );
346 	// write a collision model file for the map entity
347 	bool			WriteCollisionModelForMapEntity( const idMapEntity *mapEnt, const char *filename, const bool testTraceModel = true );
348 
349 private:			// CollisionMap_translate.cpp
350 	int				TranslateEdgeThroughEdge( idVec3 &cross, idPluecker &l1, idPluecker &l2, float *fraction );
351 	void			TranslateTrmEdgeThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmEdge_t *trmEdge );
352 	void			TranslateTrmVertexThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmVertex_t *v, int bitNum );
353 	void			TranslatePointThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmVertex_t *v );
354 	void			TranslateVertexThroughTrmPolygon( cm_traceWork_t *tw, cm_trmPolygon_t *trmpoly, cm_polygon_t *poly, cm_vertex_t *v, idVec3 &endp, idPluecker &pl );
355 	bool			TranslateTrmThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *p );
356 	void			SetupTranslationHeartPlanes( cm_traceWork_t *tw );
357 	void			SetupTrm( cm_traceWork_t *tw, const idTraceModel *trm );
358 
359 private:			// CollisionMap_rotate.cpp
360 	int				CollisionBetweenEdgeBounds( cm_traceWork_t *tw, const idVec3 &va, const idVec3 &vb,
361 											const idVec3 &vc, const idVec3 &vd, float tanHalfAngle,
362 											idVec3 &collisionPoint, idVec3 &collisionNormal );
363 	int				RotateEdgeThroughEdge( cm_traceWork_t *tw, const idPluecker &pl1,
364 											const idVec3 &vc, const idVec3 &vd,
365 											const float minTan, float &tanHalfAngle );
366 	int				EdgeFurthestFromEdge( cm_traceWork_t *tw, const idPluecker &pl1,
367 											const idVec3 &vc, const idVec3 &vd,
368 											float &tanHalfAngle, float &dir );
369 	void			RotateTrmEdgeThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmEdge_t *trmEdge );
370 	int				RotatePointThroughPlane( const cm_traceWork_t *tw, const idVec3 &point, const idPlane &plane,
371 											const float angle, const float minTan, float &tanHalfAngle );
372 	int				PointFurthestFromPlane( const cm_traceWork_t *tw, const idVec3 &point, const idPlane &plane,
373 											const float angle, float &tanHalfAngle, float &dir );
374 	int				RotatePointThroughEpsilonPlane( const cm_traceWork_t *tw, const idVec3 &point, const idVec3 &endPoint,
375 											const idPlane &plane, const float angle, const idVec3 &origin,
376 											float &tanHalfAngle, idVec3 &collisionPoint, idVec3 &endDir );
377 	void			RotateTrmVertexThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmVertex_t *v, int vertexNum);
378 	void			RotateVertexThroughTrmPolygon( cm_traceWork_t *tw, cm_trmPolygon_t *trmpoly, cm_polygon_t *poly,
379 											cm_vertex_t *v, idVec3 &rotationOrigin );
380 	bool			RotateTrmThroughPolygon( cm_traceWork_t *tw, cm_polygon_t *p );
381 	void			BoundsForRotation( const idVec3 &origin, const idVec3 &axis, const idVec3 &start, const idVec3 &end, idBounds &bounds );
382 	void			Rotation180( trace_t *results, const idVec3 &rorg, const idVec3 &axis,
383 									const float startAngle, const float endAngle, const idVec3 &start,
384 									const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
385 									cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis );
386 
387 private:			// CollisionMap_contents.cpp
388 	bool			TestTrmVertsInBrush( cm_traceWork_t *tw, cm_brush_t *b );
389 	bool			TestTrmInPolygon( cm_traceWork_t *tw, cm_polygon_t *p );
390 	cm_node_t *		PointNode( const idVec3 &p, cm_model_t *model );
391 	int				PointContents( const idVec3 p, cmHandle_t model );
392 	int				TransformedPointContents( const idVec3 &p, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis );
393 	int				ContentsTrm( trace_t *results, const idVec3 &start,
394 									const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
395 									cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis );
396 
397 private:			// CollisionMap_trace.cpp
398 	void			TraceTrmThroughNode( cm_traceWork_t *tw, cm_node_t *node );
399 	void			TraceThroughAxialBSPTree_r( cm_traceWork_t *tw, cm_node_t *node, float p1f, float p2f, idVec3 &p1, idVec3 &p2);
400 	void			TraceThroughModel( cm_traceWork_t *tw );
401 	void			RecurseProcBSP_r( trace_t *results, int parentNodeNum, int nodeNum, float p1f, float p2f, const idVec3 &p1, const idVec3 &p2 );
402 
403 private:			// CollisionMap_load.cpp
404 	void			Clear( void );
405 	void			FreeTrmModelStructure( void );
406 					// model deallocation
407 	void			RemovePolygonReferences_r( cm_node_t *node, cm_polygon_t *p );
408 	void			RemoveBrushReferences_r( cm_node_t *node, cm_brush_t *b );
409 	void			FreeNode( cm_node_t *node );
410 	void			FreePolygonReference( cm_polygonRef_t *pref );
411 	void			FreeBrushReference( cm_brushRef_t *bref );
412 	void			FreePolygon( cm_model_t *model, cm_polygon_t *poly );
413 	void			FreeBrush( cm_model_t *model, cm_brush_t *brush );
414 	void			FreeTree_r( cm_model_t *model, cm_node_t *headNode, cm_node_t *node );
415 	void			FreeModel( cm_model_t *model );
416 					// merging polygons
417 	void			ReplacePolygons( cm_model_t *model, cm_node_t *node, cm_polygon_t *p1, cm_polygon_t *p2, cm_polygon_t *newp );
418 	cm_polygon_t *	TryMergePolygons( cm_model_t *model, cm_polygon_t *p1, cm_polygon_t *p2 );
419 	bool			MergePolygonWithTreePolygons( cm_model_t *model, cm_node_t *node, cm_polygon_t *polygon );
420 	void			MergeTreePolygons( cm_model_t *model, cm_node_t *node );
421 					// finding internal edges
422 	bool			PointInsidePolygon( cm_model_t *model, cm_polygon_t *p, idVec3 &v );
423 	void			FindInternalEdgesOnPolygon( cm_model_t *model, cm_polygon_t *p1, cm_polygon_t *p2 );
424 	void			FindInternalPolygonEdges( cm_model_t *model, cm_node_t *node, cm_polygon_t *polygon );
425 	void			FindInternalEdges( cm_model_t *model, cm_node_t *node );
426 	void			FindContainedEdges( cm_model_t *model, cm_polygon_t *p );
427 					// loading of proc BSP tree
428 	void			ParseProcNodes( idLexer *src );
429 	void			LoadProcBSP( const char *name );
430 					// removal of contained polygons
431 	int				R_ChoppedAwayByProcBSP( int nodeNum, idFixedWinding *w, const idVec3 &normal, const idVec3 &origin, const float radius );
432 	int				ChoppedAwayByProcBSP( const idFixedWinding &w, const idPlane &plane, int contents );
433 	void			ChopWindingListWithBrush( cm_windingList_t *list, cm_brush_t *b );
434 	void			R_ChopWindingListWithTreeBrushes( cm_windingList_t *list, cm_node_t *node );
435 	idFixedWinding *WindingOutsideBrushes( idFixedWinding *w, const idPlane &plane, int contents, int patch, cm_node_t *headNode );
436 					// creation of axial BSP tree
437 	cm_model_t *	AllocModel( void );
438 	cm_node_t *		AllocNode( cm_model_t *model, int blockSize );
439 	cm_polygonRef_t*AllocPolygonReference( cm_model_t *model, int blockSize );
440 	cm_brushRef_t *	AllocBrushReference( cm_model_t *model, int blockSize );
441 	cm_polygon_t *	AllocPolygon( cm_model_t *model, int numEdges );
442 	cm_brush_t *	AllocBrush( cm_model_t *model, int numPlanes );
443 	void			AddPolygonToNode( cm_model_t *model, cm_node_t *node, cm_polygon_t *p );
444 	void			AddBrushToNode( cm_model_t *model, cm_node_t *node, cm_brush_t *b );
445 	void			SetupTrmModelStructure( void );
446 	void			R_FilterPolygonIntoTree( cm_model_t *model, cm_node_t *node, cm_polygonRef_t *pref, cm_polygon_t *p );
447 	void			R_FilterBrushIntoTree( cm_model_t *model, cm_node_t *node, cm_brushRef_t *pref, cm_brush_t *b );
448 	cm_node_t *		R_CreateAxialBSPTree( cm_model_t *model, cm_node_t *node, const idBounds &bounds );
449 	cm_node_t *		CreateAxialBSPTree( cm_model_t *model, cm_node_t *node );
450 					// creation of raw polygons
451 	void			SetupHash(void);
452 	void			ShutdownHash(void);
453 	void			ClearHash( idBounds &bounds );
454 	int				HashVec(const idVec3 &vec);
455 	int				GetVertex( cm_model_t *model, const idVec3 &v, int *vertexNum );
456 	int				GetEdge( cm_model_t *model, const idVec3 &v1, const idVec3 &v2, int *edgeNum, int v1num );
457 	void			CreatePolygon( cm_model_t *model, idFixedWinding *w, const idPlane &plane, const idMaterial *material, int primitiveNum );
458 	void			PolygonFromWinding( cm_model_t *model, idFixedWinding *w, const idPlane &plane, const idMaterial *material, int primitiveNum );
459 	void			CalculateEdgeNormals( cm_model_t *model, cm_node_t *node );
460 	void			CreatePatchPolygons( cm_model_t *model, idSurface_Patch &mesh, const idMaterial *material, int primitiveNum );
461 	void			ConvertPatch( cm_model_t *model, const idMapPatch *patch, int primitiveNum );
462 	void			ConvertBrushSides( cm_model_t *model, const idMapBrush *mapBrush, int primitiveNum );
463 	void			ConvertBrush( cm_model_t *model, const idMapBrush *mapBrush, int primitiveNum );
464 	void			PrintModelInfo( const cm_model_t *model );
465 	void			AccumulateModelInfo( cm_model_t *model );
466 	void			RemapEdges( cm_node_t *node, int *edgeRemap );
467 	void			OptimizeArrays( cm_model_t *model );
468 	void			FinishModel( cm_model_t *model );
469 	void			BuildModels( const idMapFile *mapFile );
470 	cmHandle_t		FindModel( const char *name );
471 	cm_model_t *	CollisionModelForMapEntity( const idMapEntity *mapEnt );	// brush/patch model from .map
472 	cm_model_t *	LoadRenderModel( const char *fileName );					// ASE/LWO models
473 	bool			TrmFromModel_r( idTraceModel &trm, cm_node_t *node );
474 	bool			TrmFromModel( const cm_model_t *model, idTraceModel &trm );
475 
476 private:			// CollisionMap_files.cpp
477 					// writing
478 	void			WriteNodes( idFile *fp, cm_node_t *node );
479 	int				CountPolygonMemory( cm_node_t *node ) const;
480 	void			WritePolygons( idFile *fp, cm_node_t *node );
481 	int				CountBrushMemory( cm_node_t *node ) const;
482 	void			WriteBrushes( idFile *fp, cm_node_t *node );
483 	void			WriteCollisionModel( idFile *fp, cm_model_t *model );
484 	void			WriteCollisionModelsToFile( const char *filename, int firstModel, int lastModel, unsigned int mapFileCRC );
485 					// loading
486 	cm_node_t *		ParseNodes( idLexer *src, cm_model_t *model, cm_node_t *parent );
487 	void			ParseVertices( idLexer *src, cm_model_t *model );
488 	void			ParseEdges( idLexer *src, cm_model_t *model );
489 	void			ParsePolygons( idLexer *src, cm_model_t *model );
490 	void			ParseBrushes( idLexer *src, cm_model_t *model );
491 	bool			ParseCollisionModel( idLexer *src );
492 	bool			LoadCollisionModelFile( const char *name, unsigned int mapFileCRC );
493 
494 private:			// CollisionMap_debug
495 	int				ContentsFromString( const char *string ) const;
496 	const char *	StringFromContents( const int contents ) const;
497 	void			DrawEdge( cm_model_t *model, int edgeNum, const idVec3 &origin, const idMat3 &axis );
498 	void			DrawPolygon( cm_model_t *model, cm_polygon_t *p, const idVec3 &origin, const idMat3 &axis,
499 								const idVec3 &viewOrigin );
500 	void			DrawNodePolygons( cm_model_t *model, cm_node_t *node, const idVec3 &origin, const idMat3 &axis,
501 								const idVec3 &viewOrigin, const float radius );
502 
503 private:			// collision map data
504 	idStr			mapName;
505 	ID_TIME_T			mapFileTime;
506 	int				loaded;
507 					// for multi-check avoidance
508 	int				checkCount;
509 					// models
510 	int				maxModels;
511 	int				numModels;
512 	cm_model_t **	models;
513 					// polygons and brush for trm model
514 	cm_polygonRef_t*trmPolygons[MAX_TRACEMODEL_POLYS];
515 	cm_brushRef_t *	trmBrushes[1];
516 	const idMaterial *trmMaterial;
517 					// for data pruning
518 	int				numProcNodes;
519 	cm_procNode_t *	procNodes;
520 					// for retrieving contact points
521 	bool			getContacts;
522 	contactInfo_t *	contacts;
523 	int				maxContacts;
524 	int				numContacts;
525 };
526 
527 // for debugging
528 extern idCVar cm_debugCollision;
529