openVROverlay.cpp
Engine/source/platform/input/openVR/openVROverlay.cpp
Public Variables
Public Functions
DefineEngineMethod(OpenVROverlay , hideOverlay , void , () , "" )
DefineEngineMethod(OpenVROverlay , showOverlay , void , () , "" )
ImplementEnumType(OpenVROverlayType , "Desired overlay type <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> OpenVROverlay. .\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@ingroup OpenVR" )
bool
setProtectedOverlayDirty(void * obj, const char * array, const char * data)
bool
setProtectedOverlayTypeDirty(void * obj, const char * array, const char * data)
Detailed Description
Public Variables
EndImplementEnumType
Public Functions
DefineEngineMethod(OpenVROverlay , hideOverlay , void , () , "" )
DefineEngineMethod(OpenVROverlay , showOverlay , void , () , "" )
IMPLEMENT_CONOBJECT(OpenVROverlay )
ImplementEnumType(OpenVROverlayType , "Desired overlay type <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> OpenVROverlay. .\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@ingroup OpenVR" )
setProtectedOverlayDirty(void * obj, const char * array, const char * data)
setProtectedOverlayTypeDirty(void * obj, const char * array, const char * data)
1 2#include "platform/input/openVR/openVRProvider.h" 3#include "platform/input/openVR/openVROverlay.h" 4 5#include "gfx/D3D11/gfxD3D11Device.h" 6#include "gfx/D3D11/gfxD3D11TextureObject.h" 7#include "gfx/D3D11/gfxD3D11EnumTranslate.h" 8 9#ifdef TORQUE_OPENGL 10#include "gfx/gl/gfxGLDevice.h" 11#include "gfx/gl/gfxGLTextureObject.h" 12#include "gfx/gl/gfxGLEnumTranslate.h" 13#endif 14 15#include "postFx/postEffectCommon.h" 16#include "gui/controls/guiTextEditCtrl.h" 17 18ImplementEnumType(OpenVROverlayType, 19 "Desired overlay type for OpenVROverlay. .\n\n" 20 "@ingroup OpenVR") 21{ OpenVROverlay::OVERLAYTYPE_OVERLAY, "Overlay" }, 22{ OpenVROverlay::OVERLAYTYPE_DASHBOARD, "Dashboard" }, 23EndImplementEnumType; 24 25IMPLEMENT_CONOBJECT(OpenVROverlay); 26 27OpenVROverlay::OpenVROverlay() 28{ 29 mTransform = MatrixF(1); 30 mOverlayWidth = 1.5f; 31 mOverlayFlags = 0; 32 33 mOverlayColor = LinearColorF(1, 1, 1, 1); 34 mTrackingOrigin = vr::TrackingUniverseSeated; 35 36 mTargetFormat = GFXFormatR8G8B8A8_LINEAR_FORCE; // needed for openvr! 37 mManualMouseHandling = true; 38 39 mMouseScale = Point2F(1, 1); 40} 41 42OpenVROverlay::~OpenVROverlay() 43{ 44 45} 46 47static bool setProtectedOverlayTypeDirty(void *obj, const char *array, const char *data) 48{ 49 OpenVROverlay *object = static_cast<OpenVROverlay*>(obj); 50 object->mOverlayTypeDirty = true; 51 return true; 52} 53 54static bool setProtectedOverlayDirty(void *obj, const char *array, const char *data) 55{ 56 OpenVROverlay *object = static_cast<OpenVROverlay*>(obj); 57 object->mOverlayDirty = true; 58 return true; 59} 60 61void OpenVROverlay::initPersistFields() 62{ 63 addProtectedField("overlayType", TypeOpenVROverlayType, Offset(mOverlayType, OpenVROverlay), &setProtectedOverlayTypeDirty, &defaultProtectedGetFn, 64 "Type of overlay."); 65 addProtectedField("overlayFlags", TypeS32, Offset(mOverlayFlags, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 66 "Flags for overlay."); 67 addProtectedField("overlayWidth", TypeF32, Offset(mOverlayWidth, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 68 "Width of overlay."); 69 addProtectedField("overlayColor", TypeColorF, Offset(mOverlayColor, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 70 "Backing color of overlay."); 71 72 addProtectedField("transformType", TypeOpenVROverlayTransformType, Offset(mOverlayTransformType, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 73 "Transform type of overlay."); 74 addProtectedField("transformPosition", TypeMatrixPosition, Offset(mTransform, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 75 "Position of overlay."); 76 addProtectedField("transformRotation", TypeMatrixRotation, Offset(mTransform, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 77 "Rotation of overlay."); 78 addProtectedField("transformDeviceIndex", TypeS32, Offset(mTransformDeviceIndex, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 79 "Rotation of overlay."); 80 addProtectedField("transformDeviceComponent", TypeString, Offset(mTransformDeviceComponent, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 81 "Rotation of overlay."); 82 83 addProtectedField("inputMethod", TypeOpenVROverlayInputMethod, Offset(mInputMethod, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 84 "Type of input method."); 85 addProtectedField("mouseScale", TypePoint2F, Offset(mMouseScale, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 86 "Scale of mouse input."); 87 88 addProtectedField("trackingOrigin", TypeOpenVRTrackingUniverseOrigin, Offset(mTrackingOrigin, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 89 "Tracking origin."); 90 91 addProtectedField("controllerDevice", TypeS32, Offset(mControllerDeviceIndex, OpenVROverlay), &setProtectedOverlayDirty, &defaultProtectedGetFn, 92 "Index of controller to attach overlay to."); 93 94 addField("manualMouseHandling", TypeBool, Offset(mManualMouseHandling, OpenVROverlay), "Forces openvr to create mouse events for overlay"); 95 96 Parent::initPersistFields(); 97} 98 99bool OpenVROverlay::onAdd() 100{ 101 if (Parent::onAdd()) 102 { 103 mOverlayTypeDirty = true; 104 mOverlayDirty = true; 105 106 if (OPENVR) 107 { 108 OPENVR->registerOverlay(this); 109 } 110 111 return true; 112 } 113 114 return false; 115} 116 117void OpenVROverlay::onRemove() 118{ 119 if (mOverlayHandle) 120 { 121 vr::VROverlay()->DestroyOverlay(mOverlayHandle); 122 mOverlayHandle = NULL; 123 } 124 125 if (mThumbOverlayHandle) 126 { 127 vr::VROverlay()->DestroyOverlay(mThumbOverlayHandle); 128 mThumbOverlayHandle = NULL; 129 } 130 131 if (ManagedSingleton<OpenVRProvider>::instanceOrNull()) 132 { 133 OPENVR->unregisterOverlay(this); 134 } 135} 136 137void OpenVROverlay::resetOverlay() 138{ 139 vr::IVROverlay *overlay = vr::VROverlay(); 140 if (!overlay) 141 return; 142 143 if (mOverlayHandle) 144 { 145 overlay->DestroyOverlay(mOverlayHandle); 146 mOverlayHandle = NULL; 147 } 148 149 if (mThumbOverlayHandle) 150 { 151 overlay->DestroyOverlay(mThumbOverlayHandle); 152 mThumbOverlayHandle = NULL; 153 } 154 155 if (mOverlayType == OpenVROverlay::OVERLAYTYPE_DASHBOARD) 156 { 157 overlay->CreateDashboardOverlay(mInternalName, mInternalName, &mOverlayHandle, &mThumbOverlayHandle); 158 } 159 else 160 { 161 overlay->CreateOverlay(mInternalName, mInternalName, &mOverlayHandle); 162 } 163 164 mOverlayDirty = true; 165 mOverlayTypeDirty = false; 166 167 // Pre-render start frame so we have a texture available 168 if (!mTarget) 169 { 170 renderFrame(false, false); 171 } 172} 173 174void OpenVROverlay::updateOverlay() 175{ 176 if (mOverlayTypeDirty) 177 resetOverlay(); 178 179 // Update params 180 vr::IVROverlay *overlay = vr::VROverlay(); 181 if (!overlay || !mOverlayHandle) 182 return; 183 184 if (!mOverlayDirty) 185 return; 186 187 MatrixF vrMat(1); 188 vr::HmdMatrix34_t ovrMat; 189 vr::HmdVector2_t ovrMouseScale; 190 ovrMouseScale.v[0] = mMouseScale.x; 191 ovrMouseScale.v[1] = mMouseScale.y; 192 193 OpenVRUtil::convertTransformToOVR(mTransform, vrMat); 194 OpenVRUtil::convertMatrixFPlainToSteamVRAffineMatrix(vrMat, ovrMat); 195 196 MatrixF reverseMat = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(ovrMat); 197 MatrixF finalReverseMat(1); 198 OpenVRUtil::convertTransformFromOVR(reverseMat, finalReverseMat); 199 200 switch (mOverlayTransformType) 201 { 202 case vr::VROverlayTransform_Absolute: 203 overlay->SetOverlayTransformAbsolute(mOverlayHandle, mTrackingOrigin, &ovrMat); 204 break; 205 case vr::VROverlayTransform_TrackedDeviceRelative: 206 overlay->SetOverlayTransformTrackedDeviceRelative(mOverlayHandle, mTransformDeviceIndex, &ovrMat); 207 break; 208 case vr::VROverlayTransform_TrackedComponent: 209 overlay->SetOverlayTransformTrackedDeviceComponent(mOverlayHandle, mTransformDeviceIndex, mTransformDeviceComponent.c_str()); 210 break; 211 // NOTE: system not handled here - doesn't seem possible to create these 212 default: 213 break; 214 } 215 216 // overlay->SetOverlayColor(mOverlayHandle, mOverlayColor.red, mOverlayColor.green, mOverlayColor.blue); 217 overlay->SetOverlayAlpha(mOverlayHandle, mOverlayColor.alpha); 218 overlay->SetOverlayMouseScale(mOverlayHandle, &ovrMouseScale); 219 overlay->SetOverlayInputMethod(mOverlayHandle, mInputMethod); 220 overlay->SetOverlayWidthInMeters(mOverlayHandle, mOverlayWidth); 221 222 // NOTE: if flags in openvr change, double check this 223 for (U32 i = vr::VROverlayFlags_None; i <= vr::VROverlayFlags_ShowTouchPadScrollWheel; i++) 224 { 225 overlay->SetOverlayFlag(mOverlayHandle, (vr::VROverlayFlags)i, mOverlayFlags & (1 << i)); 226 } 227 228 mOverlayDirty = false; 229} 230 231void OpenVROverlay::showOverlay() 232{ 233 updateOverlay(); 234 if (mOverlayHandle == NULL) 235 return; 236 237 if (mOverlayType != OVERLAYTYPE_DASHBOARD) 238 { 239 vr::EVROverlayError err = vr::VROverlay()->ShowOverlay(mOverlayHandle); 240 if (err != vr::VROverlayError_None) 241 { 242 Con::errorf("VR Overlay error!"); 243 } 244 } 245 246 if (!mStagingTexture) 247 { 248 renderFrame(false, false); 249 } 250} 251 252void OpenVROverlay::hideOverlay() 253{ 254 if (mOverlayHandle == NULL) 255 return; 256 257 if (mOverlayType != OVERLAYTYPE_DASHBOARD) 258 { 259 vr::VROverlay()->HideOverlay(mOverlayHandle); 260 } 261} 262 263 264bool OpenVROverlay::isOverlayVisible() 265{ 266 if (mOverlayHandle == NULL) 267 return false; 268 269 return vr::VROverlay()->IsOverlayVisible(mOverlayHandle); 270} 271 272bool OpenVROverlay::isOverlayHoverTarget() 273{ 274 if (mOverlayHandle == NULL) 275 return false; 276 277 return vr::VROverlay()->IsHoverTargetOverlay(mOverlayHandle); 278} 279 280 281bool OpenVROverlay::isGamepadFocussed() 282{ 283 if (mOverlayHandle == NULL) 284 return false; 285 286 return vr::VROverlay()->GetGamepadFocusOverlay() == mOverlayHandle; 287} 288 289bool OpenVROverlay::isActiveDashboardOverlay() 290{ 291 return false; // TODO WHERE DID I GET THIS FROM 292} 293 294MatrixF OpenVROverlay::getTransformForOverlayCoordinates(const Point2F &pos) 295{ 296 if (mOverlayHandle == NULL) 297 return MatrixF::Identity; 298 299 vr::HmdVector2_t vec; 300 vec.v[0] = pos.x; 301 vec.v[1] = pos.y; 302 vr::HmdMatrix34_t outMat; 303 MatrixF outTorqueMat; 304 if (vr::VROverlay()->GetTransformForOverlayCoordinates(mOverlayHandle, mTrackingOrigin, vec, &outMat) != vr::VROverlayError_None) 305 return MatrixF::Identity; 306 307 MatrixF vrMat(1); 308 vrMat = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(outMat); 309 OpenVRUtil::convertTransformFromOVR(vrMat, outTorqueMat); 310 return outTorqueMat; 311} 312 313bool OpenVROverlay::castRay(const Point3F &origin, const Point3F &direction, RayInfo *info) 314{ 315 if (mOverlayHandle == NULL) 316 return false; 317 318 vr::VROverlayIntersectionParams_t params; 319 vr::VROverlayIntersectionResults_t result; 320 321 Point3F ovrOrigin = OpenVRUtil::convertPointToOVR(origin); 322 Point3F ovrDirection = OpenVRUtil::convertPointToOVR(direction); 323 324 params.eOrigin = mTrackingOrigin; 325 params.vSource.v[0] = ovrOrigin.x; 326 params.vSource.v[1] = ovrOrigin.y; 327 params.vSource.v[2] = ovrOrigin.z; 328 params.vDirection.v[0] = ovrDirection.x; 329 params.vDirection.v[1] = ovrDirection.y; 330 params.vDirection.v[2] = ovrDirection.z; 331 332 bool rayHit = vr::VROverlay()->ComputeOverlayIntersection(mOverlayHandle, ¶ms, &result); 333 334 if (rayHit && info) 335 { 336 info->t = result.fDistance; 337 info->point = OpenVRUtil::convertPointFromOVR(result.vPoint); // TODO: need to transform this FROM vr-space 338 info->normal = OpenVRUtil::convertPointFromOVR(result.vNormal); 339 info->texCoord = Point2F(result.vUVs.v[0], result.vUVs.v[1]); 340 info->object = NULL; 341 info->userData = this; 342 } 343 344 return rayHit; 345} 346 347void OpenVROverlay::moveGamepadFocusToNeighbour() 348{ 349 350} 351 352void OpenVROverlay::handleOpenVREvents() 353{ 354 if (mManualMouseHandling) 355 { 356 // tell OpenVR to make some events for us 357 for (vr::TrackedDeviceIndex_t unDeviceId = 1; unDeviceId < vr::k_unControllerStateAxisCount; unDeviceId++) 358 { 359 if (vr::VROverlay()->HandleControllerOverlayInteractionAsMouse(mOverlayHandle, unDeviceId)) 360 { 361 break; 362 } 363 } 364 } 365 366 367 vr::VREvent_t vrEvent; 368 while (vr::VROverlay()->PollNextOverlayEvent(mOverlayHandle, &vrEvent, sizeof(vrEvent))) 369 { 370 InputEventInfo eventInfo; 371 eventInfo.deviceType = MouseDeviceType; 372 eventInfo.deviceInst = 0; 373 eventInfo.objType = SI_AXIS; 374 eventInfo.modifier = (InputModifiers)0; 375 eventInfo.ascii = 0; 376 377 //Con::printf("Overlay event %i", vrEvent.eventType); 378 379 switch (vrEvent.eventType) 380 { 381 case vr::VREvent_MouseMove: 382 { 383 //Con::printf("mousemove %f,%f", vrEvent.data.mouse.x, vrEvent.data.mouse.y); 384 eventInfo.objType = SI_AXIS; 385 eventInfo.objInst = SI_XAXIS; 386 eventInfo.action = SI_MAKE; 387 eventInfo.fValue = getExtent().x * vrEvent.data.mouse.x; 388 processMouseEvent(eventInfo); 389 390 eventInfo.objType = SI_AXIS; 391 eventInfo.objInst = SI_YAXIS; 392 eventInfo.action = SI_MAKE; 393 eventInfo.fValue = getExtent().y * (1.0 - vrEvent.data.mouse.y); 394 processMouseEvent(eventInfo); 395 } 396 break; 397 398 case vr::VREvent_MouseButtonDown: 399 { 400 eventInfo.objType = SI_BUTTON; 401 eventInfo.objInst = (InputObjectInstances)OpenVRUtil::convertOpenVRButtonToTorqueButton(vrEvent.data.mouse.button); 402 eventInfo.action = SI_MAKE; 403 eventInfo.fValue = 1.0f; 404 processMouseEvent(eventInfo); 405 } 406 break; 407 408 case vr::VREvent_MouseButtonUp: 409 { 410 eventInfo.objType = SI_BUTTON; 411 eventInfo.objInst = (InputObjectInstances)OpenVRUtil::convertOpenVRButtonToTorqueButton(vrEvent.data.mouse.button); 412 eventInfo.action = SI_BREAK; 413 eventInfo.fValue = 0.0f; 414 processMouseEvent(eventInfo); 415 } 416 break; 417 418 case vr::VREvent_OverlayShown: 419 { 420 markDirty(); 421 } 422 break; 423 424 case vr::VREvent_Quit: 425 AssertFatal(false, "WTF is going on here"); 426 break; 427 428 case vr::VREvent_KeyboardCharInput: 429 case vr::VREvent_KeyboardDone: 430 updateTextControl((GuiControl*)vrEvent.data.keyboard.uUserValue); 431 break; 432 } 433 434 } 435 436 if (mThumbOverlayHandle != vr::k_ulOverlayHandleInvalid) 437 { 438 while (vr::VROverlay()->PollNextOverlayEvent(mThumbOverlayHandle, &vrEvent, sizeof(vrEvent))) 439 { 440 switch (vrEvent.eventType) 441 { 442 case vr::VREvent_OverlayShown: 443 { 444 markDirty(); 445 } 446 break; 447 } 448 } 449 } 450} 451 452void OpenVROverlay::updateTextControl(GuiControl* ctrl) 453{ 454 if (!ctrl) 455 return; 456 457 GuiTextCtrl* textCtrl = dynamic_cast<GuiTextCtrl*>(ctrl); 458 if (textCtrl) 459 { 460 char text[GuiTextCtrl::MAX_STRING_LENGTH]; 461 vr::VROverlay()->GetKeyboardText(text, GuiTextCtrl::MAX_STRING_LENGTH); 462 textCtrl->setText(text); 463 } 464} 465 466void OpenVROverlay::onFrameRendered() 467{ 468 vr::IVROverlay *overlay = vr::VROverlay(); 469 if (!overlay || !mOverlayHandle) 470 return; 471 472 updateOverlay(); 473 474 Point2I desiredSize = mTarget->getSize(); 475 if (mStagingTexture.isNull() || mStagingTexture.getWidthHeight() != desiredSize) 476 { 477 Point2I sz = mStagingTexture.getWidthHeight(); 478 mStagingTexture.set(desiredSize.x, desiredSize.y, mTargetFormat, &VRTextureProfile, "OpenVROverlay staging texture"); 479 } 480 mTarget->resolveTo(mStagingTexture); 481 482 vr::Texture_t tex; 483 if (GFX->getAdapterType() == Direct3D11) 484 { 485 tex = { (void*)static_cast<GFXD3D11TextureObject*>(mStagingTexture.getPointer())->getResource(), vr::API_DirectX, vr::ColorSpace_Auto }; 486 } 487#ifdef TORQUE_OPENGL 488 else if (GFX->getAdapterType() == OpenGL) 489 { 490 tex = { (void*)static_cast<GFXGLTextureObject*>(mStagingTexture.getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Auto }; 491 492 } 493#endif 494 else 495 { 496 return; 497 } 498 499 //mStagingTexture->dumpToDisk("PNG", "D:\\test.png"); 500 501 vr::EVROverlayError err = overlay->SetOverlayTexture(mOverlayHandle, &tex); 502 if (err != vr::VROverlayError_None) 503 { 504 Con::errorf("VR: Error setting overlay texture."); 505 } 506 507 //Con::printf("Overlay visible ? %s", vr::VROverlay()->IsOverlayVisible(mOverlayHandle) ? "YES" : "NO"); 508} 509 510void OpenVROverlay::enableKeyboardTranslation() 511{ 512 vr::IVROverlay *overlay = vr::VROverlay(); 513 if (!overlay || !mOverlayHandle) 514 return; 515 516 GuiTextEditCtrl* ctrl = dynamic_cast<GuiTextEditCtrl*>(getFirstResponder()); 517 if (ctrl) 518 { 519 vr::EGamepadTextInputMode inputMode = ctrl->isPasswordText() ? vr::k_EGamepadTextInputModePassword : vr::k_EGamepadTextInputModeNormal; 520 char text[GuiTextCtrl::MAX_STRING_LENGTH + 1]; 521 ctrl->getText(text); 522 overlay->ShowKeyboardForOverlay(mOverlayHandle, inputMode, vr::k_EGamepadTextInputLineModeSingleLine, ctrl->getTooltip().c_str(), GuiTextCtrl::MAX_STRING_LENGTH, text, false, (uint64_t)ctrl); 523 } 524} 525 526void OpenVROverlay::disableKeyboardTranslation() 527{ 528 vr::IVROverlay *overlay = vr::VROverlay(); 529 if (!overlay || !mOverlayHandle) 530 return; 531 532 overlay->HideKeyboard(); 533} 534 535void OpenVROverlay::setNativeAcceleratorsEnabled(bool enabled) 536{ 537} 538 539DefineEngineMethod(OpenVROverlay, showOverlay, void, (), , "") 540{ 541 object->showOverlay(); 542} 543 544DefineEngineMethod(OpenVROverlay, hideOverlay, void, (), , "") 545{ 546 object->hideOverlay(); 547} 548