// // Created by martin on 25.03.22. // #ifndef ANIMTESTBED_ANIMGRAPHDATA_H #define ANIMTESTBED_ANIMGRAPHDATA_H #include #include #include #include #include #include #include #include "SyncTrack.h" #include "ozz/animation/runtime/animation.h" #include "ozz/animation/runtime/skeleton.h" #include "ozz/base/containers/vector.h" // // Data types // struct AnimGraph; struct AnimData { ozz::vector m_local_matrices; }; struct AnimDataAllocator { struct AnimDataList { AnimData* m_anim_data = nullptr; AnimDataList* next = nullptr; }; std::list m_anim_data_list; size_t m_num_allocations = 0; ~AnimDataAllocator() { while (!m_anim_data_list.empty()) { AnimData* front = m_anim_data_list.front(); #ifdef ANIM_DATA_ALLOCATOR_DEBUG std::cout << "about to delete with size " << front->m_anim_data->m_local_matrices.size() << front->m_anim_data << std::endl; #endif delete front; m_anim_data_list.pop_front(); } } AnimData* allocate(ozz::animation::Skeleton* skeleton) { if (m_anim_data_list.empty()) { AnimData* result = new AnimData(); result->m_local_matrices.resize(skeleton->num_soa_joints()); #ifdef ANIM_DATA_ALLOCATOR_DEBUG std::cout << "Allocated with size " << result->m_local_matrices.size() << " " << result << std::endl; #endif m_num_allocations++; return result; } AnimData* result = m_anim_data_list.front(); m_anim_data_list.pop_front(); #ifdef ANIM_DATA_ALLOCATOR_DEBUG std::cout << "Reusing buffer with size " << result->m_local_matrices.size() << " " << result << std::endl; #endif return result; } void free(AnimData* anim_data) { #ifdef ANIM_DATA_ALLOCATOR_DEBUG std::cout << "Storing buffer with size " << anim_data->m_local_matrices.size() << " " << anim_data << std::endl; #endif m_anim_data_list.push_front(anim_data); } size_t size() { return m_anim_data_list.size(); } }; struct AnimGraphContext { AnimGraph* m_graph = nullptr; ozz::animation::Skeleton* m_skeleton = nullptr; typedef std::map 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++; } } }; typedef float Vec3[3]; typedef float Quat[4]; enum class SocketType { SocketTypeUndefined = 0, SocketTypeBool, SocketTypeAnimation, SocketTypeFloat, SocketTypeVec3, SocketTypeQuat, SocketTypeString, SocketTypeLast }; constexpr size_t cSocketStringValueMaxLength = 256; static const char* SocketTypeNames[] = {"", "Bool", "Animation", "Float", "Vec3", "Quat", "String"}; enum SocketFlags { SocketFlagAffectsTime = 1 }; struct Socket { std::string m_name; SocketType m_type = SocketType::SocketTypeUndefined; union SocketValue { bool flag; float float_value; float vec3[3]; float quat[4]; char str[cSocketStringValueMaxLength]; }; SocketValue m_value = {0}; union SocketReference { void* ptr; void** ptr_ptr; }; SocketReference m_reference = {0}; int m_flags = 0; size_t m_type_size = 0; }; struct NodeSocketAccessorBase { std::vector m_properties; std::vector m_inputs; std::vector m_outputs; NodeSocketAccessorBase() {} virtual ~NodeSocketAccessorBase() {} virtual void UpdateFlags(){}; Socket* FindSocket(std::vector& sockets, const std::string& name) { Socket* result = nullptr; for (size_t i = 0, n = sockets.size(); i < n; i++) { if (sockets[i].m_name == name) { result = &sockets[i]; break; } } return result; } const Socket* FindSocket( const std::vector& sockets, const std::string& name) const { const Socket* result = nullptr; for (size_t i = 0, n = sockets.size(); i < n; i++) { if (sockets[i].m_name == name) { result = &sockets[i]; break; } } return result; } SocketType GetSocketType( const std::vector& sockets, const std::string& name) { const Socket* socket = FindSocket(sockets, name); if (socket == nullptr) { return SocketType::SocketTypeUndefined; } return socket->m_type; } size_t GetSocketIndex( const std::vector& sockets, const std::string& name) const { for (size_t i = 0, n = sockets.size(); i < n; i++) { if (sockets[i].m_name == name) { return i; } } return -1; } template T GetSocketValue( const std::vector& sockets, const std::string& name, T default_value) { const Socket* socket = FindSocket(sockets, name); if (socket == nullptr) { return default_value; } return *static_cast(socket->m_reference.ptr); } template void SetSocketReferenceValue(Socket* socket, T value) { std::cerr << "Could not find template specialization for socket type " << static_cast(socket->m_type) << " (" << SocketTypeNames[static_cast(socket->m_type)] << ")." << std::endl; // *static_cast(socket->m_value.ptr) = value; } template void SetSocketValue(Socket* socket, T value) { std::cerr << "Could not find template specialization for socket type " << static_cast(socket->m_type) << " (" << SocketTypeNames[static_cast(socket->m_type)] << ")." << std::endl; // *static_cast(socket->m_value.ptr) = value; } template bool RegisterSocket( std::vector& sockets, const std::string& name, T* value_ptr, int flags = 0) { Socket* socket = FindSocket(sockets, name); if (socket != nullptr) { std::cerr << "Socket " << name << " already registered." << std::endl; return false; } sockets.push_back(Socket()); socket = &sockets[sockets.size() - 1]; socket->m_name = name; socket->m_type_size = sizeof(T); socket->m_flags = flags; if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeFloat; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeBool; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeVec3; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeQuat; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeAnimation; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeString; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeFloat; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeBool; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeVec3; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeQuat; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeAnimation; } else if constexpr (std::is_same::value) { socket->m_type = SocketType::SocketTypeString; } else { std::cerr << "Cannot register socket, invalid type." << std::endl; return false; } socket->m_reference.ptr = value_ptr; return true; } template bool RegisterProperty(const std::string& name, T* value) { return RegisterSocket(m_properties, name, value); } template void SetPropertyReferenceValue(const std::string& name, T value) { Socket* socket = FindSocket(m_properties, name); SetSocketReferenceValue(socket, value); } template void SetPropertyValue(const std::string& name, T value) { Socket* socket = FindSocket(m_properties, name); SetSocketValue(socket, value); } template T GetProperty(const std::string& name, T default_value) { return GetSocketValue(m_properties, name, default_value); } SocketType GetPropertyType(const std::string& name) { return GetSocketType(m_properties, name); } template bool RegisterInput(const std::string& name, T* value, int flags = 0) { return RegisterSocket(m_inputs, name, value, flags); } template T* GetInput(const std::string& name, T* value) { return GetSocketValue(m_inputs, name, value); } Socket* FindInputSocket(const std::string& name) { return FindSocket(m_inputs, name); } SocketType GetInputType(const std::string& name) { return GetSocketType(m_inputs, name); } size_t GetInputIndex(const std::string& name) { return GetSocketIndex(m_inputs, name); } template bool RegisterOutput(const std::string& name, T* value, int flags = 0) { return RegisterSocket(m_outputs, name, value, flags); } template bool RegisterOutput(const std::string& name, T** value, int flags = 0) { return RegisterSocket(m_outputs, name, value, flags); } SocketType GetOutputType(const std::string& name) { return GetSocketType(m_outputs, name); } Socket* FindOutputSocket(const std::string& name) { return FindSocket(m_outputs, name); } size_t GetOutputIndex(const std::string& name) { return GetSocketIndex(m_outputs, name); } }; // // SetSocketReferenceValue<> specializations // template <> inline void NodeSocketAccessorBase::SetSocketReferenceValue( Socket* socket, const bool& value) { *static_cast(socket->m_reference.ptr) = value; } template <> inline void NodeSocketAccessorBase::SetSocketReferenceValue( Socket* socket, const float& value) { *static_cast(socket->m_reference.ptr) = value; } template <> inline void NodeSocketAccessorBase::SetSocketReferenceValue( Socket* socket, const Vec3& value) { static_cast(socket->m_reference.ptr)[0] = value[0]; static_cast(socket->m_reference.ptr)[1] = value[1]; static_cast(socket->m_reference.ptr)[2] = value[2]; } template <> inline void NodeSocketAccessorBase::SetSocketReferenceValue( Socket* socket, const Quat& value) { static_cast(socket->m_reference.ptr)[0] = value[0]; static_cast(socket->m_reference.ptr)[1] = value[1]; static_cast(socket->m_reference.ptr)[2] = value[2]; static_cast(socket->m_reference.ptr)[3] = value[3]; } template <> inline void NodeSocketAccessorBase::SetSocketReferenceValue( Socket* socket, const std::string& value) { *static_cast(socket->m_reference.ptr) = value; } template <> inline void NodeSocketAccessorBase::SetSocketReferenceValue( Socket* socket, const char* value) { std::string value_string(value); SetSocketReferenceValue(socket, value_string); } // // SetSocketValue<> specializations // template <> inline void NodeSocketAccessorBase::SetSocketValue( Socket* socket, const bool& value) { socket->m_value.flag = value; } template <> inline void NodeSocketAccessorBase::SetSocketValue( Socket* socket, const float& value) { socket->m_value.float_value = value; } template <> inline void NodeSocketAccessorBase::SetSocketValue( Socket* socket, const Vec3& value) { socket->m_value.vec3[0] = value[0]; socket->m_value.vec3[1] = value[1]; socket->m_value.vec3[2] = value[2]; } template <> inline void NodeSocketAccessorBase::SetSocketValue( Socket* socket, const Quat& value) { socket->m_value.quat[0] = value[0]; socket->m_value.quat[1] = value[1]; socket->m_value.quat[2] = value[2]; socket->m_value.quat[3] = value[3]; } template <> inline void NodeSocketAccessorBase::SetSocketValue( Socket* socket, const std::string& value) { constexpr size_t string_max_length = sizeof(socket->m_value.str) - 1; strncpy(socket->m_value.str, value.data(), string_max_length); socket->m_value.str [value.size() > string_max_length ? string_max_length : value.size()] = 0; } template <> inline void NodeSocketAccessorBase::SetSocketValue( Socket* socket, const char* value) { SetSocketValue(socket, value); } template struct NodeSocketAccessor : public NodeSocketAccessorBase { virtual ~NodeSocketAccessor() {} }; #endif //ANIMTESTBED_ANIMGRAPHDATA_H