Working on graph evaluations. WIP.
This commit is contained in:
+27
-17
@@ -13,6 +13,18 @@ bool AnimGraph::init(AnimGraphContext& context) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<AnimGraphConnection>& 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<AnimData*>(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());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -56,7 +68,7 @@ void AnimGraph::markActiveNodes() {
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
||||
for (size_t i = m_eval_ordered_nodes.size() - 1; i > 0; i--) {
|
||||
AnimNode* node = m_eval_ordered_nodes[i];
|
||||
if (checkIsNodeActive(node)) {
|
||||
int node_index = node->m_index;
|
||||
@@ -78,7 +90,9 @@ void AnimGraph::markActiveNodes() {
|
||||
}
|
||||
}
|
||||
|
||||
void AnimGraph::prepareNodeEval(size_t node_index) {
|
||||
void AnimGraph::prepareNodeEval(
|
||||
AnimGraphContext& graph_context,
|
||||
size_t node_index) {
|
||||
for (size_t i = 0, n = m_node_output_connections[node_index].size(); i < n;
|
||||
i++) {
|
||||
AnimGraphConnection& output_connection =
|
||||
@@ -88,9 +102,10 @@ void AnimGraph::prepareNodeEval(size_t node_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert (*output_connection.m_source_socket.m_reference.ptr_ptr == nullptr);
|
||||
|
||||
(*output_connection.m_source_socket.m_reference.ptr_ptr) =
|
||||
m_anim_data_work_buffer.peek();
|
||||
m_anim_data_work_buffer.pop();
|
||||
m_anim_data_work_buffer.allocate(graph_context);
|
||||
}
|
||||
|
||||
for (size_t i = 0, n = m_node_input_connections[node_index].size(); i < n;
|
||||
@@ -117,13 +132,12 @@ void AnimGraph::finishNodeEval(size_t node_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_anim_data_work_buffer.push(
|
||||
static_cast<AnimData*>(input_connection.m_source_socket.m_reference.ptr));
|
||||
m_anim_data_work_buffer.free(static_cast<AnimData*>(
|
||||
input_connection.m_source_socket.m_reference.ptr));
|
||||
(*input_connection.m_source_socket.m_reference.ptr_ptr) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AnimGraph::evalInputNode() {
|
||||
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
||||
AnimGraphConnection& graph_input_connection =
|
||||
@@ -154,7 +168,11 @@ void AnimGraph::evalOutputNode() {
|
||||
graph_output_connection.m_source_socket.m_reference.ptr,
|
||||
graph_output_connection.m_target_socket.m_type_size);
|
||||
} else {
|
||||
// TODO: how to deal with anim data outputs?
|
||||
AnimData* source_data = static_cast<AnimData*>(
|
||||
*graph_output_connection.m_source_socket.m_reference.ptr_ptr);
|
||||
AnimData* target_data = static_cast<AnimData*>(
|
||||
graph_output_connection.m_target_socket.m_reference.ptr);
|
||||
target_data->m_local_matrices = source_data->m_local_matrices;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,14 +226,6 @@ void AnimGraph::updateTime(float dt) {
|
||||
}
|
||||
|
||||
void AnimGraph::evaluate(AnimGraphContext& context) {
|
||||
constexpr int eval_stack_size = 5;
|
||||
int eval_stack_index = eval_stack_size;
|
||||
AnimData eval_buffers[eval_stack_size];
|
||||
AnimData* eval_stack[eval_stack_size];
|
||||
for (size_t i = 0; i < eval_stack_size; i++) {
|
||||
eval_stack[i] = &eval_buffers[i];
|
||||
}
|
||||
|
||||
for (int i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
||||
AnimNode* node = m_eval_ordered_nodes[i];
|
||||
|
||||
@@ -223,7 +233,7 @@ void AnimGraph::evaluate(AnimGraphContext& context) {
|
||||
continue;
|
||||
}
|
||||
|
||||
prepareNodeEval(node->m_index);
|
||||
prepareNodeEval(context, node->m_index);
|
||||
|
||||
node->Evaluate(context);
|
||||
|
||||
|
||||
+54
-17
@@ -9,30 +9,57 @@
|
||||
#include "AnimGraphNodes.h"
|
||||
|
||||
struct AnimDataWorkBuffer {
|
||||
std::vector<AnimData> m_eval_anim_data;
|
||||
std::vector<AnimData*> m_available_data;
|
||||
struct AnimDataList {
|
||||
AnimData* m_anim_data = nullptr;
|
||||
AnimDataList* next = nullptr;
|
||||
};
|
||||
|
||||
AnimDataWorkBuffer(size_t stack_size) {
|
||||
m_eval_anim_data.resize(stack_size);
|
||||
m_available_data.resize(stack_size);
|
||||
AnimDataList* m_anim_data_list = nullptr;
|
||||
size_t m_num_allocations = 0;
|
||||
|
||||
for (size_t i = 0; i < stack_size; i++) {
|
||||
m_available_data[i] = &m_eval_anim_data[i];
|
||||
~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;
|
||||
}
|
||||
}
|
||||
|
||||
void push(AnimData* anim_data) {
|
||||
assert (m_available_data.size() < m_eval_anim_data.size());
|
||||
m_available_data.push_back(anim_data);
|
||||
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 pop() {
|
||||
assert (m_available_data.size() > 0);
|
||||
m_available_data.pop_back();
|
||||
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;
|
||||
}
|
||||
|
||||
AnimData* peek() {
|
||||
return m_available_data.back();
|
||||
size_t size() {
|
||||
size_t result = 0;
|
||||
|
||||
AnimDataList* node = m_anim_data_list;
|
||||
while (node != nullptr) {
|
||||
result ++;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,7 +80,7 @@ struct AnimGraph {
|
||||
std::vector<Socket>& getGraphOutputs() { return m_socket_accessor->m_inputs; }
|
||||
std::vector<Socket>& getGraphInputs() { return m_socket_accessor->m_outputs; }
|
||||
|
||||
AnimDataWorkBuffer m_anim_data_work_buffer = AnimDataWorkBuffer(5);
|
||||
AnimDataWorkBuffer m_anim_data_work_buffer;
|
||||
|
||||
~AnimGraph() {
|
||||
delete[] m_input_buffer;
|
||||
@@ -76,7 +103,7 @@ struct AnimGraph {
|
||||
}
|
||||
|
||||
void evalInputNode();
|
||||
void prepareNodeEval(size_t node_index);
|
||||
void prepareNodeEval(AnimGraphContext& graph_context, size_t node_index);
|
||||
void finishNodeEval(size_t node_index);
|
||||
void evalOutputNode();
|
||||
|
||||
@@ -106,6 +133,16 @@ struct AnimGraph {
|
||||
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) {
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "SyncTrack.h"
|
||||
#include "ozz/base/containers/vector.h"
|
||||
#include <ozz/base/maths/soa_transform.h>
|
||||
#include "ozz/animation/runtime/skeleton.h"
|
||||
#include "ozz/animation/runtime/animation.h"
|
||||
|
||||
//
|
||||
// Data types
|
||||
@@ -24,6 +26,18 @@ struct AnimGraph;
|
||||
struct AnimGraphContext {
|
||||
AnimGraph* m_graph = nullptr;
|
||||
ozz::animation::Skeleton* m_skeleton = nullptr;
|
||||
|
||||
typedef std::map<std::string, ozz::animation::Animation*> AnimationFileMap;
|
||||
AnimationFileMap m_animation_map;
|
||||
|
||||
void freeAnimations() {
|
||||
AnimationFileMap::iterator animation_map_iter = m_animation_map.begin();
|
||||
|
||||
while (animation_map_iter != m_animation_map.end()) {
|
||||
delete animation_map_iter->second;
|
||||
animation_map_iter++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct AnimData {
|
||||
@@ -66,7 +80,7 @@ struct Socket {
|
||||
void* ptr;
|
||||
void** ptr_ptr;
|
||||
};
|
||||
SocketReference m_reference;
|
||||
SocketReference m_reference = { 0 };
|
||||
int m_flags = 0;
|
||||
size_t m_type_size = 0;
|
||||
};
|
||||
|
||||
@@ -33,39 +33,43 @@ void Blend2Node::Evaluate(AnimGraphContext& context) {
|
||||
if (!blend_job.Run()) {
|
||||
ozz::log::Err() << "Error blending animations." << std::endl;
|
||||
}
|
||||
bool m_sync_blend = false;
|
||||
}
|
||||
|
||||
//
|
||||
// AnimSamplerNode
|
||||
//
|
||||
AnimSamplerNode::~AnimSamplerNode() noexcept {
|
||||
delete m_animation;
|
||||
m_animation = nullptr;
|
||||
}
|
||||
|
||||
bool AnimSamplerNode::Init(AnimGraphContext& context) {
|
||||
assert (m_animation == nullptr);
|
||||
m_animation = new ozz::animation::Animation();
|
||||
|
||||
assert(m_filename.size() != 0);
|
||||
ozz::io::File file(m_filename.c_str(), "rb");
|
||||
if (!file.opened()) {
|
||||
ozz::log::Err() << "Failed to open animation file " << m_filename << "."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
ozz::io::IArchive archive(&file);
|
||||
if (!archive.TestTag<ozz::animation::Animation>()) {
|
||||
ozz::log::Err() << "Failed to load animation instance from file "
|
||||
<< m_filename << "." << std::endl;
|
||||
return false;
|
||||
|
||||
AnimGraphContext::AnimationFileMap::const_iterator animation_map_iter;
|
||||
animation_map_iter = context.m_animation_map.find(m_filename);
|
||||
if (animation_map_iter != context.m_animation_map.end()) {
|
||||
m_animation = animation_map_iter->second;
|
||||
} else {
|
||||
m_animation = new ozz::animation::Animation();
|
||||
ozz::io::File file(m_filename.c_str(), "rb");
|
||||
if (!file.opened()) {
|
||||
ozz::log::Err() << "Failed to open animation file " << m_filename << "."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
ozz::io::IArchive archive(&file);
|
||||
if (!archive.TestTag<ozz::animation::Animation>()) {
|
||||
ozz::log::Err() << "Failed to load animation instance from file "
|
||||
<< m_filename << "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
context.m_animation_map[m_filename] = m_animation;
|
||||
}
|
||||
|
||||
assert (context.m_skeleton != nullptr);
|
||||
const int num_soa_joints = context.m_skeleton->num_soa_joints();
|
||||
const int num_joints = context.m_skeleton->num_joints();
|
||||
m_sampling_cache.Resize(num_joints);
|
||||
m_sampling_cache.Resize(context.m_skeleton->num_joints());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -486,8 +486,9 @@ void AnimGraphResource::connectRuntimeNodes(AnimGraph& instance) const {
|
||||
//
|
||||
// Wire up outputs to inputs.
|
||||
//
|
||||
(*target_socket->m_reference.ptr_ptr) = source_socket->m_reference.ptr;
|
||||
// (*source_socket->m_reference.ptr_ptr) = target_socket->m_reference.ptr;
|
||||
if (target_socket->m_type != SocketType::SocketTypeAnimation) {
|
||||
(*target_socket->m_reference.ptr_ptr) = source_socket->m_reference.ptr;
|
||||
}
|
||||
|
||||
size_t target_node_index = target_node->m_index;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user