Evaluation of very simple graphs works.
parent
e38c0b4934
commit
08283d9bcf
|
@ -49,6 +49,27 @@ struct AnimGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_node_input_connections.clear();
|
||||||
|
|
||||||
|
if (m_node_output_connections.size() > 0) {
|
||||||
|
std::vector<AnimGraphConnection>& 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<AnimData*>(
|
||||||
|
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_input_buffer;
|
||||||
delete[] m_output_buffer;
|
delete[] m_output_buffer;
|
||||||
|
@ -56,6 +77,7 @@ struct AnimGraph {
|
||||||
for (int i = 0; i < m_nodes.size(); i++) {
|
for (int i = 0; i < m_nodes.size(); i++) {
|
||||||
delete m_nodes[i];
|
delete m_nodes[i];
|
||||||
}
|
}
|
||||||
|
m_nodes.clear();
|
||||||
|
|
||||||
delete m_socket_accessor;
|
delete m_socket_accessor;
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,10 +416,10 @@ inline void NodeSocketAccessorBase::SetSocketValue<const bool&>(
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void NodeSocketAccessorBase::SetSocketValue<const float&>(
|
inline void NodeSocketAccessorBase::SetSocketValue<float>(
|
||||||
Socket* socket,
|
Socket* socket,
|
||||||
const float& value) {
|
float value) {
|
||||||
socket->m_value.float_value = value;
|
*static_cast<float*>(socket->m_reference.ptr) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
|
@ -85,7 +85,7 @@ void AnimGraphEditorRenderSidebar(
|
||||||
if (property.m_type == SocketType::SocketTypeFloat) {
|
if (property.m_type == SocketType::SocketTypeFloat) {
|
||||||
ImGui::SliderFloat(
|
ImGui::SliderFloat(
|
||||||
property.m_name.c_str(),
|
property.m_name.c_str(),
|
||||||
reinterpret_cast<float*>(property.m_reference.ptr),
|
reinterpret_cast<float*>(&property.m_value.float_value),
|
||||||
-100.f,
|
-100.f,
|
||||||
100.f);
|
100.f);
|
||||||
} else if (property.m_type == SocketType::SocketTypeBool) {
|
} else if (property.m_type == SocketType::SocketTypeBool) {
|
||||||
|
@ -219,6 +219,10 @@ void AnimGraphEditorUpdate() {
|
||||||
node_type_name = "MathFloatToVec3Node";
|
node_type_name = "MathFloatToVec3Node";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("ConstScalarNode")) {
|
||||||
|
node_type_name = "ConstScalarNode";
|
||||||
|
}
|
||||||
|
|
||||||
if (node_type_name != "") {
|
if (node_type_name != "") {
|
||||||
AnimNodeResource node_resource =
|
AnimNodeResource node_resource =
|
||||||
AnimNodeResourceFactory(node_type_name);
|
AnimNodeResourceFactory(node_type_name);
|
||||||
|
|
|
@ -65,6 +65,8 @@ bool AnimSamplerNode::Init(AnimGraphContext& context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
archive >> *m_animation;
|
||||||
|
|
||||||
context.m_animation_map[m_filename] = m_animation;
|
context.m_animation_map[m_filename] = m_animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,6 +197,11 @@ struct AnimSamplerNode : public AnimNode {
|
||||||
|
|
||||||
virtual ~AnimSamplerNode();
|
virtual ~AnimSamplerNode();
|
||||||
virtual bool Init(AnimGraphContext& context) override;
|
virtual bool Init(AnimGraphContext& context) override;
|
||||||
|
void UpdateTime(float time_last, float time_now) override {
|
||||||
|
m_time_last = time_last;
|
||||||
|
m_time_now = fmodf(time_last + (time_now - time_last), m_animation->duration());
|
||||||
|
m_state = AnimNodeEvalState::TimeUpdated;
|
||||||
|
}
|
||||||
virtual void Evaluate(AnimGraphContext& context) override;
|
virtual void Evaluate(AnimGraphContext& context) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,6 +215,27 @@ struct NodeSocketAccessor<AnimSamplerNode> : public NodeSocketAccessorBase {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ConstScalarNode
|
||||||
|
//
|
||||||
|
struct ConstScalarNode : public AnimNode {
|
||||||
|
float* o_value = nullptr;
|
||||||
|
float value = 0.f;
|
||||||
|
|
||||||
|
virtual void Evaluate(AnimGraphContext& context){
|
||||||
|
*o_value = value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct NodeSocketAccessor<ConstScalarNode> : public NodeSocketAccessorBase {
|
||||||
|
NodeSocketAccessor(AnimNode* node_) {
|
||||||
|
ConstScalarNode* node = dynamic_cast<ConstScalarNode*>(node_);
|
||||||
|
RegisterOutput("ScalarOutput", &node->o_value);
|
||||||
|
RegisterProperty("ScalarValue", &node->value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// MathAddNode
|
// MathAddNode
|
||||||
//
|
//
|
||||||
|
@ -236,7 +262,6 @@ struct NodeSocketAccessor<MathAddNode> : public NodeSocketAccessorBase {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// MathFloatToVec3Node
|
// MathFloatToVec3Node
|
||||||
//
|
//
|
||||||
|
@ -282,6 +307,8 @@ static inline AnimNode* AnimNodeFactory(const std::string& name) {
|
||||||
result = new MathAddNode;
|
result = new MathAddNode;
|
||||||
} else if (name == "MathFloatToVec3Node") {
|
} else if (name == "MathFloatToVec3Node") {
|
||||||
result = new MathFloatToVec3Node;
|
result = new MathFloatToVec3Node;
|
||||||
|
} else if (name == "ConstScalarNode") {
|
||||||
|
result = new ConstScalarNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != nullptr) {
|
if (result != nullptr) {
|
||||||
|
@ -308,6 +335,8 @@ static inline NodeSocketAccessorBase* AnimNodeAccessorFactory(
|
||||||
return new NodeSocketAccessor<MathAddNode>(node);
|
return new NodeSocketAccessor<MathAddNode>(node);
|
||||||
} else if (node_type_name == "MathFloatToVec3Node") {
|
} else if (node_type_name == "MathFloatToVec3Node") {
|
||||||
return new NodeSocketAccessor<MathFloatToVec3Node>(node);
|
return new NodeSocketAccessor<MathFloatToVec3Node>(node);
|
||||||
|
} else if (node_type_name == "ConstScalarNode") {
|
||||||
|
return new NodeSocketAccessor<ConstScalarNode>(node);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Invalid node type name " << node_type_name << "."
|
std::cerr << "Invalid node type name " << node_type_name << "."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
|
@ -534,7 +534,7 @@ void AnimGraphResource::setRuntimeNodeProperties(AnimGraph& instance) const {
|
||||||
property.m_value.flag);
|
property.m_value.flag);
|
||||||
break;
|
break;
|
||||||
case SocketType::SocketTypeFloat:
|
case SocketType::SocketTypeFloat:
|
||||||
node_instance_accessor->SetPropertyReferenceValue(
|
node_instance_accessor->SetPropertyValue(
|
||||||
name,
|
name,
|
||||||
property.m_value.float_value);
|
property.m_value.float_value);
|
||||||
break;
|
break;
|
||||||
|
|
37
src/main.cc
37
src/main.cc
|
@ -383,6 +383,7 @@ int main() {
|
||||||
|
|
||||||
AnimGraph anim_graph;
|
AnimGraph anim_graph;
|
||||||
AnimGraphContext anim_graph_context;
|
AnimGraphContext anim_graph_context;
|
||||||
|
AnimData* anim_graph_output = nullptr;
|
||||||
|
|
||||||
state.time.factor = 1.0f;
|
state.time.factor = 1.0f;
|
||||||
|
|
||||||
|
@ -505,15 +506,15 @@ int main() {
|
||||||
&gApplicationConfig.window_size[0],
|
&gApplicationConfig.window_size[0],
|
||||||
&gApplicationConfig.window_size[1]);
|
&gApplicationConfig.window_size[1]);
|
||||||
|
|
||||||
|
state.time.frame = stm_sec(
|
||||||
|
stm_round_to_common_refresh_rate(stm_laptime(&state.time.laptime)));
|
||||||
|
|
||||||
if (!state.time.paused) {
|
if (!state.time.paused) {
|
||||||
state.time.frame = stm_sec(
|
|
||||||
stm_round_to_common_refresh_rate(stm_laptime(&state.time.laptime)));
|
|
||||||
|
|
||||||
state.time.absolute += state.time.frame * state.time.factor;
|
state.time.absolute += state.time.frame * state.time.factor;
|
||||||
|
}
|
||||||
|
|
||||||
if (state.ozz.animation != nullptr) {
|
if (state.ozz.animation != nullptr) {
|
||||||
state.time.absolute = fmodf (state.time.absolute, state.ozz.animation->duration());
|
state.time.absolute = fmodf (state.time.absolute, state.ozz.animation->duration());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cur_width, cur_height;
|
int cur_width, cur_height;
|
||||||
|
@ -616,9 +617,20 @@ int main() {
|
||||||
|
|
||||||
if (ImGui::Button("Update Runtime Graph")) {
|
if (ImGui::Button("Update Runtime Graph")) {
|
||||||
anim_graph.dealloc();
|
anim_graph.dealloc();
|
||||||
|
anim_graph_output = nullptr;
|
||||||
|
|
||||||
AnimGraphEditorGetRuntimeGraph(anim_graph);
|
AnimGraphEditorGetRuntimeGraph(anim_graph);
|
||||||
anim_graph_context.m_skeleton = &skinned_mesh.m_skeleton;
|
anim_graph_context.m_skeleton = &skinned_mesh.m_skeleton;
|
||||||
anim_graph.init(anim_graph_context);
|
anim_graph.init(anim_graph_context);
|
||||||
|
|
||||||
|
// For simplicity use first animation data output
|
||||||
|
const std::vector<Socket>& graph_output_sockets = anim_graph.getGraphOutputs();
|
||||||
|
for (int i = 0; i < graph_output_sockets.size(); i++) {
|
||||||
|
const Socket& output = graph_output_sockets[i];
|
||||||
|
if (output.m_type == SocketType::SocketTypeAnimation) {
|
||||||
|
anim_graph_output = static_cast<AnimData*>(output.m_reference.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
|
@ -711,6 +723,11 @@ int main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Step")) {
|
||||||
|
state.time.absolute += state.time.frame;
|
||||||
|
}
|
||||||
|
|
||||||
if (state.ozz.animation != nullptr) {
|
if (state.ozz.animation != nullptr) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
@ -741,6 +758,14 @@ int main() {
|
||||||
skinned_mesh.CalcModelMatrices();
|
skinned_mesh.CalcModelMatrices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.time.use_graph && anim_graph.m_nodes.size() > 0) {
|
||||||
|
anim_graph.updateTime(state.time.frame);
|
||||||
|
anim_graph.evaluate(anim_graph_context);
|
||||||
|
skinned_mesh.m_local_matrices = anim_graph_output->m_local_matrices;
|
||||||
|
|
||||||
|
skinned_mesh.CalcModelMatrices();
|
||||||
|
}
|
||||||
|
|
||||||
sgl_defaults();
|
sgl_defaults();
|
||||||
sgl_matrix_mode_projection();
|
sgl_matrix_mode_projection();
|
||||||
sgl_load_matrix((const float*)&state.camera.mtxProj);
|
sgl_load_matrix((const float*)&state.camera.mtxProj);
|
||||||
|
|
Loading…
Reference in New Issue