/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: include/sgx/graphics/curves/path.hpp

*/

#ifndef SGX_GFX_CURVE_PATH_HPP
#define SGX_GFX_CURVE_PATH_HPP	1


#define SGX_BEZIER_SECTIONS		8


class CMatrix
{
public:
	tREAL32 m[3][3];	//!< columns represent local axes
	sgxVector3 t;		//!< position/translation
};



// Helper classes. Could be extended with basic functionality.
class CBezierSections {
public:
	sgxVector3			pos;
	sgxVector3			delta;	// to save calculations later
	tREAL32				t;		// to save int to float calculations later

	tREAL32				getDistanceSquared(const sgxVector3 *pPos) const;
};

class CBezierSegment {
public:
	CBezierSegment() : m_bLoopAtLimits(FALSE) {}

	CMatrix				m_Control;
	CBezierSections		m_Section[SGX_BEZIER_SECTIONS+1];

	void		calculatePositionAtT(sgxVector3 &pos, const tREAL32 t);
	void		evaluateSections();
	void		getFastPosition(sgxVector3 &pos, const tREAL32 t);
	void		getPosition(sgxVector3 &pos, const tREAL32 t);

	tREAL32		evaluateTime(tREAL32 t);

	void		EnableLoopAtLimits() { m_bLoopAtLimits = TRUE; }
	void		DisableLoopAtLimits() { m_bLoopAtLimits = FALSE; }

protected:
	tBOOL	m_bLoopAtLimits;
};

class CBezierHandle {
public:
	tUINT32	m_iBezier;
	tUINT32	m_iSection;

	CBezierHandle() 
	{
		Begin();
	}

	void Begin() 
	{
		m_iBezier = 0;
		m_iSection = 0;
	}
};

// CSpline: An instance of this class is designed to represent a spline comprised 
// of multiple attached bezier sections.

// Note: prototypes are as provided, although better ones are available:
// e.g. generateLocalSpaces(const int numPoints, const sgxVector3* pPoints);
class CSpline {
public:

	// No return type supplied. Use tBOOL to indicate success/failure
	// This function can fail because of invalid NumPoints of pPoints
	tBOOL		generateLocalSpaces(int numPoints, sgxVector3* pPoints);
	tBOOL		getClosestSegment(CBezierHandle &rts, const sgxVector3 *pPos) const;
	tBOOL		getNextSegment(CBezierHandle &rts, const CBezierHandle &current) const;
	tBOOL		getPrevSegment(CBezierHandle &rts, const CBezierHandle &current) const;
	tREAL32		getDistanceSquared(const CBezierHandle &current, const sgxVector3 *pPos) const;


private:
	const CBezierSections *getSection(const CBezierHandle handle) const;
public: //TODO: FIXME:BUGWARN
	std::vector<CBezierSegment> m_Beziers;
};


#endif /* SGX_GFX_CURVE_PATH_HPP */
