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/ww3d2/coltest.h

311 lines
No EOL
10 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 : WW3D *
* *
* $Archive:: /VSS_Sync/ww3d2/coltest.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 9/12/01 10:01p $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef COLTEST_H
#define COLTEST_H
#include "always.h"
#include "castres.h"
#include "lineseg.h"
#include "aabox.h"
#include "obbox.h"
#include "tri.h"
#include "colmath.h"
#include "coltype.h"
class RenderObjClass;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CollisionTestClass
//
// Each type of collision test will have an associated class which
// ties together all of the information necessary for the test.
// These classes also provide a perfect place to add any information
// which can be pre-calculated.
//
// The base class: CollisionTestClass simply contains a pointer to
// the user's CastResultStruct which will contain the results of
// the collision test. I store a pointer to a result structure
// because in some cases, new CollisionTestClasses are created in
// the process of checking (e.g. if the test needs to be transformed
// into another coordinate system) and I did not want to be
// constantly copying the result structure around. So, the user
// must allocate a result structure (usually on the stack) and keep it
// until the CollisionTestClass is discarded.
//
// Every CollisionTestClass should have the following functions:
//
// bool Cull(const Vector3 & min,const Vector3 & max);
// bool Cull(const AABoxClass & box);
// bool Cast_To_Triangle(const TriClass & tri);
//
// These are not virtual because I don't want to pay the price of virtual function
// calls at the point in the code where these are used. It may be possible to
// write template functions if we use these exact function prototpyes for all
// collision test classes though.
//
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CollisionTestClass
{
public:
CollisionTestClass(CastResultStruct * res,int collision_type);
CollisionTestClass(const CollisionTestClass & that);
public:
CastResultStruct * Result;
int CollisionType;
RenderObjClass * CollidedRenderObj;
};
inline CollisionTestClass::CollisionTestClass(CastResultStruct * res,int collision_type) :
Result(res),
CollisionType(collision_type),
CollidedRenderObj(NULL)
{
}
inline CollisionTestClass::CollisionTestClass(const CollisionTestClass & that) :
Result(that.Result),
CollisionType(that.CollisionType),
CollidedRenderObj(that.CollidedRenderObj)
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// RayCollisionTestClass
//
// Contains a linesegment to be tested and of course the inherited
// pointer to a CollisionStruct for the result
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class RayCollisionTestClass : public CollisionTestClass
{
public:
RayCollisionTestClass(const LineSegClass & ray,CastResultStruct * res,int collision_type = COLLISION_TYPE_0,bool ignore_translucent_meshes=false);
RayCollisionTestClass(const RayCollisionTestClass & raytest,const Matrix3D & tm);
bool Cull(const Vector3 & min,const Vector3 & max);
bool Cull(const AABoxClass & box);
bool Cast_To_Triangle(const TriClass & tri);
public:
LineSegClass Ray;
bool IgnoreTranslucentMeshes;
private:
// not implemented
RayCollisionTestClass(const RayCollisionTestClass &);
RayCollisionTestClass & operator = (const RayCollisionTestClass &);
};
inline RayCollisionTestClass::RayCollisionTestClass(const LineSegClass & ray,CastResultStruct * res,int collision_type,bool ignore_translucent_meshes) :
CollisionTestClass(res,collision_type),
Ray(ray),
IgnoreTranslucentMeshes(ignore_translucent_meshes)
{
}
inline RayCollisionTestClass::RayCollisionTestClass(const RayCollisionTestClass & raytest,const Matrix3D & tm) :
CollisionTestClass(raytest),
Ray(raytest.Ray,tm),
IgnoreTranslucentMeshes(raytest.IgnoreTranslucentMeshes)
{
}
inline bool RayCollisionTestClass::Cull(const Vector3 & min,const Vector3 & max)
{
return (CollisionMath::Overlap_Test(min,max,Ray) == CollisionMath::POS);
}
inline bool RayCollisionTestClass::Cull(const AABoxClass & box)
{
return (CollisionMath::Overlap_Test(box,Ray) == CollisionMath::POS);
}
inline bool RayCollisionTestClass::Cast_To_Triangle(const TriClass & tri)
{
return CollisionMath::Collide(Ray,tri,Result);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AABoxCollisionTestClass
//
// Contains an Axis Aligned Box and a movement vector to be tested
// for collision. Also adds Min and Max vectors both for the initial
// box and for the volume swept out by the box.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class AABoxCollisionTestClass : public CollisionTestClass
{
public:
AABoxCollisionTestClass(const AABoxClass & aabox,const Vector3 & move,CastResultStruct * res,int collision_type = COLLISION_TYPE_0);
AABoxCollisionTestClass(const AABoxCollisionTestClass & that);
enum ROTATION_TYPE
{
ROTATE_NONE = 0,
ROTATE_Z90,
ROTATE_Z180,
ROTATE_Z270
};
bool Cull(const Vector3 & min,const Vector3 & max);
bool Cull(const AABoxClass & box);
bool Cast_To_Triangle(const TriClass & tri);
void Translate(const Vector3 & translation);
void Rotate(ROTATION_TYPE rotation);
void Transform(const Matrix3D & tm);
public:
AABoxClass Box;
Vector3 Move;
Vector3 SweepMin;
Vector3 SweepMax;
private:
// not implemented
AABoxCollisionTestClass & operator = (const AABoxCollisionTestClass &);
};
inline void AABoxCollisionTestClass::Translate(const Vector3 & translation)
{
// translate the test by the desired translation vector
Box.Center += translation;
SweepMin += translation;
SweepMax += translation;
}
inline bool AABoxCollisionTestClass::Cull(const Vector3 & min,const Vector3 & max)
{
if ((SweepMin.X > max.X) || (SweepMax.X < min.X)) {
return true;
}
if ((SweepMin.Y > max.Y) || (SweepMax.Y < min.Y)) {
return true;
}
if ((SweepMin.Z > max.Z) || (SweepMax.Z < min.Z)) {
return true;
}
return false;
}
inline bool AABoxCollisionTestClass::Cast_To_Triangle(const TriClass & tri)
{
return CollisionMath::Collide(Box,Move,tri,Result);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// OBBoxCollisionTestClass
//
// Contains an Oriented Bounding Box and a movement vector to be tested
// for collision. Also adds Min and Max vectors (axis aligned box)
// both for the initial box and for the volume swept out by the box.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
class OBBoxCollisionTestClass : public CollisionTestClass
{
public:
OBBoxCollisionTestClass(const OBBoxClass & obbox,const Vector3 & move,CastResultStruct * res,int type = COLLISION_TYPE_0);
OBBoxCollisionTestClass(const OBBoxCollisionTestClass & that);
OBBoxCollisionTestClass(const OBBoxCollisionTestClass & that,const Matrix3D & tm);
OBBoxCollisionTestClass(const AABoxCollisionTestClass & that,const Matrix3D & tm);
bool Cull(const Vector3 & min,const Vector3 & max);
bool Cull(const AABoxClass & box);
bool Cast_To_Triangle(const TriClass & tri);
public:
OBBoxClass Box;
Vector3 Move;
Vector3 SweepMin;
Vector3 SweepMax;
private:
// not implemented
OBBoxCollisionTestClass & operator = (const OBBoxCollisionTestClass &);
};
inline bool OBBoxCollisionTestClass::Cull(const Vector3 & min,const Vector3 & max)
{
if ((SweepMin.X > max.X) || (SweepMax.X < min.X)) {
return true;
}
if ((SweepMin.Y > max.Y) || (SweepMax.Y < min.Y)) {
return true;
}
if ((SweepMin.Z > max.Z) || (SweepMax.Z < min.Z)) {
return true;
}
return false;
}
inline bool OBBoxCollisionTestClass::Cast_To_Triangle(const TriClass & tri)
{
return CollisionMath::Collide(Box,Move,tri,Vector3(0,0,0),Result);
}
#endif