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

	Title :			Collision Module 
	Filename :		collide2.c
	Author :		Thomas Szirtes
	Revision :		2.0

	Notes :			Advanced collision toolkit for all types of cases.
					Incorporates volume checking, polyhedra checking and polygon
					intersection with ray

	Copyright :		(C) SEGA Europe 1998

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


/*
 *		INCLUDES
 */
									 
#include	<math.h>
#include	"ftypes.h"
#include	"future.h"
#include	"ship.h"

#ifndef	USING_SET4
 #include	<malloc.h>
 #include	"sound.h"
#else
 #include	"shinobi.h"
#endif

#include	"procs.h"


/*
 *		Definitions
 */

#ifndef	HUGE_VAL
#define	HUGE_VAL	1.7976931348623157e+308
#endif

/* fast macro version of V3Dot, usable with Point4 */
#define DOT3( a, b )	( (a)->x*(b)->x + (a)->y*(b)->y + (a)->z*(b)->z )


/* Return code definitions */
#define	MISSED		 0
#define	COLLISION	 1
#define	INSIDE		-1
#define	OUTSIDE		 0


/*
 *		Structure definitions
 */

typedef struct Point4Struct {	
	float	x;		/* A */
	float	y;		/* B */
	float	z;		/* C */
	float	w;		/* D */
	} POINT4;


/* Definition of a RAY */
typedef struct {
	NJS_POINT3	org;			/* origin of ray */
	NJS_POINT3	dir;			/* direction of ray */
	float		dist;			/* distance along ray */
} CT_RAY;

/* More general case of a deformed cylinder */

typedef struct {
	float	cx,cy,cz;		/* centre */
	float	radius1;		/* radius at cy */
	float	radiusstep;		/* radius unit increment/decrement  */
	float	length;			/* length */
} CT_CONE;


/* Definition of a convex polyhedran */
typedef struct {
	POINT4	*planes;
	int		plane_count;
} CT_CNXPOLY;


typedef	struct {
	float	cx,cy,cz;		/* centroid */
	float	dx,dy,dz;		/* distances around centroid */
} CT_CUBOID;

/* Definition of a box */
/* use array since easier to program algorithm */
typedef struct {
	float	minB[3];			/* minimum coordinate tuple x,y,z */
	float	maxB[3];			/* maximum coordinate tuple x,y,z */
} CT_BOX;



/*------------------------------- PUBLIC FUNCTIONS --------------------------------------// */

#if		0

/*------------------------------------------------------------------------
	RAY TO CONVEX POLYHEDRAN INTERSECTION TEST
	
	Inputs	:	ray		-	ray object
				obj		-	convex poly object
				tresult	-	distance of intersection along ray
				norm	-	normal of face hit

	Return	:	collision return code MISSED, COLLISION, INSIDE

	Notes	:	based on Haines test 1991
				adapted by T.Szirtes
  ------------------------------------------------------------------------*/

int	CT_IntersectCnxPoly( 
							CT_RAY		*ray,
							CT_CNXPOLY	*obj,		/* object */
							float		*tresult,	/* returned: distance of intersection along ray  */
							NJS_POINT3	*norm 		/* returned: normal of face hit  */
						)
{
	/* code not supplied with this build version */
	return 0;
}



/*------------------------------------------------------------------------
	RAY TO BOX INTERSECTION TEST
	
	Inputs	:	ray		-	ray object
				box		-	convex poly object
				norm	-	normal of face hit

	Return	:	collision return code MISSED, COLLISION, INSIDE

	Notes	:	based on Woo test
				adapted by T.Szirtes
  ------------------------------------------------------------------------*/


int CT_IntersectBox(
					CT_BOX		*box,
					CT_RAY		*ray,
					NJS_POINT3	*norm		/* hit point  */
				   )
{
	/* code withheld */
	return	0;
}	





/*------------------------------------------------------------------------
	RAY TO CONE TEST
	
	Inputs	:	r		-	ray object
				obj		-	cone object

	Return	:	collision return code MISSED, COLLISION, INSIDE

	Notes	:	original algorithm

  ------------------------------------------------------------------------*/

int	CT_IntersectCone( CT_RAY	*r, CT_CONE *obj )
{
	/* code withheld */
	return 0;
}





/*------------------------------------------------------------------------
	RAY TO CONE TEST
	
	Inputs	:	r		-	ray object
				obj		-	cuboid object

	Return	:	collision return code MISSED, COLLISION, INSIDE

	Notes	:	original algorithm

  ------------------------------------------------------------------------*/

int CT_IntersectCuboid( NJS_POINT3 *p, CT_CUBOID *obj )
{
	/* code withheld */
	return 0;
}


/*------------------------------------------------------------------------
	RAY TO POLYGON TEST
	
	Inputs	:	r		-	ray object
				poly	-	poly object

	Return	:	collision return code MISSED, COLLISION

	Notes	:	original algorithm

  ------------------------------------------------------------------------*/
int	CT_IntersectPolygon( 
						CT_RAY	*ray,
						CT_POLY	*ply
						)
{

	/* code withheld */
	return 0;
}

/*------------------------------------------------------------------------
	RAY TO SPHERE TEST
	
	Inputs	:	r		-	ray object
				s	-	sphere object

	Return	:	collision return code INSIDE, MISSED, COLLISION

	Notes	:	original algorithm

  ------------------------------------------------------------------------*/
int	CT_IntersectSphere( 
						CT_RAY		*ray,
						CT_SPHERE	*s
						)
{

	/* code withheld */
	return 0;
}


#endif





/*--------------------------------------------------------------------------
 
  int	COLLIDE_Floor( NJS_POINT3	*pt, float rad, NJS_VECTOR	*col )
 
  Parameters:
 	pt			center of check sphere
 	rad			radius of sphere
 	col			collision normal
 
  Returns:
 
  Notes:
	Does a very optomized check against the triangle on the floor below
	it
 
  --------------------------------------------------------------------------*/

int	COLLIDE_Floor( NJS_POINT3	*pt, float rad, NJS_VECTOR	*col )
{
	int			i,j;
	float		u,v;
	NJS_POINT3	p0,p1,p2,p;
	PLANE		pl;
	float		d,s,dist;


	/* find grid position */
	i	=	P2GRID(pt->x);
	j	=	P2GRID(pt->z);

	/* calculate u,v inside grid area */
	u	=	(pt->x - GRID2P(i)); 	
	v	=	(pt->z - GRID2P(j));
	
	/* I can optomize this a lot later... */

	/* calculate with triangle we are in (1 of two) */
	/* generate tri-poly */
	if (v<(GRID_SIZE-u))
	{
		p0.x	=	0.f;		p0.y	=	map.map[i][j].gnd;		p0.z	=	0;
		p1.x	=	GRID_SIZE;	p1.y	=	map.map[i+1][j].gnd;	p1.z	=	0;
		p2.x	=	0.f;		p2.y	=	map.map[i][j+1].gnd;	p2.z	=	GRID_SIZE;
	}
	else
	{
		p0.x	=	GRID_SIZE;	p0.y	=	map.map[i+1][j].gnd;	p0.z	=	0;
		p1.x	=	GRID_SIZE;	p1.y	=	map.map[i+1][j+1].gnd;	p1.z	=	GRID_SIZE;
		p2.x	=	0.f;		p2.y	=	map.map[i][j+1].gnd;	p2.z	=	GRID_SIZE;
	}

	/* convert to plane - will we intergrate this with above later when I have time */
	pl.a	=	((p1.y - p0.y) * (p2.z - p0.z) - (p1.z - p0.z) * (p2.y - p0.y));
	pl.b	=	((p1.z - p0.z) * (p2.x - p0.x) - (p1.x - p0.x) * (p2.z - p0.z));
	pl.c	=	((p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x));
	pl.d	=	-((pl.a * p0.x) + (pl.b * p0.y) + (pl.c * p0.z));
	
	/* create test point */
	p.x	=	u;		p.y	=	pt->y;		p.z	=	v;

	/* calculate distance from point to plane */
	d		=	(pl.a * p.x) + (pl.b * p.y) + (pl.c * p.z) + pl.d;
	s		=	njSqrt((pl.a * pl.a) + (pl.b * pl.b) + (pl.c * pl.c));
	dist	=	-d/s;

	/* check dist */
	if(dist<rad)
	{
		/* return normal - already calculated */
		col->x	=	pl.a;
		col->y	=	pl.b;
		col->z	=	pl.c;
		njUnitVector(col);
		return	TRUE;
	}
	

	/* interpolate height */
	return FALSE;
}




/*--------------------------------------------------------------------------
 
	void collide_TriangletoPlane( NJS_POINT3 *p0, NJS_POINT3 *p1, 
								  NJS_POINT3 *p2, PLANE *pl )
 
  Parameters:
 	p0,p1,p2	three points in triangle
 	pl			pointer to plane
 
  Returns:
 
  Notes:
	Convert from triangle to plane format
	
  --------------------------------------------------------------------------*/
void collide_TriangletoPlane( NJS_POINT3 *p0, NJS_POINT3 *p1, NJS_POINT3 *p2, PLANE *pl )
{
	pl->a	=	((p1->y - p0->y) * (p2->z - p0->z) - (p1->z - p0->z) * (p2->y - p0->y));
    pl->b	=	((p1->z - p0->z) * (p2->x - p0->x) - (p1->x - p0->x) * (p2->z - p0->z));
    pl->c	=	((p1->x - p0->x) * (p2->y - p0->y) - (p1->y - p0->y) * (p2->x - p0->x));

	pl->d	=	-( (pl->a * p0->x) + (pl->b * p0->y) + (pl->c * p0->z) );
}


/*--------------------------------------------------------------------------
 
	float collide_DistancetoPlane( NJS_POINT3 *p, PLANE *pl )
 
  Parameters:
	p		point to check	
	pl		plane equation

  Returns:
	distance from plane to point

  Notes:

  --------------------------------------------------------------------------*/
float collide_DistancetoPlane( NJS_POINT3 *p, PLANE *pl )
{
	float d,s;
	
	d	=	(pl->a * p->x) + (pl->b * p->y) + (pl->c * p->z) + pl->d;
	s	=	njSqrt((pl->a * pl->a) + (pl->b * pl->b) + (pl->c * pl->c));

	return	d/s;

}


/*---------------------------------------------------------------------------
	COLLIDE_Cuboid

	Inputs :	p	   - check point
				colobj - collision object
				coll   - normal address

	test against cuboid
  ----------------------------------------------------------------------------*/
int COLLIDE_Cuboid ( 
					NJS_POINT3		*p, 
					COLOBJ_CUBOID	*colobj, 
					NJS_VECTOR		*coll,
					float			surr
					)
{
	float	distx,distz;

	/* quick test to check if we inside cuboid zone */
	if (p->x > colobj->p2.x + surr) return FALSE;
	if (p->y > colobj->p2.y + surr) return FALSE;
	if (p->z > colobj->p2.z + surr) return FALSE;
	if (p->x < colobj->p1.x - surr) return FALSE;
	if (p->y < colobj->p1.y - surr) return FALSE;
	if (p->z < colobj->p1.z - surr) return FALSE;

	coll->x  = 0.f;
	coll->y = 0.f;
	coll->z = 0.f;

	if (p->y > colobj->p2.y)
	{
		coll->y	=	1.f;
		return	TRUE;
	}

	/* calculate centre */
	/* now see which face we have hit - this taken from my original collision code */
	/* split cuboid into quadrants */
			
	/* Find quadrant */
	
	if (p->x > 0)
		distx	=	(p->x - colobj->p2.x);	
	else
		distx	=	(p->x - colobj->p1.x); 

	if (p->z > 0)
		distz	=	(p->z - colobj->p2.z);
	else
		distz	=	(p->z - colobj->p1.z);

	if (fabs(distx) < fabs(distz))
	{
		if (p->x > 0)
			coll->x	=	1.f;
		else
			coll->x	=	-1.f;
		return TRUE;
	}
	else
	{
		if (p->z > 0)
			coll->z	=	1.f;
		else
			coll->z	=	-1.f;
		return TRUE;
	}
	return FALSE;
}



/*---------------------------------------------------------------------------
	COLLIDE_Sphere

	Inputs :	p	   - check point
				colobj - collision object
				coll   - normal address

	test against sphere
  ----------------------------------------------------------------------------*/
int COLLIDE_Sphere(
				   NJS_POINT3		*p, 
				   COLOBJ_SPHERE	*colobj, 
				   NJS_VECTOR		*coll,
				   float			surr
				   )
{
	float	d;
	register float	dx,dy,dz;

	dx	=	p->x - colobj->centre.x;
	dy	=	p->y - colobj->centre.y;
	dz	=	p->z - colobj->centre.z;

	d = njSqrt( (dx * dx) + (dy * dy) + (dz * dz) );
	
	if (d > (surr + colobj->rad)) return 0;

	coll->x		=	dx;
	coll->y		=	dy;
	coll->z		=	dz;
	njUnitVector(coll);
	return 1;
	
}

/*---------------------------------------------------------------------------
	COLLIDE_Cylinder

	Inputs :	p	   - check point
				colobj - collision object
				coll   - normal address

	test against cylinder lying along y or x axis
  ----------------------------------------------------------------------------*/

int COLLIDE_Cylinder(
					 NJS_POINT3			*p, 
					 COLOBJ_CYLINDER	*colobj, 
					 NJS_VECTOR			*coll,
					 float				surr
					 )
{
	float	d;
	

	if(colobj->orient	==	0)
	{
		/* VERTICAL - lies along Y axis */
		/* check top and bottom */
		if (p->y-surr > colobj->length) return FALSE;
		if (p->y+surr < 0.f) return FALSE;

		/* upright */
		d	=	njSqrt((p->x * p->x) + (p->z * p->z));	
		if (d > colobj->r + surr) return FALSE;	

		if (p->y > colobj->length)
		{
			coll->y	=	1.0f;
			return TRUE;
		}
		if (p->y < 0.f)
		{
			coll->y	=	-1.0f;
			return	TRUE;
		}

		/* calculate normal */
		coll->x	=	p->x;
		coll->z	=	p->z;
		njUnitVector(coll);
		return TRUE;
	}
	else
	{
		/* HORIZONTAL - lies along x axis */
		/* check top and bottom */
		if (p->x-surr > colobj->length) return FALSE;
		if (p->x+surr < 0.f) return FALSE;

		/* upright */
		d	=	njSqrt((p->y * p->y) + (p->z * p->z));	
		if (d > colobj->r + surr) return FALSE;	

		if (p->x > colobj->length)
		{
			coll->x	=	1.0f;
			return TRUE;
		}
		if (p->x < 0.f)
		{
			coll->x	=	-1.0f;
			return	TRUE;
		}

		/* calculate normal */
		coll->y	=	p->y;
		coll->z	=	p->z;
		njUnitVector(coll);
		return TRUE;
	
	}

	return FALSE;
}


/*---------------------------------------------------------------------------
	COLLIDE_Cone

	Inputs :	p	   - check point
				colobj - collision object
				coll   - normal address

	test against cone lying upright
  ----------------------------------------------------------------------------*/

int COLLIDE_Cone(
				 NJS_POINT3 *p, 
				 COLOBJ_CONE *colobj, 
				 NJS_VECTOR *coll,
				 float		surr)
{
	float	d,dr;


	/* Only vertical - lies along Y axis */
	/* check top and bottom */
	if (p->y-surr > colobj->height) return FALSE;

	if (p->y+surr < 0.f) return FALSE;

	if (p->y > colobj->height)
	{
		coll->y	=	1.0f;
		return TRUE;
	}

	if (p->y < 0.f)
	{
		coll->y	=	-1.0f;
		return	TRUE;
	}

	/* calculate width at point */
	dr	=	colobj->r1 + (p->y * ((colobj->r2 - colobj->r1)/colobj->height));


	/* upright */
	d	=	njSqrt((p->x * p->x) + (p->z * p->z));	
	if (d > (dr) + surr) return FALSE;	


	/* calculate normal */
	coll->x	=	p->x;
	coll->z	=	p->z;
	njUnitVector(coll);
	return TRUE;

	
	return FALSE;
}



/*---------------------------------------------------------------------------
	COLLIDE_Free
	Deallocates all memory generated by COLLIDE_NjtoPolyH and others...

	Inputs :	obj		-	object to deallocate
  ---------------------------------------------------------------------------*/

void	COLLIDE_Free( COLLIDE_OBJ *obj )
{
	return;


	if (obj->child != NULL)		COLLIDE_Free(obj->child); 

	/* at the moment this is only dynamically generated memory */
	if (obj->type == COLOBJ_TYPE_POLYH)
	{
		if(obj->collide != NULL ) 
		{
			if (((COLOBJ_POLYH *)obj->collide)->pl!=NULL)
#ifdef USING_SET4
				syFree( ((COLOBJ_POLYH *)obj->collide)->pl);

			syFree(obj->collide);
#else
				free( ((COLOBJ_POLYH *)obj->collide)->pl);

			free(obj->collide);
#endif

			obj->collide	=	NULL;
		}
	}

	if (obj->sibling != NULL)	COLLIDE_Free(obj->sibling);

}


/*---------------------------------------------------------------------------
	COLLIDE_NjtoPolyh
	Convertor from ninja model to optomized polyhedra format for collision
	detection

	Inputs	:	mdl		-	ninja model
				tmp		-	temporary workspace (to save mem-frag)
	
	Return	:	poly hedra object pointer

	Notes - assumes that model is convex, assumes single triangle/quad mesh only
	(ie. polygon co-planar) will then optomize based to duplicate normals 
	(hence quite slow).

    temporary workspace size needs to be 
		max number of triangles * 4 * sizeof(float)
  ---------------------------------------------------------------------------*/
COLOBJ_POLYH *COLLIDE_NjtoPolyh( NJS_MODEL *mdl, PLANE *tmp )
{
	register Sint16		pti;
	int					found;
	int					count;
	int					n,m,mn;
	NJS_POINT3			*p;
	int					i0,i1,i2;
	PLANE				pl;
	float				mag;
	COLOBJ_POLYH		*dstobj;


	p		=	mdl->points;
	count	=	0;

	for (mn=0;mn<mdl->nbMeshset;mn++)
	{
		/* not triangle or 4side mesh - fail */
		if (((mdl->meshsets[mn].type_matId&NJD_MESHSET_MASK) != NJD_MESHSET_3) &&
			((mdl->meshsets[mn].type_matId&NJD_MESHSET_MASK) != NJD_MESHSET_4))
			return NULL;

		pti		=	0;
		for (n=0;n<mdl->meshsets[mn].nbMesh;n++)
		{
			i0	=	mdl->meshsets[mn].meshes[pti++];
			i1	=	mdl->meshsets[mn].meshes[pti++];
			i2	=	mdl->meshsets[mn].meshes[pti++];

			/* if 4mesh - add another vertex */
			if ((mdl->meshsets[mn].type_matId&NJD_MESHSET_MASK) == NJD_MESHSET_4) pti++;

			/* calculate normalized plane */
			pl.a	=	((p[i1].y - p[i0].y) * (p[i2].z - p[i0].z) - (p[i1].z - p[i0].z) * (p[i2].y - p[i0].y));
			pl.b	=	((p[i1].z - p[i0].z) * (p[i2].x - p[i0].x) - (p[i1].x - p[i0].x) * (p[i2].z - p[i0].z));
			pl.c	=	((p[i1].x - p[i0].x) * (p[i2].y - p[i0].y) - (p[i1].y - p[i0].y) * (p[i2].x - p[i0].x));
			mag		=	njInvertSqrt((pl.a*pl.a) + (pl.b*pl.b) + (pl.c*pl.c));
			pl.a	=	pl.a * mag;
			pl.b	=	pl.b * mag;
			pl.c	=	pl.c * mag;
			pl.d	=	-( (pl.a * p[i0].x) + (pl.b * p[i0].y) + (pl.c * p[i0].z) );
		
		
			/* Search for duplicate entries - this elimates coplanar surfaces being stored twice */
			found	=	FALSE;
			for(m=0;m<count;m++)
			{
				if ( (pl.a == tmp[m].a) && (pl.b == tmp[m].b) && (pl.c == tmp[m].c) )
				{
					found = TRUE;
					break;
				}
			}
			/* no duplicates found? ... store result */
			if (found==FALSE)
			{
				tmp[count].a	=	pl.a;
				tmp[count].b	=	pl.b;
				tmp[count].c	=	pl.c;
				tmp[count].d	=	pl.d;
				count++;

			}
			
		
		}
	}

	/* perform malloc */
#ifdef USING_SET4
	dstobj		=	(COLOBJ_POLYH *)syMalloc(sizeof(COLOBJ_POLYH));
	dstobj->pl	=	(PLANE *)syMalloc(sizeof(PLANE)*count);
#else
	dstobj		=	(COLOBJ_POLYH *)malloc(sizeof(COLOBJ_POLYH));
	dstobj->pl	=	(PLANE *)malloc(sizeof(PLANE)*count);
#endif
	
	memcpy	(dstobj->pl,tmp,sizeof(PLANE)*count);
	dstobj->count	=	count;
	return	dstobj;
}



/*---------------------------------------------------------------------------
	COLLIDE_Poly
	Fast check to see if sphere intersects convex polyhedra and returns
	collision normal

	Inputs :	p	   - check point
				colobj - collision object
				coll   - normal address

  Tom's algorithm
	1.	Convert polygon to plane (can be preprocessed)
	2.  Calculate distance from point to plane
	3.	Is point in half-space?
				No... discard
				Yes.. if this is the furthest distance then store
	4.	Repeat
	5.  Any half-space hits?
				No... we must be inside space
	6.  Is furthest distance within range?
				No... there was no collision
				Yes.. collision - return normal
  ----------------------------------------------------------------------------*/

int COLLIDE_Poly(
				 NJS_POINT3 *p, 
				 COLOBJ_POLYH *colobj, 
				 NJS_VECTOR *coll,
				 float		surr
				 )
{
	int			num_hits;
	PLANE		*furthest_plane;
	float		furthest_value;
	float		dist;
	PLANE		*pl;
	int			n;
	extern		SHIP	ship1;

	num_hits		=	0;
	furthest_value	=	0.f;		
	pl				=	colobj->pl;


	for(n=0;n<colobj->count;n++)
	{
		/* calculate distance from point to plane */
		
		/* without normalization optomization */
		/*	d		=	(pl->a * p->x) + (pl->b * p->y) + (pl->c * p->z) + pl->d; */
		/*  s		=	njSqrt((pl->a * pl->a) + (pl->b * pl->b) + (pl->c * pl->c)); */

		/* with normalize optomization */
		/* assuming "normalized planes" we can disgard square root and division!! */
		dist		=	(pl->a * p->x) + (pl->b * p->y) + (pl->c * p->z) + pl->d;

		/* is point in half-space */
		if (dist > 0.f)
		{
			num_hits++;
			/* is distance furthest? */
			if (dist > furthest_value)		
			{
				furthest_value	=	dist;
				furthest_plane	=	pl;
			}
		}
		pl++;
	}
	
	/* check if we are inside object */
	if (num_hits==0)
	{
		/* haven't worked out what I going to do yet - just report collision */
		/* cheat for now */
		coll->x	=	0.f;
		coll->y	=	0.f;
		coll->z	=	1.f;
		return TRUE;
	}
		
	/* check if any collisions occurred */
	if (furthest_value > surr)
	{
		return FALSE;
	}

	coll->x	=	furthest_plane->a;
	coll->y	=	furthest_plane->b;
	coll->z	=	furthest_plane->c;

	return TRUE;
}


/*---------------------------------------------------------------------------
	COLLIDE_ProcessObj

	Inputs :	p	   - check point
				colobj - collision object
				coll   - normal address
				res	   - result pointer

	Recursive check with building
  ----------------------------------------------------------------------------*/
void	COLLIDE_ProcessObj(NJS_POINT3 p, COLLIDE_OBJ *colobj, NJS_VECTOR *coll, int *res)
{
	int r=FALSE;


	/* double check */
	if(colobj==NULL) return;

	/* check sibling if not hit */
	if (r==FALSE && colobj->sibling!=NULL)	
		COLLIDE_ProcessObj (p, colobj->sibling, coll, res);

	/* hopefully the parameter handling should recurse this */
	p.x	=	p.x	-	colobj->pos.x;
	p.y	=	p.y	-	colobj->pos.y;
	p.z	=	p.z	-	colobj->pos.z;

	switch(colobj->type)
	{
	case COLOBJ_TYPE_CUBOID :	
		r	=	COLLIDE_Cuboid (&p, (COLOBJ_CUBOID *)colobj->collide, coll, 6.f);
		break;
	case COLOBJ_TYPE_SPHERE :	
		r	=	COLLIDE_Sphere (&p, (COLOBJ_SPHERE *)colobj->collide, coll, 6.f);
		break;
	case COLOBJ_TYPE_CYLINDER :	
		r	=	COLLIDE_Cylinder (&p, (COLOBJ_CYLINDER *)colobj->collide, coll, 6.f);
		break;
	case COLOBJ_TYPE_CONE :	
		r	=	COLLIDE_Cone (&p, (COLOBJ_CONE *)colobj->collide, coll, 6.f);
		break;
	case COLOBJ_TYPE_POLYH :	
		r	=	COLLIDE_Poly (&p, (COLOBJ_POLYH *)colobj->collide, coll, 6.f);
		break;
	}

	/* How does that effect result */
	if (r==TRUE)
	{
		if (colobj->mode==0)
			*res	=	TRUE;
		else
			*res	=	FALSE;		/* reverse mode */
	}

	/* recurse tree only bother to check child if parent is hit */
	if (r==TRUE && colobj->child!=NULL)	
		COLLIDE_ProcessObj (p, colobj->child, coll, res);
	

}



/*---------------------------------------------------------------------------
	COLLIDE_Building

	Inputs :	p	 - check point
				inst - building instance
				coll - normal address

	Check collision with building - returns collision status and hit normal
  ----------------------------------------------------------------------------*/

int	COLLIDE_Building(NJS_POINT3 *p, Uint16 inst, NJS_VECTOR *coll)
{
	COLLIDE_OBJ	*colobj;
	NJS_POINT3	pos;
	int		res;

	colobj	=	buildings[build_inst[inst].id].collide;

	coll->x	=	0.f;
	coll->y	=	0.f;
	coll->z	=	0.f;

	/* convert to local */
	pos.x		=	p->x - GRID2P(build_inst[inst].i);
	pos.z		=	p->z - GRID2P(build_inst[inst].j);
	pos.y		=	p->y-75;
	/* adjust check point to take into account orientation */
/*
	orient	=	build_inst[inst].flag & INST_FLAG_ORIENT_MASK;
	switch (orient)
	{
	case(INST_FLAG_ORIENT1) : 
		temp	=	pos.x;
		pos.x	=	pos.z;
		pos.z	=	temp;
		break;
	case(INST_FLAG_ORIENT2) : 
		pos.x	=	pos.z;
		pos.z	=	temp;
		break;
	case(INST_FLAG_ORIENT3) : 
		temp	=	pos.x;
		pos.x	=	pos.z;
		pos.z	=	temp;
		break;
	}
*/			
	if (colobj==NULL) return FALSE;

	res	=	FALSE;

	COLLIDE_ProcessObj(pos,colobj,coll,&res);


	return res;
}




