doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CollisionModel_contents.cpp
Go to the documentation of this file.
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/precompiled.h"
38 #pragma hdrstop
39 
40 #include "CollisionModel_local.h"
41 
42 /*
43 ===============================================================================
44 
45 Contents test
46 
47 ===============================================================================
48 */
49 
50 /*
51 ================
52 idCollisionModelManagerLocal::TestTrmVertsInBrush
53 
54  returns true if any of the trm vertices is inside the brush
55 ================
56 */
58  int i, j, numVerts, bestPlane;
59  float d, bestd;
60  idVec3 *p;
61 
63  return false;
64  }
66 
67  if ( !(b->contents & tw->contents) ) {
68  return false;
69  }
70 
71  // if the brush bounds don't intersect the trace bounds
72  if ( !b->bounds.IntersectsBounds( tw->bounds ) ) {
73  return false;
74  }
75 
76  if ( tw->pointTrace ) {
77  numVerts = 1;
78  }
79  else {
80  numVerts = tw->numVerts;
81  }
82 
83  for ( j = 0; j < numVerts; j++ ) {
84  p = &tw->vertices[j].p;
85 
86  // see if the point is inside the brush
87  bestPlane = 0;
88  bestd = -idMath::INFINITY;
89  for ( i = 0; i < b->numPlanes; i++ ) {
90  d = b->planes[i].Distance( *p );
91  if ( d >= 0.0f ) {
92  break;
93  }
94  if ( d > bestd ) {
95  bestd = d;
96  bestPlane = i;
97  }
98  }
99  if ( i >= b->numPlanes ) {
100  tw->trace.fraction = 0.0f;
102  tw->trace.c.normal = b->planes[bestPlane].Normal();
103  tw->trace.c.dist = b->planes[bestPlane].Dist();
104  tw->trace.c.contents = b->contents;
105  tw->trace.c.material = b->material;
106  tw->trace.c.point = *p;
107  tw->trace.c.modelFeature = 0;
108  tw->trace.c.trmFeature = j;
109  return true;
110  }
111  }
112  return false;
113 }
114 
115 /*
116 ================
117 CM_SetTrmEdgeSidedness
118 ================
119 */
120 #define CM_SetTrmEdgeSidedness( edge, bpl, epl, bitNum ) { \
121  if ( !(edge->sideSet & (1<<bitNum)) ) { \
122  float fl; \
123  fl = (bpl).PermutedInnerProduct( epl ); \
124  edge->side = (edge->side & ~(1<<bitNum)) | (FLOATSIGNBITSET(fl) << bitNum); \
125  edge->sideSet |= (1 << bitNum); \
126  } \
127 }
128 
129 /*
130 ================
131 CM_SetTrmPolygonSidedness
132 ================
133 */
134 #define CM_SetTrmPolygonSidedness( v, plane, bitNum ) { \
135  if ( !((v)->sideSet & (1<<bitNum)) ) { \
136  float fl; \
137  fl = plane.Distance( (v)->p ); \
138  /* cannot use float sign bit because it is undetermined when fl == 0.0f */ \
139  if ( fl < 0.0f ) { \
140  (v)->side |= (1 << bitNum); \
141  } \
142  else { \
143  (v)->side &= ~(1 << bitNum); \
144  } \
145  (v)->sideSet |= (1 << bitNum); \
146  } \
147 }
148 
149 /*
150 ================
151 idCollisionModelManagerLocal::TestTrmInPolygon
152 
153  returns true if the trm intersects the polygon
154 ================
155 */
157  int i, j, k, edgeNum, flip, trmEdgeNum, bitNum, bestPlane;
158  int sides[MAX_TRACEMODEL_VERTS];
159  float d, bestd;
160  cm_trmEdge_t *trmEdge;
161  cm_edge_t *edge;
162  cm_vertex_t *v, *v1, *v2;
163 
164  // if already checked this polygon
166  return false;
167  }
169 
170  // if this polygon does not have the right contents behind it
171  if ( !(p->contents & tw->contents) ) {
172  return false;
173  }
174 
175  // if the polygon bounds don't intersect the trace bounds
176  if ( !p->bounds.IntersectsBounds( tw->bounds ) ) {
177  return false;
178  }
179 
180  // bounds should cross polygon plane
181  switch( tw->bounds.PlaneSide( p->plane ) ) {
182  case PLANESIDE_CROSS:
183  break;
184  case PLANESIDE_FRONT:
185  if ( tw->model->isConvex ) {
186  tw->quickExit = true;
187  return true;
188  }
189  default:
190  return false;
191  }
192 
193  // if the trace model is convex
194  if ( tw->isConvex ) {
195  // test if any polygon vertices are inside the trm
196  for ( i = 0; i < p->numEdges; i++ ) {
197  edgeNum = p->edges[i];
198  edge = tw->model->edges + abs(edgeNum);
199  // if this edge is already tested
201  continue;
202  }
203 
204  for ( j = 0; j < 2; j++ ) {
205  v = &tw->model->vertices[edge->vertexNum[j]];
206  // if this vertex is already tested
208  continue;
209  }
210 
211  bestPlane = 0;
212  bestd = -idMath::INFINITY;
213  for ( k = 0; k < tw->numPolys; k++ ) {
214  d = tw->polys[k].plane.Distance( v->p );
215  if ( d >= 0.0f ) {
216  break;
217  }
218  if ( d > bestd ) {
219  bestd = d;
220  bestPlane = k;
221  }
222  }
223  if ( k >= tw->numPolys ) {
224  tw->trace.fraction = 0.0f;
226  tw->trace.c.normal = -tw->polys[bestPlane].plane.Normal();
227  tw->trace.c.dist = -tw->polys[bestPlane].plane.Dist();
228  tw->trace.c.contents = p->contents;
229  tw->trace.c.material = p->material;
230  tw->trace.c.point = v->p;
231  tw->trace.c.modelFeature = edge->vertexNum[j];
232  tw->trace.c.trmFeature = 0;
233  return true;
234  }
235  }
236  }
237  }
238 
239  for ( i = 0; i < p->numEdges; i++ ) {
240  edgeNum = p->edges[i];
241  edge = tw->model->edges + abs(edgeNum);
242  // reset sidedness cache if this is the first time we encounter this edge
244  edge->sideSet = 0;
245  }
246  // pluecker coordinate for edge
248  tw->model->vertices[edge->vertexNum[1]].p );
249  v = &tw->model->vertices[edge->vertexNum[INTSIGNBITSET(edgeNum)]];
250  // reset sidedness cache if this is the first time we encounter this vertex
252  v->sideSet = 0;
253  }
255  }
256 
257  // get side of polygon for each trm vertex
258  for ( i = 0; i < tw->numVerts; i++ ) {
259  d = p->plane.Distance( tw->vertices[i].p );
260  sides[i] = d < 0.0f ? -1 : 1;
261  }
262 
263  // test if any trm edges go through the polygon
264  for ( i = 1; i <= tw->numEdges; i++ ) {
265  // if the trm edge does not cross the polygon plane
266  if ( sides[tw->edges[i].vertexNum[0]] == sides[tw->edges[i].vertexNum[1]] ) {
267  continue;
268  }
269  // check from which side to which side the trm edge goes
270  flip = INTSIGNBITSET( sides[tw->edges[i].vertexNum[0]] );
271  // test if trm edge goes through the polygon between the polygon edges
272  for ( j = 0; j < p->numEdges; j++ ) {
273  edgeNum = p->edges[j];
274  edge = tw->model->edges + abs(edgeNum);
275 #if 1
276  CM_SetTrmEdgeSidedness( edge, tw->edges[i].pl, tw->polygonEdgePlueckerCache[j], i );
277  if ( INTSIGNBITSET(edgeNum) ^ ((edge->side >> i) & 1) ^ flip ) {
278  break;
279  }
280 #else
282  if ( flip ) {
283  d = -d;
284  }
285  if ( edgeNum > 0 ) {
286  if ( d <= 0.0f ) {
287  break;
288  }
289  }
290  else {
291  if ( d >= 0.0f ) {
292  break;
293  }
294  }
295 #endif
296  }
297  if ( j >= p->numEdges ) {
298  tw->trace.fraction = 0.0f;
299  tw->trace.c.type = CONTACT_EDGE;
300  tw->trace.c.normal = p->plane.Normal();
301  tw->trace.c.dist = p->plane.Dist();
302  tw->trace.c.contents = p->contents;
303  tw->trace.c.material = p->material;
304  tw->trace.c.point = tw->vertices[tw->edges[i].vertexNum[ !flip ]].p;
305  tw->trace.c.modelFeature = *reinterpret_cast<int *>(&p);
306  tw->trace.c.trmFeature = i;
307  return true;
308  }
309  }
310 
311  // test if any polygon edges go through the trm polygons
312  for ( i = 0; i < p->numEdges; i++ ) {
313  edgeNum = p->edges[i];
314  edge = tw->model->edges + abs(edgeNum);
316  continue;
317  }
319 
320  for ( j = 0; j < tw->numPolys; j++ ) {
321 #if 1
322  v1 = tw->model->vertices + edge->vertexNum[0];
323  CM_SetTrmPolygonSidedness( v1, tw->polys[j].plane, j );
324  v2 = tw->model->vertices + edge->vertexNum[1];
325  CM_SetTrmPolygonSidedness( v2, tw->polys[j].plane, j );
326  // if the polygon edge does not cross the trm polygon plane
327  if ( !(((v1->side ^ v2->side) >> j) & 1) ) {
328  continue;
329  }
330  flip = (v1->side >> j) & 1;
331 #else
332  float d1, d2;
333 
334  v1 = tw->model->vertices + edge->vertexNum[0];
335  d1 = tw->polys[j].plane.Distance( v1->p );
336  v2 = tw->model->vertices + edge->vertexNum[1];
337  d2 = tw->polys[j].plane.Distance( v2->p );
338  // if the polygon edge does not cross the trm polygon plane
339  if ( (d1 >= 0.0f && d2 >= 0.0f) || (d1 <= 0.0f && d2 <= 0.0f) ) {
340  continue;
341  }
342  flip = false;
343  if ( d1 < 0.0f ) {
344  flip = true;
345  }
346 #endif
347  // test if polygon edge goes through the trm polygon between the trm polygon edges
348  for ( k = 0; k < tw->polys[j].numEdges; k++ ) {
349  trmEdgeNum = tw->polys[j].edges[k];
350  trmEdge = tw->edges + abs(trmEdgeNum);
351 #if 1
352  bitNum = abs(trmEdgeNum);
353  CM_SetTrmEdgeSidedness( edge, trmEdge->pl, tw->polygonEdgePlueckerCache[i], bitNum );
354  if ( INTSIGNBITSET(trmEdgeNum) ^ ((edge->side >> bitNum) & 1) ^ flip ) {
355  break;
356  }
357 #else
358  d = trmEdge->pl.PermutedInnerProduct( tw->polygonEdgePlueckerCache[i] );
359  if ( flip ) {
360  d = -d;
361  }
362  if ( trmEdgeNum > 0 ) {
363  if ( d <= 0.0f ) {
364  break;
365  }
366  }
367  else {
368  if ( d >= 0.0f ) {
369  break;
370  }
371  }
372 #endif
373  }
374  if ( k >= tw->polys[j].numEdges ) {
375  tw->trace.fraction = 0.0f;
376  tw->trace.c.type = CONTACT_EDGE;
377  tw->trace.c.normal = -tw->polys[j].plane.Normal();
378  tw->trace.c.dist = -tw->polys[j].plane.Dist();
379  tw->trace.c.contents = p->contents;
380  tw->trace.c.material = p->material;
381  tw->trace.c.point = tw->model->vertices[edge->vertexNum[ !flip ]].p;
382  tw->trace.c.modelFeature = edgeNum;
383  tw->trace.c.trmFeature = j;
384  return true;
385  }
386  }
387  }
388  return false;
389 }
390 
391 /*
392 ================
393 idCollisionModelManagerLocal::PointNode
394 ================
395 */
397  cm_node_t *node;
398 
399  node = model->node;
400  while ( node->planeType != -1 ) {
401  if (p[node->planeType] > node->planeDist) {
402  node = node->children[0];
403  }
404  else {
405  node = node->children[1];
406  }
407 
408  assert( node != NULL );
409  }
410  return node;
411 }
412 
413 /*
414 ================
415 idCollisionModelManagerLocal::PointContents
416 ================
417 */
419  int i;
420  float d;
421  cm_node_t *node;
422  cm_brushRef_t *bref;
423  cm_brush_t *b;
424  idPlane *plane;
425 
427  for ( bref = node->brushes; bref; bref = bref->next ) {
428  b = bref->b;
429  // test if the point is within the brush bounds
430  for ( i = 0; i < 3; i++ ) {
431  if ( p[i] < b->bounds[0][i] ) {
432  break;
433  }
434  if ( p[i] > b->bounds[1][i] ) {
435  break;
436  }
437  }
438  if ( i < 3 ) {
439  continue;
440  }
441  // test if the point is inside the brush
442  plane = b->planes;
443  for ( i = 0; i < b->numPlanes; i++, plane++ ) {
444  d = plane->Distance( p );
445  if ( d >= 0 ) {
446  break;
447  }
448  }
449  if ( i >= b->numPlanes ) {
450  return b->contents;
451  }
452  }
453  return 0;
454 }
455 
456 /*
457 ==================
458 idCollisionModelManagerLocal::TransformedPointContents
459 ==================
460 */
461 int idCollisionModelManagerLocal::TransformedPointContents( const idVec3 &p, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis ) {
462  idVec3 p_l;
463 
464  // subtract origin offset
465  p_l = p - origin;
466  if ( modelAxis.IsRotated() ) {
467  p_l *= modelAxis;
468  }
469  return idCollisionModelManagerLocal::PointContents( p_l, model );
470 }
471 
472 
473 /*
474 ==================
475 idCollisionModelManagerLocal::ContentsTrm
476 ==================
477 */
479  const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
480  cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
481  int i;
482  bool model_rotated, trm_rotated;
483  idMat3 invModelAxis, tmpAxis;
484  idVec3 dir;
485  ALIGN16( cm_traceWork_t tw );
486 
487  // fast point case
488  if ( !trm || ( trm->bounds[1][0] - trm->bounds[0][0] <= 0.0f &&
489  trm->bounds[1][1] - trm->bounds[0][1] <= 0.0f &&
490  trm->bounds[1][2] - trm->bounds[0][2] <= 0.0f ) ) {
491 
492  results->c.contents = idCollisionModelManagerLocal::TransformedPointContents( start, model, modelOrigin, modelAxis );
493  results->fraction = ( results->c.contents == 0 );
494  results->endpos = start;
495  results->endAxis = trmAxis;
496 
497  return results->c.contents;
498  }
499 
501 
502  tw.trace.fraction = 1.0f;
503  tw.trace.c.contents = 0;
504  tw.trace.c.type = CONTACT_NONE;
505  tw.contents = contentMask;
506  tw.isConvex = true;
507  tw.rotation = false;
508  tw.positionTest = true;
509  tw.pointTrace = false;
510  tw.quickExit = false;
511  tw.numContacts = 0;
513  tw.start = start - modelOrigin;
514  tw.end = tw.start;
515 
516  model_rotated = modelAxis.IsRotated();
517  if ( model_rotated ) {
518  invModelAxis = modelAxis.Transpose();
519  }
520 
521  // setup trm structure
523 
524  trm_rotated = trmAxis.IsRotated();
525 
526  // calculate vertex positions
527  if ( trm_rotated ) {
528  for ( i = 0; i < tw.numVerts; i++ ) {
529  // rotate trm around the start position
530  tw.vertices[i].p *= trmAxis;
531  }
532  }
533  for ( i = 0; i < tw.numVerts; i++ ) {
534  // set trm at start position
535  tw.vertices[i].p += tw.start;
536  }
537  if ( model_rotated ) {
538  for ( i = 0; i < tw.numVerts; i++ ) {
539  // rotate trm around model instead of rotating the model
540  tw.vertices[i].p *= invModelAxis;
541  }
542  }
543 
544  // add offset to start point
545  if ( trm_rotated ) {
546  dir = trm->offset * trmAxis;
547  tw.start += dir;
548  tw.end += dir;
549  } else {
550  tw.start += trm->offset;
551  tw.end += trm->offset;
552  }
553  if ( model_rotated ) {
554  // rotate trace instead of model
555  tw.start *= invModelAxis;
556  tw.end *= invModelAxis;
557  }
558 
559 
560  // setup trm vertices
561  tw.size.Clear();
562  for ( i = 0; i < tw.numVerts; i++ ) {
563  // get axial trm size after rotations
564  tw.size.AddPoint( tw.vertices[i].p - tw.start );
565  }
566 
567  // setup trm edges
568  for ( i = 1; i <= tw.numEdges; i++ ) {
569  // edge start, end and pluecker coordinate
570  tw.edges[i].start = tw.vertices[tw.edges[i].vertexNum[0]].p;
571  tw.edges[i].end = tw.vertices[tw.edges[i].vertexNum[1]].p;
572  tw.edges[i].pl.FromLine( tw.edges[i].start, tw.edges[i].end );
573  }
574 
575  // setup trm polygons
576  if ( trm_rotated & model_rotated ) {
577  tmpAxis = trmAxis * invModelAxis;
578  for ( i = 0; i < tw.numPolys; i++ ) {
579  tw.polys[i].plane *= tmpAxis;
580  }
581  } else if ( trm_rotated ) {
582  for ( i = 0; i < tw.numPolys; i++ ) {
583  tw.polys[i].plane *= trmAxis;
584  }
585  } else if ( model_rotated ) {
586  for ( i = 0; i < tw.numPolys; i++ ) {
587  tw.polys[i].plane *= invModelAxis;
588  }
589  }
590  for ( i = 0; i < tw.numPolys; i++ ) {
591  tw.polys[i].plane.FitThroughPoint( tw.edges[abs(tw.polys[i].edges[0])].start );
592  }
593 
594  // bounds for full trace, a little bit larger for epsilons
595  for ( i = 0; i < 3; i++ ) {
596  if ( tw.start[i] < tw.end[i] ) {
597  tw.bounds[0][i] = tw.start[i] + tw.size[0][i] - CM_BOX_EPSILON;
598  tw.bounds[1][i] = tw.end[i] + tw.size[1][i] + CM_BOX_EPSILON;
599  } else {
600  tw.bounds[0][i] = tw.end[i] + tw.size[0][i] - CM_BOX_EPSILON;
601  tw.bounds[1][i] = tw.start[i] + tw.size[1][i] + CM_BOX_EPSILON;
602  }
603  if ( idMath::Fabs(tw.size[0][i]) > idMath::Fabs(tw.size[1][i]) ) {
604  tw.extents[i] = idMath::Fabs( tw.size[0][i] ) + CM_BOX_EPSILON;
605  } else {
606  tw.extents[i] = idMath::Fabs( tw.size[1][i] ) + CM_BOX_EPSILON;
607  }
608  }
609 
610  // trace through the model
612 
613  *results = tw.trace;
614  results->fraction = ( results->c.contents == 0 );
615  results->endpos = start;
616  results->endAxis = trmAxis;
617 
618  return results->c.contents;
619 }
620 
621 /*
622 ==================
623 idCollisionModelManagerLocal::Contents
624 ==================
625 */
627  const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
628  cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
629  trace_t results;
630 
631  if ( model < 0 || model > idCollisionModelManagerLocal::maxModels || model > MAX_SUBMODELS ) {
632  common->Printf("idCollisionModelManagerLocal::Contents: invalid model handle\n");
633  return 0;
634  }
636  common->Printf("idCollisionModelManagerLocal::Contents: invalid model\n");
637  return 0;
638  }
639 
640  return ContentsTrm( &results, start, trm, trmAxis, contentMask, model, modelOrigin, modelAxis );
641 }
void SetupTrm(cm_traceWork_t *tw, const idTraceModel *trm)
struct cm_node_s * children[2]
static const float INFINITY
Definition: Math.h:218
assert(prefInfo.fullscreenBtn)
const idVec3 & Normal(void) const
Definition: Plane.h:239
unsigned long sideSet
const GLdouble * v
Definition: glext.h:2936
idMat3 Transpose(void) const
Definition: Matrix.h:677
float Distance(const idVec3 &v) const
Definition: Plane.h:324
idPluecker polygonEdgePlueckerCache[CM_MAX_POLYGON_EDGES]
#define CM_BOX_EPSILON
bool TestTrmVertsInBrush(cm_traceWork_t *tw, cm_brush_t *b)
int PointContents(const idVec3 p, cmHandle_t model)
Definition: Vector.h:316
const idMaterial * material
contactType_t type
int ContentsTrm(trace_t *results, const idVec3 &start, const idTraceModel *trm, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
void Clear(void)
Definition: Bounds.h:201
int cmHandle_t
bool IsRotated(void) const
Definition: Matrix.h:624
int i
Definition: process.py:33
contactInfo_t c
void FromLine(const idVec3 &start, const idVec3 &end)
Definition: Pluecker.h:249
float fraction
idVec3 endpos
#define PLANESIDE_FRONT
Definition: Plane.h:53
idVec3 offset
Definition: TraceModel.h:93
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
GLfloat GLfloat GLfloat v2
Definition: glext.h:3608
#define MAX_SUBMODELS
const idMaterial * material
cm_node_t * node
cm_vertex_t * vertices
const idMaterial * material
int TransformedPointContents(const idVec3 &p, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis)
cm_trmEdge_t edges[MAX_TRACEMODEL_EDGES+1]
static float Fabs(float f)
Definition: Math.h:779
idCommon * common
Definition: Common.cpp:206
void TraceThroughModel(cm_traceWork_t *tw)
#define NULL
Definition: Lib.h:88
unsigned long sideSet
unsigned long side
cm_brushRef_t * brushes
Definition: Plane.h:71
idMat3 endAxis
float PermutedInnerProduct(const idPluecker &a) const
Definition: Pluecker.h:316
bool TestTrmInPolygon(cm_traceWork_t *tw, cm_polygon_t *p)
virtual void Printf(const char *fmt,...) id_attribute((format(printf
unsigned long side
GLfloat GLfloat v1
Definition: glext.h:3607
cm_edge_t * edges
GLubyte GLubyte b
Definition: glext.h:4662
Definition: Matrix.h:333
#define INTSIGNBITSET(i)
Definition: Math.h:71
tuple f
Definition: idal.py:89
#define CM_SetTrmEdgeSidedness(edge, bpl, epl, bitNum)
#define CM_SetTrmPolygonSidedness(v, plane, bitNum)
bool IntersectsBounds(const idBounds &a) const
Definition: Bounds.h:361
struct cm_brushRef_s * next
int Contents(const idVec3 &start, const idTraceModel *trm, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
int edges[MAX_TRACEMODEL_POLYEDGES]
#define MAX_TRACEMODEL_VERTS
Definition: TraceModel.h:63
#define PLANESIDE_CROSS
Definition: Plane.h:56
GLint j
Definition: qgl.h:264
cm_trmPolygon_t polys[MAX_TRACEMODEL_POLYS]
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Bounds.cpp:108
GLfloat GLfloat p
Definition: glext.h:4674
cm_node_t * PointNode(const idVec3 &p, cm_model_t *model)
idBounds bounds
Definition: TraceModel.h:94
GLuint start
Definition: glext.h:2845
float Dist(void) const
Definition: Plane.h:271
cm_trmVertex_t vertices[MAX_TRACEMODEL_VERTS]
void FitThroughPoint(const idVec3 &p)
Definition: Plane.h:297