#ifndef __TRANSFORM_H__
#define __TRANSFORM_H__

#include "matrix.h"

#include "public.h"

namespace xrt
{
	class Ray;
	class Point;
	class Vector;
	class HPoint;
	class Normal;
	class Aabb;

	class PUBLIC Transform
	{
	public:
//		Transform() { from = to = new Matrix( 1 ); }
		Transform(): from(Reference<Matrix>(&Matrix::Identity)), to(Reference<Matrix>(&Matrix::Identity)) {}
		Transform( const MatrixPtr &m ): from( m ), to( new Matrix( m->inverse() ) ) {}
		Transform( const float m[][4] ): from( new Matrix( m ) ), to( new Matrix( from->inverse() ) ) {}
		Transform( const Matrix &m ): from( new Matrix( m ) ), to( new Matrix( from->inverse() ) ) {}
		Transform( const MatrixPtr &m, const MatrixPtr &inv ): from( m ), to( inv ) {}
		Transform( const Matrix &m, const Matrix &inv ): from( new Matrix( m ) ), to( new Matrix( inv )  ) {}
		Transform& operator*=( const Transform & );
		~Transform();
		EXPORT friend Transform operator*( const Transform &, const Transform& );
		Point operator* ( const Point & ) const;
		Vector operator* ( const Vector & ) const;
		Normal operator* ( const Normal & ) const;
		HPoint operator* ( const HPoint & ) const;
		Ray operator* ( const Ray & ) const;
		Matrix operator* ( const Matrix & ) const;
		Aabb operator* ( const Aabb & ) const;
		Transform inverse() const { return Transform( to, from ); }
		bool isLeftHanded() const { return from->isLeftHanded(); }
		const Matrix* getFrom() const { return from.get(); }
		const Matrix* getTo() const { return to.get(); }
		static const Transform Identity;
	private:
		friend class MotionTransform;
		MatrixPtr from, to;
	};

	EXPORT Transform Translate( float, float, float );
	EXPORT Transform Rotate( float, const Vector& );
	EXPORT Transform Skew( const float, const Vector&, const Vector & );
	EXPORT Transform Scale( float, float, float );
}


#endif //__TRANSFORM_H__
