OPC_Collider.h 10.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
 *	OPCODE - Optimized Collision Detection
 *	Copyright (C) 2001 Pierre Terdiman
 *	Homepage: http://www.codercorner.com/Opcode.htm
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	Contains base collider class.
 *	\file		OPC_Collider.h
 *	\author		Pierre Terdiman
 *	\date		June, 2, 2001
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __OPC_COLLIDER_H__
#define __OPC_COLLIDER_H__

	enum CollisionFlag
	{
		OPC_FIRST_CONTACT		= (1<<0),		//!< Report all contacts (false) or only first one (true)
		OPC_TEMPORAL_COHERENCE	= (1<<1),		//!< Use temporal coherence or not
		OPC_CONTACT				= (1<<2),		//!< Final contact status after a collision query
		OPC_TEMPORAL_HIT		= (1<<3),		//!< There has been an early exit due to temporal coherence
		OPC_NO_PRIMITIVE_TESTS	= (1<<4),		//!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries)

		OPC_CONTACT_FOUND		= OPC_FIRST_CONTACT | OPC_CONTACT,
		OPC_TEMPORAL_CONTACT	= OPC_TEMPORAL_HIT | OPC_CONTACT,

		OPC_FORCE_DWORD			= 0x7fffffff
	};

	class OPCODE_API Collider
	{
		public:
		// Constructor / Destructor
											Collider();
		virtual								~Collider();

		// Collision report

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Gets the last collision status after a collision query.
		 *	\return		true if a collision occured
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				BOOL			GetContactStatus()			const	{ return mFlags & OPC_CONTACT;							}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Gets the "first contact" mode.
		 *	\return		true if "first contact" mode is on
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				BOOL			FirstContactEnabled()		const	{ return mFlags & OPC_FIRST_CONTACT;					}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Gets the temporal coherence mode.
		 *	\return		true if temporal coherence is on
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				BOOL			TemporalCoherenceEnabled()	const	{ return mFlags & OPC_TEMPORAL_COHERENCE;				}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Checks a first contact has already been found.
		 *	\return		true if a first contact has been found and we can stop a query
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				BOOL			ContactFound()				const	{ return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND;	}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Checks there's been an early exit due to temporal coherence;
		 *	\return		true if a temporal hit has occured
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				BOOL			TemporalHit()				const	{ return mFlags & OPC_TEMPORAL_HIT;						}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Checks primitive tests are enabled;
		 *	\return		true if primitive tests must be skipped
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				BOOL			SkipPrimitiveTests()		const	{ return mFlags & OPC_NO_PRIMITIVE_TESTS;				}

		// Settings

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Reports all contacts (false) or first contact only (true)
		 *	\param		flag		[in] true for first contact, false for all contacts
		 *	\see		SetTemporalCoherence(bool flag)
		 *	\see		ValidateSettings()
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				void			SetFirstContact(bool flag)
											{
												if(flag)	mFlags |= OPC_FIRST_CONTACT;
												else		mFlags &= ~OPC_FIRST_CONTACT;
											}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Enable/disable temporal coherence.
		 *	\param		flag		[in] true to enable temporal coherence, false to discard it
		 *	\see		SetFirstContact(bool flag)
		 *	\see		ValidateSettings()
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				void			SetTemporalCoherence(bool flag)
											{
												if(flag)	mFlags |= OPC_TEMPORAL_COHERENCE;
												else		mFlags &= ~OPC_TEMPORAL_COHERENCE;
											}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Enable/disable primitive tests.
		 *	\param		flag		[in] true to enable primitive tests, false to discard them
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				void			SetPrimitiveTests(bool flag)
											{
												if(!flag)	mFlags |= OPC_NO_PRIMITIVE_TESTS;
												else		mFlags &= ~OPC_NO_PRIMITIVE_TESTS;
											}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
		 *	\return		null if everything is ok, else a string describing the problem
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual				const char*		ValidateSettings()	= 0;

		protected:
							udword			mFlags;			//!< Bit flags
					const	BaseModel*		mCurrentModel;	//!< Current model for collision query (owner of touched faces)
		// User mesh interface
					const	MeshInterface*	mIMesh;			//!< User-defined mesh interface

		// Internal methods
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Setups current collision model
		 *	\param		model	[in] current collision model
		 *	\return		TRUE if success
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		inline_				BOOL			Setup(const BaseModel* model)
											{
												// Keep track of current model
												mCurrentModel = model;
												if(!mCurrentModel)	return FALSE;

												mIMesh = model->GetMeshInterface();
												return mIMesh!=null;
											}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/**
		 *	Initializes a query
		 */
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual inline_		void			InitQuery()		{ mFlags &= ~OPC_TEMPORAL_CONTACT;	}
	};

#endif // __OPC_COLLIDER_H__