Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
coltest.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WW3D *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/coltest.cpp $*
26 * *
27 * Author:: Greg Hjelstrom *
28 * *
29 * $Modtime:: 5/07/01 10:26a $*
30 * *
31 * $Revision:: 2 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37
38#include "coltest.h"
39
40
49
50AABoxCollisionTestClass::AABoxCollisionTestClass(const AABoxClass & aabox,const Vector3 & move,CastResultStruct * res,int collision_type) :
51 CollisionTestClass(res,collision_type),
52 Box(aabox),
53 Move(move)
54{
55 SweepMin = Box.Center - Box.Extent;
56 SweepMax = Box.Center + Box.Extent;
57
58 Vector3 endmin = Box.Center + move - Box.Extent;
59 Vector3 endmax = Box.Center + move + Box.Extent;
60
61 if (endmax.X > SweepMax.X) SweepMax.X = endmax.X;
62 if (endmax.Y > SweepMax.Y) SweepMax.Y = endmax.Y;
63 if (endmax.Z > SweepMax.Z) SweepMax.Z = endmax.Z;
64
65 if (endmin.X < SweepMin.X) SweepMin.X = endmin.X;
66 if (endmin.Y < SweepMin.Y) SweepMin.Y = endmin.Y;
67 if (endmin.Z < SweepMin.Z) SweepMin.Z = endmin.Z;
68}
69
70
72{
73// const float MOVE_THRESHOLD = 2.0f;
74// if (WWMath::Fabs(Move.X) + WWMath::Fabs(Move.Y) + WWMath::Fabs(Move.Z) > MOVE_THRESHOLD) {
75// CastResultStruct res;
76// return !Box.Cast_To_Box(Move,box,&res);
77// } else {
78 Vector3 min_corner;
79 Vector3 max_corner;
80 Vector3::Subtract(box.Center,box.Extent,&min_corner);
81 Vector3::Add(box.Center,box.Extent,&max_corner);
82
83 if ((SweepMin.X > max_corner.X) || (SweepMax.X < min_corner.X)) {
84 return true;
85 }
86
87 if ((SweepMin.Y > max_corner.Y) || (SweepMax.Y < min_corner.Y)) {
88 return true;
89 }
90
91 if ((SweepMin.Z > max_corner.Z) || (SweepMax.Z < min_corner.Z)) {
92 return true;
93 }
94 return false;
95// }
96}
97
98
100{
101
102#ifndef NDEBUG
103
104 int i;
105 Matrix3D tm(1);
106 switch(rotation) {
107 case ROTATE_NONE:
108 break;
109 case ROTATE_Z90:
111 break;
112 case ROTATE_Z180:
114 break;
115 case ROTATE_Z270:
117 break;
118 }
119
120#ifdef ALLOW_TEMPORARIES
121 Vector3 realcenter = tm * Box.Center;
122#else
123 Vector3 realcenter;
124 tm.mulVector3(Box.Center, realcenter);
125#endif
126
127 Vector3 pts[8];
128 Vector3 & min = SweepMin;
129 Vector3 & max = SweepMax;
130
131 pts[0].Set(min.X,min.Y,min.Z);
132 pts[1].Set(min.X,max.Y,min.Z);
133 pts[2].Set(max.X,max.Y,min.Z);
134 pts[3].Set(max.X,min.Y,min.Z);
135
136 pts[4].Set(min.X,min.Y,max.Z);
137 pts[5].Set(min.X,max.Y,max.Z);
138 pts[6].Set(max.X,max.Y,max.Z);
139 pts[7].Set(max.X,min.Y,max.Z);
140
141// for (i=0; i<8; i++) {
142// pts[i] = tm * pts[i];
143// }
144 tm.mulVector3Array(pts, 8);
145
146 Vector3 realmin = pts[0];
147 Vector3 realmax = pts[0];
148
149 for (i=1; i<8; i++) {
150 if (realmin.X >= pts[i].X) realmin.X = pts[i].X;
151 if (realmin.Y >= pts[i].Y) realmin.Y = pts[i].Y;
152 if (realmin.Z >= pts[i].Z) realmin.Z = pts[i].Z;
153
154 if (realmax.X <= pts[i].X) realmax.X = pts[i].X;
155 if (realmax.Y <= pts[i].Y) realmax.Y = pts[i].Y;
156 if (realmax.Z <= pts[i].Z) realmax.Z = pts[i].Z;
157 }
158
159
160#endif
161
162
163 // rotate the test by the desired rotation about the Z axis, special cased for
164 // 90 degree rotations about Z. arbitrary rotations cause the axis aligned
165 // box to not be aligned any more :-)
166 float tmp,minx,miny,maxx,maxy;
167 switch(rotation) {
168 case ROTATE_NONE:
169 break;
170
171 case ROTATE_Z90:
172 // rotate the center point and the move vector
173 tmp = Box.Center.X; Box.Center.X = -Box.Center.Y; Box.Center.Y = tmp;
174 tmp = Move.X; Move.X = -Move.Y; Move.Y = tmp;
175
176 // swap x and y for the extent
177 tmp = Box.Extent.X; Box.Extent.X = Box.Extent.Y; Box.Extent.Y = tmp;
178
179 // update sweep bounding box
180 minx = SweepMin.X; miny = SweepMin.Y; maxx = SweepMax.X; maxy = SweepMax.Y;
181 SweepMin.X = -maxy;
182 SweepMin.Y = minx;
183 SweepMax.X = -miny;
184 SweepMax.Y = maxx;
185 break;
186
187 case ROTATE_Z180:
188 // rotate center and move vector
189 Box.Center.X = -Box.Center.X;
190 Box.Center.Y = -Box.Center.Y;
191 Move.X = -Move.X;
192 Move.Y = -Move.Y;
193
194 // update min/max boxes
195 minx = SweepMin.X; miny = SweepMin.Y; maxx = SweepMax.X; maxy = SweepMax.Y;
196 SweepMin.X = -maxx;
197 SweepMin.Y = -maxy;
198 SweepMax.X = -minx;
199 SweepMax.Y = -miny;
200 break;
201
202 case ROTATE_Z270:
203 // rotate center and move.
204 tmp = Box.Center.X; Box.Center.X = Box.Center.Y; Box.Center.Y = -tmp;
205 tmp = Move.X; Move.X = Move.Y; Move.Y = -tmp;
206
207 // update extent (x and y axis swap)
208 tmp = Box.Extent.X; Box.Extent.X = Box.Extent.Y; Box.Extent.Y = tmp;
209
210 // update min/max boxes
211 minx = SweepMin.X; miny = SweepMin.Y; maxx = SweepMax.X; maxy = SweepMax.Y;
212 SweepMin.X = miny;
213 SweepMin.Y = -maxx;
214 SweepMax.X = maxy;
215 SweepMax.Y = -minx;
216 break;
217 }
218
219#ifndef NDEBUG
220
221 assert((Box.Center - realcenter).Length() < 0.001f);
222 assert((SweepMin - realmin).Length() < 0.001f);
223 assert((SweepMax - realmax).Length() < 0.001f);
224
225#endif
226}
227
228
230{
231 // NOTE: this function will expand the box to enclose the rotated
232 // form of the original box. In practice, this function was only
233 // implemented to double-check the results of the Translate and Rotate
234 // functions.
235 int i;
236 Vector3 tmpcenter = Box.Center;
237 Vector3 tmpextent = Box.Extent;
238 tm.Transform_Center_Extent_AABox(tmpcenter,tmpextent,&Box.Center,&Box.Extent);
239
240 Move = tm.Rotate_Vector(Move);
241
242 Vector3 pts[8];
243 Vector3 & min = SweepMin;
244 Vector3 & max = SweepMax;
245
246 pts[0].Set(min.X,min.Y,min.Z);
247 pts[1].Set(min.X,max.Y,min.Z);
248 pts[2].Set(max.X,max.Y,min.Z);
249 pts[3].Set(max.X,min.Y,min.Z);
250
251 pts[4].Set(min.X,min.Y,max.Z);
252 pts[5].Set(min.X,max.Y,max.Z);
253 pts[6].Set(max.X,max.Y,max.Z);
254 pts[7].Set(max.X,min.Y,max.Z);
255
256// for (i=0; i<8; i++) {
257// pts[i] = tm * pts[i];
258// }
259 tm.mulVector3Array(pts, 8);
260
261 Vector3 realmin = pts[0];
262 Vector3 realmax = pts[0];
263
264 for (i=1; i<8; i++) {
265 if (realmin.X >= pts[i].X) realmin.X = pts[i].X;
266 if (realmin.Y >= pts[i].Y) realmin.Y = pts[i].Y;
267 if (realmin.Z >= pts[i].Z) realmin.Z = pts[i].Z;
268
269 if (realmax.X <= pts[i].X) realmax.X = pts[i].X;
270 if (realmax.Y <= pts[i].Y) realmax.Y = pts[i].Y;
271 if (realmax.Z <= pts[i].Z) realmax.Z = pts[i].Z;
272 }
273
274 SweepMin = realmin;
275 SweepMax = realmax;
276}
277
278
279
281(
282 const OBBoxClass & obbox,
283 const Vector3 & move,
284 CastResultStruct * res,
285 int type
286) :
287 CollisionTestClass(res,type),
288 Box(obbox),
289 Move(move)
290{
291 Vector3 max_extent;
292 max_extent.X = WWMath::Fabs(Box.Basis[0][0] * Box.Extent.X) +
293 WWMath::Fabs(Box.Basis[0][1] * Box.Extent.Y) +
294 WWMath::Fabs(Box.Basis[0][2] * Box.Extent.Z) + 0.01f;
295
296 max_extent.Y = WWMath::Fabs(Box.Basis[1][0] * Box.Extent.X) +
297 WWMath::Fabs(Box.Basis[1][1] * Box.Extent.Y) +
298 WWMath::Fabs(Box.Basis[1][2] * Box.Extent.Z) + 0.01f;
299
300 max_extent.Z = WWMath::Fabs(Box.Basis[2][0] * Box.Extent.X) +
301 WWMath::Fabs(Box.Basis[2][1] * Box.Extent.Y) +
302 WWMath::Fabs(Box.Basis[2][2] * Box.Extent.Z) + 0.01f;
303
304 SweepMin = Box.Center - max_extent;
305 SweepMax = Box.Center + max_extent;
306
307 Vector3 endmin = Box.Center + move - max_extent;
308 Vector3 endmax = Box.Center + move + max_extent;
309
310 if (endmax.X > SweepMax.X) SweepMax.X = endmax.X;
311 if (endmax.Y > SweepMax.Y) SweepMax.Y = endmax.Y;
312 if (endmax.Z > SweepMax.Z) SweepMax.Z = endmax.Z;
313
314 if (endmin.X < SweepMin.X) SweepMin.X = endmin.X;
315 if (endmin.Y < SweepMin.Y) SweepMin.Y = endmin.Y;
316 if (endmin.Z < SweepMin.Z) SweepMin.Z = endmin.Z;
317}
318
327
339
341(
342 const AABoxCollisionTestClass & that,
343 const Matrix3D & tm
344) :
346{
349 Matrix3D::Transform_Vector(tm,that.Box.Center,&(Box.Center));
350 Box.Extent = that.Box.Extent;
351 Box.Basis = tm; // copies the 3x3 rotation portion of the transform
352}
353
354
356{
357 Vector3 min_corner;
358 Vector3 max_corner;
359 Vector3::Subtract(box.Center,box.Extent,&min_corner);
360 Vector3::Add(box.Center,box.Extent,&max_corner);
361
362 if ((SweepMin.X > max_corner.X) || (SweepMax.X < min_corner.X)) {
363 return true;
364 }
365
366 if ((SweepMin.Y > max_corner.Y) || (SweepMax.Y < min_corner.Y)) {
367 return true;
368 }
369
370 if ((SweepMin.Z > max_corner.Z) || (SweepMax.Z < min_corner.Z)) {
371 return true;
372 }
373 return false;
374}
375
#define min(x, y)
Definition BaseType.h:101
#define max(x, y)
Definition BaseType.h:105
if(pDbg)
Vector3 Center
Definition aabox.h:123
Vector3 Extent
Definition aabox.h:124
void Transform(const Matrix3D &tm)
Definition coltest.cpp:229
AABoxCollisionTestClass(const AABoxClass &aabox, const Vector3 &move, CastResultStruct *res, int collision_type=COLL_TYPE_0)
Definition coltest.cpp:50
bool Cull(const Vector3 &min, const Vector3 &max)
Definition coltest.h:239
void Rotate(ROTATION_TYPE rotation)
Definition coltest.cpp:99
CollisionTestClass(CastResultStruct *res, int collision_type)
Definition coltest.h:104
static const Matrix3D RotateZ90
Definition matrix3d.h:379
static const Matrix3D RotateZ270
Definition matrix3d.h:381
void mulVector3Array(const Vector3 *in, Vector3 *out, int count) const
Definition matrix3d.h:1661
Vector3 Rotate_Vector(const Vector3 &vect) const
Definition matrix3d.cpp:300
void mulVector3(const Vector3 &in, Vector3 &out) const
Definition matrix3d.h:1650
static WWINLINE void Transform_Vector(const Matrix3D &tm, const Vector3 &in, Vector3 *out)
Definition matrix3d.h:1742
void Transform_Min_Max_AABox(const Vector3 &min, const Vector3 &max, Vector3 *set_min, Vector3 *set_max) const
Definition matrix3d.cpp:999
static const Matrix3D RotateZ180
Definition matrix3d.h:380
void Transform_Center_Extent_AABox(const Vector3 &center, const Vector3 &extent, Vector3 *set_center, Vector3 *set_extent) const
static void Transform(const Matrix3D &tm, const OBBoxClass &in, OBBoxClass *out)
Definition obbox.h:161
bool Cull(const Vector3 &min, const Vector3 &max)
Definition coltest.h:295
OBBoxCollisionTestClass(const OBBoxClass &obbox, const Vector3 &move, CastResultStruct *res, int type=COLL_TYPE_0)
Definition coltest.cpp:281
float X
Definition vector3.h:90
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
static WWINLINE void Subtract(const Vector3 &a, const Vector3 &b, Vector3 *c)
Definition vector3.h:576
static WWINLINE void Add(const Vector3 &a, const Vector3 &b, Vector3 *c)
Definition vector3.h:555
WWINLINE void Set(float x, float y, float z)
Definition vector3.h:103
static WWINLINE float Fabs(float val)
Definition wwmath.h:113