#ifndef PALGEOMETRY_H
#define PALGEOMETRY_H
//(c) Adrian Boeing 2007, see liscence.txt (BSD liscence)
/*! \file palBodies.h
	\brief
		PAL - Physics Abstraction Layer
		Bodies & Geometries
	\author
		Adrian Boeing
    \version
	<pre>
	Revision History:
		Version 0.1   : 23/10/07 - Split from palGeometry.h 
	</pre>
	\todo
		- Convex mesh mass/density/inertia calcs (I had an old paper on this once.. as in non electronic, early journal article.. see buoyancy code in subsim probably has some leftover references..) alt:Gauss's Theorem volume
		- Confirm cylinder inertia calculations (infact confirm all)
		- allow correction for inertia calculations if rotated.
		- Confirm suming, is it mass or area? (transfer of axis of inertia)
		- rewrite code usign ODE inertia calculations , if these can be confirmed
*/

/** The base geometry class.
	The class used to represent the shape, or part of the shape of a body (object).
	The geometry allows automated calculation of a bodies inertia properties, and provides the information required to perform collision detection.

	The geometry includes the inertia properties, as well as a mass. 
*/

class palGeometry : public palFactoryObject {
	friend class palBody;

public:
	palGeometry();
//	void SetPosition(Float x, Float y, Float z);
//	void SetPosition(Float x, Float y, Float z, Float roll, Float pitch, Float yaw);
	virtual void GetPosition(palVector3& pos);
	virtual palMatrix4x4& GetLocationMatrix(); 
	virtual void GenericInit(palMatrix4x4& location, void *param_array) = 0;

	virtual void SetMass(Float mass);
	Float GetMass();
protected:
	//virtual void iGenericInit(void *param,va_list arg_ptr) = 0;
	virtual void SetPosition(palMatrix4x4& location); 
	virtual void CalculateInertia() = 0;
public:

//	Float m_fPosX;
//	Float m_fPosY;
//	Float m_fPosZ;
	Float m_fInertiaXX; //inertia tensor XX,YY,ZZ (identity locations)
	Float m_fInertiaYY;
	Float m_fInertiaZZ;

	palGeometryType m_Type;
protected:
	palMatrix4x4 m_mLoc;
	palMatrix4x4 m_mOffset; //offset from body
	palBody *m_pBody;
	Float m_fMass;
};

/** A sphere geometry.
	This represents a sphere, at a given position with a given radius and mass.
	<img src="../pictures/sphere.jpg" alt="sphere">
	The diagram indicates the central point of the sphere, as well as its radius.
*/
class palSphereGeometry : virtual public palGeometry {
public:
	//palSphereGeometry(palBody *pbody);
	/** Initializes the sphere
	\param pos The transformation matrix representing the position and orientation of the sphere
	\param radius The sphere's radius
	\param mass The sphere's mass
	*/
	virtual void Init(palMatrix4x4 &pos, Float radius, Float mass);
//	virtual void Init(Float x, Float y, Float z, Float radius, Float mass);
	virtual void CalculateInertia();
	virtual void GenericInit(palMatrix4x4& location, void *param_array);
	Float m_fRadius; //< The radius of the sphere
protected:
	//virtual void iGenericInit(void *param,va_list arg_ptr);
};

/** A box geometry
	This represents a box (eg: cube, rectangular prism) at a given position, with a given width, height, depth and mass.
	<img src="../pictures/cube.jpg" alt="box">
	The diagram shows the central point of the box, as well as the width,height,and depth of the box.
*/
class palBoxGeometry : virtual public palGeometry {
public:
	//palBoxGeometry(palBody *pbody);
	/** Initializes the box
	The center of the box is specified by its position.
	\param pos The transformation matrix representing the position and orientation of the box
	\param width The width of the box
	\param height The height of the box
	\param depth depth The depth of the box
	\param mass The box's mass
	*/
	virtual void Init(palMatrix4x4 &pos, Float width, Float height, Float depth, Float mass);
//	virtual void Init(Float x, Float y, Float z, Float width, Float height, Float depth, Float mass);
	virtual void CalculateInertia();
	virtual void GenericInit(palMatrix4x4& location, void *param_array);
	Float m_fWidth; //< The width of the box
	Float m_fHeight; //< The height of the box
	Float m_fDepth; //< The depth of the box
protected:
	//virtual void iGenericInit(void *param,va_list arg_ptr);
};

/** A capped cylinder geometry
	This represents a capped cylinder at a given position, with a given radius, length and mass
	A capped cylinder, is just like a normal cylinder, however it has rounded end pieces (ie: two hemispheres, one at the top, one at the bottom), as opposed to flat ones. 
	<img src="../pictures/capsule.jpg" alt="cylinder">
	The diagram indicates the central point of the cylinder, as well as its length and radius.
	The default orientation of the cylinder is such that the length is specified along the "y" axis.
	The total length of the cylinder is the specified length plus double the radius.
*/
class palCylinderGeometry : virtual public palGeometry {
public:
	//palCylinderGeometry(palBody *pbody);
	/**
	Initializes the cylinder
	\param pos The transformation matrix representing the position and orientation of the cylinder
	\param radius The radius of the cylinder
	\param length The length of the cylinder
	\param mass The cylinder's mass
	????NOTE: HOW IS THE CENTER OF THE CYLINDER DEFINED? DIAGRAM.
	*/
	virtual void Init(palMatrix4x4 &pos, Float radius, Float length, Float mass);
//	virtual void Init(Float x, Float y, Float z, Float radius, Float length, Float mass);
	virtual void CalculateInertia();
	virtual void GenericInit(palMatrix4x4& location, void *param_array);
	Float m_fRadius; //< The radius of the cylinder
	Float m_fLength; //< The length of the cylinder
protected:
	//virtual void iGenericInit(void *param,va_list arg_ptr);
};
/*
//moment of inertia: parallel axis theorem:
//Itotal = ICM + M*dē (ie: original inertia tensor plus mass times distance squared)
class palCompoundBody : public palBody {
	virtual void Init(Float x, Float y, Float z);
//	this:
//	virtual void AddGeometry(palGeometry *pgeom);//?
//	or:
//	virtual palGeometry *AddGeomoetry(palGeomType type); //NYET! need to pass back sphere, box, or cylinder >=/
//	so:(?)
	virtual palSphereGeometry *AddSphere(); //NO (unless the pbody is made part of the constructor, and is created as a reference. >=])
//  so:
//  AddSphere(x,y,z,radius,mass); //eeevil

  //AddGeomoetry(STRING type,Float params?); /// eeeeevvil
  //AddGeomoetry(palSphereGeometry((this), x,y,z,radius mass);

  VECTOR<palGeometry *> m_Geometries;
};
*/


/** A convex geometry
	This represents a convex polygon shape at a given position constructed from a set of points.
	TODO: picture.
*/
class palConvexGeometry : virtual public palGeometry {
public:
	/**
	Initializes the convex shape. 
	A convex shape constains a set of vertices, which describe the location of corners in an object. 
	These vertices form a 'point cloud' describing the shape.

	The verticies are an array of Float values. Each vertex is assumed to be a group of 3 Float values.
	
	\param pos The transformation matrix representing the position and orientation of the convex object
	\param pVertices The vertices describing the shape
	\param nVertices The number of vertices (ie: the total number of Floats / 3)
	\param mass The objects's mass
	*/
	virtual void Init(palMatrix4x4 &pos, const Float *pVertices, int nVertices, Float mass);

	VECTOR<Float> m_vfVertices;
protected:
	virtual void CalculateInertia() {};
	virtual void GenericInit(palMatrix4x4& location, void *param_array) {};
};
#endif