/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     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: sgx/include/sgx/core/math/matrix43.hpp

*/

#ifndef SGX_CORE_MATH_MATRIX43_HPP
#define SGX_CORE_MATH_MATRIX43_HPP	1

class sgxVector2;
class sgxVector3;
class sgxVector4;
class sgxMatrix43;
class sgxMatrix44;

class sgxMatrix43 {
public:
	sgxVector3	right;
	sgxVector3	up;
	sgxVector3	at;
	sgxVector3	pos;

	SGX_INLINE	sgxMatrix43(){}

	SGX_INLINE	sgxMatrix43(const sgxVector3 &r, const sgxVector3 &u, const sgxVector3 &a, const sgxVector3 &p)
	{ 
		right=r;
		up=u;
		at=a;
		pos=p;
	}

	SGX_INLINE	sgxMatrix43(const tREAL32 x, const tREAL32 y, const tREAL32 z)
	{ 
		right=sgxVector3(1,0,0); 
		up=sgxVector3(0,1,0);
		at=sgxVector3(0,0,1); 
		pos=sgxVector3(x,y,z); 
	}

	SGX_INLINE	sgxMatrix43(const sgxVector3 &_pos)
	{ 
		right=sgxVector3(1,0,0); 
		up=sgxVector3(0,1,0);
		at=sgxVector3(0,0,1); 
		pos=_pos;
	}
	
	sgxMatrix43 operator*(const sgxMatrix43 &m);
	sgxVector3  operator*(const sgxVector3 &v3);
	sgxVector2  operator*(const sgxVector2 &v2);

	sgxVector2  mul(const tREAL32 x, const tREAL32 y);
	sgxVector2  mul(const tINT32 x, const tINT32 y);

	SGX_INLINE	void identity() { right=sgxVector3(1,0,0); up=sgxVector3(0,1,0);
							at=sgxVector3(0,0,1); pos=sgxVector3(0,0,0); }

	SGX_INLINE	void setPos(const sgxVector3 &vpos) { pos = vpos; }
	SGX_INLINE	void setPos(const sgxVector4 &vpos) { pos = sgxVector4(vpos); }
	SGX_INLINE	void setPosition(const sgxVector3 &vpos) { pos = vpos; }
	SGX_INLINE	void setPosition(const sgxVector4 &vpos) { pos = sgxVector4(vpos); }
	SGX_INLINE  void setPosition(const sgxVector2 &offset) { pos.x = offset.x; pos.y = offset.y; }
	
	SGX_INLINE	void getPosition(sgxVector3 &vpos) const { vpos = pos; }

				void setRotateAxis(const tREAL32 theta, const sgxVector3 &axis);
				void setRotateX(const tREAL32 theta);
				void setRotateY(const tREAL32 theta);
				void setRotateZ(const tREAL32 theta);

	SGX_INLINE  void scale(tREAL32 scale) { right.x *= scale; up.y *= scale; at.z *= scale; }
	SGX_INLINE  void scale(tREAL32 sx, tREAL32 sy, tREAL32 sz) { right.x *= sx; up.y *= sy; at.z *= sz; }
	SGX_INLINE 	void scale(const sgxVector2 &scaleFactor) { right.x *= scaleFactor.x; up.y *= scaleFactor.y; }

	SGX_INLINE	void translate(tREAL32 tx, tREAL32 ty, tREAL32 tz) { pos.x += tx; pos.y += ty; pos.z += tz; }
	SGX_INLINE	void translate(const sgxVector2 &offset) { pos.x += offset.x; pos.y += offset.y; }

				tREAL32 		determinant() const;
				sgxMatrix43 	inverse() const;
				tBOOL			inverse(sgxMatrix43 &result) const;
				sgxMatrix44 	inverse44() const;
	SGX_INLINE	void			normalize() { tREAL32 d=1.0f/determinant(); right *= d; up *= d; at *= d;  }

	SGX_INLINE	tBOOL			isIdentity() { return pos.x==0 && pos.y==0 && pos.z==0 && isIdentityTransform(); }

	SGX_INLINE	tBOOL			isIdentityTransform() { return right.x==1 && up.y==1 && at.z==1 && right.y==0 && right.z==0 && up.x==0 && up.z==0 && at.x==0 && at.y==0; }

};

#endif /* SGX_CORE_MATH_MATRIX43_HPP */
