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