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.
1330 lines
35 KiB
C++
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;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
|