7#include <OxygenEngine/util/non_copyable.h> 
    8#include <OxygenEngine/core/window.h> 
    9#include <OxygenEngine/render/texture.h> 
   11#include <glm/mat4x4.hpp> 
   19    typedef uint64_t VROverlayHandle_t;
 
   20    typedef uint32_t TrackedDeviceIndex_t;
 
   45            static System generateForScene();
 
   75            ::vr::IVRSystem* _raw_system = 
nullptr;
 
   77            System(
const uint32_t& type);
 
 
  128            uint64_t getFirmwareVersion();
 
  129            int32_t getUsageTimeSinceFirstStarted();
 
  132            ::vr::TrackedDeviceIndex_t _handle = 0;
 
  133            System* _parent = 
nullptr;
 
 
  156            Overlay(
const std::string& key, 
const std::string& name = 
"");
 
  191            void bindToDevice(
const std::unique_ptr<TrackedDevice>& device, 
const glm::mat4& matrix = glm::mat4(1.0));
 
  194            ::vr::IVROverlay* _manager = 
nullptr;
 
  195            ::vr::VROverlayHandle_t _handle = 0;
 
 
 
  208#ifdef OE_EXT_VR_IMPLEMENTATION 
  211#include <openvr/openvr.h> 
  212#include <GLFW/glfw3.h> 
  224static ::vr::HmdMatrix34_t convertMat4ToHmd34(
const glm::mat4& matrix)
 
  227        matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
 
  228        matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
 
  229        matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
 
  235    return ::vr::VR_IsHmdPresent() && ::vr::VR_IsRuntimeInstalled();
 
  238oe::ext::vr::System::System(
const uint32_t& type)
 
  240    ::vr::EVRInitError err = ::vr::VRInitError_None;
 
  242    _raw_system = ::vr::VR_Init(&err, (::vr::EVRApplicationType)type);
 
  244    if (err != ::vr::VRInitError_None)
 
  245        throw std::runtime_error(::vr::VR_GetVRInitErrorAsEnglishDescription(err));
 
  247    if (!::vr::VRCompositor())
 
  248        throw std::runtime_error(
"Unable to initialize VR compositor!\n ");
 
  253    return {::vr::VRApplication_Scene};
 
  258    return {::vr::VRApplication_Overlay};
 
  263    std::unique_ptr<oe::ext::vr::TrackedDevice> result = std::make_unique<TrackedDevice>(
this);
 
  265    result->_handle = ::vr::k_unTrackedDeviceIndex_Hmd;
 
  272    std::unique_ptr<oe::ext::vr::TrackedDevice> result;
 
  274    ::vr::TrackedDeviceIndex_t 
id = _raw_system->GetTrackedDeviceIndexForControllerRole(::vr::TrackedControllerRole_LeftHand);
 
  276    if (
id != ::vr::k_unTrackedDeviceIndexInvalid && 
id != ::vr::k_unTrackedDeviceIndex_Hmd)
 
  278        result = std::make_unique<TrackedDevice>(
this);
 
  280        result->_handle = id;
 
  288    std::unique_ptr<oe::ext::vr::TrackedDevice> result;
 
  290    ::vr::TrackedDeviceIndex_t 
id = _raw_system->GetTrackedDeviceIndexForControllerRole(::vr::TrackedControllerRole_RightHand);
 
  292    if (
id != ::vr::k_unTrackedDeviceIndexInvalid && 
id != ::vr::k_unTrackedDeviceIndex_Hmd)
 
  294        result = std::make_unique<TrackedDevice>(
this);
 
  296        result->_handle = id;
 
  304    std::vector<std::unique_ptr<TrackedDevice>> result;
 
  306    uint32_t maxTrackedDevices = ::vr::k_unMaxTrackedDeviceCount;
 
  308    for (
unsigned int id = 0; 
id<maxTrackedDevices; ++id)
 
  310        if (_raw_system->GetTrackedDeviceClass(
id) == ::vr::TrackedDeviceClass_Invalid)
 
  313        auto device = std::make_unique<TrackedDevice>(
this);
 
  315        device->_handle = id;
 
  317        result.push_back(std::move(device));
 
  325    return _parent->_raw_system->GetTrackedDeviceClass(_handle) != ::vr::TrackedDeviceClass_Invalid;
 
  328bool oe::ext::vr::TrackedDevice::isHmd()
 
  330    return _handle == ::vr::k_unTrackedDeviceIndex_Hmd;
 
  333#define GENERATE_OPENVR_GETTER(TYPE, METHOD, PROPERTY) \ 
  334TYPE oe::ext::vr::TrackedDevice::METHOD() \ 
  337    assert(isValid() && "Device not valid"); \ 
  339    ::vr::ETrackedPropertyError error = ::vr::TrackedProp_Success; \ 
  341    TYPE result = getPropertyOpenVR<TYPE>(_parent->_raw_system, _handle, ::vr::PROPERTY, &error); \ 
  353static T getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError *error)
 
  355    throw std::runtime_error(
"Unknown Type!");
 
  359bool getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
 
  361    return system->GetBoolTrackedDeviceProperty(handle, prop, error);
 
  365float getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
 
  367    return system->GetFloatTrackedDeviceProperty(handle, prop, error);
 
  371int32_t getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
 
  373    return system->GetInt32TrackedDeviceProperty(handle, prop, error);
 
  377uint64_t getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
 
  379    return system->GetUint64TrackedDeviceProperty(handle, prop, error);
 
  383std::string getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
 
  385    uint32_t bufferLength = system->GetStringTrackedDeviceProperty(handle, prop, NULL, 0, error);
 
  387    if (bufferLength == 0)
 
  390    char *buffer = 
new char[bufferLength];
 
  391    bufferLength = system->GetStringTrackedDeviceProperty(handle, prop, buffer, bufferLength, error );
 
  393    std::string result = buffer;
 
  400GENERATE_OPENVR_GETTER(std::string, getModel, Prop_ModelNumber_String)
 
  401GENERATE_OPENVR_GETTER(std::string, getSerialNumber, Prop_SerialNumber_String)
 
  402GENERATE_OPENVR_GETTER(
bool, isWireless, Prop_DeviceIsWireless_Bool)
 
  403GENERATE_OPENVR_GETTER(
bool, isCharging, Prop_DeviceIsCharging_Bool)
 
  404GENERATE_OPENVR_GETTER(
float, getBatteryCharge, Prop_DeviceBatteryPercentage_Float)
 
  405GENERATE_OPENVR_GETTER(uint64_t, getFirmwareVersion, Prop_FirmwareVersion_Uint64)
 
  406GENERATE_OPENVR_GETTER(int32_t, getUsageTimeSinceFirstStarted, Prop_EstimatedDeviceFirstUseTime_Int32)
 
  408#undef GENERATE_OPENVR_GETTER 
  410oe::ext::vr::Overlay::Overlay(
const std::string& key, 
const std::string& name)
 
  412    _manager = ::vr::VROverlay();
 
  414    assert(_manager != 
nullptr);
 
  416    _manager->CreateOverlay(key.c_str(), name != 
"" ? name.c_str() : key.c_str(), &_handle);
 
  417    _manager->SetOverlayInputMethod(_handle, ::vr::VROverlayInputMethod_Mouse);
 
  420    ::vr::VRTextureBounds_t bounds;
 
  425    _manager->SetOverlayTextureBounds(_handle, &bounds );
 
  427    _manager->SetOverlayFlag(_handle, ::vr::VROverlayFlags_SendVRSmoothScrollEvents, 
true);
 
  432    _manager->ShowOverlay(_handle);
 
  435oe::ext::vr::Overlay::~Overlay()
 
  442    _manager->SetOverlayWidthInMeters(_handle, meters);
 
  445static const std::map<uint32_t, uint32_t> OPENVR_TO_GLFW_MOUSE_BUTTONS = {
 
  446    {::vr::VRMouseButton_Left, GLFW_MOUSE_BUTTON_LEFT},
 
  447    {::vr::VRMouseButton_Middle, GLFW_MOUSE_BUTTON_MIDDLE},
 
  448    {::vr::VRMouseButton_Right, GLFW_MOUSE_BUTTON_RIGHT},
 
  453    ::vr::VREvent_t vrEvent;
 
  455    while (_manager->PollNextOverlayEvent(_handle, &vrEvent, 
sizeof(vrEvent)))
 
  459        switch( vrEvent.eventType )
 
  461            case ::vr::VREvent_MouseMove:
 
  465                event_handler.
setCursorPos({window_dimensions.x*vrEvent.data.mouse.x, window_dimensions.y * (1.0f-vrEvent.data.mouse.y)});
 
  469            case ::vr::VREvent_ScrollSmooth:
 
  471                event_handler.setMouseScroll(vrEvent.data.scroll.viewportscale * glm::vec2(vrEvent.data.scroll.xdelta, vrEvent.data.scroll.ydelta));
 
  475            case ::vr::VREvent_MouseButtonDown:
 
  477                event_handler.
forceState(OPENVR_TO_GLFW_MOUSE_BUTTONS.at(vrEvent.data.mouse.button), 
true, 
true);
 
  481            case ::vr::VREvent_MouseButtonUp:
 
  483                event_handler.
forceState(OPENVR_TO_GLFW_MOUSE_BUTTONS.at(vrEvent.data.mouse.button), 
false, 
true);
 
  492    ::vr::HmdMatrix34_t openvr_matrix = convertMat4ToHmd34(matrix);
 
  494    _manager->SetOverlayTransformTrackedDeviceRelative(_handle, device->_handle, &openvr_matrix);
 
  499    _manager->SetOverlayFlag(_handle, ::vr::VROverlayFlags_SideBySide_Parallel, enable);
 
  506    _manager->GetOverlayFlag(_handle, ::vr::VROverlayFlags_SideBySide_Parallel, &result);
 
  513    struct ::vr::Texture_t overlay_texture;
 
  514    overlay_texture.eColorSpace = ::vr::ColorSpace_Auto;
 
  515    overlay_texture.eType = ::vr::TextureType_OpenGL;
 
  516    overlay_texture.handle = 
reinterpret_cast<uintptr_t*
>(texture->getHandle());
 
  518    _manager->SetOverlayTexture(_handle, &overlay_texture);
 
  531oe::ext::vr::TrackedDevice::TrackedDevice(System* parent)
 
Event handler.
Definition event_handler.h:22
void setCursorPos(const glm::vec2 &cursor_pos) noexcept
Definition event_handler.h:148
void forceState(const key_code_t &key, const int &state, const bool &isMouse=false) noexcept
Force key or mouse button status, ignoring the real status.
Common properties to all VR applications (overlay, scene, etc...)
Definition vr.h:146
VR Overlay Application.
Definition vr.h:154
void bindToDevice(const std::unique_ptr< TrackedDevice > &device, const glm::mat4 &matrix=glm::mat4(1.0))
Attach the overlay to a tracked device.
bool isUsingStereoRendering()
Check if stereo rendering is enabled.
void useStereoRendering(const bool enable=true)
Tell overlay to split texture to left/right eye.
void submitTexture(const std::shared_ptr< oe::render::Texture > &texture)
Send texture to the Overlay.
void handleEvents(oe::core::EventHandler &event_handler, const glm::ivec2 &window_dimensions)
Handle Overlay events and send them to an event_handler.
void setRatio(const float &width)
Set Overlay ratio By default the ratio is 1.0, meaning that the sent texture width will equals 1 mete...
VR Scene Application (ie. Game)
Definition vr.h:202
VR System.
Definition vr.h:43
static System generateForOverlay()
Generate a system for an overlay application.
std::vector< std::unique_ptr< TrackedDevice > > getAllTrackedDevices()
Returns all devices used on this VR system.
std::unique_ptr< TrackedDevice > getTrackedLeftHandDevice()
Get the device used as left hand.
std::unique_ptr< TrackedDevice > getTrackedRightHandDevice()
Get the device used as right hand.
std::unique_ptr< TrackedDevice > getTrackedHmdDevice()
Get the device used as HMD.
VR Device that can track data (HMD / Controller / Tracker / etc...)
Definition vr.h:84
bool isCharging()
Check if the device battery is charging.
std::string getSerialNumber()
Get the device unique serial number.
bool isValid()
Check if device is still available or disconnected / shutdown.
float getBatteryCharge()
Get if the device battery level.
std::string getModel()
Get the device model.
bool isWireless()
Check if the device can work without being connected.
Prevent class to be copied.
Definition non_copyable.h:12
Interact with Virtual Reality.
Definition vr.h:29
bool canUseVr()
Run checks to ensure there are VR capabilities.