//------------------------------------------------------------------------------------
// irr::core::quaternion wrappers
//------------------------------------------------------------------------------------
extern "C" 
{

	quaternion* IrrCore_Quaternion_newFrom3Vals(f32 x,f32 y,f32 z)
	{
		return new quaternion(x,y,z);
	}
	
	quaternion* IrrCore_Quaternion_newFrom4Vals(f32 x,f32 y,f32 z,f32 w)
	{
		return new quaternion(x,y,z,w);
	}

	quaternion* IrrCore_Quaternion_newFromVect(vector3df& vec)
	{
		return new quaternion(vec);
	}
	
	quaternion* IrrCore_Quaternion_new()
	{
		return new quaternion();
	}
	
	quaternion* IrrCore_Quaternion_newFromMatrix(matrix4* mat)
	{
		return new quaternion(*mat);
	}
	
	void IrrCore_Quaternion_del(quaternion* del)
	{
		if (del)
			delete del;
			
		del=0;
	}
	
	f32 IrrCore_Quaternion_dotProduct(quaternion* quat,quaternion* other)
	{
		f32 fRetVal=0.0f;
	
		if (quat>0)
			fRetVal=quat->dotProduct(*other);
	
		return fRetVal;
	}
	
	quaternion* IrrCore_Quaternion_setFrom4Vals(quaternion* quat,f32 x, f32 y, f32 z, f32 w)
	{
		if (quat>0)
			return &(quat->set(x,y,z,w));
		else return 0;
	}
	
	quaternion* IrrCore_Quaternion_setFrom3Vals(quaternion* quat,f32 x, f32 y, f32 z)
	{
		if (quat>0)
			return &(quat->set(x,y,z));
		else return 0;
	}

	quaternion* IrrCore_Quaternion_setFromVect(quaternion* quat, vector3df* vec)
	{
		if (quat)
			return &(quat->set(*vec));
		else return 0;
	}

	// do not delete ptr
	quaternion* IrrCore_Quaternion_normalize(quaternion* quat)
	{
		if (quat>0)
			return &quat->normalize();
		else return 0;
	}
	
	matrix4* IrrCore_Quaternion_getMatrix(quaternion* quat)
	{
		matrix4* pRetVal=0;
	
		if (quat>0)
			pRetVal=new matrix4(quat->getMatrix());
	
		return pRetVal;
	}

	void IrrCore_Quaternion_getMatrixToDest(quaternion* quat,matrix4 &dest, const vector3df* translation)
	{
		if (quat)
			quat->getMatrix(dest, *translation);		
	}

	void IrrCore_Quaternion_getMatrix_transposed(quaternion* quat,matrix4 &dest)
	{
		if (quat)
			quat->getMatrix_transposed(dest);
	}
	
	quaternion* IrrCore_Quaternion_makeInverse(quaternion* quat)
	{
		if (quat>0)
			return &(quat->makeInverse());
		else return 0;
	}

	quaternion* IrrCore_Quaternion_slerp(quaternion* quat,quaternion* q1,quaternion* q2,f32 interpolate) 
	{	
		if (quat)
			return &(quat->slerp(*q1,*q2,interpolate));
		else return 0;
	}
	
	quaternion* IrrCore_Quaternion_fromAngleAxis(quaternion* quat,f32 angle,vector3df* axis)
	{
		if (quat>0)
			return &(quat->fromAngleAxis(angle,*axis));
		else return 0;
	}
	
	void IrrCore_Quaternion_toEuler(quaternion* quat,vector3df* euler)
	{
		if (quat>0)
			quat->toEuler(*euler);
	}
	
	f32 IrrCore_Quaternion_getX(quaternion* quat)
	{
		f32 fRetVal=0.0f;
	
		if (quat)
			fRetVal=quat->X;
	
		return fRetVal;
	}
	
	f32 IrrCore_Quaternion_getY(quaternion* quat)
	{
		f32 fRetVal=0.0f;
	
		if (quat)
			fRetVal=quat->Y;
	
		return fRetVal;
	}
	
	f32 IrrCore_Quaternion_getZ(quaternion* quat)
	{
		f32 fRetVal=0.0f;
	
		if (quat)
			fRetVal=quat->Z;
	
		return fRetVal;
	}
	
	f32 IrrCore_Quaternion_getW(quaternion* quat)
	{
		f32 fRetVal=0.0f;
	
		if (quat)
			fRetVal=quat->W;
	
		return fRetVal;
	}
	
	bool IrrCore_Quaternion_EqEq(quaternion* quat,quaternion* other)
	{
		return (*quat==*other);
	}
	
	void IrrCore_Quaternion_EqQuat(quaternion* quat,quaternion* other)
	{
		if (quat)
			*quat=*other;
	}
	
	void IrrCore_Quaternion_EqMat(quaternion* quat,matrix4* other)
	{
		if (quat)
			*quat=*other;
	}
	
	quaternion* IrrCore_Quaternion_Plus(quaternion* quat,quaternion* other)
	{
		return new quaternion(*quat+*other);
	}
	
	quaternion* IrrCore_Quaternion_MultQuat(quaternion* quat,quaternion* other)
	{
		return new quaternion(*quat * *other);
	}
	
	quaternion* IrrCore_Quaternion_MultFloat(quaternion* quat,f32 s)
	{
		return new quaternion(*quat * s);
	}
	
	vector3df* IrrCore_Quaternion_MultVect(quaternion* quat,vector3df* vect)
	{
		return new vector3df(*quat * *vect);
	}
	
	void IrrCore_Quaternion_MultEqFloat(quaternion* quat,f32 s)
	{
		if (quat)
			*quat*=s;
	}
	
	void IrrCore_Quaternion_MultEqQuat(quaternion* quat,quaternion* other)
	{
		if (quat)
			*quat*=*other;
	}
	
	quaternion* IrrCore_Quaternion_makeIdentity(quaternion* quat)
	{
		if (quat)
			return &(quat->makeIdentity());
		else return 0;
	}
	
	void IrrCore_Quaternion_toAngleAxis(quaternion* quat,f32 &angle, vector3df& axis)
	{
		if (quat)
			quat->toAngleAxis(angle,axis);
	}	

	quaternion* IrrCore_Quaternion_rotationFromTo(quaternion* quat, vector3df* from, vector3df* to)
	{
		if (quat)
			return &(quat->rotationFromTo(*from,*to));
		else return 0;
	}
	
	void IrrCore_Quaternion_getMatrixCenter(quaternion* quat, matrix4 &dest, const vector3df &center, const vector3df &translation ) {
		if (quat)
			quat->getMatrixCenter(dest, center, translation);
	}

	bool IrrCore_Quaternion_equals(quaternion* quat, const quaternion& other, const f32 tolerance = ROUNDING_ERROR_f32 )
	{
		if (quat)
			return quat->equals(other, tolerance);
		else return false;
	}
	
	quaternion* IrrCore_Quaternion_setFromOther(quaternion* quat, const core::quaternion& other) 
	{
		if (quat)
			return &(quat->set(other));
		else return 0;
	}
	
	bool IrrCore_Quaternion_NotEq(quaternion* quat, const quaternion& other)
	{
		if (quat)
			return (*quat != other);
		else return false;
	}
	
}