*/
// mathlib.c -- math primitives
-#include <math.h>
#include "quakedef.h"
+#include <math.h>
+
vec3_t vec3_origin = {0,0,0};
float ixtable[4096];
// 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];
-
- d = DotProduct(forward, right);
- VectorMA(right, -d, forward, right);
- VectorNormalize(right);
- CrossProduct(right, forward, up);
+ // 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 )
}
}
+// LordHavoc: calculates pitch/yaw/roll angles from forward and up vectors
+void AnglesFromVectors (vec3_t angles, const vec3_t forward, const vec3_t up, qboolean flippitch)
+{
+ if (forward[0] == 0 && forward[1] == 0)
+ {
+ if(forward[2] > 0)
+ {
+ angles[PITCH] = -M_PI * 0.5;
+ angles[YAW] = up ? atan2(-up[1], -up[0]) : 0;
+ }
+ else
+ {
+ angles[PITCH] = M_PI * 0.5;
+ angles[YAW] = up ? atan2(up[1], up[0]) : 0;
+ }
+ angles[ROLL] = 0;
+ }
+ else
+ {
+ 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;
+ tleft[1] = cy;
+ tleft[2] = 0;
+ tup[0] = sp*cy;
+ 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
+ VectorScale(angles, 180.0 / M_PI, angles);
+ if (flippitch)
+ angles[PITCH] *= -1;
+ if (angles[PITCH] < 0) angles[PITCH] += 360;
+ if (angles[YAW] < 0) angles[YAW] += 360;
+ if (angles[ROLL] < 0) angles[ROLL] += 360;
+
+#if 0
+{
+ // debugging code
+ vec3_t tforward, tleft, tup, nforward, nup;
+ VectorCopy(forward, nforward);
+ VectorNormalize(nforward);
+ if (up)
+ {
+ VectorCopy(up, nup);
+ VectorNormalize(nup);
+ AngleVectors(angles, tforward, tleft, tup);
+ if (VectorDistance(tforward, nforward) > 0.01 || VectorDistance(tup, nup) > 0.01)
+ {
+ Con_Printf("vectoangles('%f %f %f', '%f %f %f') = %f %f %f\n", nforward[0], nforward[1], nforward[2], nup[0], nup[1], nup[2], angles[0], angles[1], angles[2]);
+ Con_Printf("^3But that is '%f %f %f', '%f %f %f'\n", tforward[0], tforward[1], tforward[2], tup[0], tup[1], tup[2]);
+ }
+ }
+ else
+ {
+ AngleVectors(angles, tforward, tleft, tup);
+ if (VectorDistance(tforward, nforward) > 0.01)
+ {
+ Con_Printf("vectoangles('%f %f %f') = %f %f %f\n", nforward[0], nforward[1], nforward[2], angles[0], angles[1], angles[2]);
+ Con_Printf("^3But that is '%f %f %f'\n", tforward[0], tforward[1], tforward[2]);
+ }
+ }
+}
+#endif
+}
+
#if 0
void AngleMatrix (const vec3_t angles, const vec3_t translate, vec_t matrix[][4])
{
, in->m[3][0], in->m[3][1], in->m[3][2], in->m[3][3]);
}
-int Math_atov(const char *s, vec3_t out)
+int Math_atov(const char *s, prvm_vec3_t out)
{
int i;
VectorClear(out);
}
}
+// LordHavoc: this has to be done right or you get severe precision breakdown
+int LoopingFrameNumberFromDouble(double t, int loopframes)
+{
+ if (loopframes)
+ return (int)(t - floor(t/loopframes)*loopframes);
+ else
+ return (int)t;
+}
+