openVRProvider.cpp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. #include "platform/input/openVR/openVRProvider.h"
  2. #include "platform/input/openVR/openVROverlay.h"
  3. #include "platform/platformInput.h"
  4. #include "core/module.h"
  5. #include "console/engineAPI.h"
  6. #include "T3D/gameBase/gameConnection.h"
  7. #include "gui/core/guiCanvas.h"
  8. #include "postFx/postEffectCommon.h"
  9. #include "gfx/D3D11/gfxD3D11Device.h"
  10. #include "gfx/D3D11/gfxD3D11TextureObject.h"
  11. #include "gfx/D3D11/gfxD3D11EnumTranslate.h"
  12. #include "gfx/gfxStringEnumTranslate.h"
  13. #include "gfx/D3D9/gfxD3D9Device.h"
  14. #include "gfx/D3D9/gfxD3D9TextureObject.h"
  15. #include "gfx/D3D9/gfxD3D9EnumTranslate.h"
  16. #ifdef TORQUE_OPENGL
  17. #include "gfx/gl/gfxGLDevice.h"
  18. #include "gfx/gl/gfxGLTextureObject.h"
  19. #include "gfx/gl/gfxGLEnumTranslate.h"
  20. #endif
  21. AngAxisF gLastMoveRot; // jamesu - this is just here for temp debugging
  22. namespace OpenVRUtil
  23. {
  24. void convertTransformFromOVR(const MatrixF &inRotTMat, MatrixF& outRotation)
  25. {
  26. Point4F col0; inRotTMat.getColumn(0, &col0);
  27. Point4F col1; inRotTMat.getColumn(1, &col1);
  28. Point4F col2; inRotTMat.getColumn(2, &col2);
  29. Point4F col3; inRotTMat.getColumn(3, &col3);
  30. // Set rotation. We need to convert from sensor coordinates to
  31. // Torque coordinates. The sensor matrix is stored row-major.
  32. // The conversion is:
  33. //
  34. // Sensor Torque
  35. // a b c a b c a -c b
  36. // d e f --> -g -h -i --> -g i -h
  37. // g h i d e f d -f e
  38. outRotation.setColumn(0, Point4F( col0.x, -col2.x, col1.x, 0.0f));
  39. outRotation.setColumn(1, Point4F(-col0.z, col2.z, -col1.z, 0.0f));
  40. outRotation.setColumn(2, Point4F( col0.y, -col2.y, col1.y, 0.0f));
  41. outRotation.setColumn(3, Point4F(-col3.x, col3.z, -col3.y, 1.0f));
  42. }
  43. void convertTransformToOVR(const MatrixF& inRotation, MatrixF& outRotation)
  44. {
  45. Point4F col0; inRotation.getColumn(0, &col0);
  46. Point4F col1; inRotation.getColumn(1, &col1);
  47. Point4F col2; inRotation.getColumn(2, &col2);
  48. Point4F col3; inRotation.getColumn(3, &col3);
  49. // This is basically a reverse of what is in convertTransformFromOVR
  50. outRotation.setColumn(0, Point4F(col0.x, col2.x, -col1.x, 0.0f));
  51. outRotation.setColumn(1, Point4F(col0.z, col2.z, -col1.z, 0.0f));
  52. outRotation.setColumn(2, Point4F(-col0.y, -col2.y, col1.y, 0.0f));
  53. outRotation.setColumn(3, Point4F(-col3.x, -col3.z, col3.y, 1.0f));
  54. }
  55. MatrixF convertSteamVRAffineMatrixToMatrixFPlain(const vr::HmdMatrix34_t &mat)
  56. {
  57. MatrixF outMat(1);
  58. outMat.setColumn(0, Point4F(mat.m[0][0], mat.m[1][0], mat.m[2][0], 0.0));
  59. outMat.setColumn(1, Point4F(mat.m[0][1], mat.m[1][1], mat.m[2][1], 0.0));
  60. outMat.setColumn(2, Point4F(mat.m[0][2], mat.m[1][2], mat.m[2][2], 0.0));
  61. outMat.setColumn(3, Point4F(mat.m[0][3], mat.m[1][3], mat.m[2][3], 1.0f)); // pos
  62. return outMat;
  63. }
  64. void convertMatrixFPlainToSteamVRAffineMatrix(const MatrixF &inMat, vr::HmdMatrix34_t &outMat)
  65. {
  66. Point4F row0; inMat.getRow(0, &row0);
  67. Point4F row1; inMat.getRow(1, &row1);
  68. Point4F row2; inMat.getRow(2, &row2);
  69. outMat.m[0][0] = row0.x;
  70. outMat.m[0][1] = row0.y;
  71. outMat.m[0][2] = row0.z;
  72. outMat.m[0][3] = row0.w;
  73. outMat.m[1][0] = row1.x;
  74. outMat.m[1][1] = row1.y;
  75. outMat.m[1][2] = row1.z;
  76. outMat.m[1][3] = row1.w;
  77. outMat.m[2][0] = row2.x;
  78. outMat.m[2][1] = row2.y;
  79. outMat.m[2][2] = row2.z;
  80. outMat.m[2][3] = row2.w;
  81. }
  82. U32 convertOpenVRButtonToTorqueButton(uint32_t vrButton)
  83. {
  84. switch (vrButton)
  85. {
  86. case vr::VRMouseButton_Left:
  87. return KEY_BUTTON0;
  88. case vr::VRMouseButton_Right:
  89. return KEY_BUTTON1;
  90. case vr::VRMouseButton_Middle:
  91. return KEY_BUTTON2;
  92. }
  93. }
  94. vr::VRTextureBounds_t TorqueRectToBounds(const RectI &rect, const Point2I &widthHeight)
  95. {
  96. vr::VRTextureBounds_t bounds;
  97. F32 xRatio = 1.0 / (F32)widthHeight.x;
  98. F32 yRatio = 1.0 / (F32)widthHeight.y;
  99. bounds.uMin = rect.point.x * xRatio;
  100. bounds.vMin = rect.point.y * yRatio;
  101. bounds.uMax = (rect.point.x + rect.extent.x) * xRatio;
  102. bounds.vMax = (rect.point.y + rect.extent.y) * yRatio;
  103. return bounds;
  104. }
  105. }
  106. //------------------------------------------------------------
  107. DECLARE_SCOPE(OpenVR);
  108. IMPLEMENT_SCOPE(OpenVR, OpenVRProvider, , "");
  109. ConsoleDoc(
  110. "@class OpenVRProvider\n"
  111. "@brief This class is the interface between TorqueScript and OpenVR.\n\n"
  112. "@ingroup OpenVR\n"
  113. );
  114. // Enum impls
  115. ImplementEnumType(OpenVROverlayInputMethod,
  116. "Types of input supported by VR Overlays. .\n\n"
  117. "@ingroup OpenVR")
  118. { vr::VROverlayInputMethod_None, "None" },
  119. { vr::VROverlayInputMethod_Mouse, "Mouse" },
  120. EndImplementEnumType;
  121. ImplementEnumType(OpenVROverlayTransformType,
  122. "Allows the caller to figure out which overlay transform getter to call. .\n\n"
  123. "@ingroup OpenVR")
  124. { vr::VROverlayTransform_Absolute, "Absolute" },
  125. { vr::VROverlayTransform_TrackedDeviceRelative, "TrackedDeviceRelative" },
  126. { vr::VROverlayTransform_SystemOverlay, "SystemOverlay" },
  127. { vr::VROverlayTransform_TrackedComponent, "TrackedComponent" },
  128. EndImplementEnumType;
  129. ImplementEnumType(OpenVRGamepadTextInputMode,
  130. "Types of input supported by VR Overlays. .\n\n"
  131. "@ingroup OpenVR")
  132. { vr::k_EGamepadTextInputModeNormal, "Normal", },
  133. { vr::k_EGamepadTextInputModePassword, "Password", },
  134. { vr::k_EGamepadTextInputModeSubmit, "Submit" },
  135. EndImplementEnumType;
  136. ImplementEnumType(OpenVRGamepadTextInputLineMode,
  137. "Types of input supported by VR Overlays. .\n\n"
  138. "@ingroup OpenVR")
  139. { vr::k_EGamepadTextInputLineModeSingleLine, "SingleLine" },
  140. { vr::k_EGamepadTextInputLineModeMultipleLines, "MultipleLines" },
  141. EndImplementEnumType;
  142. ImplementEnumType(OpenVRTrackingResult,
  143. ". .\n\n"
  144. "@ingroup OpenVR")
  145. { vr::TrackingResult_Uninitialized, "None" },
  146. { vr::TrackingResult_Calibrating_InProgress, "Calibrating_InProgress" },
  147. { vr::TrackingResult_Calibrating_OutOfRange, "Calibrating_OutOfRange" },
  148. { vr::TrackingResult_Running_OK, "Running_Ok" },
  149. { vr::TrackingResult_Running_OutOfRange, "Running_OutOfRange" },
  150. EndImplementEnumType;
  151. ImplementEnumType(OpenVRTrackingUniverseOrigin,
  152. "Identifies which style of tracking origin the application wants to use for the poses it is requesting. .\n\n"
  153. "@ingroup OpenVR")
  154. { vr::TrackingUniverseSeated, "Seated" },
  155. { vr::TrackingUniverseStanding, "Standing" },
  156. { vr::TrackingUniverseRawAndUncalibrated, "RawAndUncalibrated" },
  157. EndImplementEnumType;
  158. ImplementEnumType(OpenVROverlayDirection,
  159. "Directions for changing focus between overlays with the gamepad. .\n\n"
  160. "@ingroup OpenVR")
  161. { vr::OverlayDirection_Up, "Up" },
  162. { vr::OverlayDirection_Down, "Down" },
  163. { vr::OverlayDirection_Left, "Left" },
  164. { vr::OverlayDirection_Right, "Right" },
  165. EndImplementEnumType;
  166. ImplementEnumType(OpenVRState,
  167. "Status of the overall system or tracked objects. .\n\n"
  168. "@ingroup OpenVR")
  169. { vr::VRState_Undefined, "Undefined" },
  170. { vr::VRState_Off, "Off" },
  171. { vr::VRState_Searching, "Searching" },
  172. { vr::VRState_Searching_Alert, "Searching_Alert" },
  173. { vr::VRState_Ready, "Ready" },
  174. { vr::VRState_Ready_Alert, "Ready_Alert" },
  175. { vr::VRState_NotReady, "NotReady" },
  176. EndImplementEnumType;
  177. //------------------------------------------------------------
  178. U32 OpenVRProvider::OVR_SENSORROT[vr::k_unMaxTrackedDeviceCount] = { 0 };
  179. U32 OpenVRProvider::OVR_SENSORROTANG[vr::k_unMaxTrackedDeviceCount] = { 0 };
  180. U32 OpenVRProvider::OVR_SENSORVELOCITY[vr::k_unMaxTrackedDeviceCount] = { 0 };
  181. U32 OpenVRProvider::OVR_SENSORANGVEL[vr::k_unMaxTrackedDeviceCount] = { 0 };
  182. U32 OpenVRProvider::OVR_SENSORMAGNETOMETER[vr::k_unMaxTrackedDeviceCount] = { 0 };
  183. U32 OpenVRProvider::OVR_SENSORPOSITION[vr::k_unMaxTrackedDeviceCount] = { 0 };
  184. U32 OpenVRProvider::OVR_BUTTONPRESSED[vr::k_unMaxTrackedDeviceCount];
  185. U32 OpenVRProvider::OVR_BUTTONTOUCHED[vr::k_unMaxTrackedDeviceCount];
  186. U32 OpenVRProvider::OVR_AXISNONE[vr::k_unMaxTrackedDeviceCount] = { 0 };
  187. U32 OpenVRProvider::OVR_AXISTRACKPAD[vr::k_unMaxTrackedDeviceCount] = { 0 };
  188. U32 OpenVRProvider::OVR_AXISJOYSTICK[vr::k_unMaxTrackedDeviceCount] = { 0 };
  189. U32 OpenVRProvider::OVR_AXISTRIGGER[vr::k_unMaxTrackedDeviceCount] = { 0 };
  190. static String GetTrackedDeviceString(vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError = NULL)
  191. {
  192. uint32_t unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, NULL, 0, peError);
  193. if (unRequiredBufferLen == 0)
  194. return "";
  195. char *pchBuffer = new char[unRequiredBufferLen];
  196. unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, pchBuffer, unRequiredBufferLen, peError);
  197. String sResult = pchBuffer;
  198. delete[] pchBuffer;
  199. return sResult;
  200. }
  201. MODULE_BEGIN(OpenVRProvider)
  202. MODULE_INIT_AFTER(InputEventManager)
  203. MODULE_SHUTDOWN_BEFORE(InputEventManager)
  204. MODULE_INIT
  205. {
  206. OpenVRProvider::staticInit();
  207. ManagedSingleton< OpenVRProvider >::createSingleton();
  208. }
  209. MODULE_SHUTDOWN
  210. {
  211. ManagedSingleton< OpenVRProvider >::deleteSingleton();
  212. }
  213. MODULE_END;
  214. bool OpenVRRenderState::setupRenderTargets(GFXDevice::GFXDeviceRenderStyles mode)
  215. {
  216. if (!mHMD)
  217. return false;
  218. if (mRenderMode == mode)
  219. return true;
  220. mRenderMode = mode;
  221. if (mode == GFXDevice::RS_Standard)
  222. {
  223. reset(mHMD);
  224. return true;
  225. }
  226. U32 sizeX, sizeY;
  227. Point2I newRTSize;
  228. mHMD->GetRecommendedRenderTargetSize(&sizeX, &sizeY);
  229. if (mode == GFXDevice::RS_StereoSeparate)
  230. {
  231. mEyeViewport[0] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY));
  232. mEyeViewport[1] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY));
  233. newRTSize.x = sizeX;
  234. newRTSize.y = sizeY;
  235. }
  236. else
  237. {
  238. mEyeViewport[0] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY));
  239. mEyeViewport[1] = RectI(Point2I(sizeX, 0), Point2I(sizeX, sizeY));
  240. newRTSize.x = sizeX * 2;
  241. newRTSize.y = sizeY;
  242. }
  243. GFXTexHandle stereoTexture;
  244. stereoTexture.set(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8, &VRTextureProfile, "OpenVR Stereo RT Color");
  245. mStereoRenderTexture = stereoTexture;
  246. GFXTexHandle stereoDepthTexture;
  247. stereoDepthTexture.set(newRTSize.x, newRTSize.y, GFXFormatD24S8, &VRDepthProfile, "OpenVR Depth");
  248. mStereoDepthTexture = stereoDepthTexture;
  249. mStereoRT = GFX->allocRenderToTextureTarget();
  250. mStereoRT->attachTexture(GFXTextureTarget::Color0, stereoTexture);
  251. mStereoRT->attachTexture(GFXTextureTarget::DepthStencil, stereoDepthTexture);
  252. mOutputEyeTextures.init(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8, &VRTextureProfile, "OpenVR Stereo RT Color OUTPUT");
  253. return true;
  254. }
  255. void OpenVRRenderState::renderPreview()
  256. {
  257. }
  258. void OpenVRRenderState::reset(vr::IVRSystem* hmd)
  259. {
  260. mHMD = hmd;
  261. mStereoRT = NULL;
  262. mStereoRenderTexture = NULL;
  263. mStereoDepthTexture = NULL;
  264. mOutputEyeTextures.clear();
  265. if (!mHMD)
  266. return;
  267. vr::HmdMatrix34_t mat = mHMD->GetEyeToHeadTransform(vr::Eye_Left);
  268. mEyePose[0] = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mat);
  269. mEyePose[0].inverse();
  270. mat = mHMD->GetEyeToHeadTransform(vr::Eye_Right);
  271. mEyePose[1] = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mat);
  272. mEyePose[1].inverse();
  273. mHMD->GetProjectionRaw(vr::Eye_Left, &mEyeFov[0].leftTan, &mEyeFov[0].rightTan, &mEyeFov[0].upTan, &mEyeFov[0].downTan);
  274. mHMD->GetProjectionRaw(vr::Eye_Right, &mEyeFov[1].leftTan, &mEyeFov[1].rightTan, &mEyeFov[1].upTan, &mEyeFov[1].downTan);
  275. mEyeFov[0].upTan = -mEyeFov[0].upTan;
  276. mEyeFov[0].leftTan = -mEyeFov[0].leftTan;
  277. mEyeFov[1].upTan = -mEyeFov[1].upTan;
  278. mEyeFov[1].leftTan = -mEyeFov[1].leftTan;
  279. }
  280. OpenVRProvider::OpenVRProvider() :
  281. mHMD(NULL),
  282. mRenderModels(NULL),
  283. mDrawCanvas(NULL),
  284. mGameConnection(NULL)
  285. {
  286. dStrcpy(mName, "openvr");
  287. mDeviceType = INPUTMGR->getNextDeviceType();
  288. buildInputCodeTable();
  289. GFXDevice::getDeviceEventSignal().notify(this, &OpenVRProvider::_handleDeviceEvent);
  290. INPUTMGR->registerDevice(this);
  291. dMemset(&mLUID, '\0', sizeof(mLUID));
  292. mTrackingSpace = vr::TrackingUniverseSeated;
  293. }
  294. OpenVRProvider::~OpenVRProvider()
  295. {
  296. }
  297. void OpenVRProvider::staticInit()
  298. {
  299. // Overlay flags
  300. Con::setIntVariable("$OpenVR::OverlayFlags_None", 1 << (U32)vr::VROverlayFlags_None);
  301. Con::setIntVariable("$OpenVR::OverlayFlags_Curved", 1 << (U32)vr::VROverlayFlags_Curved);
  302. Con::setIntVariable("$OpenVR::OverlayFlags_RGSS4X", 1 << (U32)vr::VROverlayFlags_RGSS4X);
  303. Con::setIntVariable("$OpenVR::OverlayFlags_NoDashboardTab", 1 << (U32)vr::VROverlayFlags_NoDashboardTab);
  304. Con::setIntVariable("$OpenVR::OverlayFlags_AcceptsGamepadEvents", 1 << (U32)vr::VROverlayFlags_AcceptsGamepadEvents);
  305. Con::setIntVariable("$OpenVR::OverlayFlags_ShowGamepadFocus", 1 << (U32)vr::VROverlayFlags_ShowGamepadFocus);
  306. Con::setIntVariable("$OpenVR::OverlayFlags_SendVRScrollEvents", 1 << (U32)vr::VROverlayFlags_SendVRScrollEvents);
  307. Con::setIntVariable("$OpenVR::OverlayFlags_SendVRTouchpadEvents", 1 << (U32)vr::VROverlayFlags_SendVRTouchpadEvents);
  308. Con::setIntVariable("$OpenVR::OverlayFlags_ShowTouchPadScrollWheel", 1 << (U32)vr::VROverlayFlags_ShowTouchPadScrollWheel);
  309. }
  310. bool OpenVRProvider::enable()
  311. {
  312. disable();
  313. // Load openvr runtime
  314. vr::EVRInitError eError = vr::VRInitError_None;
  315. mHMD = vr::VR_Init(&eError, vr::VRApplication_Scene);
  316. dMemset(mDeviceClassChar, '\0', sizeof(mDeviceClassChar));
  317. if (eError != vr::VRInitError_None)
  318. {
  319. mHMD = NULL;
  320. char buf[1024];
  321. sprintf_s(buf, sizeof(buf), "Unable to init VR runtime: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
  322. Con::printf(buf);
  323. return false;
  324. }
  325. dMemset(&mLUID, '\0', sizeof(mLUID));
  326. #ifdef TORQUE_OS_WIN32
  327. // For windows we need to lookup the DXGI record for this and grab the LUID for the display adapter. We need the LUID since
  328. // T3D uses EnumAdapters1 not EnumAdapters whereas openvr uses EnumAdapters.
  329. int32_t AdapterIdx;
  330. IDXGIAdapter* EnumAdapter;
  331. IDXGIFactory1* DXGIFactory;
  332. mHMD->GetDXGIOutputInfo(&AdapterIdx);
  333. // Get the LUID of the device
  334. HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&DXGIFactory));
  335. if (FAILED(hr))
  336. AssertFatal(false, "OpenVRProvider::enable -> CreateDXGIFactory1 call failure");
  337. hr = DXGIFactory->EnumAdapters(AdapterIdx, &EnumAdapter);
  338. if (FAILED(hr))
  339. {
  340. Con::warnf("VR: HMD device has an invalid adapter.");
  341. }
  342. else
  343. {
  344. DXGI_ADAPTER_DESC desc;
  345. hr = EnumAdapter->GetDesc(&desc);
  346. if (FAILED(hr))
  347. {
  348. Con::warnf("VR: HMD device has an invalid adapter.");
  349. }
  350. else
  351. {
  352. dMemcpy(&mLUID, &desc.AdapterLuid, sizeof(mLUID));
  353. }
  354. SAFE_RELEASE(EnumAdapter);
  355. }
  356. SAFE_RELEASE(DXGIFactory);
  357. #endif
  358. mRenderModels = (vr::IVRRenderModels *)vr::VR_GetGenericInterface(vr::IVRRenderModels_Version, &eError);
  359. if (!mRenderModels)
  360. {
  361. mHMD = NULL;
  362. vr::VR_Shutdown();
  363. char buf[1024];
  364. sprintf_s(buf, sizeof(buf), "Unable to get render model interface: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
  365. Con::printf(buf);
  366. return false;
  367. }
  368. mDriver = GetTrackedDeviceString(mHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
  369. mDisplay = GetTrackedDeviceString(mHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);
  370. mHMDRenderState.reset(mHMD);
  371. mHMD->ResetSeatedZeroPose();
  372. dMemset(mPreviousInputTrackedDevicePose, '\0', sizeof(mPreviousInputTrackedDevicePose));
  373. mEnabled = true;
  374. return true;
  375. }
  376. bool OpenVRProvider::disable()
  377. {
  378. if (mHMD)
  379. {
  380. mHMD = NULL;
  381. mRenderModels = NULL;
  382. mHMDRenderState.reset(NULL);
  383. vr::VR_Shutdown();
  384. }
  385. mEnabled = false;
  386. return true;
  387. }
  388. void OpenVRProvider::buildInputCodeTable()
  389. {
  390. // Obtain all of the device codes
  391. for (U32 i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i)
  392. {
  393. OVR_SENSORROT[i] = INPUTMGR->getNextDeviceCode();
  394. OVR_SENSORROTANG[i] = INPUTMGR->getNextDeviceCode();
  395. OVR_SENSORVELOCITY[i] = INPUTMGR->getNextDeviceCode();
  396. OVR_SENSORANGVEL[i] = INPUTMGR->getNextDeviceCode();
  397. OVR_SENSORMAGNETOMETER[i] = INPUTMGR->getNextDeviceCode();
  398. OVR_SENSORPOSITION[i] = INPUTMGR->getNextDeviceCode();
  399. OVR_BUTTONPRESSED[i] = INPUTMGR->getNextDeviceCode();
  400. OVR_BUTTONTOUCHED[i] = INPUTMGR->getNextDeviceCode();
  401. OVR_AXISNONE[i] = INPUTMGR->getNextDeviceCode();
  402. OVR_AXISTRACKPAD[i] = INPUTMGR->getNextDeviceCode();
  403. OVR_AXISJOYSTICK[i] = INPUTMGR->getNextDeviceCode();
  404. OVR_AXISTRIGGER[i] = INPUTMGR->getNextDeviceCode();
  405. }
  406. // Build out the virtual map
  407. char buffer[64];
  408. for (U32 i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i)
  409. {
  410. dSprintf(buffer, 64, "opvr_sensorrot%d", i);
  411. INPUTMGR->addVirtualMap(buffer, SI_ROT, OVR_SENSORROT[i]);
  412. dSprintf(buffer, 64, "opvr_sensorrotang%d", i);
  413. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORROTANG[i]);
  414. dSprintf(buffer, 64, "opvr_sensorvelocity%d", i);
  415. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORVELOCITY[i]);
  416. dSprintf(buffer, 64, "opvr_sensorangvel%d", i);
  417. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORANGVEL[i]);
  418. dSprintf(buffer, 64, "opvr_sensormagnetometer%d", i);
  419. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORMAGNETOMETER[i]);
  420. dSprintf(buffer, 64, "opvr_sensorpos%d", i);
  421. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORPOSITION[i]);
  422. dSprintf(buffer, 64, "opvr_buttonpressed%d", i);
  423. INPUTMGR->addVirtualMap(buffer, SI_INT, OVR_BUTTONPRESSED[i]);
  424. dSprintf(buffer, 64, "opvr_buttontouched%d", i);
  425. INPUTMGR->addVirtualMap(buffer, SI_INT, OVR_BUTTONTOUCHED[i]);
  426. dSprintf(buffer, 64, "opvr_axis_none%d", i);
  427. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_AXISNONE[i]);
  428. dSprintf(buffer, 64, "opvr_axis_trackpad%d", i);
  429. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_AXISTRACKPAD[i]);
  430. dSprintf(buffer, 64, "opvr_axis_joystick%d", i);
  431. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_AXISJOYSTICK[i]);
  432. dSprintf(buffer, 64, "opvr_axis_trigger%d", i);
  433. INPUTMGR->addVirtualMap(buffer, SI_INT, OVR_AXISTRIGGER[i]);
  434. }
  435. }
  436. bool OpenVRProvider::process()
  437. {
  438. if (!mHMD)
  439. return true;
  440. if (!vr::VRCompositor())
  441. return true;
  442. // Process SteamVR events
  443. vr::VREvent_t event;
  444. while (mHMD->PollNextEvent(&event, sizeof(event)))
  445. {
  446. processVREvent(event);
  447. }
  448. // process overlay events
  449. for (U32 i = 0; i < mOverlays.size(); i++)
  450. {
  451. mOverlays[i]->handleOpenVREvents();
  452. }
  453. // Process SteamVR controller state
  454. for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; unDevice++)
  455. {
  456. vr::VRControllerState_t state;
  457. if (mHMD->GetControllerState(unDevice, &state))
  458. {
  459. // TODO
  460. }
  461. }
  462. // Update input poses
  463. updateTrackedPoses();
  464. submitInputChanges();
  465. return true;
  466. }
  467. bool OpenVRProvider::providesFrameEyePose() const
  468. {
  469. return mHMD != NULL;
  470. }
  471. inline Point3F OpenVRVecToTorqueVec(vr::HmdVector3_t vec)
  472. {
  473. return Point3F(-vec.v[0], vec.v[2], -vec.v[1]);
  474. }
  475. void OpenVRTransformToRotPos(MatrixF mat, QuatF &outRot, Point3F &outPos)
  476. {
  477. // Directly set the rotation and position from the eye transforms
  478. MatrixF torqueMat(1);
  479. OpenVRUtil::convertTransformFromOVR(mat, torqueMat);
  480. Point3F pos = torqueMat.getPosition();
  481. outRot = QuatF(torqueMat);
  482. outPos = pos;// Point3F(-pos.x, pos.z, -pos.y);
  483. }
  484. void OpenVRProvider::getFrameEyePose(IDevicePose *pose, S32 eyeId) const
  485. {
  486. AssertFatal(eyeId >= -1 && eyeId < 2, "Out of bounds eye");
  487. if (eyeId == -1)
  488. {
  489. // NOTE: this is codename for "head"
  490. MatrixF mat = mHMDRenderState.mHMDPose; // same order as in the openvr example
  491. OpenVRTransformToRotPos(mat, pose->orientation, pose->position);
  492. pose->velocity = Point3F(0);
  493. pose->angularVelocity = Point3F(0);
  494. }
  495. else
  496. {
  497. MatrixF mat = mHMDRenderState.mEyePose[eyeId] * mHMDRenderState.mHMDPose; // same order as in the openvr example
  498. OpenVRTransformToRotPos(mat, pose->orientation, pose->position);
  499. pose->velocity = Point3F(0);
  500. pose->angularVelocity = Point3F(0);
  501. }
  502. }
  503. bool OpenVRProvider::providesEyeOffsets() const
  504. {
  505. return mHMD != NULL;
  506. }
  507. /// Returns eye offset not taking into account any position tracking info
  508. void OpenVRProvider::getEyeOffsets(Point3F *dest) const
  509. {
  510. dest[0] = mHMDRenderState.mEyePose[0].getPosition();
  511. dest[1] = mHMDRenderState.mEyePose[1].getPosition();
  512. dest[0] = Point3F(-dest[0].x, dest[0].y, dest[0].z); // convert from vr-space
  513. dest[1] = Point3F(-dest[1].x, dest[1].y, dest[1].z);
  514. }
  515. bool OpenVRProvider::providesFovPorts() const
  516. {
  517. return mHMD != NULL;
  518. }
  519. void OpenVRProvider::getFovPorts(FovPort *out) const
  520. {
  521. dMemcpy(out, mHMDRenderState.mEyeFov, sizeof(mHMDRenderState.mEyeFov));
  522. }
  523. void OpenVRProvider::getStereoViewports(RectI *out) const
  524. {
  525. out[0] = mHMDRenderState.mEyeViewport[0];
  526. out[1] = mHMDRenderState.mEyeViewport[1];
  527. }
  528. void OpenVRProvider::getStereoTargets(GFXTextureTarget **out) const
  529. {
  530. out[0] = mHMDRenderState.mStereoRT;
  531. out[1] = mHMDRenderState.mStereoRT;
  532. }
  533. void OpenVRProvider::setDrawCanvas(GuiCanvas *canvas)
  534. {
  535. vr::EVRInitError peError = vr::VRInitError_None;
  536. if (!vr::VRCompositor())
  537. {
  538. Con::errorf("VR: Compositor initialization failed. See log file for details\n");
  539. return;
  540. }
  541. if (mDrawCanvas != canvas || mHMDRenderState.mHMD == NULL)
  542. {
  543. mHMDRenderState.setupRenderTargets(GFXDevice::RS_Standard);
  544. }
  545. mDrawCanvas = canvas;
  546. }
  547. void OpenVRProvider::setDrawMode(GFXDevice::GFXDeviceRenderStyles style)
  548. {
  549. mHMDRenderState.setupRenderTargets(style);
  550. }
  551. void OpenVRProvider::setCurrentConnection(GameConnection *connection)
  552. {
  553. mGameConnection = connection;
  554. }
  555. GameConnection* OpenVRProvider::getCurrentConnection()
  556. {
  557. return mGameConnection;
  558. }
  559. GFXTexHandle OpenVRProvider::getPreviewTexture()
  560. {
  561. return mHMDRenderState.mStereoRenderTexture; // TODO: render distortion preview
  562. }
  563. void OpenVRProvider::onStartFrame()
  564. {
  565. if (!mHMD)
  566. return;
  567. }
  568. void OpenVRProvider::onEndFrame()
  569. {
  570. if (!mHMD)
  571. return;
  572. }
  573. void OpenVRProvider::onEyeRendered(U32 index)
  574. {
  575. if (!mHMD)
  576. return;
  577. vr::EVRCompositorError err = vr::VRCompositorError_None;
  578. vr::VRTextureBounds_t bounds;
  579. U32 textureIdxToSubmit = index;
  580. GFXTexHandle eyeTex = mHMDRenderState.mOutputEyeTextures.getTextureHandle();
  581. if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate)
  582. {
  583. mHMDRenderState.mStereoRT->resolveTo(eyeTex);
  584. mHMDRenderState.mOutputEyeTextures.advance();
  585. }
  586. else
  587. {
  588. // assuming side-by-side, so the right eye will be next
  589. if (index == 1)
  590. {
  591. mHMDRenderState.mStereoRT->resolveTo(eyeTex);
  592. mHMDRenderState.mOutputEyeTextures.advance();
  593. }
  594. else
  595. {
  596. return;
  597. }
  598. }
  599. if (GFX->getAdapterType() == Direct3D11)
  600. {
  601. vr::Texture_t eyeTexture;
  602. if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate)
  603. {
  604. // whatever eye we are on
  605. eyeTexture = { (void*)static_cast<GFXD3D11TextureObject*>(eyeTex.getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma };
  606. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[index], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  607. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture, &bounds);
  608. }
  609. else
  610. {
  611. // left & right at the same time
  612. eyeTexture = { (void*)static_cast<GFXD3D11TextureObject*>(eyeTex.getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma };
  613. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[0], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  614. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left), &eyeTexture, &bounds);
  615. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[1], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  616. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Right), &eyeTexture, &bounds);
  617. }
  618. }
  619. else if (GFX->getAdapterType() == Direct3D9)
  620. {
  621. //vr::Texture_t eyeTexture = { (void*)static_cast<GFXD3D9TextureObject*>(mHMDRenderState.mStereoRenderTextures[index].getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma };
  622. //err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture);
  623. }
  624. #ifdef TORQUE_OPENGL
  625. else if (GFX->getAdapterType() == OpenGL)
  626. {
  627. vr::Texture_t eyeTexture;
  628. if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate)
  629. {
  630. // whatever eye we are on
  631. eyeTexture = { (void*)static_cast<GFXGLTextureObject*>(eyeTex.getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Gamma };
  632. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[index], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  633. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture, &bounds);
  634. }
  635. else
  636. {
  637. // left & right at the same time
  638. eyeTexture = { (void*)static_cast<GFXGLTextureObject*>(eyeTex.getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Gamma };
  639. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[0], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  640. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left), &eyeTexture, &bounds);
  641. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[1], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  642. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Right), &eyeTexture, &bounds);
  643. }
  644. }
  645. #endif
  646. AssertFatal(err == vr::VRCompositorError_None, "VR compositor error!");
  647. }
  648. void OpenVRProvider::setRoomTracking(bool room)
  649. {
  650. vr::IVRCompositor* compositor = vr::VRCompositor();
  651. mTrackingSpace = room ? vr::TrackingUniverseStanding : vr::TrackingUniverseSeated;
  652. if (compositor) compositor->SetTrackingSpace(mTrackingSpace);
  653. }
  654. bool OpenVRProvider::_handleDeviceEvent(GFXDevice::GFXDeviceEventType evt)
  655. {
  656. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  657. {
  658. return true;
  659. }
  660. switch (evt)
  661. {
  662. case GFXDevice::deStartOfFrame:
  663. // Start of frame
  664. onStartFrame();
  665. break;
  666. case GFXDevice::dePostFrame:
  667. // End of frame
  668. onEndFrame();
  669. break;
  670. case GFXDevice::deDestroy:
  671. // Need to reinit rendering
  672. break;
  673. case GFXDevice::deLeftStereoFrameRendered:
  674. //
  675. onEyeRendered(0);
  676. break;
  677. case GFXDevice::deRightStereoFrameRendered:
  678. //
  679. onEyeRendered(1);
  680. break;
  681. default:
  682. break;
  683. }
  684. return true;
  685. }
  686. S32 OpenVRProvider::getDisplayDeviceId() const
  687. {
  688. #if defined(TORQUE_OS_WIN64) || defined(TORQUE_OS_WIN32)
  689. if (GFX && GFX->getAdapterType() == Direct3D11)
  690. {
  691. Vector<GFXAdapter*> adapterList;
  692. GFXD3D11Device::enumerateAdapters(adapterList);
  693. for (U32 i = 0, sz = adapterList.size(); i < sz; i++)
  694. {
  695. GFXAdapter* adapter = adapterList[i];
  696. if (dMemcmp(&adapter->mLUID, &mLUID, sizeof(mLUID)) == 0)
  697. {
  698. return adapter->mIndex;
  699. }
  700. }
  701. }
  702. #endif
  703. return -1;
  704. }
  705. void OpenVRProvider::processVREvent(const vr::VREvent_t & event)
  706. {
  707. switch (event.eventType)
  708. {
  709. case vr::VREvent_TrackedDeviceActivated:
  710. {
  711. // Setup render model
  712. }
  713. break;
  714. case vr::VREvent_TrackedDeviceDeactivated:
  715. {
  716. // Deactivated
  717. }
  718. break;
  719. case vr::VREvent_TrackedDeviceUpdated:
  720. {
  721. // Updated
  722. }
  723. break;
  724. }
  725. }
  726. void OpenVRProvider::updateTrackedPoses()
  727. {
  728. if (!mHMD)
  729. return;
  730. vr::IVRCompositor* compositor = vr::VRCompositor();
  731. if (!compositor)
  732. return;
  733. if (compositor->GetTrackingSpace() != mTrackingSpace)
  734. {
  735. compositor->SetTrackingSpace(mTrackingSpace);
  736. }
  737. compositor->WaitGetPoses(mTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0);
  738. mValidPoseCount = 0;
  739. for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
  740. {
  741. IDevicePose &inPose = mCurrentDevicePose[nDevice];
  742. if (mTrackedDevicePose[nDevice].bPoseIsValid)
  743. {
  744. mValidPoseCount++;
  745. MatrixF mat = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking);
  746. if (nDevice == vr::k_unTrackedDeviceIndex_Hmd)
  747. {
  748. mHMDRenderState.mHMDPose = mat;
  749. // jaeesu - store the last rotation for temp debugging
  750. MatrixF torqueMat(1);
  751. OpenVRUtil::convertTransformFromOVR(mat, torqueMat);
  752. gLastMoveRot = AngAxisF(torqueMat);
  753. //Con::printf("gLastMoveRot = %f,%f,%f,%f", gLastMoveRot.axis.x, gLastMoveRot.axis.y, gLastMoveRot.axis.z, gLastMoveRot.angle);
  754. mHMDRenderState.mHMDPose.inverse();
  755. }
  756. vr::TrackedDevicePose_t &outPose = mTrackedDevicePose[nDevice];
  757. OpenVRTransformToRotPos(mat, inPose.orientation, inPose.position);
  758. inPose.state = outPose.eTrackingResult;
  759. inPose.valid = outPose.bPoseIsValid;
  760. inPose.connected = outPose.bDeviceIsConnected;
  761. inPose.velocity = OpenVRVecToTorqueVec(outPose.vVelocity);
  762. inPose.angularVelocity = OpenVRVecToTorqueVec(outPose.vAngularVelocity);
  763. }
  764. else
  765. {
  766. inPose.valid = false;
  767. }
  768. }
  769. }
  770. void OpenVRProvider::submitInputChanges()
  771. {
  772. // Diff current frame with previous frame
  773. for (U32 i = 0; i < vr::k_unMaxTrackedDeviceCount; i++)
  774. {
  775. IDevicePose curPose = mCurrentDevicePose[i];
  776. IDevicePose prevPose = mPreviousInputTrackedDevicePose[i];
  777. if (!curPose.valid || !curPose.connected)
  778. continue;
  779. if (curPose.orientation != prevPose.orientation)
  780. {
  781. AngAxisF axisAA(curPose.orientation);
  782. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_ROT, OVR_SENSORROT[i], SI_MOVE, axisAA);
  783. }
  784. if (curPose.position != prevPose.position)
  785. {
  786. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_POS, OVR_SENSORPOSITION[i], SI_MOVE, curPose.position);
  787. }
  788. if (curPose.velocity != prevPose.velocity)
  789. {
  790. // Convert angles to degrees
  791. VectorF angles;
  792. angles.x = curPose.velocity.x;
  793. angles.y = curPose.velocity.y;
  794. angles.z = curPose.velocity.z;
  795. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_POS, OVR_SENSORVELOCITY[i], SI_MOVE, angles);
  796. }
  797. if (curPose.angularVelocity != prevPose.angularVelocity)
  798. {
  799. // Convert angles to degrees
  800. VectorF angles;
  801. angles[0] = mRadToDeg(curPose.velocity.x);
  802. angles[1] = mRadToDeg(curPose.velocity.y);
  803. angles[2] = mRadToDeg(curPose.velocity.z);
  804. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_POS, OVR_SENSORANGVEL[i], SI_MOVE, angles);
  805. }
  806. /*
  807. if (curPose.connected != prevPose.connected)
  808. {
  809. if (Con::isFunction("onOVRConnectionChanged"))
  810. {
  811. Con::executef("onOVRConnectionStatus", curPose.connected);
  812. }
  813. }*/
  814. if (curPose.state != prevPose.state)
  815. {
  816. if (Con::isFunction("onOVRStateChanged"))
  817. {
  818. Con::executef("onOVRStateChanged", curPose.state);
  819. }
  820. }
  821. }
  822. dMemcpy(mPreviousInputTrackedDevicePose, mCurrentDevicePose, sizeof(mPreviousInputTrackedDevicePose));
  823. }
  824. void OpenVRProvider::resetSensors()
  825. {
  826. if (mHMD)
  827. {
  828. mHMD->ResetSeatedZeroPose();
  829. }
  830. }
  831. void OpenVRProvider::registerOverlay(OpenVROverlay* overlay)
  832. {
  833. mOverlays.push_back(overlay);
  834. }
  835. void OpenVRProvider::unregisterOverlay(OpenVROverlay* overlay)
  836. {
  837. S32 index = mOverlays.find_next(overlay);
  838. if (index != -1)
  839. {
  840. mOverlays.erase(index);
  841. }
  842. }
  843. OpenVROverlay *OpenVRProvider::getGamepadFocusOverlay()
  844. {
  845. return NULL;
  846. }
  847. void OpenVRProvider::setOverlayNeighbour(vr::EOverlayDirection dir, OpenVROverlay *overlay)
  848. {
  849. }
  850. bool OpenVRProvider::isDashboardVisible()
  851. {
  852. return false;
  853. }
  854. void OpenVRProvider::showDashboard(const char *overlayToShow)
  855. {
  856. }
  857. vr::TrackedDeviceIndex_t OpenVRProvider::getPrimaryDashboardDevice()
  858. {
  859. return -1;
  860. }
  861. void OpenVRProvider::setKeyboardTransformAbsolute(const MatrixF &xfm)
  862. {
  863. // mTrackingSpace
  864. }
  865. void OpenVRProvider::setKeyboardPositionForOverlay(OpenVROverlay *overlay, const RectI &rect)
  866. {
  867. }
  868. DefineEngineStaticMethod(OpenVR, isDeviceActive, bool, (), ,
  869. "@brief Used to determine if the OpenVR input device is active\n\n"
  870. "The OpenVR device is considered active when the library has been "
  871. "initialized and either a real of simulated HMD is present.\n\n"
  872. "@return True if the OpenVR input device is active.\n"
  873. "@ingroup Game")
  874. {
  875. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  876. {
  877. return false;
  878. }
  879. return OPENVR->getActive();
  880. }
  881. DefineEngineStaticMethod(OpenVR, setEnabled, bool, (bool value), ,
  882. "@brief Used to determine if the OpenVR input device is active\n\n"
  883. "The OpenVR device is considered active when the library has been "
  884. "initialized and either a real of simulated HMD is present.\n\n"
  885. "@return True if the OpenVR input device is active.\n"
  886. "@ingroup Game")
  887. {
  888. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  889. {
  890. return false;
  891. }
  892. return value ? OPENVR->enable() : OPENVR->disable();
  893. }
  894. DefineEngineStaticMethod(OpenVR, setHMDAsGameConnectionDisplayDevice, bool, (GameConnection* conn), ,
  895. "@brief Sets the first HMD to be a GameConnection's display device\n\n"
  896. "@param conn The GameConnection to set.\n"
  897. "@return True if the GameConnection display device was set.\n"
  898. "@ingroup Game")
  899. {
  900. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  901. {
  902. Con::errorf("setOVRHMDAsGameConnectionDisplayDevice(): No Oculus VR Device present.");
  903. return false;
  904. }
  905. if (!conn)
  906. {
  907. Con::errorf("setOVRHMDAsGameConnectionDisplayDevice(): Invalid GameConnection.");
  908. return false;
  909. }
  910. conn->setDisplayDevice(OPENVR);
  911. return true;
  912. }
  913. DefineEngineStaticMethod(OpenVR, getDisplayDeviceId, S32, (), ,
  914. "@brief MacOS display ID.\n\n"
  915. "@param index The HMD index.\n"
  916. "@return The ID of the HMD display device, if any.\n"
  917. "@ingroup Game")
  918. {
  919. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  920. {
  921. return -1;
  922. }
  923. return OPENVR->getDisplayDeviceId();
  924. }
  925. DefineEngineStaticMethod(OpenVR, resetSensors, void, (), ,
  926. "@brief Resets all Oculus VR sensors.\n\n"
  927. "This resets all sensor orientations such that their 'normal' rotation "
  928. "is defined when this function is called. This defines an HMD's forwards "
  929. "and up direction, for example."
  930. "@ingroup Game")
  931. {
  932. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  933. {
  934. return;
  935. }
  936. OPENVR->resetSensors();
  937. }
  938. // Overlay stuff
  939. DefineEngineFunction(OpenVRIsCompiledIn, bool, (), , "")
  940. {
  941. return true;
  942. }