313 lines
14 KiB
C
313 lines
14 KiB
C
|
/*
|
||
|
** 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/colmath.h $*
|
||
|
* *
|
||
|
* Author:: Greg Hjelstrom *
|
||
|
* *
|
||
|
* $Modtime:: 5/04/01 8:25p $*
|
||
|
* *
|
||
|
* $Revision:: 19 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#if defined(_MSC_VER)
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
#ifndef COLMATH_H
|
||
|
#define COLMATH_H
|
||
|
|
||
|
#ifndef ALWAYS_H
|
||
|
#include "always.h"
|
||
|
#endif
|
||
|
|
||
|
#ifndef VECTOR3_H
|
||
|
#include "vector3.h"
|
||
|
#endif
|
||
|
|
||
|
#ifndef CASTRES_H
|
||
|
#include "castres.h"
|
||
|
#endif
|
||
|
|
||
|
class AAPlaneClass;
|
||
|
class PlaneClass;
|
||
|
class LineSegClass;
|
||
|
class TriClass;
|
||
|
class SphereClass;
|
||
|
class AABoxClass;
|
||
|
class OBBoxClass;
|
||
|
class FrustumClass;
|
||
|
|
||
|
const float COLLISION_EPSILON = 0.001f;
|
||
|
|
||
|
/*
|
||
|
** #define COLMATH_STAT_TRACKING to enable stat tracking for the collision math functions
|
||
|
*/
|
||
|
#ifdef WWDEBUG
|
||
|
#define COLMATH_STAT_TRACKING
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/**
|
||
|
** CollisionMath
|
||
|
** This is a collection of the low-level math functions for collision detection.
|
||
|
*/
|
||
|
class CollisionMath
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Intersect Functions.
|
||
|
// These functions simply return a bool indicating whether the two operands intersect.
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
static bool Intersection_Test(const AABoxClass & box,const TriClass & tri);
|
||
|
static bool Intersection_Test(const AABoxClass & box,const AABoxClass & box2);
|
||
|
static bool Intersection_Test(const AABoxClass & box,const OBBoxClass & box2);
|
||
|
static bool Intersection_Test(const OBBoxClass & box,const TriClass & tri);
|
||
|
static bool Intersection_Test(const OBBoxClass & box,const AABoxClass & box2);
|
||
|
static bool Intersection_Test(const OBBoxClass & box,const OBBoxClass & box2);
|
||
|
static bool Intersection_Test(const SphereClass & sphere,const AABoxClass & box);
|
||
|
static bool Intersection_Test(const SphereClass & sphere,const OBBoxClass & box);
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Overlap Functions.
|
||
|
// Classify the second operand with respect to the first operand.
|
||
|
// For example Overlap_Test(plane,point) tests whether 'point' is in front of or
|
||
|
// behind 'plane'.
|
||
|
// OverlapType: This enumeration is the result of an overlap test.
|
||
|
// It indicates whether the the object is in the positive (front/outside) space
|
||
|
// of the volume, the negative (back/inside) space of the volume, or both (overlapping)
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
enum OverlapType
|
||
|
{
|
||
|
POS = 0x01,
|
||
|
NEG = 0x02,
|
||
|
ON = 0x04,
|
||
|
BOTH = 0x08,
|
||
|
OUTSIDE = POS,
|
||
|
INSIDE = NEG,
|
||
|
OVERLAPPED = BOTH,
|
||
|
FRONT = POS,
|
||
|
BACK = NEG
|
||
|
};
|
||
|
|
||
|
// AAPlane functions. Where is operand B with respect to this AAPlane
|
||
|
static OverlapType Overlap_Test(const AAPlaneClass & plane,const Vector3 & point);
|
||
|
static OverlapType Overlap_Test(const AAPlaneClass & plane,const LineSegClass & line);
|
||
|
static OverlapType Overlap_Test(const AAPlaneClass & plane,const TriClass & tri);
|
||
|
static OverlapType Overlap_Test(const AAPlaneClass & plane,const SphereClass & sphere);
|
||
|
static OverlapType Overlap_Test(const AAPlaneClass & plane,const AABoxClass & box);
|
||
|
static OverlapType Overlap_Test(const AAPlaneClass & plane,const OBBoxClass & box);
|
||
|
|
||
|
// Plane functions. Where is operand B with respect to the plane
|
||
|
static OverlapType Overlap_Test(const PlaneClass & plane,const Vector3 & point);
|
||
|
static OverlapType Overlap_Test(const PlaneClass & plane,const LineSegClass & line);
|
||
|
static OverlapType Overlap_Test(const PlaneClass & plane,const TriClass & tri);
|
||
|
static OverlapType Overlap_Test(const PlaneClass & plane,const SphereClass & sphere);
|
||
|
static OverlapType Overlap_Test(const PlaneClass & plane,const Vector3 & center,const Vector3 & extent);
|
||
|
inline static OverlapType Overlap_Test(const PlaneClass & plane,const AABoxClass & box);
|
||
|
static OverlapType Overlap_Test(const PlaneClass & plane,const OBBoxClass & box);
|
||
|
|
||
|
// Sphere functions. Where is operand B with respect to the sphere
|
||
|
static OverlapType Overlap_Test(const SphereClass & sphere,const Vector3 & point);
|
||
|
static OverlapType Overlap_Test(const SphereClass & sphere,const LineSegClass & line);
|
||
|
static OverlapType Overlap_Test(const SphereClass & sphere,const TriClass & tri);
|
||
|
static OverlapType Overlap_Test(const SphereClass & sphere,const SphereClass & sphere2);
|
||
|
static OverlapType Overlap_Test(const SphereClass & sphere,const AABoxClass & aabox);
|
||
|
static OverlapType Overlap_Test(const SphereClass & sphere,const OBBoxClass & obbox);
|
||
|
|
||
|
// AABox functions. Where is operand B with respect to the AABox
|
||
|
static OverlapType Overlap_Test(const AABoxClass & box,const Vector3 & point);
|
||
|
static OverlapType Overlap_Test(const AABoxClass & box,const LineSegClass & line);
|
||
|
static OverlapType Overlap_Test(const AABoxClass & box,const TriClass & tri);
|
||
|
static OverlapType Overlap_Test(const AABoxClass & box,const AABoxClass & box2);
|
||
|
static OverlapType Overlap_Test(const AABoxClass & box,const OBBoxClass & obbox);
|
||
|
static OverlapType Overlap_Test(const AABoxClass & box,const SphereClass & sphere);
|
||
|
|
||
|
// OBBox functions, where is operand B with respect to the OBBox
|
||
|
static OverlapType Overlap_Test(const OBBoxClass & box,const Vector3 & point);
|
||
|
static OverlapType Overlap_Test(const OBBoxClass & box,const LineSegClass & line);
|
||
|
static OverlapType Overlap_Test(const OBBoxClass & box,const TriClass & tri);
|
||
|
static OverlapType Overlap_Test(const OBBoxClass & box,const AABoxClass & box2);
|
||
|
static OverlapType Overlap_Test(const OBBoxClass & box,const OBBoxClass & box2);
|
||
|
|
||
|
// Frustum functions
|
||
|
static OverlapType Overlap_Test(const FrustumClass & frustum,const Vector3 & point);
|
||
|
static OverlapType Overlap_Test(const FrustumClass & frustum,const TriClass & tri);
|
||
|
static OverlapType Overlap_Test(const FrustumClass & frustum,const SphereClass & sphere);
|
||
|
static OverlapType Overlap_Test(const FrustumClass & frustum,const AABoxClass & box);
|
||
|
static OverlapType Overlap_Test(const FrustumClass & frustum,const OBBoxClass & box);
|
||
|
|
||
|
// Frustum functions for hierachical culling systems.
|
||
|
// At your root node, just pass in planes_passed = 0, then the variable will be modified to
|
||
|
// indicate which planes that volume was inside. You can then pass that value in for the
|
||
|
// test of all child nodes and optimize away some of the tests. See AABTreeCullSystemClass
|
||
|
// for an example usage.
|
||
|
static OverlapType Overlap_Test(const FrustumClass & frustum,const AABoxClass & box,int & planes_passed);
|
||
|
static OverlapType Overlap_Test(const FrustumClass & frustum,const OBBoxClass & box,int & planes_passed);
|
||
|
|
||
|
// Miscellaneous other Overlap tests
|
||
|
static OverlapType Overlap_Test(const Vector3 & min,const Vector3 & max,const LineSegClass & line);
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Collision Functions.
|
||
|
// Collide the first operand into the last operand.
|
||
|
// For example Collide(box,move,tri) tests for collision between a box moving into
|
||
|
// a triangle.
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// Line segment functions. Intersect this line segment with the given object
|
||
|
static bool Collide(const LineSegClass & line,const AAPlaneClass & plane,CastResultStruct * result);
|
||
|
static bool Collide(const LineSegClass & line,const PlaneClass & plane,CastResultStruct * result);
|
||
|
static bool Collide(const LineSegClass & line,const TriClass & tri,CastResultStruct * result);
|
||
|
static bool Collide(const LineSegClass & line,const SphereClass & sphere,CastResultStruct * result);
|
||
|
static bool Collide(const LineSegClass & line,const AABoxClass & box,CastResultStruct * result);
|
||
|
static bool Collide(const LineSegClass & line,const OBBoxClass & box,CastResultStruct * result);
|
||
|
|
||
|
// AABox functions
|
||
|
static bool Collide(const AABoxClass & box,const Vector3 & move,const PlaneClass & plane,CastResultStruct * result);
|
||
|
static bool Collide(const AABoxClass & box,const Vector3 & move,const TriClass & tri,CastResultStruct * result);
|
||
|
static bool Collide(const AABoxClass & box,const Vector3 & move,const AABoxClass & box2,CastResultStruct * result);
|
||
|
static bool Collide(const AABoxClass & box,const Vector3 & move,const OBBoxClass & box2,const Vector3 & move2,CastResultStruct * result);
|
||
|
|
||
|
// OBBox functions
|
||
|
static bool Collide(const OBBoxClass & box,const Vector3 & move,const PlaneClass & plane,CastResultStruct * result);
|
||
|
static bool Collide(const OBBoxClass & box,const Vector3 & move,const TriClass & tri,const Vector3 & move2,CastResultStruct * result);
|
||
|
static bool Collide(const OBBoxClass & box,const Vector3 & move,const AABoxClass & box2,const Vector3 & move2,CastResultStruct * result);
|
||
|
static bool Collide(const OBBoxClass & box,const Vector3 & move,const OBBoxClass & box2,const Vector3 & move2,CastResultStruct * result);
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Stats
|
||
|
// Note that these functions will only work if you have stat tracking enabled
|
||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||
|
struct ColmathStatsStruct
|
||
|
{
|
||
|
ColmathStatsStruct(void);
|
||
|
void Reset(void);
|
||
|
|
||
|
int TotalCollisionCount;
|
||
|
int TotalCollisionHitCount;
|
||
|
|
||
|
int CollisionRayTriCount;
|
||
|
int CollisionRayTriHitCount;
|
||
|
|
||
|
int CollisionAABoxTriCount;
|
||
|
int CollisionAABoxTriHitCount;
|
||
|
int CollisionAABoxAABoxCount;
|
||
|
int CollisionAABoxAABoxHitCount;
|
||
|
|
||
|
int CollisionOBBoxTriCount;
|
||
|
int CollisionOBBoxTriHitCount;
|
||
|
int CollisionOBBoxAABoxCount;
|
||
|
int CollisionOBBoxAABoxHitCount;
|
||
|
int CollisionOBBoxOBBoxCount;
|
||
|
int CollisionOBBoxOBBoxHitCount;
|
||
|
};
|
||
|
|
||
|
static void Reset_Stats(void) { Stats.Reset(); }
|
||
|
static const ColmathStatsStruct & Get_Current_Stats(void) { return Stats; }
|
||
|
|
||
|
private:
|
||
|
|
||
|
static OverlapType eval_overlap_mask(int mask);
|
||
|
static OverlapType eval_overlap_collision(const CastResultStruct & res);
|
||
|
|
||
|
static const float COINCIDENCE_EPSILON;
|
||
|
|
||
|
static ColmathStatsStruct Stats;
|
||
|
};
|
||
|
|
||
|
|
||
|
inline CollisionMath::OverlapType CollisionMath::eval_overlap_mask(int mask)
|
||
|
{
|
||
|
// check if all verts are "ON"
|
||
|
if (mask == ON) {
|
||
|
return ON;
|
||
|
}
|
||
|
|
||
|
// check if all verts are either "ON" or "POS"
|
||
|
if ((mask & ~(POS | ON)) == 0) {
|
||
|
return POS;
|
||
|
}
|
||
|
|
||
|
// check if all verts are either "ON" or "BACK"
|
||
|
if ((mask & ~(NEG | ON)) == 0) {
|
||
|
return NEG;
|
||
|
}
|
||
|
|
||
|
// otherwise, poly spans the plane.
|
||
|
return BOTH;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline CollisionMath::OverlapType CollisionMath::eval_overlap_collision(const CastResultStruct & res)
|
||
|
{
|
||
|
if (res.Fraction < 1.0f) {
|
||
|
return BOTH;
|
||
|
} else {
|
||
|
if (res.StartBad) {
|
||
|
return NEG;
|
||
|
} else {
|
||
|
return POS;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
** Stat tracking Macros
|
||
|
*/
|
||
|
#ifdef COLMATH_STAT_TRACKING
|
||
|
#define TRACK_COLLISION_RAY_TRI Stats.CollisionRayTriCount++; Stats.TotalCollisionCount++;
|
||
|
#define TRACK_COLLISION_RAY_TRI_HIT Stats.CollisionRayTriHitCount++; Stats.TotalCollisionHitCount;
|
||
|
#define TRACK_COLLISION_AABOX_TRI Stats.CollisionAABoxTriCount++; Stats.TotalCollisionCount++;
|
||
|
#define TRACK_COLLISION_AABOX_TRI_HIT Stats.CollisionAABoxTriHitCount++; Stats.TotalCollisionHitCount++;
|
||
|
#define TRACK_COLLISION_AABOX_AABOX Stats.CollisionAABoxAABoxCount++; Stats.TotalCollisionCount++;
|
||
|
#define TRACK_COLLISION_AABOX_AABOX_HIT Stats.CollisionAABoxAABoxHitCount++; Stats.TotalCollisionHitCount++;
|
||
|
#define TRACK_COLLISION_OBBOX_TRI Stats.CollisionOBBoxTriCount++; Stats.TotalCollisionCount++;
|
||
|
#define TRACK_COLLISION_OBBOX_TRI_HIT Stats.CollisionOBBoxTriHitCount++; Stats.TotalCollisionHitCount++;
|
||
|
#define TRACK_COLLISION_OBBOX_AABOX Stats.CollisionOBBoxAABoxCount++; Stats.TotalCollisionCount++;
|
||
|
#define TRACK_COLLISION_OBBOX_AABOX_HIT Stats.CollisionOBBoxAABoxHitCount++; Stats.TotalCollisionHitCount++;
|
||
|
#define TRACK_COLLISION_OBBOX_OBBOX Stats.CollisionOBBoxOBBoxCount++; Stats.TotalCollisionCount++;
|
||
|
#define TRACK_COLLISION_OBBOX_OBBOX_HIT Stats.CollisionOBBoxOBBoxHitCount++; Stats.TotalCollisionHitCount++;
|
||
|
#else
|
||
|
#define TRACK_COLLISION_RAY_TRI
|
||
|
#define TRACK_COLLISION_RAY_TRI_HIT
|
||
|
#define TRACK_COLLISION_AABOX_TRI
|
||
|
#define TRACK_COLLISION_AABOX_TRI_HIT
|
||
|
#define TRACK_COLLISION_AABOX_AABOX
|
||
|
#define TRACK_COLLISION_AABOX_AABOX_HIT
|
||
|
#define TRACK_COLLISION_OBBOX_TRI
|
||
|
#define TRACK_COLLISION_OBBOX_TRI_HIT
|
||
|
#define TRACK_COLLISION_OBBOX_AABOX
|
||
|
#define TRACK_COLLISION_OBBOX_AABOX_HIT
|
||
|
#define TRACK_COLLISION_OBBOX_OBBOX
|
||
|
#define TRACK_COLLISION_OBBOX_OBBOX_HIT
|
||
|
#endif
|
||
|
|
||
|
#endif // COLMATH_H
|