]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - mathlib.c
try to really fix vectorvectors to be 100% equivalent to makevectors(flippitch(vectoa...
[xonotic/darkplaces.git] / mathlib.c
index ed0a43c60d3869c735dad47f6495f50afa47928d..b4a1b6a0b1d847032cd783c05b4d5975fb6455fd 100644 (file)
--- a/mathlib.c
+++ b/mathlib.c
@@ -198,35 +198,61 @@ void PerpendicularVector( vec3_t dst, const vec3_t src )
 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
 {
-       float d;
-
-       right[0] = forward[2];
-       right[1] = -forward[0];
-       right[2] = forward[1];
-       // BUG!
-       //   assume forward = {sqrt(1/3), sqrt(1/3), -sqrt(1/3)}
-       //   then right will be {-sqrt(1/3), -sqrt(1/3), sqrt(1/3)}
-       //   PROBLEM?
-
-       d = DotProduct(forward, right);
-       VectorMA(right, -d, forward, right);
-       VectorNormalize(right);
-       CrossProduct(right, forward, up);
-       VectorNormalize(up); // CrossProduct in this case returns 'up thats length is not 1
+       // NOTE: this is consistent to AngleVectors applied to AnglesFromVectors
+       if (forward[0] == 0 && forward[1] == 0)
+       {
+               if(forward[2] > 0)
+               {
+                       VectorSet(right, 0, -1, 0);
+                       VectorSet(up, -1, 0, 0);
+               }
+               else
+               {
+                       VectorSet(right, 0, -1, 0);
+                       VectorSet(up, 1, 0, 0);
+               }
+       }
+       else
+       {
+               right[0] = forward[1];
+               right[1] = -forward[0];
+               right[2] = 0;
+               VectorNormalize(right);
+
+               up[0] = (-forward[2]*forward[0]);
+               up[1] = (-forward[2]*forward[1]);
+               up[2] = (forward[0]*forward[0] + forward[1]*forward[1]);
+               VectorNormalize(up);
+       }
 }
 
 void VectorVectorsDouble(const double *forward, double *right, double *up)
 {
-       double d;
-
-       right[0] = forward[2];
-       right[1] = -forward[0];
-       right[2] = forward[1];
-
-       d = DotProduct(forward, right);
-       VectorMA(right, -d, forward, right);
-       VectorNormalize(right);
-       CrossProduct(right, forward, up);
+       if (forward[0] == 0 && forward[1] == 0)
+       {
+               if(forward[2] > 0)
+               {
+                       VectorSet(right, 0, -1, 0);
+                       VectorSet(up, -1, 0, 0);
+               }
+               else
+               {
+                       VectorSet(right, 0, -1, 0);
+                       VectorSet(up, 1, 0, 0);
+               }
+       }
+       else
+       {
+               right[0] = forward[1];
+               right[1] = -forward[0];
+               right[2] = 0;
+               VectorNormalize(right);
+
+               up[0] = (-forward[2]*forward[0]);
+               up[1] = (-forward[2]*forward[1]);
+               up[2] = (forward[0]*forward[0] + forward[1]*forward[1]);
+               VectorNormalize(up);
+       }
 }
 
 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
@@ -544,9 +570,11 @@ void AnglesFromVectors (vec3_t angles, const vec3_t forward, const vec3_t up, qb
        {
                angles[YAW] = atan2(forward[1], forward[0]);
                angles[PITCH] = -atan2(forward[2], sqrt(forward[0]*forward[0] + forward[1]*forward[1]));
+               // note: we know that angles[PITCH] is in ]-pi/2..pi/2[ due to atan2(anything, positive)
                if (up)
                {
                        vec_t cp = cos(angles[PITCH]), sp = sin(angles[PITCH]);
+                       // note: we know cp > 0, due to the range angles[pitch] is in
                        vec_t cy = cos(angles[YAW]), sy = sin(angles[YAW]);
                        vec3_t tleft, tup;
                        tleft[0] = -sy;
@@ -556,9 +584,14 @@ void AnglesFromVectors (vec3_t angles, const vec3_t forward, const vec3_t up, qb
                        tup[1] = sp*sy;
                        tup[2] = cp;
                        angles[ROLL] = -atan2(DotProduct(up, tleft), DotProduct(up, tup));
+                       // for up == '0 0 1', this is
+                       // angles[ROLL] = -atan2(0, cp);
+                       // which is 0
                }
                else
                        angles[ROLL] = 0;
+
+               // so no up vector is equivalent to '1 0 0'!
        }
 
        // now convert radians to degrees, and make all values positive