1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
8
9 RTCW MP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW MP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 RCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Quake III Arena source code; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ===========================================================================
23 */
24 //
25 // q_math.c -- stateless support routines that are included in each code module
26
27 // Some of the vector functions are static inline in q_shared.h. q3asm
28 // doesn't understand static functions though, so we only want them in
29 // one file. That's what this is about.
30 #ifdef Q3_VM
31 #define __Q3_VM_MATH
32 #endif
33
34 #include "q_shared.h"
35
36 vec3_t vec3_origin = {0,0,0};
37 vec3_t axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
38
39
40 vec4_t colorBlack = {0, 0, 0, 1};
41 vec4_t colorRed = {1, 0, 0, 1};
42 vec4_t colorGreen = {0, 1, 0, 1};
43 vec4_t colorBlue = {0, 0, 1, 1};
44 vec4_t colorYellow = {1, 1, 0, 1};
45 vec4_t colorMagenta= {1, 0, 1, 1};
46 vec4_t colorCyan = {0, 1, 1, 1};
47 vec4_t colorWhite = {1, 1, 1, 1};
48 vec4_t colorLtGrey = {0.75, 0.75, 0.75, 1};
49 vec4_t colorMdGrey = {0.5, 0.5, 0.5, 1};
50 vec4_t colorDkGrey = {0.25, 0.25, 0.25, 1};
51
52 vec4_t g_color_table[8] =
53 {
54 {0.0, 0.0, 0.0, 1.0},
55 {1.0, 0.0, 0.0, 1.0},
56 {0.0, 1.0, 0.0, 1.0},
57 {1.0, 1.0, 0.0, 1.0},
58 {0.0, 0.0, 1.0, 1.0},
59 {0.0, 1.0, 1.0, 1.0},
60 {1.0, 0.0, 1.0, 1.0},
61 {1.0, 1.0, 1.0, 1.0},
62 };
63
64
65 vec3_t bytedirs[NUMVERTEXNORMALS] =
66 {
67 {-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f},
68 {-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f},
69 {-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f},
70 {0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f},
71 {0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f},
72 {0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f},
73 {0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f},
74 {0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f},
75 {-0.809017f, 0.309017f, 0.500000f},{-0.587785f, 0.425325f, 0.688191f},
76 {-0.850651f, 0.525731f, 0.000000f},{-0.864188f, 0.442863f, 0.238856f},
77 {-0.716567f, 0.681718f, 0.147621f},{-0.688191f, 0.587785f, 0.425325f},
78 {-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f},
79 {-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f},
80 {-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f},
81 {0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f},
82 {0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f},
83 {0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f},
84 {-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f},
85 {0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f},
86 {0.238856f, 0.864188f, -0.442863f},{0.262866f, 0.951056f, -0.162460f},
87 {0.500000f, 0.809017f, -0.309017f},{0.850651f, 0.525731f, 0.000000f},
88 {0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f},
89 {0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f},
90 {0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f},
91 {0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f},
92 {0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f},
93 {1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f},
94 {0.850651f, -0.525731f, 0.000000f},{0.955423f, -0.295242f, 0.000000f},
95 {0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f},
96 {0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f},
97 {0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f},
98 {0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f},
99 {0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f},
100 {0.681718f, -0.147621f, -0.716567f},{0.850651f, 0.000000f, -0.525731f},
101 {0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f},
102 {0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f},
103 {0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f},
104 {0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f},
105 {0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f},
106 {-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f},
107 {-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f},
108 {-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f},
109 {0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f},
110 {0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f},
111 {-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f},
112 {0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f},
113 {0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f},
114 {0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f},
115 {0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f},
116 {0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f},
117 {0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f},
118 {0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f},
119 {0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f},
120 {0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f},
121 {0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f},
122 {0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f},
123 {0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f},
124 {-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f},
125 {-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f},
126 {-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f},
127 {-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f},
128 {-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f},
129 {-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f},
130 {-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f},
131 {-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f},
132 {-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f},
133 {-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f},
134 {0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f},
135 {0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f},
136 {0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f},
137 {0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f},
138 {-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f},
139 {-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f},
140 {-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f},
141 {-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f},
142 {-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f},
143 {-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f},
144 {-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f},
145 {-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f},
146 {-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f},
147 {-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f}
148 };
149
150 //==============================================================
151
Q_rand(int * seed)152 int Q_rand( int *seed ) {
153 *seed = ( 69069U * *seed + 1U );
154 return *seed;
155 }
156
Q_random(int * seed)157 float Q_random( int *seed ) {
158 return ( Q_rand( seed ) & 0xffff ) / (float)0x10000;
159 }
160
Q_crandom(int * seed)161 float Q_crandom( int *seed ) {
162 return 2.0 * ( Q_random( seed ) - 0.5 );
163 }
164
165 //=======================================================
166
ClampChar(int i)167 signed char ClampChar( int i ) {
168 if ( i < -128 ) {
169 return -128;
170 }
171 if ( i > 127 ) {
172 return 127;
173 }
174 return i;
175 }
176
ClampShort(int i)177 signed short ClampShort( int i ) {
178 if ( i < -32768 ) {
179 return -32768;
180 }
181 if ( i > 0x7fff ) {
182 return 0x7fff;
183 }
184 return i;
185 }
186
187
188 // this isn't a real cheap function to call!
DirToByte(vec3_t dir)189 int DirToByte( vec3_t dir ) {
190 int i, best;
191 float d, bestd;
192
193 if ( !dir ) {
194 return 0;
195 }
196
197 bestd = 0;
198 best = 0;
199 for (i=0 ; i<NUMVERTEXNORMALS ; i++)
200 {
201 d = DotProduct (dir, bytedirs[i]);
202 if (d > bestd)
203 {
204 bestd = d;
205 best = i;
206 }
207 }
208
209 return best;
210 }
211
ByteToDir(int b,vec3_t dir)212 void ByteToDir( int b, vec3_t dir ) {
213 if ( b < 0 || b >= NUMVERTEXNORMALS ) {
214 VectorCopy( vec3_origin, dir );
215 return;
216 }
217 VectorCopy (bytedirs[b], dir);
218 }
219
220
ColorBytes3(float r,float g,float b)221 unsigned ColorBytes3 (float r, float g, float b) {
222 unsigned i;
223
224 ( (byte *)&i )[0] = r * 255;
225 ( (byte *)&i )[1] = g * 255;
226 ( (byte *)&i )[2] = b * 255;
227
228 return i;
229 }
230
ColorBytes4(float r,float g,float b,float a)231 unsigned ColorBytes4 (float r, float g, float b, float a) {
232 unsigned i;
233
234 ( (byte *)&i )[0] = r * 255;
235 ( (byte *)&i )[1] = g * 255;
236 ( (byte *)&i )[2] = b * 255;
237 ( (byte *)&i )[3] = a * 255;
238
239 return i;
240 }
241
NormalizeColor(const vec3_t in,vec3_t out)242 float NormalizeColor( const vec3_t in, vec3_t out ) {
243 float max;
244
245 max = in[0];
246 if ( in[1] > max ) {
247 max = in[1];
248 }
249 if ( in[2] > max ) {
250 max = in[2];
251 }
252
253 if ( !max ) {
254 VectorClear( out );
255 } else {
256 out[0] = in[0] / max;
257 out[1] = in[1] / max;
258 out[2] = in[2] / max;
259 }
260 return max;
261 }
262
263
264 /*
265 =====================
266 PlaneFromPoints
267
268 Returns false if the triangle is degenrate.
269 The normal will point out of the clock for clockwise ordered points
270 =====================
271 */
PlaneFromPoints(vec4_t plane,const vec3_t a,const vec3_t b,const vec3_t c)272 qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
273 vec3_t d1, d2;
274
275 VectorSubtract( b, a, d1 );
276 VectorSubtract( c, a, d2 );
277 CrossProduct( d2, d1, plane );
278 if ( VectorNormalize( plane ) == 0 ) {
279 return qfalse;
280 }
281
282 plane[3] = DotProduct( a, plane );
283 return qtrue;
284 }
285
286 /*
287 ===============
288 RotatePointAroundVector
289
290 This is not implemented very well...
291 ===============
292 */
RotatePointAroundVector(vec3_t dst,const vec3_t dir,const vec3_t point,float degrees)293 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
294 float degrees ) {
295 float m[3][3];
296 float im[3][3];
297 float zrot[3][3];
298 float tmpmat[3][3];
299 float rot[3][3];
300 int i;
301 vec3_t vr, vup, vf;
302 float rad;
303
304 vf[0] = dir[0];
305 vf[1] = dir[1];
306 vf[2] = dir[2];
307
308 PerpendicularVector( vr, dir );
309 CrossProduct( vr, vf, vup );
310
311 m[0][0] = vr[0];
312 m[1][0] = vr[1];
313 m[2][0] = vr[2];
314
315 m[0][1] = vup[0];
316 m[1][1] = vup[1];
317 m[2][1] = vup[2];
318
319 m[0][2] = vf[0];
320 m[1][2] = vf[1];
321 m[2][2] = vf[2];
322
323 memcpy( im, m, sizeof( im ) );
324
325 im[0][1] = m[1][0];
326 im[0][2] = m[2][0];
327 im[1][0] = m[0][1];
328 im[1][2] = m[2][1];
329 im[2][0] = m[0][2];
330 im[2][1] = m[1][2];
331
332 memset( zrot, 0, sizeof( zrot ) );
333 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
334
335 rad = DEG2RAD( degrees );
336 zrot[0][0] = cos( rad );
337 zrot[0][1] = sin( rad );
338 zrot[1][0] = -sin( rad );
339 zrot[1][1] = cos( rad );
340
341 MatrixMultiply( m, zrot, tmpmat );
342 MatrixMultiply( tmpmat, im, rot );
343
344 for ( i = 0; i < 3; i++ ) {
345 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
346 }
347 }
348
349 /*
350 ===============
351 RotateAroundDirection
352 ===============
353 */
RotateAroundDirection(vec3_t axis[3],float yaw)354 void RotateAroundDirection( vec3_t axis[3], float yaw ) {
355
356 // create an arbitrary axis[1]
357 PerpendicularVector( axis[1], axis[0] );
358
359 // rotate it around axis[0] by yaw
360 if ( yaw ) {
361 vec3_t temp;
362
363 VectorCopy( axis[1], temp );
364 RotatePointAroundVector( axis[1], axis[0], temp, yaw );
365 }
366
367 // cross to get axis[2]
368 CrossProduct( axis[0], axis[1], axis[2] );
369 }
370
371
372
vectoangles(const vec3_t value1,vec3_t angles)373 void vectoangles( const vec3_t value1, vec3_t angles ) {
374 float forward;
375 float yaw, pitch;
376
377 if ( value1[1] == 0 && value1[0] == 0 ) {
378 yaw = 0;
379 if ( value1[2] > 0 ) {
380 pitch = 90;
381 }
382 else {
383 pitch = 270;
384 }
385 }
386 else {
387 if ( value1[0] ) {
388 yaw = ( atan2 ( value1[1], value1[0] ) * 180 / M_PI );
389 }
390 else if ( value1[1] > 0 ) {
391 yaw = 90;
392 }
393 else {
394 yaw = 270;
395 }
396 if ( yaw < 0 ) {
397 yaw += 360;
398 }
399
400 forward = sqrt ( value1[0]*value1[0] + value1[1]*value1[1] );
401 pitch = ( atan2(value1[2], forward) * 180 / M_PI );
402 if ( pitch < 0 ) {
403 pitch += 360;
404 }
405 }
406
407 angles[PITCH] = -pitch;
408 angles[YAW] = yaw;
409 angles[ROLL] = 0;
410 }
411
412
413 /*
414 =================
415 AnglesToAxis
416 =================
417 */
AnglesToAxis(const vec3_t angles,vec3_t axis[3])418 void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) {
419 vec3_t right;
420
421 // angle vectors returns "right" instead of "y axis"
422 AngleVectors( angles, axis[0], right, axis[2] );
423 VectorSubtract( vec3_origin, right, axis[1] );
424 }
425
AxisClear(vec3_t axis[3])426 void AxisClear( vec3_t axis[3] ) {
427 axis[0][0] = 1;
428 axis[0][1] = 0;
429 axis[0][2] = 0;
430 axis[1][0] = 0;
431 axis[1][1] = 1;
432 axis[1][2] = 0;
433 axis[2][0] = 0;
434 axis[2][1] = 0;
435 axis[2][2] = 1;
436 }
437
AxisCopy(vec3_t in[3],vec3_t out[3])438 void AxisCopy( vec3_t in[3], vec3_t out[3] ) {
439 VectorCopy( in[0], out[0] );
440 VectorCopy( in[1], out[1] );
441 VectorCopy( in[2], out[2] );
442 }
443
ProjectPointOnPlane(vec3_t dst,const vec3_t p,const vec3_t normal)444 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) {
445 float d;
446 vec3_t n;
447 float inv_denom;
448
449 inv_denom = 1.0F / DotProduct( normal, normal );
450
451 d = DotProduct( normal, p ) * inv_denom;
452
453 n[0] = normal[0] * inv_denom;
454 n[1] = normal[1] * inv_denom;
455 n[2] = normal[2] * inv_denom;
456
457 dst[0] = p[0] - d * n[0];
458 dst[1] = p[1] - d * n[1];
459 dst[2] = p[2] - d * n[2];
460 }
461
462 /*
463 ================
464 MakeNormalVectors
465
466 Given a normalized forward vector, create two
467 other perpendicular vectors
468 ================
469 */
MakeNormalVectors(const vec3_t forward,vec3_t right,vec3_t up)470 void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up) {
471 float d;
472
473 // this rotate and negate guarantees a vector
474 // not colinear with the original
475 right[1] = -forward[0];
476 right[2] = forward[1];
477 right[0] = forward[2];
478
479 d = DotProduct (right, forward);
480 VectorMA (right, -d, forward, right);
481 VectorNormalize (right);
482 CrossProduct (right, forward, up);
483 }
484
485
VectorRotate(vec3_t in,vec3_t matrix[3],vec3_t out)486 void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out )
487 {
488 out[0] = DotProduct( in, matrix[0] );
489 out[1] = DotProduct( in, matrix[1] );
490 out[2] = DotProduct( in, matrix[2] );
491 }
492
493 //============================================================================
494
495 #if !idppc
496 /*
497 ** float q_rsqrt( float number )
498 */
Q_rsqrt(float number)499 float Q_rsqrt( float number )
500 {
501 floatint_t t;
502 float x2, y;
503 const float threehalfs = 1.5F;
504
505 x2 = number * 0.5F;
506 t.f = number;
507 t.i = 0x5f3759df - ( t.i >> 1 ); // what the fuck?
508 y = t.f;
509 y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
510 // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
511
512 return y;
513 }
514
Q_fabs(float f)515 float Q_fabs( float f ) {
516 floatint_t fi;
517 fi.f = f;
518 fi.i &= 0x7FFFFFFF;
519 return fi.f;
520 }
521 #endif
522
523 //============================================================
524
525 /*
526 ===============
527 LerpAngle
528
529 ===============
530 */
LerpAngle(float from,float to,float frac)531 float LerpAngle (float from, float to, float frac) {
532 float a;
533
534 if ( to - from > 180 ) {
535 to -= 360;
536 }
537 if ( to - from < -180 ) {
538 to += 360;
539 }
540 a = from + frac * (to - from);
541
542 return a;
543 }
544
545
546 /*
547 =================
548 LerpPosition
549
550 =================
551 */
552
LerpPosition(vec3_t start,vec3_t end,float frac,vec3_t out)553 void LerpPosition( vec3_t start, vec3_t end, float frac, vec3_t out ) {
554 vec3_t dist;
555
556 VectorSubtract( end, start, dist );
557 VectorMA( start, frac, dist, out );
558 }
559
560 /*
561 =================
562 AngleSubtract
563
564 Always returns a value from -180 to 180
565 =================
566 */
AngleSubtract(float a1,float a2)567 float AngleSubtract( float a1, float a2 ) {
568 float a;
569
570 a = a1 - a2;
571 while ( a > 180 ) {
572 a -= 360;
573 }
574 while ( a < -180 ) {
575 a += 360;
576 }
577 return a;
578 }
579
580
AnglesSubtract(vec3_t v1,vec3_t v2,vec3_t v3)581 void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ) {
582 v3[0] = AngleSubtract( v1[0], v2[0] );
583 v3[1] = AngleSubtract( v1[1], v2[1] );
584 v3[2] = AngleSubtract( v1[2], v2[2] );
585 }
586
587
AngleMod(float a)588 float AngleMod(float a) {
589 a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
590 return a;
591 }
592
593
594 /*
595 =================
596 AngleNormalize360
597
598 returns angle normalized to the range [0 <= angle < 360]
599 =================
600 */
AngleNormalize360(float angle)601 float AngleNormalize360 ( float angle ) {
602 return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535);
603 }
604
605
606 /*
607 =================
608 AngleNormalize180
609
610 returns angle normalized to the range [-180 < angle <= 180]
611 =================
612 */
AngleNormalize180(float angle)613 float AngleNormalize180 ( float angle ) {
614 angle = AngleNormalize360( angle );
615 if ( angle > 180.0 ) {
616 angle -= 360.0;
617 }
618 return angle;
619 }
620
621
622 /*
623 =================
624 AngleDelta
625
626 returns the normalized delta from angle1 to angle2
627 =================
628 */
AngleDelta(float angle1,float angle2)629 float AngleDelta ( float angle1, float angle2 ) {
630 return AngleNormalize180( angle1 - angle2 );
631 }
632
633
634 //============================================================
635
636
637 /*
638 =================
639 SetPlaneSignbits
640 =================
641 */
SetPlaneSignbits(cplane_t * out)642 void SetPlaneSignbits (cplane_t *out) {
643 int bits, j;
644
645 // for fast box on planeside test
646 bits = 0;
647 for (j=0 ; j<3 ; j++) {
648 if (out->normal[j] < 0) {
649 bits |= 1<<j;
650 }
651 }
652 out->signbits = bits;
653 }
654
655
656 /*
657 ==================
658 BoxOnPlaneSide
659
660 Returns 1, 2, or 1 + 2
661 ==================
662 */
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)663 int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct cplane_s *p)
664 {
665 float dist[2];
666 int sides, b, i;
667
668 // fast axial cases
669 if (p->type < 3)
670 {
671 if (p->dist <= emins[p->type])
672 return 1;
673 if (p->dist >= emaxs[p->type])
674 return 2;
675 return 3;
676 }
677
678 // general case
679 dist[0] = dist[1] = 0;
680 if (p->signbits < 8) // >= 8: default case is original code (dist[0]=dist[1]=0)
681 {
682 for (i=0 ; i<3 ; i++)
683 {
684 b = (p->signbits >> i) & 1;
685 dist[ b] += p->normal[i]*emaxs[i];
686 dist[!b] += p->normal[i]*emins[i];
687 }
688 }
689
690 sides = 0;
691 if (dist[0] >= p->dist)
692 sides = 1;
693 if (dist[1] < p->dist)
694 sides |= 2;
695
696 return sides;
697 }
698
699
700 /*
701 =================
702 RadiusFromBounds
703 =================
704 */
RadiusFromBounds(const vec3_t mins,const vec3_t maxs)705 float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
706 int i;
707 vec3_t corner;
708 float a, b;
709
710 for (i=0 ; i<3 ; i++) {
711 a = fabs( mins[i] );
712 b = fabs( maxs[i] );
713 corner[i] = a > b ? a : b;
714 }
715
716 return VectorLength (corner);
717 }
718
719
ClearBounds(vec3_t mins,vec3_t maxs)720 void ClearBounds( vec3_t mins, vec3_t maxs ) {
721 mins[0] = mins[1] = mins[2] = 99999;
722 maxs[0] = maxs[1] = maxs[2] = -99999;
723 }
724
AddPointToBounds(const vec3_t v,vec3_t mins,vec3_t maxs)725 void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) {
726 if ( v[0] < mins[0] ) {
727 mins[0] = v[0];
728 }
729 if ( v[0] > maxs[0]) {
730 maxs[0] = v[0];
731 }
732
733 if ( v[1] < mins[1] ) {
734 mins[1] = v[1];
735 }
736 if ( v[1] > maxs[1]) {
737 maxs[1] = v[1];
738 }
739
740 if ( v[2] < mins[2] ) {
741 mins[2] = v[2];
742 }
743 if ( v[2] > maxs[2]) {
744 maxs[2] = v[2];
745 }
746 }
747
BoundsIntersect(const vec3_t mins,const vec3_t maxs,const vec3_t mins2,const vec3_t maxs2)748 qboolean BoundsIntersect(const vec3_t mins, const vec3_t maxs,
749 const vec3_t mins2, const vec3_t maxs2)
750 {
751 if ( maxs[0] < mins2[0] ||
752 maxs[1] < mins2[1] ||
753 maxs[2] < mins2[2] ||
754 mins[0] > maxs2[0] ||
755 mins[1] > maxs2[1] ||
756 mins[2] > maxs2[2])
757 {
758 return qfalse;
759 }
760
761 return qtrue;
762 }
763
BoundsIntersectSphere(const vec3_t mins,const vec3_t maxs,const vec3_t origin,vec_t radius)764 qboolean BoundsIntersectSphere(const vec3_t mins, const vec3_t maxs,
765 const vec3_t origin, vec_t radius)
766 {
767 if ( origin[0] - radius > maxs[0] ||
768 origin[0] + radius < mins[0] ||
769 origin[1] - radius > maxs[1] ||
770 origin[1] + radius < mins[1] ||
771 origin[2] - radius > maxs[2] ||
772 origin[2] + radius < mins[2])
773 {
774 return qfalse;
775 }
776
777 return qtrue;
778 }
779
BoundsIntersectPoint(const vec3_t mins,const vec3_t maxs,const vec3_t origin)780 qboolean BoundsIntersectPoint(const vec3_t mins, const vec3_t maxs,
781 const vec3_t origin)
782 {
783 if ( origin[0] > maxs[0] ||
784 origin[0] < mins[0] ||
785 origin[1] > maxs[1] ||
786 origin[1] < mins[1] ||
787 origin[2] > maxs[2] ||
788 origin[2] < mins[2])
789 {
790 return qfalse;
791 }
792
793 return qtrue;
794 }
795
VectorNormalize(vec3_t v)796 vec_t VectorNormalize( vec3_t v ) {
797 // NOTE: TTimo - Apple G4 altivec source uses double?
798 float length, ilength;
799
800 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
801
802 if ( length ) {
803 /* writing it this way allows gcc to recognize that rsqrt can be used */
804 ilength = 1/(float)sqrt (length);
805 /* sqrt(length) = length * (1 / sqrt(length)) */
806 length *= ilength;
807 v[0] *= ilength;
808 v[1] *= ilength;
809 v[2] *= ilength;
810 }
811
812 return length;
813 }
814
VectorNormalize2(const vec3_t v,vec3_t out)815 vec_t VectorNormalize2( const vec3_t v, vec3_t out) {
816 float length, ilength;
817
818 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
819
820 if (length)
821 {
822 /* writing it this way allows gcc to recognize that rsqrt can be used */
823 ilength = 1/(float)sqrt (length);
824 /* sqrt(length) = length * (1 / sqrt(length)) */
825 length *= ilength;
826 out[0] = v[0]*ilength;
827 out[1] = v[1]*ilength;
828 out[2] = v[2]*ilength;
829 } else {
830 VectorClear( out );
831 }
832
833 return length;
834
835 }
836
_VectorMA(const vec3_t veca,float scale,const vec3_t vecb,vec3_t vecc)837 void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) {
838 vecc[0] = veca[0] + scale*vecb[0];
839 vecc[1] = veca[1] + scale*vecb[1];
840 vecc[2] = veca[2] + scale*vecb[2];
841 }
842
843
_DotProduct(const vec3_t v1,const vec3_t v2)844 vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ) {
845 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
846 }
847
_VectorSubtract(const vec3_t veca,const vec3_t vecb,vec3_t out)848 void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
849 out[0] = veca[0]-vecb[0];
850 out[1] = veca[1]-vecb[1];
851 out[2] = veca[2]-vecb[2];
852 }
853
_VectorAdd(const vec3_t veca,const vec3_t vecb,vec3_t out)854 void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
855 out[0] = veca[0]+vecb[0];
856 out[1] = veca[1]+vecb[1];
857 out[2] = veca[2]+vecb[2];
858 }
859
_VectorCopy(const vec3_t in,vec3_t out)860 void _VectorCopy( const vec3_t in, vec3_t out ) {
861 out[0] = in[0];
862 out[1] = in[1];
863 out[2] = in[2];
864 }
865
_VectorScale(const vec3_t in,vec_t scale,vec3_t out)866 void _VectorScale( const vec3_t in, vec_t scale, vec3_t out ) {
867 out[0] = in[0]*scale;
868 out[1] = in[1]*scale;
869 out[2] = in[2]*scale;
870 }
871
Vector4Scale(const vec4_t in,vec_t scale,vec4_t out)872 void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ) {
873 out[0] = in[0]*scale;
874 out[1] = in[1]*scale;
875 out[2] = in[2]*scale;
876 out[3] = in[3]*scale;
877 }
878
879
Q_log2(int val)880 int Q_log2( int val ) {
881 int answer;
882
883 answer = 0;
884 while ( ( val>>=1 ) != 0 ) {
885 answer++;
886 }
887 return answer;
888 }
889
890
891
892 /*
893 =================
894 PlaneTypeForNormal
895 =================
896 */
897 /*
898 int PlaneTypeForNormal (vec3_t normal) {
899 if ( normal[0] == 1.0 )
900 return PLANE_X;
901 if ( normal[1] == 1.0 )
902 return PLANE_Y;
903 if ( normal[2] == 1.0 )
904 return PLANE_Z;
905
906 return PLANE_NON_AXIAL;
907 }
908 */
909
910
911 /*
912 ================
913 MatrixMultiply
914 ================
915 */
MatrixMultiply(float in1[3][3],float in2[3][3],float out[3][3])916 void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
917 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
918 in1[0][2] * in2[2][0];
919 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
920 in1[0][2] * in2[2][1];
921 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
922 in1[0][2] * in2[2][2];
923 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
924 in1[1][2] * in2[2][0];
925 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
926 in1[1][2] * in2[2][1];
927 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
928 in1[1][2] * in2[2][2];
929 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
930 in1[2][2] * in2[2][0];
931 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
932 in1[2][2] * in2[2][1];
933 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
934 in1[2][2] * in2[2][2];
935 }
936
937
AngleVectors(const vec3_t angles,vec3_t forward,vec3_t right,vec3_t up)938 void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
939 float angle;
940 static float sr, sp, sy, cr, cp, cy;
941 // static to help MS compiler fp bugs
942
943 angle = angles[YAW] * (M_PI*2 / 360);
944 sy = sin(angle);
945 cy = cos(angle);
946 angle = angles[PITCH] * (M_PI*2 / 360);
947 sp = sin(angle);
948 cp = cos(angle);
949 angle = angles[ROLL] * (M_PI*2 / 360);
950 sr = sin(angle);
951 cr = cos(angle);
952
953 if (forward)
954 {
955 forward[0] = cp*cy;
956 forward[1] = cp*sy;
957 forward[2] = -sp;
958 }
959 if (right)
960 {
961 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
962 right[1] = (-1*sr*sp*sy+-1*cr*cy);
963 right[2] = -1*sr*cp;
964 }
965 if (up)
966 {
967 up[0] = (cr*sp*cy+-sr*-sy);
968 up[1] = (cr*sp*sy+-sr*cy);
969 up[2] = cr*cp;
970 }
971 }
972
973 /*
974 ** assumes "src" is normalized
975 */
PerpendicularVector(vec3_t dst,const vec3_t src)976 void PerpendicularVector( vec3_t dst, const vec3_t src )
977 {
978 int pos;
979 int i;
980 float minelem = 1.0F;
981 vec3_t tempvec;
982
983 /*
984 ** find the smallest magnitude axially aligned vector
985 */
986 for ( pos = 0, i = 0; i < 3; i++ )
987 {
988 if ( fabs( src[i] ) < minelem )
989 {
990 pos = i;
991 minelem = fabs( src[i] );
992 }
993 }
994 tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
995 tempvec[pos] = 1.0F;
996
997 /*
998 ** project the point onto the plane defined by src
999 */
1000 ProjectPointOnPlane( dst, tempvec, src );
1001
1002 /*
1003 ** normalize the result
1004 */
1005 VectorNormalize( dst );
1006 }
1007
1008 // Ridah
1009 /*
1010 =================
1011 GetPerpendicularViewVector
1012
1013 Used to find an "up" vector for drawing a sprite so that it always faces the view as best as possible
1014 =================
1015 */
GetPerpendicularViewVector(const vec3_t point,const vec3_t p1,const vec3_t p2,vec3_t up)1016 void GetPerpendicularViewVector( const vec3_t point, const vec3_t p1, const vec3_t p2, vec3_t up ) {
1017 vec3_t v1, v2;
1018
1019 VectorSubtract( point, p1, v1 );
1020 VectorNormalize( v1 );
1021
1022 VectorSubtract( point, p2, v2 );
1023 VectorNormalize( v2 );
1024
1025 CrossProduct( v1, v2, up );
1026 VectorNormalize( up );
1027 }
1028
1029 /*
1030 ================
1031 ProjectPointOntoVector
1032 ================
1033 */
ProjectPointOntoVector(vec3_t point,vec3_t vStart,vec3_t vEnd,vec3_t vProj)1034 void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj ) {
1035 vec3_t pVec, vec;
1036
1037 VectorSubtract( point, vStart, pVec );
1038 VectorSubtract( vEnd, vStart, vec );
1039 VectorNormalize( vec );
1040 // project onto the directional vector for this segment
1041 VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
1042 }
1043
vectoyaw(const vec3_t vec)1044 float vectoyaw( const vec3_t vec ) {
1045 float yaw;
1046
1047 if ( vec[YAW] == 0 && vec[PITCH] == 0 ) {
1048 yaw = 0;
1049 } else {
1050 if ( vec[PITCH] ) {
1051 yaw = ( atan2( vec[YAW], vec[PITCH] ) * 180 / M_PI );
1052 } else if ( vec[YAW] > 0 ) {
1053 yaw = 90;
1054 } else {
1055 yaw = 270;
1056 }
1057 if ( yaw < 0 ) {
1058 yaw += 360;
1059 }
1060 }
1061
1062 return yaw;
1063 }
1064
1065 /*
1066 =================
1067 AxisToAngles
1068
1069 Used to convert the MD3 tag axis to MDC tag angles, which are much smaller
1070
1071 This doesn't have to be fast, since it's only used for conversion in utils, try to avoid
1072 using this during gameplay
1073 =================
1074 */
AxisToAngles(vec3_t axis[3],vec3_t angles)1075 void AxisToAngles( vec3_t axis[3], vec3_t angles ) {
1076 vec3_t right, roll_angles, tvec;
1077
1078 // first get the pitch and yaw from the forward vector
1079 vectoangles( axis[0], angles );
1080
1081 // now get the roll from the right vector
1082 VectorCopy( axis[1], right );
1083 // get the angle difference between the tmpAxis[2] and axis[2] after they have been reverse-rotated
1084 RotatePointAroundVector( tvec, axisDefault[2], right, -angles[YAW] );
1085 RotatePointAroundVector( right, axisDefault[1], tvec, -angles[PITCH] );
1086 // now find the angles, the PITCH is effectively our ROLL
1087 vectoangles( right, roll_angles );
1088 roll_angles[PITCH] = AngleNormalize180( roll_angles[PITCH] );
1089 // if the yaw is more than 90 degrees difference, we should adjust the pitch
1090 if ( DotProduct( right, axisDefault[1] ) < 0 ) {
1091 if ( roll_angles[PITCH] < 0 ) {
1092 roll_angles[PITCH] = -90 + ( -90 - roll_angles[PITCH] );
1093 } else {
1094 roll_angles[PITCH] = 90 + ( 90 - roll_angles[PITCH] );
1095 }
1096 }
1097
1098 angles[ROLL] = -roll_angles[PITCH];
1099 }
1100
VectorDistance(vec3_t v1,vec3_t v2)1101 float VectorDistance( vec3_t v1, vec3_t v2 ) {
1102 vec3_t dir;
1103
1104 VectorSubtract( v2, v1, dir );
1105 return VectorLength( dir );
1106 }
1107
1108 /*
1109 ================
1110 Q_isnan
1111
1112 Don't pass doubles to this
1113 ================
1114 */
Q_isnan(float x)1115 int Q_isnan( float x )
1116 {
1117 floatint_t fi;
1118
1119 fi.f = x;
1120 fi.ui &= 0x7FFFFFFF;
1121 fi.ui = 0x7F800000 - fi.ui;
1122
1123 return (int)( (unsigned int)fi.ui >> 31 );
1124 }
1125
1126 //------------------------------------------------------------------------
1127
1128 #ifndef Q3_VM
1129 /*
1130 =====================
1131 Q_acos
1132
1133 the msvc acos doesn't always return a value between -PI and PI:
1134
1135 int i;
1136 i = 1065353246;
1137 acos(*(float*) &i) == -1.#IND0
1138
1139 =====================
1140 */
Q_acos(float c)1141 float Q_acos(float c) {
1142 float angle;
1143
1144 angle = acos(c);
1145
1146 if (angle > M_PI) {
1147 return (float)M_PI;
1148 }
1149 if (angle < -M_PI) {
1150 return (float)M_PI;
1151 }
1152 return angle;
1153 }
1154 #endif
1155