avp/3dc/win95/plspecfn.c

1476 lines
24 KiB
C
Raw Normal View History

#include "3dc.h"
#include <math.h>
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "pvisible.h"
#if SupportWindows95
#include "krender.h" /* KJL 10:48:25 02/05/97 */
#include "kzsort.h"
#include "kshape.h"
#endif
/*
Platform Specific Functions
These functions have been written specifically for a given platform.
They are not necessarily IO or inline functions; these have their own files.
*/
/*
externs for commonly used global variables and arrays
*/
extern VECTORCH RotatedPts[];
extern unsigned int Outcodes[];
extern DISPLAYBLOCK *Global_ODB_Ptr;
extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
extern SHAPEHEADER *Global_ShapeHeaderPtr;
extern MATRIXCH LToVMat;
#if SupportMorphing
extern VECTORCH MorphedPts[];
extern MORPHDISPLAY MorphDisplay;
#endif
extern DISPLAYBLOCK *OnScreenBlockList[];
extern int NumOnScreenBlocks;
extern int NumActiveBlocks;
extern DISPLAYBLOCK *ActiveBlockList[];
#if SupportModules
extern char *ModuleLocalVisArray;
#endif
/*
Global Variables
*/
LONGLONGCH ll_one14 = {one14, 0};
LONGLONGCH ll_zero = {0, 0};
/*
Find out which objects are in the View Volume.
The list of these objects, "OnScreenBlockList", is constructed in a number
of stages.
The Range Test is a simple outcode of the View Space Location against the
Object Radius. The View Volume Test is more involved. The VSL is tested
against each of the View Volume Planes. If it is more than one Object Radius
outside any plane, the test fails.
*/
/*
This is the main view volume test shell
*/
#if StandardShapeLanguage
/*
Shape Points
The item array is a table of pointers to item arrays. The points data is
in the first and only item array.
Rotate each point and write it out to the Rotated Points Buffer
NOTE:
There is a global pointer to the shape header "Global_ShapeHeaderPtr"
*/
#define print_bfcro_stats No
#if SupportMorphing
#define checkmorphpts No
#endif
void ShapePointsInstr(SHAPEINSTR *shapeinstrptr)
{
int **shapeitemarrayptr;
int *shapeitemptr;
VECTORCH *rotptsptr;
int x, y, z;
int numitems;
#if print_bfcro_stats
int num_rot, num_not_rot;
#endif
/*
Kevin, morphed doors WON'T be using shared points, so I've put your
patch here, AFTER the intercept for the shared version of the points
instruction -- Chris.
*/
#if KZSORT_ON /* KJL 15:13:46 02/07/97 - used for z-sorting doors correctly! */
{
extern int *MorphedObjectPointsPtr;
MorphedObjectPointsPtr = 0;
}
#endif
/* Set up pointers */
shapeitemarrayptr = shapeinstrptr->sh_instr_data;
shapeitemptr = *shapeitemarrayptr;
rotptsptr = &RotatedPts[0];
#if SupportMorphing
if(Global_ODB_Ptr->ObMorphCtrl) {
#if LazyEvaluationForMorphing
VECTORCH *morphptsptr;
if(Global_ODB_Ptr->ObMorphedPts == 0) {
Global_ODB_Ptr->ObMorphedPts = GetMorphedPts(Global_ODB_Ptr,
&MorphDisplay);
}
morphptsptr = Global_ODB_Ptr->ObMorphedPts;
GLOBALASSERT(shapeinstrptr->sh_numitems<maxmorphPts);
for(numitems = shapeinstrptr->sh_numitems; numitems!=0; numitems--) {
#if SUPPORT_MMX
if (use_mmx_math)
MMX_VectorTransformedAndAdd(rotptsptr,morphptsptr,&LToVMat,&Global_ODB_Ptr->ObView);
else
#endif
{
rotptsptr->vx = MUL_FIXED(LToVMat.mat11, morphptsptr->vx);
rotptsptr->vx += MUL_FIXED(LToVMat.mat21, morphptsptr->vy);
rotptsptr->vx += MUL_FIXED(LToVMat.mat31, morphptsptr->vz);
rotptsptr->vx += Global_ODB_Ptr->ObView.vx;
rotptsptr->vy = MUL_FIXED(LToVMat.mat12, morphptsptr->vx);
rotptsptr->vy += MUL_FIXED(LToVMat.mat22, morphptsptr->vy);
rotptsptr->vy += MUL_FIXED(LToVMat.mat32, morphptsptr->vz);
rotptsptr->vy += Global_ODB_Ptr->ObView.vy;
rotptsptr->vz = MUL_FIXED(LToVMat.mat13, morphptsptr->vx);
rotptsptr->vz += MUL_FIXED(LToVMat.mat23, morphptsptr->vy);
rotptsptr->vz += MUL_FIXED(LToVMat.mat33, morphptsptr->vz);
rotptsptr->vz += Global_ODB_Ptr->ObView.vz;
}
rotptsptr->vy = MUL_FIXED(rotptsptr->vy,87381);
morphptsptr++;
rotptsptr++;
}
#else /* LazyEvaluationForMorphing */
VECTORCH *morphptsptr = &MorphedPts[0];
SHAPEHEADER *sptr1;
SHAPEHEADER *sptr2;
int *shapeitemptr1;
int *shapeitemptr2;
int x1, y1, z1;
int x2, y2, z2;
#if checkmorphpts
int num_old_pts = 0;
int num_new_pts = 0;
#endif
/*textprint("morphing points\n");*/
sptr1 = MorphDisplay.md_sptr1;
sptr2 = MorphDisplay.md_sptr2;
shapeitemptr1 = *(sptr1->points);
shapeitemptr2 = *(sptr2->points);
#if KZSORT_ON /* KJL 15:13:46 02/07/97 - used for z-sorting doors correctly! */
{
extern int *MorphedObjectPointsPtr;
MorphedObjectPointsPtr = shapeitemptr2;
}
#endif
for(numitems = shapeinstrptr->sh_numitems; numitems!=0; numitems--) {
x1 = shapeitemptr1[ix];
y1 = shapeitemptr1[iy];
z1 = shapeitemptr1[iz];
x2 = shapeitemptr2[ix];
y2 = shapeitemptr2[iy];
z2 = shapeitemptr2[iz];
if(x1 == x2 && y1 == y2 && z1 == z2) {
x = x1;
y = y1;
z = z1;
#if checkmorphpts
num_old_pts++;
#endif
}
else if(MorphDisplay.md_lerp == 0) {
x = x1;
y = y1;
z = z1;
}
else if(MorphDisplay.md_lerp == 0xffff) {
x = x2;
y = y2;
z = z2;
}
else
{
/* KJL 15:27:20 05/22/97 - I've changed this to speed things up, If a vertex
component has a magnitude greater than 32768 things will go wrong. */
x = x1 + (((x2-x1)*MorphDisplay.md_lerp)>>16);
y = y1 + (((y2-y1)*MorphDisplay.md_lerp)>>16);
z = z1 + (((z2-z1)*MorphDisplay.md_lerp)>>16);
#if checkmorphpts
num_new_pts++;
#endif
}
morphptsptr->vx = x;
morphptsptr->vy = y;
morphptsptr->vz = z;
/* KJL 16:07:15 11/27/97 - I know this test is inside the loop,
but all this will go when I change to float everywhere. */
#if MIRRORING_ON
if(!Global_ODB_Ptr->ObMyModule || MirroringActive)
#else
if (!Global_ODB_Ptr->ObMyModule)
#endif
{
#if SUPPORT_MMX
if (use_mmx_math)
MMX_VectorTransformedAndAdd(rotptsptr,morphptsptr,&LToVMat,&Global_ODB_Ptr->ObView);
else
#endif
{
rotptsptr->vx = MUL_FIXED(LToVMat.mat11, x);
rotptsptr->vx += MUL_FIXED(LToVMat.mat21, y);
rotptsptr->vx += MUL_FIXED(LToVMat.mat31, z);
rotptsptr->vx += Global_ODB_Ptr->ObView.vx;
rotptsptr->vy = MUL_FIXED(LToVMat.mat12, x);
rotptsptr->vy += MUL_FIXED(LToVMat.mat22, y);
rotptsptr->vy += MUL_FIXED(LToVMat.mat32, z);
rotptsptr->vy += Global_ODB_Ptr->ObView.vy;
rotptsptr->vz = MUL_FIXED(LToVMat.mat13, x);
rotptsptr->vz += MUL_FIXED(LToVMat.mat23, y);
rotptsptr->vz += MUL_FIXED(LToVMat.mat33, z);
rotptsptr->vz += Global_ODB_Ptr->ObView.vz;
}
}
else /* KJL 14:33:24 11/27/97 - experiment to get rid of tears */
{
x += Global_ODB_Ptr->ObWorld.vx - Global_VDB_Ptr->VDB_World.vx;
y += Global_ODB_Ptr->ObWorld.vy - Global_VDB_Ptr->VDB_World.vy;
z += Global_ODB_Ptr->ObWorld.vz - Global_VDB_Ptr->VDB_World.vz;
rotptsptr->vx = MUL_FIXED(LToVMat.mat11, x);
rotptsptr->vx += MUL_FIXED(LToVMat.mat21, y);
rotptsptr->vx += MUL_FIXED(LToVMat.mat31, z);
rotptsptr->vy = MUL_FIXED(LToVMat.mat12, x);
rotptsptr->vy += MUL_FIXED(LToVMat.mat22, y);
rotptsptr->vy += MUL_FIXED(LToVMat.mat32, z);
rotptsptr->vz = MUL_FIXED(LToVMat.mat13, x);
rotptsptr->vz += MUL_FIXED(LToVMat.mat23, y);
rotptsptr->vz += MUL_FIXED(LToVMat.mat33, z);
}
shapeitemptr1 += vsize;
shapeitemptr2 += vsize;
morphptsptr++;
rotptsptr->vy = MUL_FIXED(rotptsptr->vy,87381);
rotptsptr++;
}
#if checkmorphpts
textprint("num_old_pts = %d\n", num_old_pts);
textprint("num_new_pts = %d\n", num_new_pts);
#endif
#endif /* LazyEvaluationForMorphing */
}
else {
#endif
#if MIRRORING_ON
int useFirstMethod = 0;
if(!Global_ODB_Ptr->ObMyModule || MirroringActive)
{
useFirstMethod = 1;
}
if (Global_ODB_Ptr->ObStrategyBlock)
{
#if 0
if(Global_ODB_Ptr->ObStrategyBlock->I_SBtype == I_BehaviourInanimateObject)
{
INANIMATEOBJECT_STATUSBLOCK* osPtr = Global_ODB_Ptr->ObStrategyBlock->SBdataptr;
if(osPtr->typeId==IOT_Static)
{
useFirstMethod=0;
}
}
#endif
}
if(useFirstMethod)
#else
if (!Global_ODB_Ptr->ObMyModule)
#endif
{
for(numitems = shapeinstrptr->sh_numitems; numitems!=0; numitems--)
{
#if SUPPORT_MMX
if (use_mmx_math)
MMX_VectorTransformedAndAdd(rotptsptr,(VECTORCH *)shapeitemptr,&LToVMat,&Global_ODB_Ptr->ObView);
else
#endif
{
x = shapeitemptr[ix];
y = shapeitemptr[iy];
z = shapeitemptr[iz];
rotptsptr->vx = MUL_FIXED(LToVMat.mat11, x);
rotptsptr->vx += MUL_FIXED(LToVMat.mat21, y);
rotptsptr->vx += MUL_FIXED(LToVMat.mat31, z);
rotptsptr->vx += Global_ODB_Ptr->ObView.vx;
rotptsptr->vy = MUL_FIXED(LToVMat.mat12, x);
rotptsptr->vy += MUL_FIXED(LToVMat.mat22, y);
rotptsptr->vy += MUL_FIXED(LToVMat.mat32, z);
rotptsptr->vy += Global_ODB_Ptr->ObView.vy;
rotptsptr->vz = MUL_FIXED(LToVMat.mat13, x);
rotptsptr->vz += MUL_FIXED(LToVMat.mat23, y);
rotptsptr->vz += MUL_FIXED(LToVMat.mat33, z);
rotptsptr->vz += Global_ODB_Ptr->ObView.vz;
}
shapeitemptr += 3;
rotptsptr->vy = MUL_FIXED(rotptsptr->vy,87381);
rotptsptr++;
}
}
else
{
/* KJL 14:33:24 11/27/97 - experiment to get rid of tears */
for(numitems = shapeinstrptr->sh_numitems; numitems!=0; numitems--)
{
x = shapeitemptr[ix];
y = shapeitemptr[iy];
z = shapeitemptr[iz];
x += Global_ODB_Ptr->ObWorld.vx - Global_VDB_Ptr->VDB_World.vx;
y += Global_ODB_Ptr->ObWorld.vy - Global_VDB_Ptr->VDB_World.vy;
z += Global_ODB_Ptr->ObWorld.vz - Global_VDB_Ptr->VDB_World.vz;
rotptsptr->vx = MUL_FIXED(LToVMat.mat11, x);
rotptsptr->vx += MUL_FIXED(LToVMat.mat21, y);
rotptsptr->vx += MUL_FIXED(LToVMat.mat31, z);
rotptsptr->vy = MUL_FIXED(LToVMat.mat12, x);
rotptsptr->vy += MUL_FIXED(LToVMat.mat22, y);
rotptsptr->vy += MUL_FIXED(LToVMat.mat32, z);
rotptsptr->vz = MUL_FIXED(LToVMat.mat13, x);
rotptsptr->vz += MUL_FIXED(LToVMat.mat23, y);
rotptsptr->vz += MUL_FIXED(LToVMat.mat33, z);
shapeitemptr += 3;
rotptsptr->vy = MUL_FIXED(rotptsptr->vy,87381);
rotptsptr++;
}
}
#if SupportMorphing
}
#endif
}
#endif /* StandardShapeLanguage */
/*
WideMul2NarrowDiv
This function takes two pairs of integers, adds their 64-bit products
together, divides the summed product with another integer and then returns
the result of that divide, which is also an integer.
It is not inlined for Watcom C, although the functions it calls ARE.
*/
int WideMul2NarrowDiv(int a, int b, int c, int d, int e)
{
LONGLONGCH f;
LONGLONGCH g;
MUL_I_WIDE(a, b, &f);
MUL_I_WIDE(c, d, &g);
ADD_LL_PP(&f, &g);
return NarrowDivide(&f, e);
}
/*
Square Root
Returns the Square Root of a 32-bit number
*/
#if (SupportFPMathsFunctions || SupportFPSquareRoot)
#else
int SqRoot32(int A)
{
unsigned int edx = A;
unsigned int ecx;
unsigned int ax = 0;
unsigned int bx = 0;
unsigned int di = 0;
for(ecx = 15; ecx!=0; ecx--) {
bx <<= 1;
if(edx & 0x80000000) bx |= 1;
edx <<= 1;
bx <<= 1;
if(edx & 0x80000000) bx |= 1;
edx <<= 1;
ax += ax;
di = ax;
di += di;
if(bx > di) {
di++;
ax++;
bx -= di;
}
}
bx <<= 1;
if(edx & 0x80000000) bx |= 1;
edx <<= 1;
bx <<= 1;
if(edx & 0x80000000) bx |= 1;
edx <<= 1;
ax += ax;
di = ax;
di += di;
if(bx > di) {
ax++;
}
return ((int)ax);
}
#endif /* SupportFPMathsFunctions */
/*
Calculate Plane Normal from three POP's
The three input vectors are treated as POP's and used to make two vectors.
These are then crossed to create the normal.
Make two vectors; (2-1) & (3-1)
Cross them
Normalise the vector
Find the magnitude of the vector
Divide each component by the magnitude
*/
void MakeNormal(VECTORCH *v1, VECTORCH *v2, VECTORCH *v3, VECTORCH *v4)
{
#if SupportFPMathsFunctions
VECTORCHF vect0;
VECTORCHF vect1;
VECTORCHF n;
/* vect0 = v2 - v1 */
vect0.vx = v2->vx - v1->vx;
vect0.vy = v2->vy - v1->vy;
vect0.vz = v2->vz - v1->vz;
/* vect1 = v3 - v1 */
vect1.vx = v3->vx - v1->vx;
vect1.vy = v3->vy - v1->vy;
vect1.vz = v3->vz - v1->vz;
/* nx = v0y.v1z - v0z.v1y */
n.vx = (vect0.vy * vect1.vz) - (vect0.vz * vect1.vy);
/* ny = v0z.v1x - v0x.v1z */
n.vy = (vect0.vz * vect1.vx) - (vect0.vx * vect1.vz);
/* nz = v0x.v1y - v0y.v1x */
n.vz = (vect0.vx * vect1.vy) - (vect0.vy * vect1.vx);
FNormalise(&n);
f2i(v4->vx, n.vx * ONE_FIXED);
f2i(v4->vy, n.vy * ONE_FIXED);
f2i(v4->vz, n.vz * ONE_FIXED);
#if 0
textprint("Magnitude of v4 = %d\n", Magnitude(v4));
WaitForReturn();
#endif
#else /* SupportFPMathsFunctions */
LONGLONGCH x;
LONGLONGCH y;
LONGLONGCH z;
LONGLONGCH tmp;
VECTORCH vect0;
VECTORCH vect1;
LONGLONGCH max_abs_xyz64;
LONGLONGCH abs_xyz[3];
int s, shift;
/* vect0 = v2 - v1 */
vect0.vx = v2->vx - v1->vx;
vect0.vy = v2->vy - v1->vy;
vect0.vz = v2->vz - v1->vz;
/* vect1 = v3 - v1 */
vect1.vx = v3->vx - v1->vx;
vect1.vy = v3->vy - v1->vy;
vect1.vz = v3->vz - v1->vz;
/* nx = v0y.v1z - v0z.v1y */
#if 0
x =
(long long)vect0.vy * (long long)vect1.vz
-(long long)vect0.vz * (long long)vect1.vy;
#endif
MUL_I_WIDE(vect0.vy, vect1.vz, &x);
MUL_I_WIDE(vect0.vz, vect1.vy, &tmp);
SUB_LL_MM(&x, &tmp);
/* ny = v0z.v1x - v0x.v1z */
#if 0
y =
(long long)vect0.vz * (long long)vect1.vx
-(long long)vect0.vx * (long long)vect1.vz;
#endif
MUL_I_WIDE(vect0.vz, vect1.vx, &y);
MUL_I_WIDE(vect0.vx, vect1.vz, &tmp);
SUB_LL_MM(&y, &tmp);
/* nz = v0x.v1y - v0y.v1x */
#if 0
z =
(long long)vect0.vx * (long long)vect1.vy
-(long long)vect0.vy * (long long)vect1.vx;
#endif
MUL_I_WIDE(vect0.vx, vect1.vy, &z);
MUL_I_WIDE(vect0.vy, vect1.vx, &tmp);
SUB_LL_MM(&z, &tmp);
/* Before we can normalise we must bring these vectors down to 14-bits */
#if 0
abs_xyz[0] = x;
if(abs_xyz[0] < 0) abs_xyz[0] = -abs_xyz[0];
abs_xyz[1] = y;
if(abs_xyz[1] < 1) abs_xyz[1] = -abs_xyz[1];
abs_xyz[2] = z;
if(abs_xyz[2] < 0) abs_xyz[2] = -abs_xyz[2];
#endif
EQUALS_LL(&abs_xyz[0], &x);
s = CMP_LL(&abs_xyz[0], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[0]);
EQUALS_LL(&abs_xyz[1], &y);
s = CMP_LL(&abs_xyz[1], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[1]);
EQUALS_LL(&abs_xyz[2], &z);
s = CMP_LL(&abs_xyz[2], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[2]);
MaxLONGLONGCH(&abs_xyz[0], 3, &max_abs_xyz64);
shift = FindShift64(&max_abs_xyz64, &ll_one14);
#if 0
x >>= shift;
y >>= shift;
z >>= shift;
#endif
ASR_LL(&x, shift);
ASR_LL(&y, shift);
ASR_LL(&z, shift);
/* Watcom specific copying of lower 32-bits of LONGLONGCH values */
v4->vx = x.lo32;
v4->vy = y.lo32;
v4->vz = z.lo32;
/* Normalise the vector */
#if 0
textprint("v4 = %d,%d,%d\n", x.lo32, y.lo32, z.lo32);
textprint("v4 = %d,%d,%d\n", v4->vx, v4->vy, v4->vz);
#endif
Normalise(v4);
#if 0
textprint(" - v4 = %d,%d,%d\n", v4->vx, v4->vy, v4->vz);
#endif
#endif /* SupportFPMathsFunctions */
}
/*
Normalise a vector.
The returned vector is a fixed point unit vector.
WARNING!
The vector must be no larger than 2<<14 because of the square root.
Because this is an integer function, small components produce errors.
e.g.
(100,100,0)
m=141 (141.42)
nx = 100 * ONE_FIXED / m = 46,479
ny = 100 * ONE_FIXED / m = 46,479
nz = 0
New m ought to be 65,536 but in fact is 65,731 i.e. 0.29% too large.
*/
void Normalise(VECTORCH *nvector)
{
#if SupportFPMathsFunctions
VECTORCHF n;
float m;
n.vx = nvector->vx;
n.vy = nvector->vy;
n.vz = nvector->vz;
m = 65536.0/sqrt((n.vx * n.vx) + (n.vy * n.vy) + (n.vz * n.vz));
f2i(nvector->vx, (n.vx * m) );
f2i(nvector->vy, (n.vy * m) );
f2i(nvector->vz, (n.vz * m) );
#else /* SupportFPMathsFunctions */
int m, s;
int xsq, ysq, zsq;
LONGLONGCH max_abs_xyz64;
LONGLONGCH abs_xyz[3];
int shift;
/* Before we can normalise we must bring these vectors down to 14-bits */
IntToLL(&abs_xyz[0], &nvector->vx);
s = CMP_LL(&abs_xyz[0], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[0]);
IntToLL(&abs_xyz[1], &nvector->vy);
s = CMP_LL(&abs_xyz[1], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[1]);
IntToLL(&abs_xyz[2], &nvector->vz);
s = CMP_LL(&abs_xyz[2], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[2]);
MaxLONGLONGCH(&abs_xyz[0], 3, &max_abs_xyz64);
#if 0
textprint("value to shift = %d, %d\n", max_abs_xyz64.lo32, max_abs_xyz64.hi32);
#endif
shift = FindShift64(&max_abs_xyz64, &ll_one14);
#if 0
textprint("shift = %d\n", shift);
#endif
nvector->vx >>= shift;
nvector->vy >>= shift;
nvector->vz >>= shift;
/* 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 = WideMulNarrowDiv(nvector->vx, ONE_FIXED, m);
nvector->vy = WideMulNarrowDiv(nvector->vy, ONE_FIXED, m);
nvector->vz = WideMulNarrowDiv(nvector->vz, ONE_FIXED, m);
#endif /* SupportFPMathsFunctions */
}
void Normalise2d(VECTOR2D *nvector)
{
#if SupportFPMathsFunctions
VECTOR2DF n;
float m;
n.vx = nvector->vx;
n.vy = nvector->vy;
m = sqrt((n.vx * n.vx) + (n.vy * n.vy));
nvector->vx = (n.vx * ONE_FIXED) / m;
nvector->vy = (n.vy * ONE_FIXED) / m;
#else /* SupportFPMathsFunctions */
int m, s;
int xsq, ysq;
LONGLONGCH max_abs_xy64;
LONGLONGCH abs_xy[2];
int shift;
/* Before we can normalise we must bring these vectors down to 14-bits */
IntToLL(&abs_xyz[0], &nvector->vx);
s = CMP_LL(&abs_xyz[0], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[0]);
IntToLL(&abs_xyz[1], &nvector->vy);
s = CMP_LL(&abs_xyz[1], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[1]);
MaxLONGLONGCH(&abs_xy[0], 2, &max_abs_xy64);
#if 0
textprint("value to shift = %d, %d\n", max_abs_xyz64.lo32, max_abs_xyz64.hi32);
#endif
shift = FindShift64(&max_abs_xy64, &ll_one14);
#if 0
textprint("shift = %d\n", shift);
#endif
nvector->vx >>= shift;
nvector->vy >>= shift;
/* Normalise */
xsq = nvector->vx * nvector->vx;
ysq = nvector->vy * nvector->vy;
m = SqRoot32(xsq + ysq);
if(m == 0) m = 1; /* Just in case */
nvector->vx = WideMulNarrowDiv(nvector->vx, ONE_FIXED, m);
nvector->vy = WideMulNarrowDiv(nvector->vy, ONE_FIXED, m);
#endif /* SupportFPMathsFunctions */
}
#if SupportFPMathsFunctions
void FNormalise(VECTORCHF *n)
{
float m;
m = sqrt((n->vx * n->vx) + (n->vy * n->vy) + (n->vz * n->vz));
n->vx /= m;
n->vy /= m;
n->vz /= m;
}
void FNormalise2d(VECTOR2DF *n)
{
float m;
m = sqrt((n->vx * n->vx) + (n->vy * n->vy));
n->vx /= m;
n->vy /= m;
}
#endif /* SupportFPMathsFunctions */
/*
Return the magnitude of a vector
*/
int Magnitude(VECTORCH *v)
{
#if SupportFPMathsFunctions
VECTORCHF n;
int m;
n.vx = v->vx;
n.vy = v->vy;
n.vz = v->vz;
f2i(m, sqrt((n.vx * n.vx) + (n.vy * n.vy) + (n.vz * n.vz)));
return m;
#else /* SupportFPMathsFunctions */
VECTORCH vtemp;
LONGLONGCH max_abs_xyz64;
LONGLONGCH abs_xyz[3];
int shift;
int m;
int xsq, ysq, zsq;
int s;
/*
Before we can square and add the components we must bring these vectors
down to 14-bits
*/
IntToLL(&abs_xyz[0], &v->vx);
s = CMP_LL(&abs_xyz[0], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[0]);
IntToLL(&abs_xyz[1], &v->vy);
s = CMP_LL(&abs_xyz[1], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[1]);
IntToLL(&abs_xyz[2], &v->vz);
s = CMP_LL(&abs_xyz[2], &ll_zero);
if(s < 0) NEG_LL(&abs_xyz[2]);
MaxLONGLONGCH(&abs_xyz[0], 3, &max_abs_xyz64);
shift = FindShift64(&max_abs_xyz64, &ll_one14);
CopyVector(v, &vtemp);
vtemp.vx >>= shift;
vtemp.vy >>= shift;
vtemp.vz >>= shift;
xsq = vtemp.vx * vtemp.vx;
ysq = vtemp.vy * vtemp.vy;
zsq = vtemp.vz * vtemp.vz;
m = SqRoot32(xsq + ysq + zsq);
m <<= shift;
return m;
#endif /* SupportFPMathsFunctions */
}
/*
64-bit Square Root returns 32-bit result
All 64-bit operations are now done using the type LONGLONGCH whose format
varies from platform to platform, although it is always 64-bits in size.
NOTE:
Function currently not available to Watcom C users
A Floating point version is STRONGLY advised for the PC anyway
*/
#if 0
int SqRoot64(LONGLONGCH *A)
{
#if 0
unsigned long long edx = *A;
unsigned int eax = 0;
unsigned int ebx = 0;
unsigned int edi = 0;
unsigned int ecx;
unsigned long long TopBit = 0x8000000000000000LL;
for(ecx = 31; ecx != 0; ecx--) {
ebx <<= 1;
if(edx & TopBit) ebx |= 1;
edx <<= 1;
ebx <<= 1;
if(edx & TopBit) ebx |= 1;
edx <<= 1;
eax += eax;
edi = eax;
edi += edi;
if(ebx > edi) {
edi++;
eax++;
ebx -= edi;
}
}
ebx <<= 1;
if(edx & TopBit) ebx |= 1;
edx <<= 1;
ebx <<= 1;
if(edx & TopBit) ebx |= 1;
edx <<= 1;
eax += eax;
edi = eax;
edi += edi;
if(ebx > edi) {
eax++;
}
return eax;
#endif
return (0);
}
#endif /* for #if 0 */
/*
Shift the 64-bit value until is LTE the limit
Return the shift value
*/
int FindShift64(LONGLONGCH *value, LONGLONGCH *limit)
{
int shift = 0;
int s;
LONGLONGCH value_tmp;
EQUALS_LL(&value_tmp, value);
s = CMP_LL(&value_tmp, &ll_zero);
if(s < 0) NEG_LL(&value_tmp);
while(GT_LL(&value_tmp, limit)) {
shift++;
ASR_LL(&value_tmp, 1);
}
return shift;
}
/*
MaxLONGLONGCH
Return a pointer to the largest value of a long long array
*/
void MaxLONGLONGCH(LONGLONGCH *llarrayptr, int llarraysize, LONGLONGCH *llmax)
{
int i;
EQUALS_LL(llmax, &ll_zero);
for(i = llarraysize; i!=0; i--) {
if(LT_LL(llmax, llarrayptr)) {
EQUALS_LL(llmax, llarrayptr);
}
llarrayptr++;
}
}
/*
Some operators derived from the 64-bit CMP function.
These were first defined for pcwatcom\plspecfn.h and transferred as and
when needed to other platforms.
*/
/*
GT_LL
To express if(a > b)
use
if(GT_LL(a, b))
*/
int GT_LL(LONGLONGCH *a, LONGLONGCH *b)
{
int s = CMP_LL(a, b); /* a-b */
if(s > 0) return (Yes);
else return (No);
}
/*
LT_LL
To express if(a < b)
use
if(LT_LL(a, b))
*/
int LT_LL(LONGLONGCH *a, LONGLONGCH *b)
{
int s = CMP_LL(a, b); /* a-b */
if(s < 0) return (Yes);
else return (No);
}
/*
Copy Clip Point Function
*/
void CopyClipPoint(CLIP_POINT *cp1, CLIP_POINT *cp2)
{
cp2->ClipPoint.vx = cp1->ClipPoint.vx;
cp2->ClipPoint.vy = cp1->ClipPoint.vy;
cp2->ClipPoint.vz = cp1->ClipPoint.vz;
cp2->ClipNormal.vx = cp1->ClipNormal.vx;
cp2->ClipNormal.vy = cp1->ClipNormal.vy;
cp2->ClipNormal.vz = cp1->ClipNormal.vz;
cp2->ClipTexel.uuu = cp1->ClipTexel.uuu;
cp2->ClipTexel.vee = cp1->ClipTexel.vee;
cp2->ClipInt = cp1->ClipInt;
cp2->ClipZBuffer = cp1->ClipZBuffer;
}
/*
Matrix Rotatation of a Vector - Inline Version
Overwrite the Source Vector with the Rotated Vector
x' = v.c1
y' = v.c2
z' = v.c3
*/
void RotVect(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;
}
/*
Dot Product Function - Inline Version
It accepts two pointers to vectors and returns an int result
*/
int _Dot(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);
}
/*
Make a Vector - Inline Version
v3 = v1 - v2
*/
void MakeV(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 AddV(VECTORCH *v1, VECTORCH *v2)
{
v2->vx += v1->vx;
v2->vy += v1->vy;
v2->vz += v1->vz;
}