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.