/*
	Trampoline Sim.
	Copyright (c) 2009, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef GAME_BODY_H
#define GAME_BODY_H

//=====================================================================================================================
//=====================================================================================================================

#include "Physics/Shape.h"

//=====================================================================================================================
//=====================================================================================================================

namespace Game
{
	//=================================================================================================================
	/// @brief		This class is a base class for rigid and soft bodies. It contains all properties common to both,
	///				though some properties may be ignored in the case of soft bodies.
	//=================================================================================================================
	
	class Body
	{
		public:
		
			//=========================================================================================================
			// Functions
			//=========================================================================================================
			
				/// Creates the body
				
				Body
				( 
					Shape *					shape											,
					bool					moveable			= true						,
					float					mass				= 1.0f						,
					const Matrix3f &		inertia_tensor		= Matrix3f::Identity()		,
					float					restitution			= 0.15f						,
					float					restitution_cutoff	= 0.5f						,
					float					static_friction		= 0.5f						,
					float					dynamic_friction	= 0.5f						,
					float					linear_dampening	= 0.95f						, 
					float					angular_dampening	= 0.95f	
				);

				/// Destroys the body

				virtual ~Body();

				//=====================================================================================================
				/// @brief		Tells if this body is a soft body.
				/// @returns	True if this is a soft body.
				//=====================================================================================================

				virtual bool IsSoftBody() = 0;

				//=====================================================================================================
				/// @brief		Returns the shape used by this body.
				/// @returns	Shape used by this body
				//=====================================================================================================
				
				inline const Shape & GetShape() const { return * m_shape; }
				
				//=====================================================================================================
				/// @brief		Returns the mass of the body
				/// @returns	Mass of the body
				//=====================================================================================================
				
				inline float GetMass() const { return m_mass; }
				
				//=====================================================================================================
				/// @brief		Returns the inverse mass of the body
				/// @returns	Inverse mass of the body
				//=====================================================================================================
				
				inline float GetInverseMass() const { return m_inv_mass; }

				//=====================================================================================================
				/// @brief		Returns the coefficient of restitution for the body.
				/// @returns	Coefficient of restitution for the body
				//=====================================================================================================
				
				inline float GetRestitution() const { return m_restitution; }
				
				//=====================================================================================================
				/// @brief		Gets the contact point velocity at which we begin to reduce the coefficient of 
				///				restitution in order to stabalise small scale collisions.
				/// @returns	The cutoff velocity at contact points under which the coefficient of restitution is 
				///				scaled back.
				//=====================================================================================================
				
				inline float GetRestitutionCutoff() const { return m_restitution_cutoff; }
				
				//=====================================================================================================
				/// @brief		Gets the coefficient of static friction. This affects how much force is required to
				///				move the object from a stationary position.
				/// @returns	coefficient of static friction
				//=====================================================================================================
				
				inline float GetStaticFriction() const { return m_static_friction; }
				
				//=====================================================================================================
				/// @brief		Gets the coefficient of dynamic friction. This affects how much friction is applied
				///				to the object during motiton.
				/// @returns	coefficient of dynamic friction
				//=====================================================================================================
				
				inline float GetDynamicFriction() const { return m_dynamic_friction; }
				
				//=====================================================================================================
				/// @brief		Returns the coefficient of linear dampening. This controls how much velocity dampening
				///				is applied during the simulation.
				/// @returns	The coefficient of linear dampening.
				//=====================================================================================================
				
				inline float GetDampening() const { return m_dampening; }
				
				//=====================================================================================================
				/// @brief		Returns the coefficient of angular dampening. This controls how much angular velocity 
				///				dampening is applied during the simulation.
				/// @returns	The coefficient of angular dampening.
				//=====================================================================================================
				
				inline float GetAngularDampening() const { return m_angular_dampening; }
				
				//=====================================================================================================
				/// @brief		Sets the mass for the body
				/// @param		mass - new mass of the body
				/// @pre		Mass must be > 0
				/// @pre		Mass must be a valid number
				//=====================================================================================================
				
				inline void SetMass( float mass )
				{ 
					// Make sure ok
				
					ENSURE( mass > 0				, "Mass must be > 0"			)
					ENSURE( Float::IsValid(mass)	, "Mass must be a valid number" )
					
					// Save
					
					m_mass = mass; m_inv_mass = 1.0f / mass;
				}
				
				//=====================================================================================================
				/// @brief		Sets whether the body is moveable
				/// @param		moveable - if true then the body is moveable
				//=====================================================================================================
				
				inline void SetMoveable( bool moveable ){ m_moveable = moveable; }

				//=====================================================================================================
				/// @brief		Sets the coefficient of restitution for the body.
				/// @param		restitution - Coefficient of restitution for the body
				/// @pre		Restitution must be between 0 and 1
				//=====================================================================================================
				
				inline void SetRestitution( float restitution )
				{ 
					// Make sure ok

					ENSURE( restitution >= 0 && restitution <= 1 , "Restitution must be between 0 and 1" )

					// Save

					m_restitution = restitution;
				}
				
				//=====================================================================================================
				/// @brief		Sets the velocity of contact points during collision under which we begin to scale
				///				back the coefficient of restitution in order to stabalise small scale collisions.
				/// @param		restitution_cutoff - velocity under which we begin to reduce restitution at contact
				///				points.
				/// @pre		Given number must be valid
				//=====================================================================================================
				
				inline void SetRestitutionCutoff( float restitution_cutoff )
				{ 
					// Make sure ok

					ENSURE( Float::IsValid(restitution_cutoff), "Given number must be valid" )

					// Save

					m_restitution_cutoff = restitution_cutoff;
				}
				
				//=====================================================================================================
				/// @brief		Sets the coefficient of static friction. This affects how much force is required to
				///				move the object from a stationary position.
				/// @param		static_friction - coefficient of static friction
				/// @pre		Static friciton must not be less than zero
				//=====================================================================================================
				
				inline void SetStaticFriction( float static_friction )
				{
					// Make sure ok
					
					ENSURE( static_friction >= 0 , "Static friciton must not be less than zero" )
					
					// Save:
					
					m_static_friction = static_friction;
				}
				
				//=====================================================================================================
				/// @brief		Sets the coefficient of dynamic friction. This affects how much friction is applied
				///				to the object during motiton.
				/// @param		dynamic_friction - coefficient of dynamic friction
				/// @pre		Dynamic friciton must not be less than zero
				//=====================================================================================================
				
				inline void SetDynamicFriction( float dynamic_friction )
				{
					// Make sure ok
					
					ENSURE( dynamic_friction >= 0 , "Dynamic friciton must not be less than zero" )
					
					// Save:
					
					m_dynamic_friction = dynamic_friction;
				}
				
				//=====================================================================================================
				/// @brief		Sets the coefficient of linear dampening. This controls how much velocity dampening
				///				is applied during the simulation.
				/// @param		d - The coefficient of linear dampening. 1 is no dampening, 0 is full dampening.
				/// @pre		Dampening value must be from 0-1
				//=====================================================================================================
				
				inline void SetDampening( float d )
				{ 
					// Make sure ok
				
					ENSURE( d >= 0 && d <= 1 , "Dampening value must be from 0-1" )
					
					// Save:
					
					m_dampening = d;
				}
				
				//=====================================================================================================
				/// @brief		Sets the coefficient of angular dampening. This controls how much angular velocity 
				///				dampening is applied during the simulation.
				/// @param		d - The coefficient of angular dampening. 1 is no dampening, 0 is full dampening.
				/// @pre		Dampening value must be from 0-1
				//=====================================================================================================
				
				inline void SetAngularDampening( float d )
				{ 
					// Make sure ok
				
					ENSURE( d >= 0 && d <= 1 , "Dampening value must be from 0-1" )
					
					// Save:
					
					m_angular_dampening = d;
				}
				
				//=====================================================================================================
				/// @brief		Tells whether the body is moveable
				/// @returns	True if the body is moveable
				//=====================================================================================================
				
				inline bool IsMoveable() const { return m_moveable; }					
				
				//=====================================================================================================
				/// @brief		Returns the position of the body
				/// @returns	The position of the body
				//=====================================================================================================
				
				inline const Vec3f & GetWorldPosition() const { return m_position; }
				
				//=====================================================================================================
				/// @brief		Returns the orientation of the body
				/// @returns	The orientation of the body
				//=====================================================================================================
				
				inline const Quaternionf & GetWorldOrientation() const { return m_orientation; }
				
				//=====================================================================================================
				/// @brief		Returns the inertia tensor for this body
				/// @returns	The inertia tensor
				//=====================================================================================================
				
				inline const Matrix3f & GetInertiaTensor() const { return m_inertia; }

				//=====================================================================================================
				/// @brief		Returns the inverse inertia tensor for this body
				/// @returns	The inertia tensor
				//=====================================================================================================
				
				inline const Matrix3f & GetInverseInertiaTensor() const { return m_inv_inertia; }
				
				//=====================================================================================================
				/// @brief		Returns the linear velocity of the body in world coordinates
				/// @returns	The linear velocity of the body
				//=====================================================================================================
				
				inline const Vec3f GetWorldVelocity() const { return m_velocity; }
				
				//=====================================================================================================
				/// @brief		Returns the linear acceleration of the body in world coordinates
				/// @returns	The linear acceleration of the body
				//=====================================================================================================
				
				inline const Vec3f GetWorldAcceleration() const { return m_acceleration; }

				//=====================================================================================================
				/// @brief		Returns the angular velocity of the body in axis/angle format. This is in	
				///				world coordinates.
				/// @returns	The angular velocity of the body in axis/angle format.
				//=====================================================================================================
				
				inline const Vec3f GetWorldAngularVelocity() const { return m_angular_velocity; }
				
				//=====================================================================================================
				/// @brief		Returns the angular acceleration of the body in world coordinates
				/// @returns	The linear acceleration of the body in world coordinates
				//=====================================================================================================
				
				inline const Vec3f GetWorldAngularAcceleration() const { return m_angular_acceleration; }

				//=====================================================================================================
				/// @brief		Returns the amount of gravity applied to all rigid bodies in world coordinates.
				/// @returns	The amount of gravity in world coordinates. This is an acceleration value.
				//=====================================================================================================
				
				static inline const Vec3f & GetWorldGravity(){ return s_gravity; }
				
				//=====================================================================================================
				/// @brief		Sets the amount of gravity applied to moveable rigid bodies in world coordinates
				/// @param		gravity - new force vector for gravity. This is an acceleration value.
				/// @pre		Given gravity vector must be valid
				//=====================================================================================================
				
				static inline void SetWorldGravity( const Vec3f & gravity )
				{
					// Make sure ok:
					
					ENSURE( Float::IsValid(gravity.x) , "Given gravity vector must be valid" )
					ENSURE( Float::IsValid(gravity.y) , "Given gravity vector must be valid" )
					ENSURE( Float::IsValid(gravity.z) , "Given gravity vector must be valid" )
					
					// Save:
					
					s_gravity = gravity;
				}
				
				//=====================================================================================================
				/// @brief		Sets the position of the body in world coordinates
				/// @param		position - new position of the body
				/// @pre		Position must be valid
				//=====================================================================================================
				
				inline void SetWorldPosition( const Vec3f & position )
				{ 
					ENSURE( Float::IsValid(position.x) , "Position must be valid" )
					ENSURE( Float::IsValid(position.y) , "Position must be valid" )
					ENSURE( Float::IsValid(position.z) , "Position must be valid" )
				
					m_position = position;
					
					// Update shape also:
					
					m_shape->SetPosition(position);
				}

				//=====================================================================================================
				/// @brief		Sets the orientation of the body in world coordinates
				/// @param		orientation - new orientation of the body
				/// @pre		Given orienation must be valid
				/// @remarks	Assumes the given orientation is normalised
				//=====================================================================================================
				
				inline void SetWorldOrientation( const Quaternionf & orientation )
				{
					ENSURE( Float::IsValid(orientation.x) , "Given orienation must be valid" )
					ENSURE( Float::IsValid(orientation.y) , "Given orienation must be valid" )
					ENSURE( Float::IsValid(orientation.z) , "Given orienation must be valid" )
					ENSURE( Float::IsValid(orientation.s) , "Given orienation must be valid" )

					// Set
				
					m_orientation = orientation;
					
					// Update shape also:
					
					m_shape->SetOrientation(orientation);
				}
				
				//=====================================================================================================
				/// @brief		Sets the inertia tensor for the body
				/// @param		tensor - new inertia tensor of the body
				/// @pre		The inertia tensor must have an inverse
				/// @pre		The inertia tensor must be valid
				//=====================================================================================================
				
				inline void SetInertiaTensor( const Matrix3f & tensor )
				{ 
					// Make sure ok:
					
					ENSURE( tensor.Determinant() != 0 , "The inertia tensor must have an inverse" )
					
					// Make sure ok
					
					#ifdef DEBUG
					
						for ( unsigned i = 0 ; i < 3 ; i++ )
						for ( unsigned j = 0 ; j < 3 ; j++ )
						{
							ENSURE( Float::IsValid( tensor.m_components[i][j] ) , "The inertia tensor must be valid" )
						}
					
					#endif
					
					// Set:
					
					m_inertia = tensor;
					
					// Calcualte the inverse tensor
					
					m_inv_inertia = m_inertia.Inverse();
				}
				
				//=====================================================================================================
				/// @brief		Sets the linear velocity for the body in world coordinates
				/// @param		velocity - the new linear velocity for the body
				/// @pre		Given linear velocity must be valid
				//=====================================================================================================
				
				inline void SetWorldVelocity( const Vec3f & velocity )
				{
					// Make sure ok:
					
					ENSURE( Float::IsValid( velocity.x ) , "Given linear velocity must be valid" )
					ENSURE( Float::IsValid( velocity.y ) , "Given linear velocity must be valid" )
					ENSURE( Float::IsValid( velocity.z ) , "Given linear velocity must be valid" )
					
					// Save
					
					m_velocity = velocity;
				}			
				
				//=====================================================================================================
				/// @brief		Sets the linear acceleration for the body in world coordinates
				/// @param		acceleration - the new linear acceleration for the body
				/// @pre		Given linear acceleration must be valid
				//=====================================================================================================
				
				inline void SetWorldAcceleration( const Vec3f & acceleration )
				{
					// Make sure ok:
					
					ENSURE( Float::IsValid( acceleration.x ) , "Given linear acceleration must be valid" )
					ENSURE( Float::IsValid( acceleration.y ) , "Given linear acceleration must be valid" )
					ENSURE( Float::IsValid( acceleration.z ) , "Given linear acceleration must be valid" )
					
					// Save
					
					m_acceleration = acceleration;
				}
				
				//=====================================================================================================
				/// @brief		Sets the angular velocity for the body in world coordinates
				/// @param		angular_velocity - new angular velocity for the body
				/// @pre		Given angular velocity must be valid
				//=====================================================================================================
				
				inline void SetWorldAngularVelocity( const Vec3f & angular_velocity )
				{
					// Make sure ok:
					
					ENSURE( Float::IsValid( angular_velocity.x ) , "Given angular velocity must be valid" )
					ENSURE( Float::IsValid( angular_velocity.y ) , "Given angular velocity must be valid" )
					ENSURE( Float::IsValid( angular_velocity.z ) , "Given angular velocity must be valid" )
				
					// Save:
				
					m_angular_velocity = angular_velocity;
				}
				
				//=====================================================================================================
				/// @brief		Sets the angular acceleration for the body in world coordinates
				/// @param		angular_acceleration - new angular acceleration for the body
				/// @pre		Given angular acceleration must be valid
				//=====================================================================================================
				
				inline void SetWorldAngularAcceleration( const Vec3f & angular_acceleration )
				{
					// Make sure ok:
					
					ENSURE( Float::IsValid( angular_acceleration.x ) , "Given angular velocity must be valid" )
					ENSURE( Float::IsValid( angular_acceleration.y ) , "Given angular velocity must be valid" )
					ENSURE( Float::IsValid( angular_acceleration.z ) , "Given angular velocity must be valid" )
				
					// Save:
				
					m_angular_acceleration = angular_acceleration;
				}

				//=====================================================================================================
				/// @brief		Returns the shape for this box
				/// @returns	The shape for the box
				//=====================================================================================================

				inline Shape & GetShape(){ return * m_shape; }				
				
				//=====================================================================================================
				/// @brief		Resets all accelerations and therefore all forces acting on the body to zero
				//=====================================================================================================
				
				void ResetAccelerations()
				{
					m_acceleration			= Vec3f::Zero();
					m_angular_acceleration	= Vec3f::Zero();
				}
				
				//=====================================================================================================
				/// @brief		Resets all velocities acting on the body to zero
				//=====================================================================================================
				
				void ResetVelocities()
				{
					m_velocity			= Vec3f::Zero();
					m_angular_velocity	= Vec3f::Zero();
				}
				
				//=====================================================================================================
				/// @brief		Sets the previous linear linear acceleration of the body. This is used to help 
				///				stabalise resting contacts.
				/// @param		accel - previous linear acceleration of the body
				/// @pre		Given vector must be valid
				//=====================================================================================================
				
				inline void SetPreviousWorldAcceleration( const Vec3f & accel )
				{
					ENSURE( Float::IsValid(accel.x) , "Given vector must be valid" )
					ENSURE( Float::IsValid(accel.y) , "Given vector must be valid" )
					ENSURE( Float::IsValid(accel.z) , "Given vector must be valid" )
					
					// Save:
					
					m_prev_acceleration = accel;
				}
				
				//=====================================================================================================
				/// @brief		Gets the previous linear acceleration of the body. This is used to help 
				///				stabalise resting contacts.
				/// @returns	Previous linear acceleration of the body
				//=====================================================================================================
				
				inline const Vec3f & GetPreviousWorldAcceleration() const 
				{
					return m_prev_acceleration;
				}				
				
				//=====================================================================================================
				/// @brief		Returns the velocity of a point on the object in world coordinates.
				///				This is a combination of both linear velocity and velocity due to rotation.
				/// @param		position - world position to get the velocity for
				/// @returns	A combination of both linear and rotational induced velocity at the given point.
				///				This velocity is in world coordinates.
				//=====================================================================================================

				inline Vec3f GetWorldVelocityAtPoint( const Vec3f & position )
				{
					return GetWorldVelocity() + GetWorldRotationalVelocityAtPoint(position);
				}
				
				///	Updates all the dynamics and forces acting on the body
				
				virtual void Integrate( float time_delta ) = 0;

				/// Collides this body with the given body and does collision response:

				virtual void Collide( float time_delta , Body & other ) = 0;
				
				/// Called after the end of each update to the object: after Integrate() and Collide()
				
				virtual void EndUpdate() = 0;
				
				//=====================================================================================================
				/// @brief		Returns the rotational velocity of a point on the object in world coordinates.
				///				This includes velocity due to rotation only.
				/// @param		position - world position to get the velocity for
				/// @returns	The velocity of the point due to rotation only. Linear velocity is ignored.
				///				This velocity is in world coordinates.
				//=====================================================================================================

				inline Vec3f GetWorldRotationalVelocityAtPoint( const Vec3f & position )
				{
					return GetWorldAngularVelocity().Cross( position - GetWorldPosition() );
				}

				#pragma region(APPLY_X_FUNCTIONS)

					/// Applies a given force through the center of mass of the body. Force is given in world coordinates.
					
					virtual void ApplyWorldForce( const Vec3f & force ) = 0;
					
					/// Applies a given force from a given point in world coordinates. Force is given in world coordinates also.
					
					virtual void ApplyWorldForce( const Vec3f & force , const Vec3f & position ) = 0;

					/// Applies torque to the body: this is torque in world coordinates
					
					virtual void ApplyWorldTorque( const Vec3f & torque ) = 0;
					
					/// Applies a given linear acceleration to the body in world coordinates
					
					virtual void ApplyWorldAcceleration( const Vec3f & acceleration ) = 0;

					/// Applies a given linear acceleration to the body at the given position in world coordinates. Acceleration is in world coords also.
					
					virtual void ApplyWorldAcceleration( const Vec3f & acceleration , const Vec3f & position ) = 0;

					/// Applies a given angular acceleration to the body in world coordinates
					
					virtual void ApplyWorldAngularAcceleration( const Vec3f & angular_acceleration ) = 0;
					
					/// Applies an impulse through the center of the body in world coordinates. 
					
					virtual void ApplyWorldImpulse( const Vec3f & impulse ) = 0;

					/// Applies an impulse to the body at the given world position. Impulse is also in world coordinates.
					
					virtual void ApplyWorldImpulse( const Vec3f & impulse , const Vec3f & position ) = 0;
				
				#pragma endregion
				
		protected:
		
			//=========================================================================================================
			// Functions
			//=========================================================================================================		
		
				/// Performs collision detection and response between two dynamic objects
				
				static void DynamicDynamicCollision( Body & obj1 , Body & obj2 , float time_delta );
		
				/// Performs collision detection and response between a static and dynamic object. Obj1 is static.
				
				static void StaticDynamicCollision( Body & obj1 , Body & obj2 , float time_delta );
				
		private:
		
			//=========================================================================================================
			// Functions
			//=========================================================================================================		
		
				/// Copying is disallowed
				
				Body( const Body & other );

				/// Copying is disallowed
				
				Body & operator = ( const Body & other );
				
				/// Calculates the a matrix converting from impulse to velocity in contact space for the given object and contact
				
				static Matrix3f GetContactImpulseToVelocityMatrix
				( 
					const Contact	& c						,	
					const Body		& b						,
					const Matrix3f	& from_contact_space	,
					const Matrix3f  & to_contact_space
				);
						
			//=========================================================================================================
			// Variables
			//=========================================================================================================
			
				/// If false then the body is not moveable
				
				bool m_moveable;

				/// This is the shape used by the body

				Shape * m_shape;

				// OTHER

					/// This is the coefficient of resitition for the object: affects bounciness of collisions

					float m_restitution;
					
					//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
					/// This variable is used to help stabalise micro-collisions at resting contacts. If the velocity
					/// that a contact point is moving at happens to fall below this amount then we begin to cut 
					/// back linearly on the coefficient of restitution in order to reduce the amount of bouncing and
					/// thus reduce the amount of small scale vibrations from these collisions. 
					//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
					
					float m_restitution_cutoff;
					
					/// Coefficient of static friction. Affects the amount of force required to move the object from rest.
					
					float m_static_friction;
					
					/// Coefficient of dynamic friction. Affects the amount of friction applied to the body during motion.
					
					float m_dynamic_friction;
					
					/// Amount of dampening of linear motion from 0-1. 1 is no dampening.
					
					float m_dampening;

					/// Amount of dampening of angular motion from 0-1. 1 is no dampening.
					
					float m_angular_dampening;
				
				// LINEAR
				
					/// The position of the body
					
					Vec3f m_position;						

					/// The linear velocity of the body: this is in world coordinates
				
					Vec3f m_velocity;

					/// The linear acceleration of the body: this is in world coordinates
				
					Vec3f m_acceleration;
					
					/// The previous linear acceleration of the body: this is used to help stabalise resting contacts
					
					Vec3f m_prev_acceleration;
					
					///	The mass of the body

					float m_mass;

					///	Inverse mass of the body

					float m_inv_mass;
			
					/// This is the amount of gravitational acceleration applied to all bodies: this is in world coordinates
					
					static Vec3f s_gravity;

				// ANGULAR
				
					/// The orientation of the body
					
					Quaternionf m_orientation;	

					/// The angular velocity of the body: in axis angle format where xyz is the axis and w is the angle. This is in local coordinates.
				
					Vec3f m_angular_velocity;
					
					/// The angular acceleration of the body: this is is local coordinates
					
					Vec3f m_angular_acceleration;
										
					/// The moment of inertia of the body: this is in local coordinates

					Matrix3f m_inertia;
					
					/// The inverse moment of inertia for the body: this is in local coordinates
					
					Matrix3f m_inv_inertia;
	};
}

#endif
