/*
QtWagon: a project about 3D objects.
Science and technology promotion license applied. Third party license automatically cascaded.
Zhikai Wang/ www.heteroclinic.net 2013
You can do anything with this file or any file(s) published as part QtWagon project, given this header is kept.
*/
#ifndef __GLMOVINGOBJECT
#define __GLMOVINGOBJECT
#include "to_string.h"
#include "glOrientation.h"
#include <iostream>
#include <string>
#include <GL/glut.h>
#include <vector>
#include <algorithm> // for search
#include <set>
#include <map>
#include <string>
template <class T> class  glMovingObject;

#ifdef __USE_DOUBLE
typedef glMovingObject<double> glMovingObjectd;
#else
typedef glMovingObject<float> glMovingObjectf;
#endif

template <class T>
class  glMovingObject: 
	public glOrientation<T>
{
private:
protected:
	mathPoint<T> position;
public:
	void glMovingObject::yawThenRollToPinAPoint(mathPoint<T> target) {
		mathVector<T> targetv = target - position;
		mathVector<T>  tmpv = cross( up, targetv);
		mathVector<T>  tmpv2 = cross( tmpv, up);
		T angle2yaw =  angleBetweenVW2(front,tmpv2,up);
		glOrientation::yaw(angle2yaw);
		T angle2pitch = ((T)-1.0 )*  angleBetweenVW2(front,targetv,left);
		glOrientation::pitch(angle2pitch);
	}
	const mathPoint<T> & getPosition() {
		return position;
	}
	virtual void setPosition(const mathPoint<T> &npos) {
		position = npos;
	}
	virtual void forward(T distance = 0.5) {
		position = mathPoint<T>(position.getx()+ front.getx()*distance,
			position.gety()+ front.gety()*distance,
			position.getz()+ front.getz()*distance
			);
	}
	virtual void backward(T distance = 0.5) {
		position = mathPoint<T>(position.getx()-front.getx()*distance,
			position.gety()- front.gety()*distance,
			position.getz()- front.getz()*distance
			);
	}
	glMovingObject (const mathPoint<T> & nglobalPosition  = mathPoint<T>(0.0,0.0,0.0)):
	position ( nglobalPosition)
	{
	}
	virtual ~ glMovingObject () {
		//std::cout<<" ~ wagon ()"<<std::endl;
	}
	virtual void drawv(T scale = (T)1.0) {
		glPushMatrix();
#ifdef __USE_DOUBLE
		glTranslated(position.getx(),position.gety(),position.getz());
#else
		glTranslatef(position.getx(),position.gety(),position.getz());
#endif
		glPushMatrix();
		glPushMatrix();
		glPushMatrix();
#ifdef __USE_DOUBLE
		glMultMatrixd(RYP.getDataPointer());
#else
		glMultMatrixf(RYP.getDataPointer());
#endif
		
		glDisable(GL_LIGHTING);
		drawOrthorgonalAxis(scale );
		glPopMatrix();
		glPopMatrix();
		glPopMatrix();
	}
	template <class U> 
	friend std::ostream & operator << (std::ostream & os,const glMovingObject<U> & vl);
	template <class U> 
	friend std::istream & operator >> (std::istream & is, glMovingObject<U> & vl);
};
template <class U> 
std::ostream & operator << (std::ostream & os,const glMovingObject<U> & vl) {
	os<<vl.position;
	os<<(glOrientation<U> &)vl;
	return os;
};
template <class U> 
std::istream & operator >> (std::istream & is, glMovingObject<U> & vl ) {
	is>>vl.position;
	is>>(glOrientation<U> &)vl;
	return is;
};
#endif