/*
	Ninja Library
	
	COPYRIGHT ( C ) SEGA ENTERPRISES, LTD.
*/

#include "NuMotionMake.h"

/*
	注意:	このファイルの関数は、引数だけを入力し、引数の指すアドレスにだけ出力すること。
			暗黙の入力を持ってはならない。
			こうすることにより関数の汎用性が向上する。
*/


#define NUD_ONEOVER3		0.33333f



NUF_MOTION_INT_F3_FUNC	*_nu_motion_int_f3_func_table_[2] =
{
	nuMotionIntLinearF3, nuMotionIntOverhauserF3, 
};

NUF_MOTION_INT_A3_FUNC	*_nu_motion_int_a3_func_table_[2] =
{
	nuMotionIntLinearA3, nuMotionIntLinearA3,
};

NUF_MOTION_INT_A1_FUNC	*_nu_motion_int_a1_func_table_[2] =
{
	nuMotionIntLinearA1, nuMotionIntLinearA1
};

NUF_MOTION_INT_SA3_FUNC	*_nu_motion_int_sa3_func_table_[2] =
{
	nuMotionIntLinearSA3, nuMotionIntLinearSA3,
};

/****************************************************************/
/*	関数名：nuMotionIntLinearQ									*/
/*	機  能：クォータニオン線形補間関数							*/
/*	入  力：NUS_MKEY_F		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Float			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntLinearQ( const NUS_MKEY_QUAT *key, Uint32 nbkeys, Float frame, Float *dst )
{
	Float			rate1;
	NUS_MKEY_QUAT	*key1;
	NUS_MKEY_QUAT	*key2;
	
	_nuGetMotionLinearKeys( (void*)key, sizeof(NUS_MKEY_QUAT), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	
	njInterpolateQuaternion( (NJS_QUATERNION *)key1->key, (NJS_QUATERNION *)key2->key, rate1,
							 (NJS_QUATERNION *)dst );
}

/****************************************************************/
/*	関数名：nuMotionIntLinearF3									*/
/*	機  能：Float * 3 線形補間関数								*/
/*	入  力：NUS_MKEY_F		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Float			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntLinearF3( const NUS_MKEY_F *key, Uint32 nbkeys, Float frame, Float *dst )
{
	Float			rate1;
	NUS_MKEY_F		*key1;
	NUS_MKEY_F		*key2;
	
	_nuGetMotionLinearKeys( (void*)key, sizeof(NUS_MKEY_F), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	#if 0
	{
		Float			rate2;
		
		rate2	= 1.0f - rate1;
		
		dst[0]	= key1->key[0] * rate2 + key2->key[0] * rate1;
		dst[1]	= key1->key[1] * rate2 + key2->key[1] * rate1;
		dst[2]	= key1->key[2] * rate2 + key2->key[2] * rate1;
	}
	#else
	{
		//	掛け算の個数を６から３へ減らす。
		
		dst[0]	= key1->key[0] + (key2->key[0] - key1->key[0]) * rate1;
		dst[1]	= key1->key[1] + (key2->key[1] - key1->key[1]) * rate1;
		dst[2]	= key1->key[2] + (key2->key[2] - key1->key[2]) * rate1;
	}
	#endif
}

/****************************************************************/
/*	関数名：nuMotionIntLinearF2									*/
/*	機  能：Float * 2 線形補間関数								*/
/*	入  力：NUS_MKEY_F2		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Float			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntLinearF2( const NUS_MKEY_F2 *key, Uint32 nbkeys, Float frame, Float *dst )
{
	Float			rate1;
	NUS_MKEY_F2		*key1;
	NUS_MKEY_F2		*key2;
	
	_nuGetMotionLinearKeys( (void*)key, sizeof(NUS_MKEY_F2), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	dst[0]	= key1->key[0] + (key2->key[0] - key1->key[0]) * rate1;
	dst[1]	= key1->key[1] + (key2->key[1] - key1->key[1]) * rate1;
}

/****************************************************************/
/*	関数名：nuMotionIntLinearA1									*/
/*	機  能：Angle * 1 近い方向への線形補間関数					*/
/*	入  力：NUS_MKEY_A1		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Angle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*																*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntLinearA1( const NUS_MKEY_A1 *key, Uint32 nbkeys, Float frame, Angle *dst )
{
	Float			rate1;
	NUS_MKEY_A1		*key1;
	NUS_MKEY_A1		*key2;
	
	_nuGetMotionLinearKeys( (void*)key, sizeof(NUS_MKEY_A1), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	// 近い方への補完
	*dst	= (Angle)( key1->key + ( (Sint16)(key2->key - key1->key) ) * rate1 );
}

/****************************************************************/
/*	関数名：nuMotionIntLinearA3									*/
/*	機  能：Angle * 3 近い方向への線形補間関数					*/
/*	入  力：NUS_MKEY_A		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Angle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntLinearA3( const NUS_MKEY_A *key, Uint32 nbkeys, Float frame, Angle *dst )
{
	Float			rate1;
	NUS_MKEY_A		*key1;
	NUS_MKEY_A		*key2;
	
	_nuGetMotionLinearKeys( (void*)key, sizeof(NUS_MKEY_A), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	// 近い方への補完
	dst[0]	= (Angle)( key1->key[0] + ((Sint16)(key2->key[0] - key1->key[0])) * rate1 );
	dst[1]	= (Angle)( key1->key[1] + ((Sint16)(key2->key[1] - key1->key[1])) * rate1 );
	dst[2]	= (Angle)( key1->key[2] + ((Sint16)(key2->key[2] - key1->key[2])) * rate1 );
}

/****************************************************************/
/*	関数名：nuMotionIntLinearSA3									*/
/*	機  能：Sangle * 3 近い方向への線形補間関数					*/
/*	入  力：NUS_MKEY_SA		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Angle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntLinearSA3( const NUS_MKEY_SA *key, Uint32 nbkeys, Float frame, Sangle *dst )
{
	Float			rate1;
	NUS_MKEY_SA		*key1;
	NUS_MKEY_SA		*key2;
	
	_nuGetMotionLinearKeys16( (void*)key, sizeof(NUS_MKEY_SA), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	// 近い方への補完
	dst[0]	= (Sangle)( key1->key[0] + ((Sint16)(key2->key[0] - key1->key[0])) * rate1 );
	dst[1]	= (Sangle)( key1->key[1] + ((Sint16)(key2->key[1] - key1->key[1])) * rate1 );
	dst[2]	= (Sangle)( key1->key[2] + ((Sint16)(key2->key[2] - key1->key[2])) * rate1 );
}

/****************************************************************/
/*	関数名：nuMotionIntLinearSA1								*/
/*	機  能：Sangle * 1 近い方向への線形補間関数					*/
/*	入  力：NUS_MKEY_SA1	*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Sangle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*																*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntLinearSA1( const NUS_MKEY_SA1 *key, Uint32 nbkeys, Float frame, Sangle *dst )
{
	Float			rate1;
	NUS_MKEY_SA1	*key1;
	NUS_MKEY_SA1	*key2;
	
	_nuGetMotionLinearKeys16( (void*)key, sizeof(NUS_MKEY_SA1), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	// 近い方への補完
	*dst	= (Sangle)( key1->key + ( (Sint16)(key2->key - key1->key) ) * rate1 );
}

/****************************************************************/
/*	関数名：nuMotionIntLinearSA1								*/
/*	機  能：Sangle * 1 近い方向への線形補間関数					*/
/*	入  力：NUS_MKEY_SA1	*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Sangle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*																*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntEvent( const NUS_MKEY_UI16 *key, Uint32 nbkeys, Float frame, Uint16 *dst )
{
	Float			rate1;
	NUS_MKEY_UI16	*key1;
	NUS_MKEY_UI16	*key2;
	
	_nuGetMotionLinearKeys16( (void*)key, sizeof(NUS_MKEY_UI16), nbkeys, frame,
							(void**)&key1, (void**)&key2, &rate1 );
	
	// 近い方への補完
	if(rate1 <= 1.f){
		*dst = key1->key;
	}
	else{
		*dst = key2->key;
	}
}

/****************************************************************/
/*	関数名：nuMotionIntOverhauserF3								*/
/*	機  能：Float * 3 スプライン補間関数（Ｏｖｅｒｈａｕｓｅｒ	*/
/*	入  力：NUS_MKEY_A		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Float			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntOverhauserF3( const NUS_MKEY_F *key, Uint32 nbkeys, Float frame, Float *dst )
{
	Float			step[2] = {1, 1};
	Float			u;
	Float			u2;
	Float			u3;
	Float			rate0;
	Float			rate1;
	Float			rate2;
	Float			rate3;
	NUS_MKEY_F		*key0;
	NUS_MKEY_F		*key1;
	NUS_MKEY_F		*key2;
	NUS_MKEY_F		*key3;
	Uint32			keyno;
	
	keyno	= _nuMotionSearchKey( key, sizeof(NUS_MKEY_F), nbkeys, (Uint32)frame );
	
	key0 = &key[ ( keyno + nbkeys - 1 ) % nbkeys ];
	key1 = &key[ keyno ];
	key2 = &key[ ( keyno + 1 ) % nbkeys ];
	key3 = &key[ ( keyno + 2 ) % nbkeys ];
	step[1] = key2->keyframe - key1->keyframe;
	u = ( frame - (Float) key1->keyframe )
		/ step[( Sint32 )key2->keyframe - ( Sint32 )key1->keyframe > 0];
	u2 = u * u;
	u3 = u2 * u;

	rate0 = 0.5f * ( - u3 + 2.f * u2 - u );
	rate1 = 1.5f * u3 - 2.5f * u2 + 1.f;
	rate2 = - 1.5f * u3 + 2.f * u2 + 0.5f * u;
	rate3 = 0.5f * ( u3 - u2 );

	dst[0] = rate0*key0->key[0] + rate1*key1->key[0] + rate2*key2->key[0] + rate3*key3->key[0];
	dst[1] = rate0*key0->key[1] + rate1*key1->key[1] + rate2*key2->key[1] + rate3*key3->key[1];
	dst[2] = rate0*key0->key[2] + rate1*key1->key[2] + rate2*key2->key[2] + rate3*key3->key[2];
}

/****************************************************************/
/*	関数名：nuMotionIntBezierF3									*/
/*	機  能：Float * 3 スプライン補間関数（Ｂｅｚｉｅｒ）		*/
/*	入  力：NUS_MKEY_F		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Float			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntBezierF3( const NUS_MKEY_F *key, Uint32 nbkeys, Float frame, Float *dst )
{
	Int				i;
	Float			tmpstep1;
	Float			tmpstep2;
	Float			step;
	Float			step3;
	Float			u;
	Float			u2;
	Float			s;
	Float			s2;
	Float			k1;
	Float			k2;
	Float			rate0;
	Float			rate1;
	Float			rate2;
	Float			rate3;
	NUS_MKEY_F		*key0;
	NUS_MKEY_F		*key1;
	NUS_MKEY_F		*key2;
	NUS_MKEY_F		*key3;
	Uint32			keyno;
	
	keyno	= _nuMotionSearchKey( key, sizeof(NUS_MKEY_F), nbkeys, (Uint32)frame );
	
	key0 = &key[ ( keyno + nbkeys - 1 ) % nbkeys ];
	key1 = &key[ keyno ];
	key2 = &key[ ( keyno + 1 ) % nbkeys ];
	key3 = &key[ ( keyno + 2 ) % nbkeys ];
	
	step = (Float)key2->keyframe - (Float)key1->keyframe;
	if ( step <= 0 ) {
		step = 1.f;
	}
	
	tmpstep1 = (Float)key3->keyframe - (Float)key2->keyframe;
	if ( tmpstep1 <= 0 ) {
		tmpstep1 = 1.f;
	}
	
	tmpstep2 = (Float)key1->keyframe - (Float)key0->keyframe;
	if ( tmpstep2 <= 0 ) {
		tmpstep2 = 1.f;
	}
	
	u = ( frame - (Float) key1->keyframe ) / step;
	step3 = step * NUD_ONEOVER3;
	
	k1 = step / ( step + tmpstep1 );
	k2 = step / ( step + tmpstep2 );
	
	s = 1.f - u;
	u2 = u * u;
	s2 = s * s;
	rate3 = u2 * u;
	rate0 = s2 * s;
	rate1 = 3.f * s2 * u;
	rate2 = 3.f * u2 * s;
	
	if ( keyno == nbkeys - 2 ) {
		for ( i = 0; i < 3; i++ ) {
			Float	len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			
			len		= key2->key[i] - key1->key[i];
			len2	= key1->key[i] - key0->key[i];
			
			t1		= ( 1.f - k2 )*len/step + k2*len2/tmpstep2;
			t2		= ( 1.f + k2 )*len/step - k2*len2/tmpstep2;
			
			tmpkey1	= key1->key[i] + t1*step3;
			tmpkey2	= key2->key[i] - t2*step3;
			
			dst[i]	= rate0*key1->key[i] + rate1*tmpkey1 + rate2*tmpkey2 + rate3*key2->key[i];
		}
	}
	else if ( keyno == 0 ) {
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			
			len		= key2->key[i] - key1->key[i];
			len1	= key3->key[i] - key2->key[i];
			
			t1		= ( 1.f + k1 )*len/step - k1*len1/tmpstep1;
			t2		= ( 1.f - k1 )*len/step + k1*len1/tmpstep1;
			
			tmpkey1	= key1->key[i] + t1*step3;
			tmpkey2	= key2->key[i] - t2*step3;
			
			dst[i]	= rate0*key1->key[i] + rate1*tmpkey1 + rate2*tmpkey2 + rate3*key2->key[i];
		}
	}
	else {
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			
			len		= key2->key[i] - key1->key[i];
			len2	= key1->key[i] - key0->key[i];
			len1	= key3->key[i] - key2->key[i];
			
			t1		= ( 1.f - k2 )*len/step + k2*len2/tmpstep2;
			t2		= ( 1.f - k1 )*len/step + k1*len1/tmpstep1;
			
			tmpkey1	= key1->key[i] + t1*step3;
			tmpkey2	= key2->key[i] - t2*step3;
			
			dst[i]	= rate0*key1->key[i] + rate1*tmpkey1 + rate2*tmpkey2 + rate3*key2->key[i];
		}
	}
}

#if	0
/****************************************************************/
/*	関数名：nuMotionIntOverhauserA3								*/
/*	機  能：Angle * 3 スプライン補間関数（Ｏｖｅｒｈａｕｓｅｒ）*/
/*	入  力：NUS_MKEY_A		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Angle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntOverhauserA3( const NUS_MKEY_A *key, Uint32 nbkeys, Float frame, Angle *dst )
{
	Float			step[2] = {1, 1};
	Float			u;
	Float			u2;
	Float			u3;
	Float			rate0;
	Float			rate1;
	Float			rate2;
	Float			rate3;
	NUS_MKEY_A		*key0;
	NUS_MKEY_A		*key1;
	NUS_MKEY_A		*key2;
	NUS_MKEY_A		*key3;
	Uint32			keyno;
	
	keyno	= _nuMotionSearchKey( key, sizeof(NUS_MKEY_A), nbkeys, (Uint32)frame );
	
	key0 = &key[ ( keyno + nbkeys - 1 ) % nbkeys ];
	key1 = &key[ keyno ];
	key2 = &key[ ( keyno + 1 ) % nbkeys ];
	key3 = &key[ ( keyno + 2 ) % nbkeys ];
	step[1] = key2->keyframe - key1->keyframe;
	u = ( frame - (Float) key1->keyframe )
		/ step[( Sint32 )key2->keyframe - ( Sint32 )key1->keyframe > 0];
	u2 = u * u;
	u3 = u2 * u;

	rate0 = 0.5f * ( - u3 + 2.f * u2 - u );
	rate1 = 1.5f * u3 - 2.5f * u2 + 1.f;
	rate2 = - 1.5f * u3 + 2.f * u2 + 0.5f * u;
	rate3 = 0.5f * ( u3 - u2 );

	dst[0] = (Angle)( rate0*key0->key[0] + rate1*key1->key[0] + rate2*key2->key[0] + rate3*key3->key[0] );
	dst[1] = (Angle)( rate0*key0->key[1] + rate1*key1->key[1] + rate2*key2->key[1] + rate3*key3->key[1] );
	dst[2] = (Angle)( rate0*key0->key[2] + rate1*key1->key[2] + rate2*key2->key[2] + rate3*key3->key[2] );
}

/****************************************************************/
/*	関数名：nuMotionIntBezierA3									*/
/*	機  能：Angle * 3 スプライン補間関数（Ｂｅｚｉｅｒ）		*/
/*	入  力：NUS_MKEY_A		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Angle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntBezierA3( const NUS_MKEY_A *key, Uint32 nbkeys, Float frame, Angle *dst )
{
	Int				i;
	Float			tmpstep1;
	Float			tmpstep2;
	Float			step;
	Float			step3;
	Float			u;
	Float			u2;
	Float			s;
	Float			s2;
	Float			k1;
	Float			k2;
	Float			rate0;
	Float			rate1;
	Float			rate2;
	Float			rate3;
	NUS_MKEY_A		*key0;
	NUS_MKEY_A		*key1;
	NUS_MKEY_A		*key2;
	NUS_MKEY_A		*key3;
	Uint32			keyno;
	
	keyno	= _nuMotionSearchKey( key, sizeof(NUS_MKEY_A), nbkeys, (Uint32)frame );
	
	key0 = &key[ ( keyno + nbkeys - 1 ) % nbkeys ];
	key1 = &key[ keyno ];
	key2 = &key[ ( keyno + 1 ) % nbkeys ];
	key3 = &key[ ( keyno + 2 ) % nbkeys ];
	
	step = (Float)key2->keyframe - (Float)key1->keyframe;
	if ( step <= 0 ) {
		step = 1.f;
	}
	
	tmpstep1 = (Float)key3->keyframe - (Float)key2->keyframe;
	if ( tmpstep1 <= 0 ) {
		tmpstep1 = 1.f;
	}
	
	tmpstep2 = (Float)key1->keyframe - (Float)key0->keyframe;
	if ( tmpstep2 <= 0 ) {
		tmpstep2 = 1.f;
	}
	
	u = ( frame - (Float) key1->keyframe ) / step;
	step3 = step * NUD_ONEOVER3;
	
	k1 = step / ( step + tmpstep1 );
	k2 = step / ( step + tmpstep2 );
	
	s = 1.f - u;
	u2 = u * u;
	s2 = s * s;
	rate3 = u2 * u;
	rate0 = s2 * s;
	rate1 = 3.f * s2 * u;
	rate2 = 3.f * u2 * s;
	
	if ( keyno == nbkeys - 2 ) {
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			
			len		= key2->key[i] - key1->key[i];
			len2	= key1->key[i] - key0->key[i];
			
			t1		= ( 1.f - k2 )*len/step + k2*len2/tmpstep2;
			t2		= ( 1.f + k2 )*len/step - k2*len2/tmpstep2;
			
			tmpkey1	= key1->key[i] + t1*step3;
			tmpkey2	= key2->key[i] - t2*step3;
			
			dst[i]	= (Angle)( rate0*key1->key[i] + rate1*tmpkey1 + rate2*tmpkey2 + rate3*key2->key[i] );
		}
	}
	else if ( keyno==0 ) {
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			
			len		= key2->key[i] - key1->key[i];
			len1	= key3->key[i] - key2->key[i];
			
			t1		= ( 1.f + k1 )*len/step - k1*len1/tmpstep1;
			t2		= ( 1.f - k1 )*len/step + k1*len1/tmpstep1;
			
			tmpkey1	= key1->key[i] + t1*step3;
			tmpkey2	= key2->key[i] - t2*step3;
			
			dst[i]	= (Angle)( rate0*key1->key[i] + rate1*tmpkey1 + rate2*tmpkey2 + rate3*key2->key[i] );
		}
	}
	else {
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			
			len		= key2->key[i] - key1->key[i];
			len2	= key1->key[i] - key0->key[i];
			len1	= key3->key[i] - key2->key[i];
			
			t1		= ( 1.f - k2 )*len/step + k2*len2/tmpstep2;
			t2		= ( 1.f - k1 )*len/step + k1*len1/tmpstep1;
			
			tmpkey1	= key1->key[i] + t1*step3;
			tmpkey2	= key2->key[i] - t2*step3;
			
			dst[i]	= (Angle)( rate0*key1->key[i] + rate1*tmpkey1 + rate2*tmpkey2 + rate3*key2->key[i] );
		}
	}
}


/****************************************************************/
/*	関数名：nuMotionIntBezierA3Old								*/
/*	機  能：Angle * 3 スプライン補間関数（Ｂｅｚｉｅｒ）		*/
/*	入  力：NUS_MKEY_A		*key	:キーデータ					*/
/*		　：Uint32			nbkeys	:キーの個数					*/
/*		　：Float			frame	:フレーム番号				*/
/*		　：Angle			*dst	:結果						*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntBezierA3Old( const NUS_MKEY_A *key, Uint32 nbkeys, Float frame, Angle *dst )
{
	Int				i;
	Float			tmpstep1;
	Float			tmpstep2;
	Float			step;
	Float			step3;
	Float			u;
	Float			u2;
	Float			s;
	Float			s2;
	Float			k1;
	Float			k2;
	Float			rate0;
	Float			rate1;
	Float			rate2;
	Float			rate3;
	NUS_MKEY_A		*key0;
	NUS_MKEY_A		*key1;
	NUS_MKEY_A		*key2;
	NUS_MKEY_A		*key3;
	Uint32			keyno;
	
	keyno	= _nuMotionSearchKey( key, sizeof(NUS_MKEY_A), nbkeys, (Uint32)frame );
	
	key0 = &key[ ( keyno + nbkeys - 1 ) % nbkeys ];
	key1 = &key[ keyno ];
	key2 = &key[ ( keyno + 1 ) % nbkeys ];
	key3 = &key[ ( keyno + 2 ) % nbkeys ];
	
	step = (Float)key2->keyframe - (Float)key1->keyframe;
	if ( step <= 0 ) {
		step = 1.f;
	}
	
	tmpstep1 = (Float)key3->keyframe - (Float)key2->keyframe;
	if ( tmpstep1 <= 0 ) {
		tmpstep1 = 1.f;
	}
	
	tmpstep2 = (Float)key1->keyframe - (Float)key0->keyframe;
	if ( tmpstep2 <= 0 ) {
		tmpstep2 = 1.f;
	}
	
	u = ( frame - (Float) key1->keyframe ) / step;
	step3 = step * NUD_ONEOVER3;
	
	k1 = step / ( step + tmpstep1 );
	k2 = step / ( step + tmpstep2 );
	
	s = 1.f - u;
	u2 = u * u;
	s2 = s * s;
	rate3 = u2 * u;
	rate0 = s2 * s;
	rate1 = 3.f * s2 * u;
	rate2 = 3.f * u2 * s;
	
	if ( keyno==nbkeys-2 ) {		
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			Float	p1, p2;
			
			p1 = key1->key[i];
			p2 = key2->key[i];
			
			len = p2 - p1;
			len2 = key1->key[i] - key0->key[i];
			
			if ( len > 0x8000 ) {
				len -= 0x10000;
			}
			else if ( len <= -0x8000 ) {
				len += 0x10000;
			}
			p2 = p1 + len;
			
			if ( len2 > 0x8000 ) {
				len2 -= 0x10000;
			}
			else if ( len2 <= -0x8000 ) {
				len2 += 0x10000;
			}
			
			t1 = ( 1.f - k2 )*len/step + k2*len2/tmpstep2;
			t2 = ( 1.f + k2 )*len/step - k2*len2/tmpstep2;
			
			tmpkey1 = p1 + t1*step3;
			tmpkey2 = p2 - t2*step3;
			
			dst[i] = (Angle)( rate0*p1 + rate1*tmpkey1 + rate2*tmpkey2 + rate3*p2 );
		}
	}
	else if ( keyno==0 ) {
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			Float	p1, p2;
			
			p1 = key1->key[i];
			p2 = key2->key[i];
			len = p2 - p1;
			len1 = key3->key[i] - key2->key[i];
			
			if ( len > 0x8000 ) {
				len -= 0x10000;
			}
			else if ( len <= -0x8000 ) {
				len += 0x10000;
			}
			p2 = p1 + len;
			
			if ( len1 > 0x8000 ) {
				len1 -= 0x10000;
			}
			else if ( len1 <= -0x8000 ) {
				len1 += 0x10000;
			}
			
			t1 = ( 1.f + k1 )*len/step - k1*len1/tmpstep1;
			t2 = ( 1.f - k1 )*len/step + k1*len1/tmpstep1;
			
			tmpkey1 = p1 + t1*step3;
			tmpkey2 = p2 - t2*step3;
			
			dst[i] = (Angle)( rate0*p1 + rate1*tmpkey1 + rate2*tmpkey2 + rate3*p2 );
		}
	}
	else {
		for ( i = 0; i < 3; i++ ) {
			Float	len1, len2, len;
			Float	tmpkey1, tmpkey2;
			Float	t1, t2;
			Float	p1, p2;
			
			p1		= key1->key[i];
			p2		= key2->key[i];
			len		= p2 - p1;
			len2	= key1->key[i] - key0->key[i];
			len1	= key3->key[i] - key2->key[i];
			
			if ( len > 0x8000 ) {
				len -= 0x10000;
			}
			else if ( len <= -0x8000 ) {
				len += 0x10000;
			}
			p2 = p1 + len;
			
			if ( len2 > 0x8000 ) {
				len2 -= 0x10000;
			}
			else if ( len2 <= -0x8000 ) {
				len2 += 0x10000;
			}
			
			if ( len1 > 0x8000 ) {
				len1 -= 0x10000;
			}
			else if ( len1 <= -0x8000 ) {
				len1 += 0x10000;
			}
			
			t1 = ( 1.f - k2 )*len/step + k2*len2/tmpstep2;
			t2 = ( 1.f - k1 )*len/step + k1*len1/tmpstep1;
			
			tmpkey1 = p1 + t1*step3;
			tmpkey2 = p2 - t2*step3;
			
			dst[i] = (Angle)( rate0*p1 + rate1*tmpkey1 + rate2*tmpkey2 + rate3*p2 );
		}
	}
}
#endif

#if 0
/****************************************************************/
/*	関数名：nuMotionIntHermiteF3								*/
/*	機  能：Float * 3 スプライン補間関数（Ｈｅｒｍｉｔｅ）		*/
/*	入  力：Float		*src	:キー番号						*/
/*		　：Float		*dst	:結果							*/
/*		　：Float		u		:フレーム番号					*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntHermiteF3( const Float *src, Float *dst, Float u )
{
	Float		u2;
	Float		u3;
	Float		rate0;
	Float		rate1;
	Float		rate2;
	Float		rate3;

	u2 = u * u;
	u3 = u2 * u;

	rate0 = 2.f * u3 - 3.f * u2 + 1.f;
	rate1 = - 2.f * u3 + 3.f * u2;
	rate2 = u3 - 2.f * u2 + u;
	rate3 = u3 - u2;

	dst[0] = rate0*src[IP00] + rate1*src[IP10] + rate2*src[IP20] + rate3*src[IP30];
	dst[1] = rate0*src[IP01] + rate1*src[IP11] + rate2*src[IP21] + rate3*src[IP31];
	dst[2] = rate0*src[IP02] + rate1*src[IP12] + rate2*src[IP22] + rate3*src[IP32];
}

/****************************************************************/
/*	関数名：nuMotionIntHermiteA3								*/
/*	機  能：Angle * 3 スプライン補間関数（Ｈｅｒｍｉｔｅ）		*/
/*	入  力：Angle		*src	:キー番号						*/
/*		　：Angle		*dst	:結果							*/
/*		　：Float		u		:フレーム番号					*/
/*	出  力：なし												*/
/*	戻り値：なし												*/
/*	概　要：													*/
/*	備　考：													*/
/****************************************************************/
void nuMotionIntHermiteA3( const Angle *src, Angle *dst, Float u )
{
	Float		u2;
	Float		u3;
	Float		rate0;
	Float		rate1;
	Float		rate2;
	Float		rate3;

	u2 = u * u;
	u3 = u2 * u;

	rate0 = 2.f * u3 - 3.f * u2 + 1.f;
	rate1 = - 2.f * u3 + 3.f * u2;
	rate2 = u3 - 2.f * u2 + u;
	rate3 = u3 - u2;

	dst[0] = (Angle)(rate0*src[IP00] + rate1*src[IP10] + rate2*src[IP20] + rate3*src[IP30]);
	dst[1] = (Angle)(rate0*src[IP01] + rate1*src[IP11] + rate2*src[IP21] + rate3*src[IP31]);
	dst[2] = (Angle)(rate0*src[IP02] + rate1*src[IP12] + rate2*src[IP22] + rate3*src[IP32]);
}
#endif
