//===========================================================================//
// File:	AnimIterator.cpp                                                 
// Project: MechWarrior 4
// Contents: 
//			
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 07/01/98  JSE  Initial coding, 
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive, Inc.
// All Rights reserved worldwide
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL
//===========================================================================//


#include <MW4\MW4AnimationSystem.hpp>


//#############################################################################
//#######################       AnimIterator          #########################
//#############################################################################
using namespace MW4Animation;


AnimIterator::AnimIterator(AnimInstance *animation_instance):
	Plug(DefaultData)
{
	Check_Object(animation_instance);	
	animationInstance = animation_instance;

	Check_Pointer(animation_instance->animData);
	animationData = animation_instance->animData;


	currentTime = animationData->animHeaderBlock->startTime;


	gos_PushCurrentHeap(g_AnimIteratorHeap);

	nextFrame = new BYTE[animationData->GetChannelCount()];
	Register_Pointer(nextFrame);

	gos_PopCurrentHeap();


	// we set all of them to invalid.
	// you must reset the system to the start/end or 
	// set it to a position.

	skipChannels = false;

	velocityScale = 1.0f;
	blendValue = 1.0f;

	for (int i = 0; i < animationData->GetChannelCount(); ++i)
	{
		nextFrame[i] = MaxKeyFrame;
	}


}	

//
//#############################################################################
//#############################################################################
//

AnimIterator::~AnimIterator()
{
	Unregister_Pointer(nextFrame);
	delete[] nextFrame;
}

//
//#############################################################################
//#############################################################################
//


int 
	AnimIterator::ToAbsoluteChannel(
		BYTE joint_number, 
		BYTE channel_number
	)
{
	Verify(joint_number < animationData->GetJointCount());
	Verify(channel_number < animationData->animJointBlock[joint_number].channelsUsed);

	return animationData->animJointBlock[joint_number].firstChannel + channel_number;
}

//
//#############################################################################
//#############################################################################
//

void AnimIterator::FromAbsoluteChannel(
		int absolute_channel_number, 
		BYTE& joint_number, 
		BYTE& channel_number
	)
{

	Verify(absolute_channel_number < animationData->GetChannelCount());

	joint_number = animationData->animChannelBlock[absolute_channel_number].jointNumber;

	Verify(joint_number < animationData->GetJointCount());

	channel_number = 
		(BYTE)
			(absolute_channel_number - 
			animationData->animJointBlock[joint_number].firstChannel);

	Verify(channel_number < animationData->animJointBlock[joint_number].channelsUsed);

	return; 
}


//
//#############################################################################
//#############################################################################
//

//  -1 means that there are no more keyframes in that direction
int 
	AnimIterator::GetForwardFrameIndex(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

#ifdef _ARMOR
	if (nextFrame[absolute_channel_number] != MaxKeyFrame)
	{
		Verify(nextFrame[absolute_channel_number] < animationData->animChannelBlock[absolute_channel_number].keyframeCount);
		Verify(nextFrame[absolute_channel_number] >= 0);
	}
#endif
	// this will be set when there are no "next" keyframes.
	// once that happens, we don't animate this joint anymore.
	return nextFrame[absolute_channel_number];
}

//
//#############################################################################
//#############################################################################
//

int 
	AnimIterator::GetReverseFrameIndex(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

#ifdef _ARMOR
	if (nextFrame[absolute_channel_number] != MaxKeyFrame)
	{
		Verify(nextFrame[absolute_channel_number] >= 0);
	}
#endif


	if( nextFrame[absolute_channel_number] != 0)
	{
		Verify(nextFrame[absolute_channel_number] - 1 < 
			animationData->animChannelBlock[absolute_channel_number].keyframeCount);
		

		return nextFrame[absolute_channel_number] - 1;
	}
	
	return MaxKeyFrame;
}

//
//#############################################################################
//#############################################################################
//


BaseKeyframe * 
	AnimIterator::GetForwardKeyFrame(int absolute_channel_number)
{
	if (nextFrame[absolute_channel_number] == MaxKeyFrame)
	{
		return NULL;
	}

	Verify(absolute_channel_number < animationData->GetChannelCount());
	
#ifdef _ARMOR
	if (nextFrame[absolute_channel_number] != MaxKeyFrame)
	{	
		Verify(nextFrame[absolute_channel_number] >= 0);
		Verify(nextFrame[absolute_channel_number] < 
			animationData->animChannelBlock[absolute_channel_number].keyframeCount);
	}
#endif


	size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData + 
			(animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey * 
				nextFrame[absolute_channel_number]);


	return 
		(BaseKeyframe*)
			((BYTE*)animationData->animKeyBlock + offset);

}

//
//#############################################################################
//#############################################################################
//


BaseKeyframe * 
	AnimIterator::GetReverseKeyFrame(int absolute_channel_number)
{


	if (nextFrame[absolute_channel_number] == MaxKeyFrame)
	{
		// if there is no next that means it is the "last" keyframe
		size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData +
				((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) 
				* animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey);

		return 
			(BaseKeyframe*)
				((BYTE*)animationData->animKeyBlock + offset);
	}


	Verify(absolute_channel_number < animationData->GetChannelCount());
	
	#ifdef _ARMOR
	if (nextFrame[absolute_channel_number] != MaxKeyFrame)
	{
		Verify(nextFrame[absolute_channel_number] >= 0);
	}
	#endif

	if( nextFrame[absolute_channel_number] != 0)
	{
		Verify(nextFrame[absolute_channel_number] < 
			animationData->animChannelBlock[absolute_channel_number].keyframeCount);

		size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData + 
			(animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey * 
				(nextFrame[absolute_channel_number] - 1));

		return 
			(BaseKeyframe*)
				((BYTE*)animationData->animKeyBlock + offset);
	

	}
	
	return NULL;

}

//
//#############################################################################
//#############################################################################
//


BaseKeyframe *  
	AnimIterator::GetFirstKeyFrame(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}
  
	return 
		(BaseKeyframe*)
			((BYTE*)animationData->animKeyBlock + 
				animationData->animChannelBlock[absolute_channel_number].offsetToKeyData);

}

//
//#############################################################################
//#############################################################################
//


BaseKeyframe *  
	AnimIterator::GetLastKeyFrame(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());
	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}


	size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData +
				((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) 
				* animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey);

	return 
		(BaseKeyframe*)
			((BYTE*)animationData->animKeyBlock + offset);

}


//
//#############################################################################
//#############################################################################
//


BaseKeyframe *  
	AnimIterator::GetStartKeyFrame(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}


	BaseKeyframeTime* key = NULL;
	BaseKeyframe* ret_key = NULL;


	for (int i = 0; i < animationData->animChannelBlock[absolute_channel_number].keyframeCount; ++i)
	{
		key = GetKeyFrameTime(absolute_channel_number, i);

		if (key->timeOfFrame > animationData->animHeaderBlock->startTime)
		{
			
			ret_key = GetKeyFrame(absolute_channel_number, i);
			break;
		}

	}		


	return ret_key;
		
}

//
//#############################################################################
//#############################################################################
//


BaseKeyframe *  
	AnimIterator::GetStopKeyFrame(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());
	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}

	BaseKeyframeTime* key = NULL;
	BaseKeyframe* ret_key = NULL;

	for (int i = animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1;i >= 0; --i)
	{
		key = GetKeyFrameTime(absolute_channel_number, i);

		
		if (key->timeOfFrame < animationData->animHeaderBlock->endTime)
		{
			ret_key = GetKeyFrame(absolute_channel_number, i);
			break;
		}

	}


	return ret_key;
}

//
//#############################################################################
//#############################################################################
//


BaseKeyframe *  
	AnimIterator::GetKeyFrame(int absolute_channel_number, int index)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

	Verify( index < animationData->animChannelBlock[absolute_channel_number].keyframeCount);
	Verify( index >= 0);

	size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData +
			(index * animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey);

		return 
		(BaseKeyframe*)
			((BYTE*)animationData->animKeyBlock + offset);
			
}


//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime * 
	AnimIterator::GetForwardKeyFrameTime(int absolute_channel_number)
{
	if (nextFrame[absolute_channel_number] == MaxKeyFrame)
	{
		return NULL;
	}

	Verify(absolute_channel_number < animationData->GetChannelCount());

	
	Verify(nextFrame[absolute_channel_number] >= 0);
	Verify(nextFrame[absolute_channel_number] < 
		animationData->animChannelBlock[absolute_channel_number].keyframeCount);



	size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + 
			(4 * nextFrame[absolute_channel_number]);


	return 
		(BaseKeyframeTime*)
			((BYTE*)animationData->animKeyTimeBlock + offset);

}

//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime * 
	AnimIterator::GetReverseKeyFrameTime(int absolute_channel_number)
{


	if (nextFrame[absolute_channel_number] == MaxKeyFrame)
	{
		// if there is no next that means it is the "last" keyframe
		size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData +
				((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) * 4);

		return 
			(BaseKeyframeTime*)
				((BYTE*)animationData->animKeyTimeBlock + offset);
	}


	Verify(absolute_channel_number < animationData->GetChannelCount());
	Verify(nextFrame[absolute_channel_number] >= 0);

	if( nextFrame[absolute_channel_number] != 0)
	{
		Verify(nextFrame[absolute_channel_number] < 
			animationData->animChannelBlock[absolute_channel_number].keyframeCount);

		size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + 
			(4 * (nextFrame[absolute_channel_number] - 1));

		return 
			(BaseKeyframeTime*)
				((BYTE*)animationData->animKeyTimeBlock + offset);
	

	}
	
	return NULL;

}

//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime *  
	AnimIterator::GetFirstKeyFrameTime(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}
  
	return 
		(BaseKeyframeTime*)
			((BYTE*)animationData->animKeyTimeBlock + 
				animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData);

}

//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime *  
	AnimIterator::GetLastKeyFrameTime(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());
	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}


	size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData +
				((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) * 4);

	return 
		(BaseKeyframeTime*)
			((BYTE*)animationData->animKeyTimeBlock + offset);

}


//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime *  
	AnimIterator::GetStartKeyFrameTime(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}


	BaseKeyframeTime* key = NULL;

	for (int i = 0; i < animationData->animChannelBlock[absolute_channel_number].keyframeCount; ++i)
	{
		key = GetKeyFrameTime(absolute_channel_number, i);

		if (key->timeOfFrame > animationData->animHeaderBlock->startTime)
		{
			
			key = GetKeyFrameTime(absolute_channel_number, i);
		}

	}		


	return key;
		
}

//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime *  
	AnimIterator::GetStopKeyFrameTime(int absolute_channel_number)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());
	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0)
	{
		return NULL;
	}

	BaseKeyframeTime* key = NULL;
	
	for (int i = animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1;i >= 0; --i)
	{
		key = GetKeyFrameTime(absolute_channel_number, i);

		
		if (key->timeOfFrame < animationData->animHeaderBlock->endTime)
		{
			key = GetKeyFrameTime(absolute_channel_number, i);
		}

	}


	return key;
}

//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime *  
	AnimIterator::GetKeyFrameTime(int absolute_channel_number, int index)
{
	Verify(absolute_channel_number < animationData->GetChannelCount());

	Verify( index < animationData->animChannelBlock[absolute_channel_number].keyframeCount);
	Verify( index >= 0);

	size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + (index * 4);

		return 
		(BaseKeyframeTime*)
			((BYTE*)animationData->animKeyTimeBlock + offset);
			
}
//
//#############################################################################
//#############################################################################
//

void 
	AnimIterator::ResetStart()
{
	

	currentTime = animationData->animHeaderBlock->startTime;
	for (int i = 0; i < animationData->GetChannelCount(); ++i)
	{
		nextFrame[i] = 0;
	}
}

//
//#############################################################################
//#############################################################################
//

void 
	AnimIterator::ResetEnd()
{


	currentTime = animationData->animHeaderBlock->endTime;
	for (int i = 0; i < animationData->GetChannelCount(); ++i)
	{
		nextFrame[i] = (BYTE)(animationData->animChannelBlock[i].keyframeCount - 1);
	}
}

//
//#############################################################################
//#############################################################################
//

Stuff::Scalar 
	AnimIterator::GetCarryOverTime()
{
	if (currentTime >= animationData->animHeaderBlock->endTime)
	{
		return GetCarryOverTimeForward();
	}
	else if (currentTime <= animationData->animHeaderBlock->startTime)
	{
		return GetCarryOverTimeReverse();
	}
	else
	{
		//Abort_Program("AnimIterator::GetCarryOverTime() - Should never reach here");
	}

	return 0.0f;
}

//
//#############################################################################
//#############################################################################
//

int  
	AnimIterator::GetCarryOverFrame(int frames_per_second)
{
	return (int)(GetCarryOverTime() * frames_per_second);
}

//
//#############################################################################
//#############################################################################
//

Stuff::Scalar 
	AnimIterator::GetCarryOverPosition()
{
	Verify((animationData->animHeaderBlock->endTime -
		 animationData->animHeaderBlock->startTime) != 0.0f);


	Stuff::Scalar percent = 
		GetCarryOverTime() / 
			(animationData->animHeaderBlock->endTime -
			 animationData->animHeaderBlock->startTime);


	Verify(percent > 0.0f);
	Verify(percent <= 1.0f);


	return percent;
}

//
//#############################################################################
//#############################################################################
//

Stuff::Scalar 
	AnimIterator::GetCarryOverTimeForward()
{
	Verify((currentTime - animationData->animHeaderBlock->endTime) >= 0.0f);

	return currentTime - animationData->animHeaderBlock->endTime;
}

//
//#############################################################################
//#############################################################################
//

int  
	AnimIterator::GetCarryOverFrameForward(int frames_per_second)
{
	return (int)(GetCarryOverTimeForward() * frames_per_second);
}

//
//#############################################################################
//#############################################################################
//

Stuff::Scalar 
	AnimIterator::GetCarryOverPositionForward()
{
	Verify((animationData->animHeaderBlock->endTime -
		 animationData->animHeaderBlock->startTime) != 0.0f);


	Stuff::Scalar percent = 
		GetCarryOverTimeForward() / 
			(animationData->animHeaderBlock->endTime -
			 animationData->animHeaderBlock->startTime);


	Verify(percent > 0.0f);
	Verify(percent <= 1.0f);


	return percent;
}

//
//#############################################################################
//#############################################################################
//

Stuff::Scalar  
	AnimIterator::GetCarryOverTimeReverse()
{
	Verify((currentTime - animationData->animHeaderBlock->startTime) <= 0.0f);

	return currentTime - animationData->animHeaderBlock->startTime;
}

//
//#############################################################################
//#############################################################################
//

int   
	AnimIterator::GetCarryOverFrameReverse(int frames_per_second)
{
	return (int)(GetCarryOverTimeReverse() * frames_per_second);
}

//
//#############################################################################
//#############################################################################
//

Stuff::Scalar  
	AnimIterator::GetCarryOverPositionReverse()
{
	Verify((animationData->animHeaderBlock->endTime -
		 animationData->animHeaderBlock->startTime) != 0.0f);


	Stuff::Scalar percent = 
		GetCarryOverTimeReverse() / 
			(animationData->animHeaderBlock->endTime -
			 animationData->animHeaderBlock->startTime);


	Verify(percent > 0.0f);
	Verify(percent <= 1.0f);


	return percent;
}

//
//#############################################################################
//#############################################################################
//

void 
	AnimIterator::SetTime(Stuff::Scalar time)
{

	//SPEW(("jerryeds", "SetTime %f", time));

	// Calling bullshit on expensive calls

	if (time <= 0.0f)
	{
		ResetStart();
		return;
	}
	else if (time >= animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime)
	{
		ResetEnd();
		return;
	}

	// We have to be "IN" the animation, on out of range
	// you CAN NOT ANIMATE out of range keyframes!  They
	// are mearly helper keys.

	// time 0 is startTime, for simplicity
	time += animationData->animHeaderBlock->startTime;
	// this allows for animations that start somewhere other than 0

	Verify(time >= animationData->animHeaderBlock->startTime);
	Verify(time <= animationData->animHeaderBlock->endTime);

	currentTime = time;



	// lets get busy....

	// binary "divide-and-conquer" search from Sedgewick - "Algorithms in C++" pg. 198 
	for (int channel_count = 0; channel_count < animationData->GetChannelCount(); ++channel_count)
	{
		
		if (skipChannels)
		{
			if (! (animationData->animChannelBlock[channel_count].channelType != MW4Animation::ChannelAnimData::VelocityChannelType || 
				 animationData->animChannelBlock[channel_count].channelType != MW4Animation::ChannelAnimData::AngularVelocityChannelType ))
			{
				continue;
			}

		}

		nextFrame[channel_count] = MaxKeyFrame;

		if (animationData->animChannelBlock[channel_count].keyframeCount > 0 && 
			animationInstance->jointToIndex[animationData->animChannelBlock[channel_count].jointNumber]!=MaxKeyFrame)
		{
			// pretty sure this will skip 0
			int left = 1;
			int right = animationData->animChannelBlock[channel_count].keyframeCount-1;
			int x;

			while(right >= left)
			{
				x = (left+right)/2;

				if (x == animationData->animChannelBlock[channel_count].keyframeCount)
					break;

				BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, x);

				
				// the "next" keyframe is always greater, the last keyframe
				// can be the same.  We are always "going forward".
				// lowest keyframe we get is 1.
				BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, x-1);
				if ((last_keyframe->timeOfFrame <= time) && (keyframe->timeOfFrame > time))
				{
					// this is the keyframe, set it up and leave
					nextFrame[channel_count] = (BYTE)x;
					break;
				}
				else if (time < keyframe->timeOfFrame)
				{
					right = x-1;
				}
				else
				{
					left = x+1;
				}		
			}

			// we didn't find one...
			if ( nextFrame[channel_count] == MaxKeyFrame)
			{
				BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, 0);
				BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, animationData->animChannelBlock[channel_count].keyframeCount-1);
				if ((keyframe->timeOfFrame) > time)
				{
					// this is the keyframe, set it up and leave
					nextFrame[channel_count] = 0;
				}
				else if (last_keyframe->timeOfFrame <= time)
				{
					nextFrame[channel_count] = MaxKeyFrame;
				}
				else
				{
					//animationData->animChannelBlock[absolute_channel_number].keyframeCount
					Verify(0);
				}
			}
			

#if defined(MW4_ANIMATION_DEBUG)
			if ( nextFrame[channel_count] != MaxKeyFrame)
			{

				if (nextFrame[channel_count] >= 1)
				{
					BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, nextFrame[channel_count]);
					BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, nextFrame[channel_count]-1);
					Verify(keyframe->timeOfFrame > time);
					Verify(last_keyframe->timeOfFrame <= time);
				}
				else
				{
					BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, nextFrame[channel_count]);
					Verify(keyframe->timeOfFrame > time);
				}
			}
			else
			{
				BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, animationData->animChannelBlock[channel_count].keyframeCount-1);
				Verify(last_keyframe->timeOfFrame <= time);
			}
#endif

		

		}
	}	
}




//
//#############################################################################
//#############################################################################
//

bool 
	AnimIterator::MoveTime(Stuff::Scalar time_slice)
{

	if (time_slice > 0.0f)
	{
		return IncrementTime(time_slice);
	}
	else if (time_slice < 0.0f)
	{
		return DecrementTime(time_slice);
	}
	else
	{
		// no movement
		return false;
	}
}



//
//#############################################################################
//#############################################################################
//

bool 
	AnimIterator::IncrementTime(Stuff::Scalar time_slice)
{
	Min_Clamp(time_slice, 0.0f);

	Verify(time_slice >= 0.0f);
	currentTime += time_slice;

	Verify(currentTime >= animationData->animHeaderBlock->startTime);
	//Verify(currentTime <= animationData->animHeaderBlock->endTime);

	if (currentTime >= animationData->animHeaderBlock->endTime)
	{
		//DEBUG_STREAM << "******ct:" << currentTime << " ts:" << time_slice << " et:"  << animationData->animHeaderBlock->endTime << endl;
		// set last positions we are over 
		return true;
	}

	for (int i = 0; i < animationData->GetChannelCount(); ++i)
	{
		if (skipChannels)
		{
			if (! (animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::VelocityChannelType || 
				 animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::AngularVelocityChannelType ))
			{
				continue;
			}

		}

		if (animationData->animChannelBlock[i].keyframeCount > 0 &&
			animationInstance->jointToIndex[animationData->animChannelBlock[i].jointNumber]!=MaxKeyFrame)
		{
			// it is already at the end so go on
			if (nextFrame[i] == MaxKeyFrame)
			{
				continue;
			}

			int frame_count = nextFrame[i];
			BaseKeyframeTime *keyframe = GetKeyFrameTime( i, frame_count);
			while(keyframe != NULL)
			{
				
				if(keyframe->timeOfFrame > currentTime)
				{
					//DEBUG_STREAM << "K: " << keyframe->timeOfFrame << endl;
					// this key frame is next'
					nextFrame[i] = (BYTE)frame_count;
					break;
				}

				++frame_count;
				
				if (frame_count < animationData->animChannelBlock[i].keyframeCount)
				{
					keyframe = GetKeyFrameTime( i, frame_count);
				}
				else
				{
					nextFrame[i] = MaxKeyFrame;
					break;
				}
			}
		}

		if (nextFrame[i] != MaxKeyFrame)
		{
			Verify(nextFrame[i] < animationData->animChannelBlock[i].keyframeCount);
		}
	}
	return false;
}

//
//#############################################################################
//#############################################################################
//

bool 
	AnimIterator::DecrementTime(Stuff::Scalar time_slice)
{

	//
	// Reverse is kind of weird. 
	// The way keyframes work is by having a "next" keyframe.
	// so if you are at the begging of the animation the next keyframe is the first.
	// if you are at the end the next keyframe is -1.  This means that no more animation
	// data remains for the key.  
	//

	// this is what the interpolation engine does with the indexes...

	// frameindex -1 = no animation
	// frameindex  0 = current position to first frame
	// frameindex  x = x-1 to x interpolation

	// For reverse this is a little diffrent.
	// The interpolation engine detect backwards by the negative time motion as does the move time commands.
	// The diffrence is -1 does not really apply to the backwards lerping.
	//
	// if time is negative
	// frameindex -1 = INVALID
	// frameindex 0 = no animation
	// frameindex x =  x to x-1 interpolation
	// frameindex lastframe = current positoin to last frame


	//Verify(time_slice < 0);
	currentTime += time_slice;

	if (currentTime <= animationData->animHeaderBlock->startTime)
	{

		// set last positions we are over 
		return true;
	}

	Verify(currentTime >= animationData->animHeaderBlock->startTime);
	Verify(currentTime <= animationData->animHeaderBlock->endTime);

	for (int i = 0; i < animationData->GetChannelCount(); ++i)
	{
		if (skipChannels)
		{
			if (! (animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::VelocityChannelType || 
				 animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::AngularVelocityChannelType ))
			{
				continue;
			}

		}

		if (animationData->animChannelBlock[i].keyframeCount > 0 &&
			animationInstance->jointToIndex[animationData->animChannelBlock[i].jointNumber]!=MaxKeyFrame)
		{
			// it is already at the end so go on
			if (nextFrame[i] == MaxKeyFrame)
			{
				continue;
			}

			int frame_count = nextFrame[i];
			BaseKeyframeTime *keyframe = GetKeyFrameTime( i, frame_count);
			while(keyframe != NULL)
			{
				
				if(keyframe->timeOfFrame < currentTime)
				{
					// this key frame is next'
					nextFrame[i] = (BYTE)frame_count;
					break;
				}

				--frame_count;
				
				if (frame_count >= 0)
				{
					keyframe = GetKeyFrameTime( i, frame_count);
				}
				else
				{
					nextFrame[i] = 0;
					break;
				}
			}
		}
	}

	return false;
}



//
//#############################################################################
//#############################################################################
//

BaseKeyframe * 
	AnimIterator::GetKeyFrameAtTime(int absolute_channel_number, Stuff::Scalar time)
{
	// We have to be "IN" the animation, on out of range
	// you CAN NOT ANIMATE out of range keyframes!  They
	// are mearly helper keys.

	// time 0 is startTime, for simplicity
	time += animationData->animHeaderBlock->startTime;
	// this allows for animations that start somewhere other than 0

	Verify(time >= animationData->animHeaderBlock->startTime);
	Verify(time <= animationData->animHeaderBlock->endTime);

	currentTime = time;

	// lets get busy....

	// binary "divide-and-conquer" search from Sedgewick - "Algorithms in C++" pg. 198 
	
	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount > 0)
	{
		// pretty sure this will skip 0
		int left = 1;
		int right = animationData->animChannelBlock[absolute_channel_number].keyframeCount;
		int x;

		while(right >= left)
		{
			x = (left+right)/2;

			BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, x);

			
			// the "next" keyframe is always greater, the last keyframe
			// can be the same.  We are always "going forward".
			// lowest keyframe we get is 1.
			BaseKeyframeTime *last_keyframe = GetKeyFrameTime( absolute_channel_number, x-1);
			if ((last_keyframe->timeOfFrame) > time && (keyframe->timeOfFrame <= time))
			{
				// this is the keyframe, set it up and leave
				BaseKeyframe *ret_key = GetKeyFrame( absolute_channel_number, x);
				return ret_key;
			}
			else if (time < keyframe->timeOfFrame)
			{
				right = x-1;
			}
			else
			{
				left = x+1;
			}		
		}

		// we didn't find one...
		BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, 0);
		if ((keyframe->timeOfFrame) > time)
		{
			BaseKeyframe *ret_key = GetKeyFrame( absolute_channel_number, 0);
			return ret_key;
		}			
	}
	
	return NULL;

}



//
//#############################################################################
//#############################################################################
//


BaseKeyframeTime * 
	AnimIterator::GetKeyFrameTimeAtTime(int absolute_channel_number, Stuff::Scalar time)
{
	// We have to be "IN" the animation, on out of range
	// you CAN NOT ANIMATE out of range keyframes!  They
	// are mearly helper keys.

	// time 0 is startTime, for simplicity
	time += animationData->animHeaderBlock->startTime;
	// this allows for animations that start somewhere other than 0

	Verify(time >= animationData->animHeaderBlock->startTime);
	Verify(time <= animationData->animHeaderBlock->endTime);

	currentTime = time;

	// lets get busy....

	// binary "divide-and-conquer" search from Sedgewick - "Algorithms in C++" pg. 198 
	
	if (animationData->animChannelBlock[absolute_channel_number].keyframeCount > 0)
	{
		// pretty sure this will skip 0
		int left = 1;
		int right = animationData->animChannelBlock[absolute_channel_number].keyframeCount;
		int x;

		while(right >= left)
		{
			x = (left+right)/2;

			BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, x);

			
			// the "next" keyframe is always greater, the last keyframe
			// can be the same.  We are always "going forward".
			// lowest keyframe we get is 1.
			BaseKeyframeTime *last_keyframe = GetKeyFrameTime( absolute_channel_number, x-1);
			if ((last_keyframe->timeOfFrame) > time && (keyframe->timeOfFrame <= time))
			{
				// this is the keyframe, set it up and leave
				
				return keyframe;
			}
			else if (time < keyframe->timeOfFrame)
			{
				right = x-1;
			}
			else
			{
				left = x+1;
			}		
		}

		// we didn't find one...
		BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, 0);
		if ((keyframe->timeOfFrame) > time)
		{
			
			return keyframe;
		}			
	}
	
	return NULL;

}


//
//#############################################################################
//#############################################################################
//

