mathlib.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "../common/common.h"
00027 
00028 #ifndef logf
00029 #define logf(x) ((float)log((double)(x)))
00030 #endif
00031 
00032 const vec2_t vec2_origin = { 0, 0 };
00033 const vec3_t vec3_origin = { 0, 0, 0 };
00034 const vec4_t vec4_origin = { 0, 0, 0, 0 };
00035 
00037 #define RT2 0.70710678118654752440084436210485
00038 
00053 const vec4_t dvecs[PATHFINDING_DIRECTIONS] = {
00054     { 1,  0,  0,  0},   /* E */
00055     {-1,  0,  0,  0},   /* W */
00056     { 0,  1,  0,  0},   /* N */
00057     { 0, -1,  0,  0},   /* S */
00058     { 1,  1,  0,  0},   /* NE */
00059     {-1, -1,  0,  0},   /* SW */
00060     {-1,  1,  0,  0},   /* NW */
00061     { 1, -1,  0,  0},   /* SE */
00062     { 0,  0,  1,  0},   /* CLIMB UP */
00063     { 0,  0, -1,  0},   /* CLIMB DOWN */
00064     { 0,  0,  0, -1},   /* STAND UP */
00065     { 0,  0,  0,  1},   /* STAND DOWN */
00066     { 0,  0,  0,  0},   /* UNDEFINED OPPOSITE OF FALL DOWN */
00067     { 0,  0, -1,  0},   /* FALL DOWN */
00068     { 0,  0,  0,  0},   /* UNDEFINED */
00069     { 0,  0,  0,  0},   /* UNDEFINED */
00070     { 1,  0,  1,  0},   /* UP E (Fliers only)*/
00071     {-1,  0,  1,  0},   /* UP W (Fliers only) */
00072     { 0,  1,  1,  0},   /* UP N (Fliers only) */
00073     { 0, -1,  1,  0},   /* UP S (Fliers only) */
00074     { 1,  1,  1,  0},   /* UP NE (Fliers only) */
00075     {-1, -1,  1,  0},   /* UP SW (Fliers only) */
00076     {-1,  1,  1,  0},   /* UP NW (Fliers only) */
00077     { 1, -1,  1,  0},   /* UP SE (Fliers only) */
00078     { 1,  0,  0,  0},   /* E (Fliers only)*/
00079     {-1,  0,  0,  0},   /* W (Fliers only) */
00080     { 0,  1,  0,  0},   /* N (Fliers only) */
00081     { 0, -1,  0,  0},   /* S (Fliers only) */
00082     { 1,  1,  0,  0},   /* NE (Fliers only) */
00083     {-1, -1,  0,  0},   /* SW (Fliers only) */
00084     {-1,  1,  0,  0},   /* NW (Fliers only) */
00085     { 1, -1,  0,  0},   /* SE (Fliers only) */
00086     { 1,  0, -1,  0},   /* DOWN E (Fliers only) */
00087     {-1,  0, -1,  0},   /* DOWN W (Fliers only) */
00088     { 0,  1, -1,  0},   /* DOWN N (Fliers only) */
00089     { 0, -1, -1,  0},   /* DOWN S (Fliers only) */
00090     { 1,  1, -1,  0},   /* DOWN NE (Fliers only) */
00091     {-1, -1, -1,  0},   /* DOWN SW (Fliers only) */
00092     {-1,  1, -1,  0},   /* DOWN NW (Fliers only) */
00093     { 1, -1, -1,  0},   /* DOWN SE (Fliers only) */
00094     };
00095 
00096 /*                                           0:E     1:W      2:N     3:S      4:NE        5:SW          6:NW         7:SE  */
00097 const float dvecsn[CORE_DIRECTIONS][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, {RT2, RT2}, {-RT2, -RT2}, {-RT2, RT2}, {RT2, -RT2} };
00099 /*                                     0:E 1: W    2:N    3:S     4:NE   5:SW    6:NW    7:SE  */
00100 const float directionAngles[CORE_DIRECTIONS] = { 0, 180.0f, 90.0f, 270.0f, 45.0f, 225.0f, 135.0f, 315.0f };
00101 
00102 const byte dvright[CORE_DIRECTIONS] = { 7, 6, 4, 5, 0, 1, 2, 3 };
00103 const byte dvleft[CORE_DIRECTIONS] = { 4, 5, 6, 7, 2, 3, 1, 0 };
00104 
00105 
00112 int AngleToDir (int angle)
00113 {
00114     static const int anglesToDV[8] = {0, 4, 2, 6, 1, 5, 3, 7};
00115 
00116     angle += 22;
00117     /* set angle between 0 <= angle < 360 */
00118     angle %= 360;
00119     /* next step is because the result of angle %= 360 when angle is negative depends of the compiler
00120      * (it can be between -360 < angle <= 0 or 0 <= angle < 360) */
00121     if (angle < 0)
00122         angle += 360;
00123 
00124     /* get an integer quotient */
00125     angle /= 45;
00126 
00127     if (angle >= 0 && angle < CORE_DIRECTIONS)
00128         return anglesToDV[angle];
00129 
00130     /* This is the default for unknown values. */
00131     Com_Printf("Error in AngleToDV: shouldn't have reached this line\n");
00132     return 0;
00133 }
00134 
00138 vec_t Q_rint (const vec_t in)
00139 {
00140     /* round x down to the nearest integer */
00141     return floor(in + 0.5);
00142 }
00143 
00144 
00154 float GetDistanceOnGlobe (const vec2_t pos1, const vec2_t pos2)
00155 {
00156     /* convert into rad */
00157     const float latitude1 = pos1[1] * torad;
00158     const float latitude2 = pos2[1] * torad;
00159     const float deltaLongitude = (pos1[0] - pos2[0]) * torad;
00160     float distance;
00161 
00162     distance = cos(latitude1) * cos(latitude2) * cos(deltaLongitude) + sin(latitude1) * sin(latitude2);
00163     distance = min(max(-1, distance), 1);
00164     distance = acos(distance) * todeg;
00165 
00166     return distance;
00167 }
00168 
00172 vec_t ColorNormalize (const vec3_t in, vec3_t out)
00173 {
00174     float max;
00175 
00176     /* find the brightest component */
00177     max = in[0];
00178     if (in[1] > max)
00179         max = in[1];
00180     if (in[2] > max)
00181         max = in[2];
00182 
00183     /* avoid FPE */
00184     if (max == 0.0) {
00185         VectorClear(out);
00186         return 0;
00187     }
00188 
00189     VectorScale(in, 1.0 / max, out);
00190 
00191     return max;
00192 }
00193 
00201 qboolean VectorNearer (const vec3_t v1, const vec3_t v2, const vec3_t comp)
00202 {
00203     vec3_t d1, d2;
00204 
00205     VectorSubtract(comp, v1, d1);
00206     VectorSubtract(comp, v2, d2);
00207 
00208     return VectorLength(d1) < VectorLength(d2);
00209 }
00210 
00219 vec_t VectorNormalize2 (const vec3_t v, vec3_t out)
00220 {
00221     float length;
00222 
00223     length = DotProduct(v, v);
00224     length = sqrt(length);      
00226     if (length) {
00227         const float ilength = 1.0 / length;
00228         out[0] = v[0] * ilength;
00229         out[1] = v[1] * ilength;
00230         out[2] = v[2] * ilength;
00231     }
00232 
00233     return length;
00234 }
00235 
00243 void VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
00244 {
00245     outVector[0] = veca[0] + scale * vecb[0];
00246     outVector[1] = veca[1] + scale * vecb[1];
00247     outVector[2] = veca[2] + scale * vecb[2];
00248 }
00249 
00250 void VectorClampMA (vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc)
00251 {
00252     int i;
00253 
00254     /* clamp veca to bounds */
00255     for (i = 0; i < 3; i++)
00256         if (veca[i] > 4094.0)
00257             veca[i] = 4094.0;
00258         else if (veca[i] < -4094.0)
00259             veca[i] = -4094.0;
00260 
00261     /* rescale to fit */
00262     for (i = 0; i < 3; i++) {
00263         const float test = veca[i] + scale * vecb[i];
00264         if (test < -4095.0f) {
00265             const float newScale = (-4094.0 - veca[i]) / vecb[i];
00266             if (fabs(newScale) < fabs(scale))
00267                 scale = newScale;
00268         } else if (test > 4095.0f) {
00269             const float newScale = (4094.0 - veca[i]) / vecb[i];
00270             if (fabs(newScale) < fabs(scale))
00271                 scale = newScale;
00272         }
00273     }
00274 
00275     /* use rescaled scale */
00276     VectorMA(veca, scale, vecb, vecc);
00277 }
00278 
00286 void MatrixMultiply (const vec3_t a[3], const vec3_t b[3], vec3_t c[3])
00287 {
00288     c[0][0] = a[0][0] * b[0][0] + a[1][0] * b[0][1] + a[2][0] * b[0][2];
00289     c[0][1] = a[0][1] * b[0][0] + a[1][1] * b[0][1] + a[2][1] * b[0][2];
00290     c[0][2] = a[0][2] * b[0][0] + a[1][2] * b[0][1] + a[2][2] * b[0][2];
00291 
00292     c[1][0] = a[0][0] * b[1][0] + a[1][0] * b[1][1] + a[2][0] * b[1][2];
00293     c[1][1] = a[0][1] * b[1][0] + a[1][1] * b[1][1] + a[2][1] * b[1][2];
00294     c[1][2] = a[0][2] * b[1][0] + a[1][2] * b[1][1] + a[2][2] * b[1][2];
00295 
00296     c[2][0] = a[0][0] * b[2][0] + a[1][0] * b[2][1] + a[2][0] * b[2][2];
00297     c[2][1] = a[0][1] * b[2][0] + a[1][1] * b[2][1] + a[2][1] * b[2][2];
00298     c[2][2] = a[0][2] * b[2][0] + a[1][2] * b[2][1] + a[2][2] * b[2][2];
00299 }
00300 
00307 void GLMatrixAssemble (const vec3_t origin, const vec3_t angles, float* matrix)
00308 {
00309     /* fill in edge values */
00310     matrix[3] = matrix[7] = matrix[11] = 0.0;
00311     matrix[15] = 1.0;
00312 
00313     /* add rotation */
00314     AngleVectors(angles, &matrix[0], &matrix[4], &matrix[8]);
00315     /* flip an axis */
00316     VectorInverse(&matrix[4]);
00317 
00318     /* add translation */
00319     matrix[12] = origin[0];
00320     matrix[13] = origin[1];
00321     matrix[14] = origin[2];
00322 }
00323 
00332 void GLMatrixMultiply (const float a[16], const float b[16], float c[16])
00333 {
00334     int i, j, k;
00335 
00336     for (j = 0; j < 4; j++) {
00337         k = j * 4;
00338         for (i = 0; i < 4; i++)
00339             c[i + k] = a[i] * b[k] + a[i + 4] * b[k + 1] + a[i + 8] * b[k + 2] + a[i + 12] * b[k + 3];
00340     }
00341 }
00342 
00350 void GLVectorTransform (const float m[16], const vec4_t in, vec4_t out)
00351 {
00352     int i;
00353 
00354     for (i = 0; i < 4; i++)
00355         out[i] = m[i] * in[0] + m[i + 4] * in[1] + m[i + 8] * in[2] + m[i + 12] * in[3];
00356 }
00357 
00367 void VectorRotate (vec3_t m[3], const vec3_t va, vec3_t vb)
00368 {
00369     vb[0] = m[0][0] * va[0] + m[1][0] * va[1] + m[2][0] * va[2];
00370     vb[1] = m[0][1] * va[0] + m[1][1] * va[1] + m[2][1] * va[2];
00371     vb[2] = m[0][2] * va[0] + m[1][2] * va[1] + m[2][2] * va[2];
00372 }
00373 
00385 int VectorCompareEps (const vec3_t v1, const vec3_t v2, float epsilon)
00386 {
00387     vec3_t d;
00388 
00389     VectorSubtract(v1, v2, d);
00390     d[0] = fabs(d[0]);
00391     d[1] = fabs(d[1]);
00392     d[2] = fabs(d[2]);
00393 
00394     if (d[0] > epsilon || d[1] > epsilon || d[2] > epsilon)
00395         return 0;
00396 
00397     return 1;
00398 }
00399 
00406 vec_t VectorLength (const vec3_t v)
00407 {
00408     return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
00409 }
00410 
00419 void VectorMix (const vec3_t v1, const vec3_t v2, float mix, vec3_t out)
00420 {
00421     int i;
00422 
00423     for (i = 0; i < 3; i++)
00424         out[i] = v1[i] * (1.0 - mix) + v2[i] * mix;
00425 }
00426 
00431 void VectorInverse (vec3_t v)
00432 {
00433     v[0] = -v[0];
00434     v[1] = -v[1];
00435     v[2] = -v[2];
00436 }
00437 
00444 void VectorMidpoint (const vec3_t point1, const vec3_t point2, vec3_t midpoint)
00445 {
00446     VectorAdd(point1, point2, midpoint);
00447     VectorScale(midpoint, 0.5f, midpoint);
00448 }
00449 
00455 float VectorAngleBetween (const vec3_t vec1, const vec3_t vec2)
00456 {
00457     const float dot = DotProduct(vec1, vec2);
00458     const float angle = acos(dot);
00459     return angle;
00460 }
00461 
00462 
00463 int Q_log2 (int val)
00464 {
00465     int answer = 0;
00466 
00467     while (val >>= 1)
00468         answer++;
00469     return answer;
00470 }
00471 
00477 float frand (void)
00478 {
00479     return (rand() & 32767) * (1.0 / 32767);
00480 }
00481 
00482 
00488 float crand (void)
00489 {
00490     return (rand() & 32767) * (2.0 / 32767) - 1;
00491 }
00492 
00500 void gaussrand (float *gauss1, float *gauss2)
00501 {
00502     float x1, x2, w, tmp;
00503 
00504     do {
00505         x1 = crand();
00506         x2 = crand();
00507         w = x1 * x1 + x2 * x2;
00508     } while (w >= 1.0);
00509 
00510     tmp = -2 * logf(w);
00511     w = sqrt(tmp / w);
00512     *gauss1 = x1 * w;
00513     *gauss2 = x2 * w;
00514 }
00515 
00523 void VectorCreateRotationMatrix (const vec3_t angles, vec3_t matrix[3])
00524 {
00525     AngleVectors(angles, matrix[0], matrix[1], matrix[2]);
00526     VectorInverse(matrix[1]);
00527 }
00528 
00534 void VectorRotatePoint (vec3_t point, vec3_t matrix[3])
00535 {
00536     vec3_t tvec;
00537 
00538     VectorCopy(point, tvec);
00539 
00540     point[0] = DotProduct(matrix[0], tvec);
00541     point[1] = DotProduct(matrix[1], tvec);
00542     point[2] = DotProduct(matrix[2], tvec);
00543 }
00544 
00562 void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
00563 {
00564     const float anglePitch = angles[PITCH] * torad;
00565     const float sp = sin(anglePitch);
00566     const float cp = cos(anglePitch);
00567     const float angleYaw = angles[YAW] * torad;
00568     const float sy = sin(angleYaw);
00569     const float cy = cos(angleYaw);
00570     const float angleRoll = angles[ROLL] * torad;
00571     const float sr = sin(angleRoll);
00572     const float cr = cos(angleRoll);
00573 
00574     if (forward) {
00575         forward[0] = cp * cy;
00576         forward[1] = cp * sy;
00577         forward[2] = -sp;
00578     }
00579     if (right) {
00580         right[0] = (-1 * sr * sp * cy + -1 * cr * -sy);
00581         right[1] = (-1 * sr * sp * sy + -1 * cr * cy);
00582         right[2] = -1 * sr * cp;
00583     }
00584     if (up) {
00585         up[0] = (cr * sp * cy + -sr * -sy);
00586         up[1] = (cr * sp * sy + -sr * cy);
00587         up[2] = cr * cp;
00588     }
00589 }
00590 
00597 qboolean FrustumVis (const vec3_t origin, int dir, const vec3_t point)
00598 {
00599     /* view frustum check */
00600     vec3_t delta;
00601     byte dv;
00602 
00603     delta[0] = point[0] - origin[0];
00604     delta[1] = point[1] - origin[1];
00605     delta[2] = 0;
00606     VectorNormalize(delta);
00607     dv = dir & (DIRECTIONS - 1);
00608 
00609     /* test 120 frustum (cos 60 = 0.5) */
00610     if ((delta[0] * dvecsn[dv][0] + delta[1] * dvecsn[dv][1]) < 0.5)
00611         return qfalse;
00612     else
00613         return qtrue;
00614 }
00615 
00623 static inline void ProjectPointOnPlane (vec3_t dst, const vec3_t point, const vec3_t normal)
00624 {
00625     float distance; 
00627 #if 0
00628     vec3_t n;
00629     float inv_denom;
00630     /* I added a sqrt there, otherwise this function does not work for unnormalized vector (13052007 Kracken) */
00631     /* old line was inv_denom = 1.0F / DotProduct(normal, normal); */
00632     inv_denom = 1.0F / sqrt(DotProduct(normal, normal));
00633 #endif
00634 
00635     distance = DotProduct(normal, point);
00636 #if 0
00637     n[0] = normal[0] * inv_denom;
00638     n[1] = normal[1] * inv_denom;
00639     n[2] = normal[2] * inv_denom;
00640 #endif
00641 
00642     dst[0] = point[0] - distance * normal[0];
00643     dst[1] = point[1] - distance * normal[1];
00644     dst[2] = point[2] - distance * normal[2];
00645 }
00646 
00653 vec_t VectorNormalize (vec3_t v)
00654 {
00655     float length;
00660     if ((length = DotProduct(v, v))) { 
00661         const float ilength = 1.0 / (length = sqrtf(length));  
00662         v[0] *= ilength;
00663         v[1] *= ilength;
00664         v[2] *= ilength;
00665     }
00666 
00667     return length;
00668 }
00669 
00680 void PerpendicularVector (vec3_t dst, const vec3_t src)
00681 {
00682     int pos;
00683     int i;
00684     float minelem = 1.0F;
00685     vec3_t tempvec;
00686 
00687     /* find the smallest magnitude axially aligned vector */
00688     for (pos = 0, i = 0; i < 3; i++) {
00689         if (fabs(src[i]) < minelem) {
00690             pos = i;
00691             minelem = fabs(src[i]);
00692         }
00693     }
00694     tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
00695     tempvec[pos] = 1.0F;
00696 
00697     /* project the point onto the plane defined by src */
00698     ProjectPointOnPlane(dst, tempvec, src);
00699 
00700     /* normalize the result */
00701     VectorNormalize(dst);
00702 }
00703 
00719 void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross)
00720 {
00721     cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
00722     cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
00723     cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
00724 }
00725 
00726 static inline void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
00727 {
00728     out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
00729     out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
00730     out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
00731     out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
00732     out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
00733     out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
00734     out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
00735     out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
00736     out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
00737 }
00738 
00748 void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees)
00749 {
00750     float m[3][3];
00751     float im[3][3];
00752     float zrot[3][3];
00753     float tmpmat[3][3];
00754     float rot[3][3];
00755     int i;
00756     vec3_t vr, vup, vf;
00757 
00758     vf[0] = dir[0];
00759     vf[1] = dir[1];
00760     vf[2] = dir[2];
00761 
00762     PerpendicularVector(vr, dir);
00763     CrossProduct(vr, vf, vup);
00764 
00765     m[0][0] = vr[0];
00766     m[1][0] = vr[1];
00767     m[2][0] = vr[2];
00768 
00769     m[0][1] = vup[0];
00770     m[1][1] = vup[1];
00771     m[2][1] = vup[2];
00772 
00773     m[0][2] = vf[0];
00774     m[1][2] = vf[1];
00775     m[2][2] = vf[2];
00776 
00777     memcpy(im, m, sizeof(im));
00778 
00779     im[0][1] = m[1][0];
00780     im[0][2] = m[2][0];
00781     im[1][0] = m[0][1];
00782     im[1][2] = m[2][1];
00783     im[2][0] = m[0][2];
00784     im[2][1] = m[1][2];
00785 
00786     memset(zrot, 0, sizeof(zrot));
00787     zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
00788 
00789     zrot[0][0] = cos(degrees * torad);
00790     zrot[0][1] = sin(degrees * torad);
00791     zrot[1][0] = -sin(degrees * torad);
00792     zrot[1][1] = cos(degrees * torad);
00793 
00794     R_ConcatRotations(m, zrot, tmpmat);
00795     R_ConcatRotations(tmpmat, im, rot);
00796 
00797     for (i = 0; i < 3; i++) {
00798         dst[i] = DotProduct(rot[i], point);
00799     }
00800 }
00801 
00806 void Print3Vector (const vec3_t v)
00807 {
00808     Com_Printf("(%f, %f, %f)\n", v[0], v[1], v[2]);
00809 }
00810 
00815 void Print2Vector (const vec2_t v)
00816 {
00817     Com_Printf("(%f, %f)\n", v[0], v[1]);
00818 }
00819 
00827 void PolarToVec (const vec2_t a, vec3_t v)
00828 {
00829     const float p = a[0] * torad;   /* long */
00830     const float t = a[1] * torad;   /* lat */
00831     /* v[0] = z, v[1] = x, v[2] = y - wtf? */
00832     VectorSet(v, cos(p) * cos(t), sin(p) * cos(t), sin(t));
00833 }
00834 
00839 void VecToPolar (const vec3_t v, vec2_t a)
00840 {
00841     a[0] = todeg * atan2(v[1], v[0]);   /* long */
00842     a[1] = 90 - todeg * acos(v[2]); /* lat */
00843 }
00844 
00851 void VecToAngles (const vec3_t value1, vec3_t angles)
00852 {
00853     float yaw, pitch;
00854 
00855     if (value1[1] == 0 && value1[0] == 0) {
00856         yaw = 0;
00857         if (value1[2] > 0)
00858             pitch = 90;
00859         else
00860             pitch = 270;
00861     } else {
00862         const float forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
00863         if (value1[0])
00864             yaw = (int) (atan2(value1[1], value1[0]) * todeg);
00865         else if (value1[1] > 0)
00866             yaw = 90;
00867         else
00868             yaw = -90;
00869         if (yaw < 0)
00870             yaw += 360;
00871 
00872         pitch = (int) (atan2(value1[2], forward) * todeg);
00873         if (pitch < 0)
00874             pitch += 360;
00875     }
00876 
00877     /* up and down */
00878     angles[PITCH] = -pitch;
00879     /* left and right */
00880     angles[YAW] = yaw;
00881     /* tilt left and right */
00882     angles[ROLL] = 0;
00883 }
00884 
00885 
00889 qboolean Q_IsPowerOfTwo (int i)
00890 {
00891     return (i > 0 && !(i & (i - 1)));
00892 }
00893 
00898 float LerpAngle (float a2, float a1, float frac)
00899 {
00900     if (a1 - a2 > 180)
00901         a1 -= 360;
00902     if (a1 - a2 < -180)
00903         a1 += 360;
00904     return a2 + frac * (a1 - a2);
00905 }
00906 
00912 float AngleNormalize360 (float angle)
00913 {
00914     return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535);
00915 }
00916 
00921 float AngleNormalize180 (float angle)
00922 {
00923     angle = AngleNormalize360(angle);
00924     if (angle > 180.0)
00925         angle -= 360.0;
00926     return angle;
00927 }
00928 
00935 void VectorCenterFromMinsMaxs (const vec3_t mins, const vec3_t maxs, vec3_t center)
00936 {
00937     VectorAdd(mins, maxs, center);
00938     VectorScale(center, 0.5, center);
00939 }
00940 
00945 void ClearBounds (vec3_t mins, vec3_t maxs)
00946 {
00947     mins[0] = mins[1] = mins[2] = 99999;
00948     maxs[0] = maxs[1] = maxs[2] = -99999;
00949 }
00950 
00955 void AddPointToBounds (const vec3_t v, vec3_t mins, vec3_t maxs)
00956 {
00957     int i;
00958     vec_t val;
00959 
00960     for (i = 0; i < 3; i++) {
00961         val = v[i];
00962         if (val < mins[i])
00963             mins[i] = val;
00964         if (val > maxs[i])
00965             maxs[i] = val;
00966     }
00967 }
00968 
00973 void TangentVectors (const vec3_t normal, const vec3_t sdir, const vec3_t tdir, vec4_t tangent, vec3_t binormal)
00974 {
00975     vec3_t s, t;
00976 
00977     /* normalize the directional vectors */
00978     VectorCopy(sdir, s);
00979     VectorNormalize(s);
00980 
00981     VectorCopy(tdir, t);
00982     VectorNormalize(t);
00983 
00984     /* project the directional vector onto the plane */
00985     VectorMA(s, -DotProduct(s, normal), normal, tangent);
00986     VectorNormalize(tangent);
00987 
00988     /* resolve sidedness, encode as fourth tangent component */
00989     CrossProduct(normal, tangent, binormal);
00990 
00991     if (DotProduct(t, binormal) < 0.0)
00992         tangent[3] = -1.0;
00993     else
00994         tangent[3] = 1.0;
00995 
00996     VectorScale(binormal, tangent[3], binormal);
00997 }
00998 
01004 void Orthogonalize (vec3_t v1, const vec3_t v2)
01005 {
01006     vec3_t tmp;
01007     VectorMul(DotProduct(v1, v2), v2, tmp);
01008     VectorSubtract(v1, tmp, v1);
01009     VectorNormalize(v1);
01010 }
01011 
01017 void MatrixTranspose (const vec3_t m[3], vec3_t t[3])
01018 {
01019     int i, j;
01020 
01021     for (i = 0; i < 3; i++) {
01022         for(j = 0; j < 3; j++) {
01023             t[i][j] = m[j][i];
01024         }
01025     }
01026 }

Generated by  doxygen 1.6.2