New evaluation scheme.
- Animation Data are always referenced via a pointer in nodes. - Animation Data storage pointers are injected from graph when node is evaluated. - Node value outputs always stored in node. - Node value inputs always referenced via pointer. References are created when instantiating the graph.
This commit is contained in:
+104
-55
@@ -5,39 +5,20 @@
|
||||
#include "AnimGraph.h"
|
||||
|
||||
void AnimGraph::updateOrderedNodes() {
|
||||
std::vector<int> node_index_stack;
|
||||
node_index_stack.push_back(0);
|
||||
|
||||
m_eval_ordered_nodes.clear();
|
||||
updateOrderedNodesRecursive(0);
|
||||
}
|
||||
|
||||
while (node_index_stack.size() > 0) {
|
||||
std::vector<NodeInput>& node_inputs =
|
||||
m_node_inputs[node_index_stack.back()];
|
||||
node_index_stack.pop_back();
|
||||
|
||||
for (size_t i = 0, n = node_inputs.size(); i < n; i++) {
|
||||
AnimNode* input_node = node_inputs[i].m_node;
|
||||
if (input_node == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int input_node_index = input_node->m_index;
|
||||
bool is_node_processed = false;
|
||||
for (size_t j = 0, m = m_eval_ordered_nodes.size(); j < m; j++) {
|
||||
if (m_eval_ordered_nodes[j] == input_node) {
|
||||
is_node_processed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_node_processed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_eval_ordered_nodes.push_back(input_node);
|
||||
node_index_stack.push_back(input_node_index);
|
||||
}
|
||||
void AnimGraph::updateOrderedNodesRecursive(int node_index) {
|
||||
AnimNode* node = m_nodes[node_index];
|
||||
const std::vector<AnimGraphConnection> 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);
|
||||
updateOrderedNodesRecursive(input_node_index);
|
||||
}
|
||||
|
||||
m_eval_ordered_nodes.push_back(node);
|
||||
}
|
||||
|
||||
void AnimGraph::markActiveNodes() {
|
||||
@@ -45,10 +26,10 @@ void AnimGraph::markActiveNodes() {
|
||||
m_nodes[i]->m_state = AnimNodeEvalState::Deactivated;
|
||||
}
|
||||
|
||||
const std::vector<NodeInput> graph_output_inputs = m_node_inputs[0];
|
||||
const std::vector<AnimGraphConnection>& graph_output_inputs = m_node_input_connections[0];
|
||||
for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) {
|
||||
const NodeInput& graph_input = graph_output_inputs[i];
|
||||
AnimNode* node = graph_input.m_node;
|
||||
const AnimGraphConnection& graph_input = graph_output_inputs[i];
|
||||
AnimNode* node = graph_input.m_source_node;
|
||||
if (node != nullptr) {
|
||||
node->m_state = AnimNodeEvalState::Activated;
|
||||
}
|
||||
@@ -58,19 +39,69 @@ void AnimGraph::markActiveNodes() {
|
||||
AnimNode* node = m_eval_ordered_nodes[i];
|
||||
if (checkIsNodeActive(node)) {
|
||||
int node_index = node->m_index;
|
||||
node->MarkActiveInputs(m_node_inputs[node_index]);
|
||||
node->MarkActiveInputs(m_node_input_connections[node_index]);
|
||||
|
||||
// Non-animation data inputs are always active.
|
||||
for (size_t j = 0, nj = m_node_inputs[node_index].size(); j < nj; j++) {
|
||||
const NodeInput& input = m_node_inputs[node_index][j];
|
||||
if (input.m_node != nullptr && input.m_type != SocketType::SocketTypeAnimation) {
|
||||
input.m_node->m_state = AnimNodeEvalState::Activated;
|
||||
for (size_t j = 0, nj = m_node_input_connections[node_index].size(); j < nj; j++) {
|
||||
const AnimGraphConnection& input = m_node_input_connections[node_index][j];
|
||||
if (input.m_source_node != nullptr
|
||||
&& input.m_target_socket.m_type != SocketType::SocketTypeAnimation) {
|
||||
input.m_source_node->m_state = AnimNodeEvalState::Activated;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimGraph::prepareNodeEval(size_t node_index) {
|
||||
AnimNode* node = m_nodes[node_index];
|
||||
|
||||
for (size_t i = 0, n = m_node_output_connections[node_index].size(); i < n;
|
||||
i++) {
|
||||
AnimGraphConnection& output_connection =
|
||||
m_node_output_connections[node_index][i];
|
||||
if (output_connection.m_source_socket.m_type
|
||||
!= SocketType::SocketTypeAnimation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(*output_connection.m_source_socket.m_value.ptr_ptr) =
|
||||
m_anim_data_work_buffer.peek();
|
||||
m_anim_data_work_buffer.pop();
|
||||
}
|
||||
|
||||
for (size_t i = 0, n = m_node_input_connections[node_index].size(); i < n;
|
||||
i++) {
|
||||
AnimGraphConnection& input_connection =
|
||||
m_node_input_connections[node_index][i];
|
||||
if (input_connection.m_source_socket.m_type
|
||||
!= SocketType::SocketTypeAnimation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(*input_connection.m_target_socket.m_value.ptr_ptr) =
|
||||
(*input_connection.m_source_socket.m_value.ptr_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimGraph::finishNodeEval(size_t node_index) {
|
||||
AnimNode* node = m_nodes[node_index];
|
||||
|
||||
for (size_t i = 0, n = m_node_input_connections[node_index].size(); i < n;
|
||||
i++) {
|
||||
AnimGraphConnection& input_connection =
|
||||
m_node_input_connections[node_index][i];
|
||||
if (input_connection.m_source_socket.m_type
|
||||
!= SocketType::SocketTypeAnimation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_anim_data_work_buffer.push(
|
||||
static_cast<AnimData*>(input_connection.m_source_socket.m_value.ptr));
|
||||
(*input_connection.m_source_socket.m_value.ptr_ptr) = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimGraph::evalSyncTracks() {
|
||||
for (size_t i = m_eval_ordered_nodes.size() - 1; i >= 0; i--) {
|
||||
AnimNode* node = m_eval_ordered_nodes[i];
|
||||
@@ -79,12 +110,12 @@ void AnimGraph::evalSyncTracks() {
|
||||
continue;
|
||||
}
|
||||
|
||||
node->CalcSyncTrack(m_node_inputs[node_index]);
|
||||
node->CalcSyncTrack(m_node_input_connections[node_index]);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimGraph::updateTime(float dt) {
|
||||
const std::vector<NodeInput> graph_output_inputs = m_node_inputs[0];
|
||||
const std::vector<AnimGraphConnection> graph_output_inputs = m_node_input_connections[0];
|
||||
for (size_t i = 0, n = graph_output_inputs.size(); i < n; i++) {
|
||||
AnimNode* node = m_eval_ordered_nodes[i];
|
||||
if (node != nullptr) {
|
||||
@@ -99,17 +130,16 @@ void AnimGraph::updateTime(float dt) {
|
||||
}
|
||||
|
||||
int node_index = node->m_index;
|
||||
const std::vector<NodeInput> node_inputs =
|
||||
m_node_inputs[node_index];
|
||||
const std::vector<AnimGraphConnection> node_input_connections = m_node_input_connections[node_index];
|
||||
float node_time_now = node->m_time_now;
|
||||
float node_time_last = node->m_time_last;
|
||||
|
||||
for (size_t i = 0, n = node_inputs.size(); i < n; i++) {
|
||||
AnimNode* input_node = node_inputs[i].m_node;
|
||||
for (size_t i = 0, n = node_input_connections.size(); i < n; i++) {
|
||||
AnimNode* input_node = node_input_connections[i].m_source_node;
|
||||
|
||||
// Only propagate time updates via animation sockets.
|
||||
if (input_node != nullptr
|
||||
&& node_inputs[i].m_type == SocketType::SocketTypeAnimation
|
||||
&& node_input_connections[i].m_target_socket.m_type == SocketType::SocketTypeAnimation
|
||||
&& input_node->m_state == AnimNodeEvalState::Activated) {
|
||||
input_node->UpdateTime(node_time_last, node_time_now);
|
||||
}
|
||||
@@ -118,30 +148,49 @@ void AnimGraph::updateTime(float dt) {
|
||||
}
|
||||
|
||||
void AnimGraph::evaluate() {
|
||||
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 (size_t i = m_eval_ordered_nodes.size() - 1; i >= 0; i--) {
|
||||
AnimNode* node = m_eval_ordered_nodes[i];
|
||||
|
||||
if (node->m_state == AnimNodeEvalState::Deactivated) {
|
||||
continue;
|
||||
}
|
||||
|
||||
prepareNodeEval(node->m_index);
|
||||
|
||||
node->Evaluate();
|
||||
|
||||
finishNodeEval(node->m_index);
|
||||
}
|
||||
}
|
||||
|
||||
void* AnimGraph::getOutput(const std::string& name) const {
|
||||
Socket* socket = m_socket_accessor->FindInputSocket(name);
|
||||
if (socket == nullptr) {
|
||||
return nullptr;
|
||||
Socket* AnimGraph::getInputSocket(const std::string& name) {
|
||||
Socket* socket = nullptr;
|
||||
for (size_t i = 0, n = m_node_output_connections[1].size(); i < n; i++) {
|
||||
AnimGraphConnection& connection = m_node_output_connections[1][i];
|
||||
if (connection.m_target_socket.m_name == name) {
|
||||
return &connection.m_target_socket;
|
||||
}
|
||||
}
|
||||
|
||||
return socket->m_value.ptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* AnimGraph::getInput(const std::string& name) const {
|
||||
Socket* socket = m_socket_accessor->FindOutputSocket(name);
|
||||
if (socket == nullptr) {
|
||||
return nullptr;
|
||||
Socket* AnimGraph::getOutputSocket(const std::string& name) {
|
||||
Socket* socket = nullptr;
|
||||
for (size_t i = 0, n = m_node_input_connections[0].size(); i < n; i++) {
|
||||
AnimGraphConnection& connection = m_node_input_connections[0][i];
|
||||
if (connection.m_target_socket.m_name == name) {
|
||||
return &connection.m_target_socket;
|
||||
}
|
||||
}
|
||||
|
||||
return *(socket->m_value.ptr_ptr);
|
||||
return nullptr;
|
||||
}
|
||||
Reference in New Issue
Block a user