Compare commits
4 Commits
1870a9d214
...
86ea476881
Author | SHA1 | Date | |
---|---|---|---|
![]() |
86ea476881 | ||
![]() |
f52b19a8d2 | ||
![]() |
283306f225 | ||
![]() |
b4eda31242 |
@ -15,9 +15,9 @@ bool AnimGraphBlendTree::Init(AnimGraphContext& context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_animdata_blocks.size(); i++) {
|
for (size_t i = 0; i < m_pose_blocks.size(); i++) {
|
||||||
int num_soa_joints = context.m_skeleton->num_soa_joints();
|
int num_soa_joints = context.m_skeleton->num_soa_joints();
|
||||||
m_animdata_blocks[i]->m_local_matrices.resize(num_soa_joints);
|
m_pose_blocks[i]->m_local_matrices.resize(num_soa_joints);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
// AnimGraph (Runtime)
|
// AnimGraph (Runtime)
|
||||||
//
|
//
|
||||||
struct AnimGraphBlendTree : public AnimNode {
|
struct AnimGraphBlendTree : public AnimNode {
|
||||||
AnimData m_local_transforms;
|
|
||||||
|
|
||||||
std::vector<AnimNode*> m_nodes;
|
std::vector<AnimNode*> m_nodes;
|
||||||
std::vector<AnimNode*> m_eval_ordered_nodes;
|
std::vector<AnimNode*> m_eval_ordered_nodes;
|
||||||
std::vector<std::vector<AnimGraphConnection> > m_node_input_connections;
|
std::vector<std::vector<AnimGraphConnection> > m_node_input_connections;
|
||||||
@ -30,15 +28,17 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
return m_node_input_connections[0];
|
return m_node_input_connections[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AnimData*> m_animdata_blocks;
|
std::vector<Pose*> m_pose_blocks;
|
||||||
NodeDescriptorBase* m_node_descriptor = nullptr;
|
NodeDescriptorBase* m_node_descriptor = nullptr;
|
||||||
char* m_input_buffer = nullptr;
|
char* m_input_buffer = nullptr;
|
||||||
char* m_output_buffer = nullptr;
|
char* m_output_buffer = nullptr;
|
||||||
char* m_connection_data_storage = nullptr;
|
char* m_connection_data_storage = nullptr;
|
||||||
char* m_const_node_inputs = nullptr;
|
char* m_const_node_inputs = nullptr;
|
||||||
|
|
||||||
std::vector<Socket>& GetGraphOutputs() { return m_node_descriptor->m_inputs; }
|
std::vector<Socket>& GetGraphOutputs() {
|
||||||
std::vector<Socket>& GetGraphInputs() { return m_node_descriptor->m_outputs; }
|
return m_node_descriptor->m_outputs;
|
||||||
|
}
|
||||||
|
std::vector<Socket>& GetGraphInputs() { return m_node_descriptor->m_inputs; }
|
||||||
|
|
||||||
AnimDataAllocator m_anim_data_allocator;
|
AnimDataAllocator m_anim_data_allocator;
|
||||||
|
|
||||||
@ -48,6 +48,13 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
|
|
||||||
// AnimNode overrides
|
// AnimNode overrides
|
||||||
bool Init(AnimGraphContext& context) override;
|
bool Init(AnimGraphContext& context) override;
|
||||||
|
|
||||||
|
/// Determines which nodes in the BlendTree are active.
|
||||||
|
///
|
||||||
|
/// Note: this does not use the provided input_connections, instead it marks
|
||||||
|
/// all nodes directly connected to the BlendTree outputs as active and then
|
||||||
|
/// propagates the node state throught the tree. For this each active node's
|
||||||
|
/// AnimNode::MarkActiveInputs() gets called.
|
||||||
void MarkActiveInputs(
|
void MarkActiveInputs(
|
||||||
const std::vector<AnimGraphConnection>& input_connections) override;
|
const std::vector<AnimGraphConnection>& input_connections) override;
|
||||||
void CalcSyncTrack(
|
void CalcSyncTrack(
|
||||||
@ -58,10 +65,10 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
void PropagateTimeToNodeInputs(const AnimNode* node);
|
void PropagateTimeToNodeInputs(const AnimNode* node);
|
||||||
|
|
||||||
void dealloc() {
|
void dealloc() {
|
||||||
for (size_t i = 0; i < m_animdata_blocks.size(); i++) {
|
for (size_t i = 0; i < m_pose_blocks.size(); i++) {
|
||||||
m_animdata_blocks[i]->m_local_matrices.vector::~vector();
|
m_pose_blocks[i]->m_local_matrices.vector::~vector();
|
||||||
}
|
}
|
||||||
m_animdata_blocks.clear();
|
m_pose_blocks.clear();
|
||||||
|
|
||||||
m_node_input_connections.clear();
|
m_node_input_connections.clear();
|
||||||
m_node_output_connections.clear();
|
m_node_output_connections.clear();
|
||||||
@ -93,7 +100,7 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the address that is used for the specified AnimGraph input Socket.
|
/** Sets the address that is used for the specified BlendTree input Socket.
|
||||||
*
|
*
|
||||||
* @tparam T Type of the Socket.
|
* @tparam T Type of the Socket.
|
||||||
* @param name Name of the Socket.
|
* @param name Name of the Socket.
|
||||||
@ -101,7 +108,7 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SetInput(const char* name, T* value_ptr) {
|
void SetInput(const char* name, T* value_ptr) {
|
||||||
m_node_descriptor->SetOutput(name, value_ptr);
|
m_node_descriptor->SetInput(name, value_ptr);
|
||||||
|
|
||||||
std::vector<size_t> connected_node_indices;
|
std::vector<size_t> connected_node_indices;
|
||||||
|
|
||||||
@ -115,7 +122,7 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the address that is used for the specified AnimGraph output Socket.
|
/** Sets the address that is used for the specified BlendTree output Socket.
|
||||||
*
|
*
|
||||||
* We update the pointer of the outputting node. We also have to ensure that
|
* We update the pointer of the outputting node. We also have to ensure that
|
||||||
* all usages of that output use the same pointer.
|
* all usages of that output use the same pointer.
|
||||||
@ -148,6 +155,7 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that all connections that consume the output use the updated address.
|
||||||
size_t output_node_index =
|
size_t output_node_index =
|
||||||
GetAnimNodeIndex(graph_output_connection->m_source_node);
|
GetAnimNodeIndex(graph_output_connection->m_source_node);
|
||||||
|
|
||||||
@ -161,6 +169,12 @@ struct AnimGraphBlendTree : public AnimNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
*graph_output_connection->m_socket.m_reference.ptr_ptr = value_ptr;
|
*graph_output_connection->m_socket.m_reference.ptr_ptr = value_ptr;
|
||||||
|
|
||||||
|
// And additionally update the BlendTree's node descriptor:
|
||||||
|
Socket* blend_tree_output_socket = m_node_descriptor->GetOutputSocket(name);
|
||||||
|
assert(blend_tree_output_socket != nullptr);
|
||||||
|
|
||||||
|
*blend_tree_output_socket->m_reference.ptr_ptr = value_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the address that is used for the specified AnimGraph output Socket.
|
/** Returns the address that is used for the specified AnimGraph output Socket.
|
||||||
|
@ -25,26 +25,26 @@
|
|||||||
struct AnimGraph;
|
struct AnimGraph;
|
||||||
struct AnimNode;
|
struct AnimNode;
|
||||||
|
|
||||||
struct AnimData {
|
struct Pose {
|
||||||
ozz::vector<ozz::math::SoaTransform> m_local_matrices;
|
ozz::vector<ozz::math::SoaTransform> m_local_matrices;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimDataRef {
|
struct AnimDataRef {
|
||||||
AnimData* ptr = nullptr;
|
Pose* ptr = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimDataAllocator {
|
struct AnimDataAllocator {
|
||||||
struct AnimDataList {
|
struct PoseList {
|
||||||
AnimData* m_anim_data = nullptr;
|
Pose* m_anim_data = nullptr;
|
||||||
AnimDataList* next = nullptr;
|
PoseList* next = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::list<AnimData*> m_anim_data_list;
|
std::list<Pose*> m_anim_data_list;
|
||||||
size_t m_num_allocations = 0;
|
size_t m_num_allocations = 0;
|
||||||
|
|
||||||
~AnimDataAllocator() {
|
~AnimDataAllocator() {
|
||||||
while (!m_anim_data_list.empty()) {
|
while (!m_anim_data_list.empty()) {
|
||||||
AnimData* front = m_anim_data_list.front();
|
Pose* front = m_anim_data_list.front();
|
||||||
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
||||||
std::cout << "about to delete with size "
|
std::cout << "about to delete with size "
|
||||||
<< front->m_anim_data->m_local_matrices.size()
|
<< front->m_anim_data->m_local_matrices.size()
|
||||||
@ -55,9 +55,9 @@ struct AnimDataAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimData* allocate(ozz::animation::Skeleton* skeleton) {
|
Pose* allocate(ozz::animation::Skeleton* skeleton) {
|
||||||
if (m_anim_data_list.empty()) {
|
if (m_anim_data_list.empty()) {
|
||||||
AnimData* result = new AnimData();
|
Pose* result = new Pose();
|
||||||
result->m_local_matrices.resize(skeleton->num_soa_joints());
|
result->m_local_matrices.resize(skeleton->num_soa_joints());
|
||||||
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
||||||
std::cout << "Allocated with size " << result->m_local_matrices.size()
|
std::cout << "Allocated with size " << result->m_local_matrices.size()
|
||||||
@ -67,7 +67,7 @@ struct AnimDataAllocator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimData* result = m_anim_data_list.front();
|
Pose* result = m_anim_data_list.front();
|
||||||
m_anim_data_list.pop_front();
|
m_anim_data_list.pop_front();
|
||||||
|
|
||||||
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
||||||
@ -78,7 +78,7 @@ struct AnimDataAllocator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(AnimData* anim_data) {
|
void free(Pose* anim_data) {
|
||||||
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
#ifdef ANIM_DATA_ALLOCATOR_DEBUG
|
||||||
std::cout << "Storing buffer with size "
|
std::cout << "Storing buffer with size "
|
||||||
<< anim_data->m_local_matrices.size() << " " << anim_data
|
<< anim_data->m_local_matrices.size() << " " << anim_data
|
||||||
@ -238,7 +238,7 @@ SocketType GetSocketType() {
|
|||||||
return SocketType::SocketTypeBool;
|
return SocketType::SocketTypeBool;
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::is_same<T, AnimData>::value) {
|
if constexpr (std::is_same<T, Pose>::value) {
|
||||||
return SocketType::SocketTypeAnimation;
|
return SocketType::SocketTypeAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ struct AnimNode;
|
|||||||
// Blend2Node
|
// Blend2Node
|
||||||
//
|
//
|
||||||
struct Blend2Node : public AnimNode {
|
struct Blend2Node : public AnimNode {
|
||||||
AnimData* i_input0 = nullptr;
|
Pose* i_input0 = nullptr;
|
||||||
AnimData* i_input1 = nullptr;
|
Pose* i_input1 = nullptr;
|
||||||
AnimData* o_output = nullptr;
|
Pose* o_output = nullptr;
|
||||||
float* i_blend_weight = nullptr;
|
float* i_blend_weight = nullptr;
|
||||||
bool m_sync_blend = false;
|
bool m_sync_blend = false;
|
||||||
|
|
||||||
@ -33,12 +33,12 @@ struct Blend2Node : public AnimNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (input.m_target_socket_name == "Input0" && *i_blend_weight < 0.999) {
|
if (input.m_target_socket_name == "Input0" && *i_blend_weight < 0.999) {
|
||||||
input_node->m_state = AnimNodeEvalState::Activated;
|
input_node->Activate(m_tick_number);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.m_target_socket_name == "Input1" && *i_blend_weight > 0.001) {
|
if (input.m_target_socket_name == "Input1" && *i_blend_weight > 0.001) {
|
||||||
input_node->m_state = AnimNodeEvalState::Activated;
|
input_node->Activate(m_tick_number);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,6 +59,8 @@ struct NodeDescriptor<Blend2Node> : public NodeDescriptorBase {
|
|||||||
RegisterProperty("Sync", &node->m_sync_blend);
|
RegisterProperty("Sync", &node->m_sync_blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~NodeDescriptor() = default;
|
||||||
|
|
||||||
void UpdateFlags() override {
|
void UpdateFlags() override {
|
||||||
Socket* weight_input_socket = FindSocket("Weight", m_inputs);
|
Socket* weight_input_socket = FindSocket("Weight", m_inputs);
|
||||||
assert(weight_input_socket != nullptr);
|
assert(weight_input_socket != nullptr);
|
||||||
@ -75,8 +77,8 @@ struct NodeDescriptor<Blend2Node> : public NodeDescriptorBase {
|
|||||||
// SpeedScaleNode
|
// SpeedScaleNode
|
||||||
//
|
//
|
||||||
struct SpeedScaleNode : public AnimNode {
|
struct SpeedScaleNode : public AnimNode {
|
||||||
AnimData* i_input = nullptr;
|
Pose* i_input = nullptr;
|
||||||
AnimData* o_output = nullptr;
|
Pose* o_output = nullptr;
|
||||||
float* i_speed_scale = nullptr;
|
float* i_speed_scale = nullptr;
|
||||||
|
|
||||||
void UpdateTime(float time_last, float time_now) override {
|
void UpdateTime(float time_last, float time_now) override {
|
||||||
@ -104,13 +106,15 @@ struct NodeDescriptor<SpeedScaleNode> : public NodeDescriptorBase {
|
|||||||
|
|
||||||
RegisterOutput("Output", &node->o_output);
|
RegisterOutput("Output", &node->o_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~NodeDescriptor() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// AnimSamplerNode
|
// AnimSamplerNode
|
||||||
//
|
//
|
||||||
struct AnimSamplerNode : public AnimNode {
|
struct AnimSamplerNode : public AnimNode {
|
||||||
AnimData* o_output = nullptr;
|
Pose* o_output = nullptr;
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
ozz::animation::SamplingJob::Context m_sampling_context;
|
ozz::animation::SamplingJob::Context m_sampling_context;
|
||||||
ozz::animation::Animation* m_animation = nullptr;
|
ozz::animation::Animation* m_animation = nullptr;
|
||||||
@ -132,14 +136,16 @@ struct NodeDescriptor<AnimSamplerNode> : public NodeDescriptorBase {
|
|||||||
|
|
||||||
RegisterProperty("Filename", &node->m_filename);
|
RegisterProperty("Filename", &node->m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~NodeDescriptor() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// LockTranslationNode
|
// LockTranslationNode
|
||||||
//
|
//
|
||||||
struct LockTranslationNode : public AnimNode {
|
struct LockTranslationNode : public AnimNode {
|
||||||
AnimData* i_input = nullptr;
|
Pose* i_input = nullptr;
|
||||||
AnimData* o_output = nullptr;
|
Pose* o_output = nullptr;
|
||||||
int m_locked_bone_index = 0;
|
int m_locked_bone_index = 0;
|
||||||
bool m_lock_x = false;
|
bool m_lock_x = false;
|
||||||
bool m_lock_y = false;
|
bool m_lock_y = false;
|
||||||
@ -159,6 +165,8 @@ struct NodeDescriptor<LockTranslationNode> : public NodeDescriptorBase {
|
|||||||
RegisterProperty("LockAxisY", &node->m_lock_y);
|
RegisterProperty("LockAxisY", &node->m_lock_y);
|
||||||
RegisterProperty("LockAxisZ", &node->m_lock_z);
|
RegisterProperty("LockAxisZ", &node->m_lock_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~NodeDescriptor() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -177,6 +185,8 @@ struct NodeDescriptor<ConstScalarNode> : public NodeDescriptorBase {
|
|||||||
RegisterOutput("ScalarOutput", &node->o_value);
|
RegisterOutput("ScalarOutput", &node->o_value);
|
||||||
RegisterProperty("ScalarValue", &node->value);
|
RegisterProperty("ScalarValue", &node->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~NodeDescriptor() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -202,6 +212,8 @@ struct NodeDescriptor<MathAddNode> : public NodeDescriptorBase {
|
|||||||
RegisterInput("Input1", &node->i_input1);
|
RegisterInput("Input1", &node->i_input1);
|
||||||
RegisterOutput("Output", &node->o_output);
|
RegisterOutput("Output", &node->o_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~NodeDescriptor() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -232,6 +244,8 @@ struct NodeDescriptor<MathFloatToVec3Node> : public NodeDescriptorBase {
|
|||||||
RegisterInput("Input2", &node->i_input2);
|
RegisterInput("Input2", &node->i_input2);
|
||||||
RegisterOutput("Output", &node->o_output);
|
RegisterOutput("Output", &node->o_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~NodeDescriptor() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimNode* AnimNodeFactory(const std::string& name);
|
AnimNode* AnimNodeFactory(const std::string& name);
|
||||||
|
@ -86,7 +86,7 @@ Socket sJsonToSocket(const json& json_data) {
|
|||||||
}
|
}
|
||||||
} else if (type_string == "Animation") {
|
} else if (type_string == "Animation") {
|
||||||
result.m_type = SocketType::SocketTypeAnimation;
|
result.m_type = SocketType::SocketTypeAnimation;
|
||||||
result.m_type_size = sizeof(AnimData);
|
result.m_type_size = sizeof(Pose);
|
||||||
} else if (type_string == "Int") {
|
} else if (type_string == "Int") {
|
||||||
result.m_type = SocketType::SocketTypeInt;
|
result.m_type = SocketType::SocketTypeInt;
|
||||||
result.m_type_size = sizeof(int);
|
result.m_type_size = sizeof(int);
|
||||||
@ -933,9 +933,9 @@ void BlendTreeResource::CreateBlendTreeRuntimeNodeInstances(
|
|||||||
embedded_blend_tree_resource->CreateBlendTreeInstance(
|
embedded_blend_tree_resource->CreateBlendTreeInstance(
|
||||||
*embedded_blend_tree);
|
*embedded_blend_tree);
|
||||||
embedded_blend_tree_resource->m_virtual_socket_accessor->m_inputs =
|
embedded_blend_tree_resource->m_virtual_socket_accessor->m_inputs =
|
||||||
embedded_blend_tree->m_node_descriptor->m_outputs;
|
|
||||||
embedded_blend_tree_resource->m_virtual_socket_accessor->m_outputs =
|
|
||||||
embedded_blend_tree->m_node_descriptor->m_inputs;
|
embedded_blend_tree->m_node_descriptor->m_inputs;
|
||||||
|
embedded_blend_tree_resource->m_virtual_socket_accessor->m_outputs =
|
||||||
|
embedded_blend_tree->m_node_descriptor->m_outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->m_name = node_resource->m_name;
|
node->m_name = node_resource->m_name;
|
||||||
@ -955,9 +955,9 @@ void BlendTreeResource::PrepareBlendTreeIOData(
|
|||||||
AnimNodeDescriptorFactory("BlendTree", instance.m_nodes[0]);
|
AnimNodeDescriptorFactory("BlendTree", instance.m_nodes[0]);
|
||||||
|
|
||||||
instance.m_node_descriptor->m_outputs =
|
instance.m_node_descriptor->m_outputs =
|
||||||
GetGraphInputNode()->m_virtual_socket_accessor->m_outputs;
|
|
||||||
instance.m_node_descriptor->m_inputs =
|
|
||||||
GetGraphOutputNode()->m_virtual_socket_accessor->m_inputs;
|
GetGraphOutputNode()->m_virtual_socket_accessor->m_inputs;
|
||||||
|
instance.m_node_descriptor->m_inputs =
|
||||||
|
GetGraphInputNode()->m_virtual_socket_accessor->m_outputs;
|
||||||
|
|
||||||
//
|
//
|
||||||
// graph inputs
|
// graph inputs
|
||||||
@ -977,7 +977,7 @@ void BlendTreeResource::PrepareBlendTreeIOData(
|
|||||||
for (int i = 0; i < graph_inputs.size(); i++) {
|
for (int i = 0; i < graph_inputs.size(); i++) {
|
||||||
graph_inputs[i].m_reference.ptr =
|
graph_inputs[i].m_reference.ptr =
|
||||||
(void*)&instance.m_input_buffer[input_block_offset];
|
(void*)&instance.m_input_buffer[input_block_offset];
|
||||||
instance.m_node_descriptor->m_outputs[i].m_reference.ptr =
|
instance.m_node_descriptor->m_inputs[i].m_reference.ptr =
|
||||||
&instance.m_input_buffer[input_block_offset];
|
&instance.m_input_buffer[input_block_offset];
|
||||||
input_block_offset += sizeof(void*);
|
input_block_offset += sizeof(void*);
|
||||||
}
|
}
|
||||||
@ -998,13 +998,18 @@ void BlendTreeResource::PrepareBlendTreeIOData(
|
|||||||
|
|
||||||
int output_block_offset = 0;
|
int output_block_offset = 0;
|
||||||
for (int i = 0; i < graph_outputs.size(); i++) {
|
for (int i = 0; i < graph_outputs.size(); i++) {
|
||||||
instance.m_node_descriptor->m_inputs[i].m_reference.ptr =
|
instance.m_node_descriptor->m_outputs[i].m_reference.ptr =
|
||||||
&instance.m_output_buffer[output_block_offset];
|
&instance.m_output_buffer[output_block_offset];
|
||||||
output_block_offset += sizeof(void*);
|
output_block_offset += sizeof(void*);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// connecton data storage
|
// connection data storage: we reserve memory for the used outputs of all
|
||||||
|
// nodes:
|
||||||
|
// * If a node output does not get used: we do not reserve a memory block.
|
||||||
|
// * If a node output gets used by multiple nodes: we only reserve a single
|
||||||
|
// memory block.
|
||||||
|
// The resulting memory offsets are stored in the node_offset_map.
|
||||||
//
|
//
|
||||||
size_t connection_data_storage_size = 0;
|
size_t connection_data_storage_size = 0;
|
||||||
for (const BlendTreeConnectionResource& connection : GetConnections()) {
|
for (const BlendTreeConnectionResource& connection : GetConnections()) {
|
||||||
@ -1028,6 +1033,61 @@ void BlendTreeResource::PrepareBlendTreeIOData(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlendTreeResource::SetRuntimeNodeProperties(
|
||||||
|
AnimGraphBlendTree& result) const {
|
||||||
|
for (int i = 2; i < GetNumNodes(); i++) {
|
||||||
|
const AnimNodeResource* node_resource = GetNode(i);
|
||||||
|
|
||||||
|
NodeDescriptorBase* node_instance_accessor = AnimNodeDescriptorFactory(
|
||||||
|
node_resource->m_node_type_name,
|
||||||
|
result.m_nodes[i]);
|
||||||
|
|
||||||
|
std::vector<Socket>& resource_properties =
|
||||||
|
node_resource->m_virtual_socket_accessor->m_properties;
|
||||||
|
for (const auto& property : resource_properties) {
|
||||||
|
const std::string& name = property.m_name;
|
||||||
|
|
||||||
|
switch (property.m_type) {
|
||||||
|
case SocketType::SocketTypeBool:
|
||||||
|
node_instance_accessor->SetProperty(
|
||||||
|
name.c_str(),
|
||||||
|
property.m_value.flag);
|
||||||
|
break;
|
||||||
|
case SocketType::SocketTypeInt:
|
||||||
|
node_instance_accessor->SetProperty(
|
||||||
|
name.c_str(),
|
||||||
|
property.m_value.int_value);
|
||||||
|
break;
|
||||||
|
case SocketType::SocketTypeFloat:
|
||||||
|
node_instance_accessor->SetProperty(
|
||||||
|
name.c_str(),
|
||||||
|
property.m_value.float_value);
|
||||||
|
break;
|
||||||
|
case SocketType::SocketTypeVec3:
|
||||||
|
node_instance_accessor->SetProperty<Vec3>(
|
||||||
|
name.c_str(),
|
||||||
|
property.m_value.vec3);
|
||||||
|
break;
|
||||||
|
case SocketType::SocketTypeQuat:
|
||||||
|
node_instance_accessor->SetProperty(
|
||||||
|
name.c_str(),
|
||||||
|
property.m_value.quat);
|
||||||
|
break;
|
||||||
|
case SocketType::SocketTypeString:
|
||||||
|
node_instance_accessor->SetProperty(
|
||||||
|
name.c_str(),
|
||||||
|
property.m_value_string);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
std::cerr << "Invalid socket type "
|
||||||
|
<< static_cast<int>(property.m_type) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete node_instance_accessor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BlendTreeResource::CreateBlendTreeConnectionInstances(
|
void BlendTreeResource::CreateBlendTreeConnectionInstances(
|
||||||
AnimGraphBlendTree& instance,
|
AnimGraphBlendTree& instance,
|
||||||
NodeSocketDataOffsetMap& node_offset_map) const {
|
NodeSocketDataOffsetMap& node_offset_map) const {
|
||||||
@ -1047,9 +1107,10 @@ void BlendTreeResource::CreateBlendTreeConnectionInstances(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance_node_descriptors[0]->m_inputs = instance.m_node_descriptor->m_inputs;
|
instance_node_descriptors[0]->m_inputs =
|
||||||
instance_node_descriptors[1]->m_outputs =
|
|
||||||
instance.m_node_descriptor->m_outputs;
|
instance.m_node_descriptor->m_outputs;
|
||||||
|
instance_node_descriptors[1]->m_outputs =
|
||||||
|
instance.m_node_descriptor->m_inputs;
|
||||||
|
|
||||||
for (const BlendTreeConnectionResource& connection : GetConnections()) {
|
for (const BlendTreeConnectionResource& connection : GetConnections()) {
|
||||||
NodeDescriptorBase* source_node_descriptor =
|
NodeDescriptorBase* source_node_descriptor =
|
||||||
@ -1181,9 +1242,8 @@ void BlendTreeResource::CreateBlendTreeConnectionInstances(
|
|||||||
&instance.m_connection_data_storage[socket_data_offset];
|
&instance.m_connection_data_storage[socket_data_offset];
|
||||||
|
|
||||||
if (source_socket->m_type == SocketType::SocketTypeAnimation) {
|
if (source_socket->m_type == SocketType::SocketTypeAnimation) {
|
||||||
instance.m_animdata_blocks.push_back(
|
instance.m_pose_blocks.push_back(
|
||||||
(AnimData*)(&instance
|
(Pose*)(&instance.m_connection_data_storage[socket_data_offset]));
|
||||||
.m_connection_data_storage[socket_data_offset]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1236,59 +1296,4 @@ void BlendTreeResource::CreateBlendTreeConnectionInstances(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendTreeResource::SetRuntimeNodeProperties(
|
|
||||||
AnimGraphBlendTree& result) const {
|
|
||||||
for (int i = 2; i < GetNumNodes(); i++) {
|
|
||||||
const AnimNodeResource* node_resource = GetNode(i);
|
|
||||||
|
|
||||||
NodeDescriptorBase* node_instance_accessor = AnimNodeDescriptorFactory(
|
|
||||||
node_resource->m_node_type_name,
|
|
||||||
result.m_nodes[i]);
|
|
||||||
|
|
||||||
std::vector<Socket>& resource_properties =
|
|
||||||
node_resource->m_virtual_socket_accessor->m_properties;
|
|
||||||
for (const auto& property : resource_properties) {
|
|
||||||
const std::string& name = property.m_name;
|
|
||||||
|
|
||||||
switch (property.m_type) {
|
|
||||||
case SocketType::SocketTypeBool:
|
|
||||||
node_instance_accessor->SetProperty(
|
|
||||||
name.c_str(),
|
|
||||||
property.m_value.flag);
|
|
||||||
break;
|
|
||||||
case SocketType::SocketTypeInt:
|
|
||||||
node_instance_accessor->SetProperty(
|
|
||||||
name.c_str(),
|
|
||||||
property.m_value.int_value);
|
|
||||||
break;
|
|
||||||
case SocketType::SocketTypeFloat:
|
|
||||||
node_instance_accessor->SetProperty(
|
|
||||||
name.c_str(),
|
|
||||||
property.m_value.float_value);
|
|
||||||
break;
|
|
||||||
case SocketType::SocketTypeVec3:
|
|
||||||
node_instance_accessor->SetProperty<Vec3>(
|
|
||||||
name.c_str(),
|
|
||||||
property.m_value.vec3);
|
|
||||||
break;
|
|
||||||
case SocketType::SocketTypeQuat:
|
|
||||||
node_instance_accessor->SetProperty(
|
|
||||||
name.c_str(),
|
|
||||||
property.m_value.quat);
|
|
||||||
break;
|
|
||||||
case SocketType::SocketTypeString:
|
|
||||||
node_instance_accessor->SetProperty(
|
|
||||||
name.c_str(),
|
|
||||||
property.m_value_string);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
std::cerr << "Invalid socket type "
|
|
||||||
<< static_cast<int>(property.m_type) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete node_instance_accessor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
@ -75,8 +75,7 @@ struct BlendTreeResource : AnimGraphResource {
|
|||||||
m_virtual_socket_accessor = VirtualAnimNodeDescriptorFactory("BlendTree");
|
m_virtual_socket_accessor = VirtualAnimNodeDescriptorFactory("BlendTree");
|
||||||
|
|
||||||
InitGraphConnectors();
|
InitGraphConnectors();
|
||||||
RegisterBlendTreeOutputSocket<AnimData>(
|
RegisterBlendTreeOutputSocket<Pose>(AnimGraphResource::DefaultAnimOutput);
|
||||||
AnimGraphResource::DefaultAnimOutput);
|
|
||||||
}
|
}
|
||||||
~BlendTreeResource() { ClearAllNodes(); }
|
~BlendTreeResource() { ClearAllNodes(); }
|
||||||
|
|
||||||
@ -375,12 +374,12 @@ struct BlendTreeResource : AnimGraphResource {
|
|||||||
AnimGraphBlendTree& instance,
|
AnimGraphBlendTree& instance,
|
||||||
NodeSocketDataOffsetMap& node_offset_map) const;
|
NodeSocketDataOffsetMap& node_offset_map) const;
|
||||||
|
|
||||||
|
void SetRuntimeNodeProperties(AnimGraphBlendTree& result) const;
|
||||||
|
|
||||||
void CreateBlendTreeConnectionInstances(
|
void CreateBlendTreeConnectionInstances(
|
||||||
AnimGraphBlendTree& instance,
|
AnimGraphBlendTree& instance,
|
||||||
NodeSocketDataOffsetMap& node_offset_map) const;
|
NodeSocketDataOffsetMap& node_offset_map) const;
|
||||||
|
|
||||||
void SetRuntimeNodeProperties(AnimGraphBlendTree& result) const;
|
|
||||||
|
|
||||||
void InitGraphConnectors() {
|
void InitGraphConnectors() {
|
||||||
AddNode(AnimNodeResourceFactory("BlendTreeSockets"));
|
AddNode(AnimNodeResourceFactory("BlendTreeSockets"));
|
||||||
AnimNodeResource* output_node = GetGraphOutputNode();
|
AnimNodeResource* output_node = GetGraphOutputNode();
|
||||||
|
@ -45,8 +45,7 @@ struct AnimNode {
|
|||||||
for (const auto& input : input_connections) {
|
for (const auto& input : input_connections) {
|
||||||
AnimNode* input_node = input.m_source_node;
|
AnimNode* input_node = input.m_source_node;
|
||||||
if (input_node != nullptr) {
|
if (input_node != nullptr) {
|
||||||
input_node->m_tick_number = m_tick_number;
|
input_node->Activate(m_tick_number);
|
||||||
input_node->m_state = AnimNodeEvalState::Activated;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,13 +63,18 @@ struct AnimNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void UpdateTime(float time_last, float time_now) {
|
virtual void UpdateTime(const float time_last, const float time_now) {
|
||||||
m_time_last = time_last;
|
m_time_last = time_last;
|
||||||
m_time_now = time_now;
|
m_time_now = time_now;
|
||||||
m_state = AnimNodeEvalState::TimeUpdated;
|
m_state = AnimNodeEvalState::TimeUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Evaluate(AnimGraphContext& context){};
|
virtual void Evaluate(AnimGraphContext& context) {};
|
||||||
|
|
||||||
|
void Activate(const int tick_number) {
|
||||||
|
m_tick_number = tick_number;
|
||||||
|
m_state = AnimNodeEvalState::Activated;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //ANIMTESTBED_ANIMNODE_H
|
#endif //ANIMTESTBED_ANIMNODE_H
|
||||||
|
@ -491,7 +491,7 @@ int main() {
|
|||||||
|
|
||||||
AnimGraphBlendTree anim_graph;
|
AnimGraphBlendTree anim_graph;
|
||||||
AnimGraphContext anim_graph_context;
|
AnimGraphContext anim_graph_context;
|
||||||
AnimData anim_graph_output;
|
Pose anim_graph_output;
|
||||||
anim_graph_output.m_local_matrices.resize(
|
anim_graph_output.m_local_matrices.resize(
|
||||||
skinned_mesh.m_skeleton.num_soa_joints());
|
skinned_mesh.m_skeleton.num_soa_joints());
|
||||||
AnimGraphEditorClear();
|
AnimGraphEditorClear();
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "AnimGraph/AnimGraphBlendTree.h"
|
#include "AnimGraph/AnimGraphBlendTree.h"
|
||||||
#include "AnimGraph/AnimGraphResource.h"
|
#include "AnimGraph/AnimGraphResource.h"
|
||||||
#include "AnimGraphEditor/AnimGraphEditor.h"
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include "ozz/animation/offline/animation_builder.h"
|
#include "ozz/animation/offline/animation_builder.h"
|
||||||
#include "ozz/animation/offline/raw_animation.h"
|
#include "ozz/animation/offline/raw_animation.h"
|
||||||
@ -14,7 +13,6 @@
|
|||||||
#include "ozz/animation/runtime/sampling_job.h"
|
#include "ozz/animation/runtime/sampling_job.h"
|
||||||
#include "ozz/animation/runtime/skeleton.h"
|
#include "ozz/animation/runtime/skeleton.h"
|
||||||
#include "ozz/base/io/archive.h"
|
#include "ozz/base/io/archive.h"
|
||||||
#include "ozz/base/io/stream.h"
|
|
||||||
#include "ozz/base/log.h"
|
#include "ozz/base/log.h"
|
||||||
#include "ozz/base/maths/soa_transform.h"
|
#include "ozz/base/maths/soa_transform.h"
|
||||||
|
|
||||||
@ -66,7 +64,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, 0.f, 9.f);
|
translation_key.value = ozz::math::Float3(1.f, 0.f, 0.f);
|
||||||
bone0_translations.push_back(translation_key);
|
bone0_translations.push_back(translation_key);
|
||||||
|
|
||||||
bone0_track.translations = bone0_translations;
|
bone0_track.translations = bone0_translations;
|
||||||
@ -123,18 +121,18 @@ TEST_CASE_METHOD(
|
|||||||
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("AnimDataPlacementNew", "[AnimGraphEval]") {
|
TEST_CASE("PosePlacementNew", "[AnimGraphEval]") {
|
||||||
int anim_data_size = sizeof(AnimData);
|
int pose_size = sizeof(Pose);
|
||||||
char* buf = new char[anim_data_size];
|
char* buf = new char[pose_size];
|
||||||
|
|
||||||
AnimData* anim_data_newed = new AnimData;
|
Pose* pose_newed = new Pose;
|
||||||
anim_data_newed->m_local_matrices.resize(2);
|
pose_newed->m_local_matrices.resize(2);
|
||||||
delete anim_data_newed;
|
delete pose_newed;
|
||||||
|
|
||||||
AnimData* anim_data_ptr = new (buf) AnimData;
|
Pose* pose_ptr = new (buf) Pose;
|
||||||
anim_data_ptr->m_local_matrices.resize(4);
|
pose_ptr->m_local_matrices.resize(4);
|
||||||
anim_data_ptr->m_local_matrices.resize(0);
|
pose_ptr->m_local_matrices.resize(0);
|
||||||
anim_data_ptr->m_local_matrices.vector::~vector();
|
pose_ptr->m_local_matrices.vector::~vector();
|
||||||
|
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
}
|
}
|
||||||
@ -211,34 +209,109 @@ TEST_CASE_METHOD(
|
|||||||
// Get runtime graph inputs and outputs
|
// Get runtime graph inputs and outputs
|
||||||
float graph_float_input = 0.f;
|
float graph_float_input = 0.f;
|
||||||
blend_tree.SetInput("GraphFloatInput", &graph_float_input);
|
blend_tree.SetInput("GraphFloatInput", &graph_float_input);
|
||||||
|
CHECK(blend_tree.GetGraphInputs().size() == 1);
|
||||||
|
CHECK(
|
||||||
|
*blend_tree.GetGraphInputs()[0].m_reference.ptr_ptr
|
||||||
|
== &graph_float_input);
|
||||||
|
|
||||||
AnimData graph_anim_output;
|
Pose graph_anim_output;
|
||||||
graph_anim_output.m_local_matrices.resize(skeleton->num_joints());
|
graph_anim_output.m_local_matrices.resize(skeleton->num_joints());
|
||||||
blend_tree.SetOutput("GraphOutput", &graph_anim_output);
|
blend_tree.SetOutput("Output", &graph_anim_output);
|
||||||
|
|
||||||
// Evaluate graph
|
CHECK(blend_tree.GetGraphOutputs().size() == 1);
|
||||||
graph_float_input = 0.1f;
|
CHECK(
|
||||||
|
*blend_tree.GetGraphOutputs()[0].m_reference.ptr_ptr
|
||||||
|
== &graph_anim_output);
|
||||||
|
|
||||||
blend_tree.StartUpdateTick();
|
WHEN("Blend Weight == 0.") {
|
||||||
blend_tree.MarkActiveInputs(blend_tree.GetGraphOutputConnections());
|
// Evaluate graph
|
||||||
|
graph_float_input = 0.f;
|
||||||
|
|
||||||
CHECK(
|
blend_tree.StartUpdateTick();
|
||||||
blend_tree.m_nodes[trans_x_node_index]->m_state
|
blend_tree.MarkActiveInputs({});
|
||||||
== AnimNodeEvalState::Activated);
|
|
||||||
CHECK(
|
|
||||||
blend_tree.m_nodes[trans_y_node_index]->m_state
|
|
||||||
== AnimNodeEvalState::Activated);
|
|
||||||
CHECK(
|
|
||||||
blend_tree.m_nodes[blend_node_index]->m_state
|
|
||||||
== AnimNodeEvalState::Activated);
|
|
||||||
|
|
||||||
blend_tree.UpdateTime(0.0, 0.5f);
|
THEN("Only Blend2 and first input of Blend2 node is active.") {
|
||||||
blend_tree.Evaluate(graph_context);
|
CHECK(
|
||||||
|
blend_tree.m_nodes[trans_x_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Activated);
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[trans_y_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Deactivated);
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[blend_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Activated);
|
||||||
|
}
|
||||||
|
|
||||||
CHECK(
|
blend_tree.UpdateTime(0.0, 0.5f);
|
||||||
graph_anim_output.m_local_matrices[0].translation.x[0]
|
blend_tree.Evaluate(graph_context);
|
||||||
== Approx(0.5).margin(0.1));
|
|
||||||
CHECK(
|
CHECK(
|
||||||
graph_anim_output.m_local_matrices[0].translation.y[0]
|
graph_anim_output.m_local_matrices[0].translation.x[0]
|
||||||
== Approx(0.05).margin(0.01));
|
== Approx(0.5).margin(0.01));
|
||||||
|
CHECK(
|
||||||
|
graph_anim_output.m_local_matrices[0].translation.y[0]
|
||||||
|
== Approx(0.0).margin(0.01));
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("Blend Weight 0.1") {
|
||||||
|
// Evaluate graph
|
||||||
|
graph_float_input = 0.1f;
|
||||||
|
|
||||||
|
blend_tree.StartUpdateTick();
|
||||||
|
blend_tree.MarkActiveInputs({});
|
||||||
|
|
||||||
|
THEN("All nodes are active.") {
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[trans_x_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Activated);
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[trans_y_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Activated);
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[blend_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Activated);
|
||||||
|
}
|
||||||
|
|
||||||
|
blend_tree.UpdateTime(0.0, 0.5f);
|
||||||
|
blend_tree.Evaluate(graph_context);
|
||||||
|
|
||||||
|
CHECK(
|
||||||
|
graph_anim_output.m_local_matrices[0].translation.x[0]
|
||||||
|
== Approx(0.45).margin(0.01));
|
||||||
|
CHECK(
|
||||||
|
graph_anim_output.m_local_matrices[0].translation.y[0]
|
||||||
|
== Approx(0.05).margin(0.01));
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("Blend Weight 1.") {
|
||||||
|
// Evaluate graph
|
||||||
|
graph_float_input = 1.f;
|
||||||
|
|
||||||
|
blend_tree.StartUpdateTick();
|
||||||
|
blend_tree.MarkActiveInputs({});
|
||||||
|
|
||||||
|
THEN("Only Blend2 and second input of Blend2 are active.") {
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[trans_x_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Deactivated);
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[trans_y_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Activated);
|
||||||
|
CHECK(
|
||||||
|
blend_tree.m_nodes[blend_node_index]->m_state
|
||||||
|
== AnimNodeEvalState::Activated);
|
||||||
|
}
|
||||||
|
|
||||||
|
blend_tree.UpdateTime(0.0, 0.5f);
|
||||||
|
blend_tree.Evaluate(graph_context);
|
||||||
|
|
||||||
|
CHECK(
|
||||||
|
graph_anim_output.m_local_matrices[0].translation.x[0]
|
||||||
|
== Approx(0.).margin(0.01));
|
||||||
|
CHECK(
|
||||||
|
graph_anim_output.m_local_matrices[0].translation.y[0]
|
||||||
|
== Approx(0.5).margin(0.01));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete blend_tree_resource;
|
||||||
}
|
}
|
@ -41,7 +41,7 @@ class SimpleAnimSamplerBlendTreeResourceFixture
|
|||||||
std::string("media/Walking-loop.ozz"));
|
std::string("media/Walking-loop.ozz"));
|
||||||
|
|
||||||
AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode();
|
AnimNodeResource* graph_node = blend_tree_resource->GetGraphOutputNode();
|
||||||
graph_node->m_virtual_socket_accessor->RegisterInput<AnimData>(
|
graph_node->m_virtual_socket_accessor->RegisterInput<Pose>(
|
||||||
"GraphOutput",
|
"GraphOutput",
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
@ -161,14 +161,14 @@ class EmbeddedBlendTreeGraphResource : public BlendTreeResourceFixture {
|
|||||||
// Embedded: outputs
|
// Embedded: outputs
|
||||||
AnimNodeResource* embedded_outputs =
|
AnimNodeResource* embedded_outputs =
|
||||||
embedded_blend_tree_resource->GetGraphOutputNode();
|
embedded_blend_tree_resource->GetGraphOutputNode();
|
||||||
embedded_outputs->m_virtual_socket_accessor->RegisterInput<AnimData>(
|
embedded_outputs->m_virtual_socket_accessor->RegisterInput<Pose>(
|
||||||
"AnimOutput",
|
"AnimOutput",
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
// Embedded: inputs
|
// Embedded: inputs
|
||||||
AnimNodeResource* embedded_inputs =
|
AnimNodeResource* embedded_inputs =
|
||||||
embedded_blend_tree_resource->GetGraphInputNode();
|
embedded_blend_tree_resource->GetGraphInputNode();
|
||||||
embedded_inputs->m_virtual_socket_accessor->RegisterOutput<AnimData>(
|
embedded_inputs->m_virtual_socket_accessor->RegisterOutput<Pose>(
|
||||||
"AnimInput",
|
"AnimInput",
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ class EmbeddedTreeBlend2GraphResource : public BlendTreeResourceFixture {
|
|||||||
embedded_blend_tree_resource->m_name = "EmbeddedTreeBlend2GraphResource";
|
embedded_blend_tree_resource->m_name = "EmbeddedTreeBlend2GraphResource";
|
||||||
|
|
||||||
// Embedded: inputs
|
// Embedded: inputs
|
||||||
embedded_blend_tree_resource->RegisterBlendTreeInputSocket<AnimData>(
|
embedded_blend_tree_resource->RegisterBlendTreeInputSocket<Pose>(
|
||||||
"AnimInput");
|
"AnimInput");
|
||||||
embedded_blend_tree_resource->RegisterBlendTreeInputSocket<float>(
|
embedded_blend_tree_resource->RegisterBlendTreeInputSocket<float>(
|
||||||
"BlendWeight");
|
"BlendWeight");
|
||||||
@ -482,7 +482,7 @@ TEST_CASE_METHOD(
|
|||||||
REQUIRE(anim_sampler_walk->m_animation != nullptr);
|
REQUIRE(anim_sampler_walk->m_animation != nullptr);
|
||||||
|
|
||||||
// Ensure that outputs are properly propagated.
|
// Ensure that outputs are properly propagated.
|
||||||
AnimData output;
|
Pose output;
|
||||||
output.m_local_matrices.resize(skeleton.num_soa_joints());
|
output.m_local_matrices.resize(skeleton.num_soa_joints());
|
||||||
anim_graph_blend_tree.SetOutput(
|
anim_graph_blend_tree.SetOutput(
|
||||||
AnimGraphResource::DefaultAnimOutput,
|
AnimGraphResource::DefaultAnimOutput,
|
||||||
@ -764,9 +764,8 @@ TEST_CASE_METHOD(
|
|||||||
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);
|
||||||
|
|
||||||
AnimData* graph_output =
|
Pose* graph_output = blend_tree_graph.GetOutputPtr<Pose>(
|
||||||
static_cast<AnimData*>(blend_tree_graph.GetOutputPtr<AnimData>(
|
AnimGraphResource::DefaultAnimOutput);
|
||||||
AnimGraphResource::DefaultAnimOutput));
|
|
||||||
|
|
||||||
CHECK(
|
CHECK(
|
||||||
graph_output->m_local_matrices.size()
|
graph_output->m_local_matrices.size()
|
||||||
|
@ -8,26 +8,34 @@
|
|||||||
|
|
||||||
TEST_CASE("Descriptor Access", "[NodeDescriptorTests]") {
|
TEST_CASE("Descriptor Access", "[NodeDescriptorTests]") {
|
||||||
Blend2Node blend2Node;
|
Blend2Node blend2Node;
|
||||||
NodeDescriptor<Blend2Node> blend2Descriptor (&blend2Node);
|
NodeDescriptor<Blend2Node> blend2Descriptor(&blend2Node);
|
||||||
CHECK(blend2Descriptor.m_inputs.size() == 3);
|
CHECK(blend2Descriptor.m_inputs.size() == 3);
|
||||||
CHECK(*blend2Descriptor.m_inputs[0].m_reference.ptr_ptr == blend2Node.i_input0);
|
CHECK(
|
||||||
CHECK(*blend2Descriptor.m_inputs[1].m_reference.ptr_ptr == blend2Node.i_input1);
|
*blend2Descriptor.m_inputs[0].m_reference.ptr_ptr == blend2Node.i_input0);
|
||||||
CHECK(*blend2Descriptor.m_inputs[2].m_reference.ptr_ptr == blend2Node.i_blend_weight);
|
CHECK(
|
||||||
|
*blend2Descriptor.m_inputs[1].m_reference.ptr_ptr == blend2Node.i_input1);
|
||||||
|
CHECK(
|
||||||
|
*blend2Descriptor.m_inputs[2].m_reference.ptr_ptr
|
||||||
|
== blend2Node.i_blend_weight);
|
||||||
|
|
||||||
CHECK(blend2Descriptor.m_inputs[0].m_type_size == sizeof(AnimData));
|
CHECK(blend2Descriptor.m_inputs[0].m_type_size == sizeof(Pose));
|
||||||
CHECK(blend2Descriptor.m_inputs[2].m_type_size == 4);
|
CHECK(blend2Descriptor.m_inputs[2].m_type_size == 4);
|
||||||
|
|
||||||
CHECK(blend2Descriptor.m_outputs.size() == 1);
|
CHECK(blend2Descriptor.m_outputs.size() == 1);
|
||||||
CHECK(*blend2Descriptor.m_outputs[0].m_reference.ptr_ptr == blend2Node.o_output);
|
CHECK(
|
||||||
|
*blend2Descriptor.m_outputs[0].m_reference.ptr_ptr
|
||||||
|
== blend2Node.o_output);
|
||||||
|
|
||||||
CHECK(blend2Descriptor.m_properties.size() == 1);
|
CHECK(blend2Descriptor.m_properties.size() == 1);
|
||||||
CHECK(blend2Descriptor.m_properties[0].m_reference.ptr == &blend2Node.m_sync_blend);
|
CHECK(
|
||||||
|
blend2Descriptor.m_properties[0].m_reference.ptr
|
||||||
|
== &blend2Node.m_sync_blend);
|
||||||
|
|
||||||
// Check we can properly update inputs
|
// Check we can properly update inputs
|
||||||
CHECK(blend2Node.i_input0 == nullptr);
|
CHECK(blend2Node.i_input0 == nullptr);
|
||||||
AnimData some_anim_data;
|
Pose pose;
|
||||||
blend2Descriptor.SetInput("Input0", &some_anim_data);
|
blend2Descriptor.SetInput("Input0", &pose);
|
||||||
CHECK(blend2Node.i_input0 == &some_anim_data);
|
CHECK(blend2Node.i_input0 == &pose);
|
||||||
|
|
||||||
// Check we properly can set properties
|
// Check we properly can set properties
|
||||||
CHECK(blend2Node.m_sync_blend == false);
|
CHECK(blend2Node.m_sync_blend == false);
|
||||||
@ -41,6 +49,7 @@ TEST_CASE("Descriptor Access", "[NodeDescriptorTests]") {
|
|||||||
blend2Descriptor.UpdateFlags();
|
blend2Descriptor.UpdateFlags();
|
||||||
Socket* weight_input_socket = blend2Descriptor.GetInputSocket("Weight");
|
Socket* weight_input_socket = blend2Descriptor.GetInputSocket("Weight");
|
||||||
CHECK(weight_input_socket != nullptr);
|
CHECK(weight_input_socket != nullptr);
|
||||||
CHECK(weight_input_socket->m_flags & SocketFlagAffectsTime == SocketFlagAffectsTime);
|
CHECK(
|
||||||
|
weight_input_socket->m_flags
|
||||||
|
& SocketFlagAffectsTime == SocketFlagAffectsTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user