
Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format.
2944 lines
44 KiB
C
2944 lines
44 KiB
C
|
||
#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<39> 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<39> */
|
||
|
||
if(dotxy > dotxz && dotxy > dotyz) {
|
||
|
||
/* xy are the closest to 90<39> */
|
||
|
||
/*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<39> */
|
||
|
||
/*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<39> */
|
||
|
||
/*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<30> is Map North
|
||
090<39> is Map East
|
||
180<38> is Map South
|
||
270<37> 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;
|
||
|
||
}
|
||
|