| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184 |
- /*
- ** Command & Conquer Renegade(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:: 1/15/02 2:46p $*
- * *
- * $Revision:: 19 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * 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.N;
- set_norm.Normalize();
- break;
- case AXIS_N:
- set_norm = -CollisionContext.Side * CollisionContext.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.N;
- set_norm.Normalize();
- 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;
- 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;
- }
|