openVROverlay.cpp 16 KB

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