Files
firestorm/Gameleap/code/mw4/Code/MW4/AnimIteratorManager.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

1135 lines
31 KiB
C++

//===========================================================================//
// File: AnimIteratorManager.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>
#include <Stuff\MemoryBlock.hpp>
namespace MechWarrior4 {
DECLARE_TIMER(extern, RunAnimStates);
DECLARE_TIMER(extern, Iterate);
DECLARE_TIMER(extern, Blend);
DECLARE_TIMER(extern, Apply);
DECLARE_TIMER(extern, BlendAlloc);
DECLARE_TIMER(extern, blendDealloc);
DECLARE_TIMER(extern, BlendAnimCombine);
DECLARE_TIMER(extern, BlendCombine);
DECLARE_TIMER(extern, BlendAndApply);
};
using namespace MW4Animation;
using namespace MechWarrior4;
//define MW4_ANIMATION_HIER_COUNT
bool AnimHierarchyIteratorManager::doTransitionBlend = true;
#if 0
#define ANIM_LOGIC(string) LOGIC("Animation::" string)
#else
#define ANIM_LOGIC(string)
#endif
//
//#############################################################################
//#############################################################################
//
Stuff::MemoryBlock*
BlendBuffer::AllocatedMemory = NULL;
void BlendBuffer::InitializeClass()
{
Verify(!AllocatedMemory);
AllocatedMemory =
new Stuff::MemoryBlock(
sizeof(BlendBuffer),
10,
2,
"Animation-BlendBuffer"
);
Register_Object(AllocatedMemory);
}
void BlendBuffer::TerminateClass()
{
Unregister_Object(AllocatedMemory);
delete AllocatedMemory;
AllocatedMemory = NULL;
}
//
//#############################################################################
//#############################################################################
//
Stuff::MemoryBlock*
AnimHierarchyNode::AllocatedMemory = NULL;
void AnimHierarchyNode::InitializeClass()
{
Verify(!AllocatedMemory);
AllocatedMemory =
new Stuff::MemoryBlock(
sizeof(AnimHierarchyNode),
10,
2,
"Animation-BlendHeirarchy"
);
Register_Object(AllocatedMemory);
}
void AnimHierarchyNode::TerminateClass()
{
Unregister_Object(AllocatedMemory);
delete AllocatedMemory;
AllocatedMemory = NULL;
}
//
//#############################################################################
//#############################################################################
//
AnimHierarchyNode::AnimHierarchyNode(Stuff::Scalar blend_value):
Plug(DefaultData),
childrenNodes(NULL),
animIterators(NULL),
parentNode(NULL)
{
Verify(blend_value >= 0);
blendValue = blend_value;
}
//
//#############################################################################
//#############################################################################
//
AnimHierarchyNode::~AnimHierarchyNode()
{
Stuff::ChainIteratorOf<AnimHierarchyNode*> iterator1(&childrenNodes);
Stuff::Plug *anim_plug;
while ((anim_plug = iterator1.GetCurrent()) != NULL)
{
iterator1.Remove();
Unregister_Object(anim_plug);
delete anim_plug;
}
// we don't own these so we don't delete them
Stuff::ChainIteratorOf<AnimIterator*> iterator2(&animIterators);
while ((anim_plug = iterator1.GetCurrent()) != NULL)
{
iterator2.Remove();
}
}
//
//#############################################################################
//#############################################################################
//
AnimHierarchyIteratorManager::AnimHierarchyIteratorManager(UserDefinedApplyChannelFunction apply_function, void *user_data):
Plug(DefaultData),
iteratorHierarchy(NULL),
currentLayer(NULL)
{
Check_Pointer(apply_function);
Check_Pointer(user_data);
applyFunction = apply_function;
userData = user_data;
}
//
//#############################################################################
//#############################################################################
//
AnimHierarchyIteratorManager::~AnimHierarchyIteratorManager()
{
}
//
//#############################################################################
//#############################################################################
//
#if defined(MW4_ANIMATION_HIER_COUNT)
static int AnimationHierarchyPopCount = 0;
static int AnimationHierarchyPushCount = 0;
#endif
AnimHierarchyNode * AnimHierarchyIteratorManager::PushLayer(Stuff::Scalar blend_value)
{
#if defined(MW4_ANIMATION_HIER_COUNT)
++AnimationHierarchyPushCount;
#endif
if (iteratorHierarchy.GetCurrent() == NULL)
{
Verify(currentLayer.GetCurrent() == NULL);
AnimHierarchyNode *new_node = new AnimHierarchyNode(blend_value);
Register_Object(new_node);
iteratorHierarchy.Add(new_node);
currentLayer.Add(new_node);
}
else
{
AnimHierarchyNode *new_node = new AnimHierarchyNode(blend_value);
Register_Object(new_node);
AnimHierarchyNode *parent_node = currentLayer.GetCurrent();
Check_Object(parent_node);
parent_node->childrenNodes.Add(new_node);
new_node->parentNode.Add(parent_node);
currentLayer.Remove();
currentLayer.Add(new_node);
}
return currentLayer.GetCurrent();
}
//
//#############################################################################
//#############################################################################
//
void AnimHierarchyIteratorManager::UndoPush()
{
AnimHierarchyNode *cur_node = currentLayer.GetCurrent();
Check_Object(cur_node);
#if defined(MW4_ANIMATION_HIER_COUNT)
++AnimationHierarchyPopCount;
#endif
if( cur_node->parentNode.GetCurrent() != NULL )
{
currentLayer.Remove();
currentLayer.Add(cur_node->parentNode.GetCurrent());
Unregister_Object(cur_node);
delete cur_node;
}
else
{
STOP(("AnimHierarchyIteratorManager::UndoPush() : UNHANDLED CASE"));
// if it is equal to null we are at the top of the stack...
}
}
//
//#############################################################################
//#############################################################################
//
void AnimHierarchyIteratorManager::PopLayer()
{
AnimHierarchyNode *cur_node = currentLayer.GetCurrent();
Check_Object(cur_node);
#if defined(MW4_ANIMATION_HIER_COUNT)
++AnimationHierarchyPopCount;
#endif
if( cur_node->parentNode.GetCurrent() != NULL )
{
currentLayer.Remove();
currentLayer.Add(cur_node->parentNode.GetCurrent());
}
else
{
currentLayer.Remove();
#if defined(MW4_ANIMATION_HIER_COUNT)
Verify(AnimationHierarchyPopCount == AnimationHierarchyPushCount);
AnimationHierarchyPopCount = 0;
AnimationHierarchyPushCount = 0;
#endif
// if it is equal to null we are at the top of the stack...
}
}
//
//#############################################################################
//#############################################################################
//
void AnimHierarchyIteratorManager::AddAnimToCurrentLayer(AnimIterator *iterator)
{
Check_Object(iterator);
AnimHierarchyNode *cur_node = currentLayer.GetCurrent();
Check_Object(cur_node);
cur_node->animIterators.Add(iterator);
}
//
//#############################################################################
//#############################################################################
//
void AnimHierarchyIteratorManager::BlendAndApply
(
int total_joint_count,
void *override_user_data,
UserDefinedApplyChannelFunction override_apply_function
)
{
ANIM_LOGIC("BlendAndApply");
Start_Timer(BlendAndApply);
if (override_user_data == NULL)
{
override_user_data = userData;
}
if (override_apply_function == NULL)
{
override_apply_function = applyFunction;
}
if (iteratorHierarchy.GetCurrent() != NULL)
{
ANIM_LOGIC("BlendAndApply::Allocation");
Start_Timer(BlendAlloc);
AnimHierarchyNode *root_node = iteratorHierarchy.GetCurrent();
Check_Object(root_node);
//blend
#if defined(MW4_ANIMATION_HIER_COUNT)
TabCount = 0;
BlendCount = 0;
#endif
BlendBuffer *blend_result = new BlendBuffer(total_joint_count);
Register_Pointer(blend_result);
Stop_Timer(BlendAlloc);
Stuff::Scalar small_backup = Stuff::SMALL;
Stuff::SMALL = 0.5f;
{
ANIM_LOGIC("BlendAndApply::Blend");
Start_Timer(Blend);
Blend(root_node, blend_result);
Stop_Timer(Blend);
}
#if defined(MW4_ANIMATION_HIER_COUNT)
SPEW(("jerryeds", "Blend Buffer Allocations : %d", BlendCount ));
SPEW(("jerryeds", ""));
#endif
{
ANIM_LOGIC("BlendAndApply::Apply");
Start_Timer(Apply);
// apply result
Apply(blend_result, override_user_data, override_apply_function);
Stop_Timer(Apply);
}
Stuff::SMALL = small_backup;
{
ANIM_LOGIC("BlendAndApply::Dealloc");
Start_Timer(blendDealloc);
Unregister_Pointer(blend_result);
delete blend_result;
//then delete...
Unregister_Object(root_node);
delete root_node;
Stop_Timer(blendDealloc);
}
}
Stop_Timer(BlendAndApply);
}
//
//#############################################################################
//#############################################################################
//
void AnimHierarchyIteratorManager::Apply(
BlendBuffer *blend_result,
void *user_data,
UserDefinedApplyChannelFunction apply_function
)
{
for (int i = 0; i < blend_result->numberOfJoints; i++)
{
ChannelApplication channel_app;
bool dirty = false;
if(blend_result->IsPositionDirty(i))
{
channel_app.positionValue = blend_result->positionBuffer[i];
channel_app.hasPosition = true;
dirty = true;
}
if(blend_result->IsRotationDirty(i))
{
channel_app.rotationValue = blend_result->rotationBuffer[i];
channel_app.hasRotation = true;
dirty = true;
}
if(blend_result->IsVelocityDirty(i))
{
channel_app.velocityValue = blend_result->velocityBuffer[i];
if (blend_result->IsAngularVelocityDirty(i))
{
Verify(blend_result->IsRotationDirty(i));
Stuff::LinearMatrix4D mat(Stuff::LinearMatrix4D::Identity);
mat.BuildRotation(channel_app.rotationValue);
channel_app.velocityValue.MultiplyByInverse(blend_result->velocityBuffer[i], mat);
}
else
{
channel_app.velocityValue = blend_result->velocityBuffer[i];
}
channel_app.hasVelocity = true;
dirty = true;
}
if(blend_result->IsAngularVelocityDirty(i))
{
channel_app.angularVelocityValue = blend_result->angularVelocityBuffer[i];
channel_app.hasAngularVelocity = true;
dirty = true;
}
if(blend_result->IsTriggerDirty(i))
{
channel_app.triggerValue = blend_result->triggerBuffer[i];
channel_app.hasTrigger = true;
dirty = true;
}
if (dirty)
{
(*apply_function)(channel_app, i, user_data);
}
}
}
//
//#############################################################################
//#############################################################################
//
void AnimHierarchyIteratorManager::Blend(AnimHierarchyNode *current_node, BlendBuffer *blend_result)
{
// normalize...
Stuff::ChainIteratorOf<AnimHierarchyNode*> node_iterator(&current_node->childrenNodes);
Stuff::ChainIteratorOf<AnimIterator*> anim_iterator(&current_node->animIterators);
AnimHierarchyNode *child_node;
AnimIterator *child_anim;
Stuff::Scalar total_node_weight = 0.0f;
Stuff::Scalar total_anim_weight = 0.0f;
Stuff::Scalar total_weight = 0.0f;
int child_node_count = 0;
int child_animation_count = 0;
#if defined(MW4_ANIMATION_HIER_COUNT)
for (int i = 0; i < TabCount; ++i)
{
SPEW(("jerryeds", "\t+"));
}
SPEW(("jerryeds","|_"));
++TabCount;
#endif
// normalize stuff
while ((child_node = node_iterator.ReadAndNext()) != NULL)
{
total_node_weight += child_node->blendValue;
++child_node_count;
}
while ((child_anim = anim_iterator.ReadAndNext()) != NULL)
{
total_anim_weight += child_anim->GetBlendValue();
++child_animation_count;
}
total_weight = total_node_weight + total_anim_weight;
Stuff::Scalar current_weight = 0.0f;
// mix in the node children...
if(total_node_weight != 0.0f)
{
node_iterator.First();
if(child_node_count == 1)
{
Blend(node_iterator.GetCurrent(), blend_result);
}
else
{
BlendBuffer *new_blend_result;
{
ANIM_LOGIC("BlendAndApply::Blend::Alloc");
Start_Timer(BlendAlloc);
new_blend_result = new BlendBuffer(blend_result->numberOfJoints);
Register_Pointer(new_blend_result);
Stop_Timer(BlendAlloc);
}
while ((child_node = node_iterator.ReadAndNext()) != NULL)
{
if (child_node->blendValue > 0.0f)
{
#if defined(MW4_ANIMATION_HIER_COUNT)
for (int tab_count = 0; tab_count < TabCount; ++tab_count)
{
SPEW(("jerryeds", "\t+"));
}
SPEW(("jerryeds", "|_ CB : %ff :", child_node->blendValue/total_weight));
#endif
Stuff::Scalar unitized_weight = child_node->blendValue/total_weight;
current_weight += unitized_weight;
Stuff::Scalar local_unitized_weight = 0.0f;
if (current_weight != 0.0f)
{
local_unitized_weight = unitized_weight/current_weight;
}
Blend(child_node, new_blend_result);
Combine(blend_result, new_blend_result, local_unitized_weight);
}
}
{
ANIM_LOGIC("BlendAndApply::Blend::Dealloc");
Start_Timer(blendDealloc);
Unregister_Pointer(new_blend_result);
delete new_blend_result;
Stop_Timer(blendDealloc);
}
}
}
if (total_anim_weight != 0.0f)
{
anim_iterator.First();
while ((child_anim = anim_iterator.ReadAndNext()) != NULL)
{
if (child_anim->GetBlendValue() > 0.0f)
{
Stuff::Scalar unitized_weight = child_anim->GetBlendValue()/total_weight;
current_weight += unitized_weight;
Stuff::Scalar local_unitized_weight = 0.0f;
if (current_weight != 0.0f)
{
local_unitized_weight = unitized_weight/current_weight;
}
AnimCombine(blend_result, child_anim, local_unitized_weight);
}
}
}
#if defined(MW4_ANIMATION_HIER_COUNT)
--TabCount;
#endif
}
//
//#############################################################################
//#############################################################################
//
void
AnimHierarchyIteratorManager::AnimCombine(
BlendBuffer *target_buffer,
AnimIterator *anim_iterator,
Stuff::Scalar percent
)
{
if (Stuff::Small_Enough(percent, 0.01f))
{
return;
}
ANIM_LOGIC("BlendAndApply::AnimCombine");
Start_Timer(BlendAnimCombine);
#if defined(MW4_ANIMATION_HIER_COUNT)
for (int i = 0; i < TabCount; ++i)
{
SPEW(("jerryeds", "\t+"));
}
SPEW(("jerryeds", "|_ AC : %ff :", percent));
#endif
for (BYTE channel_number = 0; channel_number < anim_iterator->GetAnimChannelCount(); channel_number++)
{
ChannelAnimData *channel = &anim_iterator->animationInstance->animData->animChannelBlock[channel_number];
int joint_number = anim_iterator->animationInstance->jointToIndex[channel->jointNumber];
if (joint_number == -1)
{
continue;
}
if (anim_iterator->DoISkipChannels())
{
if (!(anim_iterator->GetAnimData()->animChannelBlock[channel_number].channelType == MW4Animation::ChannelAnimData::VelocityChannelType ||
anim_iterator->GetAnimData()->animChannelBlock[channel_number].channelType == MW4Animation::ChannelAnimData::AngularVelocityChannelType) )
{
continue;
}
}
if(channel->channelType == MW4Animation::ChannelAnimData::VelocityChannelType)
{
Verify(anim_iterator->animationInstance->animData->animChannelBlock[channel_number].keyType ==
MW4Animation::JointAnimData::VelocityLinearKeyType);
MW4Animation::BaseKeyframe *nextFrame = anim_iterator->GetForwardKeyFrame(channel_number);
MW4Animation::BaseKeyframe *lastFrame = anim_iterator->GetReverseKeyFrame(channel_number);
MW4Animation::BaseKeyframeTime *nextFrameTime = anim_iterator->GetForwardKeyFrameTime(channel_number);
MW4Animation::BaseKeyframeTime *lastFrameTime = anim_iterator->GetReverseKeyFrameTime(channel_number);
Stuff::Point3D position(Stuff::Point3D::Identity);
Stuff::Point3D velocity(Stuff::Point3D::Identity);
if (lastFrame != NULL && nextFrame != NULL)
{
velocity = MW4Animation::Point3DVelPosLinearInterpolator(
lastFrame, nextFrame, lastFrameTime, nextFrameTime, anim_iterator->GetRealTime());
position = MW4Animation::Point3DLinearInterpolator(
lastFrame, nextFrame, lastFrameTime, nextFrameTime, anim_iterator->GetRealTime());
}
else if (lastFrame != NULL)
{
velocity = MW4Animation::Point3DVelPosSnapInterpolator(
lastFrame, lastFrame, lastFrameTime, lastFrameTime, anim_iterator->GetRealTime() );
position = MW4Animation::Point3DSnapInterpolator(
lastFrame, lastFrame, lastFrameTime, lastFrameTime, anim_iterator->GetRealTime() );
}
else if (nextFrame != NULL)
{
velocity = MW4Animation::Point3DVelPosSnapInterpolator(
nextFrame, nextFrame, nextFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
position = MW4Animation::Point3DSnapInterpolator(
nextFrame, nextFrame, nextFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
}
else
{
STOP(("BOTH KEYFRAMES ARE NULL ! : AnimHierarchyIteratorManager::AnimCombine"));
}
velocity.Multiply(
velocity,
anim_iterator->GetVelocityScale());
if (!target_buffer->IsPositionDirty(joint_number))
{
target_buffer->SetDirtyPosition(joint_number);
target_buffer->positionBuffer[joint_number] = position;
}
else
{
target_buffer->positionBuffer[joint_number].Lerp(
target_buffer->positionBuffer[joint_number],
position,
percent);
}
if (!target_buffer->IsVelocityDirty(joint_number))
{
target_buffer->SetDirtyVelocity(joint_number);
target_buffer->velocityBuffer[joint_number] = velocity;
}
else
{
target_buffer->velocityBuffer[joint_number].Lerp(
target_buffer->velocityBuffer[joint_number],
velocity,
percent);
}
}
else if (channel->channelType == MW4Animation::ChannelAnimData::AngularVelocityChannelType)
{
Verify(anim_iterator->animationInstance->animData->animChannelBlock[channel_number].keyType ==
MW4Animation::JointAnimData::AngularVelocityLinearKeyType);
MW4Animation::BaseKeyframe *nextFrame = anim_iterator->GetForwardKeyFrame(channel_number);
MW4Animation::BaseKeyframe *lastFrame = anim_iterator->GetReverseKeyFrame(channel_number);
MW4Animation::BaseKeyframeTime *nextFrameTime = anim_iterator->GetForwardKeyFrameTime(channel_number);
MW4Animation::BaseKeyframeTime *lastFrameTime = anim_iterator->GetReverseKeyFrameTime(channel_number);
Stuff::UnitQuaternion rotation(Stuff::UnitQuaternion::Identity);
Stuff::Vector3D angular_velocity(Stuff::Vector3D::Identity);
if (lastFrame != NULL && nextFrame != NULL)
{
rotation = MW4Animation::QuaternionLinearInterpolatorSlow(
lastFrame, nextFrame, lastFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
angular_velocity = MW4Animation::AngularVelocityLinearInterpolator(
lastFrame, nextFrame, lastFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
}
else if (lastFrame != NULL)
{
rotation = MW4Animation::QuaternionSnapInterpolator(
lastFrame, lastFrame, lastFrameTime, lastFrameTime,anim_iterator->GetRealTime() );
angular_velocity = MW4Animation::AngularVelocitySnapInterpolator(
lastFrame, lastFrame, lastFrameTime, lastFrameTime, anim_iterator->GetRealTime() );
}
else if (nextFrame != NULL)
{
rotation = MW4Animation::QuaternionSnapInterpolator(
nextFrame, nextFrame, nextFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
angular_velocity = MW4Animation::AngularVelocitySnapInterpolator(
nextFrame, nextFrame, nextFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
}
else
{
STOP(("BOTH KEYFRAMES ARE NULL ! : AnimHierarchyIteratorManager::AnimCombine"));
}
angular_velocity.Multiply(
angular_velocity,
anim_iterator->GetVelocityScale());
if (!target_buffer->IsRotationDirty(joint_number))
{
target_buffer->SetDirtyRotation(joint_number);
target_buffer->rotationBuffer[joint_number] = rotation;
rotation.FastNormalize();
#if defined(MW4_ANIMATION_DEBUG)
rotation.TestInstance();
#endif
}
else
{
#if defined(MW4_ANIMATION_DEBUG)
rotation.TestInstance();
target_buffer->rotationBuffer[joint_number].TestInstance();
#endif
Stuff::UnitQuaternion temp = target_buffer->rotationBuffer[joint_number];
target_buffer->rotationBuffer[joint_number].Lerp(
temp,
rotation,
percent);
target_buffer->rotationBuffer[joint_number].Normalize();
#if defined(MW4_ANIMATION_DEBUG)
target_buffer->rotationBuffer[joint_number].TestInstance();
#endif
}
if (!target_buffer->IsAngularVelocityDirty(joint_number))
{
target_buffer->SetDirtyAngularVelocity(joint_number);
target_buffer->angularVelocityBuffer[joint_number] = angular_velocity;
}
else
{
target_buffer->angularVelocityBuffer[joint_number].Lerp(
target_buffer->angularVelocityBuffer[joint_number],
angular_velocity,
percent);
}
}
else if (channel->channelType == MW4Animation::ChannelAnimData::PositionChannelType)
{
Verify(anim_iterator->animationInstance->animData->animChannelBlock[channel_number].keyType ==
MW4Animation::JointAnimData::Point3DLinearKeyType);
MW4Animation::BaseKeyframe *nextFrame = anim_iterator->GetForwardKeyFrame(channel_number);
MW4Animation::BaseKeyframe *lastFrame = anim_iterator->GetReverseKeyFrame(channel_number);
MW4Animation::BaseKeyframeTime *nextFrameTime = anim_iterator->GetForwardKeyFrameTime(channel_number);
MW4Animation::BaseKeyframeTime *lastFrameTime = anim_iterator->GetReverseKeyFrameTime(channel_number);
Stuff::Point3D position(Stuff::Point3D::Identity);
if (lastFrame != NULL && nextFrame != NULL)
{
position = MW4Animation::Point3DLinearInterpolator(
lastFrame, nextFrame, lastFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
}
else if (lastFrame != NULL)
{
position = MW4Animation::Point3DSnapInterpolator(
lastFrame, lastFrame, lastFrameTime, lastFrameTime, anim_iterator->GetRealTime() );
}
else if (nextFrame != NULL)
{
position = MW4Animation::Point3DSnapInterpolator(
nextFrame, nextFrame, nextFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
}
else
{
STOP(("BOTH KEYFRAMES ARE NULL ! : AnimHierarchyIteratorManager::AnimCombine"));
}
if (!target_buffer->IsPositionDirty(joint_number))
{
target_buffer->SetDirtyPosition(joint_number);
target_buffer->positionBuffer[joint_number] = position;
}
else
{
if (doTransitionBlend)
{
target_buffer->positionBuffer[joint_number].Lerp(
target_buffer->positionBuffer[joint_number],
position,
percent);
}
else
{
target_buffer->SetDirtyPosition(joint_number);
target_buffer->positionBuffer[joint_number] = position;
}
}
}
else if (channel->channelType == MW4Animation::ChannelAnimData::RotationChannelType)
{
Verify(anim_iterator->animationInstance->animData->animChannelBlock[channel_number].keyType ==
MW4Animation::JointAnimData::QuaternionLinearKeyType);
MW4Animation::BaseKeyframe *nextFrame = anim_iterator->GetForwardKeyFrame(channel_number);
MW4Animation::BaseKeyframe *lastFrame = anim_iterator->GetReverseKeyFrame(channel_number);
MW4Animation::BaseKeyframeTime *nextFrameTime = anim_iterator->GetForwardKeyFrameTime(channel_number);
MW4Animation::BaseKeyframeTime *lastFrameTime = anim_iterator->GetReverseKeyFrameTime(channel_number);
Stuff::UnitQuaternion rotation(Stuff::UnitQuaternion::Identity);
if (lastFrame != NULL && nextFrame != NULL)
{
rotation = MW4Animation::QuaternionLinearInterpolator(
lastFrame, nextFrame, lastFrameTime, nextFrameTime, anim_iterator->GetRealTime());
}
else if (lastFrame != NULL)
{
rotation = MW4Animation::QuaternionSnapInterpolator(
lastFrame, lastFrame, lastFrameTime, lastFrameTime, anim_iterator->GetRealTime());
}
else if (nextFrame != NULL)
{
rotation = MW4Animation::QuaternionSnapInterpolator(
nextFrame, nextFrame, nextFrameTime, nextFrameTime, anim_iterator->GetRealTime());
}
else
{
STOP(("BOTH KEYFRAMES ARE NULL ! : AnimHierarchyIteratorManager::AnimCombine"));
}
if (!target_buffer->IsRotationDirty(joint_number))
{
target_buffer->SetDirtyRotation(joint_number);
rotation.FastNormalize();
target_buffer->rotationBuffer[joint_number] = rotation;
#if defined(MW4_ANIMATION_DEBUG)
rotation.TestInstance();
#endif
}
else
{
#if defined(MW4_ANIMATION_DEBUG)
rotation.TestInstance();
target_buffer->rotationBuffer[joint_number].TestInstance();
#endif
Stuff::UnitQuaternion temp = target_buffer->rotationBuffer[joint_number];
target_buffer->rotationBuffer[joint_number].FastLerp(
temp,
rotation,
percent);
target_buffer->rotationBuffer[joint_number].FastNormalize();
#if defined(MW4_ANIMATION_DEBUG)
target_buffer->rotationBuffer[joint_number].TestInstance();
#endif
}
}
else if (channel->channelType == MW4Animation::ChannelAnimData::TriggerChannelType)
{
Verify(anim_iterator->animationInstance->animData->animChannelBlock[channel_number].keyType ==
MW4Animation::JointAnimData::TriggerLinearKeyType);
MW4Animation::BaseKeyframe *nextFrame = anim_iterator->GetForwardKeyFrame(channel_number);
MW4Animation::BaseKeyframe *lastFrame = anim_iterator->GetReverseKeyFrame(channel_number);
MW4Animation::BaseKeyframeTime *nextFrameTime = anim_iterator->GetForwardKeyFrameTime(channel_number);
MW4Animation::BaseKeyframeTime *lastFrameTime = anim_iterator->GetReverseKeyFrameTime(channel_number);
int trigger = 0;
if (lastFrame != NULL && nextFrame != NULL)
{
trigger = MW4Animation::TriggerSnapInterpolator(
lastFrame, nextFrame, lastFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
}
else if (lastFrame != NULL)
{
trigger = MW4Animation::TriggerSnapInterpolator(
lastFrame, lastFrame, lastFrameTime, lastFrameTime, anim_iterator->GetRealTime() );
}
else if (nextFrame != NULL)
{
trigger = MW4Animation::TriggerSnapInterpolator(
nextFrame, nextFrame, nextFrameTime, nextFrameTime, anim_iterator->GetRealTime() );
}
if (!target_buffer->IsTriggerDirty(joint_number))
{
target_buffer->SetDirtyTrigger(joint_number);
target_buffer->triggerBuffer[joint_number] = trigger;
}
else
{
target_buffer->triggerBuffer[joint_number] |= trigger;
}
}
}
Stop_Timer(BlendAnimCombine);
}
//
//#############################################################################
//#############################################################################
//
void
AnimHierarchyIteratorManager::Combine(
BlendBuffer *target_buffer,
BlendBuffer *new_buffer,
Stuff::Scalar percent
)
{
if (Stuff::Small_Enough(percent,0.01f))
{
return;
}
ANIM_LOGIC("BlendAndApply::Combine");
Start_Timer(BlendCombine);
for (int i = 0; i < target_buffer->numberOfJoints; ++i)
{
if (new_buffer->IsPositionDirty(i))
{
if (!target_buffer->IsPositionDirty(i))
{
target_buffer->SetDirtyPosition(i);
target_buffer->positionBuffer[i] = new_buffer->positionBuffer[i];
}
else
{
if (doTransitionBlend)
{
target_buffer->SetDirtyPosition(i);
target_buffer->positionBuffer[i].Lerp(
target_buffer->positionBuffer[i],
new_buffer->positionBuffer[i],
percent);
}
else
{
target_buffer->SetDirtyPosition(i);
target_buffer->positionBuffer[i] = new_buffer->positionBuffer[i];
}
}
}
if (new_buffer->IsVelocityDirty(i))
{
if (!target_buffer->IsVelocityDirty(i))
{
target_buffer->SetDirtyVelocity(i);
target_buffer->velocityBuffer[i] = new_buffer->velocityBuffer[i];
}
else
{
target_buffer->SetDirtyVelocity(i);
target_buffer->velocityBuffer[i].Lerp(
target_buffer->velocityBuffer[i],
new_buffer->velocityBuffer[i],
percent);
}
}
if (new_buffer->IsAngularVelocityDirty(i))
{
if (!target_buffer->IsAngularVelocityDirty(i))
{
target_buffer->SetDirtyAngularVelocity(i);
target_buffer->angularVelocityBuffer[i] = new_buffer->angularVelocityBuffer[i];
}
else
{
target_buffer->SetDirtyAngularVelocity(i);
target_buffer->angularVelocityBuffer[i].Lerp(
target_buffer->angularVelocityBuffer[i],
new_buffer->angularVelocityBuffer[i],
percent);
}
}
if (new_buffer->IsRotationDirty(i))
{
if (!target_buffer->IsRotationDirty(i))
{
target_buffer->SetDirtyRotation(i);
target_buffer->rotationBuffer[i] = new_buffer->rotationBuffer[i];
#if defined(MW4_ANIMATION_DEBUG)
new_buffer->rotationBuffer[i].TestInstance();
#endif
}
else
{
target_buffer->SetDirtyRotation(i);
#if defined(MW4_ANIMATION_DEBUG)
target_buffer->rotationBuffer[i].TestInstance();
new_buffer->rotationBuffer[i].TestInstance();
#endif
Stuff::UnitQuaternion temp = target_buffer->rotationBuffer[i];
target_buffer->rotationBuffer[i].FastLerp(
temp,
new_buffer->rotationBuffer[i],
percent);
target_buffer->rotationBuffer[i].FastNormalize();
#if defined(MW4_ANIMATION_DEBUG)
target_buffer->rotationBuffer[i].TestInstance();
#endif
}
}
if (new_buffer->IsTriggerDirty(i))
{
if (!target_buffer->IsTriggerDirty(i))
{
target_buffer->SetDirtyTrigger(i);
target_buffer->triggerBuffer[i] = new_buffer->triggerBuffer[i];
}
else
{
target_buffer->SetDirtyTrigger(i);
target_buffer->triggerBuffer[i] |= new_buffer->triggerBuffer[i];
}
}
}
Stop_Timer(BlendCombine);
}