| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679 |
- /*
- ** 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/aabox.h $*
- * *
- * Author:: Greg_h *
- * *
- * $Modtime:: 5/08/01 6:35p $*
- * *
- * $Revision:: 30 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * AABoxClass::Transform -- transform an aabox *
- * AABoxClass::Translate -- transform an aabox *
- * AABoxClass::Init -- create a box which bounds the given points *
- * AABoxClass::Init -- initialize from a min-max form of a box *
- * AABoxClass::Init_Min_Max -- init the box from a min and max vector *
- * AABoxClass::Add_Point -- expand the box to contain the given point *
- * AABoxClass::Project_To_Axis -- compute projection onto the given axis *
- * AABoxClass::Intersects -- test for intersection with another static aabox *
- * AABoxClass::Add_Box -- expand this box to enclose the passed box *
- * AABoxClass::Add_Box -- Expand this box to enclose the passed box *
- * MinMaxAABoxClass::Init -- init the box from an array of points *
- * MinMaxAABoxClass::Init -- initializes this box from a center-extent box *
- * MinMaxAABoxClass::Add_Point -- updates this box so it encloses the given point *
- * MinMaxAABoxClass::Add_Box -- update this box to enclose the given box *
- * MinMaxAABoxClass::Add_Box -- Updates this box to enclose the specified box *
- * MinMaxAABoxClass::Transform -- Updates this box to enclose its transformed version *
- * MinMaxAABoxClass::Translate -- translates the box *
- * AABoxClass::Init -- Init from a line segment *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #ifndef AABOX_H
- #define AABOX_H
- #include "always.h"
- #include "matrix3d.h"
- #include "lineseg.h"
- #include "colmath.h"
- class AABoxClass;
- class MinMaxAABoxClass;
- class OBBoxClass;
- class TriClass;
- class PlaneClass;
- struct CastResultStruct;
- /*
- ** AABoxClass
- **
- ** Axis-Aligned Boxes. I've coded these similar to the OrientedBoxClass only
- ** without a rotation matrix. A similar algorithm is used to test the box
- ** for intersection.
- */
- class AABoxClass
- {
- public:
- WWINLINE AABoxClass(void) { }
- WWINLINE AABoxClass(const Vector3 & center,const Vector3 & extent) :
- Center(center),
- Extent(extent)
- { }
- AABoxClass(const MinMaxAABoxClass & minmaxbox) { Init(minmaxbox); }
- AABoxClass(Vector3 * points,int num) { Init(points,num); }
- bool operator== (const AABoxClass &src);
- bool operator!= (const AABoxClass &src);
- WWINLINE void Init(const Vector3& center,const Vector3 & extent) { Center = center; Extent = extent; }
- WWINLINE void Init(Vector3 * points,int num);
- WWINLINE void Init(const MinMaxAABoxClass & minmaxbox);
- void Init(const LineSegClass & line);
- void Init_Min_Max(const Vector3 & min,const Vector3 & max);
- void Init_Random(float min_center = -1.0f,float max_center = 1.0f,float min_extent = 0.5f,float max_extent = 1.0f);
- void Add_Point(const Vector3 & point);
- void Add_Box(const AABoxClass & b);
- void Add_Box(const MinMaxAABoxClass & b);
- float Project_To_Axis(const Vector3 & axis) const;
- void Transform(const Matrix3D & tm);
- void Translate(const Vector3 & pos);
- WWINLINE float Volume(void) const { return 2.0*Extent.X * 2.0*Extent.Y * 2.0*Extent.Z; }
- WWINLINE bool Contains(const Vector3 & point) const;
- WWINLINE bool Contains(const AABoxClass & other_box) const;
- WWINLINE bool Contains(const MinMaxAABoxClass & other_box) const;
- static void Transform(const Matrix3D & tm,const AABoxClass & in,AABoxClass * out);
- Vector3 Center; // world space center
- Vector3 Extent; // size of the box in the three directions
- };
- /*
- ** MinMaxAABoxClass
- ** This is another form of an AABox. It can be faster to build one of these
- ** and then convert it into a center-extent AABox in some cases. Its purpose
- ** is basically that.
- */
- class MinMaxAABoxClass
- {
- public:
- WWINLINE MinMaxAABoxClass(void) { }
- WWINLINE MinMaxAABoxClass(const Vector3 & min_corner,const Vector3 & max_corner) :
- MinCorner(min_corner),
- MaxCorner(max_corner)
- {
- }
-
- WWINLINE MinMaxAABoxClass(Vector3 * points,int num) { Init(points,num); }
- WWINLINE MinMaxAABoxClass(const AABoxClass & that) { Init(that); }
- WWINLINE void Init(Vector3 * points,int num);
- WWINLINE void Init(const AABoxClass & box);
- void Init_Empty(void);
-
- void Add_Point(const Vector3 & point);
- void Add_Box(const MinMaxAABoxClass & box);
- void Add_Box(const AABoxClass & box);
- void Add_Box(const Vector3 & min_corner,const Vector3 & max_corner);
- void Transform(const Matrix3D & tm);
- void Translate(const Vector3 & pos);
- WWINLINE float Volume(void) const { Vector3 size = MaxCorner - MinCorner; return size.X*size.Y*size.Z; }
- Vector3 MinCorner;
- Vector3 MaxCorner;
- };
- /***********************************************************************************************
- * AABoxClass::Transform -- transform an aabox *
- * *
- * Note that this function expands the box to enclose its transformed form. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/24/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Transform(const Matrix3D & tm)
- {
- Vector3 oldcenter = Center;
- Vector3 oldextent = Extent;
- tm.Transform_Center_Extent_AABox(oldcenter,oldextent,&Center,&Extent);
- }
- /***********************************************************************************************
- * AABoxClass::Translate -- translate an aabox *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/24/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Translate(const Vector3 & trans)
- {
- Center += trans;
- }
- /***********************************************************************************************
- * AABoxClass::operator== -- Comparison operator *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 6/21/00 PDS : Created. *
- *=============================================================================================*/
- WWINLINE bool AABoxClass::operator== (const AABoxClass &src)
- {
- return (Center == src.Center) && (Extent == src.Extent);
- }
- /***********************************************************************************************
- * AABoxClass::operator!= -- Comparison operator *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 6/21/00 PDS : Created. *
- *=============================================================================================*/
- WWINLINE bool AABoxClass::operator!= (const AABoxClass &src)
- {
- return (Center != src.Center) || (Extent != src.Extent);
- }
- /***********************************************************************************************
- * AABoxClass::Init -- create a box which bounds the given points *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/24/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Init(Vector3 * points,int num)
- {
- Vector3 Min = points[0];
- Vector3 Max = points[0];
-
- for (int i=1; i<num; i++) {
- if (Min.X > points[i].X) Min.X = points[i].X;
- if (Min.Y > points[i].Y) Min.Y = points[i].Y;
- if (Min.Z > points[i].Z) Min.Z = points[i].Z;
- if (Max.X < points[i].X) Max.X = points[i].X;
- if (Max.Y < points[i].Y) Max.Y = points[i].Y;
- if (Max.Z < points[i].Z) Max.Z = points[i].Z;
- }
-
- Center = (Max + Min) * 0.5f;
- Extent = (Max - Min) * 0.5f;
- }
- /***********************************************************************************************
- * AABoxClass::Init -- initialize from a min-max form of a box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Init(const MinMaxAABoxClass & mmbox)
- {
- Center = (mmbox.MaxCorner + mmbox.MinCorner) * 0.5f;
- Extent = (mmbox.MaxCorner - mmbox.MinCorner) * 0.5f;
- }
- /***********************************************************************************************
- * AABoxClass::Init -- Init from a line segment *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/27/2000 gth : Created. *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Init(const LineSegClass & line)
- {
- Vector3 min_corner = line.Get_P0();
- Vector3 max_corner = line.Get_P0();
-
- if (min_corner.X > line.Get_P1().X) min_corner.X = line.Get_P1().X;
- if (min_corner.Y > line.Get_P1().Y) min_corner.Y = line.Get_P1().Y;
- if (min_corner.Z > line.Get_P1().Z) min_corner.Z = line.Get_P1().Z;
- if (max_corner.X < line.Get_P1().X) max_corner.X = line.Get_P1().X;
- if (max_corner.Y < line.Get_P1().Y) max_corner.Y = line.Get_P1().Y;
- if (max_corner.Z < line.Get_P1().Z) max_corner.Z = line.Get_P1().Z;
- Center = (max_corner + min_corner) * 0.5f;
- Extent = (max_corner - min_corner) * 0.5f;
- }
- /***********************************************************************************************
- * AABoxClass::Init_Min_Max -- init the box from a min and max vector *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/9/99 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Init_Min_Max(const Vector3 & min,const Vector3 & max)
- {
- Center = (max + min) * 0.5f;
- Extent = (max - min) * 0.5f;
- }
- /***********************************************************************************************
- * AABoxClass::Add_Point -- expand the box to contain the given point *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/24/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Add_Point(const Vector3 & point)
- {
- Vector3 Min = Center - Extent;
- Vector3 Max = Center + Extent;
- if (Min.X > point.X) Min.X = point.X;
- if (Min.Y > point.Y) Min.Y = point.Y;
- if (Min.Z > point.Z) Min.Z = point.Z;
- if (Max.X < point.X) Max.X = point.X;
- if (Max.Y < point.Y) Max.Y = point.Y;
- if (Max.Z < point.Z) Max.Z = point.Z;
- Center = (Max + Min) / 2.0f;
- Extent = (Max - Min) / 2.0f;
- }
- /***********************************************************************************************
- * AABoxClass::Add_Box -- expand this box to enclose the passed box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- * 9/29/2000 gth : Ok to add boxes with zero extent *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Add_Box(const AABoxClass & b)
- {
- Vector3 newmin = Center - Extent;
- Vector3 newmax = Center + Extent;
- newmin.Update_Min(b.Center - b.Extent);
- newmax.Update_Max(b.Center + b.Extent);
- Center = (newmax + newmin) * 0.5f;
- Extent = (newmax - newmin) * 0.5f;
- }
- /***********************************************************************************************
- * AABoxClass::Add_Box -- Expand this box to enclose the passed box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- * 9/29/2000 gth : Ok to add boxes with zero extent *
- *=============================================================================================*/
- WWINLINE void AABoxClass::Add_Box(const MinMaxAABoxClass & b)
- {
- Vector3 newmin = Center - Extent;
- Vector3 newmax = Center + Extent;
- newmin.Update_Min(b.MinCorner);
- newmax.Update_Max(b.MaxCorner);
- Center = (newmax + newmin) * 0.5f;
- Extent = (newmax - newmin) * 0.5f;
- }
- /***********************************************************************************************
- * AABoxClass::Project_To_Axis -- compute projection onto the given axis *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 2/24/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE float AABoxClass::Project_To_Axis(const Vector3 & axis) const
- {
- float x = Extent[0] * axis[0];
- float y = Extent[1] * axis[1];
- float z = Extent[2] * axis[2];
- // projection is the sum of the absolute values of the projections of the three extents
- return (WWMath::Fabs(x) + WWMath::Fabs(y) + WWMath::Fabs(z));
- }
- /***********************************************************************************************
- * AABoxClass::Contains -- Test whether this box contains the given box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/2/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE bool AABoxClass::Contains(const AABoxClass & other_box) const
- {
- return CollisionMath::Overlap_Test(*this,other_box) == CollisionMath::INSIDE;
- }
- /***********************************************************************************************
- * AABoxClass::Contains -- Test whether this box contains the given box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/2/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE bool AABoxClass::Contains(const MinMaxAABoxClass & other_box) const
- {
- Vector3 bmin = Center - Extent;
- Vector3 bmax = Center + Extent;
- if (other_box.MinCorner.X < bmin.X) return false;
- if (other_box.MinCorner.Y < bmin.Y) return false;
- if (other_box.MinCorner.Z < bmin.Z) return false;
- if (other_box.MaxCorner.X > bmax.X) return false;
- if (other_box.MaxCorner.Y > bmax.Y) return false;
- if (other_box.MaxCorner.Z > bmax.Z) return false;
- return true;
- }
- /***********************************************************************************************
- * AABoxClass::Contains -- test whether this box contains the given point *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 9/2/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE bool AABoxClass::Contains(const Vector3 & point) const
- {
- return CollisionMath::Overlap_Test(*this,point) == CollisionMath::INSIDE;
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Init -- init the box from an array of points *
- * *
- * Makes a box which encloses the given array of points *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Init(Vector3 * points,int num)
- {
- assert(num > 0);
- assert(points != NULL);
- MinCorner = points[0];
- MaxCorner = points[0];
- for (int i=0; i<num; i++) {
- MinCorner.Update_Min(points[i]);
- MaxCorner.Update_Max(points[i]);
- }
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Init -- initializes this box from a center-extent box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Init(const AABoxClass & box)
- {
- MinCorner = box.Center - box.Extent;
- MaxCorner = box.Center + box.Extent;
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Add_Point -- updates this box so it encloses the given point *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Add_Point(const Vector3 & point)
- {
- MinCorner.Update_Min(point);
- MaxCorner.Update_Max(point);
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Add_Box -- update this box to enclose the given box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Add_Box(const MinMaxAABoxClass & box)
- {
- if (box.MinCorner == box.MaxCorner) return;
- MinCorner.Update_Min(box.MinCorner);
- MaxCorner.Update_Max(box.MaxCorner);
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Add_Box -- update this box to enclose the given box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Add_Box(const AABoxClass & box)
- {
- if (box.Extent == Vector3(0.0f, 0.0f, 0.0f)) return;
- MinCorner.Update_Min(box.Center - box.Extent);
- MaxCorner.Update_Max(box.Center + box.Extent);
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Add_Box -- Updates this box to enclose the specified box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Add_Box(const Vector3 & min_corner,const Vector3 & max_corner)
- {
- assert(max_corner.X >= min_corner.X);
- assert(max_corner.Y >= min_corner.Y);
- assert(max_corner.Z >= min_corner.Z);
- if (min_corner == max_corner) return;
- MinCorner.Update_Min(min_corner);
- MaxCorner.Update_Max(max_corner);
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Transform -- Updates this box to enclose its transformed version *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Transform(const Matrix3D & tm)
- {
- Vector3 oldmin = MinCorner;
- Vector3 oldmax = MaxCorner;
- tm.Transform_Min_Max_AABox(oldmin,oldmax,&MinCorner,&MaxCorner);
- }
- /***********************************************************************************************
- * MinMaxAABoxClass::Translate -- translates the box *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 7/31/98 GTH : Created. *
- *=============================================================================================*/
- WWINLINE void MinMaxAABoxClass::Translate(const Vector3 & pos)
- {
- MinCorner+=pos;
- MaxCorner+=pos;
- }
- #endif
|