// // Created by martin on 25.03.22. // #ifndef ANIMTESTBED_ANIMGRAPH_H #define ANIMTESTBED_ANIMGRAPH_H #include "AnimGraphData.h" #include "AnimGraphNodes.h" struct AnimDataWorkBuffer { struct AnimDataList { AnimData* m_anim_data = nullptr; AnimDataList* next = nullptr; }; AnimDataList* m_anim_data_list = nullptr; size_t m_num_allocations = 0; ~AnimDataWorkBuffer() { AnimDataList* list_node = m_anim_data_list; while (list_node != nullptr) { AnimDataList* current_node = list_node; list_node = list_node->next; //delete current_node->m_anim_data; current_node->m_anim_data = nullptr; delete current_node; } } AnimData* allocate(AnimGraphContext& graph_context) { if (m_anim_data_list == nullptr) { AnimData* result = new AnimData(); result->m_local_matrices.resize(graph_context.m_skeleton->num_soa_joints()); m_num_allocations++; return result; } AnimData* result = m_anim_data_list->m_anim_data; m_anim_data_list = m_anim_data_list->next; delete m_anim_data_list; return result; } void free(AnimData* anim_data) { AnimDataList* list_node = new AnimDataList; list_node->next = m_anim_data_list; list_node->m_anim_data = anim_data; m_anim_data_list = list_node; } size_t size() { size_t result = 0; AnimDataList* node = m_anim_data_list; while (node != nullptr) { result ++; node = node->next; } return result; } }; // // AnimGraph (Runtime) // struct AnimGraph { AnimData m_local_transforms; std::vector m_nodes; std::vector m_eval_ordered_nodes; std::vector > m_node_input_connections; std::vector > m_node_output_connections; NodeSocketAccessorBase* m_socket_accessor; char* m_input_buffer = nullptr; char* m_output_buffer = nullptr; std::vector& getGraphOutputs() { return m_socket_accessor->m_inputs; } std::vector& getGraphInputs() { return m_socket_accessor->m_outputs; } AnimDataWorkBuffer m_anim_data_work_buffer; ~AnimGraph() { delete[] m_input_buffer; delete[] m_output_buffer; for (int i = 0; i < m_nodes.size(); i++) { delete m_nodes[i]; } delete m_socket_accessor; } bool init(AnimGraphContext& context); void updateOrderedNodes(); void updateOrderedNodesRecursive(int node_index); void markActiveNodes(); bool checkIsNodeActive(AnimNode* node) { return node->m_state != AnimNodeEvalState::Deactivated; } void evalInputNode(); void prepareNodeEval(AnimGraphContext& graph_context, size_t node_index); void finishNodeEval(size_t node_index); void evalOutputNode(); void evalSyncTracks(); void updateTime(float dt); void evaluate(AnimGraphContext& context); void reset() { for (size_t i = 0, n = m_nodes.size(); i < n; i++) { m_nodes[i]->m_time_now = 0.f; m_nodes[i]->m_time_last = 0.f; m_nodes[i]->m_state = AnimNodeEvalState::Undefined; } } Socket* getInputSocket(const std::string& name); Socket* getOutputSocket(const std::string& name); const Socket* getInputSocket(const std::string& name) const; const Socket* getOutputSocket(const std::string& name) const; void* getInputPtr(const std::string& name) const { const Socket* input_socket = getInputSocket(name); if (input_socket != nullptr) { return input_socket->m_reference.ptr; } return nullptr; } void* getOutputPtr(const std::string& name) const { const Socket* input_socket = getOutputSocket(name); if (input_socket != nullptr) { return input_socket->m_reference.ptr; } return nullptr; } int getNodeEvalOrderIndex(const AnimNode* node) { for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) { if (m_eval_ordered_nodes[i] == node) { return i; } } return -1; } const AnimNode* getAnimNodeForInput ( size_t node_index, const std::string& input_name) const { assert(node_index < m_nodes.size()); const std::vector& input_connection = m_node_input_connections[node_index]; for (size_t i = 0, n = input_connection.size(); i < n; i++) { if (input_connection[i].m_target_socket.m_name == input_name) { return input_connection[i].m_source_node; } } return nullptr; } AnimNode* getAnimNode(const char* name) { for (size_t i = 0; i < m_nodes.size(); i++) { if (m_nodes[i]->m_name == name) { return m_nodes[i]; } } return nullptr; } size_t getAnimNodeIndex (AnimNode* node) { for (size_t i = 0; i < m_nodes.size(); i++) { if (m_nodes[i] == node) { return i; } } return -1; } }; #endif //ANIMTESTBED_ANIMGRAPH_H