From 08283d9bcfe73e96434626e493e4a6b0bcd8e6b8 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Tue, 28 Mar 2023 22:00:58 +0200 Subject: [PATCH] Evaluation of very simple graphs works. --- src/AnimGraph/AnimGraph.h | 22 ++++++++++++++++++ src/AnimGraph/AnimGraphData.h | 6 ++--- src/AnimGraph/AnimGraphEditor.cc | 6 ++++- src/AnimGraph/AnimGraphNodes.cc | 2 ++ src/AnimGraph/AnimGraphNodes.h | 31 ++++++++++++++++++++++++- src/AnimGraph/AnimGraphResource.cc | 2 +- src/main.cc | 37 +++++++++++++++++++++++++----- 7 files changed, 94 insertions(+), 12 deletions(-) diff --git a/src/AnimGraph/AnimGraph.h b/src/AnimGraph/AnimGraph.h index 798ebbc..d749de2 100644 --- a/src/AnimGraph/AnimGraph.h +++ b/src/AnimGraph/AnimGraph.h @@ -49,6 +49,27 @@ struct AnimGraph { } } } + m_node_input_connections.clear(); + + if (m_node_output_connections.size() > 0) { + std::vector& graph_inputs = + m_node_output_connections[0]; + + for (size_t i = 0, n = graph_inputs.size(); i < n; i++) { + AnimGraphConnection& connection = graph_inputs[i]; + if (connection.m_target_socket.m_type + == SocketType::SocketTypeAnimation) { + AnimData* graph_anim_output = static_cast( + connection.m_target_socket.m_reference.ptr); + assert(graph_anim_output != nullptr); + + // we have to explicitly call the destructor as the AnimData* was + // initialized using a placement new operator. + graph_anim_output->m_local_matrices.vector::~vector(); + } + } + } + m_node_output_connections.clear(); delete[] m_input_buffer; delete[] m_output_buffer; @@ -56,6 +77,7 @@ struct AnimGraph { for (int i = 0; i < m_nodes.size(); i++) { delete m_nodes[i]; } + m_nodes.clear(); delete m_socket_accessor; } diff --git a/src/AnimGraph/AnimGraphData.h b/src/AnimGraph/AnimGraphData.h index 39e90b0..6c8ac39 100644 --- a/src/AnimGraph/AnimGraphData.h +++ b/src/AnimGraph/AnimGraphData.h @@ -416,10 +416,10 @@ inline void NodeSocketAccessorBase::SetSocketValue( } template <> -inline void NodeSocketAccessorBase::SetSocketValue( +inline void NodeSocketAccessorBase::SetSocketValue( Socket* socket, - const float& value) { - socket->m_value.float_value = value; + float value) { + *static_cast(socket->m_reference.ptr) = value; } template <> diff --git a/src/AnimGraph/AnimGraphEditor.cc b/src/AnimGraph/AnimGraphEditor.cc index d039a49..728d2b0 100644 --- a/src/AnimGraph/AnimGraphEditor.cc +++ b/src/AnimGraph/AnimGraphEditor.cc @@ -85,7 +85,7 @@ void AnimGraphEditorRenderSidebar( if (property.m_type == SocketType::SocketTypeFloat) { ImGui::SliderFloat( property.m_name.c_str(), - reinterpret_cast(property.m_reference.ptr), + reinterpret_cast(&property.m_value.float_value), -100.f, 100.f); } else if (property.m_type == SocketType::SocketTypeBool) { @@ -219,6 +219,10 @@ void AnimGraphEditorUpdate() { node_type_name = "MathFloatToVec3Node"; } + if (ImGui::MenuItem("ConstScalarNode")) { + node_type_name = "ConstScalarNode"; + } + if (node_type_name != "") { AnimNodeResource node_resource = AnimNodeResourceFactory(node_type_name); diff --git a/src/AnimGraph/AnimGraphNodes.cc b/src/AnimGraph/AnimGraphNodes.cc index a81d23b..a020692 100644 --- a/src/AnimGraph/AnimGraphNodes.cc +++ b/src/AnimGraph/AnimGraphNodes.cc @@ -65,6 +65,8 @@ bool AnimSamplerNode::Init(AnimGraphContext& context) { return false; } + archive >> *m_animation; + context.m_animation_map[m_filename] = m_animation; } diff --git a/src/AnimGraph/AnimGraphNodes.h b/src/AnimGraph/AnimGraphNodes.h index 470061b..678d9f1 100644 --- a/src/AnimGraph/AnimGraphNodes.h +++ b/src/AnimGraph/AnimGraphNodes.h @@ -197,6 +197,11 @@ struct AnimSamplerNode : public AnimNode { virtual ~AnimSamplerNode(); virtual bool Init(AnimGraphContext& context) override; + void UpdateTime(float time_last, float time_now) override { + m_time_last = time_last; + m_time_now = fmodf(time_last + (time_now - time_last), m_animation->duration()); + m_state = AnimNodeEvalState::TimeUpdated; + } virtual void Evaluate(AnimGraphContext& context) override; }; @@ -210,6 +215,27 @@ struct NodeSocketAccessor : public NodeSocketAccessorBase { } }; +// +// ConstScalarNode +// +struct ConstScalarNode : public AnimNode { + float* o_value = nullptr; + float value = 0.f; + + virtual void Evaluate(AnimGraphContext& context){ + *o_value = value; + }; +}; + +template <> +struct NodeSocketAccessor : public NodeSocketAccessorBase { + NodeSocketAccessor(AnimNode* node_) { + ConstScalarNode* node = dynamic_cast(node_); + RegisterOutput("ScalarOutput", &node->o_value); + RegisterProperty("ScalarValue", &node->value); + } +}; + // // MathAddNode // @@ -236,7 +262,6 @@ struct NodeSocketAccessor : public NodeSocketAccessorBase { } }; - // // MathFloatToVec3Node // @@ -282,6 +307,8 @@ static inline AnimNode* AnimNodeFactory(const std::string& name) { result = new MathAddNode; } else if (name == "MathFloatToVec3Node") { result = new MathFloatToVec3Node; + } else if (name == "ConstScalarNode") { + result = new ConstScalarNode; } if (result != nullptr) { @@ -308,6 +335,8 @@ static inline NodeSocketAccessorBase* AnimNodeAccessorFactory( return new NodeSocketAccessor(node); } else if (node_type_name == "MathFloatToVec3Node") { return new NodeSocketAccessor(node); + } else if (node_type_name == "ConstScalarNode") { + return new NodeSocketAccessor(node); } else { std::cerr << "Invalid node type name " << node_type_name << "." << std::endl; diff --git a/src/AnimGraph/AnimGraphResource.cc b/src/AnimGraph/AnimGraphResource.cc index 8ebbb6b..172bc5a 100644 --- a/src/AnimGraph/AnimGraphResource.cc +++ b/src/AnimGraph/AnimGraphResource.cc @@ -534,7 +534,7 @@ void AnimGraphResource::setRuntimeNodeProperties(AnimGraph& instance) const { property.m_value.flag); break; case SocketType::SocketTypeFloat: - node_instance_accessor->SetPropertyReferenceValue( + node_instance_accessor->SetPropertyValue( name, property.m_value.float_value); break; diff --git a/src/main.cc b/src/main.cc index 4da9e65..6534d73 100644 --- a/src/main.cc +++ b/src/main.cc @@ -383,6 +383,7 @@ int main() { AnimGraph anim_graph; AnimGraphContext anim_graph_context; + AnimData* anim_graph_output = nullptr; state.time.factor = 1.0f; @@ -505,15 +506,15 @@ int main() { &gApplicationConfig.window_size[0], &gApplicationConfig.window_size[1]); + state.time.frame = stm_sec( + stm_round_to_common_refresh_rate(stm_laptime(&state.time.laptime))); + if (!state.time.paused) { - state.time.frame = stm_sec( - stm_round_to_common_refresh_rate(stm_laptime(&state.time.laptime))); - state.time.absolute += state.time.frame * state.time.factor; + } - if (state.ozz.animation != nullptr) { - state.time.absolute = fmodf (state.time.absolute, state.ozz.animation->duration()); - } + if (state.ozz.animation != nullptr) { + state.time.absolute = fmodf (state.time.absolute, state.ozz.animation->duration()); } int cur_width, cur_height; @@ -616,9 +617,20 @@ int main() { if (ImGui::Button("Update Runtime Graph")) { anim_graph.dealloc(); + anim_graph_output = nullptr; + AnimGraphEditorGetRuntimeGraph(anim_graph); anim_graph_context.m_skeleton = &skinned_mesh.m_skeleton; anim_graph.init(anim_graph_context); + + // For simplicity use first animation data output + const std::vector& graph_output_sockets = anim_graph.getGraphOutputs(); + for (int i = 0; i < graph_output_sockets.size(); i++) { + const Socket& output = graph_output_sockets[i]; + if (output.m_type == SocketType::SocketTypeAnimation) { + anim_graph_output = static_cast(output.m_reference.ptr); + } + } } ImGui::EndMainMenuBar(); @@ -711,6 +723,11 @@ int main() { } } + ImGui::SameLine(); + if (ImGui::Button("Step")) { + state.time.absolute += state.time.frame; + } + if (state.ozz.animation != nullptr) { ImGui::SameLine(); @@ -741,6 +758,14 @@ int main() { skinned_mesh.CalcModelMatrices(); } + if (state.time.use_graph && anim_graph.m_nodes.size() > 0) { + anim_graph.updateTime(state.time.frame); + anim_graph.evaluate(anim_graph_context); + skinned_mesh.m_local_matrices = anim_graph_output->m_local_matrices; + + skinned_mesh.CalcModelMatrices(); + } + sgl_defaults(); sgl_matrix_mode_projection(); sgl_load_matrix((const float*)&state.camera.mtxProj);