www.pudn.com > RCApp-src.zip > Collision.h


/* 
	RedEye Project (http://members.ozemail.com.au/~ndmcevoy/) 
	Copyright (C) 2003  Nick McEvoy 
 
	This library is free software; you can redistribute it and/or 
	modify it under the terms of the GNU Library General Public 
	License as published by the Free Software Foundation; either 
	version 2 of the License, or (at your option) any later version. 
 
	This library is distributed in the hope that it will be useful, 
	but WITHOUT ANY WARRANTY; without even the implied warranty of 
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
	Library General Public License for more details. 
 
	You should have received a copy of the GNU Library General Public 
	License along with this library; if not, write to the Free 
	Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 
	----------------------------------------------------------------- 
 
		Commented for use with Doxygen (http://www.doxygen.org) 
 
	----------------------------------------------------------------- 
*/ 
 
/*! \file Collision.h 
 *	\brief Collision detection methods. 
 * 
 *		This file contains methods for collision detection. 
 * 
 *		Thanks to the following for code: 
 *		- DigiBen (DigiBen@GameTutorials.com) 
 *		- Steve Baker (http://www.sjbaker.org) 
 *		- Tomas Akenine-Möller (Fast 3D Triangle-Box Overlap Testing - tribox.cpp) 
 *		  http://www.acm.org/jgt/papers/AkenineMoller01/tribox.html 
 *		  http://www.ce.chalmers.se/staff/tomasm/pubs/tribox.pdf 
 */ 
 
#ifndef _RE_GAME_COLLISION_H_ 
#define _RE_GAME_COLLISION_H_ 
 
// PLIB includes 
#include  
 
// ODE includes 
#include "ode/common.h" 
 
#define HIGHEST_HEAVEN 1000000.0f 
#define DEEPEST_HELL -1000000.0f 
 
// Code adapted from Steve Baker (TuxKart & TuxAQFH) 
static void 
pr_from_normal(sgVec3 hpr, sgVec3 nrm) 
{ 
	float sy = (float)sin(-hpr[0]*SG_DEGREES_TO_RADIANS); 
	float cy = (float)cos(-hpr[0]*SG_DEGREES_TO_RADIANS); 
 
	hpr[2] =  SG_RADIANS_TO_DEGREES*((float)atan2(nrm[0]* cy - nrm[1]*sy, nrm[2])); 
	hpr[1] = -SG_RADIANS_TO_DEGREES*((float)atan2(nrm[1]* cy + nrm[0]*sy, nrm[2])); 
} 
 
// Code adapted from Steve Baker (TuxKart & TuxAQFH) 
static void 
hpr_from_normal(sgVec3 hpr, sgVec3 nrm) 
{ 
	pr_from_normal(hpr, nrm); 
	hpr[0] = -SG_RADIANS_TO_DEGREES*((float)atan2(nrm[0], nrm[1])); 
} 
 
void 
reGetBodyTransform(ssgTransform* dest, dBodyID src); 
 
void 
reGetBodyPosition(sgVec3 dest, dBodyID src); 
 
void 
reGetBodyVelocity(sgVec3 dest, dBodyID src); 
 
//!	Generates ODE contacts of 'hit' triangles agains a sphere. 
/*! 
 *		This service returns true if any contacts are generated. 
 *		The hit list may be obtained from bounding sphere check 
 *		using plib's ssgIsect() routine. 
 * 
 * \param iNumHits - number of hits in hit list 
 * \param pHitList - hit list (of triangles) 
 * \param SphereBody - ODE sphere body 
 * \param SphereGeom - ODE sphere geometry 
 * \return true if contacts generated, else false 
 */ 
bool 
reTriangleSphereContact(int iNumHits, 
						ssgHit* pHitList, 
						dBodyID SphereBody, 
						dGeomID SphereGeom); 
 
//!	Generates ODE contacts of 'hit' triangles agains a box. 
/*! 
 *		This service returns true if any contacts are generated. 
 *		The hit list may be obtained from bounding sphere check 
 *		using plib's ssgIsect() routine. 
 * 
 * \param iNumHits - number of hits in hit list 
 * \param pHitList - hit list (of triangles) 
 * \param BoxBody - ODE box body 
 * \param BoxGeom - ODE box geometry 
 * \return true if contacts generated, else false 
 */ 
bool 
reTriangleBoxContact(int iNumHits, 
					 ssgHit* pHitList, 
					 dBodyID BoxBody, 
					 dGeomID BoxGeom); 
 
//!	Returns HOT (Height Of Terrain). 
/*! 
 *		This service returns the HOT (Height Of Terrain) and the normal 
 *		of the nearest polygon *beneath* a given position. 
 * 
 * \param pScene - scene 
 * \param vMyPosition - position in the scene 
 * \return vNormal - normal of nearest polygon *beneath* the position 
 * \return HOT (Height Of Terrain) 
 */ 
float 
reGetHeightAndNormal(ssgRoot* pScene, 
					 const sgVec3 vMyPosition, 
					 sgVec3 vNormal, 
					 ssgHit** pHit); 
 
//!	Returns HOT (Height Of Terrain). 
/*! 
 *		This service returns the HOT (Height Of Terrain) 
 *		of the nearest polygon *beneath* a given position. 
 * 
 * \param pScene - scene 
 * \param vMyPosition - position in the scene 
 * \return HOT (Height Of Terrain) 
 */ 
inline float 
reGetHeight(ssgRoot* pScene, 
			sgVec3 vMyPosition) 
{ 
	ssgHit* pHit; 
	return reGetHeightAndNormal(pScene, vMyPosition, NULL, &pHit); 
} 
 
//!	Returns altitude above terrain. 
/*! 
 *		This service returns the altitude above terrain. 
 * 
 * \param pScene - scene 
 * \param vMyPosition - position in the scene 
 * \return altitude 
 */ 
inline float 
reGetAltitude(ssgRoot* pScene, 
			  const sgVec3 vMyPosition) 
{ 
	ssgHit* pHit; 
	float fHOT = reGetHeightAndNormal(pScene, vMyPosition, NULL, &pHit); 
	return vMyPosition[SG_Z] - fHOT; 
} 
 
//!	Returns triangle normal. 
/*! 
 *		This service returns the normal of a triangle (ie. the direction 
 *		that the triangle is facing). 
 * 
 * \param vTriangle - triangle 
 * \return vNormal - triangle normal 
 */ 
void 
reNormal(sgVec3 vNormal, 
		 const sgVec3 vTriangle[3]); 
 
//!	Returns distance between plane and origin. 
/*! 
 *		This service returns the distance between a plane and the origin. 
 * 
 * \param vNormal - plane normal 
 * \return vPoint - point on the plane 
 */ 
float 
rePlaneDistance(const sgVec3 vNormal, 
				const sgVec3 vPoint); 
 
//!	Returns plane definition. 
/*! 
 *		This service returns the plane definition. 
 * 
 *		Plane equation Ax + By + Cz + D = 0 
 *		Where ABC = plane normal, xyz = point on plane & D = plane distance from origin 
 * 
 *		vPlane[0,1,2] = ABC 
 *		vPlane[3] = D 
 * 
 * \param vTriangle - 3 points on the plane 
 * \param vNormal - plane normal (can be set NULL) 
 * \return vPlane - plane 
 */ 
void 
reDefinePlane(const sgVec3 vTriangle[3], 
			  const sgVec3 vNormal, 
			  sgVec4 vPlane); 
 
//!	Returns true if line intersects a plane. 
/*! 
 *		This service returns true if line intersects a plane. 
 * 
 * \param vLine - line 
 * \param vPlane - plane 
 * \return true if line intersects, else false 
 */ 
bool 
reLineIntersectsPlane(const sgVec3 vLine[2], 
					  const sgVec4 vPlane); 
 
//!	Returns line-plane intersection point. 
/*! 
 *		This service returns true if line intersects a plane, also returns 
 *		the intersection point. 
 * 
 * \param vLine - line 
 * \param vPlane - plane 
 * \return vPoint - intersection point 
 * \return true if intersects, else false 
 */ 
bool 
reLinePlaneIntersectionPoint(const sgVec3 vLine[2], 
							 const sgVec4 vPlane, 
							 sgVec3 vPoint); 
 
//!	Returns line-triangle intersection point. 
/*! 
 *		This service returns true if line intersects a triangle, also returns 
 *		the intersection point. 
 * 
 * \param vLine - line 
 * \param vTriangle - triangle 
 * \param vNormal - triangle normal (can be set NULL) 
 * \return vPoint - intersection point 
 * \return true if intersects, else false 
 */ 
bool 
reLineTriangleIntersectionPoint(const sgVec3 vLine[2], 
								const sgVec3 vTriangle[3], 
								const sgVec3 vNormal, 
								sgVec3 vPoint); 
 
//!	Returns a point on a line closest to a given point. 
/*! 
 *		This service returns a point on the line that is closest to a point. 
 * 
 * \param vLine - line 
 * \param vPoint - point 
 * \return vLinePoint - point on line closest to point 
 */ 
void 
reClosestPointOnLine(const sgVec3 vLine[2], 
					 const sgVec3 vPoint, 
					 sgVec3 vLinePoint); 
 
//!	Returns true point is inside a polygon. 
/*! 
 *		This service returns true if a point is inside the ranges of a 
 *		polygon. 
 * 
 * \param vPoint - point on poly 
 * \param vPoly - polygon points 
 * \param iVertexCount - number of polygon points 
 * \return true if point is inside polygon, else false 
 */ 
bool 
reInsidePolygon(const sgVec3 vPoint, 
				const sgVec3 vPoly[], 
				int iVertexCount); 
 
//!	Returns true if sphere intersects edges of a polygon. 
/*! 
 *		This service returns true if the sphere is intersecting any of the 
 *		edges of a polygon. 
 * 
 * \param vCenter - sphere center 
 * \param vPoly - polygon points 
 * \param iVertexCount - number of polygon points 
 * \param fRadius - sphere radius 
 * \return true if sphere intersects edges polygon, else false 
 */ 
bool 
reEdgeSphereCollision(const sgVec3 vCenter, 
					  const sgVec3 vPoly[], 
					  int iVertexCount, 
					  float fRadius); 
 
//!	Returns true if sphere is *between* edge planes of a triangle. 
/*! 
 *		This service returns true if the sphere is *between* the edge 
 *		planes of a triangle. 
 * 
 * \param vCenter - sphere center 
 * \param vTriangle - triangle 
 * \param vNormal - triangle normal 
 * \param fRadius - sphere radius 
 * \return true if sphere *between* edge planes of triangle, else false 
 */ 
bool 
reEdgePlanesCollision(const sgVec3 vCenter, 
					  const sgVec3 vTriangle[], 
					  const sgVec3 vNormal, 
					  float fRadius); 
 
//!	Returns if sphere is BEHIND, in FRONT, or INTERSECTS a plane. 
/*! 
 *		This service returns if sphere is BEHIND, in FRONT, or INTERSECTS 
 *		a plane, also returns it's distance from the plane. 
 * 
 * \param vCenter - sphere center 
 * \param vNormal - plane normal 
 * \param vPoint - point on plane 
 * \param fRadius - sphere radius 
 * \return fDistance - distance from sphere center to plane point 
 * \return 0 = BEHIND, 1 = in FRONT, 2 = INTERSECTS 
 */ 
int 
reClassifySphere(const sgVec3 vCenter, 
				 const sgVec3 vNormal, 
				 const sgVec3 vPoint, 
				 float fRadius, 
				 float& fDistance); 
 
//!	Returns triangle-sphere intersection point. 
/*! 
 *		This service returns true if triangle intersects a sphere, also returns 
 *		the intersection point and depth of penetration. 
 * 
 * \param vSphereCenter - sphere center 
 * \param fSphereRadius - sphere radius 
 * \param vTriangle - triangle 
 * \param vNormal - triangle normal (can be set NULL) 
 * \return vPoint - intersection point 
 * \return fDepth - depth of penetration 
 * \return true if intersects, else false 
 */ 
bool 
reTriangleSphereIntersectionPoint(const sgVec3 vSphereCenter, 
								  float fSphereRadius, 
								  const sgVec3 vTriangle[3], 
								  const sgVec3 vNormal, 
								  sgVec3 vPoint, 
								  float& fDepth); 
 
#endif // _RE_GAME_COLLISION_H_