From 91607baa9d4638f7c16ccb069c5755e3c748df0a Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Thu, 30 Mar 2023 23:50:07 +0200 Subject: [PATCH] Initial step for connectivity refactor. Instead of wiring up pointers with prepareNodeEval() and finishNodeEval() use for each connection a single memory block where outputs and inputs point to. --- src/AnimGraph/AnimGraph.cc | 43 +--- src/AnimGraph/AnimGraph.h | 45 +--- src/AnimGraph/AnimGraphData.h | 398 +++++------------------------ src/AnimGraph/AnimGraphNodes.h | 88 +++---- src/AnimGraph/AnimGraphResource.cc | 146 ++++++++--- src/AnimGraph/AnimGraphResource.h | 8 +- tests/AnimGraphEvalTests.cc | 4 +- tests/AnimGraphResourceTests.cc | 372 +-------------------------- 8 files changed, 249 insertions(+), 855 deletions(-) diff --git a/src/AnimGraph/AnimGraph.cc b/src/AnimGraph/AnimGraph.cc index c598d29..929a9cd 100644 --- a/src/AnimGraph/AnimGraph.cc +++ b/src/AnimGraph/AnimGraph.cc @@ -15,16 +15,9 @@ bool AnimGraph::init(AnimGraphContext& context) { } } - std::vector& graph_outputs = m_node_input_connections[0]; - for (size_t i = 0, n = graph_outputs.size(); i < n; i++) { - AnimGraphConnection& connection = graph_outputs[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); - graph_anim_output->m_local_matrices.resize( - context.m_skeleton->num_soa_joints()); - } + for (size_t i = 0; i < m_animdata_blocks.size(); i++) { + int num_soa_joints = context.m_skeleton->num_soa_joints(); + m_animdata_blocks[i]->m_local_matrices.resize(num_soa_joints); } return true; @@ -37,11 +30,11 @@ void AnimGraph::updateOrderedNodes() { void AnimGraph::updateOrderedNodesRecursive(int node_index) { AnimNode* node = m_nodes[node_index]; - const std::vector node_input_connections = + const std::vector& node_input_connections = m_node_input_connections[node_index]; for (size_t i = 0, n = node_input_connections.size(); i < n; i++) { int input_node_index = - getAnimNodeIndex(node_input_connections[i].m_source_node); + getAnimNodeIndex(node_input_connections.at(i).m_source_node); if (input_node_index == 1) { continue; @@ -104,10 +97,7 @@ void AnimGraph::prepareNodeEval( continue; } - assert (*output_connection.m_source_socket.m_reference.ptr_ptr == nullptr); - - (*output_connection.m_source_socket.m_reference.ptr_ptr) = - m_anim_data_allocator.allocate(graph_context.m_skeleton); + // TODO: only allocate local matrices for active nodes } for (size_t i = 0, n = m_node_input_connections[node_index].size(); i < n; @@ -118,9 +108,6 @@ void AnimGraph::prepareNodeEval( != SocketType::SocketTypeAnimation) { continue; } - - (*input_connection.m_target_socket.m_reference.ptr_ptr) = - (*input_connection.m_source_socket.m_reference.ptr_ptr); } } @@ -134,9 +121,7 @@ void AnimGraph::finishNodeEval(size_t node_index) { continue; } - m_anim_data_allocator.free(static_cast( - *input_connection.m_source_socket.m_reference.ptr_ptr)); - (*input_connection.m_source_socket.m_reference.ptr_ptr) = nullptr; + // TODO: free local matrices for inactive nodes } } @@ -162,20 +147,6 @@ void AnimGraph::evalOutputNode() { for (size_t i = 0, n = m_node_input_connections[0].size(); i < n; i++) { AnimGraphConnection& graph_output_connection = m_node_input_connections[0][i]; - - if (graph_output_connection.m_source_socket.m_type - != SocketType::SocketTypeAnimation) { - memcpy( - graph_output_connection.m_target_socket.m_reference.ptr, - graph_output_connection.m_source_socket.m_reference.ptr, - graph_output_connection.m_target_socket.m_type_size); - } else { - AnimData* source_data = static_cast( - *graph_output_connection.m_source_socket.m_reference.ptr_ptr); - AnimData* target_data = static_cast( - graph_output_connection.m_target_socket.m_reference.ptr); - target_data->m_local_matrices = source_data->m_local_matrices; - } } } diff --git a/src/AnimGraph/AnimGraph.h b/src/AnimGraph/AnimGraph.h index d749de2..4314840 100644 --- a/src/AnimGraph/AnimGraph.h +++ b/src/AnimGraph/AnimGraph.h @@ -18,9 +18,11 @@ struct AnimGraph { std::vector m_eval_ordered_nodes; std::vector > m_node_input_connections; std::vector > m_node_output_connections; - NodeSocketAccessorBase* m_socket_accessor; + std::vector m_animdata_blocks; + NodeDescriptorBase* m_socket_accessor; char* m_input_buffer = nullptr; char* m_output_buffer = nullptr; + char* m_connection_data_storage = nullptr; std::vector& getGraphOutputs() { return m_socket_accessor->m_inputs; } std::vector& getGraphInputs() { return m_socket_accessor->m_outputs; } @@ -31,48 +33,17 @@ struct AnimGraph { bool init(AnimGraphContext& context); void dealloc() { - if (m_node_input_connections.size() > 0) { - std::vector& graph_outputs = - m_node_input_connections[0]; - - for (size_t i = 0, n = graph_outputs.size(); i < n; i++) { - AnimGraphConnection& connection = graph_outputs[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(); - } - } + for (size_t i = 0; i < m_animdata_blocks.size(); i++) { + m_animdata_blocks[i]->m_local_matrices.vector::~vector(); } + m_animdata_blocks.clear(); + 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; + delete[] m_connection_data_storage; for (int i = 0; i < m_nodes.size(); i++) { delete m_nodes[i]; diff --git a/src/AnimGraph/AnimGraphData.h b/src/AnimGraph/AnimGraphData.h index e58a2f1..d589968 100644 --- a/src/AnimGraph/AnimGraphData.h +++ b/src/AnimGraph/AnimGraphData.h @@ -29,6 +29,10 @@ struct AnimData { ozz::vector m_local_matrices; }; +struct AnimDataRef { + AnimData* ptr = nullptr; +}; + struct AnimDataAllocator { struct AnimDataList { AnimData* m_anim_data = nullptr; @@ -104,8 +108,26 @@ struct AnimGraphContext { } }; -typedef float Vec3[3]; -typedef float Quat[4]; +struct Vec3 { + struct { + float x; + float y; + float z; + }; + + float v[3] = { 0 }; +}; + +struct Quat { + struct { + float x; + float y; + float z; + float w; + }; + + float v[4] = { 0 }; +}; enum class SocketType { SocketTypeUndefined = 0, @@ -131,11 +153,11 @@ struct Socket { union SocketValue { bool flag; float float_value; - float vec3[3]; - float quat[4]; - std::string* string_ptr; + Vec3 vec3; + Quat quat; }; SocketValue m_value = {0}; + std::string m_value_string; union SocketReference { void* ptr; void** ptr_ptr; @@ -177,9 +199,9 @@ SocketType GetSocketType() { } struct NodeDescriptorBase { - std::vector m_properties; std::vector m_inputs; std::vector m_outputs; + std::vector m_properties; template bool RegisterInput( @@ -234,10 +256,39 @@ struct NodeDescriptorBase { *socket->m_reference.ptr_ptr = value_ptr; } + void SetInputUnchecked(const char* name, void* value_ptr) { + Socket* socket = FindSocket(name, m_inputs); + *socket->m_reference.ptr_ptr = value_ptr; + } + Socket* GetInputSocket(const char* name) { return FindSocket(name, m_inputs); } + int GetInputIndex(const char* name) { + return FindSocketIndex(name, m_inputs); + } + + template + void SetOutput(const char* name, T* value_ptr) { + Socket* socket = FindSocket(name, m_outputs); + assert(GetSocketType() == socket->m_type); + *socket->m_reference.ptr_ptr = value_ptr; + } + + void SetOutputUnchecked(const char* name, void* value_ptr) { + Socket* socket = FindSocket(name, m_outputs); + *socket->m_reference.ptr_ptr = value_ptr; + } + + Socket* GetOutputSocket(const char* name) { + return FindSocket(name, m_outputs); + } + + int GetOutputIndex(const char* name) { + return FindSocketIndex(name, m_outputs); + } + template void SetProperty(const char* name, const T& value) { Socket* socket = FindSocket(name, m_properties); @@ -263,6 +314,16 @@ struct NodeDescriptorBase { return nullptr; } + int FindSocketIndex(const char* name, std::vector& sockets) { + for (int i = 0, n = sockets.size(); i < n; i++) { + if (sockets[i].m_name == name) { + return i; + } + } + + return -1; + } + virtual void UpdateFlags(){}; template @@ -295,328 +356,11 @@ struct NodeDescriptor : public NodeDescriptorBase { virtual ~NodeDescriptor() {} }; -struct NodeSocketAccessorBase { - std::vector m_properties; - std::vector m_inputs; - std::vector m_outputs; - - NodeSocketAccessorBase() {} - virtual ~NodeSocketAccessorBase() {} - - virtual void UpdateFlags(){}; - - Socket* FindSocket(std::vector& sockets, const std::string& name) { - Socket* result = nullptr; - for (size_t i = 0, n = sockets.size(); i < n; i++) { - if (sockets[i].m_name == name) { - result = &sockets[i]; - break; - } - } - - return result; - } - - const Socket* FindSocket( - const std::vector& sockets, - const std::string& name) const { - const Socket* result = nullptr; - for (size_t i = 0, n = sockets.size(); i < n; i++) { - if (sockets[i].m_name == name) { - result = &sockets[i]; - break; - } - } - - return result; - } - - SocketType GetSocketType( - const std::vector& sockets, - const std::string& name) { - const Socket* socket = FindSocket(sockets, name); - if (socket == nullptr) { - return SocketType::SocketTypeUndefined; - } - return socket->m_type; - } - - size_t GetSocketIndex( - const std::vector& sockets, - const std::string& name) const { - for (size_t i = 0, n = sockets.size(); i < n; i++) { - if (sockets[i].m_name == name) { - return i; - } - } - - return -1; - } - - template - T GetSocketValue( - const std::vector& sockets, - const std::string& name, - T default_value) { - const Socket* socket = FindSocket(sockets, name); - if (socket == nullptr) { - return default_value; - } - - return *static_cast(socket->m_reference.ptr); - } - - template - void SetSocketReferenceValue(Socket* socket, T value) { - std::cerr << "Could not find template specialization for socket type " - << static_cast(socket->m_type) << " (" - << SocketTypeNames[static_cast(socket->m_type)] << ")." - << std::endl; - // *static_cast(socket->m_value.ptr) = value; - } - - template - void SetSocketValue(Socket* socket, T value) { - std::cerr << "Could not find template specialization for socket type " - << static_cast(socket->m_type) << " (" - << SocketTypeNames[static_cast(socket->m_type)] << ")." - << std::endl; - // *static_cast(socket->m_value.ptr) = value; - } - - template - bool RegisterSocket( - std::vector& sockets, - const std::string& name, - T* value_ptr, - SocketFlags flags = SocketFlagNone) { - Socket* socket = FindSocket(sockets, name); - if (socket != nullptr) { - std::cerr << "Socket " << name << " already registered." << std::endl; - return false; - } - - sockets.push_back(Socket()); - socket = &sockets[sockets.size() - 1]; - socket->m_name = name; - socket->m_type_size = sizeof(T); - socket->m_flags = flags; - - if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeFloat; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeBool; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeVec3; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeQuat; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeAnimation; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeString; - socket->m_value.string_ptr = value_ptr; - socket->m_reference.ptr = value_ptr; - return true; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeFloat; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeBool; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeVec3; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeQuat; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeAnimation; - } else if constexpr (std::is_same::value) { - socket->m_type = SocketType::SocketTypeString; - } else { - std::cerr << "Cannot register socket, invalid type." << std::endl; - return false; - } - - socket->m_reference.ptr = value_ptr; - return true; - } - - template - bool RegisterProperty(const std::string& name, T* value) { - return RegisterSocket(m_properties, name, value); - } - template - void SetPropertyReferenceValue(const std::string& name, T value) { - Socket* socket = FindSocket(m_properties, name); - SetSocketReferenceValue(socket, value); - } - template - void SetPropertyValue(const std::string& name, T value) { - Socket* socket = FindSocket(m_properties, name); - SetSocketValue(socket, value); - } - template - T GetProperty(const std::string& name, T default_value) { - return GetSocketValue(m_properties, name, default_value); - } - SocketType GetPropertyType(const std::string& name) { - return GetSocketType(m_properties, name); - } - - template - bool RegisterInput( - const std::string& name, - T* value, - SocketFlags flags = SocketFlagNone) { - return RegisterSocket(m_inputs, name, value, flags); - } - template - T* GetInput(const std::string& name, T* value) { - return GetSocketValue(m_inputs, name, value); - } - Socket* FindInputSocket(const std::string& name) { - return FindSocket(m_inputs, name); - } - SocketType GetInputType(const std::string& name) { - return GetSocketType(m_inputs, name); - } - size_t GetInputIndex(const std::string& name) { - return GetSocketIndex(m_inputs, name); - } - - template - bool RegisterOutput( - const std::string& name, - T* value, - SocketFlags flags = SocketFlagNone) { - return RegisterSocket(m_outputs, name, value, flags); - } - template - bool RegisterOutput( - const std::string& name, - T** value, - SocketFlags flags = SocketFlagNone) { - return RegisterSocket(m_outputs, name, value, flags); - } - SocketType GetOutputType(const std::string& name) { - return GetSocketType(m_outputs, name); - } - Socket* FindOutputSocket(const std::string& name) { - return FindSocket(m_outputs, name); - } - size_t GetOutputIndex(const std::string& name) { - return GetSocketIndex(m_outputs, name); - } -}; - -// -// SetSocketReferenceValue<> specializations -// -template <> -inline void NodeSocketAccessorBase::SetSocketReferenceValue( - Socket* socket, - const bool& value) { - *static_cast(socket->m_reference.ptr) = value; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketReferenceValue( - Socket* socket, - const float& value) { - *static_cast(socket->m_reference.ptr) = value; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketReferenceValue( - Socket* socket, - const Vec3& value) { - static_cast(socket->m_reference.ptr)[0] = value[0]; - static_cast(socket->m_reference.ptr)[1] = value[1]; - static_cast(socket->m_reference.ptr)[2] = value[2]; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketReferenceValue( - Socket* socket, - const Quat& value) { - static_cast(socket->m_reference.ptr)[0] = value[0]; - static_cast(socket->m_reference.ptr)[1] = value[1]; - static_cast(socket->m_reference.ptr)[2] = value[2]; - static_cast(socket->m_reference.ptr)[3] = value[3]; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketReferenceValue( - Socket* socket, - const std::string* value) { - socket->m_value.string_ptr = const_cast(value); -} - -template <> -inline void NodeSocketAccessorBase::SetSocketReferenceValue( - Socket* socket, - const std::string& value) { - *static_cast(socket->m_reference.ptr) = value; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketReferenceValue( - Socket* socket, - const char* value) { - std::string value_string(value); - SetSocketReferenceValue(socket, value_string); -} - -// -// SetSocketValue<> specializations -// -template <> -inline void NodeSocketAccessorBase::SetSocketValue( - Socket* socket, - const bool& value) { - socket->m_value.flag = value; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketValue( - Socket* socket, - float value) { - *static_cast(socket->m_reference.ptr) = value; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketValue( - Socket* socket, - const Vec3& value) { - socket->m_value.vec3[0] = value[0]; - socket->m_value.vec3[1] = value[1]; - socket->m_value.vec3[2] = value[2]; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketValue( - Socket* socket, - const Quat& value) { - socket->m_value.quat[0] = value[0]; - socket->m_value.quat[1] = value[1]; - socket->m_value.quat[2] = value[2]; - socket->m_value.quat[3] = value[3]; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketValue( - Socket* socket, - std::string value) { - *socket->m_value.string_ptr = value; -} - -template <> -inline void NodeSocketAccessorBase::SetSocketValue( - Socket* socket, - const char* value) { - SetSocketValue(socket, value); -} +struct AnimNode; template -struct NodeSocketAccessor : public NodeSocketAccessorBase { - virtual ~NodeSocketAccessor() {} -}; +NodeDescriptorBase* CreateNodeDescriptor(AnimNode* node) { + return new NodeDescriptor(dynamic_cast(node)); +} #endif //ANIMTESTBED_ANIMGRAPHDATA_H diff --git a/src/AnimGraph/AnimGraphNodes.h b/src/AnimGraph/AnimGraphNodes.h index 420f103..88d90c1 100644 --- a/src/AnimGraph/AnimGraphNodes.h +++ b/src/AnimGraph/AnimGraphNodes.h @@ -86,8 +86,8 @@ struct AnimNode { struct BlendTreeNode : public AnimNode {}; template <> -struct NodeSocketAccessor : public NodeSocketAccessorBase { - NodeSocketAccessor(AnimNode* node_) {} +struct NodeDescriptor : public NodeDescriptorBase { + NodeDescriptor(BlendTreeNode* node_) {} }; // @@ -122,34 +122,6 @@ struct Blend2Node : public AnimNode { virtual void Evaluate(AnimGraphContext& context) override; }; -template <> -struct NodeSocketAccessor : public NodeSocketAccessorBase { - NodeSocketAccessor(AnimNode* node_) { - Blend2Node* node = dynamic_cast(node_); - RegisterInput("Input0", &node->i_input0); - RegisterInput("Input1", &node->i_input1); - RegisterInput( - "Weight", - &node->i_blend_weight, - SocketFlags::SocketFlagAffectsTime); - - RegisterOutput("Output", &node->o_output); - - RegisterProperty("Sync", &node->m_sync_blend); - } - - virtual void UpdateFlags() override { - Socket* weight_input_socket = FindSocket(m_inputs, "Weight"); - assert(weight_input_socket != nullptr); - - if (GetProperty("Sync", false) == true) { - weight_input_socket->m_flags = SocketFlags::SocketFlagAffectsTime; - } else { - weight_input_socket->m_flags = SocketFlags::SocketFlagNone; - } - } -}; - template <> struct NodeDescriptor : public NodeDescriptorBase { NodeDescriptor(Blend2Node* node) { @@ -198,9 +170,8 @@ struct SpeedScaleNode : public AnimNode { }; template <> -struct NodeSocketAccessor : public NodeSocketAccessorBase { - NodeSocketAccessor(AnimNode* node_) { - SpeedScaleNode* node = dynamic_cast(node_); +struct NodeDescriptor : public NodeDescriptorBase { + NodeDescriptor(SpeedScaleNode* node) { RegisterInput( "SpeedScale", &node->i_speed_scale, @@ -211,6 +182,7 @@ struct NodeSocketAccessor : public NodeSocketAccessorBase { } }; + // // AnimSamplerNode // @@ -231,9 +203,8 @@ struct AnimSamplerNode : public AnimNode { }; template <> -struct NodeSocketAccessor : public NodeSocketAccessorBase { - NodeSocketAccessor(AnimNode* node_) { - AnimSamplerNode* node = dynamic_cast(node_); +struct NodeDescriptor : public NodeDescriptorBase { + NodeDescriptor(AnimSamplerNode* node) { RegisterOutput("Output", &node->o_output); RegisterProperty("Filename", &node->m_filename); @@ -253,34 +224,33 @@ struct ConstScalarNode : public AnimNode { }; template <> -struct NodeSocketAccessor : public NodeSocketAccessorBase { - NodeSocketAccessor(AnimNode* node_) { - ConstScalarNode* node = dynamic_cast(node_); +struct NodeDescriptor : public NodeDescriptorBase { + NodeDescriptor(ConstScalarNode* node) { RegisterOutput("ScalarOutput", &node->o_value); RegisterProperty("ScalarValue", &node->value); } }; + // // MathAddNode // struct MathAddNode : public AnimNode { float* i_input0 = nullptr; float* i_input1 = nullptr; - float o_output = 0.f; + float* o_output = nullptr; void Evaluate(AnimGraphContext& context) override { assert (i_input0 != nullptr); assert (i_input1 != nullptr); - o_output = *i_input0 + *i_input1; + *o_output = *i_input0 + *i_input1; } }; template <> -struct NodeSocketAccessor : public NodeSocketAccessorBase { - NodeSocketAccessor(AnimNode* node_) { - MathAddNode* node = dynamic_cast(node_); +struct NodeDescriptor : public NodeDescriptorBase { + NodeDescriptor(MathAddNode* node) { RegisterInput("Input0", &node->i_input0); RegisterInput("Input1", &node->i_input1); RegisterOutput("Output", &node->o_output); @@ -294,23 +264,22 @@ struct MathFloatToVec3Node : public AnimNode { float* i_input0 = nullptr; float* i_input1 = nullptr; float* i_input2 = nullptr; - Vec3 o_output = {0.f, 0.f, 0.f}; + Vec3* o_output = nullptr; void Evaluate(AnimGraphContext& context) override { assert (i_input0 != nullptr); assert (i_input1 != nullptr); assert (i_input2 != nullptr); - o_output[0] = *i_input0; - o_output[1] = *i_input1; - o_output[2] = *i_input2; + o_output->v[0] = *i_input0; + o_output->v[1] = *i_input1; + o_output->v[2] = *i_input2; } }; template <> -struct NodeSocketAccessor : public NodeSocketAccessorBase { - NodeSocketAccessor(AnimNode* node_) { - MathFloatToVec3Node* node = dynamic_cast(node_); +struct NodeDescriptor : public NodeDescriptorBase { + NodeDescriptor(MathFloatToVec3Node* node) { RegisterInput("Input0", &node->i_input0); RegisterInput("Input1", &node->i_input1); RegisterInput("Input2", &node->i_input2); @@ -318,6 +287,7 @@ struct NodeSocketAccessor : public NodeSocketAccessorBase { } }; + static inline AnimNode* AnimNodeFactory(const std::string& name) { AnimNode* result; if (name == "Blend2") { @@ -345,23 +315,23 @@ static inline AnimNode* AnimNodeFactory(const std::string& name) { return nullptr; } -static inline NodeSocketAccessorBase* AnimNodeAccessorFactory( +static inline NodeDescriptorBase* AnimNodeDescriptorFactory( const std::string& node_type_name, AnimNode* node) { if (node_type_name == "Blend2") { - return new NodeSocketAccessor(node); + return CreateNodeDescriptor(node); } else if (node_type_name == "SpeedScale") { - return new NodeSocketAccessor(node); + return CreateNodeDescriptor(node); } else if (node_type_name == "AnimSampler") { - return new NodeSocketAccessor(node); + return CreateNodeDescriptor(node); } else if (node_type_name == "BlendTree") { - return new NodeSocketAccessor(node); + return CreateNodeDescriptor(node); } else if (node_type_name == "MathAddNode") { - return new NodeSocketAccessor(node); + return CreateNodeDescriptor(node); } else if (node_type_name == "MathFloatToVec3Node") { - return new NodeSocketAccessor(node); + return CreateNodeDescriptor(node); } else if (node_type_name == "ConstScalarNode") { - return new NodeSocketAccessor(node); + return CreateNodeDescriptor(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 172bc5a..be8b88a 100644 --- a/src/AnimGraph/AnimGraphResource.cc +++ b/src/AnimGraph/AnimGraphResource.cc @@ -34,16 +34,16 @@ json sSocketToJson(const Socket& socket) { } else if (socket.m_type == SocketType::SocketTypeFloat) { result["value"] = socket.m_value.float_value; } else if (socket.m_type == SocketType::SocketTypeVec3) { - result["value"][0] = socket.m_value.vec3[0]; - result["value"][1] = socket.m_value.vec3[1]; - result["value"][2] = socket.m_value.vec3[2]; + result["value"][0] = socket.m_value.vec3.v[0]; + result["value"][1] = socket.m_value.vec3.v[1]; + result["value"][2] = socket.m_value.vec3.v[2]; } else if (socket.m_type == SocketType::SocketTypeQuat) { - result["value"][0] = socket.m_value.quat[0]; - result["value"][1] = socket.m_value.quat[1]; - result["value"][2] = socket.m_value.quat[2]; - result["value"][3] = socket.m_value.quat[3]; + result["value"][0] = socket.m_value.quat.v[0]; + result["value"][1] = socket.m_value.quat.v[1]; + result["value"][2] = socket.m_value.quat.v[2]; + result["value"][3] = socket.m_value.quat.v[3]; } else if (socket.m_type == SocketType::SocketTypeString) { - result["value"] = *socket.m_value.string_ptr; + result["value"] = *static_cast(socket.m_reference.ptr); } else { std::cerr << "Invalid socket type '" << static_cast(socket.m_type) << "'." << std::endl; @@ -118,7 +118,7 @@ AnimNodeResource sAnimGraphNodeFromJson(const json& json_node) { result.m_anim_node = AnimNodeFactory(result.m_type_name); result.m_socket_accessor = - AnimNodeAccessorFactory(result.m_type_name, result.m_anim_node); + AnimNodeDescriptorFactory(result.m_type_name, result.m_anim_node); for (size_t j = 0, n = result.m_socket_accessor->m_properties.size(); j < n; j++) { @@ -132,17 +132,17 @@ AnimNodeResource sAnimGraphNodeFromJson(const json& json_node) { } else if (property.m_type == SocketType::SocketTypeFloat) { property.m_value.float_value = json_property["value"]; } else if (property.m_type == SocketType::SocketTypeVec3) { - property.m_value.vec3[0] = json_property["value"][0]; - property.m_value.vec3[1] = json_property["value"][1]; - property.m_value.vec3[2] = json_property["value"][2]; + property.m_value.vec3.v[0] = json_property["value"][0]; + property.m_value.vec3.v[1] = json_property["value"][1]; + property.m_value.vec3.v[2] = json_property["value"][2]; } else if (property.m_type == SocketType::SocketTypeQuat) { Quat* property_quat = reinterpret_cast(property.m_reference.ptr); - property.m_value.quat[0] = json_property["value"][0]; - property.m_value.quat[1] = json_property["value"][1]; - property.m_value.quat[2] = json_property["value"][2]; - property.m_value.quat[3] = json_property["value"][3]; + property.m_value.quat.v[0] = json_property["value"][0]; + property.m_value.quat.v[1] = json_property["value"][1]; + property.m_value.quat.v[2] = json_property["value"][2]; + property.m_value.quat.v[3] = json_property["value"][3]; } else if (property.m_type == SocketType::SocketTypeString) { - *(property.m_value.string_ptr) = json_property["value"].get(); + property.m_value_string = json_property["value"].get(); } else { std::cerr << "Invalid type for property '" << property.m_name << "'. Cannot parse json to type '" @@ -333,7 +333,6 @@ bool AnimGraphResource::loadFromFile(const char* filename) { void AnimGraphResource::createInstance(AnimGraph& result) const { createRuntimeNodeInstances(result); prepareGraphIOData(result); - connectRuntimeNodes(result); setRuntimeNodeProperties(result); result.updateOrderedNodes(); @@ -359,10 +358,12 @@ void AnimGraphResource::createRuntimeNodeInstances(AnimGraph& instance) const { void AnimGraphResource::prepareGraphIOData(AnimGraph& instance) const { instance.m_socket_accessor = - AnimNodeAccessorFactory("BlendTree", instance.m_nodes[0]); + AnimNodeDescriptorFactory("BlendTree", instance.m_nodes[0]); instance.m_socket_accessor->m_outputs = m_nodes[1].m_socket_accessor->m_outputs; instance.m_socket_accessor->m_inputs = m_nodes[0].m_socket_accessor->m_inputs; + instance.m_socket_accessor->m_outputs = + m_nodes[1].m_socket_accessor->m_outputs; // inputs int input_block_size = 0; @@ -401,8 +402,87 @@ void AnimGraphResource::prepareGraphIOData(AnimGraph& instance) const { &instance.m_output_buffer[output_block_offset]; output_block_offset += graph_outputs[i].m_type_size; } + + // connections: make source and target sockets point to the same address in the connection data storage. + int connection_data_storage_size = 0; + for (int i = 0; i < m_connections.size(); i++) { + const AnimGraphConnectionResource& connection = m_connections[i]; + const AnimNodeResource& source_node = m_nodes[connection.source_node_index]; + Socket* source_socket = source_node.m_socket_accessor->GetOutputSocket( + connection.source_socket_name.c_str()); + connection_data_storage_size += source_socket->m_type_size; + } + + if (connection_data_storage_size > 0) { + instance.m_connection_data_storage = new char[connection_data_storage_size]; + memset(instance.m_connection_data_storage, 0, connection_data_storage_size); + } + + std::vector instance_node_descriptors( + m_nodes.size(), + nullptr); + for (int i = 0; i < m_nodes.size(); i++) { + instance_node_descriptors[i] = AnimNodeDescriptorFactory( + m_nodes[i].m_type_name.c_str(), + instance.m_nodes[i]); + } + + instance_node_descriptors[0]->m_inputs = instance.getGraphOutputs(); + instance_node_descriptors[1]->m_outputs = instance.getGraphInputs(); + + int connection_data_offset = 0; + for (int i = 0; i < m_connections.size(); i++) { + const AnimGraphConnectionResource& connection = m_connections[i]; + const AnimNodeResource& source_node_resource = + m_nodes[connection.source_node_index]; + const AnimNodeResource& target_node_resource = + m_nodes[connection.target_node_index]; + + NodeDescriptorBase* source_node_descriptor = + instance_node_descriptors[connection.source_node_index]; + NodeDescriptorBase* target_node_descriptor = + instance_node_descriptors[connection.target_node_index]; + + AnimNode* source_node = instance.m_nodes[connection.source_node_index]; + AnimNode* target_node = instance.m_nodes[connection.target_node_index]; + + Socket* source_socket = source_node_descriptor->GetOutputSocket( + connection.source_socket_name.c_str()); + Socket* target_socket = target_node_descriptor->GetInputSocket( + connection.target_socket_name.c_str()); + + AnimGraphConnection instance_connection; + instance_connection.m_source_node = source_node; + instance_connection.m_source_socket = *source_socket; + instance_connection.m_target_node = target_node; + instance_connection.m_target_socket = *target_socket; + instance.m_node_input_connections[connection.target_node_index].push_back( + instance_connection); + instance.m_node_output_connections[connection.source_node_index].push_back( + instance_connection); + + source_node_descriptor->SetOutputUnchecked( + connection.source_socket_name.c_str(), + &instance.m_connection_data_storage[connection_data_offset]); + + target_node_descriptor->SetInputUnchecked( + connection.target_socket_name.c_str(), + &instance.m_connection_data_storage[connection_data_offset]); + + if (source_socket->m_type == SocketType::SocketTypeAnimation) { + instance.m_animdata_blocks.push_back((AnimData*)( + &instance.m_connection_data_storage[connection_data_offset])); + } + + connection_data_offset += source_socket->m_type_size; + } + + for (int i = 0; i < m_nodes.size(); i++) { + delete instance_node_descriptors[i]; + } } +/* void AnimGraphResource::connectRuntimeNodes(AnimGraph& instance) const { for (int i = 0; i < m_connections.size(); i++) { const AnimGraphConnectionResource& connection = m_connections[i]; @@ -513,13 +593,15 @@ void AnimGraphResource::connectRuntimeNodes(AnimGraph& instance) const { } } } +*/ void AnimGraphResource::setRuntimeNodeProperties(AnimGraph& instance) const { for (int i = 2; i < m_nodes.size(); i++) { const AnimNodeResource& node_resource = m_nodes[i]; - NodeSocketAccessorBase* node_instance_accessor = - AnimNodeAccessorFactory(node_resource.m_type_name, instance.m_nodes[i]); + NodeDescriptorBase* node_instance_accessor = AnimNodeDescriptorFactory( + node_resource.m_type_name, + instance.m_nodes[i]); std::vector& resource_properties = node_resource.m_socket_accessor->m_properties; @@ -529,29 +611,29 @@ void AnimGraphResource::setRuntimeNodeProperties(AnimGraph& instance) const { switch (property.m_type) { case SocketType::SocketTypeBool: - node_instance_accessor->SetPropertyReferenceValue( - name, + node_instance_accessor->SetProperty( + name.c_str(), property.m_value.flag); break; case SocketType::SocketTypeFloat: - node_instance_accessor->SetPropertyValue( - name, + node_instance_accessor->SetProperty( + name.c_str(), property.m_value.float_value); break; case SocketType::SocketTypeVec3: - node_instance_accessor->SetPropertyReferenceValue( - name, + node_instance_accessor->SetProperty( + name.c_str(), property.m_value.vec3); break; case SocketType::SocketTypeQuat: - node_instance_accessor->SetPropertyReferenceValue( - name, + node_instance_accessor->SetProperty( + name.c_str(), property.m_value.quat); break; case SocketType::SocketTypeString: - node_instance_accessor->SetPropertyValue( - name, - *property.m_value.string_ptr); + node_instance_accessor->SetProperty( + name.c_str(), + property.m_value_string); break; default: std::cerr << "Invalid socket type " diff --git a/src/AnimGraph/AnimGraphResource.h b/src/AnimGraph/AnimGraphResource.h index c67db9e..fd1a235 100644 --- a/src/AnimGraph/AnimGraphResource.h +++ b/src/AnimGraph/AnimGraphResource.h @@ -24,7 +24,7 @@ struct AnimNodeResource { std::string m_name; std::string m_type_name; AnimNode* m_anim_node = nullptr; - NodeSocketAccessorBase* m_socket_accessor = nullptr; + NodeDescriptorBase* m_socket_accessor = nullptr; float m_position[2] = {0.f, 0.f}; }; @@ -34,7 +34,7 @@ static inline AnimNodeResource AnimNodeResourceFactory( result.m_type_name = node_type_name; result.m_anim_node = AnimNodeFactory(node_type_name); result.m_socket_accessor = - AnimNodeAccessorFactory(node_type_name, result.m_anim_node); + AnimNodeDescriptorFactory(node_type_name.c_str(), result.m_anim_node); return result; } @@ -104,9 +104,9 @@ struct AnimGraphResource { } Socket* source_socket = - source_node.m_socket_accessor->FindOutputSocket(source_socket_name); + source_node.m_socket_accessor->GetOutputSocket(source_socket_name.c_str()); Socket* target_socket = - target_node.m_socket_accessor->FindInputSocket(target_socket_name); + target_node.m_socket_accessor->GetInputSocket(target_socket_name.c_str()); if (source_socket == nullptr || target_socket == nullptr) { std::cerr << "Cannot connect nodes: could not find sockets." << std::endl; diff --git a/tests/AnimGraphEvalTests.cc b/tests/AnimGraphEvalTests.cc index af7ea02..c936f39 100644 --- a/tests/AnimGraphEvalTests.cc +++ b/tests/AnimGraphEvalTests.cc @@ -153,11 +153,11 @@ TEST_CASE_METHOD( // Setup nodes AnimNodeResource& trans_x_node = graph_resource.m_nodes[trans_x_node_index]; - trans_x_node.m_socket_accessor->SetPropertyValue("Filename", "trans_x"); + trans_x_node.m_socket_accessor->SetProperty("Filename", std::string("trans_x")); trans_x_node.m_name = "trans_x"; AnimNodeResource& trans_y_node = graph_resource.m_nodes[trans_y_node_index]; - trans_y_node.m_socket_accessor->SetPropertyValue("Filename", "trans_y"); + trans_y_node.m_socket_accessor->SetProperty("Filename", std::string("trans_y")); trans_y_node.m_name = "trans_y"; AnimNodeResource& blend_node = graph_resource.m_nodes[blend_node_index]; diff --git a/tests/AnimGraphResourceTests.cc b/tests/AnimGraphResourceTests.cc index 48a2dd7..e3042bb 100644 --- a/tests/AnimGraphResourceTests.cc +++ b/tests/AnimGraphResourceTests.cc @@ -48,9 +48,9 @@ TEST_CASE("BasicGraph", "[AnimGraphResource]") { AnimNodeResource& walk_node = graph_resource.m_nodes[walk_node_index]; walk_node.m_name = "WalkAnim"; - walk_node.m_socket_accessor->SetPropertyValue("Filename", "data/walk.anim.ozz"); + walk_node.m_socket_accessor->SetProperty("Filename", std::string("data/walk.anim.ozz")); AnimNodeResource& run_node = graph_resource.m_nodes[run_node_index]; - run_node.m_socket_accessor->SetPropertyValue("Filename", "data/run.anim.ozz"); + run_node.m_socket_accessor->SetProperty("Filename", std::string("data/run.anim.ozz")); run_node.m_name = "RunAnim"; AnimNodeResource& blend_node = graph_resource.m_nodes[blend_node_index]; blend_node.m_name = "BlendWalkRun"; @@ -132,46 +132,33 @@ TEST_CASE("BasicGraph", "[AnimGraphResource]") { CHECK(graph.m_anim_data_allocator.size() == 0); graph.prepareNodeEval(graph_context, walk_node_index); graph.finishNodeEval(walk_node_index); - CHECK(graph.m_anim_data_allocator.m_num_allocations == 1); - CHECK(graph.m_anim_data_allocator.size() == 0); graph.prepareNodeEval(graph_context, run_node_index); graph.finishNodeEval(run_node_index); - CHECK(graph.m_anim_data_allocator.m_num_allocations == 2); - CHECK(graph.m_anim_data_allocator.size() == 0); graph.prepareNodeEval(graph_context, blend_node_index); CHECK(blend2_instance->i_input0 == anim_sampler_walk->o_output); CHECK(blend2_instance->i_input1 == anim_sampler_run->o_output); - CHECK(graph.m_anim_data_allocator.m_num_allocations == 3); - CHECK(graph.m_anim_data_allocator.size() == 0); graph.finishNodeEval(blend_node_index); - CHECK(anim_sampler_walk->o_output == nullptr); - CHECK(anim_sampler_run->o_output == nullptr); - CHECK(graph.m_anim_data_allocator.m_num_allocations == 3); - CHECK(graph.m_anim_data_allocator.size() == 2); // Evaluate output node. graph.evalOutputNode(); graph.finishNodeEval(0); - const Socket* graph_output_socket = graph.getOutputSocket("GraphOutput"); AnimData* graph_output = - static_cast(graph_output_socket->m_reference.ptr); + static_cast(*graph_output_socket->m_reference.ptr_ptr); CHECK(graph_output->m_local_matrices.size() == graph_context.m_skeleton->num_soa_joints()); - CHECK(graph.m_anim_data_allocator.m_num_allocations == 3); - CHECK(graph.m_anim_data_allocator.size() == 3); - - CHECK(blend2_instance->o_output == nullptr); + CHECK(blend2_instance->o_output == *graph_output_socket->m_reference.ptr_ptr); } graph_context.freeAnimations(); } + TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") { int node_id = 3321; int input_index = 221; @@ -191,6 +178,7 @@ TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") { CHECK(output_index == parsed_output_index); } + TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { AnimGraphResource graph_resource_origin; @@ -269,16 +257,16 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { == graph_loaded_input_node.m_socket_accessor->m_outputs.size()); REQUIRE( - graph_loaded_input_node.m_socket_accessor->FindOutputSocket( + graph_loaded_input_node.m_socket_accessor->GetOutputSocket( "GraphFloatInput") != nullptr); REQUIRE( - graph_loaded_output_node.m_socket_accessor->FindInputSocket( + graph_loaded_output_node.m_socket_accessor->GetInputSocket( "GraphFloatOutput") != nullptr); REQUIRE( - graph_loaded_output_node.m_socket_accessor->FindInputSocket( + graph_loaded_output_node.m_socket_accessor->GetInputSocket( "GraphVec3Output") != nullptr); @@ -312,9 +300,9 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { *static_cast(vec3_output_socket->m_reference.ptr); THEN("output vector components equal the graph input vaulues") { - CHECK(vec3_output[0] == *graph_float_input); - CHECK(vec3_output[1] == *graph_float_input); - CHECK(vec3_output[2] == *graph_float_input); + CHECK(vec3_output.v[0] == *graph_float_input); + CHECK(vec3_output.v[1] == *graph_float_input); + CHECK(vec3_output.v[2] == *graph_float_input); } context.freeAnimations(); @@ -324,6 +312,7 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") { } } +/* TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { AnimGraphResource graph_resource_origin; @@ -470,337 +459,4 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") { } } -/* - - WHEN("Connecting input to output and instantiating the graph") { - AnimNodeResource& graph_output_node = graph_resource_origin.m_nodes[0]; - AnimNodeResource& graph_input_node = graph_resource_origin.m_nodes[1]; - - REQUIRE(graph_resource_origin.connectSockets( - graph_input_node, - "GraphAnimInput", - graph_output_node, - "GraphOutput")); - - AnimGraph anim_graph = graph_resource_origin.createInstance(); - - void* graph_anim_input_ptr = anim_graph.getInput("GraphAnimInput"); - void* graph_output_ptr = anim_graph.getOutput("GraphOutput"); - - REQUIRE(graph_anim_input_ptr == graph_output_ptr); - REQUIRE(graph_output_ptr == anim_graph.m_output_buffer); - - REQUIRE( - anim_graph.getInput("GraphAnimInput") - == anim_graph.getOutput("GraphOutput")); - } -} - -TEST_CASE("GraphInputOutputConnectivity", "[AnimGraphResource]") { - AnimGraphResource sGraphGresource; - - sGraphGresource.clear(); - sGraphGresource.m_name = "TestGraphInputOutputConnectivity"; - - AnimNodeResource& graph_output_node = sGraphGresource.m_nodes[0]; - graph_output_node.m_socket_accessor->RegisterInput( - "GraphFloatOutput", - nullptr); - graph_output_node.m_socket_accessor->RegisterInput( - "GraphAnimOutput", - nullptr); - - AnimNodeResource& graph_input_node = sGraphGresource.m_nodes[1]; - graph_input_node.m_socket_accessor->RegisterOutput( - "GraphFloatInput", - nullptr); - graph_input_node.m_socket_accessor->RegisterOutput( - "SpeedScaleInput", - nullptr); - graph_input_node.m_socket_accessor->RegisterOutput( - "GraphAnimInput0", - nullptr); - graph_input_node.m_socket_accessor->RegisterOutput( - "GraphAnimInput1", - nullptr); - - WHEN("Connecting float input with float output") { - REQUIRE(sGraphGresource.connectSockets( - sGraphGresource.getGraphInputNode(), - "GraphFloatInput", - sGraphGresource.getGraphOutputNode(), - "GraphFloatOutput")); - - AnimGraph anim_graph = sGraphGresource.createInstance(); - - THEN("Writing to the input pointer changes the value of the output.") { - float* float_input_ptr = (float*)anim_graph.getInput("GraphFloatInput"); - REQUIRE(float_input_ptr != nullptr); - *float_input_ptr = 23.123f; - - float* float_output_ptr = - (float*)anim_graph.getOutput("GraphFloatOutput"); - REQUIRE(float_output_ptr != nullptr); - CHECK(*float_output_ptr == Approx(23.123f)); - } - } - - WHEN("Connecting adding a Blend2 node") { - size_t blend2_node_index = - sGraphGresource.addNode(AnimNodeResourceFactory("Blend2")); - AnimNodeResource& blend2_node_resource = - sGraphGresource.m_nodes[blend2_node_index]; - - REQUIRE(sGraphGresource.connectSockets( - sGraphGresource.getGraphInputNode(), - "GraphFloatInput", - blend2_node_resource, - "Weight")); - - THEN("Connected float input points to the blend weight.") { - AnimGraph anim_graph = sGraphGresource.createInstance(); - - Blend2Node* blend2_node = - dynamic_cast(anim_graph.m_nodes[blend2_node_index]); - - REQUIRE( - *anim_graph.m_socket_accessor->m_outputs[0].m_reference.ptr_ptr - == blend2_node->i_blend_weight); - float* float_input_ptr = (float*)anim_graph.getInput("GraphFloatInput"); - REQUIRE(float_input_ptr == blend2_node->i_blend_weight); - } - - WHEN( - "Connecting AnimData inputs to blend2 node and blend2 output to graph " - "output.") { - REQUIRE(sGraphGresource.connectSockets( - sGraphGresource.getGraphInputNode(), - "GraphAnimInput0", - blend2_node_resource, - "Input0")); - - REQUIRE(sGraphGresource.connectSockets( - sGraphGresource.getGraphInputNode(), - "GraphAnimInput1", - blend2_node_resource, - "Input1")); - - REQUIRE(sGraphGresource.connectSockets( - blend2_node_resource, - "Output", - sGraphGresource.getGraphOutputNode(), - "GraphAnimOutput")); - - THEN( - "AnimData from output gets blended and result is written to " - "Output.") { - AnimGraph anim_graph = sGraphGresource.createInstance(); - - Blend2Node* blend2_node = - dynamic_cast(anim_graph.m_nodes[blend2_node_index]); - - AnimData* graph_input0 = - (AnimData*)anim_graph.getInput("GraphAnimInput0"); - REQUIRE(graph_input0 == blend2_node->i_input0); - REQUIRE( - anim_graph.m_nodes[1] - == anim_graph.getAnimNodeForInput(blend2_node_index, "Input0")); - - AnimData* graph_input1 = - (AnimData*)anim_graph.getInput("GraphAnimInput1"); - REQUIRE(graph_input1 == blend2_node->i_input1); - REQUIRE( - anim_graph.m_nodes[1] - == anim_graph.getAnimNodeForInput(blend2_node_index, "Input1")); - - AnimData* graph_output = - (AnimData*)anim_graph.getOutput("GraphAnimOutput"); - REQUIRE(graph_output == blend2_node->o_output); - REQUIRE( - anim_graph.m_nodes[blend2_node_index] - == anim_graph.getAnimNodeForInput(0, "GraphAnimOutput")); - } - } - } - - WHEN("Adding AnimSampler Nodes") { - size_t blend2_node_index = - sGraphGresource.addNode(AnimNodeResourceFactory("Blend2")); - size_t sampler_node_index = - sGraphGresource.addNode(AnimNodeResourceFactory("AnimSampler")); - size_t speed_scale_node_index = - sGraphGresource.addNode(AnimNodeResourceFactory("SpeedScale")); - - AnimNodeResource& blend2_node_resource = - sGraphGresource.m_nodes[blend2_node_index]; - AnimNodeResource& sampler_node_resource = - sGraphGresource.m_nodes[sampler_node_index]; - AnimNodeResource& speed_scale_node_resource = - sGraphGresource.m_nodes[speed_scale_node_index]; - - REQUIRE(sGraphGresource.connectSockets( - sGraphGresource.getGraphInputNode(), - "GraphFloatInput", - blend2_node_resource, - "Weight")); - - REQUIRE(sGraphGresource.connectSockets( - sGraphGresource.getGraphInputNode(), - "SpeedScaleInput", - speed_scale_node_resource, - "SpeedScale")); - - REQUIRE(sGraphGresource.connectSockets( - sGraphGresource.getGraphInputNode(), - "GraphAnimInput0", - blend2_node_resource, - "Input0")); - - REQUIRE(sGraphGresource.connectSockets( - sampler_node_resource, - "Output", - speed_scale_node_resource, - "Input")); - - REQUIRE(sGraphGresource.connectSockets( - speed_scale_node_resource, - "Output", - blend2_node_resource, - "Input1")); - - REQUIRE(sGraphGresource.connectSockets( - blend2_node_resource, - "Output", - sGraphGresource.getGraphOutputNode(), - "GraphAnimOutput")); - - THEN("Data flow and node ordering must be correct.") { - AnimGraph anim_graph = sGraphGresource.createInstance(); - Blend2Node* blend2_node = - dynamic_cast(anim_graph.m_nodes[blend2_node_index]); - SpeedScaleNode* speed_scale_node = dynamic_cast( - anim_graph.m_nodes[speed_scale_node_index]); - AnimSamplerNode* sampler_node = dynamic_cast( - anim_graph.m_nodes[sampler_node_index]); - - // - // check connectivity - // - AnimData* graph_input0 = - (AnimData*)anim_graph.getInput("GraphAnimInput0"); - REQUIRE(graph_input0 == blend2_node->i_input0); - REQUIRE( - anim_graph.m_nodes[1] - == anim_graph.getAnimNodeForInput(blend2_node_index, "Input0")); - - AnimData* graph_input1 = - (AnimData*)anim_graph.getInput("GraphAnimInput1"); - REQUIRE(graph_input1 == nullptr); - - REQUIRE(sampler_node->o_output == speed_scale_node->i_input); - REQUIRE( - sampler_node - == anim_graph.getAnimNodeForInput(speed_scale_node_index, "Input")); - - REQUIRE(speed_scale_node->o_output == blend2_node->i_input1); - REQUIRE( - speed_scale_node - == anim_graph.getAnimNodeForInput(blend2_node_index, "Input1")); - - AnimData* graph_output = - (AnimData*)anim_graph.getOutput("GraphAnimOutput"); - REQUIRE(graph_output == blend2_node->o_output); - REQUIRE( - anim_graph.m_nodes[blend2_node_index] - == anim_graph.getAnimNodeForInput(0, "GraphAnimOutput")); - - // - // check ordering - // - REQUIRE( - anim_graph.getNodeEvalOrderIndex(blend2_node) - < anim_graph.getNodeEvalOrderIndex(sampler_node)); - REQUIRE( - anim_graph.getNodeEvalOrderIndex(blend2_node) - < anim_graph.getNodeEvalOrderIndex(speed_scale_node)); - REQUIRE( - anim_graph.getNodeEvalOrderIndex(speed_scale_node) - < anim_graph.getNodeEvalOrderIndex(sampler_node)); - } - - WHEN("Instantiating graph") { - AnimGraph anim_graph = sGraphGresource.createInstance(); - float* blend_weight_input = - reinterpret_cast(anim_graph.getInput("GraphFloatInput")); - - Blend2Node* blend2_node = - dynamic_cast(anim_graph.m_nodes[blend2_node_index]); - SpeedScaleNode* speed_scale_node = dynamic_cast( - anim_graph.m_nodes[speed_scale_node_index]); - AnimSamplerNode* sampler_node = dynamic_cast( - anim_graph.m_nodes[sampler_node_index]); - - WHEN("Setting weight to 0. and marking nodes active.") { - *blend_weight_input = 0.; - anim_graph.markActiveNodes(); - - THEN("Speed scale and sampler node are inactive") { - REQUIRE(anim_graph.checkIsNodeActive(speed_scale_node) == false); - REQUIRE(anim_graph.checkIsNodeActive(sampler_node) == false); - } - } - - WHEN("Setting weight to 0. and marking nodes active") { - *blend_weight_input = 0.1; - anim_graph.markActiveNodes(); - - THEN("Speed scale and sampler nodes are active") { - REQUIRE(anim_graph.checkIsNodeActive(speed_scale_node) == true); - REQUIRE(anim_graph.checkIsNodeActive(sampler_node) == true); - } - } - - WHEN("Setting weight to 1. and marking nodes active") { - *blend_weight_input = 1.0; - anim_graph.markActiveNodes(); - - THEN("Speed scale and sampler nodes are active") { - REQUIRE(anim_graph.checkIsNodeActive(speed_scale_node) == true); - REQUIRE(anim_graph.checkIsNodeActive(sampler_node) == true); - } - } - - WHEN("Updating time with dt = 0.3f and speed scale = 1.0f") { - float* speed_scale_input = - reinterpret_cast(anim_graph.getInput("SpeedScaleInput")); - - *blend_weight_input = 0.1; - *speed_scale_input = 1.0f; - - anim_graph.markActiveNodes(); - anim_graph.updateTime(0.3f); - - THEN ("Anim sampler node time now must be 0.3f") { - REQUIRE(sampler_node->m_time_now == Approx(0.3f)); - } - } - - WHEN("Updating time with dt = 0.3f and speed scale = 1.3f") { - float* speed_scale_input = - reinterpret_cast(anim_graph.getInput("SpeedScaleInput")); - - *blend_weight_input = 0.1; - *speed_scale_input = 1.3f; - - anim_graph.markActiveNodes(); - anim_graph.updateTime(0.3f); - - THEN ("Anim sampler node time now must be 0.39f") { - REQUIRE(sampler_node->m_time_now == Approx(0.39f)); - } - } - } - } -} - - */ \ No newline at end of file +*/ \ No newline at end of file