diff --git a/src/m_fixed.c b/src/m_fixed.c index 70b7623da..ded294b0a 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -276,6 +276,15 @@ vector3_t *FV3_Load(vector3_t *vec, fixed_t x, fixed_t y, fixed_t z) return vec; } +vector4_t *FV4_Load(vector4_t *vec, fixed_t x, fixed_t y, fixed_t z, fixed_t a) +{ + vec->x = x; + vec->y = y; + vec->z = z; + vec->a = a; + return vec; +} + vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z) { *x = vec->x; @@ -284,11 +293,25 @@ vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z) return vec; } +vector4_t *FV4_UnLoad(vector4_t *vec, fixed_t *x, fixed_t *y, fixed_t *z, fixed_t *a) +{ + *x = vec->x; + *y = vec->y; + *z = vec->z; + *a = vec->a; + return vec; +} + vector3_t *FV3_Copy(vector3_t *a_o, const vector3_t *a_i) { return M_Memcpy(a_o, a_i, sizeof(vector3_t)); } +vector4_t *FV4_Copy(vector4_t *a_o, const vector4_t *a_i) +{ + return M_Memcpy(a_o, a_i, sizeof(vector4_t)); +} + vector3_t *FV3_AddEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o) { a_o->x = a_i->x + a_c->x; @@ -297,11 +320,25 @@ vector3_t *FV3_AddEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o) return a_o; } +vector4_t *FV4_AddEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o) +{ + a_o->x = a_i->x + a_c->x; + a_o->y = a_i->y + a_c->y; + a_o->z = a_i->z + a_c->z; + a_o->a = a_i->a + a_c->a; + return a_o; +} + vector3_t *FV3_Add(vector3_t *a_i, const vector3_t *a_c) { return FV3_AddEx(a_i, a_c, a_i); } +vector4_t *FV4_Add(vector4_t *a_i, const vector4_t *a_c) +{ + return FV4_AddEx(a_i, a_c, a_i); +} + vector3_t *FV3_SubEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o) { a_o->x = a_i->x - a_c->x; @@ -310,11 +347,25 @@ vector3_t *FV3_SubEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o) return a_o; } +vector4_t *FV4_SubEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o) +{ + a_o->x = a_i->x - a_c->x; + a_o->y = a_i->y - a_c->y; + a_o->z = a_i->z - a_c->z; + a_o->a = a_i->a - a_c->a; + return a_o; +} + vector3_t *FV3_Sub(vector3_t *a_i, const vector3_t *a_c) { return FV3_SubEx(a_i, a_c, a_i); } +vector4_t *FV4_Sub(vector4_t *a_i, const vector4_t *a_c) +{ + return FV4_SubEx(a_i, a_c, a_i); +} + vector3_t *FV3_MulEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o) { a_o->x = FixedMul(a_i->x, a_c); @@ -323,11 +374,25 @@ vector3_t *FV3_MulEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o) return a_o; } +vector4_t *FV4_MulEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o) +{ + a_o->x = FixedMul(a_i->x, a_c); + a_o->y = FixedMul(a_i->y, a_c); + a_o->z = FixedMul(a_i->z, a_c); + a_o->a = FixedMul(a_i->a, a_c); + return a_o; +} + vector3_t *FV3_Mul(vector3_t *a_i, fixed_t a_c) { return FV3_MulEx(a_i, a_c, a_i); } +vector4_t *FV4_Mul(vector4_t *a_i, fixed_t a_c) +{ + return FV4_MulEx(a_i, a_c, a_i); +} + vector3_t *FV3_DivideEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o) { a_o->x = FixedDiv(a_i->x, a_c); @@ -336,11 +401,25 @@ vector3_t *FV3_DivideEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o) return a_o; } +vector4_t *FV4_DivideEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o) +{ + a_o->x = FixedDiv(a_i->x, a_c); + a_o->y = FixedDiv(a_i->y, a_c); + a_o->z = FixedDiv(a_i->z, a_c); + a_o->a = FixedDiv(a_i->a, a_c); + return a_o; +} + vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c) { return FV3_DivideEx(a_i, a_c, a_i); } +vector4_t *FV4_Divide(vector4_t *a_i, fixed_t a_c) +{ + return FV4_DivideEx(a_i, a_c, a_i); +} + // Vector Complex Math vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o) { @@ -353,6 +432,19 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a return a_o; } +vector4_t *FV4_Midpoint(const vector4_t *a_1, const vector4_t *a_2, vector4_t *a_o) +{ + a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT); + a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT); + a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT); + a_o->a = FixedDiv(a_2->a - a_1->a, 2 * FRACUNIT); + a_o->x = a_1->x + a_o->x; + a_o->y = a_1->y + a_o->y; + a_o->z = a_1->z + a_o->z; + a_o->a = a_1->z + a_o->a; + return a_o; +} + fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2) { fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x); @@ -361,6 +453,15 @@ fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2) return FixedSqrt(xs + ys + zs); } +fixed_t FV4_Distance(const vector4_t *p1, const vector4_t *p2) +{ + fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x); + fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y); + fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z); + fixed_t za = FixedMul(p2->a - p1->a, p2->a - p1->a); + return FixedSqrt(xs + ys + zs + za); +} + fixed_t FV3_Magnitude(const vector3_t *a_normal) { fixed_t xs = FixedMul(a_normal->x, a_normal->x); @@ -369,6 +470,15 @@ fixed_t FV3_Magnitude(const vector3_t *a_normal) return FixedSqrt(xs + ys + zs); } +fixed_t FV4_Magnitude(const vector4_t *a_normal) +{ + fixed_t xs = FixedMul(a_normal->x, a_normal->x); + fixed_t ys = FixedMul(a_normal->y, a_normal->y); + fixed_t zs = FixedMul(a_normal->z, a_normal->z); + fixed_t as = FixedMul(a_normal->a, a_normal->a); + return FixedSqrt(xs + ys + zs + as); +} + // Also returns the magnitude fixed_t FV3_NormalizeEx(const vector3_t *a_normal, vector3_t *a_o) { @@ -379,11 +489,26 @@ fixed_t FV3_NormalizeEx(const vector3_t *a_normal, vector3_t *a_o) return magnitude; } +fixed_t FV4_NormalizeEx(const vector4_t *a_normal, vector4_t *a_o) +{ + fixed_t magnitude = FV4_Magnitude(a_normal); + a_o->x = FixedDiv(a_normal->x, magnitude); + a_o->y = FixedDiv(a_normal->y, magnitude); + a_o->z = FixedDiv(a_normal->z, magnitude); + a_o->a = FixedDiv(a_normal->a, magnitude); + return magnitude; +} + fixed_t FV3_Normalize(vector3_t *a_normal) { return FV3_NormalizeEx(a_normal, a_normal); } +fixed_t FV4_Normalize(vector4_t *a_normal) +{ + return FV4_NormalizeEx(a_normal, a_normal); +} + vector3_t *FV3_NegateEx(const vector3_t *a_1, vector3_t *a_o) { a_o->x = -a_1->x; @@ -392,11 +517,25 @@ vector3_t *FV3_NegateEx(const vector3_t *a_1, vector3_t *a_o) return a_o; } +vector4_t *FV4_NegateEx(const vector4_t *a_1, vector4_t *a_o) +{ + a_o->x = -a_1->x; + a_o->y = -a_1->y; + a_o->z = -a_1->z; + a_o->a = -a_1->a; + return a_o; +} + vector3_t *FV3_Negate(vector3_t *a_1) { return FV3_NegateEx(a_1, a_1); } +vector4_t *FV4_Negate(vector4_t *a_1) +{ + return FV4_NegateEx(a_1, a_1); +} + boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2) { fixed_t Epsilon = FRACUNIT / FRACUNIT; @@ -411,11 +550,31 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2) return false; } +boolean FV4_Equal(const vector4_t *a_1, const vector4_t *a_2) +{ + fixed_t Epsilon = FRACUNIT / FRACUNIT; + + if ((abs(a_2->x - a_1->x) > Epsilon) || + (abs(a_2->y - a_1->y) > Epsilon) || + (abs(a_2->z - a_1->z) > Epsilon) || + (abs(a_2->a - a_1->a) > Epsilon)) + { + return true; + } + + return false; +} + fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2) { return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z)); } +fixed_t FV4_Dot(const vector4_t *a_1, const vector4_t *a_2) +{ + return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z) + FixedMul(a_1->a, a_2->a)); +} + vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o) { a_o->x = FixedMul(a_1->y, a_2->z) - FixedMul(a_1->z, a_2->y); @@ -432,7 +591,7 @@ vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o) // vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out) { - // Determine t (the length of the vector from �Line[0]� to �p�) + // Determine t (the length of the vector from "Line[0]" to "p") vector3_t c, V; fixed_t t, d = 0; FV3_SubEx(p, &Line[0], &c); @@ -442,7 +601,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec d = FV3_Distance(&Line[0], &Line[1]); t = FV3_Dot(&V, &c); - // Check to see if �t� is beyond the extents of the line segment + // Check to see if "t" is beyond the extents of the line segment if (t < 0) { return FV3_Copy(out, &Line[0]); @@ -452,7 +611,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec return FV3_Copy(out, &Line[1]); } - // Return the point between �Line[0]� and �Line[1]� + // Return the point between "Line[0]" and "Line[1]" FV3_Mul(&V, t); return FV3_AddEx(&Line[0], &V, out); @@ -810,7 +969,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi // // Multiplies a vector by the specified matrix // -void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out) +const vector3_t *FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out) { #define M(row,col) matrix->m[col * 4 + row] out->x = FixedMul(vec->x, M(0, 0)) @@ -828,6 +987,34 @@ void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t * + FixedMul(vec->z, M(2, 2)) + M(2, 3); #undef M + return out; +} + +const vector4_t *FM_MultMatrixVec4(const matrix_t *matrix, const vector4_t *vec, vector4_t *out) +{ +#define M(row,col) matrix->m[col * 4 + row] + out->x = FixedMul(vec->x, M(0, 0)) + + FixedMul(vec->y, M(0, 1)) + + FixedMul(vec->z, M(0, 2)) + + FixedMul(vec->a, M(0, 3)); + + out->y = FixedMul(vec->x, M(1, 0)) + + FixedMul(vec->y, M(1, 1)) + + FixedMul(vec->z, M(1, 2)) + + FixedMul(vec->a, M(1, 3)); + + out->z = FixedMul(vec->x, M(2, 0)) + + FixedMul(vec->y, M(2, 1)) + + FixedMul(vec->z, M(2, 2)) + + FixedMul(vec->a, M(2, 3)); + + + out->a = FixedMul(vec->x, M(3, 0)) + + FixedMul(vec->y, M(3, 1)) + + FixedMul(vec->z, M(3, 2)) + + FixedMul(vec->a, M(3, 3)); +#undef M + return out; } // diff --git a/src/m_fixed.h b/src/m_fixed.h index fe5efc551..73e629f44 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -395,6 +395,32 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line); boolean FV3_PointInsideBox(const vector3_t *point, const vector3_t *box); +typedef struct +{ + fixed_t x, y, z, a; +} vector4_t; + +vector4_t *FV4_Load(vector4_t *vec, fixed_t x, fixed_t y, fixed_t z, fixed_t a); +vector4_t *FV4_UnLoad(vector4_t *vec, fixed_t *x, fixed_t *y, fixed_t *z, fixed_t *a); +vector4_t *FV4_Copy(vector4_t *a_o, const vector4_t *a_i); +vector4_t *FV4_AddEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o); +vector4_t *FV4_Add(vector4_t *a_i, const vector4_t *a_c); +vector4_t *FV4_SubEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o); +vector4_t *FV4_Sub(vector4_t *a_i, const vector4_t *a_c); +vector4_t *FV4_MulEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o); +vector4_t *FV4_Mul(vector4_t *a_i, fixed_t a_c); +vector4_t *FV4_DivideEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o); +vector4_t *FV4_Divide(vector4_t *a_i, fixed_t a_c); +vector4_t *FV4_Midpoint(const vector4_t *a_1, const vector4_t *a_2, vector4_t *a_o); +fixed_t FV4_Distance(const vector4_t *p1, const vector4_t *p2); +fixed_t FV4_Magnitude(const vector4_t *a_normal); +fixed_t FV4_NormalizeEx(const vector4_t *a_normal, vector4_t *a_o); +fixed_t FV4_Normalize(vector4_t *a_normal); +vector4_t *FV4_NegateEx(const vector4_t *a_1, vector4_t *a_o); +vector4_t *FV4_Negate(vector4_t *a_1); +boolean FV4_Equal(const vector4_t *a_1, const vector4_t *a_2); +fixed_t FV4_Dot(const vector4_t *a_1, const vector4_t *a_2); + typedef struct { fixed_t m[16]; @@ -402,7 +428,8 @@ typedef struct void FM_LoadIdentity(matrix_t* matrix); void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fixed_t anglex, fixed_t angley, fixed_t anglez, fixed_t upx, fixed_t upy, fixed_t upz, fixed_t radius); -void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out); +const vector3_t *FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out); +const vector4_t *FM_MultMatrixVec4(const matrix_t *matrix, const vector4_t *vec, vector4_t *out); void FM_MultMatrix(matrix_t *dest, const matrix_t *multme); void FM_Translate(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z); void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z); diff --git a/src/m_misc.c b/src/m_misc.c index 6c346e5a1..bb5f25687 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2164,63 +2164,6 @@ const char *GetRevisionString(void) return rev; } -// Vector/matrix math -TVector *VectorMatrixMultiply(TVector v, TMatrix m) -{ - static TVector ret; - - ret[0] = FixedMul(v[0],m[0][0]) + FixedMul(v[1],m[1][0]) + FixedMul(v[2],m[2][0]) + FixedMul(v[3],m[3][0]); - ret[1] = FixedMul(v[0],m[0][1]) + FixedMul(v[1],m[1][1]) + FixedMul(v[2],m[2][1]) + FixedMul(v[3],m[3][1]); - ret[2] = FixedMul(v[0],m[0][2]) + FixedMul(v[1],m[1][2]) + FixedMul(v[2],m[2][2]) + FixedMul(v[3],m[3][2]); - ret[3] = FixedMul(v[0],m[0][3]) + FixedMul(v[1],m[1][3]) + FixedMul(v[2],m[2][3]) + FixedMul(v[3],m[3][3]); - - return &ret; -} - -TMatrix *RotateXMatrix(angle_t rad) -{ - static TMatrix ret; - const angle_t fa = rad>>ANGLETOFINESHIFT; - const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa); - - ret[0][0] = FRACUNIT; ret[0][1] = 0; ret[0][2] = 0; ret[0][3] = 0; - ret[1][0] = 0; ret[1][1] = cosrad; ret[1][2] = sinrad; ret[1][3] = 0; - ret[2][0] = 0; ret[2][1] = -sinrad; ret[2][2] = cosrad; ret[2][3] = 0; - ret[3][0] = 0; ret[3][1] = 0; ret[3][2] = 0; ret[3][3] = FRACUNIT; - - return &ret; -} - -#if 0 -TMatrix *RotateYMatrix(angle_t rad) -{ - static TMatrix ret; - const angle_t fa = rad>>ANGLETOFINESHIFT; - const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa); - - ret[0][0] = cosrad; ret[0][1] = 0; ret[0][2] = -sinrad; ret[0][3] = 0; - ret[1][0] = 0; ret[1][1] = FRACUNIT; ret[1][2] = 0; ret[1][3] = 0; - ret[2][0] = sinrad; ret[2][1] = 0; ret[2][2] = cosrad; ret[2][3] = 0; - ret[3][0] = 0; ret[3][1] = 0; ret[3][2] = 0; ret[3][3] = FRACUNIT; - - return &ret; -} -#endif - -TMatrix *RotateZMatrix(angle_t rad) -{ - static TMatrix ret; - const angle_t fa = rad>>ANGLETOFINESHIFT; - const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa); - - ret[0][0] = cosrad; ret[0][1] = sinrad; ret[0][2] = 0; ret[0][3] = 0; - ret[1][0] = -sinrad; ret[1][1] = cosrad; ret[1][2] = 0; ret[1][3] = 0; - ret[2][0] = 0; ret[2][1] = 0; ret[2][2] = FRACUNIT; ret[2][3] = 0; - ret[3][0] = 0; ret[3][1] = 0; ret[3][2] = 0; ret[3][3] = FRACUNIT; - - return &ret; -} - /** Set of functions to take in a size_t as an argument, * put the argument in a character buffer, and return the * pointer to that buffer. diff --git a/src/m_misc.h b/src/m_misc.h index 5b79c6c8c..2959ba44e 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -80,17 +80,6 @@ INT32 axtoi(const char *hexStg); const char *GetRevisionString(void); -// Vector/matrix math -typedef fixed_t TVector[4]; -typedef fixed_t TMatrix[4][4]; - -TVector *VectorMatrixMultiply(TVector v, TMatrix m); -TMatrix *RotateXMatrix(angle_t rad); -#if 0 -TMatrix *RotateYMatrix(angle_t rad); -#endif -TMatrix *RotateZMatrix(angle_t rad); - // s1 = s2+s3+s1 (1024 lenghtmax) void strcatbf(char *s1, const char *s2, const char *s3); diff --git a/src/p_enemy.c b/src/p_enemy.c index 4c36446af..558b8a795 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1521,8 +1521,9 @@ void A_PointyThink(mobj_t *actor) INT32 i; player_t *player = NULL; mobj_t *ball; - TVector v; - TVector *res; + matrix_t m; + vector4_t v; + vector4_t res; angle_t fa; fixed_t radius = FixedMul(actor->info->radius*actor->info->reactiontime, actor->scale); boolean firsttime = true; @@ -1592,20 +1593,21 @@ void A_PointyThink(mobj_t *actor) while (ball) { fa = actor->lastlook+i; - v[0] = FixedMul(FINECOSINE(fa),radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),radius); - v[3] = FRACUNIT; + v.x = FixedMul(FINECOSINE(fa),radius); + v.y = 0; + v.z = FixedMul(FINESINE(fa),radius); + v.a = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->lastlook+i))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(actor->angle+ANGLE_180)); - M_Memcpy(&v, res, sizeof (v)); + FM_RotateX(&m, FixedAngle(actor->lastlook+i)); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); + + FM_RotateZ(&m, actor->angle+ANGLE_180); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); P_UnsetThingPosition(ball); - ball->x = actor->x + v[0]; - ball->y = actor->y + v[1]; - ball->z = actor->z + (actor->height>>1) + v[2]; + ball->x = actor->x + v.x; + ball->y = actor->y + v.y; + ball->z = actor->z + (actor->height>>1) + v.z; P_SetThingPosition(ball); ball = ball->tracer; diff --git a/src/p_mobj.c b/src/p_mobj.c index 3cc3dc338..2dbfac3bd 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6189,8 +6189,9 @@ static void P_MoveHoop(mobj_t *mobj) { const fixed_t fuse = (mobj->fuse*mobj->extravalue2); const angle_t fa = mobj->movedir*(FINEANGLES/mobj->extravalue1); - TVector v; - TVector *res; + matrix_t m; + vector4_t v; + vector4_t res; fixed_t finalx, finaly, finalz; fixed_t x, y, z; @@ -6203,19 +6204,20 @@ static void P_MoveHoop(mobj_t *mobj) z = mobj->target->z+mobj->target->height/2; // Make the sprite travel towards the center of the hoop - v[0] = FixedMul(FINECOSINE(fa),fuse); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),fuse); - v[3] = FRACUNIT; + v.x = FixedMul(FINECOSINE(fa),fuse); + v.y = 0; + v.z = FixedMul(FINESINE(fa),fuse); + v.a = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(mobj->target->movedir*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(FixedAngle(mobj->target->movecount*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); + FM_RotateX(&m, FixedAngle(mobj->target->movedir*FRACUNIT)); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; + FM_RotateZ(&m, FixedAngle(mobj->target->movecount*FRACUNIT)); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); + + finalx = x + v.x; + finaly = y + v.y; + finalz = z + v.z; P_UnsetThingPosition(mobj); mobj->x = finalx; @@ -6228,8 +6230,9 @@ void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT { mobj_t *mobj; INT32 i; - TVector v; - TVector *res; + matrix_t m; + vector4_t v; + vector4_t res; fixed_t finalx, finaly, finalz; mobj_t hoopcenter; mobj_t *axis; @@ -6271,19 +6274,20 @@ void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT for (i = 0; i < number; i++) { fa = (i*degrees); - v[0] = FixedMul(FINECOSINE(fa),radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),radius); - v[3] = FRACUNIT; + v.x = FixedMul(FINECOSINE(fa),radius); + v.y = 0; + v.z = FixedMul(FINESINE(fa),radius); + v.a = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(rotangle)); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); + FM_RotateX(&m, rotangle); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; + FM_RotateZ(&m, closestangle); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); + + finalx = x + v.x; + finaly = y + v.y; + finalz = z + v.z; mobj = P_SpawnMobj(finalx, finaly, finalz, type); mobj->z -= mobj->height/2; @@ -6294,8 +6298,9 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb { mobj_t *mobj; INT32 i; - TVector v; - TVector *res; + matrix_t m; + vector4_t v; + vector4_t res; fixed_t finalx, finaly, finalz, dist; angle_t degrees, fa, closestangle; fixed_t mobjx, mobjy, mobjz; @@ -6310,19 +6315,20 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb for (i = 0; i < number; i++) { fa = (i*degrees); - v[0] = FixedMul(FINECOSINE(fa),radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),radius); - v[3] = FRACUNIT; + v.x = FixedMul(FINECOSINE(fa),radius); + v.y = 0; + v.z = FixedMul(FINESINE(fa),radius); + v.a = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(rotangle)); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); + FM_RotateX(&m, rotangle); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; + FM_RotateZ(&m, closestangle); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); + + finalx = x + v.x; + finaly = y + v.y; + finalz = z + v.z; mobj = P_SpawnMobj(finalx, finaly, finalz, type); @@ -6489,9 +6495,10 @@ static void P_NightsItemChase(mobj_t *thing) // void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) { - TVector unit_lengthways, unit_sideways, pos_lengthways, pos_sideways; - TVector *res; - fixed_t radius, dist, zstore; + matrix_t m; + vector4_t unit_lengthways, unit_sideways, pos_lengthways, pos_sideways; + vector4_t res; + fixed_t radius, dist = 0, zstore; angle_t fa; boolean dosound = false; mobj_t *mobj = center->hnext, *hnext = NULL; @@ -6502,8 +6509,9 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) INT32 rot; INT32 prevrot; - dist = pos_sideways[0] = pos_sideways[1] = pos_sideways[2] = pos_sideways[3] = unit_sideways[3] =\ - pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0; + FV4_Load(&pos_sideways, 0, 0, 0, 0); + FV4_Load(&unit_sideways, 0, 0, 0, 0); + FV4_Load(&pos_lengthways, 0, 0, 0, 0); while (mobj) { @@ -6521,15 +6529,15 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) rot = (baserot + mobj->threshold) & FINEMASK; prevrot = (baseprevrot + mobj->threshold) & FINEMASK; - pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0; + FV4_Load(&pos_lengthways, 0, 0, 0, 0); dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed); dist = ((center->scale == FRACUNIT) ? dist : FixedMul(dist, center->scale)); fa = (FixedAngle(center->movefactor*FRACUNIT) >> ANGLETOFINESHIFT); radius = FixedMul(dist, FINECOSINE(fa)); - unit_lengthways[1] = -FixedMul(dist, FINESINE(fa)); - unit_lengthways[3] = FRACUNIT; + unit_lengthways.y = -FixedMul(dist, FINESINE(fa)); + unit_lengthways.a = FRACUNIT; // Swinging Chain. if (center->flags2 & MF2_STRONGBOX) @@ -6542,8 +6550,8 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) fa = ((FixedAngle(swingmag) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK; - unit_lengthways[0] = FixedMul(FINESINE(fa), -radius); - unit_lengthways[2] = FixedMul(FINECOSINE(fa), -radius); + unit_lengthways.x = FixedMul(FINESINE(fa), -radius); + unit_lengthways.z = FixedMul(FINECOSINE(fa), -radius); } // Rotating Chain. else @@ -6554,15 +6562,16 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) if (!(prevfa > (FINEMASK/2)) && (fa > (FINEMASK/2))) // completed a full swing dosound = true; - unit_lengthways[0] = FixedMul(FINECOSINE(fa), radius); - unit_lengthways[2] = FixedMul(FINESINE(fa), radius); + unit_lengthways.x = FixedMul(FINECOSINE(fa), radius); + unit_lengthways.z = FixedMul(FINESINE(fa), radius); } // Calculate the angle matrixes for the link. - res = VectorMatrixMultiply(unit_lengthways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT)); - M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways)); - res = VectorMatrixMultiply(unit_lengthways, *RotateZMatrix(center->angle)); - M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways)); + FM_RotateX(&m, center->threshold << ANGLETOFINESHIFT); + FV4_Copy(&unit_lengthways, FM_MultMatrixVec4(&m, &unit_lengthways, &res)); + + FM_RotateZ(&m, center->angle); + FV4_Copy(&unit_lengthways, FM_MultMatrixVec4(&m, &unit_lengthways, &res)); lastthreshold = mobj->threshold; lastfriction = mobj->friction; @@ -6574,63 +6583,64 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) dosound = false; } - if (pos_sideways[3] != mobj->movefactor) + if (pos_sideways.a != mobj->movefactor) { - if (!unit_sideways[3]) + if (!unit_sideways.a) { - unit_sideways[1] = dist; - unit_sideways[0] = unit_sideways[2] = 0; - unit_sideways[3] = FRACUNIT; + unit_sideways.y = dist; + unit_sideways.x = unit_sideways.z = 0; + unit_sideways.a = FRACUNIT; - res = VectorMatrixMultiply(unit_sideways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT)); - M_Memcpy(&unit_sideways, res, sizeof(unit_sideways)); - res = VectorMatrixMultiply(unit_sideways, *RotateZMatrix(center->angle)); - M_Memcpy(&unit_sideways, res, sizeof(unit_sideways)); + FM_RotateX(&m, center->threshold << ANGLETOFINESHIFT); + FV4_Copy(&unit_sideways, FM_MultMatrixVec4(&m, &unit_sideways, &res)); + + FM_RotateZ(&m, center->angle); + FV4_Copy(&unit_sideways, FM_MultMatrixVec4(&m, &unit_sideways, &res)); } - if (pos_sideways[3] > mobj->movefactor) + if (pos_sideways.a > mobj->movefactor) { do { - pos_sideways[0] -= unit_sideways[0]; - pos_sideways[1] -= unit_sideways[1]; - pos_sideways[2] -= unit_sideways[2]; + pos_sideways.x -= unit_sideways.x; + pos_sideways.y -= unit_sideways.y; + pos_sideways.z -= unit_sideways.z; } - while ((--pos_sideways[3]) != mobj->movefactor); + while ((--pos_sideways.a) != mobj->movefactor); } else { do { - pos_sideways[0] += unit_sideways[0]; - pos_sideways[1] += unit_sideways[1]; - pos_sideways[2] += unit_sideways[2]; + pos_sideways.x += unit_sideways.x; + pos_sideways.y += unit_sideways.y; + pos_sideways.z += unit_sideways.z; } - while ((++pos_sideways[3]) != mobj->movefactor); + while ((++pos_sideways.a) != mobj->movefactor); } } hnext = mobj->hnext; // just in case the mobj is removed - if (pos_lengthways[3] > mobj->movecount) + if (pos_lengthways.a > mobj->movecount) { do { - pos_lengthways[0] -= unit_lengthways[0]; - pos_lengthways[1] -= unit_lengthways[1]; - pos_lengthways[2] -= unit_lengthways[2]; + pos_lengthways.x -= unit_lengthways.x; + pos_lengthways.y -= unit_lengthways.y; + pos_lengthways.z -= unit_lengthways.z; } - while ((--pos_lengthways[3]) != mobj->movecount); + while ((--pos_lengthways.a) != mobj->movecount); } - else if (pos_lengthways[3] < mobj->movecount) + else if (pos_lengthways.a < mobj->movecount) { do { - pos_lengthways[0] += unit_lengthways[0]; - pos_lengthways[1] += unit_lengthways[1]; - pos_lengthways[2] += unit_lengthways[2]; + pos_lengthways.x += unit_lengthways.x; + pos_lengthways.y += unit_lengthways.y; + pos_lengthways.z += unit_lengthways.z; } - while ((++pos_lengthways[3]) != mobj->movecount); + while ((++pos_lengthways.a) != mobj->movecount); } P_UnsetThingPosition(mobj); @@ -6640,17 +6650,17 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) mobj->z = center->z; // Add on the appropriate distances to the center's co-ordinates. - if (pos_lengthways[3]) + if (pos_lengthways.a) { - mobj->x += pos_lengthways[0]; - mobj->y += pos_lengthways[1]; - zstore = pos_lengthways[2] + pos_sideways[2]; + mobj->x += pos_lengthways.x; + mobj->y += pos_lengthways.y; + zstore = pos_lengthways.z + pos_sideways.z; } else - zstore = pos_sideways[2]; + zstore = pos_sideways.z; - mobj->x += pos_sideways[0]; - mobj->y += pos_sideways[1]; + mobj->x += pos_sideways.x; + mobj->y += pos_sideways.y; // Cut the height to align the link with the axis. if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN || mobj->type == MT_SMALLGRABCHAIN || mobj->type == MT_BIGGRABCHAIN) @@ -6668,7 +6678,7 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) P_SetThingPosition(mobj); #if 0 // toaster's height-clipping dealie! - if (!pos_lengthways[3] || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT)) + if (!pos_lengthways.a || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT)) goto cont; if ((fa = ((center->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it @@ -6688,8 +6698,8 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) P_UnsetThingPosition(mobj); - mobj->x -= FixedMul(unit_lengthways[0], zstore); - mobj->y -= FixedMul(unit_lengthways[1], zstore); + mobj->x -= FixedMul(unit_lengthways.x, zstore); + mobj->y -= FixedMul(unit_lengthways.y, zstore); P_SetThingPosition(mobj); @@ -13342,13 +13352,13 @@ void P_SpawnHoop(mapthing_t *mthing) mobj_t *mobj = NULL; mobj_t *nextmobj = NULL; mobj_t *hoopcenter; - TMatrix *pitchmatrix, *yawmatrix; + matrix_t pitchmatrix, yawmatrix; fixed_t radius = mthing->args[0] << FRACBITS; fixed_t sizefactor = 4*FRACUNIT; fixed_t hoopsize = radius/sizefactor; INT32 i; angle_t fa; - TVector v, *res; + vector4_t v, res; fixed_t x = mthing->x << FRACBITS; fixed_t y = mthing->y << FRACBITS; fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale); @@ -13363,9 +13373,9 @@ void P_SpawnHoop(mapthing_t *mthing) P_SetThingPosition(hoopcenter); hoopcenter->movedir = mthing->pitch; - pitchmatrix = RotateXMatrix(FixedAngle(hoopcenter->movedir << FRACBITS)); + FM_RotateX(&pitchmatrix, FixedAngle(hoopcenter->movedir << FRACBITS)); hoopcenter->movecount = mthing->angle; - yawmatrix = RotateZMatrix(FixedAngle(hoopcenter->movecount << FRACBITS)); + FM_RotateZ(&yawmatrix, FixedAngle(hoopcenter->movecount << FRACBITS)); // For the hoop when it flies away hoopcenter->extravalue1 = hoopsize; @@ -13375,17 +13385,15 @@ void P_SpawnHoop(mapthing_t *mthing) for (i = 0; i < hoopsize; i++) { fa = i*(FINEANGLES/hoopsize); - v[0] = FixedMul(FINECOSINE(fa), radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), radius); - v[3] = FRACUNIT; + v.x = FixedMul(FINECOSINE(fa), radius); + v.y = 0; + v.z = FixedMul(FINESINE(fa), radius); + v.a = FRACUNIT; - res = VectorMatrixMultiply(v, *pitchmatrix); - M_Memcpy(&v, res, sizeof(v)); - res = VectorMatrixMultiply(v, *yawmatrix); - M_Memcpy(&v, res, sizeof(v)); + FV4_Copy(&v, FM_MultMatrixVec4(&pitchmatrix, &v, &res)); + FV4_Copy(&v, FM_MultMatrixVec4(&yawmatrix, &v, &res)); - mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOP); + mobj = P_SpawnMobj(x + v.x, y + v.y, z + v.z, MT_HOOP); mobj->z -= mobj->height/2; if (maptol & TOL_XMAS) @@ -13421,17 +13429,15 @@ void P_SpawnHoop(mapthing_t *mthing) for (i = 0; i < hoopsize; i++) { fa = i*(FINEANGLES/hoopsize); - v[0] = FixedMul(FINECOSINE(fa), radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), radius); - v[3] = FRACUNIT; + v.x = FixedMul(FINECOSINE(fa), radius); + v.y = 0; + v.z = FixedMul(FINESINE(fa), radius); + v.a = FRACUNIT; - res = VectorMatrixMultiply(v, *pitchmatrix); - M_Memcpy(&v, res, sizeof(v)); - res = VectorMatrixMultiply(v, *yawmatrix); - M_Memcpy(&v, res, sizeof(v)); + FV4_Copy(&v, FM_MultMatrixVec4(&pitchmatrix, &v, &res)); + FV4_Copy(&v, FM_MultMatrixVec4(&yawmatrix, &v, &res)); - mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOPCOLLIDE); + mobj = P_SpawnMobj(x + v.x, y + v.y, z + v.z, MT_HOOPCOLLIDE); mobj->z -= mobj->height/2; // Link all the collision sprites together. @@ -13522,7 +13528,8 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n angle_t angle = FixedAngle(mthing->angle << FRACBITS); angle_t fa; INT32 i; - TVector v, *res; + matrix_t m; + vector4_t v, res; for (i = 0; i < numitemtypes; i++) { @@ -13550,15 +13557,15 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n dummything.type = mobjinfo[itemtype].doomednum; fa = i*FINEANGLES/numitems; - v[0] = FixedMul(FINECOSINE(fa), size); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), size); - v[3] = FRACUNIT; + v.x = FixedMul(FINECOSINE(fa), size); + v.y = 0; + v.z = FixedMul(FINESINE(fa), size); + v.a = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateZMatrix(angle)); - M_Memcpy(&v, res, sizeof(v)); + FM_RotateZ(&m, angle); + FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res)); - mobj = P_SpawnMobjFromMapThing(&dummything, x + v[0], y + v[1], z + v[2], itemtype); + mobj = P_SpawnMobjFromMapThing(&dummything, x + v.x, y + v.y, z + v.z, itemtype); if (!mobj) continue; diff --git a/src/tables.c b/src/tables.c index 13949b6a7..f8b8030c9 100644 --- a/src/tables.c +++ b/src/tables.c @@ -407,9 +407,9 @@ void FV3_Rotate(vector3_t *rotVec, const vector3_t *axisVec, const angle_t angle rotVec->z = az+dz+ez; } -void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z) -{ #define M(row,col) dest->m[row * 4 + col] +matrix_t *FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z) +{ const fixed_t sinA = FINESINE(angle>>ANGLETOFINESHIFT); const fixed_t cosA = FINECOSINE(angle>>ANGLETOFINESHIFT); const fixed_t invCosA = FRACUNIT - cosA; @@ -459,5 +459,84 @@ void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z) M(1, 3) = 0; M(2, 3) = 0; M(3, 3) = FRACUNIT; -#undef M + + return dest; } + + +matrix_t *FM_RotateX(matrix_t *dest, angle_t rad) +{ + const angle_t fa = rad>>ANGLETOFINESHIFT; + const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa); + + M(0, 0) = FRACUNIT; + M(0, 1) = 0; + M(0, 2) = 0; + M(0, 3) = 0; + M(1, 0) = 0; + M(1, 1) = cosrad; + M(1, 2) = sinrad; + M(1, 3) = 0; + M(2, 0) = 0; + M(2, 1) = -sinrad; + M(2, 2) = cosrad; + M(2, 3) = 0; + M(3, 0) = 0; + M(3, 1) = 0; + M(3, 2) = 0; + M(3, 3) = FRACUNIT; + + return dest; +} + +matrix_t *FM_RotateY(matrix_t *dest, angle_t rad) +{ + const angle_t fa = rad>>ANGLETOFINESHIFT; + const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa); + + M(0, 0) = cosrad; + M(0, 1) = 0; + M(0, 2) = -sinrad; + M(0, 3) = 0; + M(1, 0) = 0; + M(1, 1) = FRACUNIT; + M(1, 2) = 0; + M(1, 3) = 0; + M(2, 0) = sinrad; + M(2, 1) = 0; + M(2, 2) = cosrad; + M(2, 3) = 0; + M(3, 0) = 0; + M(3, 1) = 0; + M(3, 2) = 0; + M(3, 3) = FRACUNIT; + + return dest; +} + +matrix_t *FM_RotateZ(matrix_t *dest, angle_t rad) +{ + const angle_t fa = rad>>ANGLETOFINESHIFT; + const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa); + + M(0, 0) = cosrad; + M(0, 1) = sinrad; + M(0, 2) = 0; + M(0, 3) = 0; + M(1, 0) = -sinrad; + M(1, 1) = cosrad; + M(1, 2) = 0; + M(1, 3) = 0; + M(2, 0) = 0; + M(2, 1) = 0; + M(2, 2) = FRACUNIT; + M(2, 3) = 0; + M(3, 0) = 0; + M(3, 1) = 0; + M(3, 2) = 0; + M(3, 3) = FRACUNIT; + + return dest; +} + +#undef M diff --git a/src/tables.h b/src/tables.h index c44c7d525..172ade378 100644 --- a/src/tables.h +++ b/src/tables.h @@ -107,7 +107,10 @@ boolean FV3_InsidePolygon(const vector3_t *vIntersection, const vector3_t *Poly, boolean FV3_IntersectedPolygon(const vector3_t *vPoly, const vector3_t *vLine, const INT32 vertexCount, vector3_t *collisionPoint); void FV3_Rotate(vector3_t *rotVec, const vector3_t *axisVec, const angle_t angle); /// Fixed Point Matrix functions -void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z); +matrix_t *FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z); +matrix_t *FM_RotateX(matrix_t *dest, angle_t rad); +matrix_t *FM_RotateY(matrix_t *dest, angle_t rad); +matrix_t *FM_RotateZ(matrix_t *dest, angle_t rad); // The table values in tables.c are calculated with this many fractional bits. #define FINE_FRACBITS 16