diff --git a/openVulkanoCpp/Image/XmpBuilder.cpp b/openVulkanoCpp/Image/XmpBuilder.cpp
new file mode 100644
index 0000000..9ff18a5
--- /dev/null
+++ b/openVulkanoCpp/Image/XmpBuilder.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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/.
+ */
+
+#include "XmpBuilder.hpp"
+#include "Extensions/FmtFormatter.hpp"
+
+namespace OpenVulkano::Image
+{
+ XmpBuilder::XmpBuilder()
+ {
+ xmpData << "\n"; // XMP Wrapper
+ xmpData << "";
+ }
+
+ std::string XmpBuilder::Finalize()
+ {
+ if (!complete)
+ { // Finalize
+ xmpData << "";
+ xmpData << ""; // XMP Wrapper
+ complete = true;
+ }
+ return xmpData.str();
+ }
+
+ [[maybe_unused]] XmpBuilder& XmpBuilder::SetCameraIntrinsic(const Math::CameraIntrinsicWithResolution& intrinsic)
+ {
+ // Calibration matrix in row-major format
+ const auto& mat = intrinsic.GetMatrix();
+ xmpData << fmt::format("{} {} {} {} {} {} {} {} {}",
+ mat[0][0], mat[1][0], mat[2][0], mat[0][1], mat[1][1], mat[2][1], mat[0][2], mat[1][2], mat[2][2]);
+ xmpData << fmt::format(""
+ "{}{}"
+ "{}{}"
+ "",
+ intrinsic.Fx(), intrinsic.Fy(), intrinsic.Cx(), intrinsic.Cy() );
+ // Field of View
+ xmpData << fmt::format(""
+ "{}{}"
+ "",
+ Math::Utils::degrees(intrinsic.GetFovX()), Math::Utils::degrees(intrinsic.GetFovY()));
+ return *this;
+ }
+
+ [[maybe_unused]] XmpBuilder& XmpBuilder::SetPosition(const Math::Vector3f& position)
+ {
+ xmpData << fmt::format(""
+ "{}{}{}"
+ "",
+ position.x, position.y, position.z);
+ return *this;
+ }
+
+ [[maybe_unused]] XmpBuilder& XmpBuilder::SetOrientation(const Math::Vector3f& orientation)
+ {
+ Math::Vector3f ori = Math::Utils::degrees(orientation);
+ xmpData << fmt::format(""
+ "{}{}{}"
+ "",
+ ori.x, ori.y, ori.z);
+ return *this;
+ }
+
+ [[maybe_unused]] XmpBuilder& XmpBuilder::SetSensorSize(const Math::Vector2f& sensorSize)
+ {
+ xmpData << fmt::format(""
+ "{}{}"
+ "",
+ sensorSize.x, sensorSize.y);
+ return *this;
+ }
+
+ [[maybe_unused]] XmpBuilder& XmpBuilder::SetFocalLength(const float focalLengthMM)
+ {
+ xmpData << "" << focalLengthMM << "";
+ return *this;
+ }
+
+ [[maybe_unused]] XmpBuilder& XmpBuilder::SetExposureTime(double exposureTime)
+ {
+ xmpData << fmt::format("{0}{0}", exposureTime);
+ return *this;
+ }
+
+ [[maybe_unused]] XmpBuilder& XmpBuilder::SetCreateDate(const std::string& createDate)
+ {
+ xmpData << "" << createDate << "";
+ return *this;
+ }
+}
diff --git a/openVulkanoCpp/Image/XmpBuilder.hpp b/openVulkanoCpp/Image/XmpBuilder.hpp
new file mode 100644
index 0000000..f199b68
--- /dev/null
+++ b/openVulkanoCpp/Image/XmpBuilder.hpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "Math/CameraIntrinsic.hpp"
+#include "Math/Pose.hpp"
+#include
+
+namespace OpenVulkano::Image
+{
+ class XmpBuilder final
+ {
+ std::stringstream xmpData;
+ bool complete = false;
+
+ public:
+ XmpBuilder();
+
+ [[maybe_unused]] XmpBuilder& SetCameraIntrinsic(const Math::CameraIntrinsicWithResolution& intrinsic);
+ [[maybe_unused]] XmpBuilder& SetPose(const Math::PoseF& pose) { SetPosition(pose.GetPosition()); SetOrientation(pose.GetOrientationAsEuler()); return *this; }
+ [[maybe_unused]] XmpBuilder& SetPosition(const Math::Vector3f& position);
+ [[maybe_unused]] XmpBuilder& SetOrientation(const Math::Vector3f& orientation); // in rad
+ [[maybe_unused]] XmpBuilder& SetSensorSize(const Math::Vector2f& sensorSize);
+
+ [[maybe_unused]] XmpBuilder& SetFocalLength(float focalLengthMM);
+ [[maybe_unused]] XmpBuilder& SetExposureTime(double exposureTime);
+ [[maybe_unused]] XmpBuilder& SetCreateDate(const std::string& createDate);
+
+ [[maybe_unused]] std::string Close() { return Finalize(); }
+ std::string Finalize();
+ };
+}
diff --git a/openVulkanoCpp/Math/Pose.hpp b/openVulkanoCpp/Math/Pose.hpp
index c782b17..23e8c13 100644
--- a/openVulkanoCpp/Math/Pose.hpp
+++ b/openVulkanoCpp/Math/Pose.hpp
@@ -53,6 +53,8 @@ namespace OpenVulkano::Math
[[nodiscard]] Quaternion& GetOrientation() { return m_orientation; }
+ [[nodiscard]] Math::Vector3f GetOrientationAsEuler() const { return Math::Utils::eulerAngles(m_orientation); }
+
void SetOrientation(const Math::Quaternion& orientation) { m_orientation = orientation; }
void SetOrientation(const Math::Vector3_SIMD& eulerAngle) { m_orientation = Math::Utils::qua(eulerAngle); }