#include "global.h"
#include "maths.h"
#include "collide.h"

#include "camera.h"
#include "platform.h"
#include "bff_load.h"
#include "enemies.h"
#include <limits.h>

#undef NULL
#define NULL 0

//#define PRINTHITPOS	TRUE
#define PRINTHITPOS	FALSE
#define PRINTERROR	TRUE
Point3DType pTempW[16]; 


int		ctr;
#define STARTPOLY ctr=0
#define DRAWPOLY(R,G,B)	lscapeDrawBoundPoly3D(ctr, pTempW, R,G,B)
#define ADDVERT(X,Y,Z) {pTempW[ctr].x=(X)/4096;pTempW[ctr].y=((Y)/4096);pTempW[ctr++].z=(Z)/4096;}


COLL_BFF *WorldBFFcoll = NULL;
ULONG *tempFile = NULL;

HITDATA 	pHitData[16]; // max number of hits (This was in ball.c)
COLLBOX		*collBox;	// so was this
long		numCollBoxes;// This too

HITDATA		*swap[16]; // Used for the sort done on collision types

/*	--------------------------------------------------------------------------------
	Function 	: setupCollision
	Purpose 	: Loads all the collision boxes
	Parameters 	: 
	Returns 	: 
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//


ULONG	pTestFaces[]={0x00021000};  // Tri with verts 0,1&2
VECTOR	pTestVerts[]={	{0,0,0},
						{100,0,0},
						{100,-30,100}
};

/////////////////////////////////////////////////////////////////////////////////////////

long FindRampHeight(COLLBOX *pB, long x, long z, long y)   //Improved by ANO  30/6/99
{
	RAMPHEADER *pRampHeader;
	static ULONG *pFaces;
	static VECTOR *pVerts;
	ULONG f,p;
	int vp;
	 ULONG nFaces, nVerts;
	int j,t,flags;
	static VECTOR vrt[3];
	static VECTOR n;
	static VECTOR iPos;
	static VECTOR v1,v2,a; //needed for non-precalc'd normals!!!

	
	int touch=FALSE;
	int htHt=0x7fffffff;
	int htBig=0x7fffffff;
	static Point2DType twoDpoints[4];
	Point2DType *p2D=twoDpoints;

	pRampHeader=pB->rampheader; //generalPtr);

	iPos.vx=x/4096;
	iPos.vy=y/4096;
	iPos.vz=z/4096;

	nVerts=pRampHeader->nVerts;
	nFaces=pRampHeader->nFaces;
	pFaces=pRampHeader->pFaces;
	pVerts=pRampHeader->pVerts;

	for(p=0; p<nFaces; p++)
	{
		f=pFaces[p];

		flags=f&6;
		f=f>>8;

		if ((flags==4)||(flags==0))
		{
			for(j=0; j<3; j++)
			{
				vp=f&(0x0f);
//				v[j]=vp;
				f=f>>4;
				vrt[j].vx=pVerts[vp].vx/4096;
				vrt[j].vy=pVerts[vp].vy/4096;
				vrt[j].vz=pVerts[vp].vz/4096;

				p2D[j].x=(vrt[j].vx)+(pB->pX/4096);
				p2D[j].y=(vrt[j].vz)+(pB->pZ/4096);

			}
			touch=pointInTri(iPos.vx,iPos.vz,p2D);

		}
		else
		{
			touch = 0;
		}
		if (touch)
		{

			if(flags==4)   
			{ // we're only interested in XZ polys for find height
				//DB("Inside XZ, ht=%d\n", htHt);
				htHt = ((vrt[0].vy << 12) + pB->pY) - y;	// must be a vert on the top plane
//				htHt=((pVerts->vy)+pY)-y;
			}
			else //  must be (flags==0)
			{ // test ramp then ...


				SUBVECTOR(&v1, vrt, vrt+1);
				SUBVECTOR(&v2, vrt, vrt+2);
				n.vx=(v1.vy * v2.vz - v1.vz * v2.vy);
				n.vy=(v1.vz * v2.vx - v1.vx * v2.vz);
				n.vz=(v1.vx * v2.vy - v1.vy * v2.vx);
				MakeUnit(&n);
				a.vx = vrt->vx + pB->pX/4096;
				a.vy = vrt->vy + pB->pY/4096;
				a.vz = vrt->vz + pB->pZ/4096;
				j=DotProduct(&n, &a); //height of plane at point  
				t=DotProduct(&n, &iPos)-j; //height of entry x,y,z

				if(n.vy) //temp bodge to stop div by zero
				{
					t=t*4096;
					t=t/n.vy;
				}
				else	t=0;
				htHt=-(t*4096);
			}
			if(htHt<htBig) htBig=htHt; //under plane, sets on plane
		}
	}
	return(htBig);
} 


/////////////////////////////////////////////////////////////////////////////////////////
long getHeightAt(long x,long y,long z)
{
	long	x1,y1,z1,value,i;//,diff1,diff2;
	VECTOR vect2;
	long	rval=0;
	ULONG	collBoxPos;
	//static ULONG	*collptr,*collptr1;
	ULONG	*collptr,*collptr1;
	//static DYNCOLLBOX *ptr;
	static COLLBOX cB;  //too big to be a normal local (fast stack issue!)
	static COLLBOX *pB=&cB;
	static COLLBOX *pB1;

	rval = 0x7fffffff;
	value = 0x7fffffff;


	vect2.vx=x;
	vect2.vy=y;
	vect2.vz=z;


	x1=x-startX;
	y1=y-startY;
	z1=z-startZ;

	x1/=xStepLen;
	y1/=yStepLen;
	z1/=zStepLen;

	if (x1<0 || x1>=xSteps) return(rval);
	//if (y1<0 || y1>=ySteps) return(rval);
	if (y1>=ySteps) return(rval);
	if (z1<0 || z1>=zSteps) return(rval);

/*	x-=WorldBFFcoll->startX;
	y-=WorldBFFcoll->startY;
	z-=WorldBFFcoll->startZ;		   

	x1=x/WorldBFFcoll->xStepLen;
	y1=y/WorldBFFcoll->yStepLen;
	z1=z/WorldBFFcoll->zStepLen;

	if (x1<0 || x1>=WorldBFFcoll->xSteps) return(-1);	// Out of bounds can not hit anything
	if (y1>=WorldBFFcoll->ySteps) return(-1);
	if (z1<0 || z1>=WorldBFFcoll->zSteps) return(-1);
*/

	if (y1 < 0) y1 = 0;
	//y1=0;

	while(y1 < ySteps)
	{
		for(i=0; i< enemyGlobals.numCollBoxes;i++)
		{
			pB1 = enemyGlobals.pCollBoxes + i;

			getHeightOfOneBox(pB1, &value,&vect2);
			if(value >= -10*8*512)
			{
				if(value < rval)
					rval = value;
			}

			if(rval < 0x7fffffff)	// if we've got a valid height within this zone, ok, return
				return rval;

		}
/*		collBoxPos=( x1+(z1*xSteps)+(y1*(xSteps*zSteps)) );
		collptr=(ULONG *)reducedCollBox[collBoxPos];

		//collBoxPos=( x1+(z1*WorldBFFcoll->xSteps)+(y1*(WorldBFFcoll->xSteps*WorldBFFcoll->zSteps)) );
		//collptr=(ULONG *)reducedCollBox[collBoxPos];

		//if (collptr==NULL) return(-1);	// No boxes in this voxel to test (this may need to change)

		if (collptr)
		{
			if (((ULONG)collptr) < 0x80000000)	// Check for one or >one
			{
				getHeightOfOneBox((COLLBOX*)collptr, &value,&vect2);
				if(value < rval)
					rval = value;
			}
			else
			{	// multiple boxes to deal with
				collptr = (ULONG *)(((ULONG)collptr) & 0x7fffffff);

				collptr1 = (ULONG *)(*collptr);
				do	// the "none" case has already been dealt with
				{
					getHeightOfOneBox((COLLBOX*)collptr1, &value,&vect2);
					if(value >= -10*8*512)
					{
						if(value < rval)
							rval = value;
					}

					collptr++;
					collptr1=(ULONG *)(*collptr);
				}
				while (collptr1!=NULL);

			}

			if(rval < 0x7fffffff)	// if we've got a valid height within this zone, ok, return
				return rval;

		}	*/
		y1++;
	}
	return rval;
}

/////////////////////////////////////////////////////////////////////////////////////////
long getCeilingAt(long x,long y,long z)
{
// tdb clean this up a bit
	long	x1,y1,z1,value;//,diff1,diff2;
	VECTOR vect2;
	long	rval=0;
	ULONG	collBoxPos;
	ULONG	*collptr,*collptr1;
	static COLLBOX cB;  //too big to be a normal local (fast stack issue!)
	static COLLBOX *pB=&cB;
	static COLLBOX *pB1;

	rval = 0x7fffffff;
	value = 0x7fffffff;


	vect2.vx=x;
	vect2.vy=y;
	vect2.vz=z;

	x1=x-startX;
	y1=y-startY;
	z1=z-startZ;

	x1/=xStepLen;
	y1/=yStepLen;
	z1/=zStepLen;

	if (x1<0 || x1>=xSteps) return(-1);
	//if (y1>=ySteps) return(-1);
	if (y1<0) return(-1);
	if (z1<0 || z1>=zSteps) return(-1);

	if (y1 < 0) y1 = 0;

	//while(y1 < ySteps)

	//DB("%d",y1);
	//while(y1 >0)
	//{
		collBoxPos=( x1+(z1*xSteps)+(y1*(xSteps*zSteps)) );
		collptr=(ULONG *)reducedCollBox[collBoxPos];

		if (collptr)
		{
			if (((ULONG)collptr) < 0x80000000)	// Check for one or >one
			{
				//getHeightOfOneBox((COLLBOX*)collptr, &value,&vect2);
				COLLBOX *pBox=(COLLBOX*)collptr;
				int	temp;
				if ( (vect2.vx>=pBox->pX) && (vect2.vx<=(pBox->pX+pBox->sX)) ) // inside on x
				{
					if ( (vect2.vz>=pBox->pZ) && (vect2.vz<=(pBox->pZ+pBox->sZ)) ) // inside on z
					{
						//temp=(pBox->pY)-vect2.vy;
						temp=vect2.vy-(pBox->pY);
						if ( (value > temp) && temp>0 ) (value)=temp;
					}
				}
				if(value < rval)
					rval = value;
			}
			else
			{	// multiple boxes to deal with
				collptr = (ULONG *)(((ULONG)collptr) & 0x7fffffff);
				collptr1 = (ULONG *)(*collptr);
				do	// the "none" case has already been dealt with
				{
					//getHeightOfOneBox((COLLBOX*)collptr1, &value,&vect2);
					COLLBOX *pBox=(COLLBOX*)collptr1;
					int	temp;
					if ( (vect2.vx>=pBox->pX) && (vect2.vx<=(pBox->pX+pBox->sX)) ) // inside on x
					{
						if ( (vect2.vz>=pBox->pZ) && (vect2.vz<=(pBox->pZ+pBox->sZ)) ) // inside on z
						{
							temp=vect2.vy-(pBox->pY);
							//if ( (value) < temp ) (value)=temp;
							if ( (value > temp) && temp>0 ) (value)=temp;
						}
					}
					//if(value >= -10*8*512)
					//{
						if(value < rval)
							rval = value;
					//}

					collptr++;
					collptr1=(ULONG *)(*collptr);
				}
				while (collptr1!=NULL);

			}
			if(rval < 0x80000000)	// if we've got a valid height within this zone, ok, return
				return rval;
		}
		//y1--;
	//}
	return rval;
}

/////////////////////////////////////////////////////////////////////////////////////////
long getHeightAtCam(long x,long y,long z,COLLBOX *pBox)
{
	long	x1,y1,z1,value;
	VECTOR vect2;
	long	rval=0;
	ULONG	collBoxPos;
	volatile ULONG	*collptr,*collptr1;
	static COLLBOX cB;  //too big to be a normal local (fast stack issue!)
	static COLLBOX *pB=&cB;
	static COLLBOX *pB1;

	//pBox=NULL;

	rval = 0x7fffffff;
	value = 0x7fffffff;

	vect2.vx=x;
	vect2.vy=y;
	vect2.vz=z;


	x1=x-startX;
	y1=y-startY;
	z1=z-startZ;

	x1/=xStepLen;
	y1/=yStepLen;
	z1/=zStepLen;

	if (x1<0 || x1>=xSteps) return(-1);
	if (y1>=ySteps) return(-1);
	if (z1<0 || z1>=zSteps) return(-1);

	if (y1 < 0) y1 = 0;
	//y1=0;

	while(y1 < ySteps)
	{
		collBoxPos=( x1+(z1*xSteps)+(y1*(xSteps*zSteps)) );
		collptr=(ULONG *)reducedCollBox[collBoxPos];

		if (collptr)
		{
			if (((ULONG)collptr) < 0x80000000)	// Check for one or >one
			{
				getHeightOfOneBox((COLLBOX*)collptr, &value,&vect2);
				if(value < rval)
					rval = value;
			}
			else
			{	// multiple boxes to deal with

				collptr = (ULONG *)(  ((ULONG)(collptr)) & 0x7fffffff);	// mask off collptr's top bit
				collptr1= (ULONG *)(*collptr);

				do	// the "none" case has already been dealt with
				{
					//pBox=(COLLBOX*)collptr1;
					getHeightOfOneBox((COLLBOX*)collptr1, &value,&vect2);

					if(value < rval)
					{
						rval = value;
						//pBox=(COLLBOX*)collptr1;
						pBox->pX=((COLLBOX*)collptr1)->pX;
						pBox->pY=((COLLBOX*)collptr1)->pY;
						pBox->pZ=((COLLBOX*)collptr1)->pZ;

						pBox->sX=((COLLBOX*)collptr1)->sX;
						pBox->sY=((COLLBOX*)collptr1)->sY;
						pBox->sZ=((COLLBOX*)collptr1)->sZ;
					}

					collptr++;
					collptr1=(ULONG *)(*collptr);
				}
				while (collptr1!=NULL);
			}

			if(rval < 0x7fffffff)	// if we've got a valid height within this zone, ok, return
				return rval;
		}
		y1++;
	}
	return rval;
}


/***************************************************************************************/
void getHeightOfOneBox(COLLBOX *pB, long *pVal,VECTOR *vect)
{
	long diff1,diff2,temp;

	switch(pB->flags&TYPEPART)
	{
		case BOX:
			if ( (vect->vx>=pB->pX) && (vect->vx<=(pB->pX+pB->sX)) ) // inside on x
			{
				if ( (vect->vz>=pB->pZ) && (vect->vz<=(pB->pZ+pB->sZ)) ) // inside on z
				{
					temp=(pB->pY+pB->sY)-vect->vy;
					//if ( ((*pVal) > temp ) && temp>-40960) (*pVal)=temp;	// the -10 (*4096) is an under-the-roof frig
					if ( (*pVal) > temp ) (*pVal)=temp;
				}
			}
			break;

		case RAMP:
			if ( (vect->vx>=pB->pX) && (vect->vx<=(pB->pX+pB->sX)) ) // inside on x
			{
				if ( (vect->vz>=(pB->pZ)) && (vect->vz<=(pB->pZ+pB->sZ)) ) // inside on z
				{
					temp=FindRampHeight(pB, vect->vx,vect->vz,vect->vy);  //YES, these are in a funny order!
					if((*pVal)>temp && temp>-40960) (*pVal)=temp;	// the -10 (*4096) is an under-the-roof frig
				}
			}
			break;
		default:
			//ASSERT(0); // This assert is set to always fail because we shouldn't ever be here
			break;
  	}

}

COLLBOX *collisionLoadMeshCRC(long crc)
{
	ULONG offMesh;
	void *firstRamp=NULL;
	ULONG *pM;
	int loop;
	COLLBOX *collBox;
	COLL_BFF *bffcoll;
	bffcoll=(COLL_BFF *)BFF_FindObject(BFF_COLL_ID, crc);

	if(bffcoll)
	{
		tempFile = ADD2POINTER(bffcoll,bffcoll->base_mesh_offset);
	}
	else
	{
		return(0);
	}

	numCollBoxes=*tempFile;

	collBox=(COLLBOX *)(tempFile+1);

	offMesh=(sizeof(COLLBOX)*numCollBoxes)+sizeof(ULONG);

// the ramp-header correction has now been moved to "LinkBFF", so it works for platforms too.
/*
	for(loop=0;loop<numCollBoxes;loop++)
	{
		if(((collBox[loop].flags)&TYPEPART)==RAMP)
		{
			pM=(ULONG *)(((ULONG)offMesh)+((ULONG)tempFile)+((ULONG)collBox[loop].rampheader));
			(ULONG*)collBox[loop].rampheader=pM;

			if(!firstRamp)
			{
				firstRamp=pM;
			}

			pM[1]+=(ULONG)firstRamp;
			pM[2]+=(ULONG)firstRamp;
		}
	}
*/
/*	for(loop=0;loop<numCollBoxes;loop++)
	{

		if (((collBox[loop].flags) & TYPEPART) == SPHERE)
		{
			collBox[loop].sY= collBox[loop].sY;
			collBox[loop].sX=-collBox[loop].sX;
			collBox[loop].sZ=-collBox[loop].sZ;
		}

	}
*/
	xStepLen = bffcoll->xStepLen;
	yStepLen = bffcoll->yStepLen;
	zStepLen = bffcoll->zStepLen;

	xSteps = bffcoll->xSteps;
	ySteps = bffcoll->ySteps;
	zSteps = bffcoll->zSteps;

	startX = bffcoll->startX;
	startY = bffcoll->startY;
	startZ = bffcoll->startZ;

	endX = bffcoll->endX;
	endY = bffcoll->endY;
	endZ = bffcoll->endZ;

	DB("Setting stepLen to %d, %d, %d\n", xStepLen, yStepLen, zStepLen);

	return collBox;
}
COLLBOX	*boxes;
void collideLinkBFF(COLL_BFF *header)
{
	int i;
	//COLLBOX	*boxes;
	void    **pointers;
	int value;

	DB(" *** Linking collision %p\n", header); 


// Fix the ramp headers - this used to be in "loadmeshcrc", but this needs to happen for platforms, too

	if(header->base_mesh_offset)
	{
		int *temp;
		int n_boxes;
		COLLBOX *box;
		void *firstRamp = NULL;
		int offMesh;
		int loop;
		unsigned long *pM;

		temp = ADD2POINTER(header,header->base_mesh_offset);
		n_boxes=*temp;
		box=(COLLBOX *)(temp+1);
		offMesh=(sizeof(COLLBOX)*n_boxes)+sizeof(ULONG);

		for(loop=0;loop<n_boxes;loop++)
		{
			if(((box[loop].flags)&TYPEPART)==RAMP)
			{
				pM=(ULONG *)(((ULONG)offMesh)+((ULONG)temp)+((ULONG)box[loop].rampheader));
				(ULONG*)box[loop].rampheader=pM;

				if(!firstRamp)
				{
					firstRamp=pM;
				}

				pM[1]+=(ULONG)firstRamp;
				pM[2]+=(ULONG)firstRamp;
			}
		}
		DB("done\n");
	}


	if(header->red_mesh_offset)
	{
		numCollBoxes=*(ULONG *)ADD2POINTER(header,header->base_mesh_offset);

		boxes = ADD2POINTER(header,header->base_mesh_offset+4);	// 1st int is the number of collboxes
		pointers = ADD2POINTER(header,header->red_mesh_offset);

		WorldBFFcoll = header;

		reducedCollBox = ADD2POINTER(header,header->red_mesh_offset);

		for(i = 0; i < header->n_pointers; i++)
		{
			value = (ULONG)pointers[i];
			if(value == -1)
			{
				pointers[i] = NULL;
			}
			else
			{
				if(!(value & 0x80000000))	// single
				{
					pointers[i] = &boxes[value & 0x7fffffff];
				}
				else	// multi
				{
					value = (ULONG)(&pointers[value & 0x7fffffff]);
					value |= 0x80000000;
					pointers[i] = (void *)value;
				}
			}
		}
	}


}



void *tempmemblock2;

//void	setupCollision(void)
void	setupCollision(char *name)
{

	ULONG offMesh;
	int i,p,v;
	void *firstRamp=NULL;
	ULONG *pM;
	ULONG *pFaces;
	VECTOR *pVerts;
	int nVerts,nFaces;
	ULONG f;
	VECTOR *pV;
	int loop;
	COLLBOX *collBox;

	char sBuff[64];

	// CPW:
	DB("Setting up collision '%s'\n", name);

	collBox = collisionLoadMeshCRC(0);
	ASSERT(collBox);

	enemyTellThemAboutCollision(numCollBoxes, collBox);

	return;


// RFW - this little lot's in the bff-compiler now
	/*
	strcpy(sBuff, name);
	strcat(sBuff, "\\");
	strcat(sBuff, name);
	strcat(sBuff, ".RAW");

	//tempFile=(ULONG *)fileLoad("COLLTEST\\test.dat",&loop);	// returns lenght of loaded file (I think)
	tempFile=(ULONG *)fileLoad(sBuff,&loop);	// returns lenght of loaded file (I think)
	//tempFile=(ULONG *)fileLoad("COLLTEST\\temp1.dat",&loop);	// returns lenght of loaded file (I think)
	if (tempFile==NULL)
	{
		DB("%s not found loading default\n",sBuff);
		tempFile=(ULONG *)fileLoad("colltest\\default.raw",&loop);	// returns lenght of loaded file (I think)
		ASSERT(tempFile);
	}
	


	//tempFile=(ULONG *)LoadFile(sBuff);
	numCollBoxes=*tempFile;
	collBox=(COLLBOX *)(tempFile+1);
	offMesh=(sizeof(COLLBOX)*numCollBoxes)+sizeof(ULONG);
	
	for (loop=0;loop<numCollBoxes;loop++)
	{
		//(collBox+loop)->flags=RAMP;
		//printf ("flag for box %d\n",(collBox+loop)->flags);
		(collBox+loop)->pX=( ((collBox+loop)->pX*4096) );
		(collBox+loop)->pY=-( ((collBox+loop)->pY*4096) );
		(collBox+loop)->pZ=( ((collBox+loop)->pZ*4096) );

		(collBox+loop)->sX=((collBox+loop)->sX*4096);
		(collBox+loop)->sY=-((collBox+loop)->sY*4096);
		(collBox+loop)->sZ=((collBox+loop)->sZ*4096);

		if(((collBox[loop].flags)&TYPEPART)==RAMP)
		{
			//pM=(ULONG *)(((ULONG)offMesh)+((ULONG)tempFile)+((ULONG)collBox[loop].generalPtr));
			//collBox[loop].generalPtr=pM;

			//pM=(ULONG *)(((ULONG)offMesh)+((ULONG)tempFile)+((ULONG)collBox[loop].rampheader)); // Err where does offMesh come from?

			//pM=(ULONG *)(((ULONG)tempFile)+((ULONG)collBox[loop].rampheader));
			//collBox[loop].rampheader=pM;

			pM=(ULONG *)(((ULONG)offMesh)+((ULONG)tempFile)+((ULONG)collBox[loop].rampheader));
			collBox[loop].rampheader= (RAMPHEADER *)pM;
	
			if(!firstRamp)
			{
				firstRamp=pM;
			}

			pM[1]+=(ULONG)firstRamp;
			pM[2]+=(ULONG)firstRamp;

			pFaces=(ULONG *)(pM[1]);
			nFaces=pM[0]>>16;

			pVerts=(VECTOR *)(pM[2]);
			nVerts=pM[0]&0xffff;

			for(i=0; i<nVerts; i++)
			{
				pVerts[i].vx=pVerts[i].vx*4096;
				pVerts[i].vy=-(pVerts[i].vy*4096);
				pVerts[i].vz=pVerts[i].vz*4096;
			}

			for(p=0; p<nFaces; p++)
			{
				f=pFaces[p]>>8;

				//DB("FACE %d: %08x\n", p, pFaces[p]);

				for(v=0; v<3; v++)
				{
					pV=pVerts+(f&0xf);
					f=f>>4;
					
					if(((pV->vx)>collBox[loop].sX) || ((pV->vy)<collBox[loop].sY) || ((pV->vz)>collBox[loop].sZ))
					{
						DB("ERROR: !!!!!HUGE FUCKUP!!!!!\n");
						DB("Vert[%d]=(%d,%d,%d) ", v,
							pV->vx/4096, pV->vy/4096, pV->vz/4096);

						DB("box size=(%d,%d,%d)\n",
							collBox[loop].sX/4096, collBox[loop].sY/4096, collBox[loop].sZ/4096);

						//CRASH;
					}
				}
			}

			//pM[0]=0x00010003;
			//pM[1]=(ULONG)pTestFaces;
			//pM[2]=(ULONG)pTestVerts;
		}


	}
	DB("\n%d Collision boxes\n",numCollBoxes);
	ReduceCollision(&collBox[0],(80*4096));
*/
}


VECTOR vRebound[MAXCOLLOSIONS], vTempRebound, planeRebound;
VECTOR v0v2, v0v1, velDiff;


// Knock a box off the list of boxes to check as quickly as possible
// (so we don't need to bother with corner, edge, or plane checking)
int collideNearStaticBox(COLLBOX *pB, COLLDATA *pD)
{
	int min,max;

// x
	min = pB->pX - pD->radius;
	max = pB->pX + pB->sX + pD->radius;

	if(pD->pPos->vx < min && pD->oldPos.vx < min)
		return 0;
	if(pD->pPos->vx > max && pD->oldPos.vx > max)
		return 0;

// z
	min = pB->pZ - pD->radius;
	max = pB->pZ + pB->sZ + pD->radius;

	if(pD->pPos->vz < min && pD->oldPos.vz < min)
		return 0;
	if(pD->pPos->vz > max && pD->oldPos.vz > max)
		return 0;

// y
// -ve ysize, remember
	min = pB->pY + pB->sY - pD->radius;
	max = pB->pY + pD->radius;

	if(pD->pPos->vy < min && pD->oldPos.vy < min)
		return 0;
	if(pD->pPos->vy > max && pD->oldPos.vy > max)
		return 0;

	return 1;
}


void collboxCheckOneBox(COLLBOX *pB, COLLDATA *pD, int *pnPolysHit)
{
		if(collideNearStaticBox(pB, pD))
		{
			if((pB->flags&TYPEPART)==BOX)
			{
				if( CheckCorners( pB , pD , &pHitData[*pnPolysHit] ) )
				{
					pD->flags|=pB->flags;
					*pnPolysHit++;
				}
				// Check Edges
				else if( CheckEdges( pB , pD , &pHitData[*pnPolysHit] ) )
				{
					pD->flags|=pB->flags;
					*pnPolysHit++;
				}
				// Check Planes
				else if( CheckPlanes( pB , pD , &pHitData[*pnPolysHit] ) )
				{
					pD->flags|=pB->flags;
					*pnPolysHit++;
				}
			}
			else if((pB->flags&TYPEPART)==RAMP)
			{
				//printf ("checking ramp\n");
				if(CheckRamps(pB, pD, &pHitData[*pnPolysHit]))
				{
					pD->flags|=pB->flags;
					*pnPolysHit++;
				}
			}
		}
}




int	collboxCheckSphere(COLLDATA *pD)
{
	COLLBOX	*pB;
	long	x1,x2;
	long	y1,y2;
	long	z1,z2;
	int		nPolysHit=0;
	int		bHit,i,p,low,hi;
	long	r=pD->radius;
	VECTOR	velHit;
	VECTOR	collPos;
	long	div, magv0v1, magv0v2;
	int		e,f,c;
	int		reboundcount;
	ULONG	collBoxPos;
	ULONG	*collptr,*collptr1;
	ULONG	flag=0;


	while(
		   (ABS(pD->pPos->vx - pD->oldPos.vx)) > pD->radius
		|| (ABS(pD->pPos->vy - pD->oldPos.vy)) > pD->radius
		|| (ABS(pD->pPos->vz - pD->oldPos.vz)) > pD->radius
		)
	{
		VECTOR temp;
		int rv;
		temp = *pD->pPos;
		pD->pPos->vx = (pD->pPos->vx + pD->oldPos.vx)/2;
		pD->pPos->vy = (pD->pPos->vy + pD->oldPos.vy)/2;
		pD->pPos->vz = (pD->pPos->vz + pD->oldPos.vz)/2;
//		DB("Going down %d %d %d\n",ABS(pD->pPos->vx - pD->oldPos.vx),ABS(pD->pPos->vy - pD->oldPos.vy),ABS(pD->pPos->vz - pD->oldPos.vz));
		rv = collboxCheckSphere(pD);
		if(rv)
		{
			return rv;
		}
		*pD->pPos = temp;
		DB("DIV\n");
	}



	x1=pD->pPos->vx-startX;
	y1=pD->pPos->vy-startY;
	z1=pD->pPos->vz-startZ;

//	if (x1<startX || x1>endX) return;
//	if (y1<startY || y1>endY) return;
//	if (z1<startZ || z1>endZ) return;

//	if (pad[0]&PAD_SELECT) flag=1;	// removed

	//if (pD==&cameraColl)
	//	DB("camera collision start\n");

	x1/=xStepLen;
	y1/=yStepLen;
	z1/=zStepLen;

	ASSERT(xStepLen);
	ASSERT(yStepLen);
	ASSERT(zStepLen);

	ASSERT(xSteps);
	ASSERT(ySteps);
	ASSERT(zSteps);

	pD->flags=0;


	if((x1<0) || (x1>=xSteps) ||  (y1<0) || (y1>=ySteps) || (z1<0) || (z1>=zSteps))
	{
/*		DB("Rejected: x,y,z = (%d, %d, %d)\n", x1, y1, z1);
		DB("          start = (%d, %d, %d)\n", startX, startY, startZ);
		DB("        stepLen = (%d, %d, %d)\n", xStepLen, yStepLen, zStepLen);
*/
		CopyVector(&pD->oldPos, pD->pPos);
		return 0;
	}

// CPW: 	DB ("x1 %d y1 %d z1 %d\n",x1,y1,z1);

	collBoxPos=( x1+(z1*xSteps)+(y1*(xSteps*zSteps)) );
// CPW: 	DB("collboxpos %d \n",collBoxPos);
	collptr=(ULONG *)reducedCollBox[collBoxPos];

	if (collptr==NULL)
	{
		CopyVector(&pD->oldPos, pD->pPos);
		return(0);	// No boxes to test
	}

	// Clear hit array
	for(i=0; i<16; i++)
	{
		pHitData[i].type=FALSE;
		pHitData[i].plane=FALSE;
	}

	platformCheckCollision(pD, &nPolysHit);


#define CHECK_EM_ALL

#ifdef CHECK_EM_ALL
	{
		int i;

		ASSERT(pD->nBoxes);

		for(i=0; i<pD->nBoxes; i++)
		{
			pB = pD->pCollBox + i;

			// CPW: DB("Processing box %p\n", pB);

			// CPW: if(collideNearStaticBox(pB, pD))
			{
				if((pB->flags&TYPEPART)==BOX)
				{
					if( CheckCorners( pB , pD , &pHitData[nPolysHit] ) )
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
					// Check Edges
					else if( CheckEdges( pB , pD , &pHitData[nPolysHit] ) )
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
					// Check Planes
					else if( CheckPlanes( pB , pD , &pHitData[nPolysHit] ) )
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
				}
				else if((pB->flags&TYPEPART)==RAMP)
				{
					//printf ("checking ramp\n");
					if(CheckRamps(pB, pD, &pHitData[nPolysHit]))
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
				}
			}
		}
	}
#else
	if(((ULONG)collptr) < 0x80000000)	// Check for one or >one
	{
//		collptr = (ULONG *)(((ULONG)(collptr)) & 0x7fffffff);
		ASSERT(collptr);

		pB=(COLLBOX*)collptr;
		ASSERT(pB);

		if(collideNearStaticBox(pB, pD))
		{
			if((pB->flags&TYPEPART)==BOX)
			{
				if( CheckCorners( pB , pD , &pHitData[nPolysHit] ) )
				{
					pD->flags|=pB->flags;
					nPolysHit++;
				}
				// Check Edges
				else if( CheckEdges( pB , pD , &pHitData[nPolysHit] ) )
				{
					pD->flags|=pB->flags;
					nPolysHit++;
				}
				// Check Planes
				else if( CheckPlanes( pB , pD , &pHitData[nPolysHit] ) )
				{
					pD->flags|=pB->flags;
					nPolysHit++;
				}
			}
			else if((pB->flags&TYPEPART)==RAMP)
			{
				//printf ("checking ramp\n");
				if(CheckRamps(pB, pD, &pHitData[nPolysHit]))
				{
					pD->flags|=pB->flags;
					nPolysHit++;
				}
			}
		}
	}
	else
	{	// must be >1 boxes to test
		collptr = (ULONG *)(((ULONG)(collptr)) & 0x7fffffff);
		ASSERT(collptr);

		collptr1=(ULONG*)*collptr;
		ASSERT(collptr1);

		while (collptr1!=NULL)
		{
			pB=(COLLBOX*)collptr1;

			ASSERT(pB);

			if(collideNearStaticBox(pB, pD))
			{


				if((pB->flags&TYPEPART)==BOX)
				{
					if( CheckCorners( pB , pD , &pHitData[nPolysHit] ) )
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
					// Check Edges
					else if( CheckEdges( pB , pD , &pHitData[nPolysHit] ) )
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
					// Check Planes
					else if( CheckPlanes( pB , pD , &pHitData[nPolysHit] ) )
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
				}
				else if((pB->flags&TYPEPART)==RAMP)
				{
					//printf ("checking ramp\n");
					if(CheckRamps(pB, pD, &pHitData[nPolysHit]))
					{
						pD->flags|=pB->flags;
						nPolysHit++;
					}
				}
			}
			collptr++;
			collptr1=(ULONG *)*collptr;
		}
	}
#endif

	if (nPolysHit>16)
	{
		printf ("too many collisions !\n");
		CRASH;
	}
	reboundcount=0;

	if(nPolysHit)
	{
		hi=(nPolysHit-1);
		low=0;
		if (nPolysHit>1)
		{
			for (p=0;p<nPolysHit;p++)
			{
				if ((pHitData[p].type&TYPEPART)==RAMP_H)
				{
					swap[low++]=&pHitData[p];
				}
			}
			for (p=0;p<nPolysHit;p++)
			{
				if ((pHitData[p].type&TYPEPART)==EDGE || (pHitData[p].type&TYPEPART)==CORNER)
				{
					swap[low++]=&pHitData[p];
				}
				else if ((pHitData[p].type&TYPEPART)==PLANE)
				{
					swap[hi--]=&pHitData[p];
				}
			}
			for (p=0;p<nPolysHit;p++)
			{
				if ((pHitData[p].type&TYPEPART)!=RAMP_H && (pHitData[p].type&TYPEPART)!=PLANE && (pHitData[p].type&TYPEPART)!=EDGE && (pHitData[p].type&TYPEPART)!=CORNER && (pHitData[p].type&TYPEPART)!=128) // 128=remove edge
				{
					swap[low++]=&pHitData[p];
				}
			}
		}
		else
		{
			swap[0] = &pHitData[0];
		}

		pD->lastHit=0;
		collPos.vx=pD->pPos->vx;
		collPos.vy=pD->pPos->vy;
		collPos.vz=pD->pPos->vz;

		SUBVECTOR(&v0v1, pD->pPos, &pD->oldPos);
		magv0v1=Magnitude(&v0v1);

		CopyVector(&planeRebound, pD->pVel);


		for(p=0; p<nPolysHit; p++)
		{
			switch( (swap[p]->type&TYPEPART) )
			{
			case RAMP_H:
				UpdateRampCollision(pD , swap[p], &collPos , &vRebound[reboundcount++]);
				//if (pD==&cameraColl) DB("ramp updated\n");
				break;
			case PLANE:
				UpdatePlaneCollision(pD , swap[p], &collPos , &vRebound[reboundcount++]);
				//if (pD==&cameraColl) DB("plane updated\n");
				flag=TRUE;
				break;
			case EDGE:
				UpdateEdgeCollision(pD , swap[p], &collPos , &vRebound[reboundcount++]);
				//if (pD==&cameraColl) DB("edge updated\n");
				break;
			case CORNER:
				UpdateCornerCollision(pD , swap[p],&collPos ,&vRebound[reboundcount++]);
				//if (pD==&cameraColl) DB("corner updated\n");
				break;
			}
		}

/*
			if (pHitData[p].type==PLANE)
			{
				UpdatePlaneCollision(pD , &pHitData[p] , &collPos , &planeRebound);
				flag=TRUE;
			}
		}
		for(p=0; p<nPolysHit; p++)
		{
			CopyVector(&vRebound[reboundcount], pD->pVel);

			if (pHitData[p].type==EDGE)
			{
				UpdateEdgeCollision(pD , &pHitData[p] , &collPos , &vRebound[reboundcount++]);
			}
			else if (pHitData[p].type==CORNER)
			{
				UpdateCornerCollision(pD , &pHitData[p] , &collPos , &vRebound[reboundcount++]);
			}
			else if (pHitData[p].type==RAMP_H)
			{
				//UpdateCornerCollision(pD , &pHitData[p] , &collPos , &vRebound[reboundcount++]);
				UpdateRampCollision(pD , &pHitData[p] , &collPos , &vRebound[reboundcount++]);
			}
		}
*/

		vTempRebound.vx=0;
		vTempRebound.vy=0;
		vTempRebound.vz=0;
		for(p=0; p<reboundcount; p++)
		{
			vTempRebound.vx+=vRebound[p].vx;
			vTempRebound.vy+=vRebound[p].vy;
			vTempRebound.vz+=vRebound[p].vz;
		}
		if (flag==TRUE)
		{
			vTempRebound.vx+=planeRebound.vx;
			vTempRebound.vy+=planeRebound.vy;
			vTempRebound.vz+=planeRebound.vz;
			reboundcount++;
		}

		vTempRebound.vx/=reboundcount;
		vTempRebound.vy/=reboundcount;
		vTempRebound.vz/=reboundcount;


//		vTempRebound.vx-=vTempRebound.vx/50;
//		vTempRebound.vy-=vTempRebound.vy/50;
//		vTempRebound.vz-=vTempRebound.vz/50;
		CopyVector(pD->pVel, &vTempRebound);
	}
	CopyVector(&pD->oldPos, pD->pPos);
	return(nPolysHit);
}


/*	--------------------------------------------------------------------------------
	Function 	: collboxAddBox
	Purpose 	: Adds a collision box to the list
	Parameters 	: 
	Returns 	: coll box
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//
int	g=4000/4; 
/*
void collboxAddBox(int pX,int pY,int pZ, int sX,int sY,int sZ,
				   int orient, int boxType, int bColl)
{
	ULONG 	flags;
	int 	i;
	// we need to construct normals for each of the faces
	// in a normal box, faces are in the order of:
	// D_XZPLANE, U_XZPLANE, D_YZPLANE, U_YZPLANE, D_XYPLANE, U_XYPLANE

	for(i=0; i<6; i++)
		ZeroVector((collBox[bCtr].n)+i);

	//collBox[bCtr].n[0].v[1]=4096;
	//collBox[bCtr].n[1].v[1]=-4096;
	//collBox[bCtr].n[2].v[0]=4096;
	//collBox[bCtr].n[3].v[0]=-4096;
	//collBox[bCtr].n[4].v[2]=4096;
	//collBox[bCtr].n[5].v[2]=-4096;

	collBox[bCtr].n[0].vy=4096;
	collBox[bCtr].n[1].vy=-4096;
	collBox[bCtr].n[2].vx=4096;
	collBox[bCtr].n[3].vx=-4096;
	collBox[bCtr].n[4].vz=4096;
	collBox[bCtr].n[5].vz=-4096;

	collBox[bCtr].pX=pX;
	collBox[bCtr].pY=pY;
	collBox[bCtr].pZ=pZ;

	collBox[bCtr].sX=sX;
	collBox[bCtr].sY=sY;
	collBox[bCtr].sZ=sZ;

	printf("pos=(%d,%d,%d) size=(%d,%d,%d)\n", pX/4096,pY/4096,pZ/4096, sX/4096,sY/4096,sZ/4096);

	flags=0;
	switch( boxType & TYPEPART )
	{
	case RAMP:
		//flags|=0x8;
		flags|=RAMP;
		flags|=(boxType & SPECIALPART);
		break;

	case BOX:	// don't do anything
		flags|=(boxType & SPECIALPART);
		break;

	}

	collBox[bCtr].flags=flags;
	bCtr++;
}
*/
/*	--------------------------------------------------------------------------------
	Function 	: CheckCorners
	Purpose 	: Checks all the corners of a box to see if hit or not
	Parameters 	: Collision box to check
	Returns 	: If hit incs number of hits and stores corner pos
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//


int pFaceOrder[]={D_XZPLANE, U_XZPLANE, D_YZPLANE, U_YZPLANE, D_XYPLANE, U_XYPLANE};

int pEdgeOrder[]={U_XYPLANE|U_XZPLANE, U_XZPLANE|D_XYPLANE, D_XYPLANE|D_XZPLANE, U_XYPLANE|D_XZPLANE,
				  U_XYPLANE|U_YZPLANE, U_YZPLANE|D_XYPLANE, D_XYPLANE|D_YZPLANE, U_XYPLANE|D_YZPLANE,
				  U_XZPLANE|U_YZPLANE, U_YZPLANE|D_XZPLANE, D_XZPLANE|D_YZPLANE, U_XZPLANE|D_YZPLANE};

int pCornerOrder[]={U_XYPLANE|U_XZPLANE|U_YZPLANE, U_XYPLANE|U_XZPLANE|D_YZPLANE,
					U_XYPLANE|D_XZPLANE|D_YZPLANE, U_XYPLANE|D_XZPLANE|U_YZPLANE,
					D_XYPLANE|U_XZPLANE|U_YZPLANE, D_XYPLANE|U_XZPLANE|D_YZPLANE,
					D_XYPLANE|D_XZPLANE|D_YZPLANE, D_XYPLANE|D_XZPLANE|U_YZPLANE};


ULONG	CheckCorners( COLLBOX *pB , COLLDATA *pD, HITDATA *pHitData )
{
	long x1,x2;
	long y1,y2;
	long z1,z2,c;
	ULONG	bHit=0;
	ULONG	hitFlag=0;
	x1=pB->pX;
	x2=x1+(pB->sX);
	y1=pB->pY;
	y2=y1+(pB->sY);
	z1=pB->pZ;
	z2=z1+(pB->sZ);


	for(c=0; c<8; c++)
	{ 
		switch(c)
		{
			// front of box
			case 0:
				bHit=collboxHasBallHitCorner(pD, x1,y1,z1);
				break;
			case 1:
				bHit=collboxHasBallHitCorner(pD, x2,y1,z1);
				break;
			case 2:
				bHit=collboxHasBallHitCorner(pD, x2,y2,z1);
				break;
			case 3:
				bHit=collboxHasBallHitCorner(pD, x1,y2,z1);
				break;
			// back of box
			case 4:
				bHit=collboxHasBallHitCorner(pD, x1,y1,z2);
				break;
			case 5:
				bHit=collboxHasBallHitCorner(pD, x2,y1,z2);
				break;
			case 6:
				bHit=collboxHasBallHitCorner(pD, x2,y2,z2);
				break;
			case 7:
				bHit=collboxHasBallHitCorner(pD, x1,y2,z2);
		}
		if(bHit)
		{
			if (PRINTHITPOS) printf("Hit CORNER!\n");
			pHitData->type=CORNER;
			pHitData->plane=pCornerOrder[c];
			pHitData->pCollBox=pB;
			CopyVector( &(pHitData->pos), &(pD->hitPos));
			hitFlag=TRUE;
			//nPolysHit++;
			//return (TRUE);
		}
		//else return (FALSE);
	}
	return (hitFlag);
}

/*	--------------------------------------------------------------------------------
	Function 	: collboxHasBallHitCorner
	Purpose 	: Checks if ball has hit corner
	Parameters 	: Corner position
	Returns 	: 0 if no hit !0 if hit
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//


int collboxHasBallHitCorner(COLLDATA *pD, int x, int y, int z)
{
	VECTOR *hitP=&pD->hitPos;	
	VECTOR d;	// changed from FVECTOR
	int bHit=0;

	//d.v[0]=(pD->pPos->v[0])-x;
	//d.v[1]=(pD->pPos->v[1])-y;
	//d.v[2]=(pD->pPos->v[2])-z;

	d.vx=(pD->pPos->vx)-x;
	d.vy=(pD->pPos->vy)-y;
	d.vz=(pD->pPos->vz)-z;


	if(Magnitude(&d)<(pD->radius))
	{
		//hitP->v[0]=x;
		//hitP->v[1]=y;
		//hitP->v[2]=z;
		hitP->vx=x;
		hitP->vy=y;
		hitP->vz=z;

		bHit++;
	}

	return(bHit);
}


/*	--------------------------------------------------------------------------------
	Function 	: CheckEdges
	Purpose 	: Checks all the edges of a box to see if hit or not
	Parameters 	: Collision box to check
	Returns 	: If hit incs number of hits and stores corner pos
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//
ULONG	CheckEdges(COLLBOX *pB , COLLDATA *pD , HITDATA *pHitData )
{

	long 	x1,x2;
	long 	y1,y2;
	long 	z1,z2;
	long 	e;
	ULONG	bHit=0;	
	ULONG	hitFlag=0;

	x1=pB->pX;
	x2=x1+(pB->sX);
	y1=pB->pY;
	y2=y1+(pB->sY);
	z1=pB->pZ;
	z2=z1+(pB->sZ);
	//if (pHitData[i].type!=FALSE) continue;
	// check edges of box (there's 4 X, 4 Y and 4 Z edges)
	for(e=0; e<12; e++)
	{ 
		switch(e)
		{
			// X edges
			case 0:
				bHit=collboxHasBallHitEdge(pD, XAXIS, x1,x2, y1,z1);
				break;
			case 1:
				bHit=collboxHasBallHitEdge(pD, XAXIS, x1,x2, y1,z2);
				break;
			case 2:
				bHit=collboxHasBallHitEdge(pD, XAXIS, x1,x2, y2,z2);
				break;
			case 3:
				bHit=collboxHasBallHitEdge(pD, XAXIS, x1,x2, y2,z1);
				break;
			// Y edges
			case 4:
				bHit=collboxHasBallHitEdge(pD, YAXIS, y2,y1, x1,z1);
				break;
			case 5:
				bHit=collboxHasBallHitEdge(pD, YAXIS, y2,y1, x1,z2);
				break;
			case 6:
				bHit=collboxHasBallHitEdge(pD, YAXIS, y2,y1, x2,z2);
				break;
			case 7:
				bHit=collboxHasBallHitEdge(pD, YAXIS, y2,y1, x2,z1);
				break;
				// Z edges first
			case 8:
				bHit=collboxHasBallHitEdge(pD, ZAXIS, z1,z2, x1,y1);
				break;
			case 9:
				bHit=collboxHasBallHitEdge(pD, ZAXIS, z1,z2, x1,y2);
				break;
			case 10:
				bHit=collboxHasBallHitEdge(pD, ZAXIS, z1,z2, x2,y2);
				break;
			case 11:
				bHit=collboxHasBallHitEdge(pD, ZAXIS, z1,z2, x2,y1);
				break;
		}
		if(bHit)
		{
			if (PRINTHITPOS) printf ("hit edge!\n");
			pHitData->type=EDGE;
			pHitData->plane=pEdgeOrder[e];
			pHitData->pCollBox=pB;
			CopyVector(&(pHitData->pos), &(pD->hitPos));
			//nPolysHit++;
			hitFlag=TRUE;
		}
	}
	return (hitFlag);
}



/*	--------------------------------------------------------------------------------
	Function 	: collboxHasBallHitEdge
	Purpose 	: Checks if ball has hit edge
	Parameters 	: Edge position
	Returns 	: 0 if no hit !0 if hit
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//

int collboxHasBallHitEdge(COLLDATA *pD, int axis, int l1, int l2, int x, int y)
{
	VECTOR *hitP=&pD->hitPos;
	VECTOR d;		// changed from FVECTOR
	int bHit=0;

	//ZeroVector(&d);
	d.vx=0;
	d.vy=0;
	d.vz=0;

	switch(axis)
	{
	case XAXIS:	// I'm not going to recored the old for all these if errors check in source safe
/*		d.v[1]=(pD->pPos->v[1])-x;
		d.v[2]=(pD->pPos->v[2])-y;
		if((Magnitude(&d)<(pD->radius)) && ((pD->pPos->v[0])>l1) && ((pD->pPos->v[0])<l2))
		{
			hitP->v[0]=pD->pPos->v[0];
			hitP->v[1]=x;
			hitP->v[2]=y;
			bHit++;
		}
		break;*/
		d.vy=(pD->pPos->vy)-x;
		d.vz=(pD->pPos->vz)-y;
		if((Magnitude(&d)<(pD->radius)) && ((pD->pPos->vx)>l1) && ((pD->pPos->vx)<l2))
		{
			hitP->vx=pD->pPos->vx;
			hitP->vy=x;
			hitP->vz=y;
			bHit++;
		}
		break;

	case YAXIS:
		d.vx=(pD->pPos->vx)-x;
		d.vz=(pD->pPos->vz)-y;
		if((Magnitude(&d)<(pD->radius)) && ((pD->pPos->vy)>l1) && ((pD->pPos->vy)<l2))
		{
			hitP->vx=x;
			hitP->vy=pD->pPos->vy;
			hitP->vz=y;
			bHit++;
		}
		break;
	case ZAXIS:
		d.vx=(pD->pPos->vx)-x;
		d.vy=(pD->pPos->vy)-y;
		if((Magnitude(&d)<(pD->radius)) && ((pD->pPos->vz)>l1) && ((pD->pPos->vz)<l2))
		{
			hitP->vx=x;
			hitP->vy=y;
			hitP->vz=pD->pPos->vz;
			bHit++;
		}
		break;
	}
	return(bHit);
}




/*	--------------------------------------------------------------------------------
	Function 	: CheckPlanes
	Purpose 	: Checks all the planes on a box to see if hit or not
	Parameters 	: Collision box to check
	Returns 	: If hit incs number of hits and stores corner pos
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//



ULONG	CheckPlanes(COLLBOX *pB , COLLDATA *pD , HITDATA *pHitData )
{
	long 	x1,x2;
	long 	y1,y2;
	long 	z1,z2,f;
	ULONG	bHit=0;
	ULONG	hitFlag=0;
	long r=pD->radius;

	x1=pB->pX;
	x2=x1+(pB->sX);
	y1=pB->pY;
	y2=y1+(pB->sY);
	z1=pB->pZ;
	z2=z1+(pB->sZ);

	//if (pHitData[i].type!=FALSE) continue;

	// checks added for -ve numbers

	for(f=0; f<6; f++)
	{
		//if(DotProduct((pB->n)+f, pD->pVel)<0)
		//{
			switch(f)
			{
			case 0:
				bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], y2, r, x1,z1,x2,z2);
				break;
			case 1:
				bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], y1, -r, x1,z1,x2,z2);
				break;
			case 2:
				bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], x2, r, y1,z1,y2,z2);
				break;
			case 3:
				bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], x1, -r, y1,z1,y2,z2);
				break;
			case 4:
				bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], z2, r, x1,y1,x2,y2);
				break;
			case 5:
				bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], z1, -r, x1,y1,x2,y2);
				break;
			default:
				printf("Bollocks\n");
				CRASH;
			}

			if(bHit)
			{
				//if ((pB->flags & SPECIALPART)==COLLBOXFLAG_MOVE ) printf ("hit plane on current position\n");
				pHitData->type=PLANE;
				pHitData->plane=pFaceOrder[f];
				CopyVector(&(pHitData->pos), &(pD->hitPos));
				pHitData->pCollBox=pB;
				//nPolysHit++;
				//return (TRUE);
				hitFlag=TRUE;
			}
		//}
	}


	if (hitFlag!=TRUE && (pB->flags & SPECIALPART)==COLLBOXFLAG_MOVE )
	{
		x1=pB->oldpX;
		x2=x1+(pB->sX);
		y1=pB->oldpY;
		y2=y1+(pB->sY);
		z1=pB->oldpZ;
		z2=z1+(pB->sZ);

		for(f=0; f<6; f++)
		{
			//if(DotProduct((pB->n)+f, pD->pVel)<0)
			//{
				switch(f)
				{
				case 0:
					bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], y2, r, x1,z1,x2,z2);
					break;
				case 1:
					bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], y1, -r, x1,z1,x2,z2);
					break;
				case 2:
					bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], x2, r, y1,z1,y2,z2);
					break;
				case 3:
					bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], x1, -r, y1,z1,y2,z2);
					break;
				case 4:
					bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], z2, r, x1,y1,x2,y2);
					break;
				case 5:
					bHit=collboxHasVectorCrossedPoly(pD, pFaceOrder[f], z1, -r, x1,y1,x2,y2);
					break;
				default:
					printf("Bollocks\n");
					CRASH;
				}
	
				if(bHit)
				{
					printf ("hit plane on old position\n");
					pHitData->type=PLANE;
					pHitData->plane=pFaceOrder[f];
					CopyVector(&(pHitData->pos), &(pD->hitPos));
					pHitData->pCollBox=pB;
					//nPolysHit++;
					//return (TRUE);
					hitFlag=TRUE;
				}
			//}
		}
	}



	return (hitFlag);
}


/*	--------------------------------------------------------------------------------
	Function 	: collboxHasVectorCrossedPoly
	Purpose 	: Checks if ball has crossed plane
	Parameters 	: plane position
	Returns 	: 0 if no hit !0 if hit
	Info 		: Does'nt work with moving boxes
*/
//-------------------------------------------------------------------------------//

int collboxHasVectorCrossedPoly(COLLDATA *pD, int plane, int planePos, int r, int x1, int y1, int x2, int y2)
{
	long xDist,yDist,zDist;
	long xInt,yInt,zInt;
	long xPos,xNeg,yPos,yNeg,zPos,zNeg, div;
	VECTOR *oldP=&pD->oldPos;
	VECTOR *newP=pD->pPos;
	VECTOR *hitP=&pD->hitPos;	// changed from FVECTOR
	int bHit=FALSE;

	switch(plane)
	{
	case D_XZPLANE:	// In case of errors check in source safe
		//if ( (newP->v[Y]<planePos) && (planePos-(newP->v[Y]+r))<0)
		if ( ((newP->vy+r)>planePos) && ((newP->vy-r)<planePos) )
		{
			xDist=(newP->vx)-(oldP->vx);
			yDist=(newP->vy)-(oldP->vy);
			zDist=(newP->vz)-(oldP->vz);

			//div=(yPos*4096)/yDist;
			xInt=newP->vx;
			zInt=newP->vz;

			// is it inside our bounds?
			if((xInt>=x1) && (xInt<x2) && (zInt>=y1) && (zInt<y2))
			{
				//printf ("d_xy\n");
				bHit=TRUE;
				//oldP->v[Y]=newP->v[Y]=planePos+r;
				hitP->vx=xInt;
				//hitP->vy=planePos+r;
				hitP->vy=planePos-r;
				hitP->vz=zInt;
			}
		}
		break;

	case U_XZPLANE:
		if ( ((newP->vy+r)<planePos) && ((newP->vy-r)>planePos) )
		{
			xDist=(newP->vx)-(oldP->vx);
			yDist=(newP->vy)-(oldP->vy);
			zDist=(newP->vz)-(oldP->vz);

			//div=(yPos*4096)/yDist;
			xInt=newP->vx;
			zInt=newP->vz;

			// is it inside our bounds?
			if((xInt>=x1) && (xInt<x2) && (zInt>=y1) && (zInt<y2))
			{
				//printf ("u_xy\n");
				bHit=TRUE;
				//hitP->vx=xInt;
				hitP->vx=newP->vx;
				hitP->vy=planePos-r;
				//hitP->vz=zInt;
				hitP->vz=newP->vz;
			}
		}
		break;

	case D_YZPLANE:
		if ( ((newP->vx+r)>planePos) && ((newP->vx-r)<planePos) )
		{
			xDist=(newP->vx)-(oldP->vx);
			yDist=(newP->vy)-(oldP->vy);
			zDist=(newP->vz)-(oldP->vz);

			//div=(yPos*4096)/yDist;
			yInt=newP->vy;
			zInt=newP->vz;
			// is it inside our bounds?
			// Seams to have truble with -ve numbers
			xInt=x1;
			x1=x2;
			x2=xInt;


			if((yInt>=x1) && (yInt<x2) && (zInt>=y1) && (zInt<y2))
			{
				//printf ("d_yz\n");
				bHit=TRUE;
				//oldP->v[X]=(newP->v[X]=planePos+r)+4096;
				//hitP->vx=(planePos+r)+4096;
				hitP->vx=(planePos+r);
				//hitP->vy=yInt;
				//hitP->vz=zInt;
				hitP->vy=newP->vy;
				hitP->vz=newP->vz;
			}
		}
		break;


	case U_YZPLANE:
		if ( ((newP->vx+r)<planePos) && ((newP->vx-r)>planePos) )
		{
			xDist=(newP->vx)-(oldP->vx);
			yDist=(newP->vy)-(oldP->vy);
			zDist=(newP->vz)-(oldP->vz);

			//div=(yPos*4096)/yDist;
			yInt=newP->vy;
			zInt=newP->vz;

			// is it inside our bounds?
			xInt=x1;
			x1=x2;
			x2=xInt;

			if((yInt>=x1) && (yInt<x2) && (zInt>=y1) && (zInt<y2))
			{
				//printf ("u_yz\n");
				bHit=TRUE;
				//oldP->v[X]=newP->v[X]=(planePos+r)-4096;
				//hitP->vx=(planePos+r)-4096;
				hitP->vx=(planePos+r);
				//hitP->vy=yInt;
				//hitP->vz=zInt;
				hitP->vy=newP->vy;
				hitP->vz=newP->vz;
			}
		}
		break;


/*		// work out distance from initial point to YZ plane
		xPos=(oldP->v[0])-(planePos+r);
		xNeg=(newP->v[0])-(planePos+r);
		//printf("yAbove=%d, yBelow=%d planePos=%d\n", xPos/4096, xNeg/4096, planePos/4096);

		if((xPos^xNeg)&0x80000000)
		{	// signs are different, crossing plane
			//printf("Different ...\n");
			xDist=(newP->v[0])-(oldP->v[0]);
			yDist=(newP->v[1])-(oldP->v[1]);
			zDist=(newP->v[2])-(oldP->v[2]);

			div=(xPos*4096)/xDist;
			yInt=((yDist*div)/4096)+(oldP->v[1]);
			zInt=((zDist*div)/4096)+(oldP->v[2]);

			// is it inside our bounds?
			if((yInt>=x1) && (yInt<x2) && (zInt>=y1) && (zInt<y2))
			{
				bHit=TRUE;
				hitP->v[0]=planePos+r;
				hitP->v[1]=yInt;
				hitP->v[2]=zInt;
			}
			//printf("x=%d-%d (%d), y=%d-%d (%d)\n", x1,x2,yInt, y1,y2,yInt);
		}
		break;
*/
	case D_XYPLANE:
		if ( ((newP->vz+r)>planePos) && ((newP->vz-r)<planePos) )
		{
			xDist=(newP->vx)-(oldP->vx);
			yDist=(newP->vy)-(oldP->vy);
			zDist=(newP->vz)-(oldP->vz);

			//div=(yPos*4096)/yDist;
			xInt=newP->vx;
			yInt=newP->vy;

			zInt=y1;
			y1=y2;
			y2=zInt;
			
			// is it inside our bounds?
			if((xInt>=x1) && (xInt<x2) && (yInt>=y1) && (yInt<y2))
			{
				bHit=TRUE;
				hitP->vx=xInt;
				hitP->vy=yInt;
				hitP->vz=planePos+r;
			}
		}
		break;

	case U_XYPLANE:
		if ( ((newP->vz+r)<planePos) && ((newP->vz-r)>planePos) )
		{
			xDist=(newP->vx)-(oldP->vx);
			yDist=(newP->vy)-(oldP->vy);
			zDist=(newP->vz)-(oldP->vz);

			//div=(yPos*4096)/yDist;
			xInt=newP->vx;
			yInt=newP->vy;

			zInt=y1;
			y1=y2;
			y2=zInt;

			// is it inside our bounds?
			if((xInt>=x1) && (xInt<x2) && (yInt>=y1) && (yInt<y2))
			{
				bHit=TRUE;
				hitP->vx=xInt;
				hitP->vy=yInt;
				hitP->vz=planePos+r;
			}
		}
		break;

/*
		// work out distance from initial point to YZ plane
		zPos=(oldP->v[2])-(planePos+r);
		zNeg=(newP->v[2])-(planePos+r);
		//printf("yAbove=%d, yBelow=%d planePos=%d\n", xPos/4096, xNeg/4096, planePos/4096);

		if((zPos^zNeg)&0x80000000)
		{	// signs are different, crossing plane
			//printf("Different ...\n");
			xDist=(newP->v[0])-(oldP->v[0]);
			yDist=(newP->v[1])-(oldP->v[1]);
			zDist=(newP->v[2])-(oldP->v[2]);

			div=(zPos*4096)/zDist;
			yInt=((yDist*div)/4096)+(oldP->v[1]);
			xInt=((xDist*div)/4096)+(oldP->v[0]);

			// is it inside our bounds?
			if((xInt>=x1) && (xInt<x2) && (yInt>=y1) && (yInt<y2))
			{
				bHit=TRUE;
				hitP->v[0]=xInt;
				hitP->v[1]=yInt;
				hitP->v[2]=planePos+r;
			}
		}*/
	}
	return(bHit);
}


/*	--------------------------------------------------------------------------------
	Function 	: UpdateEdgeCollision
	Purpose 	: Checks if ball has crossed plane
	Parameters 	: plane position
	Returns 	: 0 if no hit !0 if hit
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//

//FVECTOR vRebound[MAXCOLLOSIONS], vTempRebound;

void	UpdateEdgeCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound)
{

	VECTOR	objectmove,normal;	// changed from FVECTOR
	long	deltaX,deltaY,deltaZ;
	long	mag;

	if ( pHitData->plane & D_XZPLANE ) // top 
	{
		if ( pHitData->plane & U_YZPLANE ) // left
		{
			// Top Left
			deltaX=( pHitData->pos.vx - pD->pPos->vx );
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=0;

			if (deltaX<0) deltaX=0;
			if (deltaY<0) deltaY=0;
			if (deltaX==0 && deltaY==0) deltaY=4096;	// Can happen if ball moving fast enought (what ball?)

			objectmove.vx=-deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );
				
			if ( (pD->pPos->vx > pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;
		}
		else if ( pHitData->plane & D_YZPLANE ) // right
		{
			// Top Right
			deltaX=( pHitData->pos.vx - pD->pPos->vx );
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=0;

			if (deltaX>0) deltaX=0;
			if (deltaY<0) deltaY=0;
			if (deltaX==0 && deltaY==0) deltaY=4096;	// Can happen if ball moving fast enought (not in this game!)

			objectmove.vx=-deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );
				
			if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;
		}
		else if ( pHitData->plane & U_XYPLANE ) // close
		{
			// Top Near
			deltaX=0;
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=( pHitData->pos.vz - pD->pPos->vz );

			if (deltaY<0) deltaY=0;
			if (deltaZ<0) deltaZ=0;
			if (deltaY==0 && deltaZ==0) deltaY=4096;	// Can happen if ball moving fast enought (nope definatly no balls here)

			objectmove.vx=deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );

			if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

			if ( (pD->pPos->vz > pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}
		else if ( pHitData->plane & D_XYPLANE ) // far
		{
			// Top Far
			deltaX=0;
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=( pHitData->pos.vz - pD->pPos->vz );

			if (deltaY<0) deltaY=0;
			if (deltaZ>0) deltaZ=0;
			if (deltaY==0 && deltaZ==0) deltaY=4096;	// Can happen if ball moving fast enought (no balls no bounce)

			objectmove.vx=deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );

			if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

			if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}
		else if (PRINTERROR) printf ("ERROR on top plane\n");
	}
	else if ( pHitData->plane & U_XZPLANE ) // bottom
	{
		if ( pHitData->plane & U_YZPLANE ) // left
		{
			// Bottom left
			deltaX=( pHitData->pos.vx - pD->pPos->vx );
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=0;

			if (deltaX<0) deltaX=0;
			if (deltaY>0) deltaY=0;

			objectmove.vx=-deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );
				
			if ( (pD->pPos->vx > pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

		}
		else if ( pHitData->plane & D_YZPLANE ) // right
		{
			// Bottom Right
			deltaX=( pHitData->pos.vx - pD->pPos->vx );
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=0;

			if (deltaX>0) deltaX=0;
			if (deltaY>0) deltaY=0;

			objectmove.vx=-deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );
				
			if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;
		}
		else if ( pHitData->plane & U_XYPLANE ) // close
		{
			// Bottom Near
			deltaX=0;
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=( pHitData->pos.vz - pD->pPos->vz );

			if (deltaY>0) deltaY=0;
			if (deltaZ<0) deltaZ=0;

			objectmove.vx=deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR( &objectmove , (pD->radius+1) );

			if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

			if ( (pD->pPos->vz > pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}

		else if ( pHitData->plane & D_XYPLANE ) // far
		{
			// Bottom Far
			deltaX=0;
			deltaY=( pHitData->pos.vy - pD->pPos->vy );
			deltaZ=( pHitData->pos.vz - pD->pPos->vz );

			if (deltaY>0) deltaY=0;
			if (deltaZ>0) deltaZ=0;

			objectmove.vx=deltaX;
			objectmove.vy=-deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );

			if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
				pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

			if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}
		else if (PRINTERROR) printf ("ERROR on bottom plane\n");
	}
	else if ( pHitData->plane & D_YZPLANE ) // right
	{
		if ( pHitData->plane & D_XYPLANE ) // far
		{
			// Right Far
			deltaX=( pHitData->pos.vx - pD->pPos->vx);
			deltaY=0;
			deltaZ=( pHitData->pos.vz - pD->pPos->vz);

			if (deltaX>0) deltaX=0;
			if (deltaZ>0) deltaZ=0;

			objectmove.vx=-deltaX;
			objectmove.vy=deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );

			if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}
		else if ( pHitData->plane & U_XYPLANE ) // close
		{
			// Right Near
			deltaX=( pHitData->pos.vx - pD->pPos->vx);
			deltaY=0;
			deltaZ=( pHitData->pos.vz - pD->pPos->vz);

			if (deltaX>0) deltaX=0;
			if (deltaZ<0) deltaZ=0;

			objectmove.vx=-deltaX;
			objectmove.vy=deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );

			if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vz > pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}
		else if (PRINTERROR) printf ("error on left\n");
	}
	else if ( pHitData->plane & U_YZPLANE ) // left
	{
		if ( pHitData->plane & D_XYPLANE ) // far
		{
			// Left Far
			deltaX=( pHitData->pos.vx - pD->pPos->vx);
			deltaY=0;
			deltaZ=( pHitData->pos.vz - pD->pPos->vz);

			if (deltaX<0) deltaX=0;
			if (deltaZ>0) deltaZ=0;

			objectmove.vx=-deltaX;
			objectmove.vy=deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );

			if ( (pD->pPos->vx > pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}
		else if ( pHitData->plane & U_XYPLANE ) // close
		{
			// Left near
			deltaX=( pHitData->pos.vx - pD->pPos->vx);
			deltaY=0;
			deltaZ=( pHitData->pos.vz - pD->pPos->vz);

			if (deltaX<0) deltaX=0;
			if (deltaZ<0) deltaZ=0;

			objectmove.vx=-deltaX;
			objectmove.vy=deltaY;
			objectmove.vz=-deltaZ;
			MakeUnit(&objectmove);

			normal.vx=objectmove.vx;
			normal.vy=objectmove.vy;
			normal.vz=objectmove.vz;

			SCALEVECTOR(&objectmove,(pD->radius+1) );

			if ( (pD->pPos->vx > pHitData->pos.vx+objectmove.vx) && (deltaX) )
				pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

			if ( (pD->pPos->vz > pHitData->pos.vz+objectmove.vz) && (deltaZ) )
				pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
		}
		else if (PRINTERROR) printf ("error on right\n");
	}
	else if (PRINTERROR) printf ("ERROR with Edge\n");
	normal.vx=-normal.vx;
	normal.vz=-normal.vz;

	mag=Magnitude(pD->pVel);

	CopyVector(&pHitData->normal, &normal);

	CopyVector(rebound, pD->pVel);
	CalcBounce(rebound, &normal);
	SCALEVECTOR(rebound,mag);

}




/*	--------------------------------------------------------------------------------
	Function 	: UpdateCornerCollision
	Purpose 	: 
	Parameters 	: 
	Returns 	: 0 if no hit !0 if hit
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//

//FVECTOR vRebound[MAXCOLLOSIONS], vTempRebound;

void	UpdateCornerCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound)
{

	VECTOR	objectmove,normal;	// changed from FVECTOR
	long	deltaX,deltaY,deltaZ;
	long	mag;

	if (PRINTHITPOS) printf ("hit corner\n");
	if ( pHitData->plane & D_XZPLANE ) // Top
	{
		if ( pHitData->plane & U_YZPLANE ) // Left
		{
			if ( pHitData->plane & U_XYPLANE ) // Near
			{
				//printf ("top left near\n");
				deltaX=( (pD->pPos->vx) - (pHitData->pos.vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pD->pPos->vz) - (pHitData->pos.vz) );
				// will need to put checks in
				if (deltaX>0) deltaX=0;
				if (deltaY>0) deltaY=0;
				if (deltaZ>0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);

				normal.vx=-deltaX;
				normal.vy=deltaY;
				normal.vz=-deltaZ;
				MakeUnit(&normal);

				SCALEVECTOR(&objectmove,(pD->radius+1) );
				
				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx > pHitData->pos.vx+objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

					if ( (pD->pPos->vz > pHitData->pos.vz+objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
				//}

				if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;
			}
			else if ( pHitData->plane & D_XYPLANE ) // Far
			{
				//printf ("top left far\n");
				deltaX=( (pD->pPos->vx) - (pHitData->pos.vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pD->pPos->vz) - (pHitData->pos.vz) );
				// will need to put checks in
				if (deltaX>0) deltaX=0;
				if (deltaY>0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);

				normal.vx=-deltaX;
				normal.vy=deltaY;
				normal.vz=-deltaZ;
				MakeUnit(&normal);

				SCALEVECTOR(&objectmove,(pD->radius+1) );
				
				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx > pHitData->pos.vx+objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

					if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
				//}

				if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;
			}
			else printf ("ERROR on corner 1\n");
		}
		if ( pHitData->plane & D_YZPLANE ) // Right
		{
			if ( pHitData->plane & U_XYPLANE ) // Near
			{
				//printf ("top right near\n");
				deltaX=( (pD->pPos->vx) - (pHitData->pos.vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pD->pPos->vz) - (pHitData->pos.vz) );
				// will need to put checks in
				if (deltaX<0) deltaX=0;
				if (deltaY>0) deltaY=0;
				if (deltaZ>0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);

				normal.vx=-deltaX;
				normal.vy=deltaY;
				normal.vz=-deltaZ;
				MakeUnit(&normal);

				SCALEVECTOR(&objectmove,(pD->radius+1) );
				
				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

					if ( (pD->pPos->vz > pHitData->pos.vz+objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
				//}

				if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;
			}
			else if ( pHitData->plane & D_XYPLANE ) // Far
			{
				//printf ("top right far\n");
				deltaX=( (pD->pPos->vx) - (pHitData->pos.vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pD->pPos->vz) - (pHitData->pos.vz) );
				// will need to put checks in
				if (deltaX<0) deltaX=0;
				if (deltaY>0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);

				normal.vx=-deltaX;
				normal.vy=deltaY;
				normal.vz=-deltaZ;
				MakeUnit(&normal);

				SCALEVECTOR(&objectmove,(pD->radius+1) );
				
				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

					if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
				//}

				if ( (pD->pPos->vy > pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;
			}
			else printf ("ERROR on corner 2\n");
		}
	}

	else if ( pHitData->plane & U_XZPLANE ) // Bottom
	{
		if ( pHitData->plane & U_YZPLANE ) // Left
		{
			if ( pHitData->plane & U_XYPLANE ) // Near
			{
				//printf ("bottom left near\n");
				deltaX=( (pHitData->pos.vx) - (pD->pPos->vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pHitData->pos.vz) - (pD->pPos->vz) );
				// will need to put checks in
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);
				SCALEVECTOR(&objectmove,(pD->radius+1) );

				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx > pHitData->pos.vx-objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx-objectmove.vx;

					if ( (pD->pPos->vz > pHitData->pos.vz-objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz-objectmove.vz;
				//}

				if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

				deltaX=( (pHitData->pos.vx) - (collPos->vx) );
				deltaY=( (collPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pHitData->pos.vz) - (collPos->vz) );
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				normal.vx=deltaX;
				normal.vy=deltaY;
				normal.vz=deltaZ;
				MakeUnit(&normal);
			}
			else if ( pHitData->plane & D_XYPLANE ) // Far
			{
				//printf ("bottom left far\n");
				deltaX=( (pHitData->pos.vx) - (pD->pPos->vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pD->pPos->vz) - (pHitData->pos.vz) );
				// will need to put checks in
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);
				SCALEVECTOR(&objectmove,(pD->radius+1) );

				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx > pHitData->pos.vx-objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx-objectmove.vx;

					if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
				//}

				if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

				deltaX=( (pHitData->pos.vx) - (collPos->vx) );
				deltaY=( (collPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (collPos->vz) - (pHitData->pos.vz) );
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				normal.vx=deltaX;
				normal.vy=deltaY;
				normal.vz=-deltaZ;
				MakeUnit(&normal);
			}
			else printf ("ERROR on corner 3\n");
		}
		else if ( pHitData->plane & D_YZPLANE ) // Right
		{
			if ( pHitData->plane & U_XYPLANE ) // Near
			{
				//printf ("bottom right near\n");
				deltaX=( (pD->pPos->vx) - (pHitData->pos.vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pHitData->pos.vz) - (pD->pPos->vz) );
				// will need to put checks in
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);
				SCALEVECTOR(&objectmove,(pD->radius+1) );

				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

					if ( (pD->pPos->vz > pHitData->pos.vz-objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz-objectmove.vz;
				//}

				if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

				deltaX=( (collPos->vx) - (pHitData->pos.vx) );
				//deltaY=( (pHitData->pos.vy) - (collPos->vy) );
				deltaY=( (collPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pHitData->pos.vz) - (collPos->vz) );
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				normal.vx=-deltaX;
				normal.vy=deltaY;
				normal.vz=deltaZ;
				MakeUnit(&normal);
			}
			else if ( pHitData->plane & D_XYPLANE ) // Far
			{
				//printf ("bottom right far\n");
				deltaX=( (pD->pPos->vx) - (pHitData->pos.vx) );
				deltaY=( (pD->pPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (pD->pPos->vz) - (pHitData->pos.vz) );
				// will need to put checks in
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				objectmove.vx=deltaX;
				objectmove.vy=deltaY;
				objectmove.vz=deltaZ;
				MakeUnit(&objectmove);
				SCALEVECTOR(&objectmove,(pD->radius+1) );

				//if (pD->nCornerHits<2)
				//{
					if ( (pD->pPos->vx < pHitData->pos.vx+objectmove.vx) && (deltaX) )
						pD->pPos->vx=pD->oldPos.vx=pHitData->pos.vx+objectmove.vx;

					if ( (pD->pPos->vz < pHitData->pos.vz+objectmove.vz) && (deltaZ) )
						pD->pPos->vz=pD->oldPos.vz=pHitData->pos.vz+objectmove.vz;
				//}
				if ( (pD->pPos->vy < pHitData->pos.vy+objectmove.vy) && (deltaY) )
					pD->pPos->vy=pD->oldPos.vy=pHitData->pos.vy+objectmove.vy;

				deltaX=( (collPos->vx) - (pHitData->pos.vx) );
				deltaY=( (collPos->vy) - (pHitData->pos.vy) );
				deltaZ=( (collPos->vz) - (pHitData->pos.vz) );
				if (deltaX<0) deltaX=0;
				if (deltaY<0) deltaY=0;
				if (deltaZ<0) deltaZ=0;

				normal.vx=-deltaX;
				normal.vy=deltaY;
				normal.vz=-deltaZ;
				MakeUnit(&normal);
			}
			else printf ("ERROR on corner 4\n");
		}
		else printf ("ERROR on corner 5\n");
	}
	CopyVector(&pHitData->normal, &normal);

//	pHitData->normal.vx=normal.vx;
//	pHitData->normal.vy=normal.vy;
//	pHitData->normal.vz=normal.vz;


/*	if ( (pHitData->pCollBox->flags & SPECIALPART)==COLLBOXFLAG_MOVE)
	{
		printf ("box moving\n");
		//deltaX=pD->pVel->vx;
		//pD->pVel->vx=( (pHitData->pCollBox->pX-pHitData->pCollBox->oldpX) + pD->pVel->vx)/2;
		pD->pVel->vy-=(pHitData->pCollBox->pY-pHitData->pCollBox->oldpY);
		//pD->pVel->vz+=(pHitData->pCollBox->pZ-pHitData->pCollBox->oldpZ);
	}

	mag=Magnitude(pD->pVel);
	CopyVector(rebound, pD->pVel);
	CalcBounce(rebound, &normal);
	SCALEVECTOR(rebound,mag);

	if ( (pHitData->pCollBox->flags & SPECIALPART)==COLLBOXFLAG_MOVE)
	{
		//printf ("box moving\n");
		//pD->pVel->vx-=(pHitData->pCollBox->pX-pHitData->pCollBox->oldpX);
		//pD->pVel->vx=deltaX;
		pD->pVel->vy+=(pHitData->pCollBox->pY-pHitData->pCollBox->oldpY);
		//pD->pVel->vz-=(pHitData->pCollBox->pZ-pHitData->pCollBox->oldpZ);
	}
*/
}




/*	--------------------------------------------------------------------------------
	Function 	: UpdatePlaneCollision
	Purpose 	: 
	Parameters 	: 
	Returns 	: 0 if no hit !0 if hit
	Info 		: No bugs found yet
*/
//-------------------------------------------------------------------------------//

void	UpdatePlaneCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound)
{

	long div, magv0v1, magv0v2,temp,temp1;
	VECTOR v0v2, v0v1, velDiff;	// changed from FVECTOR

	if ( (pHitData->pCollBox->flags & SPECIALPART)==COLLBOXFLAG_MOVE)
	{
//		printf ("box moving\n");
//		temp=pD->pVel->v[X];
//		temp1=pD->pVel->v[Z];
//		pD->pVel->v[X]=( (pHitData->pCollBox->pX-pHitData->pCollBox->oldpX) + pD->pVel->v[X])/2;
//		//pD->pVel->v[X]+=(pHitData->pCollBox->pX-pHitData->pCollBox->oldpX);
//		pD->pVel->v[Y]-=(pHitData->pCollBox->pY-pHitData->pCollBox->oldpY);
//		pD->pVel->v[Z]=( (pHitData->pCollBox->pZ-pHitData->pCollBox->oldpZ) + pD->pVel->v[Z])/2;
//		//pD->pVel->v[Z]+=(pHitData->pCollBox->pZ-pHitData->pCollBox->oldpZ);
	}
	//CopyVector(rebound , pD->pVel);

	SUBVECTOR(&v0v1, pD->pPos, &pD->oldPos);
	magv0v1=Magnitude(&v0v1);

 	if(magv0v1)
 	{
 		SUBVECTOR(&v0v2, &pHitData->pos, &pD->oldPos);
 		magv0v2=Magnitude(&v0v2);
 		div=(magv0v2*4096)/magv0v1;
 		SUBVECTOR(&velDiff, pD->pVel, &pD->oldVel);
 		SCALEVECTOR(&velDiff, div);
 		CopyVector(&pHitData->vel, &pD->oldVel);
 	}
 	else
 		CopyVector(&pHitData->vel, pD->pVel);

 	switch(pHitData->plane)
 	{
 		case D_XZPLANE:
			// new code
/*			pD->pPos->v[1]=pHitData->pos.v[1];
 			rebound->v[1]=-(rebound->v[1]*pD->bounce)/4096;
 			rebound->v[1]-=2*g; // WHY ?????
 			//pD->pPos->v[1]=pHitData->pos.v[1];
 			if(pHitData->plane==U_XZPLANE)
 				pD->pPos->v[1]--;
 			break;
*/
 		case U_XZPLANE:
 			if (PRINTHITPOS) printf("Hit XZ plane\n");
 			//rebound->vy=-(rebound->vy*pD->bounce)/4096;
 			rebound->vy=-(rebound->vy*pD->bounce)/4096;
 			
 			//rebound->vy-=2*g; // WHY ?????

			if ( (pHitData->pCollBox->flags & SPECIALPART) ==COLLBOXFLAG_MOVE)
 				rebound->vy+=( (pHitData->pCollBox->pY-pHitData->pCollBox->oldpY));// + pD->pVel->vx)/2;

 			pD->pPos->vy=pHitData->pos.vy;
 			if(pHitData->plane==U_XZPLANE)
 				pD->pPos->vy--;
 			break;
 		case D_YZPLANE:
 		case U_YZPLANE:
 			if (PRINTHITPOS) printf("Hit YZ plane\n");
 			rebound->vx=-(rebound->vx*pD->bounce)/4096;
			if ( (pHitData->pCollBox->flags & SPECIALPART) ==COLLBOXFLAG_MOVE)
	 			rebound->vx+=( (pHitData->pCollBox->pX-pHitData->pCollBox->oldpX));// + pD->pVel->vx)/2;
 			pD->pPos->vx=pHitData->pos.vx;
 			if(pHitData->plane==U_YZPLANE)
 				pD->pPos->vx--;	
 			break;
 		case D_XYPLANE:
 		case U_XYPLANE:
 			if (PRINTHITPOS) printf("Hit XY plane\n");
 			rebound->vz=-(rebound->vz*pD->bounce)/4096;
			if ( (pHitData->pCollBox->flags & SPECIALPART) ==COLLBOXFLAG_MOVE)
	 			rebound->vz+=( (pHitData->pCollBox->pZ-pHitData->pCollBox->oldpZ));// + pD->pVel->vx)/2;
 			pD->pPos->vz=pHitData->pos.vz;
 			if(pHitData->plane==U_XYPLANE)
 				pD->pPos->vz--;	
 			break;
 		default:
 			DB("ERROR: Bad plane! Hit at (%d,%d,%d)\n",
 					pHitData->pos.vx, pHitData->pos.vy, pHitData->pos.vz);
 	}
	if ( (pHitData->pCollBox->flags & SPECIALPART)==COLLBOXFLAG_MOVE)
	{
		//printf ("box moving\n");
		//pD->pVel->vx-=(pHitData->pCollBox->pX-pHitData->pCollBox->oldpX);
//		pD->pVel->vy+=(pHitData->pCollBox->pY-pHitData->pCollBox->oldpY);
		//pD->pVel->vz-=(pHitData->pCollBox->pZ-pHitData->pCollBox->oldpZ);
//		pD->pVel->vx=temp;
//		pD->pVel->vz=temp1;
	}
}


ULONG CheckRamps(COLLBOX *pB , COLLDATA *pD , HITDATA *pHitData)
{
	int vp;
	static VECTOR v1,v2;

	RAMPHEADER *pRampHeader;
	ULONG nVerts,nFaces;
	VECTOR *pVerts;
	ULONG *pFaces;
	ULONG f;
	int p;
	static VECTOR n,temp;
	static VECTOR iPos, iOldPos;
	static VECTOR vrt[3];

	long j,dist,dist2;
	long pX=pB->pX, pY=pB->pY, pZ=pB->pZ;
	long sX=pB->sX, sY=pB->sY, sZ=pB->sZ;
	int pt,k,touch;
	int tx,ty;
	static VECTOR a;
	long dr, dr2;

	static Point2DType twoDpoints[4];
	Point2DType *p2D=twoDpoints;

// Ramps are not really ramps as such. They're a mini mesh, which means we can collide with 
// arbitrary polygons within the bounding box. Slow, but we don't have to process very many.

	pRampHeader=pB->rampheader;
	nVerts=pRampHeader->nVerts;
	nFaces=pRampHeader->nFaces;
	pFaces=pRampHeader->pFaces;
	pVerts=pRampHeader->pVerts;

	iPos.vx=(pD->pPos->vx)/4096;
	iPos.vy=(pD->pPos->vy)/4096;
	iPos.vz=(pD->pPos->vz)/4096;

	iOldPos.vx=(pD->oldPos.vx)/4096;
	iOldPos.vy=(pD->oldPos.vy)/4096;
	iOldPos.vz=(pD->oldPos.vz)/4096;

	vp=0; // This stops compiler warning

	for(p=0; p<nFaces; p++)
	{
		f=pFaces[p];

		// flags: bit 0:   0=tri, 1=quad
		// bit 1&2: 00=arbitrary poly, 01=XY plane, 10=XZ plane, 11=YZ plane
		pt=f&6;

		f=f>>8;

		for(j=0; j<3; j++)
		{
			vp=f&(0x0f);
			f=f>>4;
			vrt[j].vx=pVerts[vp].vx/4096;
			vrt[j].vy=pVerts[vp].vy/4096;
			vrt[j].vz=pVerts[vp].vz/4096;
		}
 		SUBVECTOR(&v1, vrt, vrt+1);
		SUBVECTOR(&v2, vrt, vrt+2);
		n.vx=(v1.vy * v2.vz - v1.vz * v2.vy);
		n.vy=(v1.vz * v2.vx - v1.vx * v2.vz);
		n.vz=(v1.vx * v2.vy - v1.vy * v2.vx);
		MakeUnit(&n);
		a.vx = vrt->vx + pX/4096;
		a.vy = vrt->vy + pY/4096;
		a.vz = vrt->vz + pZ/4096;

		// Find distance of new pos from plane
		switch(pt)
		{
		case 2:// XY
			if (pD->pPos->vz>pD->oldPos.vz)
			{
				dist=pD->pPos->vz-(pVerts[vp].vz+pZ);
				dist2=pD->oldPos.vz-(pVerts[vp].vz+pZ);
			}
			else
			{
				dist2=pD->pPos->vz-(pVerts[vp].vz+pZ);
				dist=pD->oldPos.vz-(pVerts[vp].vz+pZ);
			}

			break;
		case 4:// XZ
			if (pD->pPos->vy>pD->oldPos.vy)
			{
				dist=pD->pPos->vy-(pVerts[vp].vy+pY);
				dist2=pD->oldPos.vy-(pVerts[vp].vy+pY);
			}
			else
			{
				dist2=pD->pPos->vy-(pVerts[vp].vy+pY);
				dist=pD->oldPos.vy-(pVerts[vp].vy+pY);
			}

			break;


		case 6:// YZ
			if (pD->pPos->vx>pD->oldPos.vx)
			{
				dist=pD->pPos->vx-(pVerts[vp].vx+pX);
				dist2=pD->oldPos.vx-(pVerts[vp].vx+pX);
			}
			else
			{
				dist2=pD->pPos->vx-(pVerts[vp].vx+pX);
				dist=pD->oldPos.vx-(pVerts[vp].vx+pX);
			}
			break;
		default:// a sloped ramp (not sure if these need to swap on direction)

			j=-DotProduct(&n, &a);
			dist=(DotProduct(&n, &iPos)+j)*4096;
			dist2=(DotProduct(&n, &iOldPos)+j)*4096;
		}

 		dr=dist+(pD->radius);
 		dr2=dist2-(pD->radius);
		if((dr>=0) && (dr2<=0))  //has hit somewhere on the plane, of infinate size
		{
			// Where on ramp have we hit?
			// normal may be needed later ...
			switch(pt)
			{
			case 2:
				COPYVECTOR(&(pD->hitPos), pD->pPos);
				pD->hitPos.vz=((pVerts[vp].vz)+pZ);// This causes a bug (fixed?)
				break;
			case 4:
				COPYVECTOR(&(pD->hitPos), pD->pPos);
				pD->hitPos.vy=((pVerts[vp].vy)+pY);//+(pD->radius);
				break;
			case 6:
				COPYVECTOR(&(pD->hitPos), pD->pPos);
				pD->hitPos.vx=((pVerts[vp].vx)+pX);// This causes a bug (fixed?)
				break;
			default:
				COPYVECTOR(&temp, &n);
				SCALEVECTOR(&temp, -dist);
				ADDVECTOR(&(pD->hitPos), pD->pPos, &temp);
			}
			// is it within the collision box?
			if(((pD->hitPos.vx)>=pX) && ((pD->hitPos.vx)<=(pX+sX)) &&
				((pD->hitPos.vy)<=pY) && ((pD->hitPos.vy)>=(pY+sY)) &&
				((pD->hitPos.vz)>=pZ) && ((pD->hitPos.vz)<=(pZ+sZ)))
			{
				touch=TRUE;
				if(pt)
				{
					switch(pt)
					{
					case 2:	//CDB("XY\n");
						for(k=0; k<3; k++)
						{
							p2D[k].x=(vrt[k].vx)+(pX/4096);
							p2D[k].y=(vrt[k].vy)+(pY/4096);
						}
						tx=pD->hitPos.vx/4096;
						ty=pD->hitPos.vy/4096;

						break;

					case 4:	//CDB("XZ\n");
						for(k=0; k<3; k++)
						{
							p2D[k].x=(vrt[k].vx)+(pX/4096);
							p2D[k].y=(vrt[k].vz)+(pZ/4096);
						}
						tx=pD->hitPos.vx/4096;
						ty=pD->hitPos.vz/4096;

						break;
					case 6:		//CDB("YZ\n");
						for(k=0; k<3; k++)
						{
							p2D[k].x=(vrt[k].vy)+(pY/4096);
							p2D[k].y=(vrt[k].vz)+(pZ/4096);
						}
						tx=pD->hitPos.vy/4096;
						ty=pD->hitPos.vz/4096;
						break;
					default:
						CRASH;
					}
					touch=pointInTri(tx,ty,p2D);  //is it inside triangle?
				}
				if(touch)
				{
					// interpolate back up to allow for radius
					COPYVECTOR( &(pHitData->rampPos),&(pD->hitPos) );
					COPYVECTOR(&temp, &n);
					SCALEVECTOR(&temp, -(pD->radius+1));
					ADDTOVECTOR(&(pD->hitPos), &temp);
					COPYVECTOR(&pHitData->pos, &(pD->hitPos));
					COPYVECTOR(&pHitData->vel, pD->pVel);

					pHitData->type=RAMP_H;
					pHitData->pCollBox=pB;
					COPYVECTOR(&pHitData->normal, &n);

					pHitData->plane=NULL;

					switch(pt)
					{
					case 2:
						if (pD->pVel->vz>0) pHitData->plane=D_XYPLANE;
						else pHitData->plane=U_XYPLANE;
						break;
					case 4:
						if (n.vy>0) pHitData->plane=D_XZPLANE;
						else pHitData->plane=U_XZPLANE;
						break;
					case 6:
						if (pD->pVel->vx>0) pHitData->plane=D_YZPLANE;
						else pHitData->plane=U_YZPLANE;
						break;
					}
					return(TRUE);
				}
			}
		}
	}
	return(0);
}

/*****************************************************************************************/

void UpdateRampCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound)
{
	pHitData->normal.vy=-pHitData->normal.vy;
	MakeUnit(&pHitData->normal);

	// Note:- don't change this back
	if ( pHitData->normal.vx>0 && (pD->pPos->vx>pHitData->pos.vx) ) pD->pPos->vx=pHitData->pos.vx;
	if ( pHitData->normal.vx<0 && (pD->pPos->vx<pHitData->pos.vx) ) pD->pPos->vx=pHitData->pos.vx;

	if ( pHitData->normal.vy<0 && (pD->pPos->vy>pHitData->pos.vy) ) pD->pPos->vy=pHitData->pos.vy;
	if ( pHitData->normal.vy>0 && (pD->pPos->vy<pHitData->pos.vy) ) pD->pPos->vy=pHitData->pos.vy;

	if ( pHitData->normal.vz>0 && (pD->pPos->vz>pHitData->pos.vz) ) pD->pPos->vz=pHitData->pos.vz;
	if ( pHitData->normal.vz<0 && (pD->pPos->vz<pHitData->pos.vz) ) pD->pPos->vz=pHitData->pos.vz;
}
/*****************************************************************************************/

void CopyVector(VECTOR *U, VECTOR *V)
{
	U->vx=V->vx;
	U->vy=V->vy;
	U->vz=V->vz;
}

ULONG	*reducedCollBox = NULL;
//#define	MAXCOLLCUBES 16384
#define	MAXCOLLCUBES 64		/* much smaller lookup table*/
#define COLLISIONBOXES	32

long	xSteps,ySteps,zSteps;
long	xStepLen,yStepLen,zStepLen;
long	startX,startY,startZ;
long	endX,endY,endZ;

int		debugcount=0;

// This is in the BFF compiler now
/*
void ReduceCollision(COLLBOX *pcollbox,long offset)
{
	long	minx,maxx,miny,maxy,minz,maxz,i,j,k,collLoop,checkLoop,checkFlag;
	//long	xSteps,ySteps,zSteps;
	//long	xStepLen,yStepLen,zStepLen;
	//long	startX,startY,startZ;
	ULONG	test;
	ULONG	*tempholder[64];
	ULONG	*tempmemblock;
	ULONG	*generalptr,*generalptr1;
	ULONG	collPos;
	ULONG	tempmemcount=0;
	COLLBOX	*pstartcollbox=pcollbox;

	reducedCollBox=(ULONG *)MALLOC(sizeof(ULONG)*MAXCOLLCUBES); // get mem for coll cubes
	
	tempmemblock=(ULONG *)MALLOC(sizeof(ULONG)*(MAXCOLLCUBES*16)); // get mem for coll cubes
	// With a smaller lookup table this needed to be much larger to stop mem overwights (I'd forgot how much of a pain this was)
	tempmemblock2 = tempmemblock;	// for freeing
	//minx=pcollbox->pX-offset;
	//miny=pcollbox->pY-offset;
	//minz=pcollbox->pZ-offset;

	if(pcollbox->sX<0)	minx=pcollbox->pX+pcollbox->sX;
	else minx=pcollbox->pX;
	if(pcollbox->sY<0)	miny=pcollbox->pY+pcollbox->sY;
	else miny=pcollbox->pY;
	if(pcollbox->sZ<0)	minz=pcollbox->pZ+pcollbox->sZ;
	else minz=pcollbox->pZ;

	if(pcollbox->sX>0)	maxx=pcollbox->pX+pcollbox->sX;
	else maxx=pcollbox->pX;
	if(pcollbox->sY>0)	maxy=pcollbox->pY+pcollbox->sY;
	else maxy=pcollbox->pY;
	if(pcollbox->sZ>0)	maxz=pcollbox->pZ+pcollbox->sZ;
	else maxz=pcollbox->pZ;

	//pcollbox++;
	for (i=0;i<numCollBoxes;i++)
	{
		if (pcollbox->flags==COLLBOXFLAG_UNUSED) // box unused
		{
			pcollbox++;
			continue;
		}
		if (pcollbox->sX>0)
		{
			if (minx>pcollbox->pX) minx=pcollbox->pX;
			if (maxx< (pcollbox->pX+pcollbox->sX) ) maxx=(pcollbox->pX+pcollbox->sX);
		}
		else
		{
			if (minx>(pcollbox->pX+pcollbox->sX)) minx=(pcollbox->pX+pcollbox->sX);
			if (maxx< pcollbox->pX ) maxx=pcollbox->pX;
		}
		if (pcollbox->sY>0)
		{
			if (miny>pcollbox->pY) miny=pcollbox->pY;
			if (maxy< (pcollbox->pY+pcollbox->sY) ) maxy=(pcollbox->pY+pcollbox->sY);
		}
		else
		{
			if (miny>(pcollbox->pY+pcollbox->sY)) miny=(pcollbox->pY+pcollbox->sY);
			if (maxy< pcollbox->pY ) maxy=pcollbox->pY;
		}
		if (pcollbox->sZ>0)
		{
			if (minz>pcollbox->pZ) minz=pcollbox->pZ;
			if (maxz< (pcollbox->pZ+pcollbox->sZ) ) maxz=(pcollbox->pZ+pcollbox->sZ);
		}
		else
		{
			if (minz>(pcollbox->pZ+pcollbox->sZ)) minz=(pcollbox->pZ+pcollbox->sZ);
			if (maxz< pcollbox->pZ ) maxz=pcollbox->pZ;
		}
		pcollbox++;
	}

	minx-=offset;
	miny-=offset;
	minz-=offset;

	maxx+=offset;
	maxy+=offset;
	maxz+=offset;

//	ySteps=10;
//	xSteps=zSteps=40;

	ySteps=1;
	xSteps=zSteps=8;


	xStepLen=(maxx-minx)/xSteps;
	yStepLen=(maxy-miny)/ySteps;
	zStepLen=(maxz-minz)/zSteps;

	startX=minx;
	startY=miny;
	startZ=minz;
	endX=maxx;
	endY=maxy;
	endZ=maxz;

	printf ("\nprocessing collision boxes\n");
	for (i=0;i<ySteps;i++)
	{
		for (j=0;j<zSteps;j++)
		{
			for (k=0;k<xSteps;k++)
			{
				minx=(startX+(xStepLen*k))-offset;
				maxx=minx+xStepLen+(offset*2);

				miny=(startY+(yStepLen*i))-offset;
				maxy=miny+yStepLen+(offset*2);

				minz=(startZ+(zStepLen*j))-offset;
				maxz=minz+zStepLen+(offset*2);
				// Now we need to find if any coll boxes intersect these
				pcollbox=pstartcollbox;
				test=0;
				//for (collLoop=0;collLoop<COLLISIONBOXES;collLoop++)
				for (collLoop=0;collLoop<numCollBoxes;collLoop++)
				{
					if (pcollbox->flags==COLLBOXFLAG_UNUSED) // box unused
					{
						pcollbox++;
						continue;
					}

					if (checkIntersection(pcollbox,minx,miny,minz,maxx,maxy,maxz) )
					{
						*(tempholder+test)=(ULONG*) pcollbox;
						test++;
					}
					pcollbox++;
				}
				if (test>63) printf ("an error has occured\n");
				collPos=k+(j*xSteps)+(i*(xSteps*zSteps));
				if (collPos==35)
				{
					DB("here\n");
				}
				if (test==0) *(reducedCollBox+collPos)=NULL;	// mark as empty
				else if (test==1)
				{
					*(reducedCollBox+collPos)=(ULONG)tempholder[0];
					*(reducedCollBox+collPos) |=0x80000000; // set top bit to mark as one only
				}
				else if (test>1)
				{
					//now need to scan prevouse and point to them to save memory
					checkFlag=FALSE;
					for (collLoop=0;collLoop<collPos;collLoop++)
					{
						generalptr= (ULONG *)*(reducedCollBox+collLoop);
						if (((unsigned int)(generalptr)) < 0x80000000) // Denotes more than one coll box
						{
							checkFlag=TRUE;
							//generalptr1=*generalptr;
							for (checkLoop=0;checkLoop<test;checkLoop++)
							{
								generalptr1=(ULONG *)(*generalptr);
								if (generalptr1!=*(tempholder+checkLoop) ) checkFlag=FALSE;
								generalptr++;
							}
							if (checkFlag==TRUE)// we have our match
							{
								*(reducedCollBox+collPos)=*(reducedCollBox+collLoop);
								break;
							}
						}
					}
					if (checkFlag!=TRUE)
					{
						*(reducedCollBox+collPos)= (ULONG)tempmemblock;
						for (collLoop=0;collLoop<test;collLoop++)
						{
							*(tempmemblock++) = (ULONG)*(tempholder+collLoop);
							tempmemcount++;
						}
						*(tempmemblock++)=NULL;
						tempmemcount++;
					}
				}
			}
			printf (".");
		}
	}
	DB ("end of routine\n");
	//printf ("size of collbox = %d\n",(sizeof(COLLBOX)) );
	DB ("tempmemcount = %d\n",tempmemcount);

	if (tempmemcount>=(MAXCOLLCUBES*16) )
	{
		DB("over right has occured \n");
		CRASH;
	}
}
*/




enum
{
	I_NEAR,
	I_FAR,
	I_LEFT,
	I_RIGHT,
	I_TOP,
	I_BOTTOM,
	NUM_OUTCODES
};



ULONG	checkIntersection(COLLBOX *pcollbox,long minX,long minY,long minZ,long maxX,long maxY,long maxZ)
{	
	unsigned char stage1_clip[6] = 
	{
		0, // Near
		0, // Far
		0, // Left
		0, // Right
		0, // Top
		0  // Bottom
	};
	int i;

	if (pcollbox->pX > maxX)
		stage1_clip[I_RIGHT]  |= (1 << 0);
	if ( (pcollbox->pX+pcollbox->sX) > maxX)
		stage1_clip[I_RIGHT]  |= (1 << 1);

	if (pcollbox->pX < minX)
		stage1_clip[I_LEFT]  |= (1 << 0);
	if ( (pcollbox->pX+pcollbox->sX) < minX)
		stage1_clip[I_LEFT]  |= (1 << 1);

	if (pcollbox->pY < minY)
		stage1_clip[I_BOTTOM] |= (1 << 0);
	if ( (pcollbox->pY+pcollbox->sY) < minY)
		stage1_clip[I_BOTTOM] |= (1 << 1);

	if (pcollbox->pY > maxY)
	  	stage1_clip[I_TOP]    |= (1 << 0);
	if ( (pcollbox->pY+pcollbox->sY) > maxY)
	  	stage1_clip[I_TOP]    |= (1 << 1);

	if (pcollbox->pZ > maxZ)
		stage1_clip[I_FAR]    |= (1 << 0);
	if ( (pcollbox->pZ+pcollbox->sZ) > maxZ)
		stage1_clip[I_FAR]    |= (1 << 1);

	if (pcollbox->pZ < minZ)
		stage1_clip[I_NEAR]   |= (1 << 0);
	if ( (pcollbox->pZ+pcollbox->sZ) < minZ)
		stage1_clip[I_NEAR]   |= (1 << 1);


 	for (i=0; i<6; i++)
	{
		if (stage1_clip[i] == 0x03)
		{
			return FALSE;
		}
	}
	return TRUE;
}


/**************************************************************************
	FUNCTION:	pointInPoly()
	PURPOSE:	Find if a point is in a poly
	PARAMETERS:	x,y of point, number of points, and a list of points
	RETURNS:	yes or no
**************************************************************************/
UBYTE pointInTri(long x, long y,Point2DType *edge)
{
LONG x0,x1,y0,y1,xx,yy;
ULONG inside=0,i;
	//DB("Hit=(%d,%d) ", x, y);
//	numOfPoints=3;

	// Move point in by one stops falling through cracks
	xx=(edge[0].x+edge[1].x+edge[2].x)/3;
	yy=(edge[0].y+edge[1].y+edge[2].y)/3;
	if (x>xx) x--;
	else x++;
	if (y>yy) y--;
	else y++;
 	i=4-1;
	while(i>0)
	{
		i--;
		x0=edge[i].x;
		y0=edge[i].y;
		x1=edge[(i+1)MOD 3].x;
		y1=edge[(i+1)MOD 3].y;

		//DB("[%d]=(%d,%d) ", i, x0,y0);
		if((y0>=y) != (y1>=y)) //so both y's are either > or < than y
		{
			if((x0>=x) == (x1>=x)) //so both x's are either > or < than x
			{
				if((x0>=x))inside++;
			}
			else //x's straddle y axis, need to check which side point is on
			{
				if( (x1 - (y1-y) * ( x0 - x1 ) / (y0 - y1)) >= x)inside++;
			}
		}
	}
	return inside&1;		
}
/**************************************************************************/

/**************************************************************************
	FUNCTION:	findClosestBox()
	PURPOSE:	finds the closest box along a line
	PARAMETERS:	start point end point box pointer
	RETURNS:	zip
**************************************************************************/

int		findClosestBox(int sX,int sY,int sZ,int eX,int eY,int eZ,COLLBOX *pBox,int objectCheck)
{
	VECTOR	vect2;
	COLLBOX *pB;
	long	x1,y1,z1,value;
	int		g1,g2,gradient,quadrant;
	volatile ULONG	*collptr,*collptr1;
	ULONG	collBoxPos;
	int		distance,match,distance1,match1;
	int		distance2[10];
	int		count=0;
	int		temp,temp1,loop;

	distance=distance1=0x7fffffff;
	match=0;

	pBox->pX=0;pBox->pY=0;pBox->pZ=0;
	pBox->sX=0;pBox->sY=0;pBox->sZ=0;

	vect2.vx=sX;
	vect2.vy=sY;
	vect2.vz=sZ;

	x1=sX-startX;
	y1=sY-startY;
	z1=sZ-startZ;

	x1/=xStepLen;
	y1/=yStepLen;
	z1/=zStepLen;

	if (x1<0 || x1>=xSteps) return (FALSE);
	if (y1>=ySteps) return (FALSE);
	if (z1<0 || z1>=zSteps) return (FALSE);
	if (y1 < 0) y1 = 0;

	// work out which quadrant to check in
	if (sX<eX)
	{
		if (sZ<eZ) quadrant=1;
		else quadrant=2;
	}
	else
	{
		if (sZ<eZ) quadrant=4;
		else quadrant=3;
	}
	// tbd changes back to voxel system using correct voxels for camera

	//pB=(COLLBOX *)(collBox+1);
	pB=boxes;
	for (loop=0;loop<numCollBoxes;loop++)
	{
		//pB=(COLLBOX*)collptr1;
		match1=TRUE;
		// Before doing all the complex calcs remove all boxes not possable to hit
		// not sure about these

		//if ( (sY < (pB->pY+pB->sY)) && (eY < (pB->pY+pB->sY)) ) match1=FALSE;
		if ( sY < (pB->pY+pB->sY) ) match1=FALSE;
		if ( (quadrant==1) && (((pB->pX+pB->sX)<sX) || ((pB->pZ+pB->sZ)<sZ) ) ) match1=FALSE;
		if ( (quadrant==2) && (((pB->pX+pB->sX)<sX) || (pB->pZ>sZ) ) ) match1=FALSE;

		if ( (quadrant==3) && ((pB->pX>sX) || (pB->pZ>sZ) ) ) match1=FALSE;
		if ( (quadrant==4) && ((pB->pX>sX) || ((pB->pZ+pB->sZ)<sZ) ) ) match1=FALSE;
		if ( pB->flags==RAMP) match1=FALSE;
		if ( eY>pB->pY ) match1=FALSE;

//		if ( (sX>(pB->pX-40960)) && (sX<(pB->pX+pB->sX+40960)) && (sZ>(pB->pZ-40960)) && (sZ<(pB->pZ+pB->sZ+40960)) ) match1=FALSE;// if inside box reject
//		if ( (eX>(pB->pX-40960)) && (eX<(pB->pX+pB->sX+40960)) && (eZ>(pB->pZ-40960)) && (eZ<(pB->pZ+pB->sZ+40960)) ) match1=FALSE;

//		if ( (sX>(pB->pX)) && (sX<(pB->pX+pB->sX)) && (sZ>(pB->pZ)) && (sZ<(pB->pZ+pB->sZ)) ) match1=FALSE;// if inside box reject
//		if ( (eX>(pB->pX)) && (eX<(pB->pX+pB->sX)) && (eZ>(pB->pZ)) && (eZ<(pB->pZ+pB->sZ)) ) match1=FALSE;

		if ( pB->camFlags&NOCAMCOLLIDE) // Note this may need to be changed if this routine is used for other things
		{
			match1=FALSE;
		}
		if ( (pB->camFlags&OBJECTCOLLIDE) && objectCheck)
		{
			match1=FALSE;
		}
		else if ( !(pB->camFlags&OBJECTCOLLIDE) && !objectCheck)
		{
			match1=FALSE;
		}

		distance1=0x7fffffff;

		if (match1) CheckBox(sX,sZ,eX,eZ,quadrant,&distance,&distance1,pBox,pB);

		if (!objectCheck)
		{
			if (distance1!=0x7fffffff) distance2[count++]=distance1;
		}

//		if (distance1<distance2)
//		{
//			distance3=distance2;
//			distance2=distance1;
//		}
		pB++;
	}
	if (count>1)
	{
		match=distance2[0];
		for (loop=1;loop<count;loop++)
		{
			if ( (distance2[loop]!=distance) && (match>distance2[loop]) ) match=distance2[loop];
		}
		return (match);
	}
	else return(0x7fffffff);
}

/**************************************************************************
	FUNCTION:	CheckBox()
	PURPOSE:	checks a  box along a line
	PARAMETERS:	start point, end point ,quadrant to check in,distance, box pointer ,box to check ptr
	RETURNS:	zip
	NOTE:		there is a load for printfs in here remove later there just for test purpases
**************************************************************************/

void	CheckBox(int sX,int sZ,int eX,int eZ,int quadrant,int *distance,int *distance1,COLLBOX *pBox,COLLBOX *pB)
{
int		gHi,gLow,gradient;
int		temp,d1,d2,dist;

	d1 = d2 = 0;	// CPW: stops compiler warning

	pB->pX-=10*4096;
	pB->pZ-=10*4096;

	pB->sX+=20*4096;
	pB->sZ+=20*4096;

	switch(quadrant)
	{
		case 1:
			//DB ("quad 1\n");
			if (pB->pX<sX)	// box crosses x axis
			{
				temp=( (pB->pX+pB->sX)-sX)>>12;
				if (temp<0) DB ("error in check box 1\n");	// for debug only 
				if (!temp) temp=1;	// stop divide by 0
				gLow=((pB->pZ-sZ))/temp;
				gHi=0x7fffffff;
				dist=0;
				d1=pB->pZ-sZ;
				d2=eZ-sZ;

				//DB ("t1 ");
			}
			else if (pB->pZ<sZ) // box crosses z axis
			{
				temp=(pB->pX-sX)>>12;
				if (temp<0) DB ("error in check box 1\n");	// for debug only 
				if (!temp) temp=1;
				gLow=(( (pB->pZ)-sZ))/temp;

				temp=(pB->pX-sX)>>12;
				if (temp<0) DB ("error in check box 1\n");	// for debug only 
				if (!temp) temp=1;
				gHi=(( (pB->pZ+pB->sZ)-sZ))/temp;

				dist=0;
				d1=pB->pX-sX;
				d2=eX-sX;
				//DB ("t2 ");
			}
			else
			{
				temp=(pB->pX-sX)>>12;
				if (temp<0) DB ("error in check box 1\n");	// for debug only 

				if (!temp) temp=1;
				gHi=(( (pB->pZ+pB->sZ)-sZ))/temp;
				temp=( (pB->pX+pB->sX)-sX)>>12;
				if (temp<0) DB ("error in check box 1\n");	// for debug only 

				if (!temp) temp=1;	// stop divide by 0
				gLow=((pB->pZ-sZ))/temp;

				dist=Magnitude2D( (pB->pX-sX),(pB->pZ-sZ) )>>9;
				//DB ("t3 ");
			}
			temp=(sX-eX)/4096;
			if (!temp) temp=1;	// stop divide by 0
			gradient=((sZ-eZ))/temp;
			if ( (gradient<gHi) && (gradient>gLow) ) // he have a hit
			{
				if (dist==0) dist=(calcDistance(d1,d2,sX,sZ,eX,eZ));
				(*distance1)=dist;
				if (dist<(*distance))
				{
					(*distance)=dist;
					pBox->camFlags=pB->camFlags;
					pBox->pX=pB->pX;
					pBox->pY=pB->pY;
					pBox->pZ=pB->pZ;
					pBox->sX=pB->sX;
					pBox->sY=pB->sY;
					pBox->sZ=pB->sZ;
				}
			}
			break;
		case 2:
			//DB("quad 2\n");
			if (pB->pX<sX)	// box crosses x axis
			{
				temp=((pB->pX+pB->sX)-sX)>>12;
				if (temp<0) DB ("error in check box 2\n");	// for debug only 
				if (!temp) temp=1;	// stop divide by 0
				gHi=(( (pB->pZ+pB->sZ)-sZ))/temp;
				gLow=0x80000000;
				dist=0;
				d1=sZ-(pB->pZ+pB->sZ);
				d2=sZ-eZ;
				//DB ("t1 \n");
			}
			else if ( (pB->pZ<sZ) && (pB->pZ+pB->sZ)>sZ ) // box crosses z axis
			{
				// There a bug here someware
				temp=(pB->pX-sX)>>12;
				if (temp<0) DB ("error in check box 2\n");	// for debug only 
				if (!temp) temp=1;
				gLow=(pB->pZ-sZ)/temp;
				gHi=1;
				dist=0;
				d1=pB->pX-sX;
				d2=eX-sX;
				//DB ("t2 \n");
			}
			else
			{
				temp=((pB->pX+pB->sX)-sX)>>12;
				if (temp<0) DB ("error in check box 2\n");	// for debug only 
				if (!temp) temp=1;
				gHi=(( (pB->pZ+pB->sZ)-sZ))/temp;

				temp=(pB->pX-sX)>>12;
				if (temp<0) DB ("error in check box 2\n");	// for debug only 
				if (!temp) temp=1;
				gLow=((pB->pZ-sZ))/temp;
				dist=Magnitude2D( (pB->pX-sX),((pB->pZ+pB->sZ)-sZ) )>>9;
				//DB ("t3 \n");
			}
			temp=(sX-eX)/4096;
			if (!temp) temp=-1;	// stop divide by 0
			gradient=((sZ-eZ))/temp;

			if ( (gradient<gHi) && (gradient>gLow) ) // he have a hit
			{
				if (dist==0) dist=(calcDistance(d1,d2,sX,sZ,eX,eZ));
				(*distance1)=dist;
				if (dist<(*distance))
				{
					(*distance)=dist;
					pBox->camFlags=pB->camFlags;
					pBox->pX=pB->pX;
					pBox->pY=pB->pY;
					pBox->pZ=pB->pZ;
					pBox->sX=pB->sX;
					pBox->sY=pB->sY;
					pBox->sZ=pB->sZ;
				} 
			}
			break;

		case 3:
			//DB ("quad 3\n");
			if ( (pB->pX+pB->sX)>sX)	// box crosses x axis
			{
				temp=(sX-(pB->pX))>>12;
				if (temp<0) DB ("error in check box 3a\n");	// for debug only 
				if (!temp) temp=1;
				gLow=(( (pB->pZ+pB->sZ)-sZ))/-temp;
				gHi=0x7fffffff;
				dist=0;
				d1=sZ-(pB->pZ+pB->sZ);
				d2=sZ-eZ;
				//DB ("t1 ");
			}
			else if ( (pB->pZ+pB->sZ) > sZ) // box crosses z axis
			{
				temp=(sX-(pB->pX+pB->sX))>>12;
				if (temp<0) DB ("error in check box 3b\n");	// for debug only 
				if (!temp) temp=1;
				gHi=((pB->pZ-sZ))/-temp;
				gLow=-1;
				dist=0;
				d1=sX-(pB->pX+pB->sX);
				d2=sX-eX;
				//DB ("t2 ");
			}
			else
			{
				temp=(sX-(pB->pX))>>12;
				if (temp<0) DB ("error in check box 3c\n");	// for debug only 
				if (!temp) temp=1;
				gLow=(( (pB->pZ+pB->sZ)-sZ))/-temp;

				temp=(sX-(pB->pX+pB->sX))>>12;
				if (temp<0) DB ("error in check box 3d\n");	// for debug only 
				if (!temp) temp=1;
				gHi=(( (pB->pZ)-sZ))/-temp;

				dist=Magnitude2D( ((pB->pX+pB->sX)-sX),((pB->pZ+pB->sZ)-sZ) )>>9;
				//DB ("t3 ");
			}
			temp=(sX-eX)/4096;
			if (!temp) temp=1;	// stop divide by 0
			gradient=((sZ-eZ))/temp;

			if ( (gradient<gHi) && (gradient>gLow) ) // he have a hit
			{
				if (dist==0) dist=(calcDistance(d1,d2,sX,sZ,eX,eZ));
				(*distance1)=dist;
				if (dist<(*distance))
				{
					(*distance)=dist;
					pBox->camFlags=pB->camFlags;
					pBox->pX=pB->pX;
					pBox->pY=pB->pY;
					pBox->pZ=pB->pZ;
					pBox->sX=pB->sX;
					pBox->sY=pB->sY;
					pBox->sZ=pB->sZ;
				} 
			}
			break;

		case 4:
			//DB ("quad 4\n");
			if ( (pB->pX+pB->sX)>sX)	// box crosses x axis
			{
				temp=(sX-pB->pX)>>12;
				if (temp<0) DB ("error in check box 4a\n");	// for debug only 
				if (!temp) temp=1;
				gHi=((pB->pZ-sZ))/-temp;

				gLow=0x80000000;
				dist=0;
				d1=pB->pZ-sZ;
				d2=eZ-sZ;
				//DB ("t1 ");
			}
			else if (pB->pZ<sZ) // box crosses z axis
			{
				gHi=0;
				temp=(sX-(pB->pX+pB->sX))>>12;
				if (temp<0) DB ("error in check box 4b\n");	// for debug only 
				if (!temp) temp=1;
				gLow=(( (pB->pZ+pB->sZ)-sZ))/-temp;
				dist=0;
				d1=sX-(pB->pX+pB->sX);;
				d2=sX-eX;
				//DB ("t3 ");
			}
			else
			{
				temp=(sX-(pB->pX+pB->sX))>>12;
				if (temp<0) DB ("error in check box 4c\n");	// for debug only 
				if (!temp) temp=1;
				gLow=(( (pB->pZ+pB->sZ)-sZ))/-temp;

				temp=(sX-(pB->pX))>>12;
				if (temp<0) DB ("error in check box 4d\n");	// for debug only 
				if (!temp) temp=1;
				gHi=((pB->pZ-sZ))/-temp;
				//DB ("t2 ");
				dist=Magnitude2D( ((pB->pX+pB->sX)-sX),(pB->pZ-sZ) )>>9;
			}
			temp=(sX-eX)/4096;
			if (!temp) temp=1;	// stop divide by 0
			gradient=((sZ-eZ))/temp;

			if ( (gradient<gHi) && (gradient>gLow) ) // he have a hit
			{
				if (dist==0) dist=(calcDistance(d1,d2,sX,sZ,eX,eZ));
				(*distance1)=dist;
				if (dist<(*distance))
				{
					(*distance)=dist;
					pBox->camFlags=pB->camFlags;
					pBox->pX=pB->pX;
					pBox->pY=pB->pY;
					pBox->pZ=pB->pZ;
					pBox->sX=pB->sX;
					pBox->sY=pB->sY;
					pBox->sZ=pB->sZ;
				} 
			}
			break;
	}
	pB->pX+=10*4096;
	pB->pZ+=10*4096;

	pB->sX-=20*4096;
	pB->sZ-=20*4096;
}
/////////////////////////////////////////////////////////////////
int		calcDistance(int d1,int d2,int sX,int sZ,int eX,int eZ)
{
	int	distance;
	
	distance=Magnitude2D( (sX-eX),(sZ-eZ) )>>9;
	d1=abs(d1)>>12;
	d2=abs(d2)>>12;

	if (!d2) d2=1;

	//DB("dist %d \n",distance);
	distance=(distance*d1)/d2;
	//DB("dist %d \n",distance);
	return(distance);

}

/*
void	findClosestBox(int sX,int sY,int sZ,int eX,int eY,int eZ,COLLBOX *pBox)
{
	int	gradient;
	int	leftRight,upDown;
	VECTOR	vect2;
	COLLBOX *pB;
	long	x1,y1,z1,value;
	volatile ULONG	*collptr,*collptr1;
	ULONG	collBoxPos;
	int		distance,match,distance1,match1;
	int		temp,temp1;

	distance1=0x7fffffff;
	match=0;
//	COLLBOX *pB;
//	static COLLBOX cB;  //too big to be a normal local (fast stack issue!)
//	static COLLBOX *pB=&cB;
//	static COLLBOX *pB1;

	//rval = 0x7fffffff;
	//value = 0x7fffffff;

	vect2.vx=sX;
	vect2.vy=sY;
	vect2.vz=sZ;


	x1=sX-startX;
	y1=sY-startY;
	z1=sZ-startZ;

	x1/=xStepLen;
	y1/=yStepLen;
	z1/=zStepLen;


	if (x1<0 || x1>=xSteps) return;
	if (y1>=ySteps) return;
	if (z1<0 || z1>=zSteps) return;

	if (y1 < 0) y1 = 0;

	if	(sX<eX)	// ignore all boxes to the left
	{
		leftRight=1;
	}
	else leftRight=-1;

	if (sZ<eZ)	// ignore all boxes to the near
		upDown=1;
	else
		upDown=-1;

//	gradient=abs((eX-sX))/abs((eZ-sZ));

	collBoxPos=( x1+(z1*xSteps)+(y1*(xSteps*zSteps)) );
	collptr=(ULONG *)reducedCollBox[collBoxPos];

	if (!collptr)	return;	// no boxes to check

	if (((ULONG)collptr)>0x80000000)	// Check for one or >one
	{
		pB=(COLLBOX*)collptr;
		if ( (leftRight==1) && ((pB->pX+pB->sX)<sX) ) return;	// not possable to hit box
		else if ( (leftRight==-1) && ((pB->pX)>sX) ) return;	// not possable to hit box
		if ( (upDown==1) && ((pB->pZ+pB->sZ)<sZ) ) return;	// not possable to hit box
		else if ( (upDown==-1) && ((pB->pZ)>sZ) ) return;	// not possable to hit box

		if (leftRight==1 && upDown==1)
		{
			// find distance to box
			distance=sX-pB->pX;
			if (distance> abs(sX-eX) ) return;
			// Can we hit this box?
			temp=abs(eX-sX);
			if (!temp) temp=1;	// stop divide by 0
			gradient=abs((eZ-sZ)*4096)/temp;
			value=((distance*gradient)/4096)+sX;
			if (value>pB->pZ && value<(pB->pZ+pB->sZ) ) match=TRUE;
		}
		if (leftRight==1 && upDown==-1)
		{
			// find distance to box
			distance=sX-pB->pX;
			if (distance> abs(sX-eX) ) return;
			// Can we hit this box?
			temp=abs(eX-sX);
			if (!temp) temp=1;	// stop divide by 0
			gradient=abs((eZ-sZ)*4096)/temp;
			value=((distance*-gradient)/4096)+sX;
			if (value>pB->pZ && value<(pB->pZ+pB->sZ) ) match=TRUE;
		}
		if (leftRight==-1 && upDown==1)
		{
			// find distance to box
			distance=(pB->pX+pB->sX)-sX;
			if (distance> abs(sX-eX) ) return;
			// Can we hit this box?
			temp=abs(eX-sX);
			if (!temp) temp=1;	// stop divide by 0
			gradient=abs((eZ-sZ)*4096)/temp;
			value=((distance*gradient)/4096)+sX;
			if (value>pB->pZ && value<(pB->pZ+pB->sZ) ) match=TRUE;
		}
		if (leftRight==-1 && upDown==-1)
		{
			// find distance to box
			distance=(pB->pX+pB->sX)-sX;
			if (distance> abs(sX-eX) ) return;
			// Can we hit this box?
			temp=abs(eX-sX);
			if (!temp) temp=1;	// stop divide by 0
			gradient=abs((eZ-sZ)*4096)/temp;
			value=((distance*-gradient)/4096)+sX;
			if (value>pB->pZ && value<(pB->pZ+pB->sZ) ) match=TRUE;
		}
		if (match)
		{
			// we have our box
			pBox->pX=pB->pX;
			pBox->pY=pB->pY;
			pBox->pZ=pB->pZ;
			pBox->sX=pB->sX;
			pBox->sY=pB->sY;
			pBox->sZ=pB->sZ;
		}
	}
	else
	{
		//collptr = (ULONG *)( ((ULONG)(collptr)) & 0x7fffffff);	// mask off collptr's top bit
		collptr = (ULONG *)( ((ULONG)(collptr)) & 0x7fffffff);	// mask off collptr's top bit
		collptr1= (ULONG *)(*collptr);
		do	// the "none" case has already been dealt with
		{
			pB=(COLLBOX*)collptr1;
			match1=TRUE;

			if ( (leftRight==1) && ((pB->pX+pB->sX)<sX) ) match1=FALSE;
			else if ( (leftRight==-1) && ((pB->pX)>sX) ) match1=FALSE;
			if ( (upDown==1) && ((pB->pZ+pB->sZ)<sZ) ) match1=FALSE;
			else if ( (upDown==-1) && ((pB->pZ)>sZ) ) match1=FALSE;

			if ( sY < (pB->pY+pB->sY) ) match1=FALSE;

			if (leftRight==1 && upDown==1 && match1)
			{
				// find distance to box
				distance=sX-pB->pX;
				if ( (distance < abs(sX-eX)) && distance<distance1 )
				{
					// Can we hit this box?
					temp=abs(eX-sX);
					if (!temp) temp=1;	// stop divide by 0
					gradient=abs((eZ-sZ)*4096)/temp;
					value=((distance*gradient)/4096)+sZ;

					//printf ("g %d v %d sx %d ex %d ",gradient,value,sX,eX);
					//printf ("sz %d ez %d temp %d distance %d\n",sZ,eZ,temp,distance);

					if (value>pB->pZ && value<(pB->pZ+pB->sZ) )
					{
						match=TRUE;
						distance1=distance;
					}
				}
			}
			if (leftRight==1 && upDown==-1 && match1)
			{
				// find distance to box
				distance=sX-pB->pX;
				if ( (distance < abs(sX-eX)) && distance<distance1 )
				{
					// Can we hit this box?
					temp=abs(eX-sX);
					if (!temp) temp=1;	// stop divide by 0
					gradient=abs((eZ-sZ)*4096)/temp;
					value=((distance*-gradient)/4096)+sZ;
					if (value>pB->pZ && value<(pB->pZ+pB->sZ) )
					{
						match=TRUE;
						distance1=distance;
					}
				}
			}
			if (leftRight==-1 && upDown==1 && match1)
			{
				// find distance to box
				distance=(pB->pX+pB->sX)-sX;
				if ( (distance> abs(sX-eX)) && distance<distance1 )
				{
					// Can we hit this box?
					temp=abs(eX-sX);
					if (!temp) temp=1;	// stop divide by 0
					gradient=abs((eZ-sZ)*4096)/temp;
					value=((distance*gradient)/4096)+sZ;
					if (value>pB->pZ && value<(pB->pZ+pB->sZ) )
					{
						match=TRUE;
						distance1=distance;
					}
				}
			}
			if (leftRight==-1 && upDown==-1 && match1)
			{
				// find distance to box
				distance=(pB->pX+pB->sX)-sX;
				if ( (distance < abs(sX-eX)) && distance<distance1 )
				{
					// Can we hit this box?
					temp=abs(eX-sX);
					if (!temp) temp=1;	// stop divide by 0
					gradient=abs((eZ-sZ)*4096)/temp;
					value=((distance*-gradient)/4096)+sZ;
					if (value>pB->pZ && value<(pB->pZ+pB->sZ) )
					{
						match=TRUE;
						distance1=distance;
					}
				}
			}
			if (match)
			{
				// we have our box
				pBox->pX=pB->pX;
				pBox->pY=pB->pY;
				pBox->pZ=pB->pZ;
				pBox->sX=pB->sX;
				pBox->sY=pB->sY;
				pBox->sZ=pB->sZ;
			}

			//getHeightOfOneBox((COLLBOX*)collptr1, &value,&vect2);
			//if(value < rval)
			//	rval = value;

			collptr++;
			collptr1=(ULONG *)(*collptr);
		}
		while (collptr1!=NULL);
	}
//	return( (ULONG*)pBox1);
}
*/


//extern ULONG	*tempFile;
//extern void *tempmemblock2;

void collideFree()
{
// RFW - this ain't necessary, coz reducedCollBox is now within the BFF
//	if(reducedCollBox)
//	{
//		FREE(reducedCollBox);
//	}
	reducedCollBox = NULL;

	if(tempmemblock2)
	{
		FREE(tempmemblock2);
	}


// RFW - this ain't necessary, coz tempFile is now within the BFF
//	if(tempFile)
//		FREE(tempFile);
	tempFile = NULL;
}


// (A*B/C) with maths OV protection
int limitedFraction(int top1, int top2, int bot)
{
	int s;
	int num;
	num = ABS(top1) | ABS(top2);
	s = 0;
	while(num > 32768)
	{
		num = num>>2;
		s+=2;
	}
	top1 = top1 >> s;	// (top1 div 2) * (top2 div 2) / (bot div 4)
	top2 = top2 >> s;
	bot = bot >> (s*2);
	if(bot == 0)
	{
		if((top1 >= 0 && top2 >= 0) || (top1 < 0 && top2 < 0))
			return (int)(INT_MAX);
		else
			return (int)(INT_MIN);
	}
	return top1 * top2 / bot;

}

int collideBoxIsectCheck(VECTOR *p1, VECTOR *p2)
{
	COLLBOX *pB;
	int is1,is2;
	int loop;


	if(overlay_show_collision == DEBUG_OVERLAY_ENEMY_INFO)
	{
		VECTOR t1,t2;

		t1.vx = p1->vx>>9;
		t1.vy = p1->vy>>9;
		t1.vz = p1->vz>>9;

		t2.vx = p2->vx>>9;
		t2.vy = p2->vy>>9;
		t2.vz = p2->vz>>9;

		overlayShowDebugLine(&t1,&t2, 0xffffff, DEBUGPOLY_SUBDIV | DEBUGPOLY_USEDEPTH);
	}


	pB=boxes;
	for (loop=0;loop<numCollBoxes;loop++,pB++)
	{
		if(p1->vx < pB->pX && p2->vx < pB->pX)
			continue;
		if(p1->vx > pB->pX+pB->sX && p2->vx > pB->pX+pB->sX)
			continue;
		if(p1->vz < pB->pZ && p2->vz < pB->pZ)
			continue;
		if(p1->vz > pB->pZ+pB->sZ && p2->vz > pB->pZ+pB->sZ)
			continue;
		if(p1->vy < pB->pY+pB->sY && p2->vy < pB->pY+pB->sY)
			continue;
		if(p1->vy > pB->pY && p2->vy > pB->pY)
			continue;

// x-lo.
		if( (p1->vx < pB->pX && p1->vx >= pB->pX)
			|| (p1->vx >= pB->pX && p1->vx < pB->pX)
		  )
		{
			is1 = p1->vz + limitedFraction((p2->vz - p1->vz),(pB->pX - p1->vx),(p2->vx - p1->vx));
			if(is1 < pB->pZ || is1 >= pB->pZ + pB->sZ)
				continue;
			is2 = p2->vy + limitedFraction((p2->vy - p1->vy),(pB->pX - p1->vx),(p2->vx - p1->vx));
			if(is2 >= pB->pY || is2 < pB->pY + pB->sY)
				continue;
		}
//x-hi
		if( (p1->vx < pB->pX+pB->sX && p1->vx >= pB->pX+pB->sX)
			|| (p1->vx >= pB->pX+pB->sX && p1->vx < pB->pX+pB->sX)
		  )
		{
			is1 = p1->vz + limitedFraction((p2->vz - p1->vz),(pB->pX+pB->sX - p1->vx),(p2->vx - p1->vx));
			if(is1 < pB->pZ || is1 >= pB->pZ + pB->sZ)
				continue;
			is2 = p2->vy + limitedFraction((p2->vy - p1->vy),(pB->pX+pB->sX - p1->vx),(p2->vx - p1->vx));
			if(is2 >= pB->pY || is2 < pB->pY + pB->sY)
				continue;
		}


// z-lo.
		if( (p1->vz < pB->pZ && p1->vz >= pB->pZ)
			|| (p1->vz >= pB->pZ && p1->vz < pB->pZ)
		  )
		{
			is1 = p1->vx + limitedFraction((p2->vx - p1->vx),(pB->pZ - p1->vz),(p2->vz - p1->vz));
			if(is1 < pB->pX || is1 >= pB->pX + pB->sX)
				continue;
			is2 = p2->vy + limitedFraction((p2->vy - p1->vy),(pB->pZ - p1->vz),(p2->vz - p1->vz));
			if(is2 >= pB->pY || is2 < pB->pY + pB->sY)
				continue;
		}
// z-hi
		if( (p1->vz < pB->pZ+pB->sZ && p1->vz >= pB->pZ+pB->sZ)
			|| (p1->vz >= pB->pZ+pB->sZ && p1->vz < pB->pZ+pB->sZ)
		  )
		{
			is1 = p1->vx + limitedFraction((p2->vx - p1->vx),(pB->pZ+pB->sZ - p1->vz),(p2->vz - p1->vz));
			if(is1 < pB->pX || is1 >= pB->pX + pB->sX)
				continue;
			is2 = p2->vy + limitedFraction((p2->vy - p1->vy),(pB->pZ+pB->sZ - p1->vz),(p2->vz - p1->vz));
			if(is2 >= pB->pY || is2 < pB->pY + pB->sY)
				continue;
		}


// y-hi.
		if( (p1->vy < pB->pY && p1->vy >= pB->pY)
			|| (p1->vy >= pB->pY && p1->vy < pB->pY)
		  )
		{
			is1 = p1->vx + limitedFraction((p2->vx - p1->vx),(pB->pY - p1->vy),(p2->vy - p1->vy));
			if(is1 < pB->pX || is1 >= pB->pX + pB->sX)
				continue;
			is2 = p2->vz + limitedFraction((p2->vz - p1->vz),(pB->pY - p1->vy),(p2->vy - p1->vy));
			if(is2 < pB->pZ || is2 >= pB->pZ + pB->sZ)
				continue;
		}
// y-lo
		if( (p1->vy < pB->pY+pB->sY && p1->vy >= pB->pY+pB->sY)
			|| (p1->vy >= pB->pY+pB->sY && p1->vy < pB->pY+pB->sY)
		  )
		{
			is1 = p1->vx + limitedFraction((p2->vx - p1->vx),(pB->pY+pB->sY - p1->vy),(p2->vy - p1->vy));
			if(is1 < pB->pX || is1 >= pB->pX + pB->sX)
				continue;
			is2 = p2->vz + limitedFraction((p2->vz - p1->vz),(pB->pY+pB->sY - p1->vy),(p2->vy - p1->vy));
			if(is2 < pB->pZ || is2 >= pB->pZ + pB->sZ)
				continue;
		}


		return 1;
	}
	return 0;
}








