codemp/game/q_math.c

Go to the documentation of this file.
00001 // Copyright (C) 1999-2000 Id Software, Inc.
00002 //
00003 // q_math.c -- stateless support routines that are included in each code module
00004 #include "q_shared.h"
00005 
00006 
00007 vec3_t  vec3_origin = {0,0,0};
00008 vec3_t  axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
00009 
00010 
00011 vec4_t          colorBlack      = {0, 0, 0, 1};
00012 vec4_t          colorRed        = {1, 0, 0, 1};
00013 vec4_t          colorGreen      = {0, 1, 0, 1};
00014 vec4_t          colorBlue       = {0, 0, 1, 1};
00015 vec4_t          colorYellow     = {1, 1, 0, 1};
00016 vec4_t          colorMagenta= {1, 0, 1, 1};
00017 vec4_t          colorCyan       = {0, 1, 1, 1};
00018 vec4_t          colorWhite      = {1, 1, 1, 1};
00019 vec4_t          colorLtGrey     = {0.75, 0.75, 0.75, 1};
00020 vec4_t          colorMdGrey     = {0.5, 0.5, 0.5, 1};
00021 vec4_t          colorDkGrey     = {0.25, 0.25, 0.25, 1};
00022 
00023 vec4_t          colorLtBlue     = {0.367f, 0.261f, 0.722f, 1};
00024 vec4_t          colorDkBlue     = {0.199f, 0.0f,   0.398f, 1};
00025 
00026 vec4_t  g_color_table[8] =
00027         {
00028         {0.0, 0.0, 0.0, 1.0},
00029         {1.0, 0.0, 0.0, 1.0},
00030         {0.0, 1.0, 0.0, 1.0},
00031         {1.0, 1.0, 0.0, 1.0},
00032         {0.0, 0.0, 1.0, 1.0},
00033         {0.0, 1.0, 1.0, 1.0},
00034         {1.0, 0.0, 1.0, 1.0},
00035         {1.0, 1.0, 1.0, 1.0},
00036         };
00037 
00038 
00039 vec3_t  bytedirs[NUMVERTEXNORMALS] =
00040 {
00041 {-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f}, 
00042 {-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f}, 
00043 {-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f}, 
00044 {0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f}, 
00045 {0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f}, 
00046 {0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f}, 
00047 {0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f}, 
00048 {0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f}, 
00049 {-0.809017f, 0.309017f, 0.500000f},{-0.587785f, 0.425325f, 0.688191f}, 
00050 {-0.850651f, 0.525731f, 0.000000f},{-0.864188f, 0.442863f, 0.238856f}, 
00051 {-0.716567f, 0.681718f, 0.147621f},{-0.688191f, 0.587785f, 0.425325f}, 
00052 {-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f}, 
00053 {-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f}, 
00054 {-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f}, 
00055 {0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f}, 
00056 {0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f}, 
00057 {0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f}, 
00058 {-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f}, 
00059 {0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f}, 
00060 {0.238856f, 0.864188f, -0.442863f},{0.262866f, 0.951056f, -0.162460f}, 
00061 {0.500000f, 0.809017f, -0.309017f},{0.850651f, 0.525731f, 0.000000f}, 
00062 {0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f}, 
00063 {0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f}, 
00064 {0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f}, 
00065 {0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f}, 
00066 {0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f}, 
00067 {1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f}, 
00068 {0.850651f, -0.525731f, 0.000000f},{0.955423f, -0.295242f, 0.000000f}, 
00069 {0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f}, 
00070 {0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f}, 
00071 {0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f}, 
00072 {0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f}, 
00073 {0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f}, 
00074 {0.681718f, -0.147621f, -0.716567f},{0.850651f, 0.000000f, -0.525731f}, 
00075 {0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f}, 
00076 {0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f}, 
00077 {0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f}, 
00078 {0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f}, 
00079 {0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f}, 
00080 {-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f}, 
00081 {-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f}, 
00082 {-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f}, 
00083 {0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f}, 
00084 {0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f}, 
00085 {-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f}, 
00086 {0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f}, 
00087 {0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f}, 
00088 {0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f}, 
00089 {0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f}, 
00090 {0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f}, 
00091 {0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f}, 
00092 {0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f}, 
00093 {0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f}, 
00094 {0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f}, 
00095 {0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f}, 
00096 {0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f}, 
00097 {0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f}, 
00098 {-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f}, 
00099 {-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f}, 
00100 {-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f}, 
00101 {-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f}, 
00102 {-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f}, 
00103 {-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f}, 
00104 {-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f}, 
00105 {-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f}, 
00106 {-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f}, 
00107 {-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f}, 
00108 {0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f}, 
00109 {0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f}, 
00110 {0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f}, 
00111 {0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f}, 
00112 {-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f}, 
00113 {-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f}, 
00114 {-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f}, 
00115 {-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f}, 
00116 {-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f}, 
00117 {-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f}, 
00118 {-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f}, 
00119 {-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f}, 
00120 {-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f}, 
00121 {-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f}
00122 };
00123 
00124 //==============================================================
00125 
00126 int             Q_rand( int *seed ) {
00127         *seed = (69069 * *seed + 1);
00128         return *seed;
00129 }
00130 
00131 float   Q_random( int *seed ) {
00132         return ( Q_rand( seed ) & 0xffff ) / (float)0x10000;
00133 }
00134 
00135 float   Q_crandom( int *seed ) {
00136         return 2.0 * ( Q_random( seed ) - 0.5 );
00137 }
00138 
00139 #ifdef __LCC__
00140 
00141 int VectorCompare( const vec3_t v1, const vec3_t v2 ) {
00142         if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) {
00143                 return 0;
00144         }                       
00145         return 1;
00146 }
00147 
00148 vec_t VectorLength( const vec3_t v ) {
00149         return (vec_t)sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00150 }
00151 
00152 vec_t VectorLengthSquared( const vec3_t v ) {
00153         return (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00154 }
00155 
00156 vec_t Distance( const vec3_t p1, const vec3_t p2 ) {
00157         vec3_t  v;
00158 
00159         VectorSubtract (p2, p1, v);
00160         return VectorLength( v );
00161 }
00162 
00163 vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 ) {
00164         vec3_t  v;
00165 
00166         VectorSubtract (p2, p1, v);
00167         return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
00168 }
00169 
00170 // fast vector normalize routine that does not check to make sure
00171 // that length != 0, nor does it return length, uses rsqrt approximation
00172 void VectorNormalizeFast( vec3_t v )
00173 {
00174         float ilength;
00175 
00176         ilength = Q_rsqrt( DotProduct( v, v ) );
00177 
00178         v[0] *= ilength;
00179         v[1] *= ilength;
00180         v[2] *= ilength;
00181 }
00182 
00183 void VectorInverse( vec3_t v ){
00184         v[0] = -v[0];
00185         v[1] = -v[1];
00186         v[2] = -v[2];
00187 }
00188 
00189 //i wrote this function in a console test app and it appeared faster
00190 //in debug and release than the standard crossproduct asm generated
00191 //by the compiler. however, when inlining the crossproduct function
00192 //the compiler performs further optimizations and generally ends up
00193 //being faster than this asm version. but feel free to try this one
00194 //and see if you're heavily crossproducting in an area and looking
00195 //for a way to optimize. -rww
00196 #if 0
00197 void CrossProductA (float *v1, float *v2, float *cross)
00198 {
00199 #if 1
00200         static float scratch1, scratch2, scratch3, scratch4, scratch5, scratch6;
00201 
00202         __asm mov   eax,v1
00203         __asm mov   ecx,v2
00204         __asm mov   edx,cross
00205 
00206         __asm fld   dword ptr[eax+4]
00207         __asm fmul  dword ptr[ecx+8]
00208         __asm fstp  scratch1
00209 
00210         __asm fld   dword ptr[eax+8]
00211         __asm fmul  dword ptr[ecx+4]
00212         __asm fstp  scratch2
00213 
00214         __asm fld   dword ptr[eax+8]
00215         __asm fmul  dword ptr[ecx]
00216         __asm fstp  scratch3
00217 
00218         __asm fld   dword ptr[eax]
00219         __asm fmul  dword ptr[ecx+8]
00220         __asm fstp  scratch4
00221 
00222         __asm fld   dword ptr[eax]
00223         __asm fmul  dword ptr[ecx+4]
00224         __asm fstp  scratch5
00225 
00226         __asm fld   dword ptr[eax+4]
00227         __asm fmul  dword ptr[ecx]
00228         __asm fstp  scratch6
00229 
00230         __asm fld   scratch1
00231         __asm fsub  scratch2
00232         __asm fstp  dword ptr[edx]
00233 
00234         __asm fld   scratch3
00235         __asm fsub  scratch4
00236         __asm fstp  dword ptr[edx+4]
00237 
00238         __asm fld   scratch5
00239         __asm fsub  scratch6
00240         __asm fstp  dword ptr[edx+8]
00241 #else //doesn't require use of statics, but not nearly as fast.
00242         __asm mov   eax,v1
00243         __asm mov   ecx,v2
00244         __asm mov   edx,cross
00245 
00246         __asm fld   dword ptr[eax+4]
00247         __asm fmul  dword ptr[ecx+8]
00248         __asm fld   dword ptr[eax+8]
00249         __asm fmul  dword ptr[ecx+4]
00250         __asm fsubp st(1),st
00251         __asm fstp  dword ptr[edx]
00252 
00253         __asm fld   dword ptr[eax+8]
00254         __asm fmul  dword ptr[ecx]
00255         __asm fld   dword ptr[eax]
00256         __asm fmul  dword ptr[ecx+8]
00257         __asm fsubp st(1),st
00258         __asm fstp  dword ptr[edx+4]
00259 
00260         __asm fld   dword ptr[eax]
00261         __asm fmul  dword ptr[ecx+4]
00262         __asm fld   dword ptr[eax+4]
00263         __asm fmul  dword ptr[ecx]
00264         __asm fsubp st(1),st
00265         __asm fstp  dword ptr[edx+8]
00266 #endif
00267 }
00268 #endif
00269 
00270 void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ) {
00271         cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
00272         cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
00273         cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
00274 }
00275 #endif
00276 
00277 //=======================================================
00278 
00279 signed char ClampChar( int i ) {
00280         if ( i < -128 ) {
00281                 return -128;
00282         }
00283         if ( i > 127 ) {
00284                 return 127;
00285         }
00286         return i;
00287 }
00288 
00289 signed short ClampShort( int i ) {
00290         if ( i < -32768 ) {
00291                 return -32768;
00292         }
00293         if ( i > 0x7fff ) {
00294                 return 0x7fff;
00295         }
00296         return i;
00297 }
00298 
00299 
00300 // this isn't a real cheap function to call!
00301 int DirToByte( vec3_t dir ) {
00302         int             i, best;
00303         float   d, bestd;
00304 
00305         if ( !dir ) {
00306                 return 0;
00307         }
00308 
00309         bestd = 0;
00310         best = 0;
00311         for (i=0 ; i<NUMVERTEXNORMALS ; i++)
00312         {
00313                 d = DotProduct (dir, bytedirs[i]);
00314                 if (d > bestd)
00315                 {
00316                         bestd = d;
00317                         best = i;
00318                 }
00319         }
00320 
00321         return best;
00322 }
00323 
00324 void ByteToDir( int b, vec3_t dir ) {
00325         if ( b < 0 || b >= NUMVERTEXNORMALS ) {
00326                 VectorCopy( vec3_origin, dir );
00327                 return;
00328         }
00329         VectorCopy (bytedirs[b], dir);
00330 }
00331 
00332 
00333 unsigned ColorBytes3 (float r, float g, float b) {
00334         unsigned        i;
00335 
00336         ( (byte *)&i )[0] = r * 255;
00337         ( (byte *)&i )[1] = g * 255;
00338         ( (byte *)&i )[2] = b * 255;
00339 
00340         return i;
00341 }
00342 
00343 unsigned ColorBytes4 (float r, float g, float b, float a) {
00344         unsigned        i;
00345 
00346         ( (byte *)&i )[0] = r * 255;
00347         ( (byte *)&i )[1] = g * 255;
00348         ( (byte *)&i )[2] = b * 255;
00349         ( (byte *)&i )[3] = a * 255;
00350 
00351         return i;
00352 }
00353 
00354 float NormalizeColor( const vec3_t in, vec3_t out ) {
00355         float   max;
00356         
00357         max = in[0];
00358         if ( in[1] > max ) {
00359                 max = in[1];
00360         }
00361         if ( in[2] > max ) {
00362                 max = in[2];
00363         }
00364 
00365         if ( !max ) {
00366                 VectorClear( out );
00367         } else {
00368                 out[0] = in[0] / max;
00369                 out[1] = in[1] / max;
00370                 out[2] = in[2] / max;
00371         }
00372         return max;
00373 }
00374 
00375 
00376 /*
00377 =====================
00378 PlaneFromPoints
00379 
00380 Returns false if the triangle is degenrate.
00381 The normal will point out of the clock for clockwise ordered points
00382 =====================
00383 */
00384 qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
00385         vec3_t  d1, d2;
00386 
00387         VectorSubtract( b, a, d1 );
00388         VectorSubtract( c, a, d2 );
00389         CrossProduct( d2, d1, plane );
00390         if ( VectorNormalize( plane ) == 0 ) {
00391                 return qfalse;
00392         }
00393 
00394         plane[3] = DotProduct( a, plane );
00395         return qtrue;
00396 }
00397 
00398 /*
00399 ===============
00400 RotatePointAroundVector
00401 
00402 This is not implemented very well...
00403 ===============
00404 */
00405 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
00406                                                          float degrees ) {
00407         float   m[3][3];
00408         float   im[3][3];
00409         float   zrot[3][3];
00410         float   tmpmat[3][3];
00411         float   rot[3][3];
00412         int     i;
00413         vec3_t vr, vup, vf;
00414         float   rad;
00415 
00416         vf[0] = dir[0];
00417         vf[1] = dir[1];
00418         vf[2] = dir[2];
00419 
00420         PerpendicularVector( vr, dir );
00421         CrossProduct( vr, vf, vup );
00422 
00423         m[0][0] = vr[0];
00424         m[1][0] = vr[1];
00425         m[2][0] = vr[2];
00426 
00427         m[0][1] = vup[0];
00428         m[1][1] = vup[1];
00429         m[2][1] = vup[2];
00430 
00431         m[0][2] = vf[0];
00432         m[1][2] = vf[1];
00433         m[2][2] = vf[2];
00434 
00435         memcpy( im, m, sizeof( im ) );
00436 
00437         im[0][1] = m[1][0];
00438         im[0][2] = m[2][0];
00439         im[1][0] = m[0][1];
00440         im[1][2] = m[2][1];
00441         im[2][0] = m[0][2];
00442         im[2][1] = m[1][2];
00443 
00444         memset( zrot, 0, sizeof( zrot ) );
00445         zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
00446 
00447         rad = DEG2RAD( degrees );
00448         zrot[0][0] = cos( rad );
00449         zrot[0][1] = sin( rad );
00450         zrot[1][0] = -sin( rad );
00451         zrot[1][1] = cos( rad );
00452 
00453         MatrixMultiply( m, zrot, tmpmat );
00454         MatrixMultiply( tmpmat, im, rot );
00455 
00456         for ( i = 0; i < 3; i++ ) {
00457                 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
00458         }
00459 }
00460 
00461 /*
00462 ===============
00463 RotateAroundDirection
00464 ===============
00465 */
00466 void RotateAroundDirection( vec3_t axis[3], float yaw ) {
00467 
00468         // create an arbitrary axis[1] 
00469         PerpendicularVector( axis[1], axis[0] );
00470 
00471         // rotate it around axis[0] by yaw
00472         if ( yaw ) {
00473                 vec3_t  temp;
00474 
00475                 VectorCopy( axis[1], temp );
00476                 RotatePointAroundVector( axis[1], axis[0], temp, yaw );
00477         }
00478 
00479         // cross to get axis[2]
00480         CrossProduct( axis[0], axis[1], axis[2] );
00481 }
00482 
00483 
00484 
00485 void vectoangles( const vec3_t value1, vec3_t angles ) {
00486         float   forward;
00487         float   yaw, pitch;
00488         
00489         if ( value1[1] == 0 && value1[0] == 0 ) {
00490                 yaw = 0;
00491                 if ( value1[2] > 0 ) {
00492                         pitch = 90;
00493                 }
00494                 else {
00495                         pitch = 270;
00496                 }
00497         }
00498         else {
00499                 if ( value1[0] ) {
00500                         yaw = ( atan2 ( value1[1], value1[0] ) * 180 / M_PI );
00501                 }
00502                 else if ( value1[1] > 0 ) {
00503                         yaw = 90;
00504                 }
00505                 else {
00506                         yaw = 270;
00507                 }
00508                 if ( yaw < 0 ) {
00509                         yaw += 360;
00510                 }
00511 
00512                 forward = sqrt ( value1[0]*value1[0] + value1[1]*value1[1] );
00513                 pitch = ( atan2(value1[2], forward) * 180 / M_PI );
00514                 if ( pitch < 0 ) {
00515                         pitch += 360;
00516                 }
00517         }
00518 
00519         angles[PITCH] = -pitch;
00520         angles[YAW] = yaw;
00521         angles[ROLL] = 0;
00522 }
00523 
00524 
00525 /*
00526 =================
00527 AnglesToAxis
00528 =================
00529 */
00530 void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) {
00531         vec3_t  right;
00532 
00533         // angle vectors returns "right" instead of "y axis"
00534         AngleVectors( angles, axis[0], right, axis[2] );
00535         VectorSubtract( vec3_origin, right, axis[1] );
00536 }
00537 
00538 void AxisClear( vec3_t axis[3] ) {
00539         axis[0][0] = 1;
00540         axis[0][1] = 0;
00541         axis[0][2] = 0;
00542         axis[1][0] = 0;
00543         axis[1][1] = 1;
00544         axis[1][2] = 0;
00545         axis[2][0] = 0;
00546         axis[2][1] = 0;
00547         axis[2][2] = 1;
00548 }
00549 
00550 void AxisCopy( vec3_t in[3], vec3_t out[3] ) {
00551         VectorCopy( in[0], out[0] );
00552         VectorCopy( in[1], out[1] );
00553         VectorCopy( in[2], out[2] );
00554 }
00555 
00556 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
00557 {
00558         float d;
00559         vec3_t n;
00560         float inv_denom;
00561 
00562         inv_denom =  DotProduct( normal, normal );
00563 #ifndef Q3_VM
00564         assert( Q_fabs(inv_denom) != 0.0f ); // bk010122 - zero vectors get here
00565 #endif
00566         inv_denom = 1.0f / inv_denom;
00567 
00568         d = DotProduct( normal, p ) * inv_denom;
00569 
00570         n[0] = normal[0] * inv_denom;
00571         n[1] = normal[1] * inv_denom;
00572         n[2] = normal[2] * inv_denom;
00573 
00574         dst[0] = p[0] - d * n[0];
00575         dst[1] = p[1] - d * n[1];
00576         dst[2] = p[2] - d * n[2];
00577 }
00578 
00579 /*
00580 ================
00581 MakeNormalVectors
00582 
00583 Given a normalized forward vector, create two
00584 other perpendicular vectors
00585 ================
00586 */
00587 void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up) {
00588         float           d;
00589 
00590         // this rotate and negate guarantees a vector
00591         // not colinear with the original
00592         right[1] = -forward[0];
00593         right[2] = forward[1];
00594         right[0] = forward[2];
00595 
00596         d = DotProduct (right, forward);
00597         VectorMA (right, -d, forward, right);
00598         VectorNormalize (right);
00599         CrossProduct (right, forward, up);
00600 }
00601 
00602 
00603 void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out )
00604 {
00605         out[0] = DotProduct( in, matrix[0] );
00606         out[1] = DotProduct( in, matrix[1] );
00607         out[2] = DotProduct( in, matrix[2] );
00608 }
00609 
00610 //============================================================================
00611 
00612 #if !idppc
00613 /*
00614 ** float q_rsqrt( float number )
00615 */
00616 float Q_rsqrt( float number )
00617 {
00618         long i;
00619         float x2, y;
00620         const float threehalfs = 1.5F;
00621 
00622         x2 = number * 0.5F;
00623         y  = number;
00624         i  = * ( long * ) &y;                                           // evil floating point bit level hacking
00625         i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
00626         y  = * ( float * ) &i;
00627         y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
00628 //      y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
00629 
00630 #ifndef Q3_VM
00631 #ifdef __linux__
00632         assert( !isnan(y) ); // bk010122 - FPE?
00633 #endif
00634 #endif
00635         return y;
00636 }
00637 
00638 float Q_fabs( float f ) {
00639         int tmp = * ( int * ) &f;
00640         tmp &= 0x7FFFFFFF;
00641         return * ( float * ) &tmp;
00642 }
00643 #endif
00644 
00645 //============================================================
00646 
00647 /*
00648 ===============
00649 LerpAngle
00650 
00651 ===============
00652 */
00653 float LerpAngle (float from, float to, float frac) {
00654         float   a;
00655 
00656         if ( to - from > 180 ) {
00657                 to -= 360;
00658         }
00659         if ( to - from < -180 ) {
00660                 to += 360;
00661         }
00662         a = from + frac * (to - from);
00663 
00664         return a;
00665 }
00666 
00667 
00668 /*
00669 =================
00670 AngleSubtract
00671 
00672 Always returns a value from -180 to 180
00673 =================
00674 */
00675 float   AngleSubtract( float a1, float a2 ) {
00676         float   a;
00677 
00678         a = a1 - a2;
00679         a=fmod(a,360);//chop it down quickly, then level it out
00680         while ( a > 180 ) {
00681                 a -= 360;
00682         }
00683         while ( a < -180 ) {
00684                 a += 360;
00685         }
00686         return a;
00687 }
00688 
00689 
00690 void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ) {
00691         v3[0] = AngleSubtract( v1[0], v2[0] );
00692         v3[1] = AngleSubtract( v1[1], v2[1] );
00693         v3[2] = AngleSubtract( v1[2], v2[2] );
00694 }
00695 
00696 
00697 float   AngleMod(float a) {
00698         a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
00699         return a;
00700 }
00701 
00702 
00703 /*
00704 =================
00705 AngleNormalize360
00706 
00707 returns angle normalized to the range [0 <= angle < 360]
00708 =================
00709 */
00710 float AngleNormalize360 ( float angle ) {
00711         return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535);
00712 }
00713 
00714 
00715 /*
00716 =================
00717 AngleNormalize180
00718 
00719 returns angle normalized to the range [-180 < angle <= 180]
00720 =================
00721 */
00722 float AngleNormalize180 ( float angle ) {
00723         angle = AngleNormalize360( angle );
00724         if ( angle > 180.0 ) {
00725                 angle -= 360.0;
00726         }
00727         return angle;
00728 }
00729 
00730 
00731 /*
00732 =================
00733 AngleDelta
00734 
00735 returns the normalized delta from angle1 to angle2
00736 =================
00737 */
00738 float AngleDelta ( float angle1, float angle2 ) {
00739         return AngleNormalize180( angle1 - angle2 );
00740 }
00741 
00742 
00743 //============================================================
00744 
00745 
00746 /*
00747 =================
00748 SetPlaneSignbits
00749 =================
00750 */
00751 void SetPlaneSignbits (cplane_t *out) {
00752         int     bits, j;
00753 
00754         // for fast box on planeside test
00755         bits = 0;
00756         for (j=0 ; j<3 ; j++) {
00757                 if (out->normal[j] < 0) {
00758                         bits |= 1<<j;
00759                 }
00760         }
00761         out->signbits = bits;
00762 }
00763 
00764 
00765 /*
00766 ==================
00767 BoxOnPlaneSide
00768 
00769 Returns 1, 2, or 1 + 2
00770 
00771 // this is the slow, general version
00772 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
00773 {
00774         int             i;
00775         float   dist1, dist2;
00776         int             sides;
00777         vec3_t  corners[2];
00778 
00779         for (i=0 ; i<3 ; i++)
00780         {
00781                 if (p->normal[i] < 0)
00782                 {
00783                         corners[0][i] = emins[i];
00784                         corners[1][i] = emaxs[i];
00785                 }
00786                 else
00787                 {
00788                         corners[1][i] = emins[i];
00789                         corners[0][i] = emaxs[i];
00790                 }
00791         }
00792         dist1 = DotProduct (p->normal, corners[0]) - p->dist;
00793         dist2 = DotProduct (p->normal, corners[1]) - p->dist;
00794         sides = 0;
00795         if (dist1 >= 0)
00796                 sides = 1;
00797         if (dist2 < 0)
00798                 sides |= 2;
00799 
00800         return sides;
00801 }
00802 
00803 ==================
00804 */
00805 #if !( (defined __linux__ || __FreeBSD__) && (defined __i386__) && (!defined C_ONLY)) // rb010123
00806 
00807 #if defined __LCC__ || defined C_ONLY || !id386
00808 
00809 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
00810 {
00811         float   dist1, dist2;
00812         int             sides;
00813 
00814 // fast axial cases
00815         if (p->type < 3)
00816         {
00817                 if (p->dist <= emins[p->type])
00818                         return 1;
00819                 if (p->dist >= emaxs[p->type])
00820                         return 2;
00821                 return 3;
00822         }
00823 
00824 // general case
00825         switch (p->signbits)
00826         {
00827         case 0:
00828                 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00829                 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00830                 break;
00831         case 1:
00832                 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00833                 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00834                 break;
00835         case 2:
00836                 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00837                 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00838                 break;
00839         case 3:
00840                 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00841                 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00842                 break;
00843         case 4:
00844                 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00845                 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00846                 break;
00847         case 5:
00848                 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
00849                 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
00850                 break;
00851         case 6:
00852                 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00853                 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00854                 break;
00855         case 7:
00856                 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
00857                 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
00858                 break;
00859         default:
00860                 dist1 = dist2 = 0;              // shut up compiler
00861                 break;
00862         }
00863 
00864         sides = 0;
00865         if (dist1 >= p->dist)
00866                 sides = 1;
00867         if (dist2 < p->dist)
00868                 sides |= 2;
00869 
00870         return sides;
00871 }
00872 #else
00873 #pragma warning( disable: 4035 )
00874 
00875 __declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
00876 {
00877         static int bops_initialized;
00878         static int Ljmptab[8];
00879 
00880         __asm {
00881 
00882                 push ebx
00883                         
00884                 cmp bops_initialized, 1
00885                 je  initialized
00886                 mov bops_initialized, 1
00887                 
00888                 mov Ljmptab[0*4], offset Lcase0
00889                 mov Ljmptab[1*4], offset Lcase1
00890                 mov Ljmptab[2*4], offset Lcase2
00891                 mov Ljmptab[3*4], offset Lcase3
00892                 mov Ljmptab[4*4], offset Lcase4
00893                 mov Ljmptab[5*4], offset Lcase5
00894                 mov Ljmptab[6*4], offset Lcase6
00895                 mov Ljmptab[7*4], offset Lcase7
00896                         
00897 initialized:
00898 
00899                 mov edx,dword ptr[4+12+esp]
00900                 mov ecx,dword ptr[4+4+esp]
00901                 xor eax,eax
00902                 mov ebx,dword ptr[4+8+esp]
00903                 mov al,byte ptr[17+edx]
00904                 cmp al,8
00905                 jge Lerror
00906                 fld dword ptr[0+edx]
00907                 fld st(0)
00908                 jmp dword ptr[Ljmptab+eax*4]
00909 Lcase0:
00910                 fmul dword ptr[ebx]
00911                 fld dword ptr[0+4+edx]
00912                 fxch st(2)
00913                 fmul dword ptr[ecx]
00914                 fxch st(2)
00915                 fld st(0)
00916                 fmul dword ptr[4+ebx]
00917                 fld dword ptr[0+8+edx]
00918                 fxch st(2)
00919                 fmul dword ptr[4+ecx]
00920                 fxch st(2)
00921                 fld st(0)
00922                 fmul dword ptr[8+ebx]
00923                 fxch st(5)
00924                 faddp st(3),st(0)
00925                 fmul dword ptr[8+ecx]
00926                 fxch st(1)
00927                 faddp st(3),st(0)
00928                 fxch st(3)
00929                 faddp st(2),st(0)
00930                 jmp LSetSides
00931 Lcase1:
00932                 fmul dword ptr[ecx]
00933                 fld dword ptr[0+4+edx]
00934                 fxch st(2)
00935                 fmul dword ptr[ebx]
00936                 fxch st(2)
00937                 fld st(0)
00938                 fmul dword ptr[4+ebx]
00939                 fld dword ptr[0+8+edx]
00940                 fxch st(2)
00941                 fmul dword ptr[4+ecx]
00942                 fxch st(2)
00943                 fld st(0)
00944                 fmul dword ptr[8+ebx]
00945                 fxch st(5)
00946                 faddp st(3),st(0)
00947                 fmul dword ptr[8+ecx]
00948                 fxch st(1)
00949                 faddp st(3),st(0)
00950                 fxch st(3)
00951                 faddp st(2),st(0)
00952                 jmp LSetSides
00953 Lcase2:
00954                 fmul dword ptr[ebx]
00955                 fld dword ptr[0+4+edx]
00956                 fxch st(2)
00957                 fmul dword ptr[ecx]
00958                 fxch st(2)
00959                 fld st(0)
00960                 fmul dword ptr[4+ecx]
00961                 fld dword ptr[0+8+edx]
00962                 fxch st(2)
00963                 fmul dword ptr[4+ebx]
00964                 fxch st(2)
00965                 fld st(0)
00966                 fmul dword ptr[8+ebx]
00967                 fxch st(5)
00968                 faddp st(3),st(0)
00969                 fmul dword ptr[8+ecx]
00970                 fxch st(1)
00971                 faddp st(3),st(0)
00972                 fxch st(3)
00973                 faddp st(2),st(0)
00974                 jmp LSetSides
00975 Lcase3:
00976                 fmul dword ptr[ecx]
00977                 fld dword ptr[0+4+edx]
00978                 fxch st(2)
00979                 fmul dword ptr[ebx]
00980                 fxch st(2)
00981                 fld st(0)
00982                 fmul dword ptr[4+ecx]
00983                 fld dword ptr[0+8+edx]
00984                 fxch st(2)
00985                 fmul dword ptr[4+ebx]
00986                 fxch st(2)
00987                 fld st(0)
00988                 fmul dword ptr[8+ebx]
00989                 fxch st(5)
00990                 faddp st(3),st(0)
00991                 fmul dword ptr[8+ecx]
00992                 fxch st(1)
00993                 faddp st(3),st(0)
00994                 fxch st(3)
00995                 faddp st(2),st(0)
00996                 jmp LSetSides
00997 Lcase4:
00998                 fmul dword ptr[ebx]
00999                 fld dword ptr[0+4+edx]
01000                 fxch st(2)
01001                 fmul dword ptr[ecx]
01002                 fxch st(2)
01003                 fld st(0)
01004                 fmul dword ptr[4+ebx]
01005                 fld dword ptr[0+8+edx]
01006                 fxch st(2)
01007                 fmul dword ptr[4+ecx]
01008                 fxch st(2)
01009                 fld st(0)
01010                 fmul dword ptr[8+ecx]
01011                 fxch st(5)
01012                 faddp st(3),st(0)
01013                 fmul dword ptr[8+ebx]
01014                 fxch st(1)
01015                 faddp st(3),st(0)
01016                 fxch st(3)
01017                 faddp st(2),st(0)
01018                 jmp LSetSides
01019 Lcase5:
01020                 fmul dword ptr[ecx]
01021                 fld dword ptr[0+4+edx]
01022                 fxch st(2)
01023                 fmul dword ptr[ebx]
01024                 fxch st(2)
01025                 fld st(0)
01026                 fmul dword ptr[4+ebx]
01027                 fld dword ptr[0+8+edx]
01028                 fxch st(2)
01029                 fmul dword ptr[4+ecx]
01030                 fxch st(2)
01031                 fld st(0)
01032                 fmul dword ptr[8+ecx]
01033                 fxch st(5)
01034                 faddp st(3),st(0)
01035                 fmul dword ptr[8+ebx]
01036                 fxch st(1)
01037                 faddp st(3),st(0)
01038                 fxch st(3)
01039                 faddp st(2),st(0)
01040                 jmp LSetSides
01041 Lcase6:
01042                 fmul dword ptr[ebx]
01043                 fld dword ptr[0+4+edx]
01044                 fxch st(2)
01045                 fmul dword ptr[ecx]
01046                 fxch st(2)
01047                 fld st(0)
01048                 fmul dword ptr[4+ecx]
01049                 fld dword ptr[0+8+edx]
01050                 fxch st(2)
01051                 fmul dword ptr[4+ebx]
01052                 fxch st(2)
01053                 fld st(0)
01054                 fmul dword ptr[8+ecx]
01055                 fxch st(5)
01056                 faddp st(3),st(0)
01057                 fmul dword ptr[8+ebx]
01058                 fxch st(1)
01059                 faddp st(3),st(0)
01060                 fxch st(3)
01061                 faddp st(2),st(0)
01062                 jmp LSetSides
01063 Lcase7:
01064                 fmul dword ptr[ecx]
01065                 fld dword ptr[0+4+edx]
01066                 fxch st(2)
01067                 fmul dword ptr[ebx]
01068                 fxch st(2)
01069                 fld st(0)
01070                 fmul dword ptr[4+ecx]
01071                 fld dword ptr[0+8+edx]
01072                 fxch st(2)
01073                 fmul dword ptr[4+ebx]
01074                 fxch st(2)
01075                 fld st(0)
01076                 fmul dword ptr[8+ecx]
01077                 fxch st(5)
01078                 faddp st(3),st(0)
01079                 fmul dword ptr[8+ebx]
01080                 fxch st(1)
01081                 faddp st(3),st(0)
01082                 fxch st(3)
01083                 faddp st(2),st(0)
01084 LSetSides:
01085                 faddp st(2),st(0)
01086                 fcomp dword ptr[12+edx]
01087                 xor ecx,ecx
01088                 fnstsw ax
01089                 fcomp dword ptr[12+edx]
01090                 and ah,1
01091                 xor ah,1
01092                 add cl,ah
01093                 fnstsw ax
01094                 and ah,1
01095                 add ah,ah
01096                 add cl,ah
01097                 pop ebx
01098                 mov eax,ecx
01099                 ret
01100 Lerror:
01101                 int 3
01102         }
01103 }
01104 #pragma warning( default: 4035 )
01105 
01106 #endif
01107 #endif
01108 
01109 /*
01110 =================
01111 RadiusFromBounds
01112 =================
01113 */
01114 float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
01115         int             i;
01116         vec3_t  corner;
01117         float   a, b;
01118 
01119         for (i=0 ; i<3 ; i++) {
01120                 a = fabs( mins[i] );
01121                 b = fabs( maxs[i] );
01122                 corner[i] = a > b ? a : b;
01123         }
01124 
01125         return VectorLength (corner);
01126 }
01127 
01128 
01129 void ClearBounds( vec3_t mins, vec3_t maxs ) {
01130         mins[0] = mins[1] = mins[2] = 99999;
01131         maxs[0] = maxs[1] = maxs[2] = -99999;
01132 }
01133 
01134 vec_t DistanceHorizontal( const vec3_t p1, const vec3_t p2 ) {
01135         vec3_t  v;
01136 
01137         VectorSubtract( p2, p1, v );
01138         return sqrt( v[0]*v[0] + v[1]*v[1] );   //Leave off the z component
01139 }
01140 
01141 vec_t DistanceHorizontalSquared( const vec3_t p1, const vec3_t p2 ) {
01142         vec3_t  v;
01143 
01144         VectorSubtract( p2, p1, v );
01145         return v[0]*v[0] + v[1]*v[1];   //Leave off the z component
01146 }
01147 
01148 void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) {
01149         if ( v[0] < mins[0] ) {
01150                 mins[0] = v[0];
01151         }
01152         if ( v[0] > maxs[0]) {
01153                 maxs[0] = v[0];
01154         }
01155 
01156         if ( v[1] < mins[1] ) {
01157                 mins[1] = v[1];
01158         }
01159         if ( v[1] > maxs[1]) {
01160                 maxs[1] = v[1];
01161         }
01162 
01163         if ( v[2] < mins[2] ) {
01164                 mins[2] = v[2];
01165         }
01166         if ( v[2] > maxs[2]) {
01167                 maxs[2] = v[2];
01168         }
01169 }
01170 
01171 
01172 vec_t VectorNormalize( vec3_t v ) {
01173         float   length, ilength;
01174 
01175         length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
01176         length = sqrt (length);
01177 
01178         if ( length ) {
01179                 ilength = 1/length;
01180                 v[0] *= ilength;
01181                 v[1] *= ilength;
01182                 v[2] *= ilength;
01183         }
01184                 
01185         return length;
01186 }
01187 
01188 vec_t VectorNormalize2( const vec3_t v, vec3_t out) {
01189         float   length, ilength;
01190 
01191         length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
01192         length = sqrt (length);
01193 
01194         if (length)
01195         {
01196 #ifndef Q3_VM // bk0101022 - FPE related
01197 //        assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) );
01198 #endif
01199                 ilength = 1/length;
01200                 out[0] = v[0]*ilength;
01201                 out[1] = v[1]*ilength;
01202                 out[2] = v[2]*ilength;
01203         } else {
01204 #ifndef Q3_VM // bk0101022 - FPE related
01205 //        assert( ((Q_fabs(v[0])==0.0f) && (Q_fabs(v[1])==0.0f) && (Q_fabs(v[2])==0.0f)) );
01206 #endif
01207                 VectorClear( out );
01208         }
01209                 
01210         return length;
01211 
01212 }
01213 
01214 void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) {
01215         vecc[0] = veca[0] + scale*vecb[0];
01216         vecc[1] = veca[1] + scale*vecb[1];
01217         vecc[2] = veca[2] + scale*vecb[2];
01218 }
01219 
01220 
01221 vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ) {
01222         return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
01223 }
01224 
01225 void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
01226         out[0] = veca[0]-vecb[0];
01227         out[1] = veca[1]-vecb[1];
01228         out[2] = veca[2]-vecb[2];
01229 }
01230 
01231 void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
01232         out[0] = veca[0]+vecb[0];
01233         out[1] = veca[1]+vecb[1];
01234         out[2] = veca[2]+vecb[2];
01235 }
01236 
01237 void _VectorCopy( const vec3_t in, vec3_t out ) {
01238         out[0] = in[0];
01239         out[1] = in[1];
01240         out[2] = in[2];
01241 }
01242 
01243 void _VectorScale( const vec3_t in, vec_t scale, vec3_t out ) {
01244         out[0] = in[0]*scale;
01245         out[1] = in[1]*scale;
01246         out[2] = in[2]*scale;
01247 }
01248 
01249 void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ) {
01250         out[0] = in[0]*scale;
01251         out[1] = in[1]*scale;
01252         out[2] = in[2]*scale;
01253         out[3] = in[3]*scale;
01254 }
01255 
01256 
01257 int Q_log2( int val ) {
01258         int answer;
01259 
01260         answer = 0;
01261         while ( ( val>>=1 ) != 0 ) {
01262                 answer++;
01263         }
01264         return answer;
01265 }
01266 
01267 
01268 
01269 /*
01270 =================
01271 PlaneTypeForNormal
01272 =================
01273 */
01274 /*
01275 int     PlaneTypeForNormal (vec3_t normal) {
01276         if ( normal[0] == 1.0 )
01277                 return PLANE_X;
01278         if ( normal[1] == 1.0 )
01279                 return PLANE_Y;
01280         if ( normal[2] == 1.0 )
01281                 return PLANE_Z;
01282         
01283         return PLANE_NON_AXIAL;
01284 }
01285 */
01286 
01287 
01288 /*
01289 ================
01290 MatrixMultiply
01291 ================
01292 */
01293 void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
01294         out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
01295                                 in1[0][2] * in2[2][0];
01296         out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
01297                                 in1[0][2] * in2[2][1];
01298         out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
01299                                 in1[0][2] * in2[2][2];
01300         out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
01301                                 in1[1][2] * in2[2][0];
01302         out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
01303                                 in1[1][2] * in2[2][1];
01304         out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
01305                                 in1[1][2] * in2[2][2];
01306         out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
01307                                 in1[2][2] * in2[2][0];
01308         out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
01309                                 in1[2][2] * in2[2][1];
01310         out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
01311                                 in1[2][2] * in2[2][2];
01312 }
01313 
01314 
01315 void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
01316         float           angle;
01317         static float            sr, sp, sy, cr, cp, cy;
01318         // static to help MS compiler fp bugs
01319 
01320         angle = angles[YAW] * (M_PI*2 / 360);
01321         sy = sin(angle);
01322         cy = cos(angle);
01323         angle = angles[PITCH] * (M_PI*2 / 360);
01324         sp = sin(angle);
01325         cp = cos(angle);
01326         angle = angles[ROLL] * (M_PI*2 / 360);
01327         sr = sin(angle);
01328         cr = cos(angle);
01329 
01330         if (forward)
01331         {
01332                 forward[0] = cp*cy;
01333                 forward[1] = cp*sy;
01334                 forward[2] = -sp;
01335         }
01336         if (right)
01337         {
01338                 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
01339                 right[1] = (-1*sr*sp*sy+-1*cr*cy);
01340                 right[2] = -1*sr*cp;
01341         }
01342         if (up)
01343         {
01344                 up[0] = (cr*sp*cy+-sr*-sy);
01345                 up[1] = (cr*sp*sy+-sr*cy);
01346                 up[2] = cr*cp;
01347         }
01348 }
01349 
01350 /*
01351 ** assumes "src" is normalized
01352 */
01353 void PerpendicularVector( vec3_t dst, const vec3_t src )
01354 {
01355         int     pos;
01356         int i;
01357         float minelem = 1.0F;
01358         vec3_t tempvec;
01359 
01360         /*
01361         ** find the smallest magnitude axially aligned vector
01362         */
01363         for ( pos = 0, i = 0; i < 3; i++ )
01364         {
01365                 if ( fabs( src[i] ) < minelem )
01366                 {
01367                         pos = i;
01368                         minelem = fabs( src[i] );
01369                 }
01370         }
01371         tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
01372         tempvec[pos] = 1.0F;
01373 
01374         /*
01375         ** project the point onto the plane defined by src
01376         */
01377         ProjectPointOnPlane( dst, tempvec, src );
01378 
01379         /*
01380         ** normalize the result
01381         */
01382         VectorNormalize( dst );
01383 }
01384 
01385 /*
01386 ** NormalToLatLong
01387 **
01388 ** We use two byte encoded normals in some space critical applications.
01389 ** Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format
01390 ** Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
01391 **
01392 */
01393 //rwwRMG - added
01394 void NormalToLatLong( const vec3_t normal, byte bytes[2] )
01395 {
01396         // check for singularities
01397         if (!normal[0] && !normal[1])
01398         {
01399                 if ( normal[2] > 0.0f )
01400                 {
01401                         bytes[0] = 0;
01402                         bytes[1] = 0;           // lat = 0, long = 0
01403                 }
01404                 else
01405                 {
01406                         bytes[0] = 128;
01407                         bytes[1] = 0;           // lat = 0, long = 128
01408                 }
01409         }
01410         else
01411         {
01412                 int     a, b;
01413 
01414                 a = (int)(RAD2DEG( (vec_t)atan2( normal[1], normal[0] ) ) * (255.0f / 360.0f ));
01415                 a &= 0xff;
01416 
01417                 b = (int)(RAD2DEG( (vec_t)acos( normal[2] ) ) * ( 255.0f / 360.0f ));
01418                 b &= 0xff;
01419 
01420                 bytes[0] = b;   // longitude
01421                 bytes[1] = a;   // lattitude
01422         }
01423 }
01424 
01425 // This is the VC libc version of rand() without multiple seeds per thread or 12 levels
01426 // of subroutine calls.
01427 // Both calls have been designed to minimise the inherent number of float <--> int 
01428 // conversions and the additional math required to get the desired value.
01429 // eg the typical tint = (rand() * 255) / 32768
01430 // becomes tint = irand(0, 255)
01431 
01432 static unsigned long    holdrand = 0x89abcdef;
01433 
01434 void Rand_Init(int seed)
01435 {
01436         holdrand = seed;
01437 }
01438 
01439 // Returns a float min <= x < max (exclusive; will get max - 0.00001; but never max)
01440 
01441 float flrand(float min, float max)
01442 {
01443         float   result;
01444 
01445         holdrand = (holdrand * 214013L) + 2531011L;
01446         result = (float)(holdrand >> 17);                                               // 0 - 32767 range
01447         result = ((result * (max - min)) / 32768.0F) + min;
01448 
01449         return(result);
01450 }
01451 float Q_flrand(float min, float max)
01452 {
01453         return flrand(min,max);
01454 }
01455 
01456 // Returns an integer min <= x <= max (ie inclusive)
01457 
01458 int irand(int min, int max)
01459 {
01460         int             result;
01461 
01462         assert((max - min) < 32768);
01463 
01464         max++;
01465         holdrand = (holdrand * 214013L) + 2531011L;
01466         result = holdrand >> 17;
01467         result = ((result * (max - min)) >> 15) + min;
01468         return(result);
01469 }
01470 
01471 int Q_irand(int value1, int value2)
01472 {
01473         return irand(value1, value2);
01474 }
01475 
01476 float powf ( float x, int y )
01477 {
01478         float r = x;
01479         for ( y--; y>0; y-- )
01480                 r = r * r;
01481         return r;
01482 }
01483 
01484 #ifdef Q3_VM 
01485 //rwwRMG - needed for HandleEntityAdjustment
01486 double fmod( double x, double y )
01487 {
01488         int             result;
01489 
01490         if (y == 0.0)
01491         {
01492                 return 0.0;
01493         }
01494 
01495         result = x / y;
01496 
01497         return x - (result * y);
01498 }
01499 
01500 #endif // Q3_VM
01501 
01502 /*
01503 -------------------------
01504 DotProductNormalize
01505 -------------------------
01506 */
01507 
01508 float DotProductNormalize( const vec3_t inVec1, const vec3_t inVec2 )
01509 {
01510         vec3_t  v1, v2;
01511 
01512         VectorNormalize2( inVec1, v1 );
01513         VectorNormalize2( inVec2, v2 );
01514 
01515         return DotProduct(v1, v2);
01516 }
01517 
01518 /*
01519 -------------------------
01520 G_FindClosestPointOnLineSegment
01521 -------------------------
01522 */
01523 
01524 qboolean G_FindClosestPointOnLineSegment( const vec3_t start, const vec3_t end, const vec3_t from, vec3_t result )
01525 {
01526         vec3_t  vecStart2From, vecStart2End, vecEnd2Start, vecEnd2From;
01527         float   distEnd2From, distEnd2Result, theta, cos_theta, dot;
01528 
01529         //Find the perpendicular vector to vec from start to end
01530         VectorSubtract( from, start, vecStart2From);
01531         VectorSubtract( end, start, vecStart2End);
01532 
01533         dot = DotProductNormalize( vecStart2From, vecStart2End );
01534 
01535         if ( dot <= 0 )
01536         {
01537                 //The perpendicular would be beyond or through the start point
01538                 VectorCopy( start, result );
01539                 return qfalse;
01540         }
01541 
01542         if ( dot == 1 )
01543         {
01544                 //parallel, closer of 2 points will be the target
01545                 if( (VectorLengthSquared( vecStart2From )) < (VectorLengthSquared( vecStart2End )) )
01546                 {
01547                         VectorCopy( from, result );
01548                 }
01549                 else
01550                 {
01551                         VectorCopy( end, result );
01552                 }
01553                 return qfalse;
01554         }
01555 
01556         //Try other end
01557         VectorSubtract( from, end, vecEnd2From);
01558         VectorSubtract( start, end, vecEnd2Start);
01559 
01560         dot = DotProductNormalize( vecEnd2From, vecEnd2Start );
01561 
01562         if ( dot <= 0 )
01563         {//The perpendicular would be beyond or through the start point
01564                 VectorCopy( end, result );
01565                 return qfalse;
01566         }
01567 
01568         if ( dot == 1 )
01569         {//parallel, closer of 2 points will be the target
01570                 if( (VectorLengthSquared( vecEnd2From )) < (VectorLengthSquared( vecEnd2Start )))
01571                 {
01572                         VectorCopy( from, result );
01573                 }
01574                 else
01575                 {
01576                         VectorCopy( end, result );
01577                 }
01578                 return qfalse;
01579         }
01580 
01581         //                    /|
01582         //                c  / |
01583         //                  /  |a
01584         //      theta  /)__|    
01585         //                    b
01586         //cos(theta) = b / c
01587         //solve for b
01588         //b = cos(theta) * c
01589 
01590         //angle between vecs end2from and end2start, should be between 0 and 90
01591         theta = 90 * (1 - dot);//theta
01592         
01593         //Get length of side from End2Result using sine of theta
01594         distEnd2From = VectorLength( vecEnd2From );//c
01595         cos_theta = cos(DEG2RAD(theta));//cos(theta)
01596         distEnd2Result = cos_theta * distEnd2From;//b
01597 
01598         //Extrapolate to find result
01599         VectorNormalize( vecEnd2Start );
01600         VectorMA( end, distEnd2Result, vecEnd2Start, result );
01601         
01602         //perpendicular intersection is between the 2 endpoints
01603         return qtrue;
01604 }
01605 
01606 float G_PointDistFromLineSegment( const vec3_t start, const vec3_t end, const vec3_t from )
01607 {
01608         vec3_t  vecStart2From, vecStart2End, vecEnd2Start, vecEnd2From, intersection;
01609         float   distEnd2From, distStart2From, distEnd2Result, theta, cos_theta, dot;
01610 
01611         //Find the perpendicular vector to vec from start to end
01612         VectorSubtract( from, start, vecStart2From);
01613         VectorSubtract( end, start, vecStart2End);
01614         VectorSubtract( from, end, vecEnd2From);
01615         VectorSubtract( start, end, vecEnd2Start);
01616 
01617         dot = DotProductNormalize( vecStart2From, vecStart2End );
01618 
01619         distStart2From = Distance( start, from );
01620         distEnd2From = Distance( end, from );
01621 
01622         if ( dot <= 0 )
01623         {
01624                 //The perpendicular would be beyond or through the start point
01625                 return distStart2From;
01626         }
01627 
01628         if ( dot == 1 )
01629         {
01630                 //parallel, closer of 2 points will be the target
01631                 return ((distStart2From<distEnd2From)?distStart2From:distEnd2From);
01632         }
01633 
01634         //Try other end
01635 
01636         dot = DotProductNormalize( vecEnd2From, vecEnd2Start );
01637 
01638         if ( dot <= 0 )
01639         {//The perpendicular would be beyond or through the end point
01640                 return distEnd2From;
01641         }
01642 
01643         if ( dot == 1 )
01644         {//parallel, closer of 2 points will be the target
01645                 return ((distStart2From<distEnd2From)?distStart2From:distEnd2From);
01646         }
01647 
01648         //                    /|
01649         //                c  / |
01650         //                  /  |a
01651         //      theta  /)__|    
01652         //                    b
01653         //cos(theta) = b / c
01654         //solve for b
01655         //b = cos(theta) * c
01656 
01657         //angle between vecs end2from and end2start, should be between 0 and 90
01658         theta = 90 * (1 - dot);//theta
01659         
01660         //Get length of side from End2Result using sine of theta
01661         cos_theta = cos(DEG2RAD(theta));//cos(theta)
01662         distEnd2Result = cos_theta * distEnd2From;//b
01663 
01664         //Extrapolate to find result
01665         VectorNormalize( vecEnd2Start );
01666         VectorMA( end, distEnd2Result, vecEnd2Start, intersection );
01667         
01668         //perpendicular intersection is between the 2 endpoints, return dist to it from from
01669         return Distance( intersection, from );
01670 }