This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/WWMath/colmath.h

313 lines
14 KiB
C
Raw Permalink Normal View History

/*
** 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