Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
colmathaabtri.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WWMath *
24 * *
25 * $Archive:: /Commando/Code/wwmath/colmathaabtri.cpp $*
26 * *
27 * Author:: Greg Hjelstrom *
28 * *
29 * $Modtime:: 1/15/02 2:46p $*
30 * *
31 * $Revision:: 19 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * aabtri_separation_test -- test the projected extents for separation *
36 * aabtri_check_axis -- project the aab and tri onto an arbitrary axis *
37 * aabtri_check_cross_axis -- projects aab and tri onto a "cross" axis *
38 * aabtri_check_basis_axis -- projects the aab and tri onto a basis axis *
39 * aabtri_check_normal_axis -- project the box and tri onto the tri-normal *
40 * eval_side -- returns -1,0,+1 depending on the sign of val and side *
41 * aabtri_compute_contact_normal -- computes the normal of the collision *
42 * CollisionMath::Collide -- collide an aabox into a triangle *
43 * aabtri_intersect_cross_axis -- intersection check for a "cross-product" axis *
44 * aabtri_intersect_basis_axis -- intersection check for a basis axis *
45 * aabtri_intersect_normal_axis -- intersection check for the triangle normal *
46 * CollisionMath::Intersection_Test -- Intersection check for an AABox and a triangle *
47 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
48
49
50#include "colmath.h"
51#include "aabox.h"
52#include "tri.h"
53#include "wwdebug.h"
54
55
56/*
57** Separating Axes have to be rejected if their length is smaller than some epsilon.
58** Otherwise, erroneous results can be reported.
59*/
60#define AXISLEN_EPSILON2 WWMATH_EPSILON * WWMATH_EPSILON // squared length of a separating axis must be larger than this
61
62
63/*
64** Axes used in Box-Tri intersection tests
65** The axes of the box are A0,A1,A2. N is the normal of the triangle,
66** E0,E1,E2 are direction vectors for the edges of the triangle.
67** (the box axes are labeled A0,A1,A2 as a holdover from the obbox-obbox
68** collision code which this was derived from where there are two boxes
69** A and B)
70*/
71enum
72{
74 AXIS_N, // normal of the triangle
75 AXIS_A0, // first basis vector of the box
76 AXIS_A1, // second basis vector of the box
77 AXIS_A2, // third basis vector of the box
78
79 AXIS_A0E0, // box0 x edge0...
88};
89
90
91/******************************************************************************************
92
93 AABox->Triangle collision
94
95 This code is basically a special-case optimization of the OBBox->Triangle collision
96 detection code. There are many dot and cross products that can be simplified due
97 to the fact that we know the axes of the boxes are always the same and are aligned
98 with the world coordinate axes.
99
100 Each axis test will use the following logic:
101 Project D onto the axis being used, it is the separation distance. If the
102 projection of the extent of the box + the projection of the extent of the
103 tri is greater than D*axis then the two intersect
104
105 March 13, 2000 - Modified these routines to all use a static instance of
106 the BTCollisionStruct. The compiler was generating lots of extra code for the
107 constructor of this object and testing determined that re-using the same static
108 struct was slightly faster anyway.
109 NOTE: this makes the code not Thread-Safe!!!!
110
111
112******************************************************************************************/
113
114/*
115** BoxTriColStruct
116** Scratchpad variables for the AABox-Triangle collision detection functions. One instance
117** of this structure will be used for all of the local variables and its pointer will be
118** handed of to various inline functions for the axis tests.
119** Note that much of the code needs the un-normalized triangle normal. For this reason,
120** I have to compute N rather than copying it from the triangle. (commenting this to
121** avoid re-generating a difficult to find bug that I had)
122*/
124{
126
127 void Init(const AABoxClass &box,const Vector3 &move,const TriClass &tri,const Vector3 &trimove)
128 {
129 StartBad = true; // true until an axis clears it
130 MaxFrac = -0.01f; // maximum move allowed so far
131 AxisId = INTERSECTION; // axis that allowed the longest move
132 Point = 0; // index of triangle point that was closest to the box
133 Side = 0; // side of the interval
134 Box = &box;
135 Tri = &tri;
136 BoxMove = &move;
137 TriMove = &trimove;
138
139 Vector3::Subtract(*tri.V[0],box.Center,&D); // vector from center of box to vertex 0
140 Vector3::Subtract(move,trimove,&Move); // move vector relative to stationary triangle
141
142 Vector3::Subtract(*tri.V[1],*tri.V[0],&E[0]);
143 Vector3::Subtract(*tri.V[2],*tri.V[0],&E[1]);
144 Vector3::Subtract(E[1],E[0],&E[2]);
145
146 Vector3::Cross_Product(E[0],E[1],&N);
147 }
148
149 bool StartBad; // Inital configuration is intersecting?
150 float MaxFrac; // Longest move allowed so far
151
152 int AxisId; // Last separating axis
153 int Side; // which side of the interval
154 int Point; // Index of the "closest" triangle point (or one of them)
155
156 int TestAxisId; // Axis 'id' we're working on
157 int TestSide; // Was the axis we're working on flipped
158 int TestPoint; // Index of the closest vertex
159 Vector3 TestAxis; // Axis we're working on
160
161 Vector3 D; // Vector from the center of the box to v0
162 Vector3 Move; // Move vector relative to stationary triangle
163 float AE[3][3]; // Dot products of the Basis vectors and edges
164 float AN[3]; // Dot products of the Basis vectors and the normal
165 Vector3 AxE[3][3]; // Cross products of the Basis vectors and edges
166
167 Vector3 E[3]; // edge vectors for the triangle
168 Vector3 N; // normal (NOT normalized!!!)
169 Vector3 FinalD; // Vector from center of box to v0 at end of move
170
172 const TriClass * Tri;
175
176private:
177
178 // not implemented
180 BTCollisionStruct & operator = (const BTCollisionStruct &);
181};
182
183static BTCollisionStruct CollisionContext;
184
185/***********************************************************************************************
186 * aabtri_separation_test -- test the projected extents for separation *
187 * *
188 * Once the extents are projected onto the axis, this function contains *
189 * the logic that determines the allowed fraction. *
190 * *
191 * INPUT: *
192 * *
193 * OUTPUT: *
194 * *
195 * WARNINGS: *
196 * *
197 * HISTORY: *
198 * 4/8/99 GTH : Created. *
199 * 7/12/99 GTH : Converted original OBBox code to AABox *
200 *=============================================================================================*/
201static inline bool aabtri_separation_test
202(
203 float lp,float leb0,float leb1
204)
205{
206 /*
207 ** - If (I'm no more than 'EPSILON' embedded in the wall)
208 ** - not startbad
209 ** - If (I'm moving towards)
210 ** - fraction = How far I can move before embedding (can be negative if started embedded)
211 ** - If (I can take entire move)
212 ** - accept entire move
213 ** - Else If (I can move more than I could have before; *negative always fails!)
214 ** - update fraction
215 ** - Else
216 ** - Accept entire move since I'm not moving towards
217 */
218 float eps = 0.0f;
219 if (lp - leb0 <= 0.0f) {
220 eps = COLLISION_EPSILON * CollisionContext.TestAxis.Length(); // trying to only compute epsilon if I have to
221 }
222
223 if (lp - leb0 > -eps) {
224 CollisionContext.StartBad = false;
225 if (leb1 - leb0 > 0.0f) {
226 float frac = (lp-leb0)/(leb1-leb0);
227 if (frac >= 1.0f) {
228 /* moving toward but not hitting triangle */
229 CollisionContext.AxisId = CollisionContext.TestAxisId;
230 CollisionContext.MaxFrac = 1.0f;
231 return true;
232 } else {
233 /* moving toward, hitting triangle */
234 if (frac > CollisionContext.MaxFrac) {
235 CollisionContext.MaxFrac = frac;
236 CollisionContext.AxisId = CollisionContext.TestAxisId;
237 CollisionContext.Side = CollisionContext.TestSide;
238 CollisionContext.Point = CollisionContext.TestPoint;
239 }
240 }
241 } else {
242 /* moving away or not moving */
243 CollisionContext.AxisId = CollisionContext.TestAxisId;
244 CollisionContext.MaxFrac = 1.0f;
245 return true;
246 }
247 }
248 return false;
249}
250
251
252/***********************************************************************************************
253 * aabtri_check_axis -- project the aab and tri onto an arbitrary axis *
254 * *
255 * projects the box and the triangle onto the given axis and calls *
256 * obbtri_separation_test. return true if separation was detected *
257 * *
258 * INPUT: *
259 * *
260 * OUTPUT: *
261 * *
262 * WARNINGS: *
263 * *
264 * HISTORY: *
265 * 4/8/99 GTH : Created. *
266 * 7/12/99 GTH : converted to AABox *
267 *=============================================================================================*/
268static inline bool aabtri_check_axis(void)
269{
270 float dist; // separation along the axis
271 float axismove; // size of the move along the axis.
272 float leb0; // initial coordinate of the leading edge of the box
273 float leb1; // final coordinate of the leading edge of the box
274 float lp; // leading edge of the polygon.
275 float tmp; // temporary
276
277 dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
278 axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
279
280 // I want the axis centered at the box, pointing towards the triangle
281 if (dist < 0) {
282 dist = -dist;
283 axismove = -axismove;
284 CollisionContext.TestAxis = -CollisionContext.TestAxis;
285 CollisionContext.TestSide = -1.0f;
286 } else {
287 CollisionContext.TestSide = 1.0f;
288 }
289
290 // compute coordinates of the leading edge of the box at t0 and t1
291 leb0 = CollisionContext.Box->Extent.X * WWMath::Fabs(CollisionContext.TestAxis.X) +
292 CollisionContext.Box->Extent.Y * WWMath::Fabs(CollisionContext.TestAxis.Y) +
293 CollisionContext.Box->Extent.Z * WWMath::Fabs(CollisionContext.TestAxis.Z);
294 leb1 = leb0 + axismove;
295
296 // compute coordinate of "leading edge of the triangle" relative to the box center.
297 lp = 0;
298 tmp = Vector3::Dot_Product(CollisionContext.E[0],CollisionContext.TestAxis); if (tmp < lp) lp = tmp;
299 tmp = Vector3::Dot_Product(CollisionContext.E[1],CollisionContext.TestAxis); if (tmp < lp) lp = tmp;
300 lp = dist + lp;
301
302 return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
303}
304
305
306/***********************************************************************************************
307 * aabtri_check_cross_axis -- projects aab and tri onto a "cross" axis *
308 * *
309 * Assumes that the axis given is one generated from a cross product of one of the edge and *
310 * basis vectors. In this case, the box extent can be optimized and only two triangle verts *
311 * need to be checked. *
312 * *
313 * INPUT: *
314 * *
315 * OUTPUT: *
316 * *
317 * WARNINGS: *
318 * *
319 * HISTORY: *
320 * 4/8/99 GTH : Created. *
321 *=============================================================================================*/
322static inline bool aabtri_check_cross_axis
323(
324 float dp,
325 int dpi,
326 float leb0
327)
328{
329 float p0; // distance from box center to vertex 0
330 float axismove; // size of the move along the axis.
331 float leb1; // final coordinate of the leading edge of the box
332 float lp; // leading edge of the polygon.
333
334 p0 = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
335 axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
336
337 // I want the axis centered at the box, pointing towards the triangle
338 if (p0 < 0) {
339 p0 = -p0;
340 axismove = -axismove;
341 dp = -dp;
342 CollisionContext.TestAxis = -CollisionContext.TestAxis;
343 CollisionContext.TestSide = -1.0f;
344 } else {
345 CollisionContext.TestSide = 1.0f;
346 }
347
348 // compute coordinates of the leading edge of the box at t1
349 leb1 = leb0 + axismove;
350
351 // compute coordinate of "leading edge of the triangle" relative to the box center.
352 lp = 0; CollisionContext.TestPoint = 0;
353 if (dp < 0) { lp = dp; CollisionContext.TestPoint = dpi; }
354 lp = p0 + lp;
355
356 return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
357}
358
359
360/***********************************************************************************************
361 * aabtri_check_basis_axis -- projects the aab and tri onto a basis axis *
362 * *
363 * Projects the box and triangle onto an axis that is assumed to be a basis *
364 * vector from the box. In this case, we can skip a dot-product and use the *
365 * corresponding extent of the box (which is passed in as leb0). *
366 * *
367 * INPUT: *
368 * *
369 * OUTPUT: *
370 * *
371 * WARNINGS: *
372 * *
373 * HISTORY: *
374 * 4/8/99 GTH : Created. *
375 *=============================================================================================*/
376static inline bool aabtri_check_basis_axis
377(
378 float leb0,
379 float dp1,
380 float dp2
381)
382{
383 float dist; // separation along the axis
384 float axismove; // size of the move along the axis.
385 float leb1; // final coordinate of the leading edge of the box
386 float lp; // leading edge of the polygon.
387
388 dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
389 axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
390
391 // we want the axis centered at the box, pointing towards the triangle
392 if (dist < 0) {
393 dist = -dist;
394 axismove = -axismove;
395 dp1 = -dp1;
396 dp2 = -dp2;
397 CollisionContext.TestAxis = -CollisionContext.TestAxis;
398 CollisionContext.TestSide = -1.0f;
399 } else {
400 CollisionContext.TestSide = 1.0f;
401 }
402
403 // this is the "optimization", leb0 = one of the extents
404 leb1 = leb0 + axismove;
405
406 // compute coordinate of "leading edge of the polygon" relative to the box center.
407 lp = 0; CollisionContext.TestPoint = 0;
408 if (dp1 < lp) { lp = dp1; CollisionContext.TestPoint = 1; }
409 if (dp2 < lp) { lp = dp2; CollisionContext.TestPoint = 2; }
410 lp = dist + lp;
411
412 return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
413}
414
415
416/***********************************************************************************************
417 * aabtri_check_normal_axis -- project the box and tri onto the tri-normal *
418 * *
419 * Projects the box and triangle onto an axis that is assumed to be the normal *
420 * vector from the triangle. In this case, the triangle extents are zero. *
421 * *
422 * INPUT: *
423 * *
424 * OUTPUT: *
425 * *
426 * WARNINGS: *
427 * *
428 * HISTORY: *
429 * 4/8/99 GTH : Created. *
430 *=============================================================================================*/
431static inline bool aabtri_check_normal_axis(void)
432{
433 float dist; // separation along the axis
434 float axismove; // size of the move along the axis.
435 float leb0; // initial coordinate of the leading edge of the box
436 float leb1; // final coordinate of the leading edge of the box
437 float lp; // leading edge of the polygon.
438
439 dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
440 axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
441
442 // we want the axis centered at the box, pointing towards the triangle
443 if (dist < 0) {
444 dist = -dist;
445 axismove = -axismove;
446 CollisionContext.TestAxis = -CollisionContext.TestAxis;
447 CollisionContext.TestSide = -1.0f;
448 } else {
449 CollisionContext.TestSide = 1.0f;
450 }
451
452 leb0 = CollisionContext.Box->Extent.X * WWMath::Fabs(CollisionContext.AN[0]) +
453 CollisionContext.Box->Extent.Y * WWMath::Fabs(CollisionContext.AN[1]) +
454 CollisionContext.Box->Extent.Z * WWMath::Fabs(CollisionContext.AN[2]);
455 leb1 = leb0 + axismove;
456 CollisionContext.TestPoint = 0;
457 lp = dist; // this is the "optimization", don't have to find lp
458
459 return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
460}
461
462/***********************************************************************************************
463 * eval_side -- returns -1,0,+1 depending on the sign of val and side *
464 * *
465 * INPUT: *
466 * *
467 * OUTPUT: *
468 * *
469 * WARNINGS: *
470 * *
471 * HISTORY: *
472 * 4/8/99 GTH : Created. *
473 *=============================================================================================*/
474static inline float eval_side(float val,int side)
475{
476 if (val > 0.0f) {
477 return side;
478 } else if (val < 0.0f) {
479 return -side;
480 } else {
481 return 0.0f;
482 }
483}
484
485/***********************************************************************************************
486 * aabtri_compute_contact_normal -- computes the normal of the collision *
487 * *
488 * INPUT: *
489 * *
490 * OUTPUT: *
491 * *
492 * WARNINGS: *
493 * *
494 * HISTORY: *
495 * 4/8/99 GTH : Created. *
496 *=============================================================================================*/
497static inline void aabtri_compute_contact_normal
498(
499 Vector3 & set_norm
500)
501{
502#if 1
503 switch(CollisionContext.AxisId)
504 {
505 case INTERSECTION:
506 set_norm = CollisionContext.N;
507 set_norm.Normalize();
508 break;
509 case AXIS_N:
510 set_norm = -CollisionContext.Side * CollisionContext.N;
511 set_norm.Normalize();
512 break;
513 case AXIS_A0:
514 set_norm = -CollisionContext.Side * Vector3(1.0f,0.0f,0.0f);
515 break;
516 case AXIS_A1:
517 set_norm = -CollisionContext.Side * Vector3(0.0f,1.0f,0.0f);
518 break;
519 case AXIS_A2:
520 set_norm = -CollisionContext.Side * Vector3(0.0f,0.0f,1.0f);
521 break;
522 case AXIS_A0E0:
523 set_norm = -CollisionContext.Side * CollisionContext.AxE[0][0];
524 set_norm.Normalize();
525 break;
526 case AXIS_A1E0:
527 set_norm = -CollisionContext.Side * CollisionContext.AxE[1][0];
528 set_norm.Normalize();
529 break;
530 case AXIS_A2E0:
531 set_norm = -CollisionContext.Side * CollisionContext.AxE[2][0];
532 set_norm.Normalize();
533 break;
534 case AXIS_A0E1:
535 set_norm = -CollisionContext.Side * CollisionContext.AxE[0][1];
536 set_norm.Normalize();
537 break;
538 case AXIS_A1E1:
539 set_norm = -CollisionContext.Side * CollisionContext.AxE[1][1];
540 set_norm.Normalize();
541 break;
542 case AXIS_A2E1:
543 set_norm = -CollisionContext.Side * CollisionContext.AxE[2][1];
544 set_norm.Normalize();
545 break;
546 case AXIS_A0E2:
547 set_norm = -CollisionContext.Side * CollisionContext.AxE[0][2];
548 set_norm.Normalize();
549 break;
550 case AXIS_A1E2:
551 set_norm = -CollisionContext.Side * CollisionContext.AxE[1][2];
552 set_norm.Normalize();
553 break;
554 case AXIS_A2E2:
555 set_norm = -CollisionContext.Side * CollisionContext.AxE[2][2];
556 set_norm.Normalize();
557 break;
558 }
559
560 WWASSERT(set_norm.Length2() > 0.0f);
561
562#else
563 set_norm = *CollisionContext.N;
564 set_norm.Normalize();
565 if (Vector3::Dot_Product(set_norm,CollisionContext.Move) > 0.0f) {
566 set_norm = -(set_norm);
567 }
568#endif
569}
570
571inline void VERIFY_CROSS(const Vector3 & a, const Vector3 & b,const Vector3 & cross)
572{
573#ifdef WWDEBUG
574 Vector3 tmp_cross;
575 Vector3::Cross_Product(a,b,&tmp_cross);
576 Vector3 diff = cross - tmp_cross;
577 WWASSERT(WWMath::Fabs(diff.Length()) < 0.0001f);
578#endif
579}
580
581/***********************************************************************************************
582 * CollisionMath::Collide -- collide an aabox into a triangle *
583 * *
584 * INPUT: *
585 * *
586 * OUTPUT: *
587 * *
588 * WARNINGS: *
589 * *
590 * HISTORY: *
591 * 4/8/99 GTH : Created. *
592 *=============================================================================================*/
594(
595 const AABoxClass & box,
596 const Vector3 & move,
597 const TriClass & tri,
598 CastResultStruct * result
599)
600{
602
603 float dp,leb0;
604
605 CollisionContext.Init(box,move,tri,Vector3(0,0,0));
606
607 /*
608 ** AXIS_N
609 */
610 CollisionContext.TestAxis = CollisionContext.N;
611 CollisionContext.TestAxisId = AXIS_N;
612 CollisionContext.AN[0] = CollisionContext.N.X;
613 CollisionContext.AN[1] = CollisionContext.N.Y;
614 CollisionContext.AN[2] = CollisionContext.N.Z;
615 if (aabtri_check_normal_axis()) goto exit;
616
617 /*
618 ** AXIS_A0
619 */
620 CollisionContext.TestAxis.Set(1,0,0);
621 CollisionContext.TestAxisId = AXIS_A0;
622 CollisionContext.AE[0][0] = CollisionContext.E[0].X;
623 CollisionContext.AE[0][1] = CollisionContext.E[1].X;
624 if (aabtri_check_basis_axis(box.Extent.X,CollisionContext.AE[0][0],CollisionContext.AE[0][1])) goto exit;
625
626 /*
627 ** AXIS_A1
628 */
629 CollisionContext.TestAxis.Set(0,1,0);
630 CollisionContext.TestAxisId = AXIS_A1;
631 CollisionContext.AE[1][0] = CollisionContext.E[0].Y;
632 CollisionContext.AE[1][1] = CollisionContext.E[1].Y;
633 if (aabtri_check_basis_axis(box.Extent.Y,CollisionContext.AE[1][0],CollisionContext.AE[1][1])) goto exit;
634
635 /*
636 ** AXIS_A2
637 */
638 CollisionContext.TestAxis.Set(0,0,1);
639 CollisionContext.TestAxisId = AXIS_A2;
640 CollisionContext.AE[2][0] = CollisionContext.E[0].Z;
641 CollisionContext.AE[2][1] = CollisionContext.E[1].Z;
642 if (aabtri_check_basis_axis(box.Extent.Z,CollisionContext.AE[2][0],CollisionContext.AE[2][1])) goto exit;
643
644 /*
645 ** AXIS_A0xE0
646 */
647 CollisionContext.AxE[0][0].Set(0,-CollisionContext.E[0].Z,CollisionContext.E[0].Y);
648 VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[0],CollisionContext.AxE[0][0]);
649 CollisionContext.TestAxis = CollisionContext.AxE[0][0];
650 CollisionContext.TestAxisId = AXIS_A0E0;
651 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
652 dp = CollisionContext.AN[0];
653 leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][0]);
654 if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
655 }
656
657 /*
658 ** AXIS_A0xE1
659 */
660 CollisionContext.AxE[0][1].Set(0,-CollisionContext.E[1].Z,CollisionContext.E[1].Y);
661 VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[1],CollisionContext.AxE[0][1]);
662 CollisionContext.TestAxis = CollisionContext.AxE[0][1];
663 CollisionContext.TestAxisId = AXIS_A0E1;
664 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
665 dp = -CollisionContext.AN[0];
666 leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][1]);
667 if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
668 }
669
670 /*
671 ** AXIS_A0xE2
672 */
673 CollisionContext.AE[0][2] = CollisionContext.E[2].X;
674 CollisionContext.AE[1][2] = CollisionContext.E[2].Y;
675 CollisionContext.AE[2][2] = CollisionContext.E[2].Z;
676
677 CollisionContext.AxE[0][2].Set(0,-CollisionContext.E[2].Z,CollisionContext.E[2].Y);
678 VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[2],CollisionContext.AxE[0][2]);
679 CollisionContext.TestAxis = CollisionContext.AxE[0][2];
680 CollisionContext.TestAxisId = AXIS_A0E2;
681
682 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
683 dp = -CollisionContext.AN[0];
684 leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][2]);
685 if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
686 }
687
688 /*
689 ** AXIS_A1xE0
690 */
691 CollisionContext.AxE[1][0].Set(CollisionContext.E[0].Z,0,-CollisionContext.E[0].X);
692 VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[0],CollisionContext.AxE[1][0]);
693 CollisionContext.TestAxis = CollisionContext.AxE[1][0];
694 CollisionContext.TestAxisId = AXIS_A1E0;
695 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
696 dp = CollisionContext.AN[1];
697 leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][0]);
698 if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
699 }
700
701 /*
702 ** AXIS_A1xE1
703 */
704 CollisionContext.AxE[1][1].Set(CollisionContext.E[1].Z,0,-CollisionContext.E[1].X);
705 VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[1],CollisionContext.AxE[1][1]);
706 CollisionContext.TestAxis = CollisionContext.AxE[1][1];
707 CollisionContext.TestAxisId = AXIS_A1E1;
708 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
709 dp = -CollisionContext.AN[1];
710 leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][1]);
711 if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
712 }
713
714 /*
715 ** AXIS_A1xE2
716 */
717 CollisionContext.AxE[1][2].Set(CollisionContext.E[2].Z,0,-CollisionContext.E[2].X);
718 VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[2],CollisionContext.AxE[1][2]);
719 CollisionContext.TestAxis = CollisionContext.AxE[1][2];
720 CollisionContext.TestAxisId = AXIS_A1E2;
721 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
722 dp = -CollisionContext.AN[1];
723 leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][2]);
724 if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
725 }
726
727 /*
728 ** AXIS_A2xE0
729 */
730 CollisionContext.AxE[2][0].Set(-CollisionContext.E[0].Y,CollisionContext.E[0].X,0);
731 VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[0],CollisionContext.AxE[2][0]);
732 CollisionContext.TestAxis = CollisionContext.AxE[2][0];
733 CollisionContext.TestAxisId = AXIS_A2E0;
734 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
735 dp = CollisionContext.AN[2];
736 leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][0]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][0]);
737 if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
738 }
739
740 /*
741 ** AXIS_A2xE1
742 */
743 CollisionContext.AxE[2][1].Set(-CollisionContext.E[1].Y,CollisionContext.E[1].X,0);
744 VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[1],CollisionContext.AxE[2][1]);
745 CollisionContext.TestAxis = CollisionContext.AxE[2][1];
746 CollisionContext.TestAxisId = AXIS_A2E1;
747 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
748 dp = -CollisionContext.AN[2];
749 leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][1]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][1]);
750 if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
751 }
752
753 /*
754 ** AXIS_A2xE2
755 */
756 CollisionContext.AxE[2][2].Set(-CollisionContext.E[2].Y,CollisionContext.E[2].X,0);
757 VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[2],CollisionContext.AxE[2][2]);
758 CollisionContext.TestAxis = CollisionContext.AxE[2][2];
759 CollisionContext.TestAxisId = AXIS_A2E2;
760 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
761 dp = -CollisionContext.AN[2];
762 leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][2]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][2]);
763 if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
764 }
765
766 /*
767 ** Last ditch effort, check an axis based on the move vector
768 */
769 if (!CollisionContext.StartBad) {
770 CollisionContext.TestPoint = CollisionContext.Point;
771 CollisionContext.TestAxisId = CollisionContext.AxisId;
772
773 CollisionContext.TestAxis.Set(0,-CollisionContext.Move.Z,CollisionContext.Move.Y); // A0 X Move
774 VERIFY_CROSS(Vector3(1,0,0),CollisionContext.Move,CollisionContext.TestAxis);
775 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
776 if (aabtri_check_axis()) goto exit;
777 }
778 CollisionContext.TestAxis.Set(CollisionContext.Move.Z,0,-CollisionContext.Move.X); // A1 X Move
779 VERIFY_CROSS(Vector3(0,1,0),CollisionContext.Move,CollisionContext.TestAxis);
780 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
781 if (aabtri_check_axis()) goto exit;
782 }
783 CollisionContext.TestAxis.Set(-CollisionContext.Move.Y,CollisionContext.Move.X,0); // A2 X Move
784 VERIFY_CROSS(Vector3(0,0,1),CollisionContext.Move,CollisionContext.TestAxis);
785 if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
786 if (aabtri_check_axis()) goto exit;
787 }
788 }
789
790exit:
791
792 /*
793 ** If MaxFrac is less than zero, clamp it to zero. Negative fractions can
794 ** leak through this routine due to the epsilon in the separation test.
795 */
796 if (CollisionContext.MaxFrac < 0.0f) {
797 CollisionContext.MaxFrac = 0.0f;
798 }
799
800 /*
801 ** If the triangle and box are intersecting before the move, return that
802 ** result.
803 */
804 if (CollisionContext.StartBad) {
805 result->StartBad = true;
806 result->Fraction = 0.0f;
807 result->Normal = *tri.N;
809 return true;
810 }
811
812 /*
813 ** If the fraction allowed is basically equal to the fraction allowed by
814 ** another polygon, try to pick the polygon which is least "edge-on" to the
815 ** move.
816 */
817 if ((CollisionContext.MaxFrac <= result->Fraction) && (CollisionContext.MaxFrac < 1.0f)) {
818
819 /*
820 ** Reflect the normal if it is pointing the same way as our move
821 ** (probably hitting the back side of a polygon)
822 */
823 Vector3 tmp_norm(0.0f,0.0f,0.0f);
824 aabtri_compute_contact_normal(tmp_norm);
825// if (Vector3::Dot_Product(tmp_norm,move) > 0.0f) {
826// tmp_norm = -tmp_norm;
827// }
828
829 /*
830 ** If this polygon cuts off more of the move -OR- this polygon cuts
831 ** of the same amount but has a "better" normal, then use this normal
832 */
833 if ( (WWMath::Fabs(CollisionContext.MaxFrac - result->Fraction) > WWMATH_EPSILON) ||
834 (Vector3::Dot_Product(tmp_norm,move) < Vector3::Dot_Product(result->Normal,move)))
835 {
836 result->Normal = tmp_norm;
837 WWASSERT(WWMath::Fabs(result->Normal.Length() - 1.0f) < WWMATH_EPSILON);
838 }
839
840 result->Fraction = CollisionContext.MaxFrac;
841
843 return true;
844 }
845
846 return false;
847}
848
849
850
851/*
852** AABTIntersectStruct
853** Scratchpad variables for the AABox-Triangle intersection functions. One instance
854** of this structure will be used for all of the local variables and its pointer will be
855** handed of to various inline functions for the axis tests.
856** Note that much of the code needs the un-normalized triangle normal. For this reason,
857** I have to compute N rather than copying it from the triangle. (commenting this to
858** avoid re-generating a difficult to find bug that I had)
859*/
861{
863 Box(NULL),
864 Tri(NULL)
865 {
866 }
867
868 void Init(const AABoxClass &box,const TriClass &tri)
869 {
870 Box = &box;
871 Tri = &tri;
872 Vector3::Subtract(*tri.V[0],box.Center,&D); // vector from center of box to vertex 0
873 Vector3::Subtract(*tri.V[1],*tri.V[0],&E[0]);
874 Vector3::Subtract(*tri.V[2],*tri.V[0],&E[1]);
875 Vector3::Subtract(E[1],E[0],&E[2]);
876
877 Vector3::Cross_Product(E[0],E[1],&N);
878 }
879
880
881 Vector3 D; // Vector from the center of the box to v0
882 float AE[3][3]; // Dot products of the Basis vectors and edges
883 float AN[3]; // Dot products of the Basis vectors and the normal
884 Vector3 AxE[3][3]; // Cross produts of the Basis vectors and edges
885
886 Vector3 E[3]; // edge vectors for the triangle
887 Vector3 N; // normal (NOT normalized!!!)
888
890 const TriClass * Tri;
891
892private:
893
894 // not implemented
896 AABTIntersectStruct & operator = (const AABTIntersectStruct &);
897};
898
899static AABTIntersectStruct IntersectContext;
900
901
902/***********************************************************************************************
903 * aabtri_intersect_cross_axis -- intersection check for a "cross-product" axis *
904 * *
905 * axis being checked is a cross product between a triangle edge and a box basis vector *
906 * *
907 * INPUT: *
908 * *
909 * OUTPUT: *
910 * *
911 * WARNINGS: *
912 * *
913 * HISTORY: *
914 * 5/4/99 GTH : Created. *
915 *=============================================================================================*/
916static inline bool aabtri_intersect_cross_axis
917(
918 Vector3 & axis,
919 float dp,
920 float leb0
921)
922{
923 float p0; // distance from box center to vertex 0
924 float lp; // leading edge of the polygon.
925
926 p0 = Vector3::Dot_Product(IntersectContext.D,axis);
927
928 // I want the axis centered at the box, pointing towards the triangle
929 if (p0 < 0) {
930 p0 = -p0;
931 axis = -axis;
932 dp = -dp;
933 }
934
935 // compute coordinate of "leading edge of the triangle" relative to the box center.
936 lp = 0;
937 if (dp < 0) { lp = dp; }
938 lp = p0 + lp;
939
940 return (lp - leb0 > -WWMATH_EPSILON);
941}
942
943
944/***********************************************************************************************
945 * aabtri_intersect_basis_axis -- intersection check for a basis axis *
946 * *
947 * axis being checked is one of the basis vectors for the box *
948 * *
949 * INPUT: *
950 * *
951 * OUTPUT: *
952 * *
953 * WARNINGS: *
954 * *
955 * HISTORY: *
956 * 5/4/99 GTH : Created. *
957 *=============================================================================================*/
958static inline bool aabtri_intersect_basis_axis
959(
960 Vector3 & axis,
961 float leb0,
962 float dp1,
963 float dp2
964)
965{
966 float dist; // separation along the axis
967 float lp; // leading edge of the polygon.
968
969 dist = Vector3::Dot_Product(IntersectContext.D,axis);
970
971 // we want the axis centered at the box, pointing towards the triangle
972 if (dist < 0) {
973 dist = -dist;
974 axis = -axis;
975 dp1 = -dp1;
976 dp2 = -dp2;
977 }
978
979 // compute coordinate of "leading edge of the polygon" relative to the box center.
980 lp = 0;
981 if (dp1 < lp) { lp = dp1; }
982 if (dp2 < lp) { lp = dp2; }
983 lp = dist + lp;
984
985 return (lp - leb0 > -WWMATH_EPSILON);
986}
987
988
989/***********************************************************************************************
990 * aabtri_intersect_normal_axis -- intersection check for the triangle normal *
991 * *
992 * axis being checked is the triangle's normal *
993 * *
994 * INPUT: *
995 * *
996 * OUTPUT: *
997 * *
998 * WARNINGS: *
999 * *
1000 * HISTORY: *
1001 * 5/4/99 GTH : Created. *
1002 *=============================================================================================*/
1003static inline bool aabtri_intersect_normal_axis
1004(
1005 Vector3 & axis
1006)
1007{
1008 float dist; // separation along the axis
1009 float leb0; // initial coordinate of the leading edge of the box
1010 float lp; // leading edge of the polygon.
1011
1012 dist = Vector3::Dot_Product(IntersectContext.D,axis);
1013
1014 // we want the axis centered at the box, pointing towards the triangle
1015 if (dist < 0) {
1016 dist = -dist;
1017 axis = -axis;
1018 }
1019
1020 leb0 = IntersectContext.Box->Extent.X * WWMath::Fabs(IntersectContext.AN[0]) +
1021 IntersectContext.Box->Extent.Y * WWMath::Fabs(IntersectContext.AN[1]) +
1022 IntersectContext.Box->Extent.Z * WWMath::Fabs(IntersectContext.AN[2]);
1023 lp = dist; // this is the "optimization", don't have to find lp
1024
1025 return (lp - leb0 > -WWMATH_EPSILON);
1026}
1027
1028
1029/***********************************************************************************************
1030 * CollisionMath::Intersection_Test -- Intersection check for an AABox and a triangle *
1031 * *
1032 * INPUT: *
1033 * *
1034 * OUTPUT: *
1035 * *
1036 * WARNINGS: *
1037 * *
1038 * HISTORY: *
1039 * 1/20/00 gth : copied from OBBox version and removed some Dot-products *
1040 *=============================================================================================*/
1042{
1043 Vector3 axis;
1044 float dp,leb0;
1045
1046 IntersectContext.Init(box,tri);
1047
1048 /*
1049 ** AXIS_N
1050 */
1051 axis = IntersectContext.N;
1052 IntersectContext.AN[0] = IntersectContext.N.X;
1053 IntersectContext.AN[1] = IntersectContext.N.Y;
1054 IntersectContext.AN[2] = IntersectContext.N.Z;
1055 if (aabtri_intersect_normal_axis(axis)) return false;
1056
1057 /*
1058 ** AXIS_A0
1059 */
1060 axis.Set(1,0,0);
1061 IntersectContext.AE[0][0] = IntersectContext.E[0].X;
1062 IntersectContext.AE[0][1] = IntersectContext.E[1].Y;
1063 if (aabtri_intersect_basis_axis(axis,box.Extent.X,IntersectContext.AE[0][0],IntersectContext.AE[0][1])) return false;
1064
1065 /*
1066 ** AXIS_A1
1067 */
1068 axis.Set(0,1,0);
1069 IntersectContext.AE[1][0] = IntersectContext.E[0].Y;
1070 IntersectContext.AE[1][1] = IntersectContext.E[1].Y;
1071 if (aabtri_intersect_basis_axis(axis,box.Extent.Y,IntersectContext.AE[1][0],IntersectContext.AE[1][1])) return false;
1072
1073 /*
1074 ** AXIS_A2
1075 */
1076 axis.Set(0,0,1);
1077 IntersectContext.AE[2][0] = IntersectContext.E[0].Z;
1078 IntersectContext.AE[2][1] = IntersectContext.E[1].Z;
1079 if (aabtri_intersect_basis_axis(axis,box.Extent.Z,IntersectContext.AE[2][0],IntersectContext.AE[2][1])) return false;
1080
1081 /*
1082 ** AXIS_A0xE0
1083 */
1084 Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[0],&IntersectContext.AxE[0][0]);
1085 axis = IntersectContext.AxE[0][0];
1086 if (axis.Length2() > AXISLEN_EPSILON2) {
1087 dp = IntersectContext.AN[0];
1088 leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][0]);
1089 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1090 }
1091
1092 /*
1093 ** AXIS_A0xE1
1094 */
1095 Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[1],&IntersectContext.AxE[0][1]);
1096 axis = IntersectContext.AxE[0][1];
1097 if (axis.Length2() > AXISLEN_EPSILON2) {
1098 dp = -IntersectContext.AN[0];
1099 leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][1]);
1100 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1101 }
1102
1103 /*
1104 ** AXIS_A0xE2
1105 */
1106 Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[2],&IntersectContext.AxE[0][2]);
1107 axis = IntersectContext.AxE[0][2];
1108 IntersectContext.AE[1][2] = IntersectContext.E[2].Y;
1109 IntersectContext.AE[2][2] = IntersectContext.E[2].Z;
1110 if (axis.Length2() > AXISLEN_EPSILON2) {
1111 dp = -IntersectContext.AN[0];
1112 leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][2]);
1113 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1114 }
1115
1116 /*
1117 ** AXIS_A1xE0
1118 */
1119 Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[0],&IntersectContext.AxE[1][0]);
1120 axis = IntersectContext.AxE[1][0];
1121 if (axis.Length2() > AXISLEN_EPSILON2) {
1122 dp = IntersectContext.AN[1];
1123 leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][0]);
1124 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1125 }
1126
1127 /*
1128 ** AXIS_A1xE1
1129 */
1130 Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[1],&IntersectContext.AxE[1][1]);
1131 axis = IntersectContext.AxE[1][1];
1132 if (axis.Length2() > AXISLEN_EPSILON2) {
1133 dp = -IntersectContext.AN[1];
1134 leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][1]);
1135 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1136 }
1137
1138 /*
1139 ** AXIS_A1xE2
1140 */
1141 Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[2],&IntersectContext.AxE[1][2]);
1142 axis = IntersectContext.AxE[1][2];
1143 IntersectContext.AE[0][2] = IntersectContext.E[2].X;
1144 if (axis.Length2() > AXISLEN_EPSILON2) {
1145 dp = -IntersectContext.AN[1];
1146 leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][2]);
1147 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1148 }
1149
1150 /*
1151 ** AXIS_A2xE0
1152 */
1153 Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[0],&IntersectContext.AxE[2][0]);
1154 axis = IntersectContext.AxE[2][0];
1155 if (axis.Length2() > AXISLEN_EPSILON2) {
1156 dp = IntersectContext.AN[2];
1157 leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][0]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][0]);
1158 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1159 }
1160
1161 /*
1162 ** AXIS_A2xE1
1163 */
1164 Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[1],&IntersectContext.AxE[2][1]);
1165 axis = IntersectContext.AxE[2][1];
1166 if (axis.Length2() > AXISLEN_EPSILON2) {
1167 dp = -IntersectContext.AN[2];
1168 leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][1]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][1]);
1169 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1170 }
1171
1172 /*
1173 ** AXIS_A2xE2
1174 */
1175 Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[2],&IntersectContext.AxE[2][2]);
1176 axis = IntersectContext.AxE[2][2];
1177 if (axis.Length2() > AXISLEN_EPSILON2) {
1178 dp = -IntersectContext.AN[2];
1179 leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][2]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][2]);
1180 if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
1181 }
1182
1183 return true;
1184}
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define WWMATH_EPSILON
Definition wwmath.h:54
Vector3 Center
Definition aabox.h:123
Vector3 Extent
Definition aabox.h:124
static bool Collide(const LineSegClass &line, const AAPlaneClass &plane, CastResultStruct *result)
static bool Intersection_Test(const AABoxClass &box, const TriClass &tri)
Definition tri.h:61
const Vector3 * N
Definition tri.h:64
const Vector3 * V[3]
Definition tri.h:65
static WWINLINE float Dot_Product(const Vector3 &a, const Vector3 &b)
Definition vector3.h:293
float X
Definition vector3.h:90
WWINLINE float Length2(void) const
Definition vector3.h:469
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
WWINLINE float Length(void) const
Definition vector3.h:453
static WWINLINE void Subtract(const Vector3 &a, const Vector3 &b, Vector3 *c)
Definition vector3.h:576
void Normalize(void)
Definition vector3.h:417
static WWINLINE void Cross_Product(const Vector3 &a, const Vector3 &b, Vector3 *result)
Definition vector3.h:374
WWINLINE void Set(float x, float y, float z)
Definition vector3.h:103
static WWINLINE float Fabs(float val)
Definition wwmath.h:113
#define TRACK_COLLISION_AABOX_TRI
Definition colmath.h:300
#define TRACK_COLLISION_AABOX_TRI_HIT
Definition colmath.h:301
const float COLLISION_EPSILON
Definition colmath.h:65
@ AXIS_A1
@ AXIS_A1E0
@ AXIS_A2E0
@ AXIS_A1E2
@ AXIS_A0E1
@ AXIS_A2E1
@ INTERSECTION
@ AXIS_N
@ AXIS_A1E1
@ AXIS_A2E2
@ AXIS_A0
@ AXIS_A2
@ AXIS_A0E2
@ AXIS_A0E0
#define AXISLEN_EPSILON2
void VERIFY_CROSS(const Vector3 &a, const Vector3 &b, const Vector3 &cross)
@ INTERSECTION
const AABoxClass * Box
void Init(const AABoxClass &box, const TriClass &tri)
const TriClass * Tri
const Vector3 * BoxMove
const AABoxClass * Box
void Init(const AABoxClass &box, const Vector3 &move, const TriClass &tri, const Vector3 &trimove)
const TriClass * Tri
const Vector3 * TriMove
Vector3 Normal
Definition castres.h:66