
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_SurfaceReorientationNormalInterpolator_AxisRotation.h
// Author : Andy Tate
// Date   : 7-Feb-2008
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __AVP_SURFACEREORIENTATIONNORMALINTERPOLATOR_AXISROTATION_H__
#define __AVP_SURFACEREORIENTATIONNORMALINTERPOLATOR_AXISROTATION_H__

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Physics/AVP_SurfaceReorientationNormalInterpolator.h"


////////////////////////////////////////////////////////////////////////////////
// Forward class declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_SurfaceReorientationNormalInterpolator_AxisRotation
// Author       : Andy Tate
// Date         : 7-Feb-2008
//
// Description  : Class used to interpolate to a desired normal (using a 
//				  velocity-interceptor) during surface-reorientation.
////////////////////////////////////////////////////////////////////////////////

class AVP_SurfaceReorientationNormalInterpolator_AxisRotation : public AVP_SurfaceReorientationNormalInterpolator
{
public:
	// Public functions...
	AVP_SurfaceReorientationNormalInterpolator_AxisRotation(void);
	//virtual ~AVP_SurfaceReorientationNormalInterpolator_AxisRotation();

	// Overridden functions...
	virtual void	Reset(Asura_AVector3_InParam xNormal);

	virtual	void	Update(const float fTimeStep, Asura_AVector3_InParam xDesiredNormal, Asura_AVector3_InOutParam xCurrentNormal);
	virtual	void	Update(const float fTimeStep, const AVP_CalculateSurfaceReorientationNormal& xNormalCalculation, Asura_AVector3_InOutParam xCurrentNormal);

	// Accessor functions...
	void	SetVelocityToAngularVelocityScale(const float fScale)	{ m_fVelocityToAngularVelocityScale = fScale; }
	void	SetAngleToRotateScale(const float fScale)				{ m_fAngleToRotateScale = fScale; }


protected:
	// Protected variables...
	Asura_AVector3	m_xCurrentAxisOfRotation;			// The current axis around which we are to rotate.
	Asura_Angle		m_fCurrentRotationSpeed;			// The current speed at which to rotate.
	float			m_fVelocityToAngularVelocityScale;	// Scale factor used to convert from velocity to angular-velocity.
	float			m_fAngleToRotateScale;				// Scale factor used to smooth rotation near the end.

	// Protected functions...
	Asura_Angle	CalculateAngleAboutAxis(Asura_AVector3_InParam xAxisOfRotation, Asura_AVector3_InParam xFromNormal, Asura_AVector3_InParam xToNormal) const;
	void		CalculateAveragedNormalIgnoringClosest(const AVP_CalculateSurfaceReorientationNormal& xNormalCalculation, Asura_AVector3_InParam xAxisOfRotation, Asura_AVector3_InParam xUpVector, Asura_AVector3_OutParam xAveragedNormal) const;
	void		CalculateAveragedNormalWereRotatingTowards(const AVP_CalculateSurfaceReorientationNormal& xNormalCalculation, Asura_AVector3_InParam xAxisOfRotation, Asura_AVector3_InParam xUpVector, const float fRotationSign, Asura_AVector3_OutParam xAveragedNormal) const;

	void		CalculateRotationFromGravityDirection(Asura_AVector3_InParam xGravityDirection, Asura_Quat& xRotation) const;
	bool		CalculateAxisOfRotation(Asura_AVector3_InParam xDesiredNormal, Asura_AVector3_InParam xCurrentNormal, Asura_AVector3_OutParam xAxisOfRotation) const;
	bool		CalculateAxisOfRotation(const AVP_CalculateSurfaceReorientationNormal& xNormalCalculation, Asura_AVector3_InParam xDesiredNormal, Asura_AVector3_InParam xCurrentNormal, Asura_AVector3_OutParam xAxisOfRotation) const;
	Asura_Angle	CalculateRotationSpeed(const AVP_CalculateSurfaceReorientationNormal& xNormalCalculation, Asura_AVector3_InParam xAxisOfRotation, Asura_AVector3_InParam xDesiredNormal, Asura_AVector3_InParam xCurrentNormal) const;
	Asura_Angle	CalculateAngleToRotate(const float fTimeStep, const AVP_CalculateSurfaceReorientationNormal& xNormalCalculation, Asura_AVector3_InParam xAxisOfRotation, const Asura_Angle fRotationSpeed, Asura_AVector3_InParam xCurrentNormal) const;


private:
	// Private variables...

	// Private functions...
	AVP_SurfaceReorientationNormalInterpolator_AxisRotation(const AVP_SurfaceReorientationNormalInterpolator_AxisRotation& xOther);

	AVP_SurfaceReorientationNormalInterpolator_AxisRotation&	operator=(const AVP_SurfaceReorientationNormalInterpolator_AxisRotation& xOther);

};   // End of class 'AVP_SurfaceReorientationNormalInterpolator_AxisRotation'.


#endif   // ifndef __AVP_SURFACEREORIENTATIONNORMALINTERPOLATOR_AXISROTATION_H__


/// End of file. ///
