1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 Copyright (C) 2000-2006 Tim Angus
5
6 This file is part of Tremulous.
7
8 Tremulous is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12
13 Tremulous is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Tremulous; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 ===========================================================================
22 */
23 //
24 // q_math.c -- stateless support routines that are included in each code module
25
26 // Some of the vector functions are static inline in q_shared.h. q3asm
27 // doesn't understand static functions though, so we only want them in
28 // one file. That's what this is about.
29 #ifdef Q3_VM
30 #define __Q3_VM_MATH
31 #endif
32
33 #include "q_shared.h"
34
35 vec3_t vec3_origin = {0,0,0};
36 vec3_t axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
37
38
39 vec4_t colorBlack = {0, 0, 0, 1};
40 vec4_t colorRed = {1, 0, 0, 1};
41 vec4_t colorGreen = {0, 1, 0, 1};
42 vec4_t colorBlue = {0, 0, 1, 1};
43 vec4_t colorYellow = {1, 1, 0, 1};
44 vec4_t colorMagenta= {1, 0, 1, 1};
45 vec4_t colorCyan = {0, 1, 1, 1};
46 vec4_t colorWhite = {1, 1, 1, 1};
47 vec4_t colorLtGrey = {0.75, 0.75, 0.75, 1};
48 vec4_t colorMdGrey = {0.5, 0.5, 0.5, 1};
49 vec4_t colorDkGrey = {0.25, 0.25, 0.25, 1};
50
51 vec4_t g_color_table[8] =
52 {
53 {0.0, 0.0, 0.0, 1.0},
54 {1.0, 0.0, 0.0, 1.0},
55 {0.0, 1.0, 0.0, 1.0},
56 {1.0, 1.0, 0.0, 1.0},
57 {0.0, 0.0, 1.0, 1.0},
58 {0.0, 1.0, 1.0, 1.0},
59 {1.0, 0.0, 1.0, 1.0},
60 {1.0, 1.0, 1.0, 1.0},
61 };
62
63
64 vec3_t bytedirs[NUMVERTEXNORMALS] =
65 {
66 {-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f},
67 {-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f},
68 {-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f},
69 {0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f},
70 {0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f},
71 {0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f},
72 {0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f},
73 {0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f},
74 {-0.809017f, 0.309017f, 0.500000f},{-0.587785f, 0.425325f, 0.688191f},
75 {-0.850651f, 0.525731f, 0.000000f},{-0.864188f, 0.442863f, 0.238856f},
76 {-0.716567f, 0.681718f, 0.147621f},{-0.688191f, 0.587785f, 0.425325f},
77 {-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f},
78 {-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f},
79 {-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f},
80 {0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f},
81 {0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f},
82 {0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f},
83 {-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f},
84 {0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f},
85 {0.238856f, 0.864188f, -0.442863f},{0.262866f, 0.951056f, -0.162460f},
86 {0.500000f, 0.809017f, -0.309017f},{0.850651f, 0.525731f, 0.000000f},
87 {0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f},
88 {0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f},
89 {0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f},
90 {0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f},
91 {0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f},
92 {1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f},
93 {0.850651f, -0.525731f, 0.000000f},{0.955423f, -0.295242f, 0.000000f},
94 {0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f},
95 {0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f},
96 {0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f},
97 {0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f},
98 {0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f},
99 {0.681718f, -0.147621f, -0.716567f},{0.850651f, 0.000000f, -0.525731f},
100 {0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f},
101 {0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f},
102 {0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f},
103 {0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f},
104 {0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f},
105 {-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f},
106 {-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f},
107 {-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f},
108 {0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f},
109 {0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f},
110 {-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f},
111 {0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f},
112 {0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f},
113 {0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f},
114 {0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f},
115 {0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f},
116 {0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f},
117 {0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f},
118 {0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f},
119 {0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f},
120 {0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f},
121 {0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f},
122 {0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f},
123 {-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f},
124 {-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f},
125 {-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f},
126 {-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f},
127 {-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f},
128 {-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f},
129 {-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f},
130 {-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f},
131 {-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f},
132 {-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f},
133 {0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f},
134 {0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f},
135 {0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f},
136 {0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f},
137 {-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f},
138 {-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f},
139 {-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f},
140 {-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f},
141 {-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f},
142 {-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f},
143 {-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f},
144 {-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f},
145 {-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f},
146 {-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f}
147 };
148
149 //==============================================================
150
Q_rand(int * seed)151 int Q_rand( int *seed ) {
152 *seed = (69069 * *seed + 1);
153 return *seed;
154 }
155
Q_random(int * seed)156 float Q_random( int *seed ) {
157 return ( Q_rand( seed ) & 0xffff ) / (float)0x10000;
158 }
159
Q_crandom(int * seed)160 float Q_crandom( int *seed ) {
161 return 2.0 * ( Q_random( seed ) - 0.5 );
162 }
163
164 //=======================================================
165
ClampChar(int i)166 signed char ClampChar( int i ) {
167 if ( i < -128 ) {
168 return -128;
169 }
170 if ( i > 127 ) {
171 return 127;
172 }
173 return i;
174 }
175
ClampShort(int i)176 signed short ClampShort( int i ) {
177 if ( i < -32768 ) {
178 return -32768;
179 }
180 if ( i > 0x7fff ) {
181 return 0x7fff;
182 }
183 return i;
184 }
185
186
187 // this isn't a real cheap function to call!
DirToByte(vec3_t dir)188 int DirToByte( vec3_t dir ) {
189 int i, best;
190 float d, bestd;
191
192 if ( !dir ) {
193 return 0;
194 }
195
196 bestd = 0;
197 best = 0;
198 for (i=0 ; i<NUMVERTEXNORMALS ; i++)
199 {
200 d = DotProduct (dir, bytedirs[i]);
201 if (d > bestd)
202 {
203 bestd = d;
204 best = i;
205 }
206 }
207
208 return best;
209 }
210
ByteToDir(int b,vec3_t dir)211 void ByteToDir( int b, vec3_t dir ) {
212 if ( b < 0 || b >= NUMVERTEXNORMALS ) {
213 VectorCopy( vec3_origin, dir );
214 return;
215 }
216 VectorCopy (bytedirs[b], dir);
217 }
218
219
ColorBytes3(float r,float g,float b)220 unsigned ColorBytes3 (float r, float g, float b) {
221 unsigned i;
222
223 ( (byte *)&i )[0] = r * 255;
224 ( (byte *)&i )[1] = g * 255;
225 ( (byte *)&i )[2] = b * 255;
226
227 return i;
228 }
229
ColorBytes4(float r,float g,float b,float a)230 unsigned ColorBytes4 (float r, float g, float b, float a) {
231 unsigned i;
232
233 ( (byte *)&i )[0] = r * 255;
234 ( (byte *)&i )[1] = g * 255;
235 ( (byte *)&i )[2] = b * 255;
236 ( (byte *)&i )[3] = a * 255;
237
238 return i;
239 }
240
NormalizeColor(const vec3_t in,vec3_t out)241 float NormalizeColor( const vec3_t in, vec3_t out ) {
242 float max;
243
244 max = in[0];
245 if ( in[1] > max ) {
246 max = in[1];
247 }
248 if ( in[2] > max ) {
249 max = in[2];
250 }
251
252 if ( !max ) {
253 VectorClear( out );
254 } else {
255 out[0] = in[0] / max;
256 out[1] = in[1] / max;
257 out[2] = in[2] / max;
258 }
259 return max;
260 }
261
262
263 /*
264 =====================
265 PlaneFromPoints
266
267 Returns false if the triangle is degenrate.
268 The normal will point out of the clock for clockwise ordered points
269 =====================
270 */
PlaneFromPoints(vec4_t plane,const vec3_t a,const vec3_t b,const vec3_t c)271 qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
272 vec3_t d1, d2;
273
274 VectorSubtract( b, a, d1 );
275 VectorSubtract( c, a, d2 );
276 CrossProduct( d2, d1, plane );
277 if ( VectorNormalize( plane ) == 0 ) {
278 return qfalse;
279 }
280
281 plane[3] = DotProduct( a, plane );
282 return qtrue;
283 }
284
285 /*
286 ===============
287 RotatePointAroundVector
288
289 This is not implemented very well...
290 ===============
291 */
RotatePointAroundVector(vec3_t dst,const vec3_t dir,const vec3_t point,float degrees)292 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
293 float degrees ) {
294 float sin_a;
295 float cos_a;
296 float cos_ia;
297 float i_i_ia;
298 float j_j_ia;
299 float k_k_ia;
300 float i_j_ia;
301 float i_k_ia;
302 float j_k_ia;
303 float a_sin;
304 float b_sin;
305 float c_sin;
306 float rot[3][3];
307
308 cos_ia = DEG2RAD(degrees);
309 sin_a = sin(cos_ia);
310 cos_a = cos(cos_ia);
311 cos_ia = 1.0F - cos_a;
312
313 i_i_ia = dir[0] * dir[0] * cos_ia;
314 j_j_ia = dir[1] * dir[1] * cos_ia;
315 k_k_ia = dir[2] * dir[2] * cos_ia;
316 i_j_ia = dir[0] * dir[1] * cos_ia;
317 i_k_ia = dir[0] * dir[2] * cos_ia;
318 j_k_ia = dir[1] * dir[2] * cos_ia;
319
320 a_sin = dir[0] * sin_a;
321 b_sin = dir[1] * sin_a;
322 c_sin = dir[2] * sin_a;
323
324 rot[0][0] = i_i_ia + cos_a;
325 rot[0][1] = i_j_ia - c_sin;
326 rot[0][2] = i_k_ia + b_sin;
327 rot[1][0] = i_j_ia + c_sin;
328 rot[1][1] = j_j_ia + cos_a;
329 rot[1][2] = j_k_ia - a_sin;
330 rot[2][0] = i_k_ia - b_sin;
331 rot[2][1] = j_k_ia + a_sin;
332 rot[2][2] = k_k_ia + cos_a;
333
334 dst[0] = point[0] * rot[0][0] + point[1] * rot[0][1] + point[2] * rot[0][2];
335 dst[1] = point[0] * rot[1][0] + point[1] * rot[1][1] + point[2] * rot[1][2];
336 dst[2] = point[0] * rot[2][0] + point[1] * rot[2][1] + point[2] * rot[2][2];
337 }
338
339 /*
340 ===============
341 RotateAroundDirection
342 ===============
343 */
RotateAroundDirection(vec3_t axis[3],vec_t angle)344 void RotateAroundDirection( vec3_t axis[3], vec_t angle ) {
345 vec_t scale;
346
347 angle = DEG2RAD( angle );
348
349 // create an arbitrary axis[1]
350 PerpendicularVector( axis[ 1 ], axis[ 0 ] );
351
352 // cross to get axis[2]
353 CrossProduct( axis[ 0 ], axis[ 1 ], axis[ 2 ] );
354
355 // rotate
356 scale = cos( angle );
357 VectorScale( axis[ 1 ], scale, axis[ 1 ] );
358
359 scale = sin( angle );
360 VectorMA( axis[ 1 ], scale, axis[ 2 ], axis[ 1 ] );
361
362 // recalculate axis[2]
363 CrossProduct( axis[ 0 ], axis[ 1 ], axis[ 2 ] );
364 }
365
366
367
vectoangles(const vec3_t value1,vec3_t angles)368 void vectoangles( const vec3_t value1, vec3_t angles ) {
369 float forward;
370 float yaw, pitch;
371
372 if ( value1[1] == 0 && value1[0] == 0 ) {
373 yaw = 0;
374 if ( value1[2] > 0 ) {
375 pitch = 90;
376 }
377 else {
378 pitch = 270;
379 }
380 }
381 else {
382 if ( value1[0] ) {
383 yaw = ( atan2 ( value1[1], value1[0] ) * 180 / M_PI );
384 }
385 else if ( value1[1] > 0 ) {
386 yaw = 90;
387 }
388 else {
389 yaw = 270;
390 }
391 if ( yaw < 0 ) {
392 yaw += 360;
393 }
394
395 forward = sqrt ( value1[0]*value1[0] + value1[1]*value1[1] );
396 pitch = ( atan2(value1[2], forward) * 180 / M_PI );
397 if ( pitch < 0 ) {
398 pitch += 360;
399 }
400 }
401
402 angles[PITCH] = -pitch;
403 angles[YAW] = yaw;
404 angles[ROLL] = 0;
405 }
406
407
408 /*
409 =================
410 AxisToAngles
411
412 Takes an axis (forward + right + up)
413 and returns angles -- including a roll
414 =================
415 */
AxisToAngles(vec3_t axis[3],vec3_t angles)416 void AxisToAngles( vec3_t axis[3], vec3_t angles ) {
417 float length1;
418 float yaw, pitch, roll = 0.0f;
419
420 if ( axis[0][1] == 0 && axis[0][0] == 0 ) {
421 yaw = 0;
422 if ( axis[0][2] > 0 ) {
423 pitch = 90;
424 }
425 else {
426 pitch = 270;
427 }
428 }
429 else {
430 if ( axis[0][0] ) {
431 yaw = ( atan2 ( axis[0][1], axis[0][0] ) * 180 / M_PI );
432 }
433 else if ( axis[0][1] > 0 ) {
434 yaw = 90;
435 }
436 else {
437 yaw = 270;
438 }
439 if ( yaw < 0 ) {
440 yaw += 360;
441 }
442
443 length1 = sqrt ( axis[0][0]*axis[0][0] + axis[0][1]*axis[0][1] );
444 pitch = ( atan2(axis[0][2], length1) * 180 / M_PI );
445 if ( pitch < 0 ) {
446 pitch += 360;
447 }
448
449 roll = ( atan2( axis[1][2], axis[2][2] ) * 180 / M_PI );
450 if ( roll < 0 ) {
451 roll += 360;
452 }
453 }
454
455 angles[PITCH] = -pitch;
456 angles[YAW] = yaw;
457 angles[ROLL] = roll;
458 }
459
460 /*
461 =================
462 AnglesToAxis
463 =================
464 */
AnglesToAxis(const vec3_t angles,vec3_t axis[3])465 void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) {
466 vec3_t right;
467
468 // angle vectors returns "right" instead of "y axis"
469 AngleVectors( angles, axis[0], right, axis[2] );
470 VectorSubtract( vec3_origin, right, axis[1] );
471 }
472
AxisClear(vec3_t axis[3])473 void AxisClear( vec3_t axis[3] ) {
474 axis[0][0] = 1;
475 axis[0][1] = 0;
476 axis[0][2] = 0;
477 axis[1][0] = 0;
478 axis[1][1] = 1;
479 axis[1][2] = 0;
480 axis[2][0] = 0;
481 axis[2][1] = 0;
482 axis[2][2] = 1;
483 }
484
AxisCopy(vec3_t in[3],vec3_t out[3])485 void AxisCopy( vec3_t in[3], vec3_t out[3] ) {
486 VectorCopy( in[0], out[0] );
487 VectorCopy( in[1], out[1] );
488 VectorCopy( in[2], out[2] );
489 }
490
ProjectPointOnPlane(vec3_t dst,const vec3_t p,const vec3_t normal)491 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
492 {
493 float d;
494 vec3_t n;
495 float inv_denom;
496
497 inv_denom = 1.0f / DotProduct( normal, normal );
498 #ifndef Q3_VM
499 assert( Q_fabs(inv_denom) != 0.0f ); // bk010122 - zero vectors get here
500 #endif
501 inv_denom = 1.0f / inv_denom;
502
503 d = DotProduct( normal, p ) * inv_denom;
504
505 n[0] = normal[0] * inv_denom;
506 n[1] = normal[1] * inv_denom;
507 n[2] = normal[2] * inv_denom;
508
509 dst[0] = p[0] - d * n[0];
510 dst[1] = p[1] - d * n[1];
511 dst[2] = p[2] - d * n[2];
512 }
513
514 /*
515 ================
516 MakeNormalVectors
517
518 Given a normalized forward vector, create two
519 other perpendicular vectors
520 ================
521 */
MakeNormalVectors(const vec3_t forward,vec3_t right,vec3_t up)522 void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up) {
523 float d;
524
525 // this rotate and negate guarantees a vector
526 // not colinear with the original
527 right[1] = -forward[0];
528 right[2] = forward[1];
529 right[0] = forward[2];
530
531 d = DotProduct (right, forward);
532 VectorMA (right, -d, forward, right);
533 VectorNormalize (right);
534 CrossProduct (right, forward, up);
535 }
536
537
VectorRotate(vec3_t in,vec3_t matrix[3],vec3_t out)538 void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out )
539 {
540 out[0] = DotProduct( in, matrix[0] );
541 out[1] = DotProduct( in, matrix[1] );
542 out[2] = DotProduct( in, matrix[2] );
543 }
544
545 //============================================================================
546
547 #if !idppc
548 /*
549 ** float q_rsqrt( float number )
550 */
Q_rsqrt(float number)551 float Q_rsqrt( float number )
552 {
553 union {
554 float f;
555 int i;
556 } t;
557 float x2, y;
558 const float threehalfs = 1.5F;
559
560 x2 = number * 0.5F;
561 t.f = number;
562 t.i = 0x5f3759df - ( t.i >> 1 ); // what the fuck?
563 y = t.f;
564 y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
565 // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
566
567 //assert( !isnan(y) ); // bk010122 - FPE?
568 return y;
569 }
570
Q_fabs(float f)571 float Q_fabs( float f ) {
572 int tmp = * ( int * ) &f;
573 tmp &= 0x7FFFFFFF;
574 return * ( float * ) &tmp;
575 }
576 #endif
577
578 //============================================================
579
580 /*
581 ===============
582 LerpAngle
583
584 ===============
585 */
LerpAngle(float from,float to,float frac)586 float LerpAngle (float from, float to, float frac) {
587 float a;
588
589 if ( to - from > 180 ) {
590 to -= 360;
591 }
592 if ( to - from < -180 ) {
593 to += 360;
594 }
595 a = from + frac * (to - from);
596
597 return a;
598 }
599
600
601 /*
602 =================
603 AngleSubtract
604
605 Always returns a value from -180 to 180
606 =================
607 */
AngleSubtract(float a1,float a2)608 float AngleSubtract( float a1, float a2 ) {
609 float a;
610
611 a = a1 - a2;
612 while ( a > 180 ) {
613 a -= 360;
614 }
615 while ( a < -180 ) {
616 a += 360;
617 }
618 return a;
619 }
620
621
AnglesSubtract(vec3_t v1,vec3_t v2,vec3_t v3)622 void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ) {
623 v3[0] = AngleSubtract( v1[0], v2[0] );
624 v3[1] = AngleSubtract( v1[1], v2[1] );
625 v3[2] = AngleSubtract( v1[2], v2[2] );
626 }
627
628
AngleMod(float a)629 float AngleMod(float a) {
630 a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
631 return a;
632 }
633
634
635 /*
636 =================
637 AngleNormalize360
638
639 returns angle normalized to the range [0 <= angle < 360]
640 =================
641 */
AngleNormalize360(float angle)642 float AngleNormalize360 ( float angle ) {
643 return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535);
644 }
645
646
647 /*
648 =================
649 AngleNormalize180
650
651 returns angle normalized to the range [-180 < angle <= 180]
652 =================
653 */
AngleNormalize180(float angle)654 float AngleNormalize180 ( float angle ) {
655 angle = AngleNormalize360( angle );
656 if ( angle > 180.0 ) {
657 angle -= 360.0;
658 }
659 return angle;
660 }
661
662
663 /*
664 =================
665 AngleDelta
666
667 returns the normalized delta from angle1 to angle2
668 =================
669 */
AngleDelta(float angle1,float angle2)670 float AngleDelta ( float angle1, float angle2 ) {
671 return AngleNormalize180( angle1 - angle2 );
672 }
673
674
675 //============================================================
676
677
678 /*
679 =================
680 SetPlaneSignbits
681 =================
682 */
SetPlaneSignbits(cplane_t * out)683 void SetPlaneSignbits (cplane_t *out) {
684 int bits, j;
685
686 // for fast box on planeside test
687 bits = 0;
688 for (j=0 ; j<3 ; j++) {
689 if (out->normal[j] < 0) {
690 bits |= 1<<j;
691 }
692 }
693 out->signbits = bits;
694 }
695
696
697 /*
698 ==================
699 BoxOnPlaneSide
700
701 Returns 1, 2, or 1 + 2
702
703 // this is the slow, general version
704 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
705 {
706 int i;
707 float dist1, dist2;
708 int sides;
709 vec3_t corners[2];
710
711 for (i=0 ; i<3 ; i++)
712 {
713 if (p->normal[i] < 0)
714 {
715 corners[0][i] = emins[i];
716 corners[1][i] = emaxs[i];
717 }
718 else
719 {
720 corners[1][i] = emins[i];
721 corners[0][i] = emaxs[i];
722 }
723 }
724 dist1 = DotProduct (p->normal, corners[0]) - p->dist;
725 dist2 = DotProduct (p->normal, corners[1]) - p->dist;
726 sides = 0;
727 if (dist1 >= 0)
728 sides = 1;
729 if (dist2 < 0)
730 sides |= 2;
731
732 return sides;
733 }
734
735 ==================
736 */
737
738 #if !id386
739
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)740 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
741 {
742 float dist1, dist2;
743 int sides;
744
745 // fast axial cases
746 if (p->type < 3)
747 {
748 if (p->dist <= emins[p->type])
749 return 1;
750 if (p->dist >= emaxs[p->type])
751 return 2;
752 return 3;
753 }
754
755 // general case
756 switch (p->signbits)
757 {
758 case 0:
759 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
760 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
761 break;
762 case 1:
763 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
764 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
765 break;
766 case 2:
767 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
768 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
769 break;
770 case 3:
771 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
772 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
773 break;
774 case 4:
775 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
776 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
777 break;
778 case 5:
779 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
780 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
781 break;
782 case 6:
783 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
784 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
785 break;
786 case 7:
787 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
788 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
789 break;
790 default:
791 dist1 = dist2 = 0; // shut up compiler
792 break;
793 }
794
795 sides = 0;
796 if (dist1 >= p->dist)
797 sides = 1;
798 if (dist2 < p->dist)
799 sides |= 2;
800
801 return sides;
802 }
803 #elif __GNUC__
804 // use matha.s
805 #else
806 #pragma warning( disable: 4035 )
807
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)808 __declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
809 {
810 static int bops_initialized;
811 static int Ljmptab[8];
812
813 __asm {
814
815 push ebx
816
817 cmp bops_initialized, 1
818 je initialized
819 mov bops_initialized, 1
820
821 mov Ljmptab[0*4], offset Lcase0
822 mov Ljmptab[1*4], offset Lcase1
823 mov Ljmptab[2*4], offset Lcase2
824 mov Ljmptab[3*4], offset Lcase3
825 mov Ljmptab[4*4], offset Lcase4
826 mov Ljmptab[5*4], offset Lcase5
827 mov Ljmptab[6*4], offset Lcase6
828 mov Ljmptab[7*4], offset Lcase7
829
830 initialized:
831
832 mov edx,dword ptr[4+12+esp]
833 mov ecx,dword ptr[4+4+esp]
834 xor eax,eax
835 mov ebx,dword ptr[4+8+esp]
836 mov al,byte ptr[17+edx]
837 cmp al,8
838 jge Lerror
839 fld dword ptr[0+edx]
840 fld st(0)
841 jmp dword ptr[Ljmptab+eax*4]
842 Lcase0:
843 fmul dword ptr[ebx]
844 fld dword ptr[0+4+edx]
845 fxch st(2)
846 fmul dword ptr[ecx]
847 fxch st(2)
848 fld st(0)
849 fmul dword ptr[4+ebx]
850 fld dword ptr[0+8+edx]
851 fxch st(2)
852 fmul dword ptr[4+ecx]
853 fxch st(2)
854 fld st(0)
855 fmul dword ptr[8+ebx]
856 fxch st(5)
857 faddp st(3),st(0)
858 fmul dword ptr[8+ecx]
859 fxch st(1)
860 faddp st(3),st(0)
861 fxch st(3)
862 faddp st(2),st(0)
863 jmp LSetSides
864 Lcase1:
865 fmul dword ptr[ecx]
866 fld dword ptr[0+4+edx]
867 fxch st(2)
868 fmul dword ptr[ebx]
869 fxch st(2)
870 fld st(0)
871 fmul dword ptr[4+ebx]
872 fld dword ptr[0+8+edx]
873 fxch st(2)
874 fmul dword ptr[4+ecx]
875 fxch st(2)
876 fld st(0)
877 fmul dword ptr[8+ebx]
878 fxch st(5)
879 faddp st(3),st(0)
880 fmul dword ptr[8+ecx]
881 fxch st(1)
882 faddp st(3),st(0)
883 fxch st(3)
884 faddp st(2),st(0)
885 jmp LSetSides
886 Lcase2:
887 fmul dword ptr[ebx]
888 fld dword ptr[0+4+edx]
889 fxch st(2)
890 fmul dword ptr[ecx]
891 fxch st(2)
892 fld st(0)
893 fmul dword ptr[4+ecx]
894 fld dword ptr[0+8+edx]
895 fxch st(2)
896 fmul dword ptr[4+ebx]
897 fxch st(2)
898 fld st(0)
899 fmul dword ptr[8+ebx]
900 fxch st(5)
901 faddp st(3),st(0)
902 fmul dword ptr[8+ecx]
903 fxch st(1)
904 faddp st(3),st(0)
905 fxch st(3)
906 faddp st(2),st(0)
907 jmp LSetSides
908 Lcase3:
909 fmul dword ptr[ecx]
910 fld dword ptr[0+4+edx]
911 fxch st(2)
912 fmul dword ptr[ebx]
913 fxch st(2)
914 fld st(0)
915 fmul dword ptr[4+ecx]
916 fld dword ptr[0+8+edx]
917 fxch st(2)
918 fmul dword ptr[4+ebx]
919 fxch st(2)
920 fld st(0)
921 fmul dword ptr[8+ebx]
922 fxch st(5)
923 faddp st(3),st(0)
924 fmul dword ptr[8+ecx]
925 fxch st(1)
926 faddp st(3),st(0)
927 fxch st(3)
928 faddp st(2),st(0)
929 jmp LSetSides
930 Lcase4:
931 fmul dword ptr[ebx]
932 fld dword ptr[0+4+edx]
933 fxch st(2)
934 fmul dword ptr[ecx]
935 fxch st(2)
936 fld st(0)
937 fmul dword ptr[4+ebx]
938 fld dword ptr[0+8+edx]
939 fxch st(2)
940 fmul dword ptr[4+ecx]
941 fxch st(2)
942 fld st(0)
943 fmul dword ptr[8+ecx]
944 fxch st(5)
945 faddp st(3),st(0)
946 fmul dword ptr[8+ebx]
947 fxch st(1)
948 faddp st(3),st(0)
949 fxch st(3)
950 faddp st(2),st(0)
951 jmp LSetSides
952 Lcase5:
953 fmul dword ptr[ecx]
954 fld dword ptr[0+4+edx]
955 fxch st(2)
956 fmul dword ptr[ebx]
957 fxch st(2)
958 fld st(0)
959 fmul dword ptr[4+ebx]
960 fld dword ptr[0+8+edx]
961 fxch st(2)
962 fmul dword ptr[4+ecx]
963 fxch st(2)
964 fld st(0)
965 fmul dword ptr[8+ecx]
966 fxch st(5)
967 faddp st(3),st(0)
968 fmul dword ptr[8+ebx]
969 fxch st(1)
970 faddp st(3),st(0)
971 fxch st(3)
972 faddp st(2),st(0)
973 jmp LSetSides
974 Lcase6:
975 fmul dword ptr[ebx]
976 fld dword ptr[0+4+edx]
977 fxch st(2)
978 fmul dword ptr[ecx]
979 fxch st(2)
980 fld st(0)
981 fmul dword ptr[4+ecx]
982 fld dword ptr[0+8+edx]
983 fxch st(2)
984 fmul dword ptr[4+ebx]
985 fxch st(2)
986 fld st(0)
987 fmul dword ptr[8+ecx]
988 fxch st(5)
989 faddp st(3),st(0)
990 fmul dword ptr[8+ebx]
991 fxch st(1)
992 faddp st(3),st(0)
993 fxch st(3)
994 faddp st(2),st(0)
995 jmp LSetSides
996 Lcase7:
997 fmul dword ptr[ecx]
998 fld dword ptr[0+4+edx]
999 fxch st(2)
1000 fmul dword ptr[ebx]
1001 fxch st(2)
1002 fld st(0)
1003 fmul dword ptr[4+ecx]
1004 fld dword ptr[0+8+edx]
1005 fxch st(2)
1006 fmul dword ptr[4+ebx]
1007 fxch st(2)
1008 fld st(0)
1009 fmul dword ptr[8+ecx]
1010 fxch st(5)
1011 faddp st(3),st(0)
1012 fmul dword ptr[8+ebx]
1013 fxch st(1)
1014 faddp st(3),st(0)
1015 fxch st(3)
1016 faddp st(2),st(0)
1017 LSetSides:
1018 faddp st(2),st(0)
1019 fcomp dword ptr[12+edx]
1020 xor ecx,ecx
1021 fnstsw ax
1022 fcomp dword ptr[12+edx]
1023 and ah,1
1024 xor ah,1
1025 add cl,ah
1026 fnstsw ax
1027 and ah,1
1028 add ah,ah
1029 add cl,ah
1030 pop ebx
1031 mov eax,ecx
1032 ret
1033 Lerror:
1034 int 3
1035 }
1036 }
1037 #pragma warning( default: 4035 )
1038
1039 #endif
1040
1041 /*
1042 =================
1043 RadiusFromBounds
1044 =================
1045 */
RadiusFromBounds(const vec3_t mins,const vec3_t maxs)1046 float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
1047 int i;
1048 vec3_t corner;
1049 float a, b;
1050
1051 for (i=0 ; i<3 ; i++) {
1052 a = fabs( mins[i] );
1053 b = fabs( maxs[i] );
1054 corner[i] = a > b ? a : b;
1055 }
1056
1057 return VectorLength (corner);
1058 }
1059
1060
ClearBounds(vec3_t mins,vec3_t maxs)1061 void ClearBounds( vec3_t mins, vec3_t maxs ) {
1062 mins[0] = mins[1] = mins[2] = 99999;
1063 maxs[0] = maxs[1] = maxs[2] = -99999;
1064 }
1065
AddPointToBounds(const vec3_t v,vec3_t mins,vec3_t maxs)1066 void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) {
1067 if ( v[0] < mins[0] ) {
1068 mins[0] = v[0];
1069 }
1070 if ( v[0] > maxs[0]) {
1071 maxs[0] = v[0];
1072 }
1073
1074 if ( v[1] < mins[1] ) {
1075 mins[1] = v[1];
1076 }
1077 if ( v[1] > maxs[1]) {
1078 maxs[1] = v[1];
1079 }
1080
1081 if ( v[2] < mins[2] ) {
1082 mins[2] = v[2];
1083 }
1084 if ( v[2] > maxs[2]) {
1085 maxs[2] = v[2];
1086 }
1087 }
1088
1089
VectorNormalize(vec3_t v)1090 vec_t VectorNormalize( vec3_t v ) {
1091 // NOTE: TTimo - Apple G4 altivec source uses double?
1092 float length, ilength;
1093
1094 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
1095 length = sqrt (length);
1096
1097 if ( length ) {
1098 ilength = 1/length;
1099 v[0] *= ilength;
1100 v[1] *= ilength;
1101 v[2] *= ilength;
1102 }
1103
1104 return length;
1105 }
1106
VectorNormalize2(const vec3_t v,vec3_t out)1107 vec_t VectorNormalize2( const vec3_t v, vec3_t out) {
1108 float length, ilength;
1109
1110 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
1111 length = sqrt (length);
1112
1113 if (length)
1114 {
1115 #ifndef Q3_VM // bk0101022 - FPE related
1116 // assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) );
1117 #endif
1118 ilength = 1/length;
1119 out[0] = v[0]*ilength;
1120 out[1] = v[1]*ilength;
1121 out[2] = v[2]*ilength;
1122 } else {
1123 #ifndef Q3_VM // bk0101022 - FPE related
1124 // assert( ((Q_fabs(v[0])==0.0f) && (Q_fabs(v[1])==0.0f) && (Q_fabs(v[2])==0.0f)) );
1125 #endif
1126 VectorClear( out );
1127 }
1128
1129 return length;
1130
1131 }
1132
_VectorMA(const vec3_t veca,float scale,const vec3_t vecb,vec3_t vecc)1133 void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) {
1134 vecc[0] = veca[0] + scale*vecb[0];
1135 vecc[1] = veca[1] + scale*vecb[1];
1136 vecc[2] = veca[2] + scale*vecb[2];
1137 }
1138
1139
_DotProduct(const vec3_t v1,const vec3_t v2)1140 vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ) {
1141 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
1142 }
1143
_VectorSubtract(const vec3_t veca,const vec3_t vecb,vec3_t out)1144 void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
1145 out[0] = veca[0]-vecb[0];
1146 out[1] = veca[1]-vecb[1];
1147 out[2] = veca[2]-vecb[2];
1148 }
1149
_VectorAdd(const vec3_t veca,const vec3_t vecb,vec3_t out)1150 void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
1151 out[0] = veca[0]+vecb[0];
1152 out[1] = veca[1]+vecb[1];
1153 out[2] = veca[2]+vecb[2];
1154 }
1155
_VectorCopy(const vec3_t in,vec3_t out)1156 void _VectorCopy( const vec3_t in, vec3_t out ) {
1157 out[0] = in[0];
1158 out[1] = in[1];
1159 out[2] = in[2];
1160 }
1161
_VectorScale(const vec3_t in,vec_t scale,vec3_t out)1162 void _VectorScale( const vec3_t in, vec_t scale, vec3_t out ) {
1163 out[0] = in[0]*scale;
1164 out[1] = in[1]*scale;
1165 out[2] = in[2]*scale;
1166 }
1167
Vector4Scale(const vec4_t in,vec_t scale,vec4_t out)1168 void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ) {
1169 out[0] = in[0]*scale;
1170 out[1] = in[1]*scale;
1171 out[2] = in[2]*scale;
1172 out[3] = in[3]*scale;
1173 }
1174
1175
Q_log2(int val)1176 int Q_log2( int val ) {
1177 int answer;
1178
1179 answer = 0;
1180 while ( ( val>>=1 ) != 0 ) {
1181 answer++;
1182 }
1183 return answer;
1184 }
1185
1186
1187
1188 /*
1189 =================
1190 PlaneTypeForNormal
1191 =================
1192 */
1193 /*
1194 int PlaneTypeForNormal (vec3_t normal) {
1195 if ( normal[0] == 1.0 )
1196 return PLANE_X;
1197 if ( normal[1] == 1.0 )
1198 return PLANE_Y;
1199 if ( normal[2] == 1.0 )
1200 return PLANE_Z;
1201
1202 return PLANE_NON_AXIAL;
1203 }
1204 */
1205
1206
1207 /*
1208 ================
1209 MatrixMultiply
1210 ================
1211 */
MatrixMultiply(float in1[3][3],float in2[3][3],float out[3][3])1212 void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
1213 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
1214 in1[0][2] * in2[2][0];
1215 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
1216 in1[0][2] * in2[2][1];
1217 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
1218 in1[0][2] * in2[2][2];
1219 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
1220 in1[1][2] * in2[2][0];
1221 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
1222 in1[1][2] * in2[2][1];
1223 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
1224 in1[1][2] * in2[2][2];
1225 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
1226 in1[2][2] * in2[2][0];
1227 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
1228 in1[2][2] * in2[2][1];
1229 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
1230 in1[2][2] * in2[2][2];
1231 }
1232
1233 /*
1234 ================
1235 VectorMatrixMultiply
1236 ================
1237 */
VectorMatrixMultiply(const vec3_t p,vec3_t m[3],vec3_t out)1238 void VectorMatrixMultiply( const vec3_t p, vec3_t m[ 3 ], vec3_t out )
1239 {
1240 out[ 0 ] = m[ 0 ][ 0 ] * p[ 0 ] + m[ 1 ][ 0 ] * p[ 1 ] + m[ 2 ][ 0 ] * p[ 2 ];
1241 out[ 1 ] = m[ 0 ][ 1 ] * p[ 0 ] + m[ 1 ][ 1 ] * p[ 1 ] + m[ 2 ][ 1 ] * p[ 2 ];
1242 out[ 2 ] = m[ 0 ][ 2 ] * p[ 0 ] + m[ 1 ][ 2 ] * p[ 1 ] + m[ 2 ][ 2 ] * p[ 2 ];
1243 }
1244
1245
AngleVectors(const vec3_t angles,vec3_t forward,vec3_t right,vec3_t up)1246 void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
1247 float angle;
1248 static float sr, sp, sy, cr, cp, cy;
1249 // static to help MS compiler fp bugs
1250
1251 angle = angles[YAW] * (M_PI*2 / 360);
1252 sy = sin(angle);
1253 cy = cos(angle);
1254 angle = angles[PITCH] * (M_PI*2 / 360);
1255 sp = sin(angle);
1256 cp = cos(angle);
1257 angle = angles[ROLL] * (M_PI*2 / 360);
1258 sr = sin(angle);
1259 cr = cos(angle);
1260
1261 if (forward)
1262 {
1263 forward[0] = cp*cy;
1264 forward[1] = cp*sy;
1265 forward[2] = -sp;
1266 }
1267 if (right)
1268 {
1269 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
1270 right[1] = (-1*sr*sp*sy+-1*cr*cy);
1271 right[2] = -1*sr*cp;
1272 }
1273 if (up)
1274 {
1275 up[0] = (cr*sp*cy+-sr*-sy);
1276 up[1] = (cr*sp*sy+-sr*cy);
1277 up[2] = cr*cp;
1278 }
1279 }
1280
1281 /*
1282 ** assumes "src" is normalized
1283 */
PerpendicularVector(vec3_t dst,const vec3_t src)1284 void PerpendicularVector( vec3_t dst, const vec3_t src )
1285 {
1286 int pos;
1287 int i;
1288 float minelem = 1.0F;
1289 vec3_t tempvec;
1290
1291 /*
1292 ** find the smallest magnitude axially aligned vector
1293 */
1294 for ( pos = 0, i = 0; i < 3; i++ )
1295 {
1296 if ( fabs( src[i] ) < minelem )
1297 {
1298 pos = i;
1299 minelem = fabs( src[i] );
1300 }
1301 }
1302 tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
1303 tempvec[pos] = 1.0F;
1304
1305 /*
1306 ** project the point onto the plane defined by src
1307 */
1308 ProjectPointOnPlane( dst, tempvec, src );
1309
1310 /*
1311 ** normalize the result
1312 */
1313 VectorNormalize( dst );
1314 }
1315
1316 /*
1317 =================
1318 pointToLineDistance
1319
1320 Distance from a point to some line
1321 =================
1322 */
pointToLineDistance(const vec3_t p0,const vec3_t p1,const vec3_t p2)1323 float pointToLineDistance( const vec3_t p0, const vec3_t p1, const vec3_t p2 )
1324 {
1325 vec3_t v, w, y;
1326 float c1, c2;
1327
1328 VectorSubtract( p2, p1, v );
1329 VectorSubtract( p1, p0, w );
1330
1331 CrossProduct( w, v, y );
1332 c1 = VectorLength( y );
1333 c2 = VectorLength( v );
1334
1335 if( c2 == 0.0f )
1336 return 0.0f;
1337 else
1338 return c1 / c2;
1339 }
1340
1341 /*
1342 =================
1343 GetPerpendicularViewVector
1344
1345 Used to find an "up" vector for drawing a sprite so that it always faces the view as best as possible
1346 =================
1347 */
GetPerpendicularViewVector(const vec3_t point,const vec3_t p1,const vec3_t p2,vec3_t up)1348 void GetPerpendicularViewVector( const vec3_t point, const vec3_t p1, const vec3_t p2, vec3_t up )
1349 {
1350 vec3_t v1, v2;
1351
1352 VectorSubtract( point, p1, v1 );
1353 VectorNormalize( v1 );
1354
1355 VectorSubtract( point, p2, v2 );
1356 VectorNormalize( v2 );
1357
1358 CrossProduct( v1, v2, up );
1359 VectorNormalize( up );
1360 }
1361
1362 /*
1363 ================
1364 ProjectPointOntoVector
1365 ================
1366 */
ProjectPointOntoVector(vec3_t point,vec3_t vStart,vec3_t vEnd,vec3_t vProj)1367 void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
1368 {
1369 vec3_t pVec, vec;
1370
1371 VectorSubtract( point, vStart, pVec );
1372 VectorSubtract( vEnd, vStart, vec );
1373 VectorNormalize( vec );
1374 // project onto the directional vector for this segment
1375 VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
1376 }
1377
1378 /*
1379 ================
1380 VectorMaxComponent
1381
1382 Return the biggest component of some vector
1383 ================
1384 */
VectorMaxComponent(vec3_t v)1385 float VectorMaxComponent( vec3_t v )
1386 {
1387 float biggest = v[ 0 ];
1388
1389 if( v[ 1 ] > biggest )
1390 biggest = v[ 1 ];
1391
1392 if( v[ 2 ] > biggest )
1393 biggest = v[ 2 ];
1394
1395 return biggest;
1396 }
1397
1398 /*
1399 ================
1400 VectorMinComponent
1401
1402 Return the smallest component of some vector
1403 ================
1404 */
VectorMinComponent(vec3_t v)1405 float VectorMinComponent( vec3_t v )
1406 {
1407 float smallest = v[ 0 ];
1408
1409 if( v[ 1 ] < smallest )
1410 smallest = v[ 1 ];
1411
1412 if( v[ 2 ] < smallest )
1413 smallest = v[ 2 ];
1414
1415 return smallest;
1416 }
1417
1418
1419 #define LINE_DISTANCE_EPSILON 1e-05f
1420
1421 /*
1422 ================
1423 DistanceBetweenLineSegmentsSquared
1424
1425 Return the smallest distance between two line segments, squared
1426 ================
1427 */
DistanceBetweenLineSegmentsSquared(const vec3_t sP0,const vec3_t sP1,const vec3_t tP0,const vec3_t tP1,float * s,float * t)1428 vec_t DistanceBetweenLineSegmentsSquared(
1429 const vec3_t sP0, const vec3_t sP1,
1430 const vec3_t tP0, const vec3_t tP1,
1431 float *s, float *t )
1432 {
1433 vec3_t sMag, tMag, diff;
1434 float a, b, c, d, e;
1435 float D;
1436 float sN, sD;
1437 float tN, tD;
1438 vec3_t separation;
1439
1440 VectorSubtract( sP1, sP0, sMag );
1441 VectorSubtract( tP1, tP0, tMag );
1442 VectorSubtract( sP0, tP0, diff );
1443 a = DotProduct( sMag, sMag );
1444 b = DotProduct( sMag, tMag );
1445 c = DotProduct( tMag, tMag );
1446 d = DotProduct( sMag, diff );
1447 e = DotProduct( tMag, diff );
1448 sD = tD = D = a * c - b * b;
1449
1450 if( D < LINE_DISTANCE_EPSILON )
1451 {
1452 // the lines are almost parallel
1453 sN = 0.0; // force using point P0 on segment S1
1454 sD = 1.0; // to prevent possible division by 0.0 later
1455 tN = e;
1456 tD = c;
1457 }
1458 else
1459 {
1460 // get the closest points on the infinite lines
1461 sN = ( b * e - c * d );
1462 tN = ( a * e - b * d );
1463
1464 if( sN < 0.0 )
1465 {
1466 // sN < 0 => the s=0 edge is visible
1467 sN = 0.0;
1468 tN = e;
1469 tD = c;
1470 }
1471 else if( sN > sD )
1472 {
1473 // sN > sD => the s=1 edge is visible
1474 sN = sD;
1475 tN = e + b;
1476 tD = c;
1477 }
1478 }
1479
1480 if( tN < 0.0 )
1481 {
1482 // tN < 0 => the t=0 edge is visible
1483 tN = 0.0;
1484
1485 // recompute sN for this edge
1486 if( -d < 0.0 )
1487 sN = 0.0;
1488 else if( -d > a )
1489 sN = sD;
1490 else
1491 {
1492 sN = -d;
1493 sD = a;
1494 }
1495 }
1496 else if( tN > tD )
1497 {
1498 // tN > tD => the t=1 edge is visible
1499 tN = tD;
1500
1501 // recompute sN for this edge
1502 if( ( -d + b ) < 0.0 )
1503 sN = 0;
1504 else if( ( -d + b ) > a )
1505 sN = sD;
1506 else
1507 {
1508 sN = ( -d + b );
1509 sD = a;
1510 }
1511 }
1512
1513 // finally do the division to get *s and *t
1514 *s = ( fabs( sN ) < LINE_DISTANCE_EPSILON ? 0.0 : sN / sD );
1515 *t = ( fabs( tN ) < LINE_DISTANCE_EPSILON ? 0.0 : tN / tD );
1516
1517 // get the difference of the two closest points
1518 VectorScale( sMag, *s, sMag );
1519 VectorScale( tMag, *t, tMag );
1520 VectorAdd( diff, sMag, separation );
1521 VectorSubtract( separation, tMag, separation );
1522
1523 return VectorLengthSquared( separation );
1524 }
1525
1526 /*
1527 ================
1528 DistanceBetweenLineSegments
1529
1530 Return the smallest distance between two line segments
1531 ================
1532 */
DistanceBetweenLineSegments(const vec3_t sP0,const vec3_t sP1,const vec3_t tP0,const vec3_t tP1,float * s,float * t)1533 vec_t DistanceBetweenLineSegments(
1534 const vec3_t sP0, const vec3_t sP1,
1535 const vec3_t tP0, const vec3_t tP1,
1536 float *s, float *t )
1537 {
1538 return (vec_t)sqrt( DistanceBetweenLineSegmentsSquared(
1539 sP0, sP1, tP0, tP1, s, t ) );
1540 }
1541
1542 /*
1543 =================
1544 Q_isnan
1545
1546 Don't pass doubles to this
1547 ================
1548 */
Q_isnan(float x)1549 int Q_isnan( float x )
1550 {
1551 union
1552 {
1553 float f;
1554 unsigned int i;
1555 } t;
1556
1557 t.f = x;
1558 t.i &= 0x7FFFFFFF;
1559 t.i = 0x7F800000 - t.i;
1560
1561 return (int)( (unsigned int)t.i >> 31 );
1562 }
1563