openVRProvider.cpp 36 KB

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