| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : WWMath *
- * *
- * $Archive:: /Commando/Code/wwmath/colmathaabtri.cpp $*
- * *
- * Author:: Greg Hjelstrom *
- * *
- * $Modtime:: 5/08/01 9:52a $*
- * *
- * $Revision:: 17 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * aabtri_separation_test -- test the projected extents for separation *
- * aabtri_check_axis -- project the aab and tri onto an arbitrary axis *
- * aabtri_check_cross_axis -- projects aab and tri onto a "cross" axis *
- * aabtri_check_basis_axis -- projects the aab and tri onto a basis axis *
- * aabtri_check_normal_axis -- project the box and tri onto the tri-normal *
- * eval_side -- returns -1,0,+1 depending on the sign of val and side *
- * aabtri_compute_contact_normal -- computes the normal of the collision *
- * CollisionMath::Collide -- collide an aabox into a triangle *
- * aabtri_intersect_cross_axis -- intersection check for a "cross-product" axis *
- * aabtri_intersect_basis_axis -- intersection check for a basis axis *
- * aabtri_intersect_normal_axis -- intersection check for the triangle normal *
- * CollisionMath::Intersection_Test -- Intersection check for an AABox and a triangle *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "colmath.h"
- #include "aabox.h"
- #include "tri.h"
- #include "wwdebug.h"
- /*
- ** Separating Axes have to be rejected if their length is smaller than some epsilon.
- ** Otherwise, erroneous results can be reported.
- */
- #define AXISLEN_EPSILON2 WWMATH_EPSILON * WWMATH_EPSILON // squared length of a separating axis must be larger than this
- /*
- ** Axes used in Box-Tri intersection tests
- ** The axes of the box are A0,A1,A2. N is the normal of the triangle,
- ** E0,E1,E2 are direction vectors for the edges of the triangle.
- ** (the box axes are labeled A0,A1,A2 as a holdover from the obbox-obbox
- ** collision code which this was derived from where there are two boxes
- ** A and B)
- */
- enum
- {
- INTERSECTION = 0,
- AXIS_N, // normal of the triangle
- AXIS_A0, // first basis vector of the box
- AXIS_A1, // second basis vector of the box
- AXIS_A2, // third basis vector of the box
- AXIS_A0E0, // box0 x edge0...
- AXIS_A1E0,
- AXIS_A2E0,
- AXIS_A0E1,
- AXIS_A1E1,
- AXIS_A2E1,
- AXIS_A0E2,
- AXIS_A1E2,
- AXIS_A2E2
- };
- /******************************************************************************************
-
- AABox->Triangle collision
- This code is basically a special-case optimization of the OBBox->Triangle collision
- detection code. There are many dot and cross products that can be simplified due
- to the fact that we know the axes of the boxes are always the same and are aligned
- with the world coordinate axes.
- Each axis test will use the following logic:
- Project D onto the axis being used, it is the separation distance. If the
- projection of the extent of the box + the projection of the extent of the
- tri is greater than D*axis then the two intersect
- March 13, 2000 - Modified these routines to all use a static instance of
- the BTCollisionStruct. The compiler was generating lots of extra code for the
- constructor of this object and testing determined that re-using the same static
- struct was slightly faster anyway.
- NOTE: this makes the code not Thread-Safe!!!!
- ******************************************************************************************/
- /*
- ** BoxTriColStruct
- ** Scratchpad variables for the AABox-Triangle collision detection functions. One instance
- ** of this structure will be used for all of the local variables and its pointer will be
- ** handed of to various inline functions for the axis tests.
- ** Note that much of the code needs the un-normalized triangle normal. For this reason,
- ** I have to compute N rather than copying it from the triangle. (commenting this to
- ** avoid re-generating a difficult to find bug that I had)
- */
- struct BTCollisionStruct
- {
- BTCollisionStruct(void) {}
- void Init(const AABoxClass &box,const Vector3 &move,const TriClass &tri,const Vector3 &trimove)
- {
- StartBad = true; // true until an axis clears it
- MaxFrac = -0.01f; // maximum move allowed so far
- AxisId = INTERSECTION; // axis that allowed the longest move
- Point = 0; // index of triangle point that was closest to the box
- Side = 0; // side of the interval
- Box = &box;
- Tri = &tri;
- BoxMove = &move;
- TriMove = &trimove;
-
- Vector3::Subtract(*tri.V[0],box.Center,&D); // vector from center of box to vertex 0
- Vector3::Subtract(move,trimove,&Move); // move vector relative to stationary triangle
- Vector3::Subtract(*tri.V[1],*tri.V[0],&E[0]);
- Vector3::Subtract(*tri.V[2],*tri.V[0],&E[1]);
- Vector3::Subtract(E[1],E[0],&E[2]);
- Vector3::Cross_Product(E[0],E[1],&N);
- }
- bool StartBad; // Inital configuration is intersecting?
- float MaxFrac; // Longest move allowed so far
- int AxisId; // Last separating axis
- int Side; // which side of the interval
- int Point; // Index of the "closest" triangle point (or one of them)
-
- int TestAxisId; // Axis 'id' we're working on
- int TestSide; // Was the axis we're working on flipped
- int TestPoint; // Index of the closest vertex
- Vector3 TestAxis; // Axis we're working on
- Vector3 D; // Vector from the center of the box to v0
- Vector3 Move; // Move vector relative to stationary triangle
- float AE[3][3]; // Dot products of the Basis vectors and edges
- float AN[3]; // Dot products of the Basis vectors and the normal
- Vector3 AxE[3][3]; // Cross products of the Basis vectors and edges
- Vector3 E[3]; // edge vectors for the triangle
- Vector3 N; // normal (NOT normalized!!!)
- Vector3 FinalD; // Vector from center of box to v0 at end of move
- const AABoxClass * Box;
- const TriClass * Tri;
- const Vector3 * BoxMove;
- const Vector3 * TriMove;
- private:
-
- // not implemented
- BTCollisionStruct(const BTCollisionStruct &);
- BTCollisionStruct & operator = (const BTCollisionStruct &);
- };
- static BTCollisionStruct CollisionContext;
- /***********************************************************************************************
- * aabtri_separation_test -- test the projected extents for separation *
- * *
- * Once the extents are projected onto the axis, this function contains *
- * the logic that determines the allowed fraction. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- * 7/12/99 GTH : Converted original OBBox code to AABox *
- *=============================================================================================*/
- static inline bool aabtri_separation_test
- (
- float lp,float leb0,float leb1
- )
- {
- /*
- ** - If (I'm no more than 'EPSILON' embedded in the wall)
- ** - not startbad
- ** - If (I'm moving towards)
- ** - fraction = How far I can move before embedding (can be negative if started embedded)
- ** - If (I can take entire move)
- ** - accept entire move
- ** - Else If (I can move more than I could have before; *negative always fails!)
- ** - update fraction
- ** - Else
- ** - Accept entire move since I'm not moving towards
- */
- float eps = 0.0f;
- if (lp - leb0 <= 0.0f) {
- eps = COLLISION_EPSILON * CollisionContext.TestAxis.Length(); // trying to only compute epsilon if I have to
- }
- if (lp - leb0 > -eps) {
- CollisionContext.StartBad = false;
- if (leb1 - leb0 > 0.0f) {
- float frac = (lp-leb0)/(leb1-leb0);
- if (frac >= 1.0f) {
- /* moving toward but not hitting triangle */
- CollisionContext.AxisId = CollisionContext.TestAxisId;
- CollisionContext.MaxFrac = 1.0f;
- return true;
- } else {
- /* moving toward, hitting triangle */
- if (frac > CollisionContext.MaxFrac) {
- CollisionContext.MaxFrac = frac;
- CollisionContext.AxisId = CollisionContext.TestAxisId;
- CollisionContext.Side = CollisionContext.TestSide;
- CollisionContext.Point = CollisionContext.TestPoint;
- }
- }
- } else {
- /* moving away or not moving */
- CollisionContext.AxisId = CollisionContext.TestAxisId;
- CollisionContext.MaxFrac = 1.0f;
- return true;
- }
- }
- return false;
- }
- /***********************************************************************************************
- * aabtri_check_axis -- project the aab and tri onto an arbitrary axis *
- * *
- * projects the box and the triangle onto the given axis and calls *
- * obbtri_separation_test. return true if separation was detected *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- * 7/12/99 GTH : converted to AABox *
- *=============================================================================================*/
- static inline bool aabtri_check_axis(void)
- {
- float dist; // separation along the axis
- float axismove; // size of the move along the axis.
- float leb0; // initial coordinate of the leading edge of the box
- float leb1; // final coordinate of the leading edge of the box
- float lp; // leading edge of the polygon.
- float tmp; // temporary
- dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
- axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
- // I want the axis centered at the box, pointing towards the triangle
- if (dist < 0) {
- dist = -dist;
- axismove = -axismove;
- CollisionContext.TestAxis = -CollisionContext.TestAxis;
- CollisionContext.TestSide = -1.0f;
- } else {
- CollisionContext.TestSide = 1.0f;
- }
- // compute coordinates of the leading edge of the box at t0 and t1
- leb0 = CollisionContext.Box->Extent.X * WWMath::Fabs(CollisionContext.TestAxis.X) +
- CollisionContext.Box->Extent.Y * WWMath::Fabs(CollisionContext.TestAxis.Y) +
- CollisionContext.Box->Extent.Z * WWMath::Fabs(CollisionContext.TestAxis.Z);
- leb1 = leb0 + axismove;
-
- // compute coordinate of "leading edge of the triangle" relative to the box center.
- lp = 0;
- tmp = Vector3::Dot_Product(CollisionContext.E[0],CollisionContext.TestAxis); if (tmp < lp) lp = tmp;
- tmp = Vector3::Dot_Product(CollisionContext.E[1],CollisionContext.TestAxis); if (tmp < lp) lp = tmp;
- lp = dist + lp;
- return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
- }
- /***********************************************************************************************
- * aabtri_check_cross_axis -- projects aab and tri onto a "cross" axis *
- * *
- * Assumes that the axis given is one generated from a cross product of one of the edge and *
- * basis vectors. In this case, the box extent can be optimized and only two triangle verts *
- * need to be checked. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- *=============================================================================================*/
- static inline bool aabtri_check_cross_axis
- (
- float dp,
- int dpi,
- float leb0
- )
- {
- float p0; // distance from box center to vertex 0
- float axismove; // size of the move along the axis.
- float leb1; // final coordinate of the leading edge of the box
- float lp; // leading edge of the polygon.
- p0 = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
- axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
- // I want the axis centered at the box, pointing towards the triangle
- if (p0 < 0) {
- p0 = -p0;
- axismove = -axismove;
- dp = -dp;
- CollisionContext.TestAxis = -CollisionContext.TestAxis;
- CollisionContext.TestSide = -1.0f;
- } else {
- CollisionContext.TestSide = 1.0f;
- }
- // compute coordinates of the leading edge of the box at t1
- leb1 = leb0 + axismove;
-
- // compute coordinate of "leading edge of the triangle" relative to the box center.
- lp = 0; CollisionContext.TestPoint = 0;
- if (dp < 0) { lp = dp; CollisionContext.TestPoint = dpi; }
- lp = p0 + lp;
- return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
- }
- /***********************************************************************************************
- * aabtri_check_basis_axis -- projects the aab and tri onto a basis axis *
- * *
- * Projects the box and triangle onto an axis that is assumed to be a basis *
- * vector from the box. In this case, we can skip a dot-product and use the *
- * corresponding extent of the box (which is passed in as leb0). *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- *=============================================================================================*/
- static inline bool aabtri_check_basis_axis
- (
- float leb0,
- float dp1,
- float dp2
- )
- {
- float dist; // separation along the axis
- float axismove; // size of the move along the axis.
- float leb1; // final coordinate of the leading edge of the box
- float lp; // leading edge of the polygon.
- dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
- axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
- // we want the axis centered at the box, pointing towards the triangle
- if (dist < 0) {
- dist = -dist;
- axismove = -axismove;
- dp1 = -dp1;
- dp2 = -dp2;
- CollisionContext.TestAxis = -CollisionContext.TestAxis;
- CollisionContext.TestSide = -1.0f;
- } else {
- CollisionContext.TestSide = 1.0f;
- }
- // this is the "optimization", leb0 = one of the extents
- leb1 = leb0 + axismove;
-
- // compute coordinate of "leading edge of the polygon" relative to the box center.
- lp = 0; CollisionContext.TestPoint = 0;
- if (dp1 < lp) { lp = dp1; CollisionContext.TestPoint = 1; }
- if (dp2 < lp) { lp = dp2; CollisionContext.TestPoint = 2; }
- lp = dist + lp;
- return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
- }
- /***********************************************************************************************
- * aabtri_check_normal_axis -- project the box and tri onto the tri-normal *
- * *
- * Projects the box and triangle onto an axis that is assumed to be the normal *
- * vector from the triangle. In this case, the triangle extents are zero. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- *=============================================================================================*/
- static inline bool aabtri_check_normal_axis(void)
- {
- float dist; // separation along the axis
- float axismove; // size of the move along the axis.
- float leb0; // initial coordinate of the leading edge of the box
- float leb1; // final coordinate of the leading edge of the box
- float lp; // leading edge of the polygon.
- dist = Vector3::Dot_Product(CollisionContext.D,CollisionContext.TestAxis);
- axismove = Vector3::Dot_Product(CollisionContext.Move,CollisionContext.TestAxis);
- // we want the axis centered at the box, pointing towards the triangle
- if (dist < 0) {
- dist = -dist;
- axismove = -axismove;
- CollisionContext.TestAxis = -CollisionContext.TestAxis;
- CollisionContext.TestSide = -1.0f;
- } else {
- CollisionContext.TestSide = 1.0f;
- }
- leb0 = CollisionContext.Box->Extent.X * WWMath::Fabs(CollisionContext.AN[0]) +
- CollisionContext.Box->Extent.Y * WWMath::Fabs(CollisionContext.AN[1]) +
- CollisionContext.Box->Extent.Z * WWMath::Fabs(CollisionContext.AN[2]);
- leb1 = leb0 + axismove;
- CollisionContext.TestPoint = 0;
- lp = dist; // this is the "optimization", don't have to find lp
- return aabtri_separation_test(/*CollisionContext,*/lp,leb0,leb1);
- }
- /***********************************************************************************************
- * eval_side -- returns -1,0,+1 depending on the sign of val and side *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- *=============================================================================================*/
- static inline float eval_side(float val,int side)
- {
- if (val > 0.0f) {
- return side;
- } else if (val < 0.0f) {
- return -side;
- } else {
- return 0.0f;
- }
- }
- /***********************************************************************************************
- * aabtri_compute_contact_normal -- computes the normal of the collision *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- *=============================================================================================*/
- static inline void aabtri_compute_contact_normal
- (
- Vector3 & set_norm
- )
- {
- #if 1
- switch(CollisionContext.AxisId)
- {
- case INTERSECTION:
- set_norm = *CollisionContext.Tri->N;
- break;
- case AXIS_N:
- set_norm = -CollisionContext.Side * *CollisionContext.Tri->N;
- set_norm.Normalize();
- break;
- case AXIS_A0:
- set_norm = -CollisionContext.Side * Vector3(1.0f,0.0f,0.0f);
- break;
- case AXIS_A1:
- set_norm = -CollisionContext.Side * Vector3(0.0f,1.0f,0.0f);
- break;
- case AXIS_A2:
- set_norm = -CollisionContext.Side * Vector3(0.0f,0.0f,1.0f);
- break;
- case AXIS_A0E0:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[0][0];
- set_norm.Normalize();
- break;
- case AXIS_A1E0:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[1][0];
- set_norm.Normalize();
- break;
- case AXIS_A2E0:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[2][0];
- set_norm.Normalize();
- break;
- case AXIS_A0E1:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[0][1];
- set_norm.Normalize();
- break;
- case AXIS_A1E1:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[1][1];
- set_norm.Normalize();
- break;
- case AXIS_A2E1:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[2][1];
- set_norm.Normalize();
- break;
- case AXIS_A0E2:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[0][2];
- set_norm.Normalize();
- break;
- case AXIS_A1E2:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[1][2];
- set_norm.Normalize();
- break;
- case AXIS_A2E2:
- set_norm = -CollisionContext.Side * CollisionContext.AxE[2][2];
- set_norm.Normalize();
- break;
- }
- WWASSERT(set_norm.Length2() > 0.0f);
- #else
- set_norm = *CollisionContext.Tri.N;
- if (Vector3::Dot_Product(set_norm,CollisionContext.Move) > 0.0f) {
- set_norm = -(set_norm);
- }
- #endif
- }
- inline void VERIFY_CROSS(const Vector3 & a, const Vector3 & b,const Vector3 & cross)
- {
- #ifdef WWDEBUG
- Vector3 tmp_cross;
- Vector3::Cross_Product(a,b,&tmp_cross);
- Vector3 diff = cross - tmp_cross;
- WWASSERT(WWMath::Fabs(diff.Length()) < 0.0001f);
- #endif
- }
- /***********************************************************************************************
- * CollisionMath::Collide -- collide an aabox into a triangle *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/8/99 GTH : Created. *
- *=============================================================================================*/
- bool CollisionMath::Collide
- (
- const AABoxClass & box,
- const Vector3 & move,
- const TriClass & tri,
- CastResultStruct * result
- )
- {
- TRACK_COLLISION_AABOX_TRI;
- float dp,leb0;
- CollisionContext.Init(box,move,tri,Vector3(0,0,0));
- /*
- ** AXIS_N
- */
- CollisionContext.TestAxis = CollisionContext.N;
- CollisionContext.TestAxisId = AXIS_N;
- CollisionContext.AN[0] = CollisionContext.N.X;
- CollisionContext.AN[1] = CollisionContext.N.Y;
- CollisionContext.AN[2] = CollisionContext.N.Z;
- if (aabtri_check_normal_axis()) goto exit;
- /*
- ** AXIS_A0
- */
- CollisionContext.TestAxis.Set(1,0,0);
- CollisionContext.TestAxisId = AXIS_A0;
- CollisionContext.AE[0][0] = CollisionContext.E[0].X;
- CollisionContext.AE[0][1] = CollisionContext.E[1].X;
- if (aabtri_check_basis_axis(box.Extent.X,CollisionContext.AE[0][0],CollisionContext.AE[0][1])) goto exit;
- /*
- ** AXIS_A1
- */
- CollisionContext.TestAxis.Set(0,1,0);
- CollisionContext.TestAxisId = AXIS_A1;
- CollisionContext.AE[1][0] = CollisionContext.E[0].Y;
- CollisionContext.AE[1][1] = CollisionContext.E[1].Y;
- if (aabtri_check_basis_axis(box.Extent.Y,CollisionContext.AE[1][0],CollisionContext.AE[1][1])) goto exit;
- /*
- ** AXIS_A2
- */
- CollisionContext.TestAxis.Set(0,0,1);
- CollisionContext.TestAxisId = AXIS_A2;
- CollisionContext.AE[2][0] = CollisionContext.E[0].Z;
- CollisionContext.AE[2][1] = CollisionContext.E[1].Z;
- if (aabtri_check_basis_axis(box.Extent.Z,CollisionContext.AE[2][0],CollisionContext.AE[2][1])) goto exit;
- /*
- ** AXIS_A0xE0
- */
- CollisionContext.AxE[0][0].Set(0,-CollisionContext.E[0].Z,CollisionContext.E[0].Y);
- VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[0],CollisionContext.AxE[0][0]);
- CollisionContext.TestAxis = CollisionContext.AxE[0][0];
- CollisionContext.TestAxisId = AXIS_A0E0;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = CollisionContext.AN[0];
- leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][0]);
- if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
- }
- /*
- ** AXIS_A0xE1
- */
- CollisionContext.AxE[0][1].Set(0,-CollisionContext.E[1].Z,CollisionContext.E[1].Y);
- VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[1],CollisionContext.AxE[0][1]);
- CollisionContext.TestAxis = CollisionContext.AxE[0][1];
- CollisionContext.TestAxisId = AXIS_A0E1;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = -CollisionContext.AN[0];
- leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][1]);
- if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
- }
- /*
- ** AXIS_A0xE2
- */
- CollisionContext.AE[0][2] = CollisionContext.E[2].X;
- CollisionContext.AE[1][2] = CollisionContext.E[2].Y;
- CollisionContext.AE[2][2] = CollisionContext.E[2].Z;
- CollisionContext.AxE[0][2].Set(0,-CollisionContext.E[2].Z,CollisionContext.E[2].Y);
- VERIFY_CROSS(Vector3(1,0,0),CollisionContext.E[2],CollisionContext.AxE[0][2]);
- CollisionContext.TestAxis = CollisionContext.AxE[0][2];
- CollisionContext.TestAxisId = AXIS_A0E2;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = -CollisionContext.AN[0];
- leb0 = box.Extent[1]*WWMath::Fabs(CollisionContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[1][2]);
- if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
- }
- /*
- ** AXIS_A1xE0
- */
- CollisionContext.AxE[1][0].Set(CollisionContext.E[0].Z,0,-CollisionContext.E[0].X);
- VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[0],CollisionContext.AxE[1][0]);
- CollisionContext.TestAxis = CollisionContext.AxE[1][0];
- CollisionContext.TestAxisId = AXIS_A1E0;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = CollisionContext.AN[1];
- leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][0]);
- if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
- }
- /*
- ** AXIS_A1xE1
- */
- CollisionContext.AxE[1][1].Set(CollisionContext.E[1].Z,0,-CollisionContext.E[1].X);
- VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[1],CollisionContext.AxE[1][1]);
- CollisionContext.TestAxis = CollisionContext.AxE[1][1];
- CollisionContext.TestAxisId = AXIS_A1E1;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = -CollisionContext.AN[1];
- leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][1]);
- if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
- }
- /*
- ** AXIS_A1xE2
- */
- CollisionContext.AxE[1][2].Set(CollisionContext.E[2].Z,0,-CollisionContext.E[2].X);
- VERIFY_CROSS(Vector3(0,1,0),CollisionContext.E[2],CollisionContext.AxE[1][2]);
- CollisionContext.TestAxis = CollisionContext.AxE[1][2];
- CollisionContext.TestAxisId = AXIS_A1E2;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = -CollisionContext.AN[1];
- leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(CollisionContext.AE[0][2]);
- if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
- }
- /*
- ** AXIS_A2xE0
- */
- CollisionContext.AxE[2][0].Set(-CollisionContext.E[0].Y,CollisionContext.E[0].X,0);
- VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[0],CollisionContext.AxE[2][0]);
- CollisionContext.TestAxis = CollisionContext.AxE[2][0];
- CollisionContext.TestAxisId = AXIS_A2E0;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = CollisionContext.AN[2];
- leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][0]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][0]);
- if (aabtri_check_cross_axis(dp,2,leb0)) goto exit;
- }
- /*
- ** AXIS_A2xE1
- */
- CollisionContext.AxE[2][1].Set(-CollisionContext.E[1].Y,CollisionContext.E[1].X,0);
- VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[1],CollisionContext.AxE[2][1]);
- CollisionContext.TestAxis = CollisionContext.AxE[2][1];
- CollisionContext.TestAxisId = AXIS_A2E1;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = -CollisionContext.AN[2];
- leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][1]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][1]);
- if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
- }
-
- /*
- ** AXIS_A2xE2
- */
- CollisionContext.AxE[2][2].Set(-CollisionContext.E[2].Y,CollisionContext.E[2].X,0);
- VERIFY_CROSS(Vector3(0,0,1),CollisionContext.E[2],CollisionContext.AxE[2][2]);
- CollisionContext.TestAxis = CollisionContext.AxE[2][2];
- CollisionContext.TestAxisId = AXIS_A2E2;
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- dp = -CollisionContext.AN[2];
- leb0 = box.Extent[0]*WWMath::Fabs(CollisionContext.AE[1][2]) + box.Extent[1]*WWMath::Fabs(CollisionContext.AE[0][2]);
- if (aabtri_check_cross_axis(dp,1,leb0)) goto exit;
- }
- /*
- ** Last ditch effort, check an axis based on the move vector
- */
- if (!CollisionContext.StartBad) {
- CollisionContext.TestPoint = CollisionContext.Point;
- CollisionContext.TestAxisId = CollisionContext.AxisId;
- CollisionContext.TestAxis.Set(0,-CollisionContext.Move.Z,CollisionContext.Move.Y); // A0 X Move
- VERIFY_CROSS(Vector3(1,0,0),CollisionContext.Move,CollisionContext.TestAxis);
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- if (aabtri_check_axis()) goto exit;
- }
- CollisionContext.TestAxis.Set(CollisionContext.Move.Z,0,-CollisionContext.Move.X); // A1 X Move
- VERIFY_CROSS(Vector3(0,1,0),CollisionContext.Move,CollisionContext.TestAxis);
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- if (aabtri_check_axis()) goto exit;
- }
- CollisionContext.TestAxis.Set(-CollisionContext.Move.Y,CollisionContext.Move.X,0); // A2 X Move
- VERIFY_CROSS(Vector3(0,0,1),CollisionContext.Move,CollisionContext.TestAxis);
- if (CollisionContext.TestAxis.Length2() > AXISLEN_EPSILON2) {
- if (aabtri_check_axis()) goto exit;
- }
- }
- exit:
- /*
- ** If MaxFrac is less than zero, clamp it to zero. Negative fractions can
- ** leak through this routine due to the epsilon in the separation test.
- */
- if (CollisionContext.MaxFrac < 0.0f) {
- CollisionContext.MaxFrac = 0.0f;
- }
- /*
- ** If the triangle and box are intersecting before the move, return that
- ** result.
- */
- if (CollisionContext.StartBad) {
- result->StartBad = true;
- result->Fraction = 0.0f;
- result->Normal = *tri.N;
- TRACK_COLLISION_AABOX_TRI_HIT;
- return true;
- }
- /*
- ** If the fraction allowed is basically equal to the fraction allowed by
- ** another polygon, try to pick the polygon which is least "edge-on" to the
- ** move.
- */
- if ((CollisionContext.MaxFrac <= result->Fraction) && (CollisionContext.MaxFrac < 1.0f)) {
- /*
- ** Reflect the normal if it is pointing the same way as our move
- ** (probably hitting the back side of a polygon)
- */
- Vector3 tmp_norm(0.0f,0.0f,0.0f);
- aabtri_compute_contact_normal(tmp_norm);
- // if (Vector3::Dot_Product(tmp_norm,move) > 0.0f) {
- // tmp_norm = -tmp_norm;
- // }
- /*
- ** If this polygon cuts off more of the move -OR- this polygon cuts
- ** of the same amount but has a "better" normal, then use this normal
- */
- if ( (WWMath::Fabs(CollisionContext.MaxFrac - result->Fraction) > WWMATH_EPSILON) ||
- (Vector3::Dot_Product(tmp_norm,move) < Vector3::Dot_Product(result->Normal,move)))
- {
- result->Normal = tmp_norm;
- #pragma message("fatal assert disabled for demo")
- //WWASSERT(WWMath::Fabs(result->Normal.Length() - 1.0f) < WWMATH_EPSILON);
- }
-
- result->Fraction = CollisionContext.MaxFrac;
- TRACK_COLLISION_AABOX_TRI_HIT;
- return true;
- }
-
- return false;
- }
- /*
- ** AABTIntersectStruct
- ** Scratchpad variables for the AABox-Triangle intersection functions. One instance
- ** of this structure will be used for all of the local variables and its pointer will be
- ** handed of to various inline functions for the axis tests.
- ** Note that much of the code needs the un-normalized triangle normal. For this reason,
- ** I have to compute N rather than copying it from the triangle. (commenting this to
- ** avoid re-generating a difficult to find bug that I had)
- */
- struct AABTIntersectStruct
- {
- AABTIntersectStruct(void) :
- Box(NULL),
- Tri(NULL)
- {
- }
-
- void Init(const AABoxClass &box,const TriClass &tri)
- {
- Box = &box;
- Tri = &tri;
- Vector3::Subtract(*tri.V[0],box.Center,&D); // vector from center of box to vertex 0
- Vector3::Subtract(*tri.V[1],*tri.V[0],&E[0]);
- Vector3::Subtract(*tri.V[2],*tri.V[0],&E[1]);
- Vector3::Subtract(E[1],E[0],&E[2]);
- Vector3::Cross_Product(E[0],E[1],&N);
- }
- Vector3 D; // Vector from the center of the box to v0
- float AE[3][3]; // Dot products of the Basis vectors and edges
- float AN[3]; // Dot products of the Basis vectors and the normal
- Vector3 AxE[3][3]; // Cross produts of the Basis vectors and edges
- Vector3 E[3]; // edge vectors for the triangle
- Vector3 N; // normal (NOT normalized!!!)
- const AABoxClass * Box;
- const TriClass * Tri;
- private:
-
- // not implemented
- AABTIntersectStruct(const AABTIntersectStruct &);
- AABTIntersectStruct & operator = (const AABTIntersectStruct &);
- };
- static AABTIntersectStruct IntersectContext;
- /***********************************************************************************************
- * aabtri_intersect_cross_axis -- intersection check for a "cross-product" axis *
- * *
- * axis being checked is a cross product between a triangle edge and a box basis vector *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 5/4/99 GTH : Created. *
- *=============================================================================================*/
- static inline bool aabtri_intersect_cross_axis
- (
- Vector3 & axis,
- float dp,
- float leb0
- )
- {
- float p0; // distance from box center to vertex 0
- float lp; // leading edge of the polygon.
- p0 = Vector3::Dot_Product(IntersectContext.D,axis);
- // I want the axis centered at the box, pointing towards the triangle
- if (p0 < 0) {
- p0 = -p0;
- axis = -axis;
- dp = -dp;
- }
- // compute coordinate of "leading edge of the triangle" relative to the box center.
- lp = 0;
- if (dp < 0) { lp = dp; }
- lp = p0 + lp;
- return (lp - leb0 > -WWMATH_EPSILON);
- }
- /***********************************************************************************************
- * aabtri_intersect_basis_axis -- intersection check for a basis axis *
- * *
- * axis being checked is one of the basis vectors for the box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 5/4/99 GTH : Created. *
- *=============================================================================================*/
- static inline bool aabtri_intersect_basis_axis
- (
- Vector3 & axis,
- float leb0,
- float dp1,
- float dp2
- )
- {
- float dist; // separation along the axis
- float lp; // leading edge of the polygon.
- dist = Vector3::Dot_Product(IntersectContext.D,axis);
- // we want the axis centered at the box, pointing towards the triangle
- if (dist < 0) {
- dist = -dist;
- axis = -axis;
- dp1 = -dp1;
- dp2 = -dp2;
- }
- // compute coordinate of "leading edge of the polygon" relative to the box center.
- lp = 0;
- if (dp1 < lp) { lp = dp1; }
- if (dp2 < lp) { lp = dp2; }
- lp = dist + lp;
- return (lp - leb0 > -WWMATH_EPSILON);
- }
- /***********************************************************************************************
- * aabtri_intersect_normal_axis -- intersection check for the triangle normal *
- * *
- * axis being checked is the triangle's normal *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 5/4/99 GTH : Created. *
- *=============================================================================================*/
- static inline bool aabtri_intersect_normal_axis
- (
- Vector3 & axis
- )
- {
- float dist; // separation along the axis
- float leb0; // initial coordinate of the leading edge of the box
- float lp; // leading edge of the polygon.
- dist = Vector3::Dot_Product(IntersectContext.D,axis);
- // we want the axis centered at the box, pointing towards the triangle
- if (dist < 0) {
- dist = -dist;
- axis = -axis;
- }
- leb0 = IntersectContext.Box->Extent.X * WWMath::Fabs(IntersectContext.AN[0]) +
- IntersectContext.Box->Extent.Y * WWMath::Fabs(IntersectContext.AN[1]) +
- IntersectContext.Box->Extent.Z * WWMath::Fabs(IntersectContext.AN[2]);
- lp = dist; // this is the "optimization", don't have to find lp
- return (lp - leb0 > -WWMATH_EPSILON);
- }
- /***********************************************************************************************
- * CollisionMath::Intersection_Test -- Intersection check for an AABox and a triangle *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 1/20/00 gth : copied from OBBox version and removed some Dot-products *
- *=============================================================================================*/
- bool CollisionMath::Intersection_Test(const AABoxClass & box,const TriClass & tri)
- {
- Vector3 axis;
- float dp,leb0;
- IntersectContext.Init(box,tri);
- /*
- ** AXIS_N
- */
- axis = IntersectContext.N;
- IntersectContext.AN[0] = IntersectContext.N.X;
- IntersectContext.AN[1] = IntersectContext.N.Y;
- IntersectContext.AN[2] = IntersectContext.N.Z;
- if (aabtri_intersect_normal_axis(axis)) return false;
- /*
- ** AXIS_A0
- */
- axis.Set(1,0,0);
- IntersectContext.AE[0][0] = IntersectContext.E[0].X;
- IntersectContext.AE[0][1] = IntersectContext.E[1].Y;
- if (aabtri_intersect_basis_axis(axis,box.Extent.X,IntersectContext.AE[0][0],IntersectContext.AE[0][1])) return false;
- /*
- ** AXIS_A1
- */
- axis.Set(0,1,0);
- IntersectContext.AE[1][0] = IntersectContext.E[0].Y;
- IntersectContext.AE[1][1] = IntersectContext.E[1].Y;
- if (aabtri_intersect_basis_axis(axis,box.Extent.Y,IntersectContext.AE[1][0],IntersectContext.AE[1][1])) return false;
- /*
- ** AXIS_A2
- */
- axis.Set(0,0,1);
- IntersectContext.AE[2][0] = IntersectContext.E[0].Z;
- IntersectContext.AE[2][1] = IntersectContext.E[1].Z;
- if (aabtri_intersect_basis_axis(axis,box.Extent.Z,IntersectContext.AE[2][0],IntersectContext.AE[2][1])) return false;
- /*
- ** AXIS_A0xE0
- */
- Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[0],&IntersectContext.AxE[0][0]);
- axis = IntersectContext.AxE[0][0];
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = IntersectContext.AN[0];
- leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][0]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- /*
- ** AXIS_A0xE1
- */
- Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[1],&IntersectContext.AxE[0][1]);
- axis = IntersectContext.AxE[0][1];
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = -IntersectContext.AN[0];
- leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][1]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- /*
- ** AXIS_A0xE2
- */
- Vector3::Cross_Product(Vector3(1,0,0),IntersectContext.E[2],&IntersectContext.AxE[0][2]);
- axis = IntersectContext.AxE[0][2];
- IntersectContext.AE[1][2] = IntersectContext.E[2].Y;
- IntersectContext.AE[2][2] = IntersectContext.E[2].Z;
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = -IntersectContext.AN[0];
- leb0 = box.Extent[1]*WWMath::Fabs(IntersectContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[1][2]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- /*
- ** AXIS_A1xE0
- */
- Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[0],&IntersectContext.AxE[1][0]);
- axis = IntersectContext.AxE[1][0];
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = IntersectContext.AN[1];
- leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][0]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][0]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- /*
- ** AXIS_A1xE1
- */
- Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[1],&IntersectContext.AxE[1][1]);
- axis = IntersectContext.AxE[1][1];
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = -IntersectContext.AN[1];
- leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][1]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][1]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- /*
- ** AXIS_A1xE2
- */
- Vector3::Cross_Product(Vector3(0,1,0),IntersectContext.E[2],&IntersectContext.AxE[1][2]);
- axis = IntersectContext.AxE[1][2];
- IntersectContext.AE[0][2] = IntersectContext.E[2].X;
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = -IntersectContext.AN[1];
- leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[2][2]) + box.Extent[2]*WWMath::Fabs(IntersectContext.AE[0][2]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- /*
- ** AXIS_A2xE0
- */
- Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[0],&IntersectContext.AxE[2][0]);
- axis = IntersectContext.AxE[2][0];
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = IntersectContext.AN[2];
- leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][0]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][0]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- /*
- ** AXIS_A2xE1
- */
- Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[1],&IntersectContext.AxE[2][1]);
- axis = IntersectContext.AxE[2][1];
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = -IntersectContext.AN[2];
- leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][1]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][1]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
-
- /*
- ** AXIS_A2xE2
- */
- Vector3::Cross_Product(Vector3(0,0,1),IntersectContext.E[2],&IntersectContext.AxE[2][2]);
- axis = IntersectContext.AxE[2][2];
- if (axis.Length2() > AXISLEN_EPSILON2) {
- dp = -IntersectContext.AN[2];
- leb0 = box.Extent[0]*WWMath::Fabs(IntersectContext.AE[1][2]) + box.Extent[1]*WWMath::Fabs(IntersectContext.AE[0][2]);
- if (aabtri_intersect_cross_axis(axis,dp,leb0)) return false;
- }
- return true;
- }
|