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();
70 ::vr::IVRSystem* _raw_system =
nullptr;
72 System(
const uint32_t& type);
123 uint64_t getFirmwareVersion();
124 int32_t getUsageTimeSinceFirstStarted();
127 ::vr::TrackedDeviceIndex_t _handle = 0;
128 System* _parent =
nullptr;
151 Overlay(
const std::string& key,
const std::string& name =
"");
186 void bindToDevice(
const std::unique_ptr<TrackedDevice>& device,
const glm::mat4& matrix = glm::mat4(1.0));
189 ::vr::IVROverlay* _manager =
nullptr;
190 ::vr::VROverlayHandle_t _handle = 0;
203#ifdef OE_EXT_VR_IMPLEMENTATION
206#include <openvr/openvr.h>
207#include <GLFW/glfw3.h>
219static ::vr::HmdMatrix34_t convertMat4ToHmd34(
const glm::mat4& matrix)
222 matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
223 matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
224 matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
230 return ::vr::VR_IsHmdPresent() && ::vr::VR_IsRuntimeInstalled();
233oe::ext::vr::System::System(
const uint32_t& type)
235 ::vr::EVRInitError err = ::vr::VRInitError_None;
237 _raw_system = ::vr::VR_Init(&err, (::vr::EVRApplicationType)type);
239 if (err != ::vr::VRInitError_None)
240 throw std::runtime_error(::vr::VR_GetVRInitErrorAsEnglishDescription(err));
242 if (!::vr::VRCompositor())
243 throw std::runtime_error(
"Unable to initialize VR compositor!\n ");
248 return {::vr::VRApplication_Scene};
253 return {::vr::VRApplication_Overlay};
258 std::unique_ptr<oe::ext::vr::TrackedDevice> result;
260 ::vr::TrackedDeviceIndex_t
id = _raw_system->GetTrackedDeviceIndexForControllerRole(::vr::TrackedControllerRole_LeftHand);
262 if (
id != ::vr::k_unTrackedDeviceIndexInvalid &&
id != ::vr::k_unTrackedDeviceIndex_Hmd)
264 result = std::make_unique<TrackedDevice>(
this);
266 result->_handle = id;
274 std::unique_ptr<oe::ext::vr::TrackedDevice> result;
276 ::vr::TrackedDeviceIndex_t
id = _raw_system->GetTrackedDeviceIndexForControllerRole(::vr::TrackedControllerRole_RightHand);
278 if (
id != ::vr::k_unTrackedDeviceIndexInvalid &&
id != ::vr::k_unTrackedDeviceIndex_Hmd)
280 result = std::make_unique<TrackedDevice>(
this);
282 result->_handle = id;
290 std::vector<std::unique_ptr<TrackedDevice>> result;
292 uint32_t maxTrackedDevices = ::vr::k_unMaxTrackedDeviceCount;
294 for (
unsigned int id = 0;
id<maxTrackedDevices; ++id)
296 if (_raw_system->GetTrackedDeviceClass(
id) == ::vr::TrackedDeviceClass_Invalid)
299 auto device = std::make_unique<TrackedDevice>(
this);
301 device->_handle = id;
303 result.push_back(std::move(device));
311 return _parent->_raw_system->GetTrackedDeviceClass(_handle) != ::vr::TrackedDeviceClass_Invalid;
314bool oe::ext::vr::TrackedDevice::isHmd()
316 return _handle == ::vr::k_unTrackedDeviceIndex_Hmd;
319#define GENERATE_OPENVR_GETTER(TYPE, METHOD, PROPERTY) \
320TYPE oe::ext::vr::TrackedDevice::METHOD() \
323 assert(isValid() && "Device not valid"); \
325 ::vr::ETrackedPropertyError error = ::vr::TrackedProp_Success; \
327 TYPE result = getPropertyOpenVR<TYPE>(_parent->_raw_system, _handle, ::vr::PROPERTY, &error); \
339static T getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError *error)
341 throw std::runtime_error(
"Unknown Type!");
345bool getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
347 return system->GetBoolTrackedDeviceProperty(handle, prop, error);
351float getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
353 return system->GetFloatTrackedDeviceProperty(handle, prop, error);
357int32_t getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
359 return system->GetInt32TrackedDeviceProperty(handle, prop, error);
363uint64_t getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
365 return system->GetUint64TrackedDeviceProperty(handle, prop, error);
369std::string getPropertyOpenVR(::vr::IVRSystem* system, ::vr::TrackedDeviceIndex_t handle, ::vr::TrackedDeviceProperty prop, ::vr::TrackedPropertyError* error)
371 uint32_t bufferLength = system->GetStringTrackedDeviceProperty(handle, prop, NULL, 0, error);
373 if (bufferLength == 0)
376 char *buffer =
new char[bufferLength];
377 bufferLength = system->GetStringTrackedDeviceProperty(handle, prop, buffer, bufferLength, error );
379 std::string result = buffer;
386GENERATE_OPENVR_GETTER(std::string, getModel, Prop_ModelNumber_String)
387GENERATE_OPENVR_GETTER(std::string, getSerialNumber, Prop_SerialNumber_String)
388GENERATE_OPENVR_GETTER(
bool, isWireless, Prop_DeviceIsWireless_Bool)
389GENERATE_OPENVR_GETTER(
bool, isCharging, Prop_DeviceIsCharging_Bool)
390GENERATE_OPENVR_GETTER(
float, getBatteryCharge, Prop_DeviceBatteryPercentage_Float)
391GENERATE_OPENVR_GETTER(uint64_t, getFirmwareVersion, Prop_FirmwareVersion_Uint64)
392GENERATE_OPENVR_GETTER(int32_t, getUsageTimeSinceFirstStarted, Prop_EstimatedDeviceFirstUseTime_Int32)
394#undef GENERATE_OPENVR_GETTER
396oe::ext::vr::Overlay::Overlay(
const std::string& key,
const std::string& name)
398 _manager = ::vr::VROverlay();
400 assert(_manager !=
nullptr);
402 _manager->CreateOverlay(key.c_str(), name !=
"" ? name.c_str() : key.c_str(), &_handle);
403 _manager->SetOverlayInputMethod(_handle, ::vr::VROverlayInputMethod_Mouse);
406 ::vr::VRTextureBounds_t bounds;
411 _manager->SetOverlayTextureBounds(_handle, &bounds );
413 _manager->SetOverlayFlag(_handle, ::vr::VROverlayFlags_SendVRSmoothScrollEvents,
true);
418 _manager->ShowOverlay(_handle);
421oe::ext::vr::Overlay::~Overlay()
428 _manager->SetOverlayWidthInMeters(_handle, meters);
431static const std::map<uint32_t, uint32_t> OPENVR_TO_GLFW_MOUSE_BUTTONS = {
432 {::vr::VRMouseButton_Left, GLFW_MOUSE_BUTTON_LEFT},
433 {::vr::VRMouseButton_Middle, GLFW_MOUSE_BUTTON_MIDDLE},
434 {::vr::VRMouseButton_Right, GLFW_MOUSE_BUTTON_RIGHT},
439 ::vr::VREvent_t vrEvent;
441 while (_manager->PollNextOverlayEvent(_handle, &vrEvent,
sizeof(vrEvent)))
445 switch( vrEvent.eventType )
447 case ::vr::VREvent_MouseMove:
451 event_handler.
setCursorPos({window_dimensions.x*vrEvent.data.mouse.x, window_dimensions.y * (1.0f-vrEvent.data.mouse.y)});
455 case ::vr::VREvent_ScrollSmooth:
457 event_handler.setMouseScroll(vrEvent.data.scroll.viewportscale * glm::vec2(vrEvent.data.scroll.xdelta, vrEvent.data.scroll.ydelta));
461 case ::vr::VREvent_MouseButtonDown:
463 event_handler.
forceState(OPENVR_TO_GLFW_MOUSE_BUTTONS.at(vrEvent.data.mouse.button),
true,
true);
467 case ::vr::VREvent_MouseButtonUp:
469 event_handler.
forceState(OPENVR_TO_GLFW_MOUSE_BUTTONS.at(vrEvent.data.mouse.button),
false,
true);
478 ::vr::HmdMatrix34_t openvr_matrix = convertMat4ToHmd34(matrix);
480 _manager->SetOverlayTransformTrackedDeviceRelative(_handle, device->_handle, &openvr_matrix);
485 _manager->SetOverlayFlag(_handle, ::vr::VROverlayFlags_SideBySide_Parallel, enable);
492 _manager->GetOverlayFlag(_handle, ::vr::VROverlayFlags_SideBySide_Parallel, &result);
499 struct ::vr::Texture_t overlay_texture;
500 overlay_texture.eColorSpace = ::vr::ColorSpace_Auto;
501 overlay_texture.eType = ::vr::TextureType_OpenGL;
502 overlay_texture.handle =
reinterpret_cast<uintptr_t*
>(texture->getHandle());
504 _manager->SetOverlayTexture(_handle, &overlay_texture);
517oe::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:141
VR Overlay Application.
Definition vr.h:149
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:197
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.
VR Device that can track data (HMD / Controller / Tracker / etc...)
Definition vr.h:79
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.