//===========================================================================// // 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 #include 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 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 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 node_iterator(¤t_node->childrenNodes); Stuff::ChainIteratorOf anim_iterator(¤t_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); }