// **********************************************************************************
// * "a3i_intb.c"																	*
// * Written by :	Sébastien Rubens												*
// * Tabulations :	4 char															*
// **********************************************************************************
#define	A3I_INTB_C



// **********************************************************************************
//																	Included files
#include <stdio.h>
#include <math.h>

#include "specif\\a3x_pref.h"


#include "a3x_glob.h"
#include "a3x_int.h"
#include "a3x_intb.h"

// temp
extern SEB_xReal xEps;
extern SEB_xReal xOneSubEps;

// **********************************************************************************
//														Interpolations computations

// Interpolation of the whole matrixial definition of an object
// By :		Sébastien Rubens (thursday 97/10/16)
// Input :
//		_stKey1			 =	first key
//		_stKey2			 =	second key
//		_a3a3_xMtxOri	<-	interpolated orientation matrix
//		_a3a3_xMtxSca	<-	interpolated scale matrix
//		_a3a3_xVecTra	<-	interpolated translation vector
//		_xT				 =	interpolation parameter
// Output :
//		void
// Modif 28/08/98 : Treat Interpolation - type 1 (Non Linear)
void	fn_v_BinInterpolBetweenKeys(	tdstBinFrame		*_p_stKey1,
										tdstBinFrame		*_p_stKey2,
										tdxMatrix33			_a3a3_xMtxOri,
										tdxMatrix33			_a3a3_xMtxSca,
										tdxVector3			_a3_xPosition,
										register SEB_xReal	_xT,
										tdxVector3			_a3_xPivotPosition,
										tdxQuater4			_a4_xQuatOri,
										tdxQuater4			_a4_xQuatSca,
										tdxVector3			_a3_xVecSca	)
{	static tdxQuater4		a4_xQuatI;
	static tdxVector3		a3_xTmpVec;
	register SEB_xReal		xSinOmega;
	register SEB_xReal		xCoef1, xCoef2;
	register SEB_xReal		xOmega, xCosOmega, xTbyOmega;


// -- Non linear T parameter -------
	if	( (fabs(_p_stKey1->xInterpolationParameter) > xEps) && (_xT != xZero) )
	{	register	SEB_xReal	xTmp;
		xTmp=	_p_stKey1->xInterpolationParameter * ((SEB_xReal) (1.0f / 8192.0f));
		_xT=	_xT * (_xT * xTmp + xOne - xTmp);
	}


// -- Interpolation of scale -------
	// Interpolation of scale direction
	fn_v_InterpolQuat( _a4_xQuatSca, _p_stKey1->a4_xQuatSca, _p_stKey2->a4_xQuatSca, _xT );
	//fn_v_InterpolQuatWithOmega( a4_xQuatI, _p_stKey1->a4_xQuatSca, _p_stKey2->a4_xQuatSca,
	//							_xT, _p_stKey1->uwOmegaSca );
	fn_v_QuatToMatrix( _a3a3_xMtxOri, _a4_xQuatSca);

	// Linear interpolation of scale values
	fn_v_InterpolVect( _a3_xVecSca, _p_stKey1->a3_xScaleValues, _p_stKey2->a3_xScaleValues, _xT );

	// Create final scale matrix
	// Final matrix= [scale dir. matrix]^-1*[values scale matrix]*[scale dir. matrix]
	fn_v_InvRotDiaRot( _a3a3_xMtxSca, _a3a3_xMtxOri, _a3_xVecSca );
	//printf("%3.8f  %3.8f  %3.8f  %3.8f\n",	a4_xQuatI[0], a4_xQuatI[1], a4_xQuatI[2], a4_xQuatI[3] );


// -- Interpolation of orientation -------
	fn_v_InterpolQuat( _a4_xQuatOri, _p_stKey1->a4_xQuatOri, _p_stKey2->a4_xQuatOri, _xT );
	//fn_v_InterpolQuatWithOmega( a4_xQuatI, _p_stKey1->a4_xQuatOri, _p_stKey2->a4_xQuatOri,
	//							_xT, _p_stKey1->uwOmegaOri  );
	fn_v_QuatToMatrix(	_a3a3_xMtxOri, _a4_xQuatOri );


// -- Les deux matrices multipliées -------
	// Multiplie dans l'espace des quaternions (16 mul), et transformation en matrice (9 mul)
	// puis multiplie par matrice diagonale (9 mul)


// -- Interpolation of position -------
	if	( (_p_stKey1->uwTypeOfObject & SEB_xTypeHierarchized) == 0 )
	{
	// Interpolation with the pivot
		// Rotate pivot (local to object)
		fn_v_MatrixByVector( _a3_xPosition, _a3a3_xMtxSca, _a3_xPivotPosition );
		fn_v_MatrixByVector(    a3_xTmpVec, _a3a3_xMtxOri, _a3_xPosition );

		// Pivot (linear) interpolation in world axes
		fn_v_InterpolVect(	_a3_xPosition,  _p_stKey1->a3_xWorldPivotPosition,
											_p_stKey2->a3_xWorldPivotPosition, _xT );

		// Computes the interpolated position
		_a3_xPosition[0]-=	a3_xTmpVec[0];
		_a3_xPosition[1]-=	a3_xTmpVec[1];
		_a3_xPosition[2]-=	a3_xTmpVec[2];
	}
	else
	{
	// Interpolation with Hierarchy
		if	( (_p_stKey1->xDistMaster > xEps) || (_p_stKey2->xDistMaster > xEps) )
		{
			// Computes values for "Geodesic" interpolation

			if	( (_p_stKey1->xDistMaster > xEps) && (_p_stKey2->xDistMaster > xEps) )
			{
				xCosOmega=	(_p_stKey1->a3_xPosition[0] * _p_stKey2->a3_xPosition[0] +
							 _p_stKey1->a3_xPosition[1] * _p_stKey2->a3_xPosition[1] +
							 _p_stKey1->a3_xPosition[2] * _p_stKey2->a3_xPosition[2]) /
							(_p_stKey1->xDistMaster * _p_stKey2->xDistMaster);
				xOmega=		(SEB_xReal) acos( xCosOmega );

				if	( xOneSubEps > xCosOmega )
				{	xSinOmega=	xOne / (SEB_xReal) sin( xOmega );
					xTbyOmega=	(_xT * xOmega);		// Toujours < _lOmega et toujours positif
					xCoef1=		(SEB_xReal) sin( xOmega - xTbyOmega ) * xSinOmega;
					xCoef2=		(SEB_xReal) sin( xTbyOmega ) * xSinOmega;
				}
				else
				{	xCoef1=		xOne - _xT;
					xCoef2=		_xT;
				}

				// Linear interpolation of vector length
				xSinOmega=	( _p_stKey2->xDistMaster - _p_stKey1->xDistMaster ) * _xT
							+ _p_stKey1->xDistMaster;
				xCoef1*=	xSinOmega / _p_stKey1->xDistMaster;
				xCoef2*=	xSinOmega / _p_stKey2->xDistMaster;

				// Computes the interpolated position
				_a3_xPosition[0]=	xCoef1 * _p_stKey1->a3_xPosition[0] + xCoef2 * _p_stKey2->a3_xPosition[0];
				_a3_xPosition[1]=	xCoef1 * _p_stKey1->a3_xPosition[1] + xCoef2 * _p_stKey2->a3_xPosition[1];
				_a3_xPosition[2]=	xCoef1 * _p_stKey1->a3_xPosition[2] + xCoef2 * _p_stKey2->a3_xPosition[2];
			}
			else
			{	fn_v_InterpolVect( _a3_xPosition, _p_stKey1->a3_xPosition, _p_stKey2->a3_xPosition, _xT );
			}

		}
		else
		{
			_a3_xPosition[0]=	xZero;
			_a3_xPosition[1]=	xZero;
			_a3_xPosition[2]=	xZero;
		}
	}
}



// **********************************************************************************
#undef	A3I_INTB_C
