

#ifndef _COLLIDE_H_
#define _COLLIDE_H_

typedef struct tagCOLL_BFF
{
	unsigned long id;
	unsigned long len;
	unsigned long name_crc;

	int base_mesh_offset;
	int base_mesh_len;
	int red_mesh_offset;
	int red_mesh_len;

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

	int n_pointers;

}COLL_BFF;

// the Ulong pointer pM points to one of these
typedef struct tagRAMPHEADER
{
	short nVerts;
	short nFaces;
	ULONG *pFaces;
	VECTOR *pVerts;

	short normal_x;	// new....
	short normal_y;
	short normal_z;
	short plane;

}RAMPHEADER;	// not implmented yet

typedef struct tagCOLLBOX
{
	long	pX,pY,pZ;
	long	oldpX,oldpY,oldpZ;
	long	sX,sY,sZ;
	// bit 0  0=box 1=mesh

// Chris pointed out last night that tom's using some other bits as terrain type...(!)
	ULONG	flags; //maybe could use the other 3 bytes.
	ULONG	camFlags;
//	 flags;
//	char pad;
//	short boxnum;
	RAMPHEADER*	rampheader;
}COLLBOX;




/*
typedef struct tagCOLLBOX
{
	long pX,pY,pZ;
	long oldpX,oldpY,oldpZ;
	long sX,sY,sZ;
	// bits 0-2 = orientation	(NESW and NE SE SW NW for corner)
	//      2 =   ramp flag		(0=box, 1=ramp)
	ULONG flags;
	//VECTOR n[6];// normals of faces (changed form FVECTOR)
}COLLBOX;
*/
typedef struct _Point2DType
{
	int	x,y;
} Point2DType;

typedef struct _Point3DType
{
	int	x,y,z;
} Point3DType;



//extern COLLBOX collBox[32];
extern COLLBOX *collBox;
extern int bCtr;
extern long	numCollBoxes;

/*typedef struct tagREBDATA
{
	VECTOR		pos;
	VECTOR		vel;	// both changed from FVECTOR
	COLLBOX		*pCollBox;
	short		plane;
	short		type;
}HITDATA;
*/
typedef struct tagREBDATA
{
	VECTOR		pos;
	VECTOR		rampPos;
	VECTOR		vel;	// both changed from FVECTOR
	VECTOR		normal;
	COLLBOX		*pCollBox;
	short		plane;
	short		type;
	void		*pPlatHit;
}HITDATA;

extern	HITDATA 	pHitData[16]; // max number of hits

typedef struct tagCOLLDATA
{
	int nBoxes;
	int bounce;
	int radius;
	COLLBOX *pCollBox;
	VECTOR *pVel;
	VECTOR *pPos;
	VECTOR *pRot;	// changed from FVECTOR
	int nHits;

	// internal use only
	VECTOR	oldPos;
	VECTOR	oldRot;
	VECTOR	oldVel;
	VECTOR	hitPos;	// changed from FVECTOR
	int lastHit;

	ULONG	flags;	// OR of the flags of the collboxes we've hit. NB - Unlike Glover, I'm *not* shifting this down 8
}COLLDATA;

extern	COLLDATA	actorColl;		// temp colision stuff

//const long g=4000/4;//long(4096.0*9.80665)/16;

// box orientations

#define N	0
#define NE	1
#define E	2
#define SE 	3
#define S	4
#define SW	5
#define	W	6
#define NW	7


// HIT types
#define PLANE		0
#define EDGE		1
#define CORNER		2
// dount we'll need these
//#define	CYLINDER	3
//#define	SPHERE_H	4
#define RAMP_H		5



// Box types
#define BOX			0
#define RAMP		1
// Bits for type and special
#define TYPEPART	15
#define	SPECIALPART	240
// Box special cases 
#define COLLBOXFLAG_MOVE	16

#define COLLBOXFLAG_UNUSED	128

// Coming soon, to a collision box near you...?
// (Doesn't matter if they need changing, I just want to get some defines in...)
// Conveyors, done this way in Glover, are dealt with by new improved means in Ch Run
#define COLLBOXFLAG_STICKY		(1<<8)		// "I"... Gravy
#define COLLBOXFLAG_SLIPPY		(1<<9)		// Dough
#define COLLBOXFLAG_SPRINGY		(1<<10)	// Springs (note - switchable by the terrain type puzzle switch). Constant (Definable?) exit velocity
#define COLLBOXFLAG_BOUNCY		(1<<11)	// Trampolines
#define COLLBOXFLAG_HARMFUL		(1<<12)	// Hurts
#define COLLBOXFLAG_DEADLY		(1<<13)	// Kills   highly deadly, black 'taranchla'
#define COLLBOXFLAG_NOISY		(1<<14) // CPW: makes a racket when you touch it

#define COLLBOXFLAG_TERRAINMASK (0x3F00)	// OR of the above

// Terrain types
// (The camera cases are in another "flags" long now, anyway
#define	CAMSWEEPCASE	(1<<16)
#define	OBJECTCOLLIDE	(1<<30)
#define	NOCAMCOLLIDE	(1<<31)

// These are for the dogchase
#define OBJECTLEFT		(1<<29)
#define OBJECTRIGHT		(1<<28)

// This is for when main char can push up against the wall
#define	HUGWALL			(1<<27)
// NOTE bits 0 to 14 hold tag number for the above




#define XAXIS 1
#define YAXIS 2
#define ZAXIS 4

#define D_XZPLANE 1
#define D_XYPLANE 2
#define D_YZPLANE 4

#define U_XZPLANE 8
#define U_XYPLANE 16
#define U_YZPLANE 32

#define LARGERTOSMALLER 0
#define SMALLERTOLARGER 1
#define MAXCOLLOSIONS 20

#define BFF_COLL_ID (('C'<<0) | ('O'<<8) | ('L'<<16) | ('1'<<24))


//extern	ULONG	*tempFile;

extern int pFaceOrder[];

extern int pEdgeOrder[];

extern int pCornerOrder[];

extern long	xSteps,ySteps,zSteps;
extern long	xStepLen,yStepLen,zStepLen;
extern long	startX,startY,startZ;
extern long	endX,endY,endZ;
extern ULONG	*reducedCollBox;

extern COLL_BFF *WorldBFFcoll;

void collideLinkBFF(COLL_BFF *header);
UBYTE	pointInTri(long x, long y,Point2DType *edge);
ULONG	CheckCorners( COLLBOX *pB , COLLDATA *pD, HITDATA *pHitData );
int		collboxHasBallHitCorner(COLLDATA *pD, int x, int y, int z);
ULONG	CheckEdges(COLLBOX *pB , COLLDATA *pD , HITDATA *pHitData );
int		collboxHasBallHitEdge(COLLDATA *pD, int axis, int l1, int l2, int x, int y);
ULONG	CheckPlanes(COLLBOX *pB , COLLDATA *pD , HITDATA *pHitData );
int		collboxHasVectorCrossedPoly(COLLDATA *pD, int plane, int planePos, int r, int x1, int y1, int x2, int y2);
void	UpdateEdgeCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound); 
void	UpdateCornerCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound);
void	UpdatePlaneCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound);
void	CopyVector(VECTOR *U, VECTOR *V);
void collboxAddBox(int pX,int pY,int pZ, int sX,int sY,int sZ,
				   int orient, int boxType, int bColl);


void	ReduceCollision(COLLBOX *pcollbox,long offset);
ULONG	checkIntersection(COLLBOX *pcollbox,long minX,long minY,long minZ,long maxX,long maxY,long maxZ);

//void	setupCollision(void);
void	setupCollision(char *name);
int		collboxCheckSphere(COLLDATA *pD);

ULONG	CheckRamps(COLLBOX *pB , COLLDATA *pD , HITDATA *pHitData );
void UpdateRampCollision(COLLDATA *pD , HITDATA *pHitData , VECTOR *collPos , VECTOR *rebound);

long	getHeightAt(long x,long y,long z);
long	getHeightAtCam(long x,long y,long z,COLLBOX *pBox);
void	getHeightOfOneBox(COLLBOX *pB, long *pVal,VECTOR *vect);

long	getCeilingAt(long x,long y,long z);

int		findClosestBox(int sX,int sY,int sZ,int eX,int eY,int eZ,COLLBOX *pBox,int objectCheck);

void	CheckBox(int sX,int sZ,int eX,int eZ,int quadrant,int *distance,int *distance1,COLLBOX *pBox,COLLBOX *pB);

int		calcDistance(int d1,int d2,int sX,int sZ,int eX,int eZ);

int collideBoxIsectCheck(VECTOR *p1, VECTOR *p2);

#endif
