From 1ced3302371bf31d3db0ffa072241c6d7af94864 Mon Sep 17 00:00:00 2001 From: "Kevin M. Godby" Date: Mon, 4 Jul 2016 23:52:22 -0500 Subject: [PATCH 1/3] Refactored to pull common code into OSVRTrackedDevice base class. --- src/CMakeLists.txt | 5 +- src/OSVRTrackedDevice.cpp | 915 +----------------- src/OSVRTrackedDevice.h | 144 ++- src/OSVRTrackedHMD.cpp | 508 ++++++++++ src/OSVRTrackedHMD.h | 144 +++ src/OSVRTrackingReference.cpp | 526 +--------- src/OSVRTrackingReference.h | 85 +- src/PropertyMap.h | 47 + ...vice_properties.h => PropertyProperties.h} | 11 +- src/ServerDriver_OSVR.cpp | 4 +- 10 files changed, 858 insertions(+), 1531 deletions(-) create mode 100644 src/OSVRTrackedHMD.cpp create mode 100644 src/OSVRTrackedHMD.h create mode 100644 src/PropertyMap.h rename src/{osvr_device_properties.h => PropertyProperties.h} (98%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 10d7f2c..202174a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,8 @@ add_library(driver_osvr Logging.h OSVRTrackedDevice.cpp OSVRTrackedDevice.h + OSVRTrackedHMD.cpp + OSVRTrackedHMD.h OSVRTrackingReference.cpp OSVRTrackingReference.h ServerDriver_OSVR.cpp @@ -51,7 +53,8 @@ add_library(driver_osvr identity.h make_unique.h matrix_cast.h - osvr_device_properties.h + PropertyProperties.h + PropertyMap.h osvr_dll_export.h platform_fixes.h pretty_print.h diff --git a/src/OSVRTrackedDevice.cpp b/src/OSVRTrackedDevice.cpp index a2c4b82..d0e4190 100644 --- a/src/OSVRTrackedDevice.cpp +++ b/src/OSVRTrackedDevice.cpp @@ -29,7 +29,6 @@ #include "osvr_compiler_detection.h" #include "make_unique.h" #include "matrix_cast.h" -#include "osvr_device_properties.h" #include "ValveStrCpy.h" #include "platform_fixes.h" // strcasecmp #include "make_unique.h" @@ -55,17 +54,9 @@ #include #include // for std::find -OSVRTrackedDevice::OSVRTrackedDevice(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, vr::IDriverLog* driver_log) : context_(context), driverHost_(driver_host), pose_(), deviceClass_(vr::TrackedDeviceClass_HMD) +OSVRTrackedDevice::OSVRTrackedDevice(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, vr::ETrackedDeviceClass device_class) : context_(context), driverHost_(driver_host), pose_(), deviceClass_(device_class) { - OSVR_LOG(trace) << "OSVRTrackedDevice::OSVRTrackedDevice() called."; - - OSVR_LOG(debug) << "Client context: " << (&context_); - settings_ = std::make_unique(driver_host->GetSettings(vr::IVRSettings_Version)); - if (driver_log) { - Logging::instance().setDriverLog(driver_log); - } - - configure(); + settings_ = std::make_unique(driverHost_->GetSettings(vr::IVRSettings_Version)); } OSVRTrackedDevice::~OSVRTrackedDevice() @@ -75,114 +66,38 @@ OSVRTrackedDevice::~OSVRTrackedDevice() vr::EVRInitError OSVRTrackedDevice::Activate(uint32_t object_id) { - OSVR_LOG(trace) << "OSVRTrackedDevice::Activate() called."; - objectId_ = object_id; - - const std::time_t waitTime = 5; // wait up to 5 seconds for init - - // Register tracker callback - if (trackerInterface_.notEmpty()) { - trackerInterface_.free(); - } - - // Ensure context is fully started up - OSVR_LOG(trace) << "OSVRTrackedDevice::Activate(): Waiting for the context to fully start up...\n"; - std::time_t startTime = std::time(nullptr); - while (!context_.checkStatus()) { - context_.update(); - if (std::time(nullptr) > startTime + waitTime) { - OSVR_LOG(err) << "OSVRTrackedDevice::Activate(): Context startup timed out!\n"; - return vr::VRInitError_Driver_Failed; - } - } - - configureDistortionParameters(); - - displayConfig_ = osvr::clientkit::DisplayConfig(context_); - - // Ensure display is fully started up - OSVR_LOG(trace) << "OSVRTrackedDevice::Activate(): Waiting for the display to fully start up, including receiving initial pose update...\n"; - startTime = std::time(nullptr); - while (!displayConfig_.checkStartup()) { - context_.update(); - if (std::time(nullptr) > startTime + waitTime) { - OSVR_LOG(err) << "OSVRTrackedDevice::Activate(): Display startup timed out!\n"; - return vr::VRInitError_Driver_Failed; - } - } - - // Verify valid display config - if ((displayConfig_.getNumViewers() != 1) && (displayConfig_.getViewer(0).getNumEyes() != 2) && (displayConfig_.getViewer(0).getEye(0).getNumSurfaces() == 1) && (displayConfig_.getViewer(0).getEye(1).getNumSurfaces() != 1)) { - OSVR_LOG(err) << "OSVRTrackedDevice::Activate(): Unexpected display parameters!\n"; - - if (displayConfig_.getNumViewers() < 1) { - OSVR_LOG(err) << "OSVRTrackedDevice::Activate(): At least one viewer must exist.\n"; - return vr::VRInitError_Driver_HmdDisplayNotFound; - } else if (displayConfig_.getViewer(0).getNumEyes() < 2) { - OSVR_LOG(err) << "OSVRTrackedDevice::Activate(): At least two eyes must exist.\n"; - return vr::VRInitError_Driver_HmdDisplayNotFound; - } else if ((displayConfig_.getViewer(0).getEye(0).getNumSurfaces() < 1) || (displayConfig_.getViewer(0).getEye(1).getNumSurfaces() < 1)) { - OSVR_LOG(err) << "OSVRTrackedDevice::Activate(): At least one surface must exist for each eye.\n"; - return vr::VRInitError_Driver_HmdDisplayNotFound; - } - } - - // Register tracker callback - trackerInterface_ = context_.getInterface("/me/head"); - trackerInterface_.registerCallback(&OSVRTrackedDevice::HmdTrackerCallback, this); - - auto configString = context_.getStringParameter("/renderManagerConfig"); - - // If the /renderManagerConfig parameter is missing from the configuration - // file, use an empty dictionary instead. This allows the render manager - // config to zero out its values. - if (configString.empty()) { - OSVR_LOG(info) << "OSVRTrackedDevice::Activate(): Render Manager config is empty, using default values.\n"; - configString = "{}"; - } - - try { - renderManagerConfig_.parse(configString); - } catch(const std::exception& e) { - OSVR_LOG(err) << "OSVRTrackedDevice::Activate(): Exception parsing Render Manager config: " << e.what() << "\n"; - } - - driverHost_->ProximitySensorState(objectId_, true); - - OSVR_LOG(trace) << "OSVRTrackedDevice::Activate(): Activation complete.\n"; return vr::VRInitError_None; } void OSVRTrackedDevice::Deactivate() { - OSVR_LOG(trace) << "OSVRTrackedDevice::Deactivate() called."; - - /// Have to force freeing here - if (trackerInterface_.notEmpty()) { - trackerInterface_.free(); - } + // do nothing } void OSVRTrackedDevice::PowerOff() { - // FIXME Implement + // do nothing } void* OSVRTrackedDevice::GetComponent(const char* component_name_and_version) { if (!strcasecmp(component_name_and_version, vr::IVRDisplayComponent_Version)) { - return static_cast(this); + return dynamic_cast(this); + } else if (!strcasecmp(component_name_and_version, vr::IVRDriverDirectModeComponent_Version)) { + return dynamic_cast(this); + } else if (!strcasecmp(component_name_and_version, vr::IVRControllerComponent_Version)) { + return dynamic_cast(this); + } else if (!strcasecmp(component_name_and_version, vr::IVRCameraComponent_Version)) { + return dynamic_cast(this); + } else { + OSVR_LOG(warn) << "Unknown component [" << component_name_and_version << "] requested."; + return nullptr; } - - // Override this to add a component to a driver - return nullptr; } void OSVRTrackedDevice::DebugRequest(const char* request, char* response_buffer, uint32_t response_buffer_size) { - // TODO - // Log the requests just to see what info clients are looking for OSVR_LOG(debug) << "Received debug request [" << request << "] with response buffer size of " << response_buffer_size << "]."; @@ -193,119 +108,6 @@ void OSVRTrackedDevice::DebugRequest(const char* request, char* response_buffer, } } -void OSVRTrackedDevice::GetWindowBounds(int32_t* x, int32_t* y, uint32_t* width, uint32_t* height) -{ - int nDisplays = displayConfig_.getNumDisplayInputs(); - if (nDisplays != 1) { - OSVR_LOG(err) << "OSVRTrackedDevice::OSVRTrackedDevice(): Unexpected display number of displays!\n"; - } - osvr::clientkit::DisplayDimensions displayDims = displayConfig_.getDisplayDimensions(0); - *x = renderManagerConfig_.getWindowXPosition(); // todo: assumes desktop display of 1920. get this from display config when it's exposed. - *y = renderManagerConfig_.getWindowYPosition(); - *width = static_cast(displayDims.width); - *height = static_cast(displayDims.height); - -#if defined(OSVR_WINDOWS) || defined(OSVR_MACOSX) - // ... until we've added code for other platforms - *x = display_.position.x; - *y = display_.position.y; - *height = display_.size.height; - *width = display_.size.width; -#endif -} - -bool OSVRTrackedDevice::IsDisplayOnDesktop() -{ - // If the current display still appeara in the active displays list, - // then it's attached to the desktop. - const auto displays = osvr::display::getDisplays(); - const auto display_on_desktop = (end(displays) != std::find(begin(displays), end(displays), display_)); - OSVR_LOG(trace) << "OSVRTrackedDevice::IsDisplayOnDesktop(): " << (display_on_desktop ? "yes" : "no"); - return display_on_desktop; -} - -bool OSVRTrackedDevice::IsDisplayRealDisplay() -{ - // TODO get this info from display description? - return true; -} - -void OSVRTrackedDevice::GetRecommendedRenderTargetSize(uint32_t* width, uint32_t* height) -{ - /// @todo calculate overfill factor properly - double overfill_factor = 1.0; - int32_t x, y; - uint32_t w, h; - GetWindowBounds(&x, &y, &w, &h); - - *width = static_cast(w * overfill_factor); - *height = static_cast(h * overfill_factor); -} - -void OSVRTrackedDevice::GetEyeOutputViewport(vr::EVREye eye, uint32_t* x, uint32_t* y, uint32_t* width, uint32_t* height) -{ - osvr::clientkit::RelativeViewport viewPort = displayConfig_.getViewer(0).getEye(eye).getSurface(0).getRelativeViewport(); - *x = static_cast(viewPort.left); - *y = static_cast(viewPort.bottom); - *width = static_cast(viewPort.width); - *height = static_cast(viewPort.height); -} - -void OSVRTrackedDevice::GetProjectionRaw(vr::EVREye eye, float* left, float* right, float* top, float* bottom) -{ - // Reference: https://github.com/ValveSoftware/openvr/wiki/IVRSystem::GetProjectionRaw - // SteamVR expects top and bottom to be swapped! - osvr::clientkit::ProjectionClippingPlanes pl = displayConfig_.getViewer(0).getEye(eye).getSurface(0).getProjectionClippingPlanes(); - *left = static_cast(pl.left); - *right = static_cast(pl.right); - *bottom = static_cast(pl.top); // SWAPPED - *top = static_cast(pl.bottom); // SWAPPED -} - -vr::DistortionCoordinates_t OSVRTrackedDevice::ComputeDistortion(vr::EVREye eye, float u, float v) -{ - // Note that RenderManager expects the (0, 0) to be the lower-left corner and (1, 1) to be the upper-right corner while SteamVR assumes (0, 0) is upper-left and (1, 1) is lower-right. - // To accommodate this, we need to flip the y-coordinate before passing it to RenderManager and flip it again before returning the value to SteamVR. - OSVR_LOG(trace) << "OSVRTrackedDevice::ComputeDistortion(" << eye << ", " << u << ", " << v << ") called."; - - using osvr::renderkit::DistortionCorrectTextureCoordinate; - static const size_t COLOR_RED = 0; - static const size_t COLOR_GREEN = 1; - static const size_t COLOR_BLUE = 2; - - const auto osvr_eye = static_cast(eye); - const auto distortion_parameters = distortionParameters_[osvr_eye]; - const auto in_coords = osvr::renderkit::Float2 {{u, 1.0 - v}}; // flip v-coordinate - - auto interpolators = &leftEyeInterpolators_; - if (vr::Eye_Right == eye) { - interpolators = &rightEyeInterpolators_; - } - - auto coords_red = DistortionCorrectTextureCoordinate( - osvr_eye, in_coords, distortion_parameters, - COLOR_RED, overfillFactor_, *interpolators); - - auto coords_green = DistortionCorrectTextureCoordinate( - osvr_eye, in_coords, distortion_parameters, - COLOR_GREEN, overfillFactor_, *interpolators); - - auto coords_blue = DistortionCorrectTextureCoordinate( - osvr_eye, in_coords, distortion_parameters, - COLOR_BLUE, overfillFactor_, *interpolators); - - vr::DistortionCoordinates_t coords; - // flip v-coordinates again - coords.rfRed[0] = coords_red[0]; - coords.rfRed[1] = 1.0 - coords_red[1]; - coords.rfGreen[0] = coords_green[0]; - coords.rfGreen[1] = 1.0 - coords_green[1]; - coords.rfBlue[0] = coords_blue[0]; - coords.rfBlue[1] = 1.0 - coords_blue[1]; - - return coords; -} - vr::DriverPose_t OSVRTrackedDevice::GetPose() { return pose_; @@ -313,376 +115,22 @@ vr::DriverPose_t OSVRTrackedDevice::GetPose() bool OSVRTrackedDevice::GetBoolTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) { - const bool default_value = false; - - const auto result = checkProperty(prop, bool()); - if (vr::TrackedProp_Success != result) { - if (error) - *error = result; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - // Prop_ContainsProximitySensor_Bool spams our log files. Ignoring it here. - //OSVR_LOG(trace) << "OSVRTrackedDevice::GetBoolTrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // Properties that apply to all device classes - case vr::Prop_WillDriftInYaw_Bool: - if (error) - *error = vr::TrackedProp_Success; - return true; - break; - case vr::Prop_DeviceIsWireless_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_DeviceIsCharging_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_Firmware_UpdateAvailable_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_Firmware_ManualUpdate_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_BlockServerShutdown_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_CanUnifyCoordinateSystemWithHmd_Bool: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - break; - case vr::Prop_ContainsProximitySensor_Bool: - if (error) - *error = vr::TrackedProp_Success; - return true; - break; - case vr::Prop_DeviceProvidesBatteryStatus_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_DeviceCanPowerOff_Bool: - if (error) - *error = vr::TrackedProp_Success; - return true; - break; - case vr::Prop_HasCamera_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - // Properties that apply to HMDs - case vr::Prop_ReportsTimeSinceVSync_Bool: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - break; - case vr::Prop_IsOnDesktop_Bool: - if (error) - *error = vr::TrackedProp_Success; - return this->IsDisplayOnDesktop(); - break; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackedDevice::GetBoolTrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; + return GetTrackedDeviceProperty(prop, error, false); } float OSVRTrackedDevice::GetFloatTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) { - const float default_value = 0.0f; - - const auto result = checkProperty(prop, float()); - if (vr::TrackedProp_Success != result) { - if (error) - *error = result; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackedDevice::GetFloatTrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_DeviceBatteryPercentage_Float: - if (error) - *error = vr::TrackedProp_Success; - return 1.0f; // full battery - // Properties that are unique to TrackedDeviceClass_HMD - case vr::Prop_SecondsFromVsyncToPhotons_Float: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayFrequency_Float: - if (error) - *error = vr::TrackedProp_Success; - return static_cast(display_.verticalRefreshRate); - case vr::Prop_UserIpdMeters_Float: - if (error) - *error = vr::TrackedProp_Success; - return GetIPD(); - case vr::Prop_DisplayMCOffset_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayMCScale_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayGCBlackClamp_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayGCOffset_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayGCScale_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayGCPrescale_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_LensCenterLeftU_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_LensCenterLeftV_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_LensCenterRightU_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_LensCenterRightV_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_UserHeadToEyeDepthMeters_Float: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - // Properties that are unique to TrackedDeviceClass_TrackingReference - case vr::Prop_FieldOfViewLeftDegrees_Float: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_FieldOfViewRightDegrees_Float: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_FieldOfViewTopDegrees_Float: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_FieldOfViewBottomDegrees_Float: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_TrackingRangeMinimumMeters_Float: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_TrackingRangeMaximumMeters_Float: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackedDevice::GetFloatTrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; + return GetTrackedDeviceProperty(prop, error, 0.0f); } int32_t OSVRTrackedDevice::GetInt32TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) { - const int32_t default_value = 0; - - const auto result = checkProperty(prop, int32_t()); - if (vr::TrackedProp_Success != result) { - if (error) - *error = result; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackedDevice::GetInt32TrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_DeviceClass_Int32: - if (error) - *error = vr::TrackedProp_Success; - return deviceClass_; - // Properties that are unique to TrackedDeviceClass_HMD - case vr::Prop_DisplayMCType_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_EdidVendorID_Int32: - if (error) - *error = vr::TrackedProp_Success; - return static_cast(display_.edidVendorId); - case vr::Prop_EdidProductID_Int32: - if (error) - *error = vr::TrackedProp_Success; - return static_cast(display_.edidProductId); - case vr::Prop_DisplayGCType_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_CameraCompatibilityMode_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - // Properties that are unique to TrackedDeviceClass_Controller - case vr::Prop_Axis0Type_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Axis1Type_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Axis2Type_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Axis3Type_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Axis4Type_Int32: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackedDevice::GetInt32TrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; + return GetTrackedDeviceProperty(prop, error, static_cast(0)); } uint64_t OSVRTrackedDevice::GetUint64TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) { - const uint64_t default_value = 0; - - const auto result = checkProperty(prop, uint64_t()); - if (vr::TrackedProp_Success != result) { - if (error) - *error = result; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackedDevice::GetUint64TrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_HardwareRevision_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_FirmwareVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_FPGAVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_VRCVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_RadioVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DongleVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - // Properties that are unique to TrackedDeviceClass_HMD - case vr::Prop_CurrentUniverseId_Uint64: - if (error) - *error = vr::TrackedProp_Success; - return 1; - case vr::Prop_PreviousUniverseId_Uint64: - if (error) - *error = vr::TrackedProp_Success; - return 1; - case vr::Prop_DisplayFirmwareVersion_Uint64: - /// @todo This really should be read from the server - if (error) - *error = vr::TrackedProp_Success; - return 192; - case vr::Prop_CameraFirmwareVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayFPGAVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayBootloaderVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayHardwareVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_AudioFirmwareVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - // Properties that are unique to TrackedDeviceClass_Controller - case vr::Prop_SupportedButtons_Uint64: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackedDevice::GetUint64TrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; + return GetTrackedDeviceProperty(prop, error, static_cast(0)); } vr::HmdMatrix34_t OSVRTrackedDevice::GetMatrix34TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) @@ -690,38 +138,7 @@ vr::HmdMatrix34_t OSVRTrackedDevice::GetMatrix34TrackedDeviceProperty(vr::ETrack // Default value is identity matrix vr::HmdMatrix34_t default_value; map(default_value) = Matrix34f::Identity(); - - const auto result = checkProperty(prop, vr::HmdMatrix34_t()); - if (vr::TrackedProp_Success != result) { - if (error) - *error = result; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackedDevice::GetMatrix34TrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_StatusDisplayTransform_Matrix34: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - // Properties that are unique to TrackedDeviceClass_HMD - case vr::Prop_CameraToHeadTransform_Matrix34: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackedDevice::GetMatrix34TrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; + return GetTrackedDeviceProperty(prop, error, default_value); } uint32_t OSVRTrackedDevice::GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, char* value, uint32_t buffer_size, vr::ETrackedPropertyError *error) @@ -735,303 +152,25 @@ uint32_t OSVRTrackedDevice::GetStringTrackedDeviceProperty(vr::ETrackedDevicePro return default_value; } - OSVR_LOG(trace) << "OSVRTrackedDevice::GetStringTrackedDeviceProperty(): Requested property: " << prop << "\n"; - - std::string sValue = GetStringTrackedDeviceProperty(prop, error); + const auto str = GetStringTrackedDeviceProperty(prop, error); if (*error == vr::TrackedProp_Success) { - if (sValue.size() + 1 > buffer_size) { + if (str.size() + 1 > buffer_size) { *error = vr::TrackedProp_BufferTooSmall; } else { - valveStrCpy(sValue, value, buffer_size); + valveStrCpy(str, value, buffer_size); } - return static_cast(sValue.size()) + 1; + return static_cast(str.size()) + 1; } return 0; } - // ------------------------------------ - // Private Methods - // ------------------------------------ +// ------------------------------------ +// Protected Methods +// ------------------------------------ std::string OSVRTrackedDevice::GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *error) { - std::string default_value = ""; - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_TrackingSystemName_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_ModelNumber_String: - if (error) - *error = vr::TrackedProp_Success; - return "OSVR HMD"; - case vr::Prop_SerialNumber_String: - if (error) - *error = vr::TrackedProp_Success; - return this->GetId(); - case vr::Prop_RenderModelName_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_ManufacturerName_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_TrackingFirmwareVersion_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_HardwareRevision_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_AllWirelessDongleDescriptions_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_ConnectedWirelessDongle_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Firmware_ManualUpdateURL_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Firmware_ProgrammingTarget_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DriverVersion_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - - // Properties that are unique to TrackedDeviceClass_HMD - case vr::Prop_DisplayMCImageLeft_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayMCImageRight_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DisplayGCImage_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_CameraFirmwareDescription_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - - // Properties that are unique to TrackedDeviceClass_Controller - case vr::Prop_AttachedDeviceId_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - - // Properties that are unique to TrackedDeviceClass_TrackingReference - case vr::Prop_ModeLabel_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackedDevice::GetStringTrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; -} - -void OSVRTrackedDevice::HmdTrackerCallback(void* userdata, const OSVR_TimeValue*, const OSVR_PoseReport* report) -{ - if (!userdata) - return; - - auto* self = static_cast(userdata); - - vr::DriverPose_t pose; - pose.poseTimeOffset = 0; // close enough - - Eigen::Vector3d::Map(pose.vecWorldFromDriverTranslation) = Eigen::Vector3d::Zero(); - Eigen::Vector3d::Map(pose.vecDriverFromHeadTranslation) = Eigen::Vector3d::Zero(); - - map(pose.qWorldFromDriverRotation) = Eigen::Quaterniond::Identity(); - - map(pose.qDriverFromHeadRotation) = Eigen::Quaterniond::Identity(); - - // Position - Eigen::Vector3d::Map(pose.vecPosition) = osvr::util::vecMap(report->pose.translation); - - // Position velocity and acceleration are not currently consistently provided - Eigen::Vector3d::Map(pose.vecVelocity) = Eigen::Vector3d::Zero(); - Eigen::Vector3d::Map(pose.vecAcceleration) = Eigen::Vector3d::Zero(); - - // Orientation - map(pose.qRotation) = osvr::util::fromQuat(report->pose.rotation); - - // Angular velocity and acceleration are not currently consistently provided - Eigen::Vector3d::Map(pose.vecAngularVelocity) = Eigen::Vector3d::Zero(); - Eigen::Vector3d::Map(pose.vecAngularAcceleration) = Eigen::Vector3d::Zero(); - - pose.result = vr::TrackingResult_Running_OK; - pose.poseIsValid = true; - pose.willDriftInYaw = true; - pose.shouldApplyHeadModel = true; - - self->pose_ = pose; - self->driverHost_->TrackedDevicePoseUpdated(self->objectId_, self->pose_); -} - -float OSVRTrackedDevice::GetIPD() -{ - OSVR_Pose3 leftEye, rightEye; - - if (displayConfig_.getViewer(0).getEye(0).getPose(leftEye) != true) { - OSVR_LOG(err) << "OSVRTrackedDevice::GetHeadFromEyePose(): Unable to get left eye pose!\n"; - } - - if (displayConfig_.getViewer(0).getEye(1).getPose(rightEye) != true) { - OSVR_LOG(err) << "OSVRTrackedDevice::GetHeadFromEyePose(): Unable to get right eye pose!\n"; - } - - float ipd = static_cast((osvr::util::vecMap(leftEye.translation) - osvr::util::vecMap(rightEye.translation)).norm()); - return ipd; -} - -const char* OSVRTrackedDevice::GetId() -{ - return display_.name.c_str(); -} - -void OSVRTrackedDevice::configure() -{ - // Get settings from config file - const bool verbose_logging = settings_->getSetting("verbose", false); - if (verbose_logging) { - OSVR_LOG(info) << "Verbose logging enabled."; - Logging::instance().setLogLevel(trace); - } else { - OSVR_LOG(info) << "Verbose logging disabled."; - Logging::instance().setLogLevel(info); - } - - // The name of the display we want to use - const std::string display_name = settings_->getSetting("displayName", "OSVR"); - - // Detect displays and find the one we're using as an HMD - bool display_found = false; - auto displays = osvr::display::getDisplays(); - for (const auto& display : displays) { - if (std::string::npos == display.name.find(display_name)) - continue; - - display_ = display; - display_found = true; - break; - } - - if (!display_found) { - // Default to OSVR HDK display settings - display_.adapter.description = "Unknown"; - display_.name = "OSVR HDK"; - display_.size.width = 1920; - display_.size.height = 1080; - display_.position.x = 1920; - display_.position.y = 0; - display_.rotation = osvr::display::Rotation::Zero; - display_.verticalRefreshRate = 60.0; - display_.attachedToDesktop = true; - display_.edidVendorId = 0xd24e;// 53838 - display_.edidProductId = 0x1019; // 4121 - } - - if (display_found) { - OSVR_LOG(info) << "Detected display named [" << display_.name << "]:"; - } else { - OSVR_LOG(info) << "Default display:"; - } - OSVR_LOG(info) << " Adapter: " << display_.adapter.description; - OSVR_LOG(info) << " Monitor name: " << display_.name; - OSVR_LOG(info) << " Resolution: " << display_.size.width << "x" << display_.size.height; - OSVR_LOG(info) << " Position: (" << display_.position.x << ", " << display_.position.y << ")"; - switch (display_.rotation) { - case osvr::display::Rotation::Zero: - OSVR_LOG(info) << " Rotation: Landscape"; - break; - case osvr::display::Rotation::Ninety: - OSVR_LOG(info) << " Rotation: Portrait"; - break; - case osvr::display::Rotation::OneEighty: - OSVR_LOG(info) << " Rotation: Landscape (flipped)"; - break; - case osvr::display::Rotation::TwoSeventy: - OSVR_LOG(info) << " Rotation: Portrait (flipped)"; - break; - default: - OSVR_LOG(info) << " Rotation: Landscape"; - break; - } - OSVR_LOG(info) << " Refresh rate: " << display_.verticalRefreshRate; - OSVR_LOG(info) << " " << (display_.attachedToDesktop ? "Extended mode" : "Direct mode"); - OSVR_LOG(info) << " EDID vendor ID: " << display_.edidVendorId; - OSVR_LOG(info) << " EDID product ID: " << display_.edidProductId; -} - -void OSVRTrackedDevice::configureDistortionParameters() -{ - // Parse the display descriptor - displayDescription_ = context_.getStringParameter("/display"); - displayConfiguration_ = OSVRDisplayConfiguration(displayDescription_); - - // Initialize the distortion parameters - OSVR_LOG(debug) << "OSVRTrackedDevice::configureDistortionParameters(): Number of eyes: " << displayConfiguration_.getEyes().size() << "."; - for (size_t i = 0; i < displayConfiguration_.getEyes().size(); ++i) { - auto distortion = osvr::renderkit::DistortionParameters { displayConfiguration_, i }; - distortion.m_desiredTriangles = 200 * 64; - OSVR_LOG(debug) << "OSVRTrackedDevice::configureDistortionParameters(): Adding distortion for eye " << i << "."; - distortionParameters_.push_back(distortion); - } - OSVR_LOG(debug) << "OSVRTrackedDevice::configureDistortionParameters(): Number of distortion parameters: " << distortionParameters_.size() << "."; - - // Make the interpolators to be used by each eye. - OSVR_LOG(debug) << "OSVRTrackedDevice::configureDistortionParameters(): Creating mesh interpolators for the left eye."; - if (!makeUnstructuredMeshInterpolators(distortionParameters_[0], 0, leftEyeInterpolators_)) { - OSVR_LOG(err) << "OSVRTrackedDevice::configureDistortionParameters(): Could not create mesh interpolators for left eye."; - } - OSVR_LOG(debug) << "OSVRTrackedDevice::configureDistortionParameters(): Number of left eye interpolators: " << leftEyeInterpolators_.size() << "."; - - OSVR_LOG(debug) << "OSVRTrackedDevice::configureDistortionParameters(): Creating mesh interpolators for the right eye."; - if (!makeUnstructuredMeshInterpolators(distortionParameters_[1], 1, rightEyeInterpolators_)) { - OSVR_LOG(err) << "OSVRTrackedDevice::configureDistortionParameters(): Could not create mesh interpolators for right eye."; - } - OSVR_LOG(debug) << "OSVRTrackedDevice::configureDistortionParameters(): Number of right eye interpolators: " << leftEyeInterpolators_.size() << "."; -} - -template -vr::ETrackedPropertyError OSVRTrackedDevice::checkProperty(vr::ETrackedDeviceProperty prop, const T&) -{ - if (isWrongDataType(prop, T())) { - return vr::TrackedProp_WrongDataType; - } - - if (isWrongDeviceClass(prop, deviceClass_)) { - return vr::TrackedProp_WrongDeviceClass; - } - - if (vr::TrackedDeviceClass_Invalid == deviceClass_) { - return vr::TrackedProp_InvalidDevice; - } - - return vr::TrackedProp_Success; + return GetTrackedDeviceProperty(prop, error, std::string{""}); } diff --git a/src/OSVRTrackedDevice.h b/src/OSVRTrackedDevice.h index 4764f00..599c1e4 100644 --- a/src/OSVRTrackedDevice.h +++ b/src/OSVRTrackedDevice.h @@ -29,6 +29,8 @@ #include "osvr_compiler_detection.h" // for OSVR_OVERRIDE #include "Settings.h" #include "display/Display.h" +#include "PropertyMap.h" +#include "PropertyProperties.h" // OpenVR includes #include @@ -46,12 +48,13 @@ #include #include -class OSVRTrackedDevice : public vr::ITrackedDeviceServerDriver, public vr::IVRDisplayComponent { +class OSVRTrackedDevice : public vr::ITrackedDeviceServerDriver { friend class ServerDriver_OSVR; public: - OSVRTrackedDevice(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, vr::IDriverLog* driver_log = nullptr); + OSVRTrackedDevice(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, vr::ETrackedDeviceClass device_class); virtual ~OSVRTrackedDevice(); + // ------------------------------------ // Management Methods // ------------------------------------ @@ -92,53 +95,10 @@ friend class ServerDriver_OSVR; */ virtual void DebugRequest(const char* request, char* response_buffer, uint32_t response_buffer_size) OSVR_OVERRIDE; - // ------------------------------------ - // Display Methods - // ------------------------------------ - - /** - * Size and position that the window needs to be on the VR display. - */ - virtual void GetWindowBounds(int32_t* x, int32_t* y, uint32_t* width, uint32_t* height) OSVR_OVERRIDE; - - /** - * Returns true if the display is extending the desktop. - */ - virtual bool IsDisplayOnDesktop() OSVR_OVERRIDE; - - /** - * Returns true if the display is real and not a fictional display. - */ - virtual bool IsDisplayRealDisplay() OSVR_OVERRIDE; - - /** - * Suggested size for the intermediate render target that the distortion - * pulls from. - */ - virtual void GetRecommendedRenderTargetSize(uint32_t* width, uint32_t* height) OSVR_OVERRIDE; - - /** - * Gets the viewport in the frame buffer to draw the output of the distortion - * into - */ - virtual void GetEyeOutputViewport(vr::EVREye eye, uint32_t* x, uint32_t* y, uint32_t* width, uint32_t* height) OSVR_OVERRIDE; - - /** - * The components necessary to build your own projection matrix in case your - * application is doing something fancy like infinite Z - */ - virtual void GetProjectionRaw(vr::EVREye eye, float* left, float* right, float* top, float* bottom) OSVR_OVERRIDE; - - /** - * Returns the result of the distortion function for the specified eye and - * input UVs. UVs go from 0,0 in the upper left of that eye's viewport and - * 1,1 in the lower right of that eye's viewport. - */ - virtual vr::DistortionCoordinates_t ComputeDistortion(vr::EVREye eye, float u, float v) OSVR_OVERRIDE; - // ------------------------------------ // Tracking Methods // ------------------------------------ + virtual vr::DriverPose_t GetPose() OSVR_OVERRIDE; // ------------------------------------ @@ -187,29 +147,8 @@ friend class ServerDriver_OSVR; virtual uint32_t GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, char* value, uint32_t buffer_size, vr::ETrackedPropertyError* error) OSVR_OVERRIDE; protected: - const char* GetId(); - -private: std::string GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *error); - /** - * Callback function which is called whenever new data has been received - * from the tracker. - */ - static void HmdTrackerCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_PoseReport* report); - - float GetIPD(); - - /** - * Read configuration settings from configuration file. - */ - void configure(); - - /** - * Configure RenderManager and distortion parameters. - */ - void configureDistortionParameters(); - /** * Cecks to see if the requested property is valid for the device class and * type requested. @@ -223,30 +162,69 @@ friend class ServerDriver_OSVR; template vr::ETrackedPropertyError checkProperty(vr::ETrackedDeviceProperty prop, const T&); + template + T GetTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error, const T& default_value); + osvr::clientkit::ClientContext& context_; - std::string displayDescription_; - osvr::clientkit::DisplayConfig displayConfig_; - osvr::client::RenderManagerConfig renderManagerConfig_; vr::IServerDriverHost* driverHost_ = nullptr; - osvr::clientkit::Interface trackerInterface_; vr::DriverPose_t pose_; vr::ETrackedDeviceClass deviceClass_; std::unique_ptr settings_; uint32_t objectId_ = 0; - std::vector distortionParameters_; - OSVRDisplayConfiguration displayConfiguration_; - - // per-eye mesh interpolators - using MeshInterpolators = std::vector>; - MeshInterpolators leftEyeInterpolators_; - MeshInterpolators rightEyeInterpolators_; - float overfillFactor_ = 1.0; // TODO get from RenderManager - - // Settings - bool verboseLogging_ = false; - osvr::display::Display display_ = {}; + /** \name Collections of properties and their values. */ + //@{ + //std::map boolProperties_; + //std::map floatProperties_; + //std::map int32Properties_; + //std::map uint64Properties_; + //std::map matrix34Properties; + //std::map uint32Properties_; + //std::map stringProperties_; + PropertyMap properties_; + //@} }; +//template +//inline T OSVRTrackedDevice::GetTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error, const std::map& map, const T& default_value) +template +inline T OSVRTrackedDevice::GetTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error, const T& default_value) +{ + const auto result = checkProperty(prop, T()); + if (vr::TrackedProp_Success != result) { + if (error) + *error = result; + return default_value; + } + + if (properties_.find(prop) != end(properties_)) { + if (error) + *error = vr::TrackedProp_Success; + return boost::get(properties_[prop]); + } else { + if (error) + *error = vr::TrackedProp_ValueNotProvidedByDevice; + return default_value; + } +} + +template +inline vr::ETrackedPropertyError OSVRTrackedDevice::checkProperty(vr::ETrackedDeviceProperty prop, const T&) +{ + if (isWrongDataType(prop, T())) { + return vr::TrackedProp_WrongDataType; + } + + if (isWrongDeviceClass(prop, deviceClass_)) { + return vr::TrackedProp_WrongDeviceClass; + } + + if (vr::TrackedDeviceClass_Invalid == deviceClass_) { + return vr::TrackedProp_InvalidDevice; + } + + return vr::TrackedProp_Success; +} + #endif // INCLUDED_OSVRTrackedDevice_h_GUID_128E3B29_F5FC_4221_9B38_14E3F402E645 diff --git a/src/OSVRTrackedHMD.cpp b/src/OSVRTrackedHMD.cpp new file mode 100644 index 0000000..0394f4d --- /dev/null +++ b/src/OSVRTrackedHMD.cpp @@ -0,0 +1,508 @@ +/** @file + @brief OSVR tracked device + + @date 2015 + + @author + Sensics, Inc. + +*/ + +// Copyright 2015 Sensics, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Internal Includes +#include "OSVRTrackedHMD.h" +#include "Logging.h" + +#include "osvr_compiler_detection.h" +#include "make_unique.h" +#include "matrix_cast.h" +#include "ValveStrCpy.h" +#include "platform_fixes.h" // strcasecmp +#include "make_unique.h" +#include "osvr_platform.h" +#include "display/DisplayEnumerator.h" + +// OpenVR includes +#include + +// Library/third-party includes +#include +#include +#include +#include +#include + +// Standard includes +#include +#include +#include +#include +#include +#include // for std::find + +OSVRTrackedHMD::OSVRTrackedHMD(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host) : OSVRTrackedDevice(context, driver_host, vr::TrackedDeviceClass_HMD) +{ + OSVR_LOG(trace) << "OSVRTrackedHMD::OSVRTrackedHMD() called."; + + settings_ = std::make_unique(driver_host->GetSettings(vr::IVRSettings_Version)); + configure(); +} + +OSVRTrackedHMD::~OSVRTrackedHMD() +{ + // do nothing +} + +vr::EVRInitError OSVRTrackedHMD::Activate(uint32_t object_id) +{ + OSVR_LOG(trace) << "OSVRTrackedHMD::Activate() called."; + + objectId_ = object_id; + + const std::time_t waitTime = 5; // wait up to 5 seconds for init + + // Register tracker callback + if (trackerInterface_.notEmpty()) { + trackerInterface_.free(); + } + + // Ensure context is fully started up + OSVR_LOG(trace) << "OSVRTrackedHMD::Activate(): Waiting for the context to fully start up...\n"; + std::time_t startTime = std::time(nullptr); + while (!context_.checkStatus()) { + context_.update(); + if (std::time(nullptr) > startTime + waitTime) { + OSVR_LOG(err) << "OSVRTrackedHMD::Activate(): Context startup timed out!\n"; + return vr::VRInitError_Driver_Failed; + } + } + + configureDistortionParameters(); + + displayConfig_ = osvr::clientkit::DisplayConfig(context_); + + // Ensure display is fully started up + OSVR_LOG(trace) << "OSVRTrackedHMD::Activate(): Waiting for the display to fully start up, including receiving initial pose update...\n"; + startTime = std::time(nullptr); + while (!displayConfig_.checkStartup()) { + context_.update(); + if (std::time(nullptr) > startTime + waitTime) { + OSVR_LOG(err) << "OSVRTrackedHMD::Activate(): Display startup timed out!\n"; + return vr::VRInitError_Driver_Failed; + } + } + + // Verify valid display config + if ((displayConfig_.getNumViewers() != 1) && (displayConfig_.getViewer(0).getNumEyes() != 2) && (displayConfig_.getViewer(0).getEye(0).getNumSurfaces() == 1) && (displayConfig_.getViewer(0).getEye(1).getNumSurfaces() != 1)) { + OSVR_LOG(err) << "OSVRTrackedHMD::Activate(): Unexpected display parameters!\n"; + + if (displayConfig_.getNumViewers() < 1) { + OSVR_LOG(err) << "OSVRTrackedHMD::Activate(): At least one viewer must exist.\n"; + return vr::VRInitError_Driver_HmdDisplayNotFound; + } else if (displayConfig_.getViewer(0).getNumEyes() < 2) { + OSVR_LOG(err) << "OSVRTrackedHMD::Activate(): At least two eyes must exist.\n"; + return vr::VRInitError_Driver_HmdDisplayNotFound; + } else if ((displayConfig_.getViewer(0).getEye(0).getNumSurfaces() < 1) || (displayConfig_.getViewer(0).getEye(1).getNumSurfaces() < 1)) { + OSVR_LOG(err) << "OSVRTrackedHMD::Activate(): At least one surface must exist for each eye.\n"; + return vr::VRInitError_Driver_HmdDisplayNotFound; + } + } + + // Register tracker callback + trackerInterface_ = context_.getInterface("/me/head"); + trackerInterface_.registerCallback(&OSVRTrackedHMD::HmdTrackerCallback, this); + + auto configString = context_.getStringParameter("/renderManagerConfig"); + + // If the /renderManagerConfig parameter is missing from the configuration + // file, use an empty dictionary instead. This allows the render manager + // config to zero out its values. + if (configString.empty()) { + OSVR_LOG(info) << "OSVRTrackedHMD::Activate(): Render Manager config is empty, using default values.\n"; + configString = "{}"; + } + + try { + renderManagerConfig_.parse(configString); + } catch(const std::exception& e) { + OSVR_LOG(err) << "OSVRTrackedHMD::Activate(): Exception parsing Render Manager config: " << e.what() << "\n"; + } + + driverHost_->ProximitySensorState(objectId_, true); + + OSVR_LOG(trace) << "OSVRTrackedHMD::Activate(): Activation complete.\n"; + return vr::VRInitError_None; +} + +void OSVRTrackedHMD::Deactivate() +{ + OSVR_LOG(trace) << "OSVRTrackedHMD::Deactivate() called."; + + /// Have to force freeing here + if (trackerInterface_.notEmpty()) { + trackerInterface_.free(); + } +} + +void OSVRTrackedHMD::GetWindowBounds(int32_t* x, int32_t* y, uint32_t* width, uint32_t* height) +{ + int nDisplays = displayConfig_.getNumDisplayInputs(); + if (nDisplays != 1) { + OSVR_LOG(err) << "OSVRTrackedHMD::OSVRTrackedHMD(): Unexpected display number of displays!\n"; + } + osvr::clientkit::DisplayDimensions displayDims = displayConfig_.getDisplayDimensions(0); + *x = renderManagerConfig_.getWindowXPosition(); // todo: assumes desktop display of 1920. get this from display config when it's exposed. + *y = renderManagerConfig_.getWindowYPosition(); + *width = static_cast(displayDims.width); + *height = static_cast(displayDims.height); + +#if defined(OSVR_WINDOWS) || defined(OSVR_MACOSX) + // ... until we've added code for other platforms + *x = display_.position.x; + *y = display_.position.y; + *height = display_.size.height; + *width = display_.size.width; +#endif +} + +bool OSVRTrackedHMD::IsDisplayOnDesktop() +{ + // If the current display still appeara in the active displays list, + // then it's attached to the desktop. + const auto displays = osvr::display::getDisplays(); + const auto display_on_desktop = (end(displays) != std::find(begin(displays), end(displays), display_)); + OSVR_LOG(trace) << "OSVRTrackedHMD::IsDisplayOnDesktop(): " << (display_on_desktop ? "yes" : "no"); + return display_on_desktop; +} + +bool OSVRTrackedHMD::IsDisplayRealDisplay() +{ + // TODO get this info from display description? + return true; +} + +void OSVRTrackedHMD::GetRecommendedRenderTargetSize(uint32_t* width, uint32_t* height) +{ + /// @todo calculate overfill factor properly + double overfill_factor = 1.0; + int32_t x, y; + uint32_t w, h; + GetWindowBounds(&x, &y, &w, &h); + + *width = static_cast(w * overfill_factor); + *height = static_cast(h * overfill_factor); +} + +void OSVRTrackedHMD::GetEyeOutputViewport(vr::EVREye eye, uint32_t* x, uint32_t* y, uint32_t* width, uint32_t* height) +{ + osvr::clientkit::RelativeViewport viewPort = displayConfig_.getViewer(0).getEye(eye).getSurface(0).getRelativeViewport(); + *x = static_cast(viewPort.left); + *y = static_cast(viewPort.bottom); + *width = static_cast(viewPort.width); + *height = static_cast(viewPort.height); +} + +void OSVRTrackedHMD::GetProjectionRaw(vr::EVREye eye, float* left, float* right, float* top, float* bottom) +{ + // Reference: https://github.com/ValveSoftware/openvr/wiki/IVRSystem::GetProjectionRaw + // SteamVR expects top and bottom to be swapped! + osvr::clientkit::ProjectionClippingPlanes pl = displayConfig_.getViewer(0).getEye(eye).getSurface(0).getProjectionClippingPlanes(); + *left = static_cast(pl.left); + *right = static_cast(pl.right); + *bottom = static_cast(pl.top); // SWAPPED + *top = static_cast(pl.bottom); // SWAPPED +} + +vr::DistortionCoordinates_t OSVRTrackedHMD::ComputeDistortion(vr::EVREye eye, float u, float v) +{ + // Note that RenderManager expects the (0, 0) to be the lower-left corner and (1, 1) to be the upper-right corner while SteamVR assumes (0, 0) is upper-left and (1, 1) is lower-right. + // To accommodate this, we need to flip the y-coordinate before passing it to RenderManager and flip it again before returning the value to SteamVR. + OSVR_LOG(trace) << "OSVRTrackedHMD::ComputeDistortion(" << eye << ", " << u << ", " << v << ") called."; + + using osvr::renderkit::DistortionCorrectTextureCoordinate; + static const size_t COLOR_RED = 0; + static const size_t COLOR_GREEN = 1; + static const size_t COLOR_BLUE = 2; + + const auto osvr_eye = static_cast(eye); + const auto distortion_parameters = distortionParameters_[osvr_eye]; + const auto in_coords = osvr::renderkit::Float2 {{u, 1.0f - v}}; // flip v-coordinate + + auto interpolators = &leftEyeInterpolators_; + if (vr::Eye_Right == eye) { + interpolators = &rightEyeInterpolators_; + } + + auto coords_red = DistortionCorrectTextureCoordinate( + osvr_eye, in_coords, distortion_parameters, + COLOR_RED, overfillFactor_, *interpolators); + + auto coords_green = DistortionCorrectTextureCoordinate( + osvr_eye, in_coords, distortion_parameters, + COLOR_GREEN, overfillFactor_, *interpolators); + + auto coords_blue = DistortionCorrectTextureCoordinate( + osvr_eye, in_coords, distortion_parameters, + COLOR_BLUE, overfillFactor_, *interpolators); + + vr::DistortionCoordinates_t coords; + // flip v-coordinates again + coords.rfRed[0] = coords_red[0]; + coords.rfRed[1] = 1.0f - coords_red[1]; + coords.rfGreen[0] = coords_green[0]; + coords.rfGreen[1] = 1.0f - coords_green[1]; + coords.rfBlue[0] = coords_blue[0]; + coords.rfBlue[1] = 1.0f - coords_blue[1]; + + return coords; +} + +void OSVRTrackedHMD::HmdTrackerCallback(void* userdata, const OSVR_TimeValue*, const OSVR_PoseReport* report) +{ + if (!userdata) + return; + + auto* self = static_cast(userdata); + + vr::DriverPose_t pose; + pose.poseTimeOffset = 0; // close enough + + Eigen::Vector3d::Map(pose.vecWorldFromDriverTranslation) = Eigen::Vector3d::Zero(); + Eigen::Vector3d::Map(pose.vecDriverFromHeadTranslation) = Eigen::Vector3d::Zero(); + + map(pose.qWorldFromDriverRotation) = Eigen::Quaterniond::Identity(); + + map(pose.qDriverFromHeadRotation) = Eigen::Quaterniond::Identity(); + + // Position + Eigen::Vector3d::Map(pose.vecPosition) = osvr::util::vecMap(report->pose.translation); + + // Position velocity and acceleration are not currently consistently provided + Eigen::Vector3d::Map(pose.vecVelocity) = Eigen::Vector3d::Zero(); + Eigen::Vector3d::Map(pose.vecAcceleration) = Eigen::Vector3d::Zero(); + + // Orientation + map(pose.qRotation) = osvr::util::fromQuat(report->pose.rotation); + + // Angular velocity and acceleration are not currently consistently provided + Eigen::Vector3d::Map(pose.vecAngularVelocity) = Eigen::Vector3d::Zero(); + Eigen::Vector3d::Map(pose.vecAngularAcceleration) = Eigen::Vector3d::Zero(); + + pose.result = vr::TrackingResult_Running_OK; + pose.poseIsValid = true; + pose.willDriftInYaw = true; + pose.shouldApplyHeadModel = true; + + self->pose_ = pose; + self->driverHost_->TrackedDevicePoseUpdated(self->objectId_, self->pose_); +} + +float OSVRTrackedHMD::GetIPD() +{ + OSVR_Pose3 leftEye, rightEye; + + if (displayConfig_.getViewer(0).getEye(0).getPose(leftEye) != true) { + OSVR_LOG(err) << "OSVRTrackedHMD::GetHeadFromEyePose(): Unable to get left eye pose!\n"; + } + + if (displayConfig_.getViewer(0).getEye(1).getPose(rightEye) != true) { + OSVR_LOG(err) << "OSVRTrackedHMD::GetHeadFromEyePose(): Unable to get right eye pose!\n"; + } + + float ipd = static_cast((osvr::util::vecMap(leftEye.translation) - osvr::util::vecMap(rightEye.translation)).norm()); + return ipd; +} + +void OSVRTrackedHMD::configure() +{ + // The name of the display we want to use + const std::string display_name = settings_->getSetting("displayName", "OSVR"); + + // Detect displays and find the one we're using as an HMD + bool display_found = false; + auto displays = osvr::display::getDisplays(); + for (const auto& display : displays) { + if (std::string::npos == display.name.find(display_name)) + continue; + + display_ = display; + display_found = true; + break; + } + + if (!display_found) { + // Default to OSVR HDK display settings + display_.adapter.description = "Unknown"; + display_.name = "OSVR HDK"; + display_.size.width = 1920; + display_.size.height = 1080; + display_.position.x = 1920; + display_.position.y = 0; + display_.rotation = osvr::display::Rotation::Zero; + display_.verticalRefreshRate = 60.0; + display_.attachedToDesktop = true; + display_.edidVendorId = 0xd24e;// 53838 + display_.edidProductId = 0x1019; // 4121 + } + + if (display_found) { + OSVR_LOG(info) << "Detected display named [" << display_.name << "]:"; + } else { + OSVR_LOG(info) << "Default display:"; + } + OSVR_LOG(info) << " Adapter: " << display_.adapter.description; + OSVR_LOG(info) << " Monitor name: " << display_.name; + OSVR_LOG(info) << " Resolution: " << display_.size.width << "x" << display_.size.height; + OSVR_LOG(info) << " Position: (" << display_.position.x << ", " << display_.position.y << ")"; + switch (display_.rotation) { + case osvr::display::Rotation::Zero: + OSVR_LOG(info) << " Rotation: Landscape"; + break; + case osvr::display::Rotation::Ninety: + OSVR_LOG(info) << " Rotation: Portrait"; + break; + case osvr::display::Rotation::OneEighty: + OSVR_LOG(info) << " Rotation: Landscape (flipped)"; + break; + case osvr::display::Rotation::TwoSeventy: + OSVR_LOG(info) << " Rotation: Portrait (flipped)"; + break; + default: + OSVR_LOG(info) << " Rotation: Landscape"; + break; + } + OSVR_LOG(info) << " Refresh rate: " << display_.verticalRefreshRate; + OSVR_LOG(info) << " " << (display_.attachedToDesktop ? "Extended mode" : "Direct mode"); + OSVR_LOG(info) << " EDID vendor ID: " << display_.edidVendorId; + OSVR_LOG(info) << " EDID product ID: " << display_.edidProductId; +} + +void OSVRTrackedHMD::configureDistortionParameters() +{ + // Parse the display descriptor + displayDescription_ = context_.getStringParameter("/display"); + displayConfiguration_ = OSVRDisplayConfiguration(displayDescription_); + + // Initialize the distortion parameters + OSVR_LOG(debug) << "OSVRTrackedHMD::configureDistortionParameters(): Number of eyes: " << displayConfiguration_.getEyes().size() << "."; + for (size_t i = 0; i < displayConfiguration_.getEyes().size(); ++i) { + auto distortion = osvr::renderkit::DistortionParameters { displayConfiguration_, i }; + distortion.m_desiredTriangles = 200 * 64; + OSVR_LOG(debug) << "OSVRTrackedHMD::configureDistortionParameters(): Adding distortion for eye " << i << "."; + distortionParameters_.push_back(distortion); + } + OSVR_LOG(debug) << "OSVRTrackedHMD::configureDistortionParameters(): Number of distortion parameters: " << distortionParameters_.size() << "."; + + // Make the interpolators to be used by each eye. + OSVR_LOG(debug) << "OSVRTrackedHMD::configureDistortionParameters(): Creating mesh interpolators for the left eye."; + if (!makeUnstructuredMeshInterpolators(distortionParameters_[0], 0, leftEyeInterpolators_)) { + OSVR_LOG(err) << "OSVRTrackedHMD::configureDistortionParameters(): Could not create mesh interpolators for left eye."; + } + OSVR_LOG(debug) << "OSVRTrackedHMD::configureDistortionParameters(): Number of left eye interpolators: " << leftEyeInterpolators_.size() << "."; + + OSVR_LOG(debug) << "OSVRTrackedHMD::configureDistortionParameters(): Creating mesh interpolators for the right eye."; + if (!makeUnstructuredMeshInterpolators(distortionParameters_[1], 1, rightEyeInterpolators_)) { + OSVR_LOG(err) << "OSVRTrackedHMD::configureDistortionParameters(): Could not create mesh interpolators for right eye."; + } + OSVR_LOG(debug) << "OSVRTrackedHMD::configureDistortionParameters(): Number of right eye interpolators: " << leftEyeInterpolators_.size() << "."; +} + +void OSVRTrackedHMD::configureProperties() +{ + // General properties that apply to all device classes + + properties_[vr::Prop_WillDriftInYaw_Bool] = true; + properties_[vr::Prop_DeviceIsWireless_Bool] = false; + properties_[vr::Prop_DeviceIsCharging_Bool] = false; + properties_[vr::Prop_Firmware_UpdateAvailable_Bool] = false; + properties_[vr::Prop_Firmware_ManualUpdate_Bool] = false; + properties_[vr::Prop_BlockServerShutdown_Bool] = false; + //properties_[vr::Prop_CanUnifyCoordinateSystemWithHmd_Bool] = true; + properties_[vr::Prop_ContainsProximitySensor_Bool] = false; + properties_[vr::Prop_DeviceProvidesBatteryStatus_Bool] = false; + properties_[vr::Prop_DeviceCanPowerOff_Bool] = true; + properties_[vr::Prop_HasCamera_Bool] = false; + + properties_[vr::Prop_DeviceBatteryPercentage_Float] = 1.0f; // full battery + + properties_[vr::Prop_DeviceClass_Int32] = deviceClass_; + + //properties_[vr::Prop_HardwareRevision_Uint64] = 0ul; + //properties_[vr::Prop_FirmwareVersion_Uint64] = 0ul; + //properties_[vr::Prop_FPGAVersion_Uint64] = 0ul; + //properties_[vr::Prop_VRCVersion_Uint64] = 0ul; + //properties_[vr::Prop_RadioVersion_Uint64] = 0ul; + //properties_[vr::Prop_DongleVersion_Uint64] = 0ul; + + //properties_[vr::Prop_StatusDisplayTransform_Matrix34] = /* TODO */ + + //properties_[vr::Prop_TrackingSystemName_String] = ""; + properties_[vr::Prop_ModelNumber_String] = "OSVR HMD"; + properties_[vr::Prop_SerialNumber_String] = display_.name; + //properties_[vr::Prop_RenderModelName_String] = ""; + //properties_[vr::Prop_ManufacturerName_String] = ""; + //properties_[vr::Prop_TrackingFirmwareVersion_String] = ""; + //properties_[vr::Prop_HardwareRevision_String] = ""; + //properties_[vr::Prop_AllWirelessDongleDescriptions_String] = ""; + //properties_[vr::Prop_ConnectedWirelessDongle_String] = ""; + //properties_[vr::Prop_Firmware_ManualUpdateURL_String] = ""; + //properties_[vr::Prop_Firmware_ProgrammingTarget_String] = ""; + //properties_[vr::Prop_DriverVersion_String] = ""; + + + // Properties that apply to HMDs + + //properties_[vr::Prop_ReportsTimeSinceVSync_Bool] = false; + properties_[vr::Prop_IsOnDesktop_Bool] = IsDisplayOnDesktop(); + + //properties_[vr::Prop_SecondsFromVsyncToPhotons_Float] = 0.0; + properties_[vr::Prop_DisplayFrequency_Float] = static_cast(display_.verticalRefreshRate); + properties_[vr::Prop_UserIpdMeters_Float] = GetIPD(); + //properties_[vr::Prop_DisplayMCOffset_Float] = 0.0; + //properties_[vr::Prop_DisplayMCScale_Float] = 0.0; + //properties_[vr::Prop_DisplayGCBlackClamp_Float] = 0.0; + //properties_[vr::Prop_DisplayGCOffset_Float] = 0.0; + //properties_[vr::Prop_DisplayGCScale_Float] = 0.0; + //properties_[vr::Prop_DisplayGCPrescale_Float] = 0.0; + //properties_[vr::Prop_LensCenterLeftU_Float] = 0.0; + //properties_[vr::Prop_LensCenterLeftV_Float] = 0.0; + //properties_[vr::Prop_LensCenterRightU_Float] = 0.0; + //properties_[vr::Prop_LensCenterRightV_Float] = 0.0; + //properties_[vr::Prop_UserHeadToEyeDepthMeters_Float] = 0.0; + + //properties_[vr::Prop_DisplayMCType_Int32] = 0; + properties_[vr::Prop_EdidVendorID_Int32] = static_cast(display_.edidVendorId); + properties_[vr::Prop_EdidProductID_Int32] = static_cast(display_.edidProductId); + //properties_[vr::Prop_DisplayGCType_Int32] = 0; + //properties_[vr::Prop_CameraCompatibilityMode_Int32] = 0; + + properties_[vr::Prop_CurrentUniverseId_Uint64] = 1; + properties_[vr::Prop_PreviousUniverseId_Uint64] = 1; + properties_[vr::Prop_DisplayFirmwareVersion_Uint64] = 192; // FIXME read from OSVR server + //properties_[vr::Prop_CameraFirmwareVersion_Uint64] = 0ul; + //properties_[vr::Prop_DisplayFPGAVersion_Uint64] = 0ul; + //properties_[vr::Prop_DisplayBootloaderVersion_Uint64] = 0ul; + //properties_[vr::Prop_DisplayHardwareVersion_Uint64] = 0ul; + //properties_[vr::Prop_AudioFirmwareVersion_Uint64] = 0ul; + + //properties_[vr::Prop_CameraToHeadTransform_Matrix34] = /* TODO */ + + //properties_[vr::Prop_DisplayMCImageLeft_String] = ""; + //properties_[vr::Prop_DisplayMCImageRight_String] = ""; + //properties_[vr::Prop_DisplayGCImage_String] = ""; + //properties_[vr::Prop_CameraFirmwareDescription_String] = ""; +} + diff --git a/src/OSVRTrackedHMD.h b/src/OSVRTrackedHMD.h new file mode 100644 index 0000000..96125bb --- /dev/null +++ b/src/OSVRTrackedHMD.h @@ -0,0 +1,144 @@ +/** @file + @brief OSVR tracked device + + @date 2015 + + @author + Sensics, Inc. + +*/ + +// Copyright 2015 Sensics, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef INCLUDED_OSVRTrackedHMD_h_GUID_233AC6EA_4833_4EE2_B4ED_1F60A2208C9D +#define INCLUDED_OSVRTrackedHMD_h_GUID_233AC6EA_4833_4EE2_B4ED_1F60A2208C9D + +// Internal Includes +#include "OSVRTrackedDevice.h" +#include "display/Display.h" + +// Library/third-party includes +#include + +#include +#include +#include +#include +#include + +// Standard includes +#include +#include +#include + +class OSVRTrackedHMD : public OSVRTrackedDevice, public vr::IVRDisplayComponent { +friend class ServerDriver_OSVR; +public: + OSVRTrackedHMD(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host); + + virtual ~OSVRTrackedHMD(); + + // ------------------------------------ + // Management Methods + // ------------------------------------ + + virtual vr::EVRInitError Activate(uint32_t object_id) OSVR_OVERRIDE; + virtual void Deactivate() OSVR_OVERRIDE; + + // ------------------------------------ + // Display Methods + // ------------------------------------ + + /** + * Size and position that the window needs to be on the VR display. + */ + virtual void GetWindowBounds(int32_t* x, int32_t* y, uint32_t* width, uint32_t* height) OSVR_OVERRIDE; + + /** + * Returns true if the display is extending the desktop. + */ + virtual bool IsDisplayOnDesktop() OSVR_OVERRIDE; + + /** + * Returns true if the display is real and not a fictional display. + */ + virtual bool IsDisplayRealDisplay() OSVR_OVERRIDE; + + /** + * Suggested size for the intermediate render target that the distortion + * pulls from. + */ + virtual void GetRecommendedRenderTargetSize(uint32_t* width, uint32_t* height) OSVR_OVERRIDE; + + /** + * Gets the viewport in the frame buffer to draw the output of the distortion + * into + */ + virtual void GetEyeOutputViewport(vr::EVREye eye, uint32_t* x, uint32_t* y, uint32_t* width, uint32_t* height) OSVR_OVERRIDE; + + /** + * The components necessary to build your own projection matrix in case your + * application is doing something fancy like infinite Z + */ + virtual void GetProjectionRaw(vr::EVREye eye, float* left, float* right, float* top, float* bottom) OSVR_OVERRIDE; + + /** + * Returns the result of the distortion function for the specified eye and + * input UVs. UVs go from 0,0 in the upper left of that eye's viewport and + * 1,1 in the lower right of that eye's viewport. + */ + virtual vr::DistortionCoordinates_t ComputeDistortion(vr::EVREye eye, float u, float v) OSVR_OVERRIDE; + +private: + /** + * Callback function which is called whenever new data has been received + * from the tracker. + */ + static void HmdTrackerCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_PoseReport* report); + + float GetIPD(); + + /** + * Read configuration settings from configuration file. + */ + void configure(); + + /** + * Configure RenderManager and distortion parameters. + */ + void configureDistortionParameters(); + + void configureProperties(); + + std::string displayDescription_; + osvr::clientkit::DisplayConfig displayConfig_; + osvr::client::RenderManagerConfig renderManagerConfig_; + osvr::clientkit::Interface trackerInterface_; + std::vector distortionParameters_; + OSVRDisplayConfiguration displayConfiguration_; + + // per-eye mesh interpolators + using MeshInterpolators = std::vector>; + MeshInterpolators leftEyeInterpolators_; + MeshInterpolators rightEyeInterpolators_; + + float overfillFactor_ = 1.0; // TODO get from RenderManager + + // Settings + osvr::display::Display display_ = {}; +}; + +#endif // INCLUDED_OSVRTrackedHMD_h_GUID_233AC6EA_4833_4EE2_B4ED_1F60A2208C9D + diff --git a/src/OSVRTrackingReference.cpp b/src/OSVRTrackingReference.cpp index 4d43e11..51995f8 100644 --- a/src/OSVRTrackingReference.cpp +++ b/src/OSVRTrackingReference.cpp @@ -29,7 +29,6 @@ #include "osvr_compiler_detection.h" #include "make_unique.h" #include "matrix_cast.h" -#include "osvr_device_properties.h" #include "ValveStrCpy.h" #include "platform_fixes.h" // strcasecmp #include "make_unique.h" @@ -49,19 +48,15 @@ #include #include -OSVRTrackingReference::OSVRTrackingReference(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, vr::IDriverLog* driver_log) : m_Context(context), driver_host_(driver_host), pose_(), deviceClass_(vr::TrackedDeviceClass_TrackingReference) +OSVRTrackingReference::OSVRTrackingReference(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host) : OSVRTrackedDevice(context, driver_host, vr::TrackedDeviceClass_TrackingReference) { OSVR_LOG(trace) << "OSVRTrackingReference::OSVRTrackingReference() called."; - settings_ = std::make_unique(driver_host->GetSettings(vr::IVRSettings_Version)); - if (driver_log) { - Logging::instance().setDriverLog(driver_log); - } configure(); } OSVRTrackingReference::~OSVRTrackingReference() { - driver_host_ = nullptr; + // do nothing } vr::EVRInitError OSVRTrackingReference::Activate(uint32_t object_id) @@ -75,7 +70,7 @@ vr::EVRInitError OSVRTrackingReference::Activate(uint32_t object_id) } // Register tracker callback - m_TrackerInterface = m_Context.getInterface(trackerPath_); + m_TrackerInterface = context_.getInterface(trackerPath_); m_TrackerInterface.registerCallback(&OSVRTrackingReference::TrackerCallback, this); return vr::VRInitError_None; @@ -91,460 +86,6 @@ void OSVRTrackingReference::Deactivate() } } -void OSVRTrackingReference::PowerOff() -{ - // do nothing -} - -void* OSVRTrackingReference::GetComponent(const char* component_name_and_version) -{ - if (!strcasecmp(component_name_and_version, vr::ITrackedDeviceServerDriver_Version)) { - return static_cast(this); - } - - return nullptr; -} - -void OSVRTrackingReference::DebugRequest(const char* request, char* response_buffer, uint32_t response_buffer_size) -{ - // TODO - // make use of (from vrtypes.h) static const uint32_t k_unMaxDriverDebugResponseSize = 32768; - // return empty string for now - if (response_buffer_size > 0) { - response_buffer[0] = '\0'; - } -} - -vr::DriverPose_t OSVRTrackingReference::GetPose() -{ - return pose_; -} - -bool OSVRTrackingReference::GetBoolTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) -{ - const bool default_value = false; - - if (isWrongDataType(prop, bool())) { - if (error) - *error = vr::TrackedProp_WrongDataType; - return default_value; - } - - if (isWrongDeviceClass(prop, deviceClass_)) { - if (error) - *error = vr::TrackedProp_WrongDeviceClass; - return default_value; - } - - if (vr::TrackedDeviceClass_Invalid == deviceClass_) { - if (error) - *error = vr::TrackedProp_InvalidDevice; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - //OSVR_LOG(trace) << "OSVRTrackingReference::GetBoolTrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // Properties that apply to all device classes - case vr::Prop_WillDriftInYaw_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_DeviceIsWireless_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_DeviceIsCharging_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_Firmware_UpdateAvailable_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_Firmware_ManualUpdate_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_BlockServerShutdown_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_CanUnifyCoordinateSystemWithHmd_Bool: // TODO - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - break; - case vr::Prop_ContainsProximitySensor_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_DeviceProvidesBatteryStatus_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_DeviceCanPowerOff_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - case vr::Prop_HasCamera_Bool: - if (error) - *error = vr::TrackedProp_Success; - return false; - break; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackingReference::GetBoolTrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; -} - -float OSVRTrackingReference::GetFloatTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) -{ - const float default_value = 0.0f; - - if (isWrongDataType(prop, float())) { - if (error) - *error = vr::TrackedProp_WrongDataType; - return default_value; - } - - if (isWrongDeviceClass(prop, deviceClass_)) { - if (error) - *error = vr::TrackedProp_WrongDeviceClass; - return default_value; - } - - if (vr::TrackedDeviceClass_Invalid == deviceClass_) { - if (error) - *error = vr::TrackedProp_InvalidDevice; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackingReference::GetFloatTrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_DeviceBatteryPercentage_Float: - if (error) - *error = vr::TrackedProp_Success; - return 1.0f; // full battery - // Properties that are unique to TrackedDeviceClass_TrackingReference - case vr::Prop_FieldOfViewLeftDegrees_Float: - if (error) - *error = vr::TrackedProp_Success; - return fovLeft_; - case vr::Prop_FieldOfViewRightDegrees_Float: - if (error) - *error = vr::TrackedProp_Success; - return fovRight_; - case vr::Prop_FieldOfViewTopDegrees_Float: - if (error) - *error = vr::TrackedProp_Success; - return fovTop_; - case vr::Prop_FieldOfViewBottomDegrees_Float: - if (error) - *error = vr::TrackedProp_Success; - return fovBottom_; - case vr::Prop_TrackingRangeMinimumMeters_Float: - if (error) - *error = vr::TrackedProp_Success; - return minTrackingRange_; - case vr::Prop_TrackingRangeMaximumMeters_Float: - if (error) - *error = vr::TrackedProp_Success; - return maxTrackingRange_; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackingReference::GetFloatTrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; -} - -int32_t OSVRTrackingReference::GetInt32TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) -{ - const int32_t default_value = 0; - - if (isWrongDataType(prop, int32_t())) { - if (error) - *error = vr::TrackedProp_WrongDataType; - return default_value; - } - - if (isWrongDeviceClass(prop, deviceClass_)) { - if (error) - *error = vr::TrackedProp_WrongDeviceClass; - return default_value; - } - - if (vr::TrackedDeviceClass_Invalid == deviceClass_) { - if (error) - *error = vr::TrackedProp_InvalidDevice; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackingReference::GetInt32TrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_DeviceClass_Int32: - if (error) - *error = vr::TrackedProp_Success; - return deviceClass_; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackingReference::GetInt32TrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; -} - -uint64_t OSVRTrackingReference::GetUint64TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) -{ - const uint64_t default_value = 0; - - if (isWrongDataType(prop, uint64_t())) { - if (error) - *error = vr::TrackedProp_WrongDataType; - return default_value; - } - - if (isWrongDeviceClass(prop, deviceClass_)) { - if (error) - *error = vr::TrackedProp_WrongDeviceClass; - return default_value; - } - - if (vr::TrackedDeviceClass_Invalid == deviceClass_) { - if (error) - *error = vr::TrackedProp_InvalidDevice; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackingReference::GetUint64TrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_HardwareRevision_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_FirmwareVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_FPGAVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_VRCVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_RadioVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DongleVersion_Uint64: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackingReference::GetUint64TrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; -} - -vr::HmdMatrix34_t OSVRTrackingReference::GetMatrix34TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) -{ - // Default value is identity matrix - vr::HmdMatrix34_t default_value; - map(default_value) = Matrix34f::Identity(); - - if (isWrongDataType(prop, vr::HmdMatrix34_t())) { - if (error) - *error = vr::TrackedProp_WrongDataType; - return default_value; - } - - if (isWrongDeviceClass(prop, deviceClass_)) { - if (error) - *error = vr::TrackedProp_WrongDeviceClass; - return default_value; - } - - if (vr::TrackedDeviceClass_Invalid == deviceClass_) { - if (error) - *error = vr::TrackedProp_InvalidDevice; - return default_value; - } - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - OSVR_LOG(trace) << "OSVRTrackingReference::GetMatrix34TrackedDeviceProperty(): Requested property: " << prop << "\n"; - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_StatusDisplayTransform_Matrix34: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackingReference::GetMatrix34TrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; -} - -uint32_t OSVRTrackingReference::GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, char *pchValue, uint32_t unBufferSize, vr::ETrackedPropertyError *pError) -{ - uint32_t default_value = 0; - if (isWrongDataType(prop, pchValue)) { - if (pError) - *pError = vr::TrackedProp_WrongDataType; - return default_value; - } - - if (isWrongDeviceClass(prop, deviceClass_)) { - if (pError) - *pError = vr::TrackedProp_WrongDeviceClass; - return default_value; - } - - if (vr::TrackedDeviceClass_Invalid == deviceClass_) { - if (pError) - *pError = vr::TrackedProp_InvalidDevice; - return default_value; - } - - OSVR_LOG(trace) << "OSVRTrackingReference::GetStringTrackedDeviceProperty(): Requested property: " << prop << "\n"; - - std::string sValue = GetStringTrackedDeviceProperty(prop, pError); - if (*pError == vr::TrackedProp_Success) { - if (sValue.size() + 1 > unBufferSize) { - *pError = vr::TrackedProp_BufferTooSmall; - } else { - valveStrCpy(sValue, pchValue, unBufferSize); - } - return static_cast(sValue.size()) + 1; - } - - return 0; -} - - // ------------------------------------ - // Private Methods - // ------------------------------------ - -std::string OSVRTrackingReference::GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *error) -{ - std::string default_value = ""; - -#include "ignore-warning/push" -#include "ignore-warning/switch-enum" - - switch (prop) { - // General properties that apply to all device classes - case vr::Prop_TrackingSystemName_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_ModelNumber_String: - if (error) - *error = vr::TrackedProp_Success; - return "OSVR HMD"; - case vr::Prop_SerialNumber_String: - if (error) - *error = vr::TrackedProp_Success; - return this->GetId(); - case vr::Prop_RenderModelName_String: - if (error) - *error = vr::TrackedProp_Success; - return "dk2_camera"; // FIXME replace with HDK IR camera model - case vr::Prop_ManufacturerName_String: - if (error) - *error = vr::TrackedProp_Success; - return "OSVR"; // FIXME read value from server - case vr::Prop_TrackingFirmwareVersion_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_HardwareRevision_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_AllWirelessDongleDescriptions_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_ConnectedWirelessDongle_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Firmware_ManualUpdateURL_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_Firmware_ProgrammingTarget_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - case vr::Prop_DriverVersion_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - // Properties that are unique to TrackedDeviceClass_TrackingReference - case vr::Prop_ModeLabel_String: - if (error) - *error = vr::TrackedProp_ValueNotProvidedByDevice; - return default_value; - } - -#include "ignore-warning/pop" - - OSVR_LOG(warn) << "OSVRTrackingReference::GetStringTrackedDeviceProperty(): Unknown property " << prop << " requested.\n"; - if (error) - *error = vr::TrackedProp_UnknownProperty; - return default_value; -} - const char* OSVRTrackingReference::GetId() { return "OSVR IR camera"; @@ -583,21 +124,11 @@ void OSVRTrackingReference::TrackerCallback(void* userdata, const OSVR_TimeValue pose.willDriftInYaw = false; pose.shouldApplyHeadModel = false; self->pose_ = pose; - self->driver_host_->TrackedDevicePoseUpdated(self->objectId_, self->pose_); + self->driverHost_->TrackedDevicePoseUpdated(self->objectId_, self->pose_); } void OSVRTrackingReference::configure() { - // Get settings from config file - const bool verbose_logging = settings_->getSetting("verbose", verboseLogging_); - if (verbose_logging) { - OSVR_LOG(info) << "Verbose logging enabled."; - Logging::instance().setLogLevel(trace); - } else { - OSVR_LOG(info) << "Verbose logging disabled."; - Logging::instance().setLogLevel(info); - } - // Read tracking reference values from config file trackerPath_ = settings_->getSetting("cameraPath", trackerPath_); fovLeft_ = settings_->getSetting("cameraFOVLeftDegrees", fovLeft_); @@ -606,5 +137,54 @@ void OSVRTrackingReference::configure() fovBottom_ = settings_->getSetting("cameraFOVBottomDegrees", fovBottom_); minTrackingRange_ = settings_->getSetting("minTrackingRangeMeters", minTrackingRange_); maxTrackingRange_ = settings_->getSetting("maxTrackingRangeMeters", maxTrackingRange_); + + configureProperties(); } +void OSVRTrackingReference::configureProperties() +{ + // Properties that apply to all device classes + properties_[vr::Prop_WillDriftInYaw_Bool] = false; + properties_[vr::Prop_DeviceIsWireless_Bool] = false; + properties_[vr::Prop_DeviceIsCharging_Bool] = false; + properties_[vr::Prop_Firmware_UpdateAvailable_Bool] = false; + properties_[vr::Prop_Firmware_ManualUpdate_Bool] = false; + properties_[vr::Prop_BlockServerShutdown_Bool] = false; + //properties_[vr::Prop_CanUnifyCoordinateSystemWithHmd_Bool] = true; + properties_[vr::Prop_ContainsProximitySensor_Bool] = false; + properties_[vr::Prop_DeviceProvidesBatteryStatus_Bool] = false; + properties_[vr::Prop_DeviceCanPowerOff_Bool] = false; + properties_[vr::Prop_HasCamera_Bool] = false; + properties_[vr::Prop_DeviceBatteryPercentage_Float] = 1.0f; + properties_[vr::Prop_DeviceClass_Int32] = deviceClass_; + //properties_[vr::Prop_HardwareRevision_Uint64] = 0ul; + //properties_[vr::Prop_FirmwareVersion_Uint64] = 0ul; + //properties_[vr::Prop_FPGAVersion_Uint64] = 0ul; + //properties_[vr::Prop_VRCVersion_Uint64] = 0ul; + //properties_[vr::Prop_RadioVersion_Uint64] = 0ul; + //properties_[vr::Prop_DongleVersion_Uint64] = 0ul; + //properties_[vr::Prop_StatusDisplayTransform_Matrix34] = /* ... */; + //properties_[vr::Prop_TrackingSystemName_String] = ""; + properties_[vr::Prop_ModelNumber_String] = "OSVR Tracking Reference"; + properties_[vr::Prop_SerialNumber_String] = GetId(); + properties_[vr::Prop_RenderModelName_String] = "dk2_camera"; // FIXME replace with HDK IR camera model + properties_[vr::Prop_ManufacturerName_String] = "OSVR"; // FIXME read value from server + //properties_[vr::Prop_TrackingFirmwareVersion_String] = ""; + //properties_[vr::Prop_HardwareRevision_String] = ""; + //properties_[vr::Prop_AllWirelessDongleDescriptions_String] = ""; + //properties_[vr::Prop_ConnectedWirelessDongle_String] = ""; + //properties_[vr::Prop_Firmware_ManualUpdateURL_String] = ""; + //properties_[vr::Prop_Firmware_ProgrammingTarget_String] = ""; + //properties_[vr::Prop_DriverVersion_String] = ""; + + // Properties that are unique to TrackedDeviceClass_TrackingReference + properties_[vr::Prop_FieldOfViewLeftDegrees_Float] = fovLeft_; + properties_[vr::Prop_FieldOfViewRightDegrees_Float] = fovRight_; + properties_[vr::Prop_FieldOfViewTopDegrees_Float] = fovTop_; + properties_[vr::Prop_FieldOfViewBottomDegrees_Float] = fovBottom_; + properties_[vr::Prop_TrackingRangeMinimumMeters_Float] = minTrackingRange_; + properties_[vr::Prop_TrackingRangeMaximumMeters_Float] = maxTrackingRange_; + //properties_[vr::Prop_ModeLabel_String] = ""; +} + + diff --git a/src/OSVRTrackingReference.h b/src/OSVRTrackingReference.h index 308e3c3..a1ed1d8 100644 --- a/src/OSVRTrackingReference.h +++ b/src/OSVRTrackingReference.h @@ -26,7 +26,7 @@ #define INCLUDED_OSVRTrackingReference_h_GUID_250D4551_4054_9D37_A8F6_F2FCFDB1C188 // Internal Includes -#include "osvr_compiler_detection.h" // for OSVR_OVERRIDE +#include "OSVRTrackedDevice.h" #include "Settings.h" // OpenVR includes @@ -39,10 +39,10 @@ #include #include -class OSVRTrackingReference : public vr::ITrackedDeviceServerDriver { +class OSVRTrackingReference : public OSVRTrackedDevice { friend class ServerDriver_OSVR; public: - OSVRTrackingReference(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, vr::IDriverLog* driver_log = nullptr); + OSVRTrackingReference(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host); virtual ~OSVRTrackingReference(); @@ -66,98 +66,21 @@ friend class ServerDriver_OSVR; */ virtual void Deactivate() OSVR_OVERRIDE; - /** - * Handles a request from the system to power off this device. - */ - virtual void PowerOff() OSVR_OVERRIDE; - - /** - * Requests a component interface of the driver for device-specific - * functionality. The driver should return NULL if the requested interface - * or version is not supported. - */ - virtual void* GetComponent(const char* component_name_and_version) OSVR_OVERRIDE; - - /** - * A VR Client has made this debug request of the driver. The set of valid - * requests is entirely up to the driver and the client to figure out, as is - * the format of the response. Responses that exceed the length of the - * supplied buffer should be truncated and null terminated. - */ - virtual void DebugRequest(const char* request, char* response_buffer, uint32_t response_buffer_size) OSVR_OVERRIDE; - - // ------------------------------------ - // Tracking Methods - // ------------------------------------ - virtual vr::DriverPose_t GetPose() OSVR_OVERRIDE; - - // ------------------------------------ - // Property Methods - // ------------------------------------ - - /** - * Returns a bool property. If the property is not available this function - * will return false. - */ - virtual bool GetBoolTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) OSVR_OVERRIDE; - - /** - * Returns a float property. If the property is not available this function - * will return 0. - */ - virtual float GetFloatTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) OSVR_OVERRIDE; - - /** - * Returns an int property. If the property is not available this function - * will return 0. - */ - virtual int32_t GetInt32TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) OSVR_OVERRIDE; - - /** - * Returns a uint64 property. If the property is not available this function - * will return 0. - */ - virtual uint64_t GetUint64TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) OSVR_OVERRIDE; - - /** - * Returns a matrix property. If the device index is not valid or the - * property is not a matrix type, this function will return identity. - */ - virtual vr::HmdMatrix34_t GetMatrix34TrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error) OSVR_OVERRIDE; - - /** - * Returns a string property. If the property is not available this function - * will return 0 and @p error will be set to an error. Otherwise it returns - * the length of the number of bytes necessary to hold this string including - * the trailing null. If the buffer is too small the error will be - * @c TrackedProp_BufferTooSmall. Strings will generally fit in buffers of - * @c k_unTrackingStringSize characters. Drivers may not return strings longer - * than @c k_unMaxPropertyStringSize. - */ - virtual uint32_t GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, char* value, uint32_t buffer_size, vr::ETrackedPropertyError* error) OSVR_OVERRIDE; - protected: const char* GetId(); private: - std::string GetStringTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *error); static void TrackerCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_PoseReport* report); /** * Read configuration settings from configuration file. */ void configure(); + void configureProperties(); - osvr::clientkit::ClientContext& m_Context; - vr::IServerDriverHost* driver_host_ = nullptr; osvr::clientkit::Interface m_TrackerInterface; - vr::DriverPose_t pose_; - vr::ETrackedDeviceClass deviceClass_; - std::unique_ptr settings_; - uint32_t objectId_ = 0; // Settings - bool verboseLogging_ = false; std::string trackerPath_ = "/org_osvr_filter_videoimufusion/HeadFusion/semantic/camera"; // Default values are those for the OSVR HDK IR camera diff --git a/src/PropertyMap.h b/src/PropertyMap.h new file mode 100644 index 0000000..4e642cd --- /dev/null +++ b/src/PropertyMap.h @@ -0,0 +1,47 @@ +/** @file + @brief Header + + @date 2016 + + @author + Sensics, Inc. + + +*/ + +// Copyright 2016 Sensics, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef INCLUDED_PropertyMap_h_GUID_D9C1D812_9B04_485C_BD5D_4316974D0043 +#define INCLUDED_PropertyMap_h_GUID_D9C1D812_9B04_485C_BD5D_4316974D0043 + +// Internal Includes +// - none + +// Library/third-party includes +#include + +#include + +// Standard includes +#include +#include +#include + +using Property = boost::variant; + +using PropertyMap = std::map; + +#endif // INCLUDED_PropertyMap_h_GUID_D9C1D812_9B04_485C_BD5D_4316974D0043 + diff --git a/src/osvr_device_properties.h b/src/PropertyProperties.h similarity index 98% rename from src/osvr_device_properties.h rename to src/PropertyProperties.h index 9865ec6..4fcad36 100644 --- a/src/osvr_device_properties.h +++ b/src/PropertyProperties.h @@ -22,8 +22,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef INCLUDED_osvr_device_properties_h_GUID_5212DE9D_B211_4139_A140_45A578EFA47E -#define INCLUDED_osvr_device_properties_h_GUID_5212DE9D_B211_4139_A140_45A578EFA47E +#ifndef INCLUDED_PropertyProperties_h_GUID_5212DE9D_B211_4139_A140_45A578EFA47E +#define INCLUDED_PropertyProperties_h_GUID_5212DE9D_B211_4139_A140_45A578EFA47E // Internal Includes // - none @@ -546,6 +546,11 @@ inline bool isWrongDataType(vr::ETrackedDeviceProperty prop, const char*) return true; } +inline bool isWrongDataType(vr::ETrackedDeviceProperty prop, std::string) +{ + return isWrongDataType(prop, ""); +} + inline bool isWrongDataType(vr::ETrackedDeviceProperty prop, vr::HmdMatrix34_t) { switch (prop) { @@ -756,5 +761,5 @@ inline bool isWrongDeviceClass(vr::ETrackedDeviceProperty prop, vr::ETrackedDevi return true; } -#endif // INCLUDED_osvr_device_properties_h_GUID_5212DE9D_B211_4139_A140_45A578EFA47E +#endif // INCLUDED_PropertyProperties_h_GUID_5212DE9D_B211_4139_A140_45A578EFA47E diff --git a/src/ServerDriver_OSVR.cpp b/src/ServerDriver_OSVR.cpp index d46ec24..05c3e42 100644 --- a/src/ServerDriver_OSVR.cpp +++ b/src/ServerDriver_OSVR.cpp @@ -25,7 +25,7 @@ // Internal Includes #include "ServerDriver_OSVR.h" -#include "OSVRTrackedDevice.h" // for OSVRTrackedDevice +#include "OSVRTrackedHMD.h" // for OSVRTrackedHMD #include "OSVRTrackingReference.h" // for OSVRTrackingReference #include "platform_fixes.h" // strcasecmp #include "make_unique.h" // for std::make_unique @@ -49,7 +49,7 @@ vr::EVRInitError ServerDriver_OSVR::Init(vr::IDriverLog* driver_log, vr::IServer context_ = std::make_unique("org.osvr.SteamVR"); - trackedDevices_.emplace_back(std::make_unique(*(context_.get()), driver_host)); + trackedDevices_.emplace_back(std::make_unique(*(context_.get()), driver_host)); trackedDevices_.emplace_back(std::make_unique(*(context_.get()), driver_host)); return vr::VRInitError_None; From a4fc526f17a4aeb71df5f6cd24bad3ff305f89a6 Mon Sep 17 00:00:00 2001 From: "Kevin M. Godby" Date: Tue, 5 Jul 2016 18:00:15 -0500 Subject: [PATCH 2/3] Removed obsolete code. --- src/OSVRTrackedDevice.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/OSVRTrackedDevice.h b/src/OSVRTrackedDevice.h index 599c1e4..19f50c2 100644 --- a/src/OSVRTrackedDevice.h +++ b/src/OSVRTrackedDevice.h @@ -174,19 +174,10 @@ friend class ServerDriver_OSVR; /** \name Collections of properties and their values. */ //@{ - //std::map boolProperties_; - //std::map floatProperties_; - //std::map int32Properties_; - //std::map uint64Properties_; - //std::map matrix34Properties; - //std::map uint32Properties_; - //std::map stringProperties_; PropertyMap properties_; //@} }; -//template -//inline T OSVRTrackedDevice::GetTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error, const std::map& map, const T& default_value) template inline T OSVRTrackedDevice::GetTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError* error, const T& default_value) { From 5a4a62f8eb945e048da7d9dc134976f3df00c399 Mon Sep 17 00:00:00 2001 From: "Kevin M. Godby" Date: Tue, 5 Jul 2016 20:59:45 -0500 Subject: [PATCH 3/3] Initial import of controller support. --- src/CMakeLists.txt | 2 + src/OSVRTrackedController.cpp | 392 ++++++++++++++++++++++++++++++++++ src/OSVRTrackedController.h | 135 ++++++++++++ src/OSVRTrackedHMD.cpp | 2 +- src/OSVRTrackingReference.cpp | 2 +- 5 files changed, 531 insertions(+), 2 deletions(-) create mode 100644 src/OSVRTrackedController.cpp create mode 100644 src/OSVRTrackedController.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 202174a..8feb5f1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,8 @@ add_library(driver_osvr Logging.h OSVRTrackedDevice.cpp OSVRTrackedDevice.h + OSVRTrackedController.cpp + OSVRTrackedController.h OSVRTrackedHMD.cpp OSVRTrackedHMD.h OSVRTrackingReference.cpp diff --git a/src/OSVRTrackedController.cpp b/src/OSVRTrackedController.cpp new file mode 100644 index 0000000..288b237 --- /dev/null +++ b/src/OSVRTrackedController.cpp @@ -0,0 +1,392 @@ +/** @file + @brief OSVR tracked controller + + @date 2015 + + @author + Sensics, Inc. + +*/ + +// Copyright 2015 Sensics, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Internal Includes +#include "OSVRTrackedController.h" + +#include "osvr_compiler_detection.h" +#include "make_unique.h" +#include "matrix_cast.h" +#include "ValveStrCpy.h" +#include "platform_fixes.h" // strcasecmp +#include "Logging.h" + +// OpenVR includes +#include + +// Library/third-party includes +#include +#include +#include +#include + +// Standard includes +#include +#include +#include +#include +#include + +// TODO: +// Trackpad +// OSVRButton(OSVR_BUTTON_TYPE_DIGITAL, FGamepadKeyNames::MotionController_Left_Thumbstick, "/controller/left/joystick/button"), +// OSVRButton(OSVR_BUTTON_TYPE_DIGITAL, FGamepadKeyNames::MotionController_Left_Shoulder, "/controller/left/bumper"), +// OSVRButton(OSVR_BUTTON_TYPE_DIGITAL, FGamepadKeyNames::SpecialLeft, "/controller/left/middle"), + +OSVRTrackedController::OSVRTrackedController(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, int controller_index) : OSVRTrackedDevice(context, driver_host, vr::TrackedDeviceClass_Controller), controllerIndex_(controller_index) +{ + controllerName_ = "OSVRController" + std::to_string(controller_index); + + numAxis_ = 0; + for (int iter_axis = 0; iter_axis < NUM_AXIS; iter_axis++) { + analogInterface_[iter_axis].parentController = this; + analogInterface_[iter_axis].axisType = vr::EVRControllerAxisType::k_eControllerAxis_None; + } +} + +OSVRTrackedController::~OSVRTrackedController() +{ + // do nothing +} + +vr::EVRInitError OSVRTrackedController::Activate(uint32_t object_id) +{ + OSVRTrackedDevice::Activate(object_id); + + const std::time_t wait_time = 5; // wait up to 5 seconds for init + + freeInterfaces(); + numAxis_ = 0; + + // Ensure context is fully started up + OSVR_LOG(info) << "Waiting for the context to fully start up..."; + const auto start_time = std::time(nullptr); + while (!context_.checkStatus()) { + context_.update(); + if (std::time(nullptr) > start_time + wait_time) { + OSVR_LOG(warn) << "Context startup timed out!"; + return vr::VRInitError_Driver_Failed; + } + } + + // Register callbacks + std::string trackerPath; + std::string buttonPath; + std::string triggerPath; + std::string joystickPath; + if (controllerIndex_ == 0) { + trackerPath = "/me/hands/left"; + buttonPath = "/controller/left/"; + triggerPath = "/controller/left/trigger"; + joystickPath = "/controller/left/joystick"; + } else if (controllerIndex_ == 1) { + trackerPath = "/me/hands/right"; + buttonPath = "/controller/right/"; + triggerPath = "/controller/right/trigger"; + joystickPath = "/controller/right/joystick"; + } else { + buttonPath = "/controller" + std::to_string(controllerIndex_) + "/"; + triggerPath = "/controller" + std::to_string(controllerIndex_) + "/trigger"; + joystickPath = "/controller" + std::to_string(controllerIndex_) + "/joystick"; + } + + if (!trackerPath.empty()) { + trackerInterface_ = context_.getInterface(trackerPath); + trackerInterface_.registerCallback(&OSVRTrackedController::controllerTrackerCallback, this); + } + + for (int iter_button = 0; iter_button < NUM_BUTTONS; iter_button++) { + buttonInterface_[iter_button] = context_.getInterface(buttonPath + std::to_string(iter_button)); + if (buttonInterface_[iter_button].notEmpty()) { + buttonInterface_[iter_button].registerCallback(&OSVRTrackedController::controllerButtonCallback, this); + } else { + buttonInterface_[iter_button].free(); + } + } + + // TODO: ADD TOUCHPAD PART HERE + numAxis_ = 0; + + numAxis_ = 1; + for (int iter_trigger = 0; iter_trigger < NUM_TRIGGER; iter_trigger++) { + if (numAxis_ >= NUM_AXIS) + break; + + if (iter_trigger == 0) { + analogInterface_[numAxis_].analogInterfaceX = context_.getInterface(triggerPath); + } else { + analogInterface_[numAxis_].analogInterfaceX = context_.getInterface(triggerPath + std::to_string(iter_trigger)); + } + + if (analogInterface_[numAxis_].analogInterfaceX.notEmpty()) { + analogInterface_[numAxis_].axisIndex = numAxis_; + analogInterface_[numAxis_].axisType = vr::EVRControllerAxisType::k_eControllerAxis_Trigger; + analogInterface_[numAxis_].analogInterfaceX.registerCallback(&OSVRTrackedController::controllerTriggerCallback, &analogInterface_[numAxis_]); + numAxis_++; + } else { + analogInterface_[numAxis_].analogInterfaceX.free(); + } + } + + numAxis_ = 2; + for (int iter_joystick = 0; iter_joystick < NUM_JOYSTICKS; iter_joystick++) { + if (numAxis_ >= NUM_AXIS) + break; + + if (iter_joystick == 0) { + analogInterface_[numAxis_].analogInterfaceX = context_.getInterface(joystickPath + "/x"); + analogInterface_[numAxis_].analogInterfaceY = context_.getInterface(joystickPath + "/y"); + } else { + analogInterface_[numAxis_].analogInterfaceX = context_.getInterface(joystickPath + std::to_string(iter_joystick) + "/x"); + analogInterface_[numAxis_].analogInterfaceY = context_.getInterface(joystickPath + std::to_string(iter_joystick) + "/y"); + } + + bool somethingFound = false; + + if (analogInterface_[numAxis_].analogInterfaceX.notEmpty()) { + analogInterface_[numAxis_].axisIndex = numAxis_; + analogInterface_[numAxis_].axisType = vr::EVRControllerAxisType::k_eControllerAxis_Joystick; + analogInterface_[numAxis_].analogInterfaceX.registerCallback(&OSVRTrackedController::controllerJoystickXCallback, &analogInterface_[numAxis_]); + somethingFound = true; + } else { + analogInterface_[numAxis_].analogInterfaceX.free(); + } + + if (analogInterface_[numAxis_].analogInterfaceY.notEmpty()) { + analogInterface_[numAxis_].axisIndex = numAxis_; + analogInterface_[numAxis_].axisType = vr::EVRControllerAxisType::k_eControllerAxis_Joystick; + analogInterface_[numAxis_].analogInterfaceY.registerCallback(&OSVRTrackedController::controllerJoystickYCallback, &analogInterface_[numAxis_]); + somethingFound = true; + } else { + analogInterface_[numAxis_].analogInterfaceY.free(); + } + + if (somethingFound) + numAxis_++; + } + + return vr::VRInitError_None; +} + +void OSVRTrackedController::Deactivate() +{ + /// Have to force freeing here + freeInterfaces(); +} + +vr::VRControllerState_t OSVRTrackedController::GetControllerState() +{ + // TODO + vr::VRControllerState_t state; + state.unPacketNum = 0; + return state; +} + +bool OSVRTrackedController::TriggerHapticPulse(uint32_t axis_id, uint16_t pulse_duration_microseconds) +{ + return false; +} + +void OSVRTrackedController::freeInterfaces() +{ + if (trackerInterface_.notEmpty()) { + trackerInterface_.free(); + } + + for (int iter_axis = 0; iter_axis < NUM_AXIS; iter_axis++) { + if (analogInterface_[iter_axis].analogInterfaceX.notEmpty()) + analogInterface_[iter_axis].analogInterfaceX.free(); + if (analogInterface_[iter_axis].analogInterfaceY.notEmpty()) + analogInterface_[iter_axis].analogInterfaceY.free(); + } + + for (int iter_button = 0; iter_button < NUM_BUTTONS; iter_button++) { + if (buttonInterface_[iter_button].notEmpty()) + buttonInterface_[iter_button].free(); + } +} + +inline vr::HmdQuaternion_t HmdQuaternion_Init(double w, double x, double y, double z) +{ + vr::HmdQuaternion_t quat; + quat.w = w; + quat.x = x; + quat.y = y; + quat.z = z; + return quat; +} + +void OSVRTrackedController::controllerTrackerCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_PoseReport* report) +{ + if (!userdata) + return; + + auto* self = static_cast(userdata); + + vr::DriverPose_t pose = { 0 }; + pose.poseTimeOffset = 0; // close enough + + Eigen::Vector3d::Map(pose.vecWorldFromDriverTranslation) = Eigen::Vector3d::Zero(); + Eigen::Vector3d::Map(pose.vecDriverFromHeadTranslation) = Eigen::Vector3d::Zero(); + + map(pose.qWorldFromDriverRotation) = Eigen::Quaterniond::Identity(); + map(pose.qDriverFromHeadRotation) = Eigen::Quaterniond::Identity(); + //pose.qWorldFromDriverRotation = HmdQuaternion_Init(1, 0, 0, 0); + //pose.qDriverFromHeadRotation = HmdQuaternion_Init(1, 0, 0, 0); + + // Position + Eigen::Vector3d::Map(pose.vecPosition) = osvr::util::vecMap(report->pose.translation); + + // Position velocity and acceleration are not currently consistently provided + Eigen::Vector3d::Map(pose.vecVelocity) = Eigen::Vector3d::Zero(); + Eigen::Vector3d::Map(pose.vecAcceleration) = Eigen::Vector3d::Zero(); + + // Orientation + map(pose.qRotation) = osvr::util::fromQuat(report->pose.rotation); + + // Angular velocity and acceleration are not currently consistently provided + Eigen::Vector3d::Map(pose.vecAngularVelocity) = Eigen::Vector3d::Zero(); + Eigen::Vector3d::Map(pose.vecAngularAcceleration) = Eigen::Vector3d::Zero(); + + pose.result = vr::TrackingResult_Running_OK; + pose.poseIsValid = true; + //pose.willDriftInYaw = true; + //pose.shouldApplyHeadModel = true; + pose.deviceIsConnected = true; + + self->pose_ = pose; + + self->driverHost_->TrackedDevicePoseUpdated(self->objectId_, self->pose_); +} + +void OSVRTrackedController::controllerButtonCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_ButtonReport* report) +{ + if (!userdata) + return; + + auto* self = static_cast(userdata); + + vr::EVRButtonId button_id; + if ((report->sensor >= 0 && report->sensor <= 7) || (report->sensor >= 32 && report->sensor <= 36)) { + button_id = static_cast(report->sensor); + } else if (report->sensor >= 8 && report->sensor <= 12) { + button_id = static_cast(report->sensor + 24); + } else { + return; + } + + if (OSVR_BUTTON_PRESSED == report->state) { + self->driverHost_->TrackedDeviceButtonPressed(self->objectId_, button_id, 0); + } else { + self->driverHost_->TrackedDeviceButtonUnpressed(self->objectId_, button_id, 0); + } +} + +void OSVRTrackedController::controllerTriggerCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_AnalogReport* report) +{ + if (!userdata) + return; + + auto* analog_interface = static_cast(userdata); + OSVRTrackedController* self = analog_interface->parentController; + + analog_interface->x = report->state; + + vr::VRControllerAxis_t axis_state; + axis_state.x = static_cast(analog_interface->x); + + self->driverHost_->TrackedDeviceAxisUpdated(self->objectId_, analog_interface->axisIndex, axis_state); +} + +void OSVRTrackedController::controllerJoystickXCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_AnalogReport* report) +{ + if (!userdata) + return; + + auto* analog_interface = static_cast(userdata); + OSVRTrackedController* self = analog_interface->parentController; + + analog_interface->x = report->state; + + vr::VRControllerAxis_t axis_state; + axis_state.x = static_cast(analog_interface->x); + axis_state.y = static_cast(analog_interface->y); + + self->driverHost_->TrackedDeviceAxisUpdated(self->objectId_, analog_interface->axisIndex, axis_state); +} + +void OSVRTrackedController::controllerJoystickYCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_AnalogReport* report) +{ + if (!userdata) + return; + + auto* analog_interface = static_cast(userdata); + OSVRTrackedController* self = analog_interface->parentController; + + analog_interface->y = report->state; + + vr::VRControllerAxis_t axis_state; + axis_state.x = static_cast(analog_interface->x); + axis_state.y = static_cast(analog_interface->y); + + self->driverHost_->TrackedDeviceAxisUpdated(self->objectId_, analog_interface->axisIndex, axis_state); +} + +const char* OSVRTrackedController::GetId() +{ + /// @todo When available, return the actual unique ID of the HMD + return controllerName_.c_str(); +} + +void OSVRTrackedController::configure() +{ + configureProperties(); +} + +void OSVRTrackedController::configureProperties() +{ + properties_[vr::Prop_DeviceClass_Int32] = static_cast(deviceClass_); + properties_[vr::Prop_Axis0Type_Int32] = static_cast(analogInterface_[0].axisType); + properties_[vr::Prop_Axis1Type_Int32] = static_cast(analogInterface_[1].axisType); + properties_[vr::Prop_Axis2Type_Int32] = static_cast(analogInterface_[2].axisType); + properties_[vr::Prop_Axis3Type_Int32] = static_cast(analogInterface_[3].axisType); + properties_[vr::Prop_Axis4Type_Int32] = static_cast(analogInterface_[4].axisType); + + properties_[vr::Prop_SupportedButtons_Uint64] = static_cast(NUM_BUTTONS); + + properties_[vr::Prop_ModelNumber_String] = "OSVR Controller"; + properties_[vr::Prop_SerialNumber_String] = controllerName_.c_str(); + properties_[vr::Prop_RenderModelName_String] = ""; + + // Properties that are unique to TrackedDeviceClass_Controller + //Prop_AttachedDeviceId_String = 3000, + //Prop_SupportedButtons_Uint64 = 3001, + //Prop_Axis0Type_Int32 = 3002, // Return value is of type EVRControllerAxisType + //Prop_Axis1Type_Int32 = 3003, // Return value is of type EVRControllerAxisType + //Prop_Axis2Type_Int32 = 3004, // Return value is of type EVRControllerAxisType + //Prop_Axis3Type_Int32 = 3005, // Return value is of type EVRControllerAxisType + //Prop_Axis4Type_Int32 = 3006, // Return value is of type EVRControllerAxisType + +} + diff --git a/src/OSVRTrackedController.h b/src/OSVRTrackedController.h new file mode 100644 index 0000000..c20b54d --- /dev/null +++ b/src/OSVRTrackedController.h @@ -0,0 +1,135 @@ +/** @file + @brief OSVR tracked controller + + @date 2015 + + @author + Sensics, Inc. + +*/ + +// Copyright 2015 Sensics, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef INCLUDED_OSVRTrackedController_h_GUID_128E3B29_F5FC_4221_9B38_14E3F402E645 +#define INCLUDED_OSVRTrackedController_h_GUID_128E3B29_F5FC_4221_9B38_14E3F402E645 + + +#define NUM_BUTTONS 64 +#define NUM_TOUCHPAD 1 // only SteamVR Axis 0 for the moment (not implemented yet) +#define NUM_TRIGGER 1 // only SteamVR Axis 1 for the moment +#define NUM_JOYSTICKS 3 // only SteamVR Axis 2,3,4 for the moment (there is always x and y in one joystick) +#define NUM_AXIS 5 + +// Internal Includes +#include "OSVRTrackedDevice.h" +#include "osvr_compiler_detection.h" // for OSVR_OVERRIDE + +// OpenVR includes +#include + +// Library/third-party includes +#include +#include + +// Standard includes +#include + +class OSVRTrackedController; + +struct AnalogInterface { + osvr::clientkit::Interface analogInterfaceX; + osvr::clientkit::Interface analogInterfaceY; + + OSVRTrackedController* parentController; + + vr::EVRControllerAxisType axisType; + double x; + double y; + uint32_t axisIndex; +}; + + +class OSVRTrackedController : public OSVRTrackedDevice, public vr::IVRControllerComponent { + friend class ServerDriver_OSVR; + +public: + OSVRTrackedController(osvr::clientkit::ClientContext& context, vr::IServerDriverHost* driver_host, int controller_index); + + virtual ~OSVRTrackedController(); + + // ------------------------------------ + // Management Methods + // ------------------------------------ + + /** + * This is called before an HMD is returned to the application. It will + * always be called before any display or tracking methods. Memory and + * processor use by the ITrackedDeviceServerDriver object should be kept to + * a minimum until it is activated. The pose listener is guaranteed to be + * valid until Deactivate is called, but should not be used after that + * point. + */ + virtual vr::EVRInitError Activate(uint32_t object_id) OSVR_OVERRIDE; + + /** + * This is called when The VR system is switching from this Hmd being the + * active display to another Hmd being the active display. The driver should + * clean whatever memory and thread use it can when it is deactivated. + */ + virtual void Deactivate() OSVR_OVERRIDE; + + // ------------------------------------ + // Controller Methods + // ------------------------------------ + + /** + * Gets the current state of a controller. + */ + virtual vr::VRControllerState_t GetControllerState() OSVR_OVERRIDE; + + /** + * Returns a uint64 property. If the property is not available this function will return 0. + */ + virtual bool TriggerHapticPulse(uint32_t axis_id, uint16_t pulse_duration_microseconds) OSVR_OVERRIDE; + +protected: + const char* GetId(); + +private: + void configure(); + void configureProperties(); + + void freeInterfaces(); + + /** + * Callback function which is called whenever new data has been received + * from the tracker. + */ + static void controllerTrackerCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_PoseReport* report); + static void controllerButtonCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_ButtonReport* report); + static void controllerTriggerCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_AnalogReport* report); + static void controllerJoystickXCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_AnalogReport* report); + static void controllerJoystickYCallback(void* userdata, const OSVR_TimeValue* timestamp, const OSVR_AnalogReport* report); + + std::string controllerName_; + int controllerIndex_; + osvr::clientkit::Interface trackerInterface_; + osvr::clientkit::Interface buttonInterface_[NUM_BUTTONS]; + uint32_t numAxis_; + AnalogInterface analogInterface_[NUM_AXIS]; +}; + +#endif // INCLUDED_OSVRTrackedDevice_h_GUID_128E3B29_F5FC_4221_9B38_14E3F402E645 + diff --git a/src/OSVRTrackedHMD.cpp b/src/OSVRTrackedHMD.cpp index 0394f4d..4889026 100644 --- a/src/OSVRTrackedHMD.cpp +++ b/src/OSVRTrackedHMD.cpp @@ -70,7 +70,7 @@ vr::EVRInitError OSVRTrackedHMD::Activate(uint32_t object_id) { OSVR_LOG(trace) << "OSVRTrackedHMD::Activate() called."; - objectId_ = object_id; + OSVRTrackedDevice::Activate(object_id); const std::time_t waitTime = 5; // wait up to 5 seconds for init diff --git a/src/OSVRTrackingReference.cpp b/src/OSVRTrackingReference.cpp index 51995f8..24d2006 100644 --- a/src/OSVRTrackingReference.cpp +++ b/src/OSVRTrackingReference.cpp @@ -62,7 +62,7 @@ OSVRTrackingReference::~OSVRTrackingReference() vr::EVRInitError OSVRTrackingReference::Activate(uint32_t object_id) { OSVR_LOG(trace) << "OSVRTrackingReference::Activate() called."; - objectId_ = object_id; + OSVRTrackedDevice::Activate(object_id); // Clean up tracker callback if exists if (m_TrackerInterface.notEmpty()) {