Working on graph evaluations. WIP.
parent
b518220576
commit
2da07ef961
|
@ -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;
|
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];
|
AnimNode* node = m_eval_ordered_nodes[i];
|
||||||
if (checkIsNodeActive(node)) {
|
if (checkIsNodeActive(node)) {
|
||||||
int node_index = node->m_index;
|
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;
|
for (size_t i = 0, n = m_node_output_connections[node_index].size(); i < n;
|
||||||
i++) {
|
i++) {
|
||||||
AnimGraphConnection& output_connection =
|
AnimGraphConnection& output_connection =
|
||||||
|
@ -88,9 +102,10 @@ void AnimGraph::prepareNodeEval(size_t node_index) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert (*output_connection.m_source_socket.m_reference.ptr_ptr == nullptr);
|
||||||
|
|
||||||
(*output_connection.m_source_socket.m_reference.ptr_ptr) =
|
(*output_connection.m_source_socket.m_reference.ptr_ptr) =
|
||||||
m_anim_data_work_buffer.peek();
|
m_anim_data_work_buffer.allocate(graph_context);
|
||||||
m_anim_data_work_buffer.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0, n = m_node_input_connections[node_index].size(); i < n;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_anim_data_work_buffer.push(
|
m_anim_data_work_buffer.free(static_cast<AnimData*>(
|
||||||
static_cast<AnimData*>(input_connection.m_source_socket.m_reference.ptr));
|
input_connection.m_source_socket.m_reference.ptr));
|
||||||
(*input_connection.m_source_socket.m_reference.ptr_ptr) = nullptr;
|
(*input_connection.m_source_socket.m_reference.ptr_ptr) = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AnimGraph::evalInputNode() {
|
void AnimGraph::evalInputNode() {
|
||||||
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
||||||
AnimGraphConnection& graph_input_connection =
|
AnimGraphConnection& graph_input_connection =
|
||||||
|
@ -154,7 +168,11 @@ void AnimGraph::evalOutputNode() {
|
||||||
graph_output_connection.m_source_socket.m_reference.ptr,
|
graph_output_connection.m_source_socket.m_reference.ptr,
|
||||||
graph_output_connection.m_target_socket.m_type_size);
|
graph_output_connection.m_target_socket.m_type_size);
|
||||||
} else {
|
} 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) {
|
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++) {
|
for (int i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
||||||
AnimNode* node = m_eval_ordered_nodes[i];
|
AnimNode* node = m_eval_ordered_nodes[i];
|
||||||
|
|
||||||
|
@ -223,7 +233,7 @@ void AnimGraph::evaluate(AnimGraphContext& context) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareNodeEval(node->m_index);
|
prepareNodeEval(context, node->m_index);
|
||||||
|
|
||||||
node->Evaluate(context);
|
node->Evaluate(context);
|
||||||
|
|
||||||
|
|
|
@ -9,30 +9,57 @@
|
||||||
#include "AnimGraphNodes.h"
|
#include "AnimGraphNodes.h"
|
||||||
|
|
||||||
struct AnimDataWorkBuffer {
|
struct AnimDataWorkBuffer {
|
||||||
std::vector<AnimData> m_eval_anim_data;
|
struct AnimDataList {
|
||||||
std::vector<AnimData*> m_available_data;
|
AnimData* m_anim_data = nullptr;
|
||||||
|
AnimDataList* next = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
AnimDataWorkBuffer(size_t stack_size) {
|
AnimDataList* m_anim_data_list = nullptr;
|
||||||
m_eval_anim_data.resize(stack_size);
|
size_t m_num_allocations = 0;
|
||||||
m_available_data.resize(stack_size);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < stack_size; i++) {
|
~AnimDataWorkBuffer() {
|
||||||
m_available_data[i] = &m_eval_anim_data[i];
|
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) {
|
AnimData* allocate(AnimGraphContext& graph_context) {
|
||||||
assert (m_available_data.size() < m_eval_anim_data.size());
|
if (m_anim_data_list == nullptr) {
|
||||||
m_available_data.push_back(anim_data);
|
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() {
|
void free(AnimData* anim_data) {
|
||||||
assert (m_available_data.size() > 0);
|
AnimDataList* list_node = new AnimDataList;
|
||||||
m_available_data.pop_back();
|
list_node->next = m_anim_data_list;
|
||||||
|
list_node->m_anim_data = anim_data;
|
||||||
|
m_anim_data_list = list_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimData* peek() {
|
size_t size() {
|
||||||
return m_available_data.back();
|
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>& getGraphOutputs() { return m_socket_accessor->m_inputs; }
|
||||||
std::vector<Socket>& getGraphInputs() { return m_socket_accessor->m_outputs; }
|
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() {
|
~AnimGraph() {
|
||||||
delete[] m_input_buffer;
|
delete[] m_input_buffer;
|
||||||
|
@ -76,7 +103,7 @@ struct AnimGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
void evalInputNode();
|
void evalInputNode();
|
||||||
void prepareNodeEval(size_t node_index);
|
void prepareNodeEval(AnimGraphContext& graph_context, size_t node_index);
|
||||||
void finishNodeEval(size_t node_index);
|
void finishNodeEval(size_t node_index);
|
||||||
void evalOutputNode();
|
void evalOutputNode();
|
||||||
|
|
||||||
|
@ -106,6 +133,16 @@ struct AnimGraph {
|
||||||
return nullptr;
|
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) {
|
int getNodeEvalOrderIndex(const AnimNode* node) {
|
||||||
for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
for (size_t i = 0, n = m_eval_ordered_nodes.size(); i < n; i++) {
|
||||||
if (m_eval_ordered_nodes[i] == node) {
|
if (m_eval_ordered_nodes[i] == node) {
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "SyncTrack.h"
|
#include "SyncTrack.h"
|
||||||
#include "ozz/base/containers/vector.h"
|
#include "ozz/base/containers/vector.h"
|
||||||
#include <ozz/base/maths/soa_transform.h>
|
#include <ozz/base/maths/soa_transform.h>
|
||||||
#include "ozz/animation/runtime/skeleton.h"
|
#include "ozz/animation/runtime/skeleton.h"
|
||||||
|
#include "ozz/animation/runtime/animation.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Data types
|
// Data types
|
||||||
|
@ -24,6 +26,18 @@ struct AnimGraph;
|
||||||
struct AnimGraphContext {
|
struct AnimGraphContext {
|
||||||
AnimGraph* m_graph = nullptr;
|
AnimGraph* m_graph = nullptr;
|
||||||
ozz::animation::Skeleton* m_skeleton = 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 {
|
struct AnimData {
|
||||||
|
@ -66,7 +80,7 @@ struct Socket {
|
||||||
void* ptr;
|
void* ptr;
|
||||||
void** ptr_ptr;
|
void** ptr_ptr;
|
||||||
};
|
};
|
||||||
SocketReference m_reference;
|
SocketReference m_reference = { 0 };
|
||||||
int m_flags = 0;
|
int m_flags = 0;
|
||||||
size_t m_type_size = 0;
|
size_t m_type_size = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,39 +33,43 @@ void Blend2Node::Evaluate(AnimGraphContext& context) {
|
||||||
if (!blend_job.Run()) {
|
if (!blend_job.Run()) {
|
||||||
ozz::log::Err() << "Error blending animations." << std::endl;
|
ozz::log::Err() << "Error blending animations." << std::endl;
|
||||||
}
|
}
|
||||||
bool m_sync_blend = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// AnimSamplerNode
|
// AnimSamplerNode
|
||||||
//
|
//
|
||||||
AnimSamplerNode::~AnimSamplerNode() noexcept {
|
AnimSamplerNode::~AnimSamplerNode() noexcept {
|
||||||
delete m_animation;
|
|
||||||
m_animation = nullptr;
|
m_animation = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AnimSamplerNode::Init(AnimGraphContext& context) {
|
bool AnimSamplerNode::Init(AnimGraphContext& context) {
|
||||||
assert (m_animation == nullptr);
|
assert (m_animation == nullptr);
|
||||||
m_animation = new ozz::animation::Animation();
|
|
||||||
|
|
||||||
assert(m_filename.size() != 0);
|
assert(m_filename.size() != 0);
|
||||||
ozz::io::File file(m_filename.c_str(), "rb");
|
|
||||||
if (!file.opened()) {
|
AnimGraphContext::AnimationFileMap::const_iterator animation_map_iter;
|
||||||
ozz::log::Err() << "Failed to open animation file " << m_filename << "."
|
animation_map_iter = context.m_animation_map.find(m_filename);
|
||||||
<< std::endl;
|
if (animation_map_iter != context.m_animation_map.end()) {
|
||||||
return false;
|
m_animation = animation_map_iter->second;
|
||||||
}
|
} else {
|
||||||
ozz::io::IArchive archive(&file);
|
m_animation = new ozz::animation::Animation();
|
||||||
if (!archive.TestTag<ozz::animation::Animation>()) {
|
ozz::io::File file(m_filename.c_str(), "rb");
|
||||||
ozz::log::Err() << "Failed to load animation instance from file "
|
if (!file.opened()) {
|
||||||
<< m_filename << "." << std::endl;
|
ozz::log::Err() << "Failed to open animation file " << m_filename << "."
|
||||||
return false;
|
<< 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);
|
assert (context.m_skeleton != nullptr);
|
||||||
const int num_soa_joints = context.m_skeleton->num_soa_joints();
|
m_sampling_cache.Resize(context.m_skeleton->num_joints());
|
||||||
const int num_joints = context.m_skeleton->num_joints();
|
|
||||||
m_sampling_cache.Resize(num_joints);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,8 +486,9 @@ void AnimGraphResource::connectRuntimeNodes(AnimGraph& instance) const {
|
||||||
//
|
//
|
||||||
// Wire up outputs to inputs.
|
// Wire up outputs to inputs.
|
||||||
//
|
//
|
||||||
(*target_socket->m_reference.ptr_ptr) = source_socket->m_reference.ptr;
|
if (target_socket->m_type != SocketType::SocketTypeAnimation) {
|
||||||
// (*source_socket->m_reference.ptr_ptr) = target_socket->m_reference.ptr;
|
(*target_socket->m_reference.ptr_ptr) = source_socket->m_reference.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
size_t target_node_index = target_node->m_index;
|
size_t target_node_index = target_node->m_index;
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct SimpleAnimFixture {
|
||||||
bone0_translations.push_back(translation_key);
|
bone0_translations.push_back(translation_key);
|
||||||
|
|
||||||
translation_key.time = 1.f;
|
translation_key.time = 1.f;
|
||||||
translation_key.value = ozz::math::Float3(1.f, 6.f, 9.f);
|
translation_key.value = ozz::math::Float3(1.f, 0.f, 9.f);
|
||||||
bone0_translations.push_back(translation_key);
|
bone0_translations.push_back(translation_key);
|
||||||
|
|
||||||
bone0_track.translations = bone0_translations;
|
bone0_track.translations = bone0_translations;
|
||||||
|
@ -119,3 +119,85 @@ TEST_CASE_METHOD(
|
||||||
CHECK(
|
CHECK(
|
||||||
sampled_translation.z[0] == Approx(translation_key.value.z).margin(0.01));
|
sampled_translation.z[0] == Approx(translation_key.value.z).margin(0.01));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(
|
||||||
|
SimpleAnimFixture,
|
||||||
|
"AnimGraphSimpleEval",
|
||||||
|
"[AnimGraphEvalTests]") {
|
||||||
|
AnimGraphResource graph_resource;
|
||||||
|
|
||||||
|
// Add nodes
|
||||||
|
size_t trans_x_node_index =
|
||||||
|
graph_resource.addNode(AnimNodeResourceFactory("AnimSampler"));
|
||||||
|
size_t trans_y_node_index =
|
||||||
|
graph_resource.addNode(AnimNodeResourceFactory("AnimSampler"));
|
||||||
|
size_t blend_node_index =
|
||||||
|
graph_resource.addNode(AnimNodeResourceFactory("Blend2"));
|
||||||
|
|
||||||
|
// 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_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_name = "trans_y";
|
||||||
|
|
||||||
|
AnimNodeResource& blend_node = graph_resource.m_nodes[blend_node_index];
|
||||||
|
blend_node.m_name = "BlendWalkRun";
|
||||||
|
|
||||||
|
// Setup graph outputs and inputs
|
||||||
|
AnimNodeResource& graph_output_node = graph_resource.getGraphOutputNode();
|
||||||
|
graph_output_node.m_socket_accessor->RegisterInput<AnimData>("GraphOutput", nullptr);
|
||||||
|
|
||||||
|
AnimNodeResource& graph_input_node =
|
||||||
|
graph_resource.getGraphInputNode();
|
||||||
|
graph_input_node.m_socket_accessor->RegisterOutput<float>(
|
||||||
|
"GraphFloatInput",
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
// Wire up nodes
|
||||||
|
graph_resource.connectSockets(trans_x_node, "Output", blend_node, "Input0");
|
||||||
|
graph_resource.connectSockets(trans_y_node, "Output", blend_node, "Input1");
|
||||||
|
graph_resource.connectSockets(
|
||||||
|
blend_node,
|
||||||
|
"Output",
|
||||||
|
graph_resource.getGraphOutputNode(),
|
||||||
|
"GraphOutput");
|
||||||
|
REQUIRE(graph_resource.connectSockets(graph_input_node, "GraphFloatInput", blend_node, "Weight"));
|
||||||
|
|
||||||
|
// Prepare animation maps
|
||||||
|
AnimGraphContext graph_context;
|
||||||
|
graph_context.m_skeleton = skeleton.get();
|
||||||
|
graph_context.m_animation_map["trans_x"] = animation_translate_x.get();
|
||||||
|
graph_context.m_animation_map["trans_y"] = animation_translate_y.get();
|
||||||
|
|
||||||
|
// Instantiate graph
|
||||||
|
AnimGraph graph = graph_resource.createInstance();
|
||||||
|
graph_context.m_graph = &graph;
|
||||||
|
graph.init(graph_context);
|
||||||
|
|
||||||
|
// Get runtime graph inputs and outputs
|
||||||
|
float* graph_float_input = nullptr;
|
||||||
|
graph_float_input =
|
||||||
|
static_cast<float*>(graph.getInputPtr("GraphFloatInput"));
|
||||||
|
|
||||||
|
Socket* anim_output_socket =
|
||||||
|
graph.getOutputSocket("GraphOutput");
|
||||||
|
|
||||||
|
AnimData* graph_anim_output = static_cast<AnimData*>(graph.getOutputPtr("GraphOutput"));
|
||||||
|
|
||||||
|
// Evaluate graph
|
||||||
|
*graph_float_input = 0.1f;
|
||||||
|
|
||||||
|
graph.markActiveNodes();
|
||||||
|
CHECK(graph.m_nodes[trans_x_node_index]->m_state == AnimNodeEvalState::Activated);
|
||||||
|
CHECK(graph.m_nodes[trans_y_node_index]->m_state == AnimNodeEvalState::Activated);
|
||||||
|
CHECK(graph.m_nodes[blend_node_index]->m_state == AnimNodeEvalState::Activated);
|
||||||
|
|
||||||
|
graph.updateTime(0.5f);
|
||||||
|
graph.evaluate(graph_context);
|
||||||
|
|
||||||
|
CHECK(graph_anim_output->m_local_matrices[0].translation.x[0] == Approx(0.5).margin(0.1));
|
||||||
|
CHECK(graph_anim_output->m_local_matrices[0].translation.y[0] == Approx(0.05).margin(0.01));
|
||||||
|
}
|
|
@ -129,23 +129,31 @@ TEST_CASE("BasicGraph", "[AnimGraphResource]") {
|
||||||
REQUIRE(anim_sampler_run->m_animation != nullptr);
|
REQUIRE(anim_sampler_run->m_animation != nullptr);
|
||||||
|
|
||||||
WHEN("Emulating Graph Evaluation") {
|
WHEN("Emulating Graph Evaluation") {
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 5);
|
CHECK(graph.m_anim_data_work_buffer.size() == 0);
|
||||||
graph.prepareNodeEval(walk_node_index);
|
graph.prepareNodeEval(graph_context, walk_node_index);
|
||||||
graph.finishNodeEval(walk_node_index);
|
graph.finishNodeEval(walk_node_index);
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 4);
|
CHECK(graph.m_anim_data_work_buffer.m_num_allocations == 1);
|
||||||
graph.prepareNodeEval(run_node_index);
|
CHECK(graph.m_anim_data_work_buffer.size() == 0);
|
||||||
|
|
||||||
|
graph.prepareNodeEval(graph_context, run_node_index);
|
||||||
graph.finishNodeEval(run_node_index);
|
graph.finishNodeEval(run_node_index);
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 3);
|
CHECK(graph.m_anim_data_work_buffer.m_num_allocations == 2);
|
||||||
graph.prepareNodeEval(blend_node_index);
|
CHECK(graph.m_anim_data_work_buffer.size() == 0);
|
||||||
|
|
||||||
|
graph.prepareNodeEval(graph_context, blend_node_index);
|
||||||
CHECK(blend2_instance->i_input0 == anim_sampler_walk->o_output);
|
CHECK(blend2_instance->i_input0 == anim_sampler_walk->o_output);
|
||||||
CHECK(blend2_instance->i_input1 == anim_sampler_run->o_output);
|
CHECK(blend2_instance->i_input1 == anim_sampler_run->o_output);
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 2);
|
CHECK(graph.m_anim_data_work_buffer.m_num_allocations == 3);
|
||||||
|
CHECK(graph.m_anim_data_work_buffer.size() == 0);
|
||||||
|
|
||||||
graph.finishNodeEval(blend_node_index);
|
graph.finishNodeEval(blend_node_index);
|
||||||
CHECK(anim_sampler_walk->o_output == nullptr);
|
CHECK(anim_sampler_walk->o_output == nullptr);
|
||||||
CHECK(anim_sampler_run->o_output == nullptr);
|
CHECK(anim_sampler_run->o_output == nullptr);
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 4);
|
CHECK(graph.m_anim_data_work_buffer.m_num_allocations == 3);
|
||||||
|
CHECK(graph.m_anim_data_work_buffer.size() == 2);
|
||||||
|
|
||||||
graph.prepareNodeEval(0);
|
// TODO: rethink output node evaluation
|
||||||
|
graph.prepareNodeEval(graph_context, 0);
|
||||||
const Socket* graph_output_socket = graph.getOutputSocket("GraphOutput");
|
const Socket* graph_output_socket = graph.getOutputSocket("GraphOutput");
|
||||||
CHECK(blend2_instance->o_output == (*graph_output_socket->m_reference.ptr_ptr));
|
CHECK(blend2_instance->o_output == (*graph_output_socket->m_reference.ptr_ptr));
|
||||||
AnimData* graph_output =
|
AnimData* graph_output =
|
||||||
|
@ -153,8 +161,11 @@ TEST_CASE("BasicGraph", "[AnimGraphResource]") {
|
||||||
graph.finishNodeEval(0);
|
graph.finishNodeEval(0);
|
||||||
CHECK(blend2_instance->o_output == nullptr);
|
CHECK(blend2_instance->o_output == nullptr);
|
||||||
CHECK(graph_output == (*graph_output_socket->m_reference.ptr_ptr));
|
CHECK(graph_output == (*graph_output_socket->m_reference.ptr_ptr));
|
||||||
CHECK(graph.m_anim_data_work_buffer.m_available_data.size() == 5);
|
CHECK(graph.m_anim_data_work_buffer.m_num_allocations == 3);
|
||||||
|
CHECK(graph.m_anim_data_work_buffer.size() == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
graph_context.freeAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") {
|
TEST_CASE("InputAttributeConversion", "[AnimGraphResource]") {
|
||||||
|
@ -282,7 +293,8 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") {
|
||||||
*graph_float_input = 123.456f;
|
*graph_float_input = 123.456f;
|
||||||
|
|
||||||
AND_WHEN("Evaluating Graph") {
|
AND_WHEN("Evaluating Graph") {
|
||||||
AnimGraphContext context = {&anim_graph, nullptr};
|
AnimGraphContext context;
|
||||||
|
context.m_graph = &anim_graph;
|
||||||
|
|
||||||
anim_graph.updateTime(0.f);
|
anim_graph.updateTime(0.f);
|
||||||
anim_graph.evaluate(context);
|
anim_graph.evaluate(context);
|
||||||
|
@ -299,6 +311,8 @@ TEST_CASE("ResourceSaveLoadMathGraphInputs", "[AnimGraphResource]") {
|
||||||
CHECK(vec3_output[1] == *graph_float_input);
|
CHECK(vec3_output[1] == *graph_float_input);
|
||||||
CHECK(vec3_output[2] == *graph_float_input);
|
CHECK(vec3_output[2] == *graph_float_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.freeAnimations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,7 +428,8 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") {
|
||||||
*graph_float_input = 123.456f;
|
*graph_float_input = 123.456f;
|
||||||
|
|
||||||
AND_WHEN("Evaluating Graph") {
|
AND_WHEN("Evaluating Graph") {
|
||||||
AnimGraphContext context = {&anim_graph, nullptr};
|
AnimGraphContext context;
|
||||||
|
context.m_graph = &anim_graph;
|
||||||
|
|
||||||
anim_graph.updateTime(0.f);
|
anim_graph.updateTime(0.f);
|
||||||
anim_graph.evaluate(context);
|
anim_graph.evaluate(context);
|
||||||
|
@ -442,6 +457,8 @@ TEST_CASE("SimpleMathEvaluations", "[AnimGraphResource]") {
|
||||||
CHECK(float1_output == Approx(*graph_float_input * 2.));
|
CHECK(float1_output == Approx(*graph_float_input * 2.));
|
||||||
CHECK(float2_output == Approx(*graph_float_input * 3.));
|
CHECK(float2_output == Approx(*graph_float_input * 3.));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.freeAnimations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue