summaryrefslogtreecommitdiff
path: root/3dc/Maths.c
diff options
context:
space:
mode:
Diffstat (limited to '3dc/Maths.c')
-rw-r--r--3dc/Maths.c2944
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;
-
-}
-