/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include "Timestamp.hpp" #include "Math.hpp" namespace OpenVulkano::Math { template>> class Pose { Quaternion m_orientation; Vector3_SIMD m_position; public: Pose() {} Pose(const Quaternion& orientation, const Vector3_SIMD& position) : m_orientation(orientation), m_position(position) {} Pose(const Math::Vector3_SIMD& eulerAngle, const Vector3f_SIMD& position) : m_orientation(Math::Utils::qua(eulerAngle)), m_position(position) {} Pose(const Math::Matrix4 &matrix) { Math::Vector3_SIMD scale; Math::Quaternion rotation; Math::Vector3_SIMD translation; Math::Vector3_SIMD skew; Math::Vector4_SIMD perspective; bool decomposed = Math::Utils::decompose(matrix, scale, rotation, translation, skew, perspective); if(decomposed) { m_orientation = rotation; m_position = translation; } } bool operator==(const Math::Pose &otherPose) const { return (GetOrientation() == otherPose.GetOrientation()) && (GetPosition() == otherPose.GetPosition()); } [[nodiscard]] const Quaternion& GetOrientation() const { return m_orientation; } void SetOrientation(const Math::Quaternion& orientation) { m_orientation = orientation; } void SetOrientation(const Math::Vector3_SIMD& eulerAngle) { m_orientation = Math::Utils::qua(eulerAngle); } [[nodiscard]] const Vector3_SIMD& GetPosition() const { return m_position; } void SetPosition(const Math::Vector3_SIMD& pos) { m_position = pos; } [[nodiscard]] Pose Interpolate(const Pose& otherPose, T mixFactor) const { return Pose( Utils::mix(m_orientation, otherPose.m_orientation, mixFactor), Utils::mix(m_position, otherPose.m_position, mixFactor) ); } [[nodiscard]] Math::Matrix4 ToMatrix() const { Math::Matrix4 mat = Utils::toMat4(m_orientation); mat[3] = Math::Vector4(m_position, 1); return mat; } }; typedef Pose PoseF; typedef Pose PoseD; template>> class PoseWithTimestamp final : public Pose { Timestamp m_timestamp; public: PoseWithTimestamp(Timestamp timestamp, Quaternion orientation, Vector3_SIMD position) : m_timestamp(timestamp), Pose(orientation, position) {} PoseWithTimestamp(Timestamp timestamp, Math::Vector3_SIMD eulerAngle, Vector3_SIMD position) : m_timestamp(timestamp), Pose(eulerAngle, position) {} PoseWithTimestamp(Timestamp timestamp, Pose pose) : m_timestamp(timestamp), Pose(pose) {} [[nodiscard]] PoseWithTimestamp Interpolate(const PoseWithTimestamp& otherPose, Timestamp targetTime) const { PoseWithTimestamp* start = *this; PoseWithTimestamp* end = &otherPose; if (start->m_timestamp == end->m_timestamp) return *this; // Nothing to interpolate if (start->m_timestamp > end->m_timestamp) { std::swap(start, end); } if (targetTime <= start->m_timestamp) return *start; if (targetTime >= end->m_timestamp) return *end; T mixFactor = (targetTime - start->m_timestamp) / (end->m_timestamp - start->m_timestamp); return PoseWithTimestamp(targetTime, start->Interpolate(*end, mixFactor)); } [[nodiscard]] Timestamp GetTimestamp() { return m_timestamp; } }; typedef PoseWithTimestamp PoseWithTimestampF; typedef PoseWithTimestamp PoseWithTimestampD; }