From 1f858d68c02cc1a3c1ec708082673ebee396f175 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Fri, 12 Nov 2021 21:54:21 +0100 Subject: [PATCH] Implemented blend2 node. --- src/AnimationController.cc | 24 ++++++++++++---- src/BlendNode.cc | 59 ++++++++++++++++++++++++++++++++++++++ src/BlendNode.h | 36 +++++++++++++++++++++++ src/SpeedScaleNode.cc | 2 +- src/SpeedScaleNode.h | 6 ++-- 5 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 src/BlendNode.cc create mode 100644 src/BlendNode.h diff --git a/src/AnimationController.cc b/src/AnimationController.cc index 6ab4c6f..412f07f 100644 --- a/src/AnimationController.cc +++ b/src/AnimationController.cc @@ -10,6 +10,7 @@ #include #include "AnimSamplerNode.h" +#include "BlendNode.h" #include "SkinnedMesh.h" #include "SpeedScaleNode.h" @@ -26,17 +27,28 @@ AnimationController::AnimationController(SkinnedMesh* skinned_mesh) SetBlendAnims(skinned_mesh->m_animations[1], skinned_mesh->m_animations[0]); ResetAnims(); - AnimSamplerNode* sampler_node = new AnimSamplerNode(this); - sampler_node->m_name = "AnimSampler0"; - sampler_node->SetAnimation(skinned_mesh->m_animations[0]); - m_anim_nodes.push_back(sampler_node); + AnimSamplerNode* sampler_node0 = new AnimSamplerNode(this); + sampler_node0->m_name = "AnimSampler0"; + sampler_node0->SetAnimation(skinned_mesh->m_animations[1]); + m_anim_nodes.push_back(sampler_node0); + + AnimSamplerNode* sampler_node1 = new AnimSamplerNode(this); + sampler_node1->m_name = "AnimSampler0"; + sampler_node1->SetAnimation(skinned_mesh->m_animations[2]); + m_anim_nodes.push_back(sampler_node1); SpeedScaleNode* speed_node = new SpeedScaleNode(this); speed_node->m_name = "SpeedNode0"; - speed_node->m_child_node = sampler_node; + speed_node->m_input_node = sampler_node0; m_anim_nodes.push_back(speed_node); - m_output_node = speed_node; + BlendNode* blend_node = new BlendNode(this); + blend_node->m_name = "Blend0"; + blend_node->m_input_A = speed_node; + blend_node->m_input_B = sampler_node1; + m_anim_nodes.push_back(blend_node); + + m_output_node = blend_node; m_output_node->Reset(); } diff --git a/src/BlendNode.cc b/src/BlendNode.cc new file mode 100644 index 0000000..f7f70f3 --- /dev/null +++ b/src/BlendNode.cc @@ -0,0 +1,59 @@ +// +// Created by martin on 12.11.21. +// + +#include "BlendNode.h" + +#include + +#include "SkinnedMesh.h" +#include + +BlendNode::BlendNode(AnimationController* animation_controller) + : AnimNode(animation_controller), + m_input_A(nullptr), + m_input_B(nullptr), + m_weight(0.f) { + const SkinnedMesh* skinned_mesh = m_animation_controller->m_skinned_mesh; + const int num_soa_joints = skinned_mesh->m_skeleton.num_soa_joints(); + const int num_joints = skinned_mesh->m_skeleton.num_joints(); + m_local_matrices_A.resize(num_soa_joints); + m_local_matrices_B.resize(num_soa_joints); +} + +void BlendNode::Evaluate(ozz::vector* local_matrices) { + const SkinnedMesh* skinned_mesh = m_animation_controller->m_skinned_mesh; + + m_input_A->Evaluate(&m_local_matrices_A); + m_input_B->Evaluate(&m_local_matrices_B); + + // perform blend + ozz::animation::BlendingJob::Layer layers[2]; + layers[0].transform = make_span(m_local_matrices_A); + layers[0].weight = (1.0f - m_weight); + + layers[1].transform = make_span(m_local_matrices_B); + layers[1].weight = (m_weight); + + ozz::animation::BlendingJob blend_job; + blend_job.threshold = ozz::animation::BlendingJob().threshold; + blend_job.layers = layers; + blend_job.bind_pose = skinned_mesh->m_skeleton.joint_bind_poses(); + blend_job.output = make_span(*local_matrices); + + if (!blend_job.Run()) { + ozz::log::Err() << "Error blending animations." << std::endl; + } +} + +void BlendNode::DrawDebugUi() { + std::string node_name = "BlendNode: " + m_name; + if (ImGui::TreeNode(node_name.c_str())) { + ImGui::Text("Input A:"); + m_input_A->DrawDebugUi(); + ImGui::Text("Input B:"); + m_input_B->DrawDebugUi(); + ImGui::SliderFloat("Weight", &m_weight, 0.f, 1.f); + ImGui::TreePop(); + } +} diff --git a/src/BlendNode.h b/src/BlendNode.h new file mode 100644 index 0000000..64b53c2 --- /dev/null +++ b/src/BlendNode.h @@ -0,0 +1,36 @@ +// +// Created by martin on 12.11.21. +// + +#ifndef ANIMTESTBED_BLENDNODE_H +#define ANIMTESTBED_BLENDNODE_H + +#include "AnimNode.h" + +struct BlendNode : public AnimNode { + BlendNode(AnimationController* animation_controller); + virtual ~BlendNode() {} + + AnimNode* m_input_A; + AnimNode* m_input_B; + float m_weight; + + ozz::vector m_local_matrices_A; + ozz::vector m_local_matrices_B; + + virtual void Reset() { + m_current_time = 0.f; + } + + virtual void Update(float dt) { + m_input_A->Update(dt); + m_input_B->Update(dt); + } + + virtual void Evaluate( + ozz::vector* local_matrices) override; + + virtual void DrawDebugUi(); +}; + +#endif //ANIMTESTBED_BLENDNODE_H diff --git a/src/SpeedScaleNode.cc b/src/SpeedScaleNode.cc index a3ba2f6..c755488 100644 --- a/src/SpeedScaleNode.cc +++ b/src/SpeedScaleNode.cc @@ -11,7 +11,7 @@ void SpeedScaleNode::DrawDebugUi() { if (ImGui::TreeNode(node_name.c_str())) { ImGui::SliderFloat("Time Scale", &m_time_scale, -5.f, 5.f); - m_child_node->DrawDebugUi(); + m_input_node->DrawDebugUi(); ImGui::TreePop(); } diff --git a/src/SpeedScaleNode.h b/src/SpeedScaleNode.h index 9c64edd..f5c0a05 100644 --- a/src/SpeedScaleNode.h +++ b/src/SpeedScaleNode.h @@ -11,7 +11,7 @@ struct SpeedScaleNode : public AnimNode { SpeedScaleNode(AnimationController* animation_controller): AnimNode (animation_controller), m_time_scale(1.f) {} float m_time_scale; - AnimNode* m_child_node; + AnimNode* m_input_node; virtual void Reset() { m_current_time = 0.f; @@ -19,11 +19,11 @@ struct SpeedScaleNode : public AnimNode { virtual void Update(float dt) { m_current_time += dt * m_time_scale; - m_child_node->Update(dt * m_time_scale); + m_input_node->Update(dt * m_time_scale); } virtual void Evaluate(ozz::vector* local_matrices) override { - m_child_node->Evaluate(local_matrices); + m_input_node->Evaluate(local_matrices); }; virtual void DrawDebugUi() override;