Files
firestorm/Gameleap/code/mw4/Code/MW4/AnimIterator.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1330 lines
35 KiB
C++

//===========================================================================//
// 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;
}
//
//#############################################################################
//#############################################################################
//