| 672 | } |
| 673 | |
| 674 | Variant AnimGraphExecutor::Blend(AnimGraphNode* node, const Value& poseA, const Value& poseB, float alpha, AlphaBlendMode alphaMode) |
| 675 | { |
| 676 | ANIM_GRAPH_PROFILE_EVENT("Blend Pose"); |
| 677 | |
| 678 | if (isnan(alpha) || isinf(alpha)) |
| 679 | alpha = 0; |
| 680 | alpha = Math::Saturate(alpha); |
| 681 | alpha = AlphaBlend::Process(alpha, alphaMode); |
| 682 | |
| 683 | const auto nodes = node->GetNodes(this); |
| 684 | auto nodesA = static_cast<AnimGraphImpulse*>(poseA.AsPointer); |
| 685 | auto nodesB = static_cast<AnimGraphImpulse*>(poseB.AsPointer); |
| 686 | if (!ANIM_GRAPH_IS_VALID_PTR(poseA)) |
| 687 | nodesA = GetEmptyNodes(); |
| 688 | if (!ANIM_GRAPH_IS_VALID_PTR(poseB)) |
| 689 | nodesB = GetEmptyNodes(); |
| 690 | |
| 691 | const Transform* srcA = nodesA->Nodes.Get(); |
| 692 | const Transform* srcB = nodesB->Nodes.Get(); |
| 693 | Transform* dst = nodes->Nodes.Get(); |
| 694 | for (int32 i = 0; i < nodes->Nodes.Count(); i++) |
| 695 | { |
| 696 | Transform::Lerp(srcA[i], srcB[i], alpha, dst[i]); |
| 697 | } |
| 698 | Transform::Lerp(nodesA->RootMotion, nodesB->RootMotion, alpha, nodes->RootMotion); |
| 699 | nodes->Position = Math::Lerp(nodesA->Position, nodesB->Position, alpha); |
| 700 | nodes->Length = Math::Lerp(nodesA->Length, nodesB->Length, alpha); |
| 701 | |
| 702 | return nodes; |
| 703 | } |
| 704 | |
| 705 | Variant AnimGraphExecutor::SampleState(AnimGraphContext& context, const AnimGraphNode* state) |
| 706 | { |