X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=mathlib.c;h=60cc04b0d58ed6393d061ccbbb6dcfff4dd68538;hb=769127c03a39beebd771ab3b6e662327cd167548;hp=eaa1a765d8e05bc5c65328a808591ad5053941e1;hpb=da29a8beeb35293e2fd38b51883c91b5cf4cf4ad;p=xonotic%2Fdarkplaces.git diff --git a/mathlib.c b/mathlib.c index eaa1a765..60cc04b0 100644 --- a/mathlib.c +++ b/mathlib.c @@ -19,9 +19,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // mathlib.c -- math primitives -#include #include "quakedef.h" +#include + vec3_t vec3_origin = {0,0,0}; float ixtable[4096]; @@ -197,30 +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]; - - 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 ) @@ -517,6 +549,89 @@ void AngleVectorsFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t u } } +// 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]) { @@ -645,7 +760,7 @@ void Matrix4x4_Print(const matrix4x4_t *in) , 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); @@ -679,3 +794,12 @@ void BoxFromPoints(vec3_t mins, vec3_t maxs, int numpoints, vec_t *point3f) } } +// 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; +} +