Start design of AR abstraction layer
This commit is contained in:
27
openVulkanoCpp/AR/ArConstans.hpp
Normal file
27
openVulkanoCpp/AR/ArConstans.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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/Math.hpp"
|
||||
#include "Math/Range.hpp"
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
class ArConstants final
|
||||
{
|
||||
public:
|
||||
Math::Matrix4f yuvToRgbMatrix;
|
||||
Math::Range<uint8_t> confidenceValueRange;
|
||||
|
||||
ArConstants() : yuvToRgbMatrix(0), confidenceValueRange(0, 255)
|
||||
{}
|
||||
|
||||
ArConstants(const Math::Matrix4f& yuvToRgb, const Math::Range<uint8_t> confidenceRange)
|
||||
: yuvToRgbMatrix(yuvToRgb), confidenceValueRange(confidenceRange)
|
||||
{}
|
||||
};
|
||||
}
|
||||
59
openVulkanoCpp/AR/ArDepthFormat.hpp
Normal file
59
openVulkanoCpp/AR/ArDepthFormat.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 <magic_enum.hpp>
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
class ArDepthFormat final
|
||||
{
|
||||
static inline constexpr std::string_view ALT_NAMES[] = {
|
||||
"Unavailable", "FP32_METER", "FP64_METER", "U16_MILLIMETER", "U32_MILLIMETER"
|
||||
};
|
||||
|
||||
public:
|
||||
enum Format : uint8_t { UNAVAILABLE = 0, METER_FP32, METER_FP64, MILLIMETER_U16, MILLIMETER_U32 };
|
||||
|
||||
ArDepthFormat() : ArDepthFormat(UNAVAILABLE) {}
|
||||
|
||||
ArDepthFormat(Format format) : m_format(format) {}
|
||||
|
||||
[[nodiscard]] std::string_view GetName() const
|
||||
{
|
||||
return magic_enum::enum_name(m_format);
|
||||
}
|
||||
|
||||
static std::optional<ArDepthFormat> GetFromName(std::string_view name)
|
||||
{
|
||||
auto result = magic_enum::enum_cast<Format>(name);
|
||||
if (result.has_value()) return ArDepthFormat(result.value());
|
||||
return GetFromAltName(name);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string_view& GetAltName() const
|
||||
{
|
||||
return ALT_NAMES[m_format];
|
||||
}
|
||||
|
||||
static std::optional<ArDepthFormat> GetFromAltName(std::string_view name)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
for(const std::string_view& n : ALT_NAMES)
|
||||
{
|
||||
if (n == name) return { static_cast<Format>(i) };
|
||||
i++;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
operator Format() const { return m_format; }
|
||||
|
||||
private:
|
||||
Format m_format;
|
||||
};
|
||||
}
|
||||
113
openVulkanoCpp/AR/ArFrame.h
Normal file
113
openVulkanoCpp/AR/ArFrame.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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/Math.hpp"
|
||||
#include "Math/Timestamp.hpp"
|
||||
#include "Math/Pose.hpp"
|
||||
#include "Math/CameraIntrinsic.hpp"
|
||||
#include "ArDepthFormat.hpp"
|
||||
#include "ArTrackingState.hpp"
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
class ArImage
|
||||
{
|
||||
public:
|
||||
void* data;
|
||||
Math::Vector2ui resolution;
|
||||
};
|
||||
|
||||
class ArImagePlanar
|
||||
{
|
||||
public:
|
||||
enum class Format { NV12, NV21, RGB, BGR };
|
||||
|
||||
ArImage luminescenceOrColor;
|
||||
ArImage uv;
|
||||
|
||||
Math::CameraIntrinsic intrinsic;
|
||||
Format format = Format::NV12;
|
||||
|
||||
[[nodiscard]] Math::Vector4uc Sample(uint32_t x, uint32_t y, bool asRgb = true) const
|
||||
{
|
||||
const uint8_t* lumColBuffer = static_cast<const uint8_t*>(luminescenceOrColor.data);
|
||||
if (format == Format::BGR)
|
||||
{
|
||||
size_t idx = (y * luminescenceOrColor.resolution.x + x) * 3;
|
||||
return { lumColBuffer[idx + 2], lumColBuffer[idx + 1], lumColBuffer[idx], 255 };
|
||||
}
|
||||
else if (format == Format::RGB)
|
||||
{
|
||||
size_t idx = (y * luminescenceOrColor.resolution.x + x) * 3;
|
||||
return { lumColBuffer[idx], lumColBuffer[idx + 1], lumColBuffer[idx + 2], 255 };
|
||||
}
|
||||
|
||||
int iUV = ((y / 2) * uv.resolution.x + x / 2) * 2;
|
||||
|
||||
Math::Vector4uc sample(
|
||||
lumColBuffer[y * luminescenceOrColor.resolution.x + x],
|
||||
static_cast<const uint8_t*>(uv.data)[iUV],
|
||||
static_cast<const uint8_t*>(uv.data)[iUV+1],
|
||||
255);
|
||||
|
||||
if (asRgb)
|
||||
{
|
||||
Math::Vector4f c(sample);
|
||||
Math::Matrix4f conversionMatrix(
|
||||
Math::Vector4f(+1.0000f, +1.0000f, +1.0000f, +0.0000f),
|
||||
Math::Vector4f(+0.0000f, -0.3441f, +1.7720f, +0.0000f),
|
||||
Math::Vector4f(+1.4020f, -0.7141f, +0.0000f, +0.0000f),
|
||||
Math::Vector4f(-0.7010f, +0.5291f, -0.8860f, +1.0000f)
|
||||
);
|
||||
sample = Math::Utils::clamp(conversionMatrix * c, 0.0f, 255.0f);
|
||||
}
|
||||
|
||||
return sample;
|
||||
}
|
||||
};
|
||||
|
||||
class ArDepthImage
|
||||
{
|
||||
public:
|
||||
ArImage depth;
|
||||
ArImage confidence;
|
||||
ArDepthFormat format;
|
||||
Math::CameraIntrinsic intrinsic;
|
||||
};
|
||||
|
||||
class ArFrame
|
||||
{
|
||||
protected:
|
||||
ArFrame() = default;
|
||||
|
||||
public:
|
||||
virtual ~ArFrame() = default;
|
||||
|
||||
[[nodiscard]] virtual ArTrackingState GetTrackingState() = 0;
|
||||
|
||||
[[nodiscard]] virtual Math::PoseF GetPose() = 0;
|
||||
|
||||
[[nodiscard]] virtual Math::Timestamp GetTimestamp() = 0;
|
||||
|
||||
//[[nodiscard]] virtual Math::Timestamp GetTimestampDepth() = 0;
|
||||
|
||||
[[nodiscard]] virtual ArImagePlanar GetCameraImage() = 0;
|
||||
|
||||
[[nodiscard]] virtual ArDepthImage GetDepthImage() = 0;
|
||||
|
||||
[[nodiscard]] virtual const Math::Matrix4f& GetCameraTransformation() = 0;
|
||||
|
||||
[[nodiscard]] virtual Math::Matrix4f GetCameraViewForCurrentDeviceOrientation() = 0;
|
||||
|
||||
[[nodiscard]] virtual Math::Matrix4f GetCameraProjection(Math::Vector2f viewportSize, float near = 0.25f, float far = 250.0f) = 0;
|
||||
|
||||
[[nodiscard]] virtual float GetConfidenceNormalisationFactor() = 0;
|
||||
|
||||
[[nodiscard]] virtual float GetColorTemperature() const = 0;
|
||||
};
|
||||
}
|
||||
90
openVulkanoCpp/AR/ArRecorder.h
Normal file
90
openVulkanoCpp/AR/ArRecorder.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 <string>
|
||||
#include <filesystem>
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
enum class RecordingMode
|
||||
{
|
||||
/**
|
||||
* Frames will only be saved when manually requested through ArFrame::Save()
|
||||
*/
|
||||
MANUAL,
|
||||
/**
|
||||
* Frames will only be saved when the frame is manually requested through ArSession::GetFrame()
|
||||
*/
|
||||
FRAME_REQUEST,
|
||||
/**
|
||||
* Every new frame will be stored automatically
|
||||
*/
|
||||
NEW_FRAME
|
||||
};
|
||||
|
||||
class ArRecorder
|
||||
{
|
||||
protected:
|
||||
ArRecorder() = default;
|
||||
|
||||
public:
|
||||
virtual ~ArRecorder() = default;
|
||||
|
||||
/**
|
||||
* Starts the recording of the owning AR session
|
||||
*/
|
||||
virtual void Start() = 0;
|
||||
|
||||
/**
|
||||
* Stops the recording of the owning AR session
|
||||
*/
|
||||
virtual void Stop() = 0;
|
||||
|
||||
/**
|
||||
* Sets the directory into which the AR recording should be stored.
|
||||
* The path needs to be set to make the recording persistent.
|
||||
* If path is changed after starting the recording, the already running recording will be moved to the new path.
|
||||
* @param path The path to be used to store the recording
|
||||
*/
|
||||
virtual void SetRecordingPath(const std::string& path) = 0;
|
||||
|
||||
/**
|
||||
* Gets the current recording path
|
||||
* @return Current recording dir
|
||||
*/
|
||||
[[nodiscard]] virtual const std::filesystem::path& GetRecordingPath() const = 0;
|
||||
|
||||
/**
|
||||
* Checks if a path to be used for the recording has been set.
|
||||
* If no path has been set the recording will be stored in a temporary location and will be deleted once the recording is stopped.
|
||||
* @return True if a path has been set and the recording will persist after stopping the recording.
|
||||
*/
|
||||
[[nodiscard]] virtual bool IsPersistent() const = 0;
|
||||
|
||||
/**
|
||||
* Checks if the recording of the AR session is running
|
||||
* @return True if recording is started
|
||||
*/
|
||||
[[nodiscard]] virtual bool IsRecording() const = 0;
|
||||
|
||||
/**
|
||||
* Sets the used recording mode
|
||||
* @param mode The mode that should be used to record the current session
|
||||
*/
|
||||
void SetRecordingMode(RecordingMode mode) { recordingMode = mode; }
|
||||
|
||||
/**
|
||||
* Chceks the currently used recording mode for the AR session
|
||||
* @return The currently used recording mode
|
||||
*/
|
||||
[[nodiscard]] RecordingMode SetRecordingMode() { return recordingMode; }
|
||||
|
||||
protected:
|
||||
RecordingMode recordingMode = RecordingMode::FRAME_REQUEST;
|
||||
};
|
||||
}
|
||||
132
openVulkanoCpp/AR/ArSession.cpp
Normal file
132
openVulkanoCpp/AR/ArSession.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 "ArSession.h"
|
||||
#ifndef __APPLE__
|
||||
#include "Provider/Playback/ArSessionPlayback.h"
|
||||
#endif
|
||||
#include "Provider/Network/ArSessionStream.h"
|
||||
#ifdef __APPLE__
|
||||
#include "Provider/ArKit/ArSessionArKit.h"
|
||||
#else
|
||||
#ifdef ANDROID
|
||||
#include "Provider/ArCore/ArSessionArCore.h"
|
||||
#else
|
||||
#include "Provider/ArSessionNull.hpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
std::vector<std::weak_ptr<ArSession>> ArSession::sessions;
|
||||
std::weak_ptr<ArSession> ArSession::nativeSession;
|
||||
|
||||
ArCreateResult ArSession::Create(const ArSessionConfig& config)
|
||||
{
|
||||
if (!IsNativeArAvailable())
|
||||
{
|
||||
return { nullptr, ArCreateResult::FAILED_NOT_SUPPORTED, "No native AR implementation available for current system." };
|
||||
}
|
||||
if (auto session = nativeSession.lock())
|
||||
{
|
||||
return { session, ArCreateResult::FAILED_ALREADY_CREATED, "Session has already been created. Return existing session." };
|
||||
}
|
||||
if (!GetNativeCapabilities().IsDepthSupported() && config.enableDepth)
|
||||
{
|
||||
return { nullptr, ArCreateResult::FAILED_INCOMPATIBLE_CONFIG, "AR depth is not supported on the current system." };
|
||||
}
|
||||
try
|
||||
{
|
||||
if (auto session = NATIVE_AR_SESSION_CLASS::Create(config))
|
||||
{
|
||||
return {session, ArCreateResult::SUCCESS, ""};
|
||||
}
|
||||
return { nullptr, ArCreateResult::FAILED_NOT_SUPPORTED, "No implementation for current system." };
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
return { nullptr, ArCreateResult::FAILED_UNKNOWN, e.what() };
|
||||
}
|
||||
catch (...) {}
|
||||
return { nullptr, ArCreateResult::FAILED_UNKNOWN, "Unknown exception while initializing AR system." };
|
||||
}
|
||||
|
||||
ArCreateResult ArSession::CreatePlayback(const std::string& recordingPath, bool autoAdvance)
|
||||
{
|
||||
return { nullptr, ArCreateResult::FAILED_NOT_SUPPORTED, "not yet implemented" };
|
||||
try
|
||||
{
|
||||
/*const auto session = std::make_shared<Playback::ArSessionPlayback>(recordingPath, autoAdvance);
|
||||
sessions.push_back(session);
|
||||
return { session, ArCreateResult::SUCCESS, "" };*/
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{ // TODO error handling
|
||||
return { nullptr, ArCreateResult::FAILED_INVALID_PATH, e.what() };
|
||||
}
|
||||
catch (...)
|
||||
{}
|
||||
return { nullptr, ArCreateResult::FAILED_UNKNOWN, "Unknown exception while initializing AR system." };
|
||||
}
|
||||
|
||||
ArCreateResult ArSession::CreateNetwork(const std::string& serverAddress, std::optional<ArSessionConfig> requestConfig)
|
||||
{
|
||||
return { nullptr, ArCreateResult::FAILED_NOT_SUPPORTED, "not yet implemented" };
|
||||
try
|
||||
{
|
||||
const auto session = std::make_shared<Network::ArSessionStream>(serverAddress, requestConfig);
|
||||
sessions.push_back(session);
|
||||
return { session, ArCreateResult::SUCCESS, "" };
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{} // TODO error handling
|
||||
catch (...)
|
||||
{}
|
||||
return { nullptr, ArCreateResult::FAILED_UNKNOWN, "Unknown exception while initializing networked AR system." };
|
||||
}
|
||||
|
||||
std::future<ArCreateResult> ArSession::CreateNetworkAsync(const std::string& serverAddress, std::optional<ArSessionConfig> requestConfig)
|
||||
{
|
||||
return std::async(&CreateNetwork, serverAddress, requestConfig);
|
||||
}
|
||||
|
||||
std::shared_ptr<ArSession> ArSession::GetPrimarySession()
|
||||
{
|
||||
const auto activeSessions = GetActiveSessions();
|
||||
if (activeSessions.empty()) return nullptr;
|
||||
return activeSessions[0];
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<ArSession>> ArSession::GetActiveSessions()
|
||||
{
|
||||
std::vector<std::shared_ptr<ArSession>> activeSessions;
|
||||
|
||||
auto it = sessions.begin();
|
||||
while(it != sessions.end())
|
||||
{
|
||||
if (auto activeSession = (*it).lock())
|
||||
{
|
||||
activeSessions.push_back(std::move(activeSession));
|
||||
}
|
||||
else
|
||||
{
|
||||
it = sessions.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
return activeSessions;
|
||||
}
|
||||
|
||||
bool ArSession::IsNativeArAvailable()
|
||||
{
|
||||
return NATIVE_AR_SESSION_CLASS::IsAvailable();
|
||||
}
|
||||
|
||||
const ArSessionCapabilities& ArSession::GetNativeCapabilities()
|
||||
{
|
||||
return NATIVE_AR_SESSION_CLASS::GetCapabilities();
|
||||
}
|
||||
}
|
||||
218
openVulkanoCpp/AR/ArSession.h
Normal file
218
openVulkanoCpp/AR/ArSession.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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 "ArType.hpp"
|
||||
#include "ArConstans.hpp"
|
||||
#include "ArTrackingState.hpp"
|
||||
#include "Math/Range.hpp"
|
||||
#include "Base/Event.hpp"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <future>
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
class ArSession;
|
||||
class ArFrame;
|
||||
class ArRecorder;
|
||||
|
||||
enum class ArSessionType
|
||||
{
|
||||
NATIVE, PLAYBACK, NETWORK_STREAM
|
||||
};
|
||||
|
||||
class ArSessionCapabilities final
|
||||
{
|
||||
ArType type = ArType::UNKNOWN;
|
||||
ArSessionType sessionType = ArSessionType::NATIVE;
|
||||
bool uncompressed = true;
|
||||
bool depthSupported = false;
|
||||
bool recordingSupported = false;
|
||||
|
||||
public:
|
||||
ArSessionCapabilities() = default;
|
||||
|
||||
ArSessionCapabilities(const ArType type, const ArSessionType sessionType, const bool uncompressed, const bool depthSupported, const bool recordingSupported)
|
||||
: type(type), sessionType(sessionType), uncompressed(uncompressed), depthSupported(depthSupported), recordingSupported(recordingSupported)
|
||||
{}
|
||||
|
||||
[[nodiscard]] bool IsUncompressed() const { return uncompressed; }
|
||||
[[nodiscard]] bool IsDepthSupported() const { return depthSupported; }
|
||||
[[nodiscard]] bool IsRecordingSupported() const { return recordingSupported; }
|
||||
[[nodiscard]] bool IsNative() const { return sessionType == ArSessionType::NATIVE; }
|
||||
[[nodiscard]] bool IsPlayback() const { return sessionType == ArSessionType::PLAYBACK; }
|
||||
[[nodiscard]] bool IsStream() const { return sessionType == ArSessionType::NETWORK_STREAM; }
|
||||
[[nodiscard]] ArType GetArType() const { return type; }
|
||||
[[nodiscard]] ArSessionType GetSessionType() const { return sessionType; }
|
||||
};
|
||||
|
||||
struct ArSessionConfig
|
||||
{
|
||||
bool enableDepth = true;
|
||||
};
|
||||
|
||||
struct ArCreateResult
|
||||
{
|
||||
enum Status { SUCCESS, FAILED_UNKNOWN, FAILED_INCOMPATIBLE_CONFIG, FAILED_ALREADY_CREATED, FAILED_NOT_SUPPORTED, FAILED_INVALID_PATH, FAILED_TIMEOUT, FAILED_INVALID_SERVER };
|
||||
|
||||
const std::shared_ptr<ArSession> session;
|
||||
const Status status;
|
||||
const std::string statusMessage;
|
||||
|
||||
[[nodiscard]] bool IsSuccess() const { return status == SUCCESS; }
|
||||
};
|
||||
|
||||
class ArSession
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a platform native AR session. nullptr if failed to create session.
|
||||
* @return ArCreateResult about the status of the AR session creation. The session pointer will always be nullptr unless the status is SUCCESS or FAILED_ALREADY_CREATED (in this case the session pointer will point to the previously created instance).
|
||||
*/
|
||||
[[nodiscard]] static ArCreateResult Create(const ArSessionConfig& config = {});
|
||||
|
||||
/**
|
||||
* Creates a playback AR session. nullptr if failed to create session for given path.
|
||||
* @param recordingPath Path to a previously recorded AR session.
|
||||
* @param autoAdvance If set to true the playback will advance based on the stored timestamps. If set to false it will only advance if a new frame is requested.
|
||||
* @return ArCreateResult about the status of the AR session creation. The session pointer will always be nullptr unless the status is SUCCESS.
|
||||
*/
|
||||
[[nodiscard]] static ArCreateResult CreatePlayback(const std::string& recordingPath, bool autoAdvance = true);
|
||||
|
||||
/**
|
||||
* Creates a network streamed AR session. nullptr if failed to create session for given address. This will block till the connection with the remote host has been established.
|
||||
* @param serverAddress The address of the server that is hosting the AR session.
|
||||
* @param requestConfig An optional config to be requested. It is not guaranteed that this will be honored (especially in multi guest sessions).
|
||||
* @return ArCreateResult about the status of the AR session creation. The session pointer will always be nullptr unless the status is SUCCESS.
|
||||
*/
|
||||
[[nodiscard]] static ArCreateResult CreateNetwork(const std::string& serverAddress, std::optional<ArSessionConfig> requestConfig = std::nullopt);
|
||||
|
||||
/**
|
||||
* Creates a network streamed AR session. nullptr if failed to create session for given address.
|
||||
* @param serverAddress The address of the server that is hosting the AR session.
|
||||
* @param requestConfig An optional config to be requested. It is not guaranteed that this will be honored (especially in multi guest sessions).
|
||||
* @return ArCreateResult about the status of the AR session creation. The session pointer will always be nullptr unless the status is SUCCESS.
|
||||
*/
|
||||
[[nodiscard]] static std::future<ArCreateResult> CreateNetworkAsync(const std::string& serverAddress, std::optional<ArSessionConfig> requestConfig = std::nullopt);
|
||||
|
||||
/**
|
||||
* Gets the primary session. This is the longest running session.
|
||||
* @return The primary ar session. nullptr if no active session.
|
||||
*/
|
||||
[[nodiscard]] static std::shared_ptr<ArSession> GetPrimarySession();
|
||||
|
||||
/**
|
||||
* Gets all the active ar sessions.
|
||||
* @return Vector of active ar sessions.
|
||||
*/
|
||||
[[nodiscard]] static std::vector<std::shared_ptr<ArSession>> GetActiveSessions();
|
||||
|
||||
/**
|
||||
* Gets the capabilities of the native AR system.
|
||||
* @return ArSessionCapabilities for the current system.
|
||||
*/
|
||||
[[nodiscard]] static const ArSessionCapabilities& GetNativeCapabilities();
|
||||
|
||||
/**
|
||||
* Checks if a native AR implementation is available for this system. If false the Create(...) call will fail and only CreatePlayback(...) and CreateNetwork(...) are available.
|
||||
* @return true if there is a native AR system available. false if not.
|
||||
*/
|
||||
static bool IsNativeArAvailable();
|
||||
|
||||
virtual ~ArSession() = default;
|
||||
|
||||
/**
|
||||
* Starts the AR session.
|
||||
*/
|
||||
virtual void Start() = 0;
|
||||
|
||||
/**
|
||||
* Stops the AR session.
|
||||
*/
|
||||
virtual void Stop() = 0;
|
||||
|
||||
/**
|
||||
* Pauses the AR session. The behaviour of this will depend on the type of the AR session.
|
||||
* The type can be checked with the GetSessionType() method.
|
||||
* NATIVE: The session will continue to run, but GetFrame() will block until continued and events will not be triggered.
|
||||
* PLAYBACK: There will be no new frames being read from the recording until continued. As a result GetFrame() will block until continued and no events will be triggered.
|
||||
* NETWORK_STREAM: The session on the remote host will stay active. Data might still be sent to the client (in multi client mode). But no data will be forwarded to app and thus GetFrame() will block until continued and no events will be triggered.
|
||||
*/
|
||||
virtual void Pause() { paused = true; }
|
||||
|
||||
/**
|
||||
* Checks if the AR session is running. Will be true while paused!
|
||||
* @return True if the AR session is running. False if not.
|
||||
*/
|
||||
[[nodiscard]] virtual bool IsRunning() const { return running; };
|
||||
|
||||
/**
|
||||
* Checks if the AR session is paused.
|
||||
* @return True if the AR session is paused. False if not.
|
||||
*/
|
||||
[[nodiscard]] virtual bool IsPaused() const { return paused; };
|
||||
|
||||
/**
|
||||
* Gets the next ArFrame. Is guaranteed to be a new frame. Will block till new frame is available or an internal timeout is reached.
|
||||
* @return Next ArFrame, or nullptr if no more frames are available or internal timeout was reached.
|
||||
*/
|
||||
[[nodiscard]] virtual std::shared_ptr<ArFrame> GetFrame() = 0;
|
||||
|
||||
/**
|
||||
* The ArRecorder for this ArSession.
|
||||
* @return ArRecorder instance or nullptr if the ArSession does not support recording.
|
||||
*/
|
||||
[[nodiscard]] virtual ArRecorder* GetRecorder() = 0;
|
||||
|
||||
/**
|
||||
* Gets the type of the AR session.
|
||||
* @return Type of the AR session.
|
||||
*/
|
||||
[[nodiscard]] virtual ArSessionType GetSessionType() = 0;
|
||||
|
||||
/**
|
||||
* Gets the type of the AR system backed by this session.
|
||||
* @return The type of the AR system used by this session.
|
||||
*/
|
||||
[[nodiscard]] virtual ArType GetArType() = 0;
|
||||
|
||||
virtual void RequestHighResolutionFrame() {}
|
||||
|
||||
/**
|
||||
* Gets the capabilities for this ArSession.
|
||||
* @return The capabilities for the current AR session.
|
||||
*/
|
||||
[[nodiscard]] const ArSessionCapabilities& GetCapabilities() const { return capabilities; };
|
||||
|
||||
[[nodiscard]] const ArConstants& GetConstants() const { return constants; }
|
||||
|
||||
[[nodiscard]] bool GetShouldAttemptRelocalization() { return shouldAttemptRelocalization; }
|
||||
|
||||
void SetShouldAttemptRelocalization(bool attemptReloc) { shouldAttemptRelocalization = attemptReloc; }
|
||||
|
||||
Event<> OnNewFrameAvailable;
|
||||
Event<const std::shared_ptr<ArFrame>&> OnNewFrame;
|
||||
Event<bool> OnSessionInterruptionChange;
|
||||
Event<ArTrackingState> OnTrackingStateChanged;
|
||||
Event<const Math::Matrix4f&> OnNewCameraTransformation;
|
||||
Event<const Math::Matrix4f&> OnNewCameraViewMatrix;
|
||||
Event<const std::string&> OnSessionFailed;
|
||||
Event<> OnAnchorsUpdated;
|
||||
|
||||
protected:
|
||||
bool running = false, paused = false, shouldAttemptRelocalization = false;
|
||||
ArSessionCapabilities capabilities;
|
||||
ArConstants constants;
|
||||
|
||||
private:
|
||||
static std::vector<std::weak_ptr<ArSession>> sessions;
|
||||
static std::weak_ptr<ArSession> nativeSession;
|
||||
};
|
||||
}
|
||||
99
openVulkanoCpp/AR/ArTrackingState.hpp
Normal file
99
openVulkanoCpp/AR/ArTrackingState.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 <magic_enum.hpp>
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
class ArTrackingState final
|
||||
{
|
||||
static inline constexpr std::string_view ALT_NAMES[] = {
|
||||
"unknown", "notAvailable", "limitedInitializing",
|
||||
"limitedRelocalizing", "limitedExcessiveMotion",
|
||||
"limitedInsufficientFeatures", "normal", "paused"
|
||||
};
|
||||
|
||||
public:
|
||||
enum State : uint8_t
|
||||
{
|
||||
UNKNOWN,
|
||||
UNAVAILABLE,
|
||||
INITIALIZING,
|
||||
RELOCALIZING,
|
||||
EXCESSIVE_MOTION,
|
||||
INSUFFICIENT_FEATURES,
|
||||
NORMAL,
|
||||
PAUSED
|
||||
};
|
||||
|
||||
ArTrackingState() : ArTrackingState(UNKNOWN) {}
|
||||
|
||||
ArTrackingState(State state) : m_state(state) {}
|
||||
|
||||
[[nodiscard]] constexpr bool IsLimited() const
|
||||
{
|
||||
return m_state > UNAVAILABLE && m_state < NORMAL;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsUnavailable() const
|
||||
{
|
||||
return m_state == PAUSED || m_state == UNAVAILABLE;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsGood() const
|
||||
{
|
||||
return m_state == NORMAL;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool IsPaused() const
|
||||
{
|
||||
return m_state == PAUSED;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::string_view GetName() const
|
||||
{
|
||||
return magic_enum::enum_name(m_state);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::string_view GetAltName() const
|
||||
{
|
||||
return ALT_NAMES[m_state];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator ==(State rhs)
|
||||
{
|
||||
return m_state == rhs;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator !=(State rhs)
|
||||
{
|
||||
return m_state != rhs;
|
||||
}
|
||||
|
||||
static ArTrackingState GetFromName(std::string_view name)
|
||||
{
|
||||
auto result = magic_enum::enum_cast<State>(name);
|
||||
if (result.has_value()) return ArTrackingState(result.value());
|
||||
return GetFromAltName(name);
|
||||
}
|
||||
|
||||
static ArTrackingState GetFromAltName(std::string_view name)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
for(const std::string_view& n : ALT_NAMES)
|
||||
{
|
||||
if (n == name) return static_cast<State>(i);
|
||||
i++;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
private:
|
||||
State m_state;
|
||||
};
|
||||
}
|
||||
55
openVulkanoCpp/AR/ArType.hpp
Normal file
55
openVulkanoCpp/AR/ArType.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 <magic_enum.hpp>
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
class ArType final
|
||||
{
|
||||
static inline constexpr std::string_view HUMAN_READABLE_NAMES[] = { "Unknown", "ARKit", "ARCore" };
|
||||
|
||||
public:
|
||||
enum Type : uint8_t { UNKNOWN = 0, AR_KIT, AR_CORE };
|
||||
|
||||
ArType() : ArType(UNKNOWN) {}
|
||||
|
||||
ArType(Type type) : m_type(type) {}
|
||||
|
||||
[[nodiscard]] std::string_view GetName() const
|
||||
{
|
||||
return magic_enum::enum_name(m_type);
|
||||
}
|
||||
|
||||
static ArType GetFromName(std::string_view name)
|
||||
{
|
||||
auto result = magic_enum::enum_cast<Type>(name);
|
||||
if (result.has_value()) return { result.value() };
|
||||
return GetFromHumanReadableName(name);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string_view& GetHumanReadableName() const
|
||||
{
|
||||
return HUMAN_READABLE_NAMES[m_type];
|
||||
}
|
||||
|
||||
static ArType GetFromHumanReadableName(const std::string_view& name)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
for (const std::string_view& n : HUMAN_READABLE_NAMES)
|
||||
{
|
||||
if (n == name) return {static_cast<Type>(i)};
|
||||
i++;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
};
|
||||
}
|
||||
26
openVulkanoCpp/AR/Provider/ArCore/ArSessionArCore.cpp
Normal file
26
openVulkanoCpp/AR/Provider/ArCore/ArSessionArCore.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 "ArSessionArCore.h"
|
||||
|
||||
namespace openVulkanoCpp::AR::ArCore
|
||||
{
|
||||
std::shared_ptr<ArSession> ArSessionArCore::Create(const ArSessionConfig& config)
|
||||
{
|
||||
return nullptr; // TODO
|
||||
}
|
||||
|
||||
bool ArSessionArCore::IsAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const ArSessionCapabilities& ArSessionArCore::GetCapabilities()
|
||||
{
|
||||
static ArSessionCapabilities capabilities; // TODO setup
|
||||
return capabilities;
|
||||
}
|
||||
}
|
||||
32
openVulkanoCpp/AR/Provider/ArCore/ArSessionArCore.h
Normal file
32
openVulkanoCpp/AR/Provider/ArCore/ArSessionArCore.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 "AR/ArSession.h"
|
||||
|
||||
// Define the class of the native AR session to be used
|
||||
#define NATIVE_AR_SESSION_CLASS ArCore::ArSessionArCore
|
||||
|
||||
namespace openVulkanoCpp::AR::ArCore
|
||||
{
|
||||
class ArSessionArCore : public ArSession
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] static std::shared_ptr<ArSession> Create(const ArSessionConfig& config);
|
||||
|
||||
[[nodiscard]] static bool IsAvailable();
|
||||
|
||||
[[nodiscard]] static const ArSessionCapabilities& GetCapabilities();
|
||||
|
||||
[[nodiscard]] ArSessionType GetSessionType() final { return ArSessionType::NATIVE; }
|
||||
|
||||
[[nodiscard]] ArType GetArType() final { return ArType::AR_CORE; }
|
||||
|
||||
protected:
|
||||
~ArSessionArCore() override = default;
|
||||
};
|
||||
}
|
||||
35
openVulkanoCpp/AR/Provider/ArSessionNull.hpp
Normal file
35
openVulkanoCpp/AR/Provider/ArSessionNull.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "AR/ArSession.h"
|
||||
|
||||
// Define the class of the native AR session to be used
|
||||
#define NATIVE_AR_SESSION_CLASS ArSessionNull
|
||||
|
||||
namespace openVulkanoCpp::AR
|
||||
{
|
||||
struct ArSessionNull final
|
||||
{
|
||||
inline static const ArSessionCapabilities AR_CAPS_UNAVAILABLE;
|
||||
|
||||
static std::shared_ptr<ArSession> Create(const ArSessionConfig& config)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool IsAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static const ArSessionCapabilities& GetCapabilities()
|
||||
{
|
||||
return AR_CAPS_UNAVAILABLE;
|
||||
}
|
||||
};
|
||||
}
|
||||
40
openVulkanoCpp/AR/Provider/Network/ArSessionStream.cpp
Normal file
40
openVulkanoCpp/AR/Provider/Network/ArSessionStream.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 "ArSessionStream.h"
|
||||
|
||||
namespace openVulkanoCpp::AR::Network
|
||||
{
|
||||
ArSessionStream::ArSessionStream(const std::string& serverAddress, std::optional<ArSessionConfig> requestConfig)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void ArSessionStream::Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ArSessionStream::Stop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ArSessionStream::Pause()
|
||||
{
|
||||
ArSession::Pause();
|
||||
}
|
||||
|
||||
std::shared_ptr<ArFrame> ArSessionStream::GetFrame()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ArType ArSessionStream::GetArType()
|
||||
{
|
||||
return GetCapabilities().GetArType();
|
||||
}
|
||||
}
|
||||
35
openVulkanoCpp/AR/Provider/Network/ArSessionStream.h
Normal file
35
openVulkanoCpp/AR/Provider/Network/ArSessionStream.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "AR/ArSession.h"
|
||||
|
||||
namespace openVulkanoCpp::AR::Network
|
||||
{
|
||||
class ArSessionStream final : public ArSession
|
||||
{
|
||||
public:
|
||||
ArSessionStream(const std::string& serverAddress, std::optional<ArSessionConfig> requestConfig = std::nullopt);
|
||||
|
||||
~ArSessionStream() override = default;
|
||||
|
||||
void Start() override;
|
||||
|
||||
void Stop() override;
|
||||
|
||||
void Pause() override;
|
||||
|
||||
[[nodiscard]] std::shared_ptr<ArFrame> GetFrame() override;
|
||||
|
||||
[[nodiscard]] ArRecorder* GetRecorder() override { return nullptr; }
|
||||
|
||||
[[nodiscard]] ArSessionType GetSessionType() override { return ArSessionType::NETWORK_STREAM; }
|
||||
|
||||
[[nodiscard]] ArType GetArType() override;
|
||||
};
|
||||
}
|
||||
|
||||
52
openVulkanoCpp/AR/Provider/Playback/ArFramePlayback.hpp
Normal file
52
openVulkanoCpp/AR/Provider/Playback/ArFramePlayback.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 "AR/ArFrame.h"
|
||||
#include "ArPlaybackReader.hpp"
|
||||
#include "ArPlaybackData.hpp"
|
||||
|
||||
namespace openVulkanoCpp::AR::Playback
|
||||
{
|
||||
class ArSessionPlayback;
|
||||
|
||||
class ArFramePlayback final : public ArFrame
|
||||
{
|
||||
public:
|
||||
ArFramePlayback(const std::shared_ptr<ArSessionPlayback>& session, ArPlaybackReader& frameReader);
|
||||
|
||||
ArTrackingState GetTrackingState() override;
|
||||
|
||||
Math::PoseF GetPose() override;
|
||||
|
||||
Math::Timestamp GetTimestamp() override;
|
||||
|
||||
ArImagePlanar GetCameraImage() override;
|
||||
|
||||
ArDepthImage GetDepthImage() override;
|
||||
|
||||
const Math::Matrix4f& GetCameraTransformation() override;
|
||||
|
||||
Math::Matrix4f GetCameraViewForCurrentDeviceOrientation() override;
|
||||
|
||||
Math::Matrix4f GetCameraProjection(Math::Vector2f viewportSize, float near, float far) override;
|
||||
|
||||
float GetConfidenceNormalisationFactor() override;
|
||||
|
||||
[[nodiscard]] float GetColorTemperature() const override;
|
||||
|
||||
private:
|
||||
ArPlaybackFrameData frameData;
|
||||
ArImagePlanar colorImage;
|
||||
ArDepthImage depthImage;
|
||||
|
||||
std::unique_ptr<char[]> confImgData;
|
||||
std::unique_ptr<float[]> depthImgData;
|
||||
ColorImg colorImgData;
|
||||
//cv::Mat colorImgData;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user