diff options
Diffstat (limited to '3dc/Maths.c')
| -rw-r--r-- | 3dc/Maths.c | 2944 |
1 files changed, 0 insertions, 2944 deletions
diff --git a/3dc/Maths.c b/3dc/Maths.c deleted file mode 100644 index 5cd3f49..0000000 --- a/3dc/Maths.c +++ /dev/null @@ -1,2944 +0,0 @@ - -#if PSX -#include <kernel.h> -#include <sys/types.h> -#include <libetc.h> -#include <libgte.h> -#include <libgpu.h> -#include <stdlib.h> -#include <inline_c.h> -#include <gtemac.h> -#endif - -#include "3dc.h" -#include "inline.h" - -#define UseTimsPinp Yes - -#define trip_debugger No - -#if trip_debugger -int testa = 0; -int testb = 100; -int testc = 0; -#endif - - -/* - - externs for commonly used global variables and arrays - -*/ - - #if platform_pc - extern int sine[]; - extern int cosine[]; - #endif - - extern short ArcCosTable[]; - extern short ArcSineTable[]; - extern short ArcTanTable[]; - - extern LONGLONGCH ll_zero; - - extern int NormalFrameTime; - - -#if PSX -extern unsigned long *scratchp; -#endif - -/* - - Globals - -*/ - - MATRIXCH IdentityMatrix = { - - ONE_FIXED, 0, 0, - 0, ONE_FIXED, 0, - 0, 0, ONE_FIXED - - }; - - - -/* - - Maths functions used by the system - -*/ - - - -#if PSX -inline void ch2psx(MATRIXCH *chm, MATRIX *psxm) -{ - psxm->m[0][0] = chm->mat11 >> 4; - psxm->m[0][1] = chm->mat21 >> 4; - psxm->m[0][2] = chm->mat31 >> 4; - psxm->m[1][0] = chm->mat12 >> 4; - psxm->m[1][1] = chm->mat22 >> 4; - psxm->m[1][2] = chm->mat32 >> 4; - psxm->m[2][0] = chm->mat13 >> 4; - psxm->m[2][1] = chm->mat23 >> 4; - psxm->m[2][2] = chm->mat33 >> 4; -} - -inline void psx2ch(MATRIX *psxm, MATRIXCH *chm) -{ - - chm->mat11 = psxm->m[0][0] << 4; - chm->mat21 = psxm->m[0][1] << 4; - chm->mat31 = psxm->m[0][2] << 4; - chm->mat12 = psxm->m[1][0] << 4; - chm->mat22 = psxm->m[1][1] << 4; - chm->mat32 = psxm->m[1][2] << 4; - chm->mat13 = psxm->m[2][0] << 4; - chm->mat23 = psxm->m[2][1] << 4; - chm->mat33 = psxm->m[2][2] << 4; -} - -#endif - -/* One over sin functions - CDF 4/2/98 */ - -extern int oneoversin[4096]; - -void ConstructOneOverSinTable(void) { - - int a,sin; - - for (a=0; a<4096; a++) { - sin=GetSin(a); - - if (sin!=0) { - oneoversin[a]=DIV_FIXED(ONE_FIXED,sin); - } else { - sin=100; - oneoversin[a]=DIV_FIXED(ONE_FIXED,sin); - } - } - -} - -int GetOneOverSin(int a) { - - int b; - - b=a&wrap360; - - return(oneoversin[b]); - -} - -/* - - Dot Product Function - - It accepts two pointers to vectors and returns an int result - -*/ - -int _DotProduct(VECTORCH *vptr1, VECTORCH *vptr2) - -{ - - int dp; - - dp = MUL_FIXED(vptr1->vx, vptr2->vx); - dp += MUL_FIXED(vptr1->vy, vptr2->vy); - dp += MUL_FIXED(vptr1->vz, vptr2->vz); - - return(dp); - -} - - -int DotProduct2d(VECTOR2D *vptr1, VECTOR2D *vptr2) - -{ - - int dp; - - - dp = MUL_FIXED(vptr1->vx, vptr2->vx); - dp += MUL_FIXED(vptr1->vy, vptr2->vy); - - return dp; - -} - - -/* - - This function returns the distance between two vectors - -*/ - -int VectorDistance(VECTORCH *v1, VECTORCH *v2) - -{ - - VECTORCH v; - - - v.vx = v1->vx - v2->vx; - v.vy = v1->vy - v2->vy; - v.vz = v1->vz - v2->vz; - - return Magnitude(&v); - -} - - -/* - - This function compares the distance between two vectors along each of - the major axes and returns Yes or No if they are within the cube defined - by the argument passed. - -*/ - -int OutcodeVectorDistance(VECTORCH *v1, VECTORCH *v2, int d) - -{ - - int i; - - - i = v1->vx - v2->vx; - if(i < 0) i = -i; - - if(i >= d) return No; - - i = v1->vy - v2->vy; - if(i < 0) i = -i; - - if(i >= d) return No; - - i = v1->vz - v2->vz; - if(i < 0) i = -i; - - if(i >= d) return No; - - return Yes; - -} - - -/* - - Subtract one VECTORCH from another and return the result as a normal - - v3 = Normal(v1 - v2) - -*/ - -void GetNormalVector(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3) - -{ - - v3->vx = v1->vx - v2->vx; - v3->vy = v1->vy - v2->vy; - v3->vz = v1->vz - v2->vz; - - Normalise(v3); - -} - - -/* - - Normalise a vector close to, but less than, unit length - -*/ - -void Renormalise(VECTORCH *nvector) - -{ - - int m; - int xsq, ysq, zsq; - - -/* Scale x, y and z */ - - nvector->vx >>= 2; - nvector->vy >>= 2; - nvector->vz >>= 2; - - -/* Normalise */ - - xsq = nvector->vx * nvector->vx; - ysq = nvector->vy * nvector->vy; - zsq = nvector->vz * nvector->vz; - - m = SqRoot32(xsq + ysq + zsq); - - if(m == 0) m = 1; /* Just in case */ - - nvector->vx = (nvector->vx * ONE_FIXED) / m; - nvector->vy = (nvector->vy * ONE_FIXED) / m; - nvector->vz = (nvector->vz * ONE_FIXED) / m; - -} - - - - - - - - - -/* - - Return the shift value required to get one value LTE the other value - -*/ - -int FindShift32(int value, int limit) - -{ - - int shift = 0; - - - /*if(limit == 0) exit(0xfa11fa11);*/ - - - if(value < 0) value = -value; - - while(value > limit) { - - #if trip_debugger - if(shift > 32) { - testa = testb / testc; - } - #endif - - shift++; - - value >>= 1; - - } - - return shift; - -} - - -/* - - Return the largest value of an int array - -*/ - -int MaxInt(int *iarray, int iarraysize) - -{ - - int imax = smallint; - int i; - - for(i = iarraysize; i!=0; i--) { - - if(imax < *iarray) imax = *iarray; - - iarray++; - - } - - return imax; - -} - - -/* - - Return the smallest value of an int array - -*/ - -int MinInt(int *iarray, int iarraysize) - -{ - - int imin = bigint; - int i; - - for(i = iarraysize; i!=0; i--) { - - if(imin > *iarray) imin = *iarray; - - iarray++; - - } - - return imin; - -} - - - -/* - - Create Matrix from Euler Angles - - It requires a pointer to some euler angles and a pointer to a matrix - - Construct the matrix elements using the following formula - - Formula for ZXY Matrix - - m11 = cy*cz + sx*sy*sz m12 = -cy*sz + sx*sy*cz m13 = cx*sy - m21 = cx*sz m22 = cx*cz m23 = -sx - m31 = -sy*cz + sx*cy*sz m32 = sy*sz + sx*cy*cz m33 = cx*cy - -*/ - -void CreateEulerMatrix(e, m1) - - EULER *e; - MATRIXCH *m1; - -{ - -#if 0 - - SVECTOR eulers; - - eulers.vx=(e->EulerX)&4095; - eulers.vy=(e->EulerY)&4095; - eulers.vz=(e->EulerZ)&4095; - - RotMatrix(&eulers,(MATRIX *)scratchp); - - psx2ch((MATRIX *)scratchp,m1); - -#else - - int t, sx, sy, sz, cx, cy, cz; - - - sx = GetSin(e->EulerX); - sy = GetSin(e->EulerY); - sz = GetSin(e->EulerZ); - - cx = GetCos(e->EulerX); - cy = GetCos(e->EulerY); - cz = GetCos(e->EulerZ); - - - #if 0 - textprint("Euler Matrix Sines & Cosines\n"); - textprint("%d, %d, %d\n", sx, sy, sz); - textprint("%d, %d, %d\n", cx, cy, cz); - #endif - - -/* m11 = cy*cz + sx*sy*sz */ - - m1->mat11 = MUL_FIXED(cy, cz); /* cy*cz */ - t = MUL_FIXED(sx, sy); /* sx*sy */ - t = MUL_FIXED(t, sz); /* *sz */ - m1->mat11 += t; - - -/* m12 = -cy*sz + sx*sy*cz */ - - m1->mat12=MUL_FIXED(-cy,sz); - t=MUL_FIXED(sx,sy); - t=MUL_FIXED(t,cz); - m1->mat12+=t; - - -/* m13 = cx*sy */ - - m1->mat13=MUL_FIXED(cx,sy); - - -/* m21 = cx*sz */ - - m1->mat21=MUL_FIXED(cx,sz); - - -/* m22 = cx*cz */ - - m1->mat22=MUL_FIXED(cx,cz); - - -/* m23 = -sx */ - - m1->mat23=-sx; - - -/* m31 = -sy*cz + sx*cy*sz */ - - m1->mat31=MUL_FIXED(-sy,cz); - t=MUL_FIXED(sx,cy); - t=MUL_FIXED(t,sz); - m1->mat31+=t; - - -/* m32 = sy*sz + sx*cy*cz */ - - m1->mat32=MUL_FIXED(sy,sz); - t=MUL_FIXED(sx,cy); - t=MUL_FIXED(t,cz); - m1->mat32+=t; - - -/* m33 = cx*cy */ - - m1->mat33=MUL_FIXED(cx,cy); - -#endif - -} - - -/* - - Create a Unit Vector from three Euler Angles - -*/ - -void CreateEulerVector(EULER *e, VECTORCH *v) - -{ - - int t, sx, sy, sz, cx, cy, cz; - - - sx = GetSin(e->EulerX); - sy = GetSin(e->EulerY); - sz = GetSin(e->EulerZ); - - cx = GetCos(e->EulerX); - cy = GetCos(e->EulerY); - cz = GetCos(e->EulerZ); - - - /* x = -sy*cz + sx*cy*sz */ - - v->vx = MUL_FIXED(-sy, cz); - t = MUL_FIXED(sx, cy); - t = MUL_FIXED(t, sz); - v->vx += t; - - - /* y = sy*sz + sx*cy*cz */ - - v->vy = MUL_FIXED(sy, sz); - t = MUL_FIXED(sx, cy); - t = MUL_FIXED(t, cz); - v->vy += t; - - - /* z = cx*cy */ - - v->vz = MUL_FIXED(cx,cy); - -} - - - -/* - - Matrix Multiply Function - - A 3x3 Matrix is represented here as - - m11 m12 m13 - m21 m22 m23 - m31 m32 m33 - - Row #1 (r1) of the matrix is m11 m12 m13 - Column #1 (c1) of the matrix is m11 m32 m31 - - Under multiplication - - m'' = m x m' - - where - - m11'' = c1.r1' - m12'' = c2.r1' - m13'' = c3.r1' - - m21'' = c1.r2' - m22'' = c2.r2' - m23'' = c3.r2' - - m31'' = c1.r3' - m32'' = c2.r3' - m33'' = c3.r3' - -*/ - -void MatrixMultiply(m1, m2, m3) - - struct matrixch *m1, *m2, *m3; - -{ - - #if 0 - - PushMatrix(); - - ch2psx(m1,(MATRIX *)scratchp); - ch2psx(m2,(MATRIX *)(scratchp+(sizeof(MATRIX)))); - - MulMatrix0((MATRIX *)scratchp,(MATRIX *)(scratchp+(sizeof(MATRIX))),(MATRIX *)(scratchp+((sizeof(MATRIX)<<1)))); - - psx2ch((MATRIX *)(scratchp+((sizeof(MATRIX)<<1))),m3); - - PopMatrix(); - - #else - - MATRIXCH TmpMat; - -/* m11'' = c1.r1' */ - - TmpMat.mat11=MUL_FIXED(m1->mat11,m2->mat11); - TmpMat.mat11+=MUL_FIXED(m1->mat21,m2->mat12); - TmpMat.mat11+=MUL_FIXED(m1->mat31,m2->mat13); - -/* m12'' = c2.r1' */ - - TmpMat.mat12=MUL_FIXED(m1->mat12,m2->mat11); - TmpMat.mat12+=MUL_FIXED(m1->mat22,m2->mat12); - TmpMat.mat12+=MUL_FIXED(m1->mat32,m2->mat13); - -/* m13'' = c3.r1' */ - - TmpMat.mat13=MUL_FIXED(m1->mat13,m2->mat11); - TmpMat.mat13+=MUL_FIXED(m1->mat23,m2->mat12); - TmpMat.mat13+=MUL_FIXED(m1->mat33,m2->mat13); - -/* m21'' = c1.r2' */ - - TmpMat.mat21=MUL_FIXED(m1->mat11,m2->mat21); - TmpMat.mat21+=MUL_FIXED(m1->mat21,m2->mat22); - TmpMat.mat21+=MUL_FIXED(m1->mat31,m2->mat23); - -/* m22'' = c2.r2' */ - - TmpMat.mat22=MUL_FIXED(m1->mat12,m2->mat21); - TmpMat.mat22+=MUL_FIXED(m1->mat22,m2->mat22); - TmpMat.mat22+=MUL_FIXED(m1->mat32,m2->mat23); - -/* m23'' = c3.r2' */ - - TmpMat.mat23=MUL_FIXED(m1->mat13,m2->mat21); - TmpMat.mat23+=MUL_FIXED(m1->mat23,m2->mat22); - TmpMat.mat23+=MUL_FIXED(m1->mat33,m2->mat23); - -/* m31'' = c1.r3' */ - - TmpMat.mat31=MUL_FIXED(m1->mat11,m2->mat31); - TmpMat.mat31+=MUL_FIXED(m1->mat21,m2->mat32); - TmpMat.mat31+=MUL_FIXED(m1->mat31,m2->mat33); - -/* m32'' = c2.r3' */ - - TmpMat.mat32=MUL_FIXED(m1->mat12,m2->mat31); - TmpMat.mat32+=MUL_FIXED(m1->mat22,m2->mat32); - TmpMat.mat32+=MUL_FIXED(m1->mat32,m2->mat33); - -/* m33'' = c3.r3' */ - - TmpMat.mat33=MUL_FIXED(m1->mat13,m2->mat31); - TmpMat.mat33+=MUL_FIXED(m1->mat23,m2->mat32); - TmpMat.mat33+=MUL_FIXED(m1->mat33,m2->mat33); - -/* Finally, copy TmpMat to m3 */ - - CopyMatrix(&TmpMat, m3); - - #endif - -} - - -void PSXAccurateMatrixMultiply(m1, m2, m3) - - struct matrixch *m1, *m2, *m3; - -{ - - MATRIXCH TmpMat; - -/* m11'' = c1.r1' */ - - TmpMat.mat11=MUL_FIXED(m1->mat11,m2->mat11); - TmpMat.mat11+=MUL_FIXED(m1->mat21,m2->mat12); - TmpMat.mat11+=MUL_FIXED(m1->mat31,m2->mat13); - -/* m12'' = c2.r1' */ - - TmpMat.mat12=MUL_FIXED(m1->mat12,m2->mat11); - TmpMat.mat12+=MUL_FIXED(m1->mat22,m2->mat12); - TmpMat.mat12+=MUL_FIXED(m1->mat32,m2->mat13); - -/* m13'' = c3.r1' */ - - TmpMat.mat13=MUL_FIXED(m1->mat13,m2->mat11); - TmpMat.mat13+=MUL_FIXED(m1->mat23,m2->mat12); - TmpMat.mat13+=MUL_FIXED(m1->mat33,m2->mat13); - -/* m21'' = c1.r2' */ - - TmpMat.mat21=MUL_FIXED(m1->mat11,m2->mat21); - TmpMat.mat21+=MUL_FIXED(m1->mat21,m2->mat22); - TmpMat.mat21+=MUL_FIXED(m1->mat31,m2->mat23); - -/* m22'' = c2.r2' */ - - TmpMat.mat22=MUL_FIXED(m1->mat12,m2->mat21); - TmpMat.mat22+=MUL_FIXED(m1->mat22,m2->mat22); - TmpMat.mat22+=MUL_FIXED(m1->mat32,m2->mat23); - -/* m23'' = c3.r2' */ - - TmpMat.mat23=MUL_FIXED(m1->mat13,m2->mat21); - TmpMat.mat23+=MUL_FIXED(m1->mat23,m2->mat22); - TmpMat.mat23+=MUL_FIXED(m1->mat33,m2->mat23); - -/* m31'' = c1.r3' */ - - TmpMat.mat31=MUL_FIXED(m1->mat11,m2->mat31); - TmpMat.mat31+=MUL_FIXED(m1->mat21,m2->mat32); - TmpMat.mat31+=MUL_FIXED(m1->mat31,m2->mat33); - -/* m32'' = c2.r3' */ - - TmpMat.mat32=MUL_FIXED(m1->mat12,m2->mat31); - TmpMat.mat32+=MUL_FIXED(m1->mat22,m2->mat32); - TmpMat.mat32+=MUL_FIXED(m1->mat32,m2->mat33); - -/* m33'' = c3.r3' */ - - TmpMat.mat33=MUL_FIXED(m1->mat13,m2->mat31); - TmpMat.mat33+=MUL_FIXED(m1->mat23,m2->mat32); - TmpMat.mat33+=MUL_FIXED(m1->mat33,m2->mat33); - -/* Finally, copy TmpMat to m3 */ - - CopyMatrix(&TmpMat, m3); - -} - - - - - -/* - - Transpose Matrix - -*/ - -void TransposeMatrixCH(m1) - - MATRIXCH *m1; - -{ - - int t; - - t=m1->mat12; - m1->mat12=m1->mat21; - m1->mat21=t; - - t=m1->mat13; - m1->mat13=m1->mat31; - m1->mat31=t; - - t=m1->mat23; - m1->mat23=m1->mat32; - m1->mat32=t; - -} - - -/* - - Copy Vector - -*/ - -void CopyVector(VECTORCH *v1, VECTORCH *v2) - -{ - -/* Copy VECTORCH v1 -> VECTORCH v2 */ - - v2->vx=v1->vx; - v2->vy=v1->vy; - v2->vz=v1->vz; - -} - - -/* - - Copy Location - -*/ - -void CopyLocation(VECTORCH *v1, VECTORCH *v2) - -{ - -/* Copy VECTORCH v1 -> VECTORCH v2 */ - - v2->vx=v1->vx; - v2->vy=v1->vy; - v2->vz=v1->vz; - -} - - - - - -/* - - Copy Euler - -*/ - -void CopyEuler(EULER *e1, EULER *e2) - -{ - -/* Copy EULER e1 -> EULER e2 */ - - e2->EulerX=e1->EulerX; - e2->EulerY=e1->EulerY; - e2->EulerZ=e1->EulerZ; - -} - - -/* - - Copy Matrix - -*/ - -void CopyMatrix(MATRIXCH *m1, MATRIXCH *m2) - -{ - -/* Copy MATRIXCH m1 -> MATRIXCH m2 */ - - m2->mat11=m1->mat11; - m2->mat12=m1->mat12; - m2->mat13=m1->mat13; - - m2->mat21=m1->mat21; - m2->mat22=m1->mat22; - m2->mat23=m1->mat23; - - m2->mat31=m1->mat31; - m2->mat32=m1->mat32; - m2->mat33=m1->mat33; - -} - - -/* - - Make a Vector. - - v3 = v1 - v2 - -*/ - -void MakeVector(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3) - -{ - - v3->vx = v1->vx - v2->vx; - v3->vy = v1->vy - v2->vy; - v3->vz = v1->vz - v2->vz; - -} - - -/* - - Add a Vector. - - v2 = v2 + v1 - -*/ - -void AddVector(VECTORCH *v1, VECTORCH *v2) - -{ - - v2->vx += v1->vx; - v2->vy += v1->vy; - v2->vz += v1->vz; - -} - - -/* - - Subtract a Vector. - - v2 = v2 - v1 - -*/ - -void SubVector(VECTORCH *v1, VECTORCH *v2) - -{ - - v2->vx -= v1->vx; - v2->vy -= v1->vy; - v2->vz -= v1->vz; - -} - - - -/* - - Matrix Rotatation of a Vector - - Overwrite the Source Vector with the Rotated Vector - - x' = v.c1 - y' = v.c2 - z' = v.c3 - -*/ - -void _RotateVector(VECTORCH *v, MATRIXCH* m) -{ - - int x, y, z; - - - x = MUL_FIXED(m->mat11, v->vx); - x += MUL_FIXED(m->mat21, v->vy); - x += MUL_FIXED(m->mat31, v->vz); - - y = MUL_FIXED(m->mat12, v->vx); - y += MUL_FIXED(m->mat22, v->vy); - y += MUL_FIXED(m->mat32, v->vz); - - z = MUL_FIXED(m->mat13, v->vx); - z += MUL_FIXED(m->mat23, v->vy); - z += MUL_FIXED(m->mat33, v->vz); - - v->vx = x; - v->vy = y; - v->vz = z; -} - - -/* - - Matrix Rotation of a Source Vector using a Matrix - Copying to a Destination Vector - - x' = v.c1 - y' = v.c2 - z' = v.c3 - -*/ - -void _RotateAndCopyVector(v1, v2, m) - - VECTORCH *v1; - VECTORCH *v2; - MATRIXCH *m; - -{ - - v2->vx=MUL_FIXED(m->mat11,v1->vx); - v2->vx+=MUL_FIXED(m->mat21,v1->vy); - v2->vx+=MUL_FIXED(m->mat31,v1->vz); - - v2->vy=MUL_FIXED(m->mat12,v1->vx); - v2->vy+=MUL_FIXED(m->mat22,v1->vy); - v2->vy+=MUL_FIXED(m->mat32,v1->vz); - - v2->vz=MUL_FIXED(m->mat13,v1->vx); - v2->vz+=MUL_FIXED(m->mat23,v1->vy); - v2->vz+=MUL_FIXED(m->mat33,v1->vz); - -} - - - - - - -/* - - Matrix to Euler Angles - - Maths overflow is a real problem for this function. To prevent overflows - the matrix Sines and Cosines are calculated using values scaled down by 4. - - - sinx = -M23 - - cosx = sqr ( 1 - sinx^2 ) - - - siny = M13 / cosx - - cosy = M33 / cosx - - - sinz = M21 / cosx - - cosz = M22 / cosx - - -*/ - - -#define m2e_scale 2 -#define ONE_FIXED_S ((ONE_FIXED >> m2e_scale) - 1) -#define m2e_shift 14 - -#define j_and_r_change Yes - - -void MatrixToEuler(MATRIXCH *m, EULER *e) - -{ - - int x, sinx, cosx, siny, cosy, sinz, cosz; - int abs_cosx, abs_cosy, abs_cosz; - int SineMatrixPitch, SineMatrixYaw, SineMatrixRoll; - int CosMatrixPitch, CosMatrixYaw, CosMatrixRoll; - - - - - #if 0 - textprint("CosMatrixPitch = %d\n", CosMatrixPitch); - /* WaitForReturn(); */ - #endif - - - if(m->mat32 >-65500 && m->mat32<65500) - { - /* Yaw */ - - /* Pitch */ - - #if j_and_r_change - SineMatrixPitch = -m->mat32; - #else - SineMatrixPitch = -m->mat23; - #endif - - SineMatrixPitch >>= m2e_scale; - - #if 0 - textprint("SineMatrixPitch = %d\n", SineMatrixPitch); - /* WaitForReturn(); */ - #endif - - CosMatrixPitch = SineMatrixPitch * SineMatrixPitch; - CosMatrixPitch >>= m2e_shift; - - CosMatrixPitch = -CosMatrixPitch; - CosMatrixPitch += ONE_FIXED_S; - CosMatrixPitch *= ONE_FIXED_S; - CosMatrixPitch = SqRoot32(CosMatrixPitch); - - if(CosMatrixPitch) { - - if(CosMatrixPitch > ONE_FIXED_S) CosMatrixPitch = ONE_FIXED_S; - else if(CosMatrixPitch < -ONE_FIXED_S) CosMatrixPitch = -ONE_FIXED_S; - - } - - else CosMatrixPitch = 1; - - SineMatrixYaw = WideMulNarrowDiv( - #if j_and_r_change - m->mat31 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #else - m->mat13 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #endif - - #if 0 - textprint("SineMatrixYaw = %d\n", SineMatrixYaw); - /* WaitForReturn(); */ - #endif - - CosMatrixYaw = WideMulNarrowDiv( - m->mat33 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - - #if 0 - textprint("CosMatrixYaw = %d\n", CosMatrixYaw); - /* WaitForReturn(); */ - #endif - - - /* Roll */ - - SineMatrixRoll = WideMulNarrowDiv( - #if j_and_r_change - m->mat12 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #else - m->mat21 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #endif - - #if 0 - textprint("SineMatrixRoll = %d\n", SineMatrixRoll); - /* WaitForReturn(); */ - #endif - - CosMatrixRoll = WideMulNarrowDiv( - m->mat22 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - - #if 0 - textprint("CosMatrixRoll = %d\n", CosMatrixRoll); - /* WaitForReturn(); */ - #endif - - /* Tables are for values +- 2^16 */ - - sinx = SineMatrixPitch << m2e_scale; - siny = SineMatrixYaw << m2e_scale; - sinz = SineMatrixRoll << m2e_scale; - - cosx = CosMatrixPitch << m2e_scale; - cosy = CosMatrixYaw << m2e_scale; - cosz = CosMatrixRoll << m2e_scale; - - #if 0 - textprint("sines = %d, %d, %d\n", sinx, siny, sinz); - textprint("cos's = %d, %d, %d\n", cosx, cosy, cosz); - /* WaitForReturn(); */ - #endif - - /* Absolute Cosines */ - - abs_cosx = cosx; - if(abs_cosx < 0) abs_cosx = -abs_cosx; - - abs_cosy = cosy; - if(abs_cosy < 0) abs_cosy = -abs_cosy; - - abs_cosz = cosz; - if(abs_cosz < 0) abs_cosz = -abs_cosz; - - - /* Euler X */ - - if(abs_cosx > Cosine45) { - - x = ArcSin(sinx); - - if(cosx < 0) { - x = -x; - x += deg180; - x &= wrap360; - } - } - - else { - - x = ArcCos(cosx); - - if(sinx < 0) { - x = -x; - x &= wrap360; - } - } - - #if (j_and_r_change == No) - x = -x; - x &= wrap360; - #endif - - e->EulerX = x; - - - /* Euler Y */ - - if(abs_cosy > Cosine45) { - - x = ArcSin(siny); - - if(cosy < 0) { - x = -x; - x += deg180; - x &= wrap360; - } - - } - - else { - - x = ArcCos(cosy); - - if(siny < 0) { - x = -x; - x &= wrap360; - } - - } - - #if (j_and_r_change == No) - x = -x; - x &= wrap360; - #endif - - e->EulerY = x; - - - /* Euler Z */ - - if(abs_cosz > Cosine45) { - - x = ArcSin(sinz); - - if(cosz < 0) { - x = -x; - x += deg180; - x &= wrap360; - } - } - - else { - - x = ArcCos(cosz); - - if(sinz < 0) { - x = -x; - x &= wrap360; - } - } - - #if (j_and_r_change == No) - x = -x; - x &= wrap360; - #endif - - e->EulerZ = x; - } - else //singularity case - { - - if(m->mat32>0) - e->EulerX = 3072; - else - e->EulerX = 1024; - - e->EulerZ=0; - - - - /* Yaw */ - - siny = -m->mat13 ; - - cosy = m->mat11 ; - - abs_cosy = cosy; - if(abs_cosy < 0) abs_cosy = -abs_cosy; - - - if(abs_cosy > Cosine45) { - - x = ArcSin(siny); - - if(cosy < 0) { - x = -x; - x += deg180; - x &= wrap360; - } - - } - - else { - - x = ArcCos(cosy); - - if(siny < 0) { - x = -x; - x &= wrap360; - } - - } - - #if (j_and_r_change == No) - x = -x; - x &= wrap360; - #endif - - e->EulerY = x; - - } - - - - - #if 0 - textprint("\nEuler from VDB Matrix is:\n%d\n%d\n%d\n", - e->EulerX, - e->EulerY, - e->EulerZ - ); - /* WaitForReturn(); */ - #endif - -} - - - -#if 1 - - - - -#define j_and_r_change_2 Yes - -void MatrixToEuler2(MATRIXCH *m, EULER *e) - -{ - - int x, sinx, cosx, siny, cosy, sinz, cosz; - int abs_cosx, abs_cosy, abs_cosz; - int SineMatrixPitch, SineMatrixYaw, SineMatrixRoll; - int CosMatrixPitch, CosMatrixYaw, CosMatrixRoll; - - - /* Pitch */ - - #if j_and_r_change_2 - SineMatrixPitch = -m->mat32; - #else - SineMatrixPitch = -m->mat23; - #endif - - SineMatrixPitch >>= m2e_scale; - - #if 0 - textprint("SineMatrixPitch = %d\n", SineMatrixPitch); - /* WaitForReturn(); */ - #endif - - CosMatrixPitch = SineMatrixPitch * SineMatrixPitch; - CosMatrixPitch >>= m2e_shift; - - CosMatrixPitch = -CosMatrixPitch; - CosMatrixPitch += ONE_FIXED_S; - CosMatrixPitch *= ONE_FIXED_S; - CosMatrixPitch = SqRoot32(CosMatrixPitch); - - if(CosMatrixPitch) { - - if(CosMatrixPitch > ONE_FIXED_S) CosMatrixPitch = ONE_FIXED_S; - else if(CosMatrixPitch < -ONE_FIXED_S) CosMatrixPitch = -ONE_FIXED_S; - - } - - else CosMatrixPitch = 1; - - - #if 0 - textprint("CosMatrixPitch = %d\n", CosMatrixPitch); - /* WaitForReturn(); */ - #endif - - - /* Yaw */ - - SineMatrixYaw = WideMulNarrowDiv( - #if j_and_r_change_2 - m->mat31 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #else - m->mat13 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #endif - - #if 0 - textprint("SineMatrixYaw = %d\n", SineMatrixYaw); - /* WaitForReturn(); */ - #endif - - CosMatrixYaw = WideMulNarrowDiv( - m->mat33 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - - #if 0 - textprint("CosMatrixYaw = %d\n", CosMatrixYaw); - /* WaitForReturn(); */ - #endif - - - /* Roll */ - - SineMatrixRoll = WideMulNarrowDiv( - #if j_and_r_change_2 - m->mat12 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #else - m->mat21 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - #endif - - #if 0 - textprint("SineMatrixRoll = %d\n", SineMatrixRoll); - /* WaitForReturn(); */ - #endif - - CosMatrixRoll = WideMulNarrowDiv( - m->mat22 >> m2e_scale, ONE_FIXED_S, CosMatrixPitch); - - #if 0 - textprint("CosMatrixRoll = %d\n", CosMatrixRoll); - /* WaitForReturn(); */ - #endif - - - /* Tables are for values +- 2^16 */ - - sinx = SineMatrixPitch << m2e_scale; - siny = SineMatrixYaw << m2e_scale; - sinz = SineMatrixRoll << m2e_scale; - - cosx = CosMatrixPitch << m2e_scale; - cosy = CosMatrixYaw << m2e_scale; - cosz = CosMatrixRoll << m2e_scale; - - #if 0 - textprint("sines = %d, %d, %d\n", sinx, siny, sinz); - textprint("cos's = %d, %d, %d\n", cosx, cosy, cosz); - /* WaitForReturn(); */ - #endif - - /* Absolute Cosines */ - - abs_cosx = cosx; - if(abs_cosx < 0) abs_cosx = -abs_cosx; - - abs_cosy = cosy; - if(abs_cosy < 0) abs_cosy = -abs_cosy; - - abs_cosz = cosz; - if(abs_cosz < 0) abs_cosz = -abs_cosz; - - - /* Euler X */ - - if(abs_cosx > Cosine45) { - - x = ArcSin(sinx); - - if(cosx < 0) { - x = -x; - x += deg180; - x &= wrap360; - } - } - - else { - - x = ArcCos(cosx); - - if(sinx < 0) { - x = -x; - x &= wrap360; - } - } - - #if (j_and_r_change_2 == No) - x = -x; - x &= wrap360; - #endif - - e->EulerX = x; - - - /* Euler Y */ - - if(abs_cosy > Cosine45) { - - x = ArcSin(siny); - - if(cosy < 0) { - x = -x; - x += deg180; - x &= wrap360; - } - - } - - else { - - x = ArcCos(cosy); - - if(siny < 0) { - x = -x; - x &= wrap360; - } - - } - - #if (j_and_r_change_2 == No) - x = -x; - x &= wrap360; - #endif - - e->EulerY = x; - - - /* Euler Z */ - - if(abs_cosz > Cosine45) { - - x = ArcSin(sinz); - - if(cosz < 0) { - x = -x; - x += deg180; - x &= wrap360; - } - } - - else { - - x = ArcCos(cosz); - - if(sinz < 0) { - x = -x; - x &= wrap360; - } - } - - #if (j_and_r_change_2 == No) - x = -x; - x &= wrap360; - #endif - - e->EulerZ = x; - - - #if 0 - textprint("\nEuler from VDB Matrix is:\n%d\n%d\n%d\n", - e->EulerX, - e->EulerY, - e->EulerZ - ); - /* WaitForReturn(); */ - #endif - -} - - - -#endif - - - -/* - - Normalise a Matrix - - Dot the three vectors together (XY, XZ, YZ) and take the two nearest to - 90ø from each other. Cross them to create a new third vector, then cross - the first and third to create a new second. - -*/ - -void MNormalise(MATRIXCH *m) - -{ - - VECTORCH *x = (VECTORCH *) &m->mat11; - VECTORCH *y = (VECTORCH *) &m->mat21; - VECTORCH *z = (VECTORCH *) &m->mat31; - int dotxy = Dot(x, y); - int dotxz = Dot(x, z); - int dotyz = Dot(y, z); - VECTORCH *s; - VECTORCH *t; - VECTORCH u; - VECTORCH v; - VECTORCH zero = {0, 0, 0}; - - - #if 0 - textprint("dotxy = %d\n", dotxy); - textprint("dotxz = %d\n", dotxz); - textprint("dotyz = %d\n", dotyz); - #endif - - #if 0 - /* TEST */ - dotxy = 0; - dotxz = 0; - dotyz = 1; - #endif - - - #if 0 - textprint("%d %d %d\n", - x->vx, - x->vy, - x->vz - ); - - textprint("%d %d %d\n", - y->vx, - y->vy, - y->vz - ); - - textprint("%d %d %d\n", - z->vx, - z->vy, - z->vz - ); - #endif - - - /* Find the two vectors nearest 90ø */ - - if(dotxy > dotxz && dotxy > dotyz) { - - /* xy are the closest to 90ø */ - - /*textprint("xy\n");*/ - - s = x; - t = y; - - MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */ - - MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */ - v.vx = -v.vx; - v.vy = -v.vy; - v.vz = -v.vz; - - CopyVector(&u, z); - CopyVector(&v, y); - - } - - else if(dotxz > dotxy && dotxz > dotyz) { - - /* xz are the closest to 90ø */ - - /*textprint("xz\n");*/ - - s = x; - t = z; - - MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */ - u.vx = -u.vx; - u.vy = -u.vy; - u.vz = -u.vz; - - MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */ - - CopyVector(&u, y); - CopyVector(&v, z); - - } - - else { - - /* yz are the closest to 90ø */ - - /*textprint("yz\n");*/ - - s = y; - t = z; - - MakeNormal(&zero, s, t, &u); /* Cross them for a new 3rd vector */ - - MakeNormal(&zero, s, &u, &v); /* Cross 1st & 3rd for a new 2nd */ - v.vx = -v.vx; - v.vy = -v.vy; - v.vz = -v.vz; - - CopyVector(&u, x); - CopyVector(&v, z); - - } - - - #if 0 - textprint("%d %d %d\n", - x->vx, - x->vy, - x->vz - ); - - textprint("%d %d %d\n", - y->vx, - y->vy, - y->vz - ); - - textprint("%d %d %d\n", - z->vx, - z->vy, - z->vz - ); - #endif - - #if 0 - textprint("mag. x = %d\n", Magnitude(x)); - textprint("mag. y = %d\n", Magnitude(y)); - textprint("mag. z = %d\n", Magnitude(z)); - #endif - - /*WaitForReturn();*/ - - -} - - - - -/* - - ArcCos - - In: COS value as -65,536 -> +65,536. - Out: Angle in 0 -> 4095 form. - - Notes: - - The angle returned is in the range 0 -> 2,047 since the sign of SIN - is not known. - - ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) ) - ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x) - - -65,536 = 180 Degrees - 0 = 90 Degrees - +65,536 = 0 Degrees - - The table has 4,096 entries. - -*/ - -int ArcCos(int c) - -{ - - short acos; - - if(c < (-(ONE_FIXED - 1))) c = -(ONE_FIXED - 1); - else if(c > (ONE_FIXED - 1)) c = ONE_FIXED - 1; - - #if 0 - c = c >> 5; /* -64k -> +64k becomes -2k -> +2k */ - c += 2048; /* -2k -> +2k becomes 0 -> 4k */ - #endif - - acos = ArcCosTable[(c >> 5) + 2048]; - - return (int) (acos & wrap360); - -} - - -/* - - ArcSin - - In: SIN value in ax as -65,536 -> +65,536. - Out: Angle in 0 -> 4095 form in ax. - - Notes: - - The angle returned is in the range -1,024 -> 1,023 since the sign of COS - is not known. - - ArcSin(x) = ArcTan ( x, sqr ( 1-x*x ) ) - ArcCos(x) = ArcTan ( sqr ( 1-x*x ), x) - - -65,536 = 270 Degrees - 0 = 0 Degrees - +65,536 = 90 Degrees - - The table has 4,096 entries. - -*/ - -int ArcSin(int s) - -{ - - short asin; - - - if(s < (-(ONE_FIXED - 1))) s = -(ONE_FIXED - 1); - else if(s > (ONE_FIXED - 1)) s = ONE_FIXED - 1; - - #if 0 - s = s >> 5; /* -64k -> +64k becomes -2k -> +2k */ - s += 2048; /* -2k -> +2k becomes 0 -> 4k */ - #endif - - asin = ArcSineTable[(s >> 5) + 2048]; - - return (int) (asin & wrap360); - -} - - -/* - - ArcTan - - Pass (x,z) - - And ATN(x/z) is returned such that: - - 000ø is Map North - 090ø is Map East - 180ø is Map South - 270ø is Map West - -*/ - -int ArcTan(height_x, width_z) - - int height_x,width_z; - -{ - - int abs_height_x, abs_width_z, angle, sign, signsame, temp; - - sign=0; - - if((height_x<0 && width_z<0) || (height_x>=0 && width_z>=0)) - signsame=Yes; - else - signsame=No; - - abs_height_x=height_x; - if(abs_height_x<0) abs_height_x=-abs_height_x; - - abs_width_z=width_z; - if(abs_width_z<0) abs_width_z=-abs_width_z; - -/* - - Find ATN - -*/ - - if(width_z==0) angle=-deg90; - - else if(abs_width_z==abs_height_x) - angle=deg45; - - else { - - if(abs_width_z>abs_height_x) { - temp=abs_width_z; - abs_width_z=abs_height_x; - abs_height_x=temp; - sign=-1; - } - - if(abs_height_x!=0) - - /* angle = (abs_width_z << 8) / abs_height_x; */ - - - - angle = DIV_INT((abs_width_z << 8), abs_height_x); - - - - - - else - angle=deg22pt5; - - angle=ArcTanTable[angle]; - - if(sign>=0) { - angle=-angle; - angle+=deg90; - } - - } - - if(signsame==No) angle=-angle; - - if(width_z<=0) angle+=deg180; - - angle&=wrap360; - - return(angle); - -} - - -/* - - Matrix from Z-Vector - -*/ - -void MatrixFromZVector(VECTORCH *v, MATRIXCH *m) - -{ - - VECTORCH XVector; - VECTORCH YVector; - - VECTORCH zero = {0, 0, 0}; - - - XVector.vx = v->vz; - XVector.vy = 0; - XVector.vz = -v->vx; - - Normalise(&XVector); - - MakeNormal(&zero, &XVector, v, &YVector); - - m->mat11 = XVector.vx; - m->mat12 = XVector.vy; - m->mat13 = XVector.vz; - - m->mat21 = -YVector.vx; - m->mat22 = -YVector.vy; - m->mat23 = -YVector.vz; - - m->mat31 = v->vx; - m->mat32 = v->vy; - m->mat33 = v->vz; - -} - - - - - - - - - - -/* - - Distance Functions - -*/ - - -/* - - Foley and Van Dam 2d distance function - - WARNING! Returns distance x 3 - - Here is the F & VD distance function: - - x + z + (max(x,z) * 2) - ---------------------- - 3 - -*/ - -int FandVD_Distance_2d(VECTOR2D *v0, VECTOR2D *v1) - -{ - - int max; - int d; - - - int dx = v1->vx - v0->vx; - int dy = v1->vy - v0->vy; - - if(dx < 0) dx = -dx; - if(dy < 0) dy = -dy; - - if(dx > dy) max = dx; - else max = dy; - - d = (dx + dy + (max * 2)); - - return d; - -} - - -/* - - Foley and Van Dam 3d distance function - - WARNING! Returns distance x 9 - - For a 3d version, calculate (f(f(x,y), y*3))/9 - -*/ - -int FandVD_Distance_3d(VECTORCH *v0, VECTORCH *v1) - -{ - - int dxy, max; - - int dz = v1->vz - v0->vz; - - if(dz < 0) dz = -dz; - - dz *= 3; - - dxy = FandVD_Distance_2d((VECTOR2D *) v0, (VECTOR2D *) v1); - - if(dxy > dz) max = dxy; - else max = dz; - - return (dxy + dz + (max * 2)); - -} - - -/* - - NextLowPower2() returns the next lowest power of 2 of the passed value. - - e.g. 18 is returned as 16. - -*/ - -int NextLowPower2(int i) - -{ - - int n = 1; - - - while(n <= i) - n <<= 1; - - return n >> 1; - -} - - -/* - - Transform a world location into the local space of the passed matrix and - location. - - Vector v1 is transformed to v2 - It is made relative to vector v3 and rotated using matrix m transposed - - A possible use is the transformation of world points into the local space - of a display block - - e.g. - - MakeVectorLocal(&v1, &v2, &dptr->ObWorld, &dptr->ObMat); - - This would place vector v2 into the local space of display block dptr - -*/ - -void MakeVectorLocal(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3, MATRIXCH *m) - -{ - - MATRIXCH transmat; - - - CopyMatrix(m, &transmat); - TransposeMatrixCH(&transmat); - - v2->vx = v1->vx - v3->vx; - v2->vy = v1->vy - v3->vy; - v2->vz = v1->vz - v3->vz; - - RotateVector(v2, &transmat); - -} - - - - - -/* - - Returns "Yes" if "point" is inside "polygon" - - - ************************************************** - - WARNING!! Point and Polygon Data are OVERWRITTEN!! - - ************************************************** - - - The function requires point to be an integer array containing a single - XY pair. The number of points must be passed too. - - Pass the size of the polygon point e.g. A Gouraud polygon has points X,Y,I - so its point size would be 3. - - - Item Polygon Point Size - ---- ------------------ - - I_Polygon 2 - I_GouraudPolygon 3 - I_2dTexturedPolygon 4 - I_3dTexturedPolygon, 5 - I_Gouraud2dTexturedPolygon 5 - I_Polygon_ZBuffer 3 - I_GouraudPolygon_ZBuffer 4 - - - PASS ONLY POSITIVE COORDINATES! - -*/ - -int PointInPolygon(int *point, int *polygon, int c, int ppsize) - -{ - - - #if UseTimsPinp - - - /* Tim's New Point In Polygon test-- hopefully much faster, */ - /* certainly much smaller. */ - /* Uses Half-Line test for point-in-2D-polygon test */ - /* Tests the half-line going from the point in the direction of positive z */ - - int x, z; /* point */ - int sx, sz; /* vertex 1 */ - int *polyp; /* vertex 2 pointer */ - int t; - int dx, dz; /* ABS(vertex 2 - vertex 1) */ - int sgnx; /* going left or going right */ - int intersects; /* number of intersections so far discovered */ - LONGLONGCH a_ll, b_ll; - - /* reject lines and points */ - if (c < 3) return(No); - - intersects = 0; - - x = point[ix]; - z = point[iy]; /* ! */ - - /* get last point */ - polyp = polygon + ((c - 1) * ppsize); - sx = polyp[0]; - sz = polyp[1]; - - /* go back to first point */ - polyp = polygon; - - /* for each point */ - while (0 != c) - { - /* is this line straddling the x co-ordinate of the point? */ - /* if not it is not worth testing for intersection with the half-line */ - /* we must be careful to get the strict and non-stict inequalities */ - /* correct, or we may count intersections with vertices the wrong number */ - /* of times. */ - sgnx = 0; - if (sx < x && x <= polyp[0]) - { - /* going right */ - sgnx = 1; - dx = polyp[0] - sx; - } - if (polyp[0] < x && x <= sx) - { - /* going left */ - sgnx = -1; - dx = sx - polyp[0]; - } - - /* if sgnx is zero then neither of the above conditions are true, */ - /* hence the line does not straddle the point in x */ - if (0 != sgnx) - { - /* next do trivial cases of line totally above or below point */ - if (z < sz && z < polyp[1]) - { - /* line totally above point -- intersection */ - intersects++; - } - else if (z <= sz || z <= polyp[1]) - { - /* line straddles point in both x and z -- we must do interpolation */ - - /* get absolute differences between line end z co-ordinates */ - dz = (sz < polyp[1])?(polyp[1] - sz):(sz - polyp[1]); - - /* B504 is the square root of 7FFFFFFF */ - if (0xB504L < dx || 0xB504L < dz) - { - /* LARGE line -- use 64-bit values */ - /* interpolate z */ - MUL_I_WIDE(polyp[1] - sz, x - sx, &a_ll); - MUL_I_WIDE(polyp[0] - sx, z - sz, &b_ll); - if(CMP_LL(&a_ll, &b_ll) == sgnx) - { - /* we have an intersection */ - intersects++; - } - } - else - { - /* small line -- use 32-bit values */ - /* interpolate z */ - t = (polyp[1] - sz) * (x - sx) - (polyp[0] - sx) * (z - sz); - if (t < 0 && sgnx < 0 || 0 < t && 0 < sgnx) - { - /* we have an intersection */ - intersects++; - } - } - } /* (if line straddles point in z) */ - } /* (if line straddles point in x) */ - - /* get next line : */ - /* new vertex 1 is old vertex 2 */ - sx = polyp[0]; - sz = polyp[1]; - - /* new vertex 2 is next point */ - polyp += ppsize; - - /* next vertex */ - c--; - } - - if (intersects & 1) - { - /* Odd number of intersections -- point is inside polygon */ - return(Yes); - } - else - { - /* even number of intersections -- point is outside polygon */ - return(No); - } - - - -#else - - - int i; - int si, ti; - int s0, t0; - int s1, t1; - int *v0; - int *v1; - int ivdot, ivdotcnt, sgn_currivdot, sgn_ivdot, ivstate; - int ns, nt; - int x_scale, y_scale; - int DotNudge; - - int x, z; - LONGLONGCH xx; - LONGLONGCH zz; - LONGLONGCH xx_tmp; - LONGLONGCH zz_tmp; - VECTORCH PolyAvgPt; - - - /* Reject points and lines */ - - if(c < 3) return No; - - - /* Find the average point */ - - v0 = polygon; - - EQUALS_LL(&xx, &ll_zero); - EQUALS_LL(&zz, &ll_zero); - - for(i = c; i!=0; i--) { - - x = v0[0]; - z = v0[1]; - - IntToLL(&xx_tmp, &x); /* xx_tmp = (long long)x */ - IntToLL(&zz_tmp, &z); /* zz_tmp = (long long)z */ - - ADD_LL_PP(&xx, &xx_tmp); /* xx += xx_tmp */ - ADD_LL_PP(&zz, &zz_tmp); /* zz += zz_tmp */ - - v0 += ppsize; - - } - - PolyAvgPt.vx = NarrowDivide(&xx, c); - PolyAvgPt.vz = NarrowDivide(&zz, c); - - - /* Centre the polygon */ - - v0 = polygon; - - for(i = c; i!=0; i--) { - - v0[0] -= PolyAvgPt.vx; - v0[1] -= PolyAvgPt.vz; - - v0 += ppsize; - - } - - - /* Centre the test point */ - - point[0] -= PolyAvgPt.vx; - point[1] -= PolyAvgPt.vz; - - - /* Scale to avoid maths overflow */ - - v0 = polygon; - - s0 = 0; - t0 = 0; - - for(i = c; i!=0; i--) { - - si = v0[0]; if(si < 0) si = -si; - if(si > s0) s0 = si; - - ti = v0[1]; if(ti < 0) ti = -ti; - if(ti > t0) t0 = ti; - - v0 += ppsize; - - } - - si = point[ix]; if(si < 0) si = -si; - if(si > s0) s0 = si; - - ti = point[iy]; if(ti < 0) ti = -ti; - if(ti > t0) t0 = ti; - - - #if 0 - textprint("\nmax x = %d\n", s0); - textprint("max y = %d\n", t0); - #endif - - - x_scale = FindShift32(s0, 16383); - y_scale = FindShift32(t0, 16383); - - - #if 0 - textprint("scales = %d, %d\n", x_scale, y_scale); - #endif - - - v0 = polygon; - - for(i = c; i!=0; i--) { - - v0[0] >>= x_scale; - v0[1] >>= y_scale; - - /*textprint("(%d, %d)\n", v0[0], v0[1]);*/ - - v0 += ppsize; - - } - - point[ix] >>= x_scale; - point[iy] >>= y_scale; - - - - -#if 1 - - /* Clockwise or Anti-Clockwise? */ - - ns = -(polygon[iy + ppsize] - polygon[iy]); - nt = (polygon[ix + ppsize] - polygon[ix]); - - si = polygon[(ppsize*2) + ix] - polygon[ix]; - ti = polygon[(ppsize*2) + iy] - polygon[iy]; - - ivdot = (ns * si) + (nt * ti); - - if(ivdot < 0) DotNudge = -1; - else DotNudge = 1; - -#endif - - - - #if 0 - if(ivdot < 0) textprint("Clockwise\n"); - WaitForReturn(); - #endif - - - /* Point to test */ - - si = point[ix]; - ti = point[iy]; - - - #if 0 - textprint("p_test %d, %d\n", si, ti); - #endif - - - /* Polygon Vector pointers */ - - v0 = polygon; - v1 = v0 + ppsize; - - - /* Dot result monitor */ - - ivdotcnt = 0; - ivstate = Yes; /* assume inside */ - - - /* Test v(s, t) against the vectors */ - - for(i = c; i!=0 && ivstate == Yes; i--) { - - - /* second vector pointer wraps once */ - - if(i == 1) v1 = polygon; - - - /* get the vector */ - - s0 = v0[ix]; - t0 = v0[iy]; - - s1 = v1[ix]; - t1 = v1[iy]; - - - #if 0 - textprint("%d,%d; %d,%d\n", s0, t0, s1, t1); - #endif - - - /* get the vector normal */ - - ns = -(t1 - t0); /* s -> -t */ - nt = s1 - s0; /* t -> s */ - - - /* Dot with intersection point */ - - ivdot = (ns * (si - s0)) + (nt * (ti - t0)); - - - /* TEST */ - ivdot += DotNudge; - - - sgn_ivdot = 1; - if(ivdot < 0) sgn_ivdot = -1; - - - /* only continue if current dot is same as last, else quit */ - - if(ivdotcnt == 0) sgn_currivdot = sgn_ivdot; - - else { - - if(sgn_ivdot != sgn_currivdot) ivstate = No; - sgn_currivdot = sgn_ivdot; - - } - - v0 += ppsize; - v1 += ppsize; - - ivdotcnt++; - - } - - if(ivstate) return Yes; - else return No; - - -#endif - - -} - - - - - - - -/* - - #defines and statics required for Jamie's Most Excellent - random number generator - -*/ - -#define DEG_3 31 -#define SEP_3 3 - -static long table [DEG_3] = -{ - -851904987, -43806228, -2029755270, 1390239686, -1912102820, - -485608943, 1969813258, -1590463333, -1944053249, 455935928, - 508023712, -1714531963, 1800685987, -2015299881, 654595283, - -1149023258, -1470005550, -1143256056, -1325577603, -1568001885, - 1275120390, -607508183, -205999574, -1696891592, 1492211999, - -1528267240, -952028296, -189082757, 362343714, 1424981831, - 2039449641 -}; - -#define TABLE_END (table + sizeof (table) / sizeof (table [0])) - -static long * front_ptr = table + SEP_3; -static long * rear_ptr = table; - - -/* - This code (FastRandom and SetFastRandom) stolen from Jamie Lokier - September 95. The original version was part of a C library - implementation -*/ - - -/* This is derived from the GNU C library source, which is in turn - derived from Berkeley source. The algorithm, the polynomial, and the - initial numbers are the same, but the code has been reworked for the - needs of this version. - - This version doesn't support different types of random number - generators, or saving and restoring the state. It is fast, short and - as simple as it can be while still generating numbers as good as the - Berkeley one. The basic algorithm is to have a linear-feedback shift - register, whose bits are the least significant bits of each word in - the `table' array. The higher-order bits are generated by carries - from the arithmetic on the shift register bits, and have an even - longer period than the shift register. */ - -/* x**31 + x**3 + 1. */ - -void SetSeededFastRandom(int seed); -void SetFastRandom(void) - -{ - - int i; - long number = GetTickCount(); - - - for(i = 0; i < DEG_3; ++i) { - - number = 1103515145 * number + 12345; - table[i] = number; - - } - - front_ptr = table + SEP_3; - rear_ptr = table; - - for(i = 0; i < 10 * DEG_3; ++i) - (void) FastRandom (); - - SetSeededFastRandom(FastRandom()); - -} - - -int FastRandom(void) - -{ - - long i; - - /* - - Discard least random bit. - Shift as unsigned to avoid replicating sign bit. - Faster than masking. - - */ - - *front_ptr += *rear_ptr; - i = (long) ((unsigned long) *front_ptr >> 1); - - /* `front_ptr' and `rear_ptr' can't wrap at the same time. */ - - ++front_ptr; - - if(front_ptr < TABLE_END) { - - ++rear_ptr; - - if (rear_ptr < TABLE_END) return i; - - rear_ptr = table; - - } - - else { /* front_ptr >= TABLE_END */ - - front_ptr = table; - ++rear_ptr; - - } - - return (int) i; - -} - -/*a second copy of the random number generator for getting random numbers from a single seed*/ - -#define SEEDED_DEG_3 13 -#define SEEDED_SEP_3 3 - -static long seeded_table [SEEDED_DEG_3]; - -#define SEEDED_TABLE_END (seeded_table + sizeof (seeded_table) / sizeof (seeded_table [0])) - -static long * seeded_front_ptr = seeded_table + SEEDED_SEP_3; -static long * seeded_rear_ptr = seeded_table; - - - -int SeededFastRandom(void) - -{ - - long i; - - /* - - Discard least random bit. - Shift as unsigned to avoid replicating sign bit. - Faster than masking. - - */ - - *seeded_front_ptr += *seeded_rear_ptr; - i = (long) ((unsigned long) *seeded_front_ptr >> 1); - - /* `front_ptr' and `rear_ptr' can't wrap at the same time. */ - - ++seeded_front_ptr; - - if(seeded_front_ptr < SEEDED_TABLE_END) { - - ++seeded_rear_ptr; - - if (seeded_rear_ptr < SEEDED_TABLE_END) return i; - - seeded_rear_ptr = seeded_table; - - } - - else { /* front_ptr >= TABLE_END */ - - seeded_front_ptr = seeded_table; - ++seeded_rear_ptr; - - } - - return (int) i; - -} - -void SetSeededFastRandom(int seed) - -{ - - int i; - long number = seed; - - - for(i = 0; i < SEEDED_DEG_3; ++i) { - - number = 1103515145 * number + 12345; - seeded_table[i] = number; - - } - - seeded_front_ptr = seeded_table + SEEDED_SEP_3; - seeded_rear_ptr = seeded_table; - - for(i = 0; i < 2 * SEEDED_DEG_3; ++i) - (void) SeededFastRandom (); - -} - -#if StandardShapeLanguage - -/* - - Calculate the average point on this polygon - -*/ - -void PolyAveragePoint(POLYHEADER *pheader, int *spts, VECTORCH *apt) - -{ - - int x, y, z; - LONGLONGCH xx; - LONGLONGCH yy; - LONGLONGCH zz; - LONGLONGCH xx_tmp; - LONGLONGCH yy_tmp; - LONGLONGCH zz_tmp; - int *mypolystart = &pheader->Poly1stPt; - int numpolypts; - - - /* Find the average point */ - - EQUALS_LL(&xx, &ll_zero); - EQUALS_LL(&yy, &ll_zero); - EQUALS_LL(&zz, &ll_zero); - - numpolypts = 0; - - while(*mypolystart != Term) { - - x = *(spts + *mypolystart + ix); - y = *(spts + *mypolystart + iy); - z = *(spts + *mypolystart + iz); - - IntToLL(&xx_tmp, &x); /* xx_tmp = (long long)x */ - IntToLL(&yy_tmp, &y); /* yy_tmp = (long long)y */ - IntToLL(&zz_tmp, &z); /* zz_tmp = (long long)z */ - - ADD_LL_PP(&xx, &xx_tmp); /* xx += xx_tmp */ - ADD_LL_PP(&yy, &yy_tmp); /* yy += yy_tmp */ - ADD_LL_PP(&zz, &zz_tmp); /* zz += zz_tmp */ - - numpolypts++; - mypolystart++; - - } - - apt->vx = NarrowDivide(&xx, numpolypts); - apt->vy = NarrowDivide(&yy, numpolypts); - apt->vz = NarrowDivide(&zz, numpolypts); - -} - -#endif /* StandardShapeLanguage */ - - - - - - -/* KJL 15:07:39 01/08/97 - Returns the magnitude of the - cross product of two vectors a and b. */ -int MagnitudeOfCrossProduct(VECTORCH *a, VECTORCH *b) - -{ - VECTORCH c; - - c.vx = MUL_FIXED(a->vy,b->vz) - MUL_FIXED(a->vz,b->vy); - c.vy = MUL_FIXED(a->vz,b->vx) - MUL_FIXED(a->vx,b->vz); - c.vz = MUL_FIXED(a->vx,b->vy) - MUL_FIXED(a->vy,b->vx); - - return Magnitude(&c); -} - -/* KJL 15:08:01 01/08/97 - sets the vector c to be the - cross product of the vectors a and b. */ -void CrossProduct(VECTORCH *a, VECTORCH *b, VECTORCH *c) - -{ - c->vx = MUL_FIXED(a->vy,b->vz) - MUL_FIXED(a->vz,b->vy); - c->vy = MUL_FIXED(a->vz,b->vx) - MUL_FIXED(a->vx,b->vz); - c->vz = MUL_FIXED(a->vx,b->vy) - MUL_FIXED(a->vy,b->vx); -} - - - -/* KJL 12:01:08 7/16/97 - returns the magnitude of a vector - max error about 13%, though average error -less than half this. Very fast compared to other approaches. */ -int Approximate3dMagnitude(VECTORCH *v) -{ - int dx,dy,dz; - - dx = v->vx; - if (dx<0) dx = -dx; - - dy = v->vy; - if (dy<0) dy = -dy; - - dz = v->vz; - if (dz<0) dz = -dz; - - - if (dx>dy) - { - if (dx>dz) - { - return dx + ((dy+dz)>>2); - } - else - { - return dz + ((dy+dx)>>2); - } - } - else - { - if (dy>dz) - { - return dy + ((dx+dz)>>2); - } - else - { - return dz + ((dx+dy)>>2); - } - } -} - - -/* - - Quaternion to Matrix - - This is the column(row) matrix that is produced. Our matrices are - row(column) and so are a transpose of this. - - 1 - 2yy - 2zz 2xy + 2wz 2xz - 2wy - - 2xy - 2wz 1 - 2xx - 2zz 2yz + 2wx - - 2xz + 2wy 2yz - 2wx 1 - 2xx - 2yy - -*/ - -void QuatToMat(QUAT *q,MATRIXCH *m) -{ - - int q_w, q_x, q_y, q_z; - - int q_2x, q_2y, q_2z; - - int q_2xw; - int q_2xx; - int q_2xy; - int q_2xz; - int q_2yw; - int q_2yy; - int q_2yz; - int q_2zw; - int q_2zz; - -/* - - The most efficient way to create the matrix is as follows - - 1/ Double x, y & z - -*/ - - q_w=q->quatw; - q_x=q->quatx; - q_y=q->quaty; - q_z=q->quatz; - - q_2x=q_x*2; - q_2y=q_y*2; - q_2z=q_z*2; - -/* - - 2/ Form their products with w, x, y & z - These are - - (2x)w (2y)w (2z)w - (2x)x - (2x)y (2y)y - (2x)z (2y)z (2z)z - -*/ - - q_2xw=MUL_FIXED(q_2x,q_w); - q_2yw=MUL_FIXED(q_2y,q_w); - q_2zw=MUL_FIXED(q_2z,q_w); - - q_2xx=MUL_FIXED(q_2x,q_x); - - q_2xy=MUL_FIXED(q_2x,q_y); - q_2yy=MUL_FIXED(q_2y,q_y); - - q_2xz=MUL_FIXED(q_2x,q_z); - q_2yz=MUL_FIXED(q_2y,q_z); - q_2zz=MUL_FIXED(q_2z,q_z); - - -/* mat11 = 1 - 2y^2 - 2z^2 */ - - m->mat11=ONE_FIXED-q_2yy-q_2zz; - -/* mat12 = 2xy - 2wz */ - - m->mat12=q_2xy-q_2zw; - -/* mat13 = 2xz + 2wy */ - - m->mat13=q_2xz+q_2yw; - -/* mat21 = 2xy + 2wz */ - - m->mat21=q_2xy+q_2zw; - -/* mat22 = 1 - 2x^2 - 2z^2 */ - - m->mat22=ONE_FIXED-q_2xx-q_2zz; - -/* mat23 = 2yz - 2wx */ - - m->mat23=q_2yz-q_2xw; - -/* mat31 = 2xz - 2wy */ - - m->mat31=q_2xz-q_2yw; - -/* mat32 = 2yz + 2wx */ - - m->mat32=q_2yz+q_2xw; - -/* mat33 = 1 - 2x^2 - 2y^2 */ - - m->mat33=ONE_FIXED-q_2xx-q_2yy; - -} - |
