openVRProvider.cpp 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751
  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 "renderInstance/renderPassManager.h"
  10. #include "scene/sceneRenderState.h"
  11. #include "materials/baseMatInstance.h"
  12. #include "materials/materialManager.h"
  13. #include "console/consoleInternal.h"
  14. #include "core/stream/fileStream.h"
  15. #include "gfx/D3D11/gfxD3D11Device.h"
  16. #include "gfx/D3D11/gfxD3D11TextureObject.h"
  17. #include "gfx/D3D11/gfxD3D11EnumTranslate.h"
  18. #include "gfx/gfxStringEnumTranslate.h"
  19. #include "materials/matTextureTarget.h"
  20. #ifdef TORQUE_OPENGL
  21. #include "gfx/gl/gfxGLDevice.h"
  22. #include "gfx/gl/gfxGLTextureObject.h"
  23. #include "gfx/gl/gfxGLEnumTranslate.h"
  24. #endif
  25. struct OpenVRLoadedTexture
  26. {
  27. vr::TextureID_t texId;
  28. NamedTexTarget texTarget;
  29. };
  30. AngAxisF gLastMoveRot; // jamesu - this is just here for temp debugging
  31. namespace OpenVRUtil
  32. {
  33. void convertTransformFromOVR(const MatrixF &inRotTMat, MatrixF& outRotation)
  34. {
  35. Point4F col0; inRotTMat.getColumn(0, &col0);
  36. Point4F col1; inRotTMat.getColumn(1, &col1);
  37. Point4F col2; inRotTMat.getColumn(2, &col2);
  38. Point4F col3; inRotTMat.getColumn(3, &col3);
  39. // Set rotation. We need to convert from sensor coordinates to
  40. // Torque coordinates. The sensor matrix is stored row-major.
  41. // The conversion is:
  42. //
  43. // Sensor Torque
  44. // a b c a b c a -c b
  45. // d e f --> -g -h -i --> -g i -h
  46. // g h i d e f d -f e
  47. outRotation.setColumn(0, Point4F( col0.x, -col2.x, col1.x, 0.0f));
  48. outRotation.setColumn(1, Point4F(-col0.z, col2.z, -col1.z, 0.0f));
  49. outRotation.setColumn(2, Point4F( col0.y, -col2.y, col1.y, 0.0f));
  50. outRotation.setColumn(3, Point4F(-col3.x, col3.z, -col3.y, 1.0f));
  51. }
  52. void convertTransformToOVR(const MatrixF& inRotation, MatrixF& outRotation)
  53. {
  54. Point4F col0; inRotation.getColumn(0, &col0);
  55. Point4F col1; inRotation.getColumn(1, &col1);
  56. Point4F col2; inRotation.getColumn(2, &col2);
  57. Point4F col3; inRotation.getColumn(3, &col3);
  58. // This is basically a reverse of what is in convertTransformFromOVR
  59. outRotation.setColumn(0, Point4F(col0.x, col2.x, -col1.x, 0.0f));
  60. outRotation.setColumn(1, Point4F(col0.z, col2.z, -col1.z, 0.0f));
  61. outRotation.setColumn(2, Point4F(-col0.y, -col2.y, col1.y, 0.0f));
  62. outRotation.setColumn(3, Point4F(-col3.x, -col3.z, col3.y, 1.0f));
  63. }
  64. MatrixF convertSteamVRAffineMatrixToMatrixFPlain(const vr::HmdMatrix34_t &mat)
  65. {
  66. MatrixF outMat(1);
  67. outMat.setColumn(0, Point4F(mat.m[0][0], mat.m[1][0], mat.m[2][0], 0.0));
  68. outMat.setColumn(1, Point4F(mat.m[0][1], mat.m[1][1], mat.m[2][1], 0.0));
  69. outMat.setColumn(2, Point4F(mat.m[0][2], mat.m[1][2], mat.m[2][2], 0.0));
  70. outMat.setColumn(3, Point4F(mat.m[0][3], mat.m[1][3], mat.m[2][3], 1.0f)); // pos
  71. return outMat;
  72. }
  73. void convertMatrixFPlainToSteamVRAffineMatrix(const MatrixF &inMat, vr::HmdMatrix34_t &outMat)
  74. {
  75. Point4F row0; inMat.getRow(0, &row0);
  76. Point4F row1; inMat.getRow(1, &row1);
  77. Point4F row2; inMat.getRow(2, &row2);
  78. outMat.m[0][0] = row0.x;
  79. outMat.m[0][1] = row0.y;
  80. outMat.m[0][2] = row0.z;
  81. outMat.m[0][3] = row0.w;
  82. outMat.m[1][0] = row1.x;
  83. outMat.m[1][1] = row1.y;
  84. outMat.m[1][2] = row1.z;
  85. outMat.m[1][3] = row1.w;
  86. outMat.m[2][0] = row2.x;
  87. outMat.m[2][1] = row2.y;
  88. outMat.m[2][2] = row2.z;
  89. outMat.m[2][3] = row2.w;
  90. }
  91. U32 convertOpenVRButtonToTorqueButton(uint32_t vrButton)
  92. {
  93. switch (vrButton)
  94. {
  95. case vr::VRMouseButton_Left:
  96. return KEY_BUTTON0;
  97. case vr::VRMouseButton_Right:
  98. return KEY_BUTTON1;
  99. case vr::VRMouseButton_Middle:
  100. return KEY_BUTTON2;
  101. default:
  102. return KEY_NULL;
  103. }
  104. }
  105. vr::VRTextureBounds_t TorqueRectToBounds(const RectI &rect, const Point2I &widthHeight)
  106. {
  107. vr::VRTextureBounds_t bounds;
  108. F32 xRatio = 1.0 / (F32)widthHeight.x;
  109. F32 yRatio = 1.0 / (F32)widthHeight.y;
  110. bounds.uMin = rect.point.x * xRatio;
  111. bounds.vMin = rect.point.y * yRatio;
  112. bounds.uMax = (rect.point.x + rect.extent.x) * xRatio;
  113. bounds.vMax = (rect.point.y + rect.extent.y) * yRatio;
  114. return bounds;
  115. }
  116. String GetTrackedDeviceString(vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError = NULL)
  117. {
  118. uint32_t unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, NULL, 0, peError);
  119. if (unRequiredBufferLen == 0)
  120. return "";
  121. char *pchBuffer = new char[unRequiredBufferLen];
  122. unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, pchBuffer, unRequiredBufferLen, peError);
  123. String sResult = pchBuffer;
  124. delete[] pchBuffer;
  125. return sResult;
  126. }
  127. }
  128. //------------------------------------------------------------
  129. bool OpenVRRenderModel::init(const vr::RenderModel_t & vrModel, StringTableEntry materialName)
  130. {
  131. SAFE_DELETE(mMaterialInstance);
  132. mMaterialInstance = MATMGR->createMatInstance(materialName, getGFXVertexFormat< VertexType >());
  133. if (!mMaterialInstance)
  134. return false;
  135. mLocalBox = Box3F::Invalid;
  136. // Prepare primitives
  137. U16 *indPtr = NULL;
  138. GFXPrimitive *primPtr = NULL;
  139. mPrimitiveBuffer.set(GFX, vrModel.unTriangleCount * 3, 1, GFXBufferTypeStatic, "OpenVR Controller buffer");
  140. mPrimitiveBuffer.lock(&indPtr, &primPtr);
  141. if (!indPtr || !primPtr)
  142. return false;
  143. primPtr->minIndex = 0;
  144. primPtr->numPrimitives = vrModel.unTriangleCount;
  145. primPtr->numVertices = vrModel.unVertexCount;
  146. primPtr->startIndex = 0;
  147. primPtr->startVertex = 0;
  148. primPtr->type = GFXTriangleList;
  149. //dMemcpy(indPtr, vrModel.rIndexData, sizeof(U16) * vrModel.unTriangleCount * 3);
  150. for (U32 i = 0; i < vrModel.unTriangleCount; i++)
  151. {
  152. const U32 idx = i * 3;
  153. indPtr[idx + 0] = vrModel.rIndexData[idx + 2];
  154. indPtr[idx + 1] = vrModel.rIndexData[idx + 1];
  155. indPtr[idx + 2] = vrModel.rIndexData[idx + 0];
  156. }
  157. mPrimitiveBuffer.unlock();
  158. // Prepare verts
  159. mVertexBuffer.set(GFX, vrModel.unVertexCount, GFXBufferTypeStatic);
  160. VertexType *vertPtr = mVertexBuffer.lock();
  161. if (!vertPtr)
  162. return false;
  163. // Convert to torque coordinate system
  164. for (U32 i = 0; i < vrModel.unVertexCount; i++)
  165. {
  166. const vr::RenderModel_Vertex_t &vert = vrModel.rVertexData[i];
  167. vertPtr->point = OpenVRUtil::convertPointFromOVR(vert.vPosition);
  168. vertPtr->point.x = -vertPtr->point.x;
  169. vertPtr->point.y = -vertPtr->point.y;
  170. vertPtr->point.z = -vertPtr->point.z;
  171. vertPtr->normal = OpenVRUtil::convertPointFromOVR(vert.vNormal);
  172. vertPtr->normal.x = -vertPtr->normal.x;
  173. vertPtr->normal.y = -vertPtr->normal.y;
  174. vertPtr->normal.z = -vertPtr->normal.z;
  175. vertPtr->texCoord = Point2F(vert.rfTextureCoord[0], vert.rfTextureCoord[1]);
  176. vertPtr++;
  177. }
  178. mVertexBuffer.unlock();
  179. for (U32 i = 0, sz = vrModel.unVertexCount; i < sz; i++)
  180. {
  181. Point3F pos = Point3F(vrModel.rVertexData[i].vPosition.v[0], vrModel.rVertexData[i].vPosition.v[1], vrModel.rVertexData[i].vPosition.v[2]);
  182. mLocalBox.extend(pos);
  183. }
  184. return true;
  185. }
  186. void OpenVRRenderModel::draw(SceneRenderState *state, MeshRenderInst* renderInstance)
  187. {
  188. renderInstance->type = RenderPassManager::RIT_Mesh;
  189. renderInstance->matInst = state->getOverrideMaterial(mMaterialInstance);
  190. if (!renderInstance->matInst)
  191. return;
  192. renderInstance->vertBuff = &mVertexBuffer;
  193. renderInstance->primBuff = &mPrimitiveBuffer;
  194. renderInstance->prim = NULL;
  195. renderInstance->primBuffIndex = 0;
  196. if (renderInstance->matInst->getMaterial()->isTranslucent())
  197. {
  198. renderInstance->type = RenderPassManager::RIT_Translucent;
  199. renderInstance->translucentSort = true;
  200. }
  201. renderInstance->defaultKey = renderInstance->matInst->getStateHint();
  202. renderInstance->defaultKey2 = (uintptr_t)renderInstance->vertBuff;
  203. }
  204. //------------------------------------------------------------
  205. DECLARE_SCOPE(OpenVR);
  206. IMPLEMENT_SCOPE(OpenVR, OpenVRProvider, , "");
  207. ConsoleDoc(
  208. "@class OpenVRProvider\n"
  209. "@brief This class is the interface between TorqueScript and OpenVR.\n\n"
  210. "@ingroup OpenVR\n"
  211. );
  212. // Enum impls
  213. ImplementEnumType(OpenVROverlayInputMethod,
  214. "Types of input supported by VR Overlays. .\n\n"
  215. "@ingroup OpenVR")
  216. { vr::VROverlayInputMethod_None, "None" },
  217. { vr::VROverlayInputMethod_Mouse, "Mouse" },
  218. EndImplementEnumType;
  219. ImplementEnumType(OpenVROverlayTransformType,
  220. "Allows the caller to figure out which overlay transform getter to call. .\n\n"
  221. "@ingroup OpenVR")
  222. { vr::VROverlayTransform_Absolute, "Absolute" },
  223. { vr::VROverlayTransform_TrackedDeviceRelative, "TrackedDeviceRelative" },
  224. { vr::VROverlayTransform_SystemOverlay, "SystemOverlay" },
  225. { vr::VROverlayTransform_TrackedComponent, "TrackedComponent" },
  226. EndImplementEnumType;
  227. ImplementEnumType(OpenVRGamepadTextInputMode,
  228. "Types of input supported by VR Overlays. .\n\n"
  229. "@ingroup OpenVR")
  230. { vr::k_EGamepadTextInputModeNormal, "Normal", },
  231. { vr::k_EGamepadTextInputModePassword, "Password", },
  232. { vr::k_EGamepadTextInputModeSubmit, "Submit" },
  233. EndImplementEnumType;
  234. ImplementEnumType(OpenVRGamepadTextInputLineMode,
  235. "Types of input supported by VR Overlays. .\n\n"
  236. "@ingroup OpenVR")
  237. { vr::k_EGamepadTextInputLineModeSingleLine, "SingleLine" },
  238. { vr::k_EGamepadTextInputLineModeMultipleLines, "MultipleLines" },
  239. EndImplementEnumType;
  240. ImplementEnumType(OpenVRTrackingResult,
  241. ". .\n\n"
  242. "@ingroup OpenVR")
  243. { vr::TrackingResult_Uninitialized, "None" },
  244. { vr::TrackingResult_Calibrating_InProgress, "Calibrating_InProgress" },
  245. { vr::TrackingResult_Calibrating_OutOfRange, "Calibrating_OutOfRange" },
  246. { vr::TrackingResult_Running_OK, "Running_Ok" },
  247. { vr::TrackingResult_Running_OutOfRange, "Running_OutOfRange" },
  248. EndImplementEnumType;
  249. ImplementEnumType(OpenVRTrackingUniverseOrigin,
  250. "Identifies which style of tracking origin the application wants to use for the poses it is requesting. .\n\n"
  251. "@ingroup OpenVR")
  252. { vr::TrackingUniverseSeated, "Seated" },
  253. { vr::TrackingUniverseStanding, "Standing" },
  254. { vr::TrackingUniverseRawAndUncalibrated, "RawAndUncalibrated" },
  255. EndImplementEnumType;
  256. ImplementEnumType(OpenVROverlayDirection,
  257. "Directions for changing focus between overlays with the gamepad. .\n\n"
  258. "@ingroup OpenVR")
  259. { vr::OverlayDirection_Up, "Up" },
  260. { vr::OverlayDirection_Down, "Down" },
  261. { vr::OverlayDirection_Left, "Left" },
  262. { vr::OverlayDirection_Right, "Right" },
  263. EndImplementEnumType;
  264. ImplementEnumType(OpenVRState,
  265. "Status of the overall system or tracked objects. .\n\n"
  266. "@ingroup OpenVR")
  267. { vr::VRState_Undefined, "Undefined" },
  268. { vr::VRState_Off, "Off" },
  269. { vr::VRState_Searching, "Searching" },
  270. { vr::VRState_Searching_Alert, "Searching_Alert" },
  271. { vr::VRState_Ready, "Ready" },
  272. { vr::VRState_Ready_Alert, "Ready_Alert" },
  273. { vr::VRState_NotReady, "NotReady" },
  274. EndImplementEnumType;
  275. ImplementEnumType(OpenVRTrackedDeviceClass,
  276. "Types of devices which are tracked .\n\n"
  277. "@ingroup OpenVR")
  278. { vr::TrackedDeviceClass_Invalid, "Invalid" },
  279. { vr::TrackedDeviceClass_HMD, "HMD" },
  280. { vr::TrackedDeviceClass_Controller, "Controller" },
  281. { vr::TrackedDeviceClass_TrackingReference, "TrackingReference" },
  282. { vr::TrackedDeviceClass_Other, "Other" },
  283. EndImplementEnumType;
  284. //------------------------------------------------------------
  285. U32 OpenVRProvider::OVR_SENSORROT[vr::k_unMaxTrackedDeviceCount] = { 0 };
  286. U32 OpenVRProvider::OVR_SENSORROTANG[vr::k_unMaxTrackedDeviceCount] = { 0 };
  287. U32 OpenVRProvider::OVR_SENSORVELOCITY[vr::k_unMaxTrackedDeviceCount] = { 0 };
  288. U32 OpenVRProvider::OVR_SENSORANGVEL[vr::k_unMaxTrackedDeviceCount] = { 0 };
  289. U32 OpenVRProvider::OVR_SENSORMAGNETOMETER[vr::k_unMaxTrackedDeviceCount] = { 0 };
  290. U32 OpenVRProvider::OVR_SENSORPOSITION[vr::k_unMaxTrackedDeviceCount] = { 0 };
  291. U32 OpenVRProvider::OVR_BUTTONPRESSED[vr::k_unMaxTrackedDeviceCount];
  292. U32 OpenVRProvider::OVR_BUTTONTOUCHED[vr::k_unMaxTrackedDeviceCount];
  293. U32 OpenVRProvider::OVR_AXISNONE[vr::k_unMaxTrackedDeviceCount] = { 0 };
  294. U32 OpenVRProvider::OVR_AXISTRACKPAD[vr::k_unMaxTrackedDeviceCount] = { 0 };
  295. U32 OpenVRProvider::OVR_AXISJOYSTICK[vr::k_unMaxTrackedDeviceCount] = { 0 };
  296. U32 OpenVRProvider::OVR_AXISTRIGGER[vr::k_unMaxTrackedDeviceCount] = { 0 };
  297. EulerF OpenVRProvider::smHMDRotOffset(0);
  298. F32 OpenVRProvider::smHMDmvYaw = 0;
  299. F32 OpenVRProvider::smHMDmvPitch = 0;
  300. bool OpenVRProvider::smRotateYawWithMoveActions = false;
  301. static String GetTrackedDeviceString(vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError = NULL)
  302. {
  303. uint32_t unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, NULL, 0, peError);
  304. if (unRequiredBufferLen == 0)
  305. return "";
  306. char *pchBuffer = new char[unRequiredBufferLen];
  307. unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty(unDevice, prop, pchBuffer, unRequiredBufferLen, peError);
  308. String sResult = pchBuffer;
  309. delete[] pchBuffer;
  310. return sResult;
  311. }
  312. MODULE_BEGIN(OpenVRProvider)
  313. MODULE_INIT_AFTER(InputEventManager)
  314. MODULE_SHUTDOWN_BEFORE(InputEventManager)
  315. MODULE_INIT
  316. {
  317. OpenVRProvider::staticInit();
  318. ManagedSingleton< OpenVRProvider >::createSingleton();
  319. }
  320. MODULE_SHUTDOWN
  321. {
  322. ManagedSingleton< OpenVRProvider >::deleteSingleton();
  323. }
  324. MODULE_END;
  325. bool OpenVRRenderState::setupRenderTargets(GFXDevice::GFXDeviceRenderStyles mode)
  326. {
  327. if (!mHMD)
  328. return false;
  329. if (mRenderMode == mode)
  330. return true;
  331. mRenderMode = mode;
  332. if (mode == GFXDevice::RS_Standard)
  333. {
  334. reset(mHMD);
  335. return true;
  336. }
  337. U32 sizeX, sizeY;
  338. Point2I newRTSize;
  339. mHMD->GetRecommendedRenderTargetSize(&sizeX, &sizeY);
  340. if (mode == GFXDevice::RS_StereoSeparate)
  341. {
  342. mEyeViewport[0] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY));
  343. mEyeViewport[1] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY));
  344. newRTSize.x = sizeX;
  345. newRTSize.y = sizeY;
  346. }
  347. else
  348. {
  349. mEyeViewport[0] = RectI(Point2I(0, 0), Point2I(sizeX, sizeY));
  350. mEyeViewport[1] = RectI(Point2I(sizeX, 0), Point2I(sizeX, sizeY));
  351. newRTSize.x = sizeX * 2;
  352. newRTSize.y = sizeY;
  353. }
  354. GFXTexHandle stereoTexture;
  355. stereoTexture.set(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8_SRGB, &VRTextureProfile, "OpenVR Stereo RT Color");
  356. mStereoRenderTexture = stereoTexture;
  357. GFXTexHandle stereoDepthTexture;
  358. stereoDepthTexture.set(newRTSize.x, newRTSize.y, GFXFormatD24S8, &VRDepthProfile, "OpenVR Depth");
  359. mStereoDepthTexture = stereoDepthTexture;
  360. mStereoRT = GFX->allocRenderToTextureTarget();
  361. mStereoRT->attachTexture(GFXTextureTarget::Color0, stereoTexture);
  362. mStereoRT->attachTexture(GFXTextureTarget::DepthStencil, stereoDepthTexture);
  363. mOutputEyeTextures.init(newRTSize.x, newRTSize.y, GFXFormatR8G8B8A8_SRGB, &VRTextureProfile, "OpenVR Stereo RT Color OUTPUT");
  364. return true;
  365. }
  366. void OpenVRRenderState::renderPreview()
  367. {
  368. }
  369. void OpenVRRenderState::reset(vr::IVRSystem* hmd)
  370. {
  371. mHMD = hmd;
  372. mStereoRT = NULL;
  373. mStereoRenderTexture = NULL;
  374. mStereoDepthTexture = NULL;
  375. mOutputEyeTextures.clear();
  376. if (!mHMD)
  377. return;
  378. updateHMDProjection();
  379. }
  380. void OpenVRRenderState::updateHMDProjection()
  381. {
  382. vr::HmdMatrix34_t mat = mHMD->GetEyeToHeadTransform(vr::Eye_Left);
  383. mEyePose[0] = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mat);
  384. mEyePose[0].inverse();
  385. mat = mHMD->GetEyeToHeadTransform(vr::Eye_Right);
  386. mEyePose[1] = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mat);
  387. mEyePose[1].inverse();
  388. mHMD->GetProjectionRaw(vr::Eye_Left, &mEyeFov[0].leftTan, &mEyeFov[0].rightTan, &mEyeFov[0].upTan, &mEyeFov[0].downTan);
  389. mHMD->GetProjectionRaw(vr::Eye_Right, &mEyeFov[1].leftTan, &mEyeFov[1].rightTan, &mEyeFov[1].upTan, &mEyeFov[1].downTan);
  390. mEyeFov[0].upTan = -mEyeFov[0].upTan;
  391. mEyeFov[0].leftTan = -mEyeFov[0].leftTan;
  392. mEyeFov[1].upTan = -mEyeFov[1].upTan;
  393. mEyeFov[1].leftTan = -mEyeFov[1].leftTan;
  394. }
  395. OpenVRProvider::OpenVRProvider() :
  396. mHMD(NULL),
  397. mRenderModels(NULL),
  398. mDrawCanvas(NULL),
  399. mGameConnection(NULL)
  400. {
  401. dStrcpy(mName, "openvr", 30);
  402. mDeviceType = INPUTMGR->getNextDeviceType();
  403. buildInputCodeTable();
  404. GFXDevice::getDeviceEventSignal().notify(this, &OpenVRProvider::_handleDeviceEvent);
  405. INPUTMGR->registerDevice(this);
  406. dMemset(&mLUID, '\0', sizeof(mLUID));
  407. mTrackingSpace = vr::TrackingUniverseStanding;
  408. }
  409. OpenVRProvider::~OpenVRProvider()
  410. {
  411. }
  412. void OpenVRProvider::staticInit()
  413. {
  414. // Overlay flags
  415. Con::setIntVariable("$OpenVR::OverlayFlags_None", 1 << (U32)vr::VROverlayFlags_None);
  416. Con::setIntVariable("$OpenVR::OverlayFlags_Curved", 1 << (U32)vr::VROverlayFlags_Curved);
  417. Con::setIntVariable("$OpenVR::OverlayFlags_RGSS4X", 1 << (U32)vr::VROverlayFlags_RGSS4X);
  418. Con::setIntVariable("$OpenVR::OverlayFlags_NoDashboardTab", 1 << (U32)vr::VROverlayFlags_NoDashboardTab);
  419. Con::setIntVariable("$OpenVR::OverlayFlags_AcceptsGamepadEvents", 1 << (U32)vr::VROverlayFlags_AcceptsGamepadEvents);
  420. Con::setIntVariable("$OpenVR::OverlayFlags_ShowGamepadFocus", 1 << (U32)vr::VROverlayFlags_ShowGamepadFocus);
  421. Con::setIntVariable("$OpenVR::OverlayFlags_SendVRScrollEvents", 1 << (U32)vr::VROverlayFlags_SendVRScrollEvents);
  422. Con::setIntVariable("$OpenVR::OverlayFlags_SendVRTouchpadEvents", 1 << (U32)vr::VROverlayFlags_SendVRTouchpadEvents);
  423. Con::setIntVariable("$OpenVR::OverlayFlags_ShowTouchPadScrollWheel", 1 << (U32)vr::VROverlayFlags_ShowTouchPadScrollWheel);
  424. Con::addVariable("$OpenVR::HMDRotOffsetX", TypeF32, &smHMDRotOffset.x);
  425. Con::addVariable("$OpenVR::HMDRotOffsetY", TypeF32, &smHMDRotOffset.y);
  426. Con::addVariable("$OpenVR::HMDRotOffsetZ", TypeF32, &smHMDRotOffset.z);
  427. Con::addVariable("$OpenVR::HMDmvYaw", TypeF32, &smHMDmvYaw);
  428. Con::addVariable("$OpenVR::HMDmvPitch", TypeF32, &smHMDmvPitch);
  429. Con::addVariable("$OpenVR::HMDRotateYawWithMoveActions", TypeBool, &smRotateYawWithMoveActions);
  430. }
  431. bool OpenVRProvider::enable()
  432. {
  433. mOpenVRNS = Namespace::find(StringTable->insert("OpenVR"));
  434. disable();
  435. // Load openvr runtime
  436. vr::EVRInitError eError = vr::VRInitError_None;
  437. mHMD = vr::VR_Init(&eError, vr::VRApplication_Scene);
  438. dMemset(mDeviceClassChar, '\0', sizeof(mDeviceClassChar));
  439. if (eError != vr::VRInitError_None)
  440. {
  441. mHMD = NULL;
  442. char buf[1024];
  443. sprintf_s(buf, sizeof(buf), "Unable to init VR runtime: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
  444. Con::printf(buf);
  445. return false;
  446. }
  447. dMemset(&mLUID, '\0', sizeof(mLUID));
  448. #ifdef TORQUE_OS_WIN32
  449. // For windows we need to lookup the DXGI record for this and grab the LUID for the display adapter. We need the LUID since
  450. // T3D uses EnumAdapters1 not EnumAdapters whereas openvr uses EnumAdapters.
  451. int32_t AdapterIdx;
  452. IDXGIAdapter* EnumAdapter;
  453. IDXGIFactory1* DXGIFactory;
  454. mHMD->GetDXGIOutputInfo(&AdapterIdx);
  455. // Get the LUID of the device
  456. HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&DXGIFactory));
  457. if (FAILED(hr))
  458. AssertFatal(false, "OpenVRProvider::enable -> CreateDXGIFactory1 call failure");
  459. hr = DXGIFactory->EnumAdapters(AdapterIdx, &EnumAdapter);
  460. if (FAILED(hr))
  461. {
  462. Con::warnf("VR: HMD device has an invalid adapter.");
  463. }
  464. else
  465. {
  466. DXGI_ADAPTER_DESC desc;
  467. hr = EnumAdapter->GetDesc(&desc);
  468. if (FAILED(hr))
  469. {
  470. Con::warnf("VR: HMD device has an invalid adapter.");
  471. }
  472. else
  473. {
  474. dMemcpy(&mLUID, &desc.AdapterLuid, sizeof(mLUID));
  475. }
  476. SAFE_RELEASE(EnumAdapter);
  477. }
  478. SAFE_RELEASE(DXGIFactory);
  479. #endif
  480. mRenderModels = (vr::IVRRenderModels *)vr::VR_GetGenericInterface(vr::IVRRenderModels_Version, &eError);
  481. if (!mRenderModels)
  482. {
  483. mHMD = NULL;
  484. vr::VR_Shutdown();
  485. char buf[1024];
  486. sprintf_s(buf, sizeof(buf), "Unable to get render model interface: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
  487. Con::printf(buf);
  488. return false;
  489. }
  490. mDriver = GetTrackedDeviceString(mHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
  491. mDisplay = GetTrackedDeviceString(mHMD, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);
  492. mHMDRenderState.mHMDPose = MatrixF(1);
  493. mHMDRenderState.mEyePose[0] = MatrixF(1);
  494. mHMDRenderState.mEyePose[1] = MatrixF(1);
  495. mHMDRenderState.reset(mHMD);
  496. mHMD->ResetSeatedZeroPose();
  497. dMemset(mPreviousInputTrackedDevicePose, '\0', sizeof(mPreviousInputTrackedDevicePose));
  498. mEnabled = true;
  499. dMemset(mCurrentControllerState, '\0', sizeof(mCurrentControllerState));
  500. dMemset(mPreviousCurrentControllerState, '\0', sizeof(mPreviousCurrentControllerState));
  501. return true;
  502. }
  503. bool OpenVRProvider::disable()
  504. {
  505. if (mHMD)
  506. {
  507. mHMD = NULL;
  508. mRenderModels = NULL;
  509. mHMDRenderState.reset(NULL);
  510. vr::VR_Shutdown();
  511. }
  512. mEnabled = false;
  513. return true;
  514. }
  515. void OpenVRProvider::buildInputCodeTable()
  516. {
  517. // Obtain all of the device codes
  518. for (U32 i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i)
  519. {
  520. OVR_SENSORROT[i] = INPUTMGR->getNextDeviceCode();
  521. OVR_SENSORROTANG[i] = INPUTMGR->getNextDeviceCode();
  522. OVR_SENSORVELOCITY[i] = INPUTMGR->getNextDeviceCode();
  523. OVR_SENSORANGVEL[i] = INPUTMGR->getNextDeviceCode();
  524. OVR_SENSORMAGNETOMETER[i] = INPUTMGR->getNextDeviceCode();
  525. OVR_SENSORPOSITION[i] = INPUTMGR->getNextDeviceCode();
  526. OVR_BUTTONPRESSED[i] = INPUTMGR->getNextDeviceCode();
  527. OVR_BUTTONTOUCHED[i] = INPUTMGR->getNextDeviceCode();
  528. OVR_AXISNONE[i] = INPUTMGR->getNextDeviceCode();
  529. OVR_AXISTRACKPAD[i] = INPUTMGR->getNextDeviceCode();
  530. OVR_AXISJOYSTICK[i] = INPUTMGR->getNextDeviceCode();
  531. OVR_AXISTRIGGER[i] = INPUTMGR->getNextDeviceCode();
  532. }
  533. // Build out the virtual map
  534. char buffer[64];
  535. for (U32 i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i)
  536. {
  537. dSprintf(buffer, 64, "opvr_sensorrot%d", i);
  538. INPUTMGR->addVirtualMap(buffer, SI_ROT, OVR_SENSORROT[i]);
  539. dSprintf(buffer, 64, "opvr_sensorrotang%d", i);
  540. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORROTANG[i]);
  541. dSprintf(buffer, 64, "opvr_sensorvelocity%d", i);
  542. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORVELOCITY[i]);
  543. dSprintf(buffer, 64, "opvr_sensorangvel%d", i);
  544. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORANGVEL[i]);
  545. dSprintf(buffer, 64, "opvr_sensormagnetometer%d", i);
  546. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORMAGNETOMETER[i]);
  547. dSprintf(buffer, 64, "opvr_sensorpos%d", i);
  548. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_SENSORPOSITION[i]);
  549. dSprintf(buffer, 64, "opvr_buttonpressed%d", i);
  550. INPUTMGR->addVirtualMap(buffer, SI_INT, OVR_BUTTONPRESSED[i]);
  551. dSprintf(buffer, 64, "opvr_buttontouched%d", i);
  552. INPUTMGR->addVirtualMap(buffer, SI_INT, OVR_BUTTONTOUCHED[i]);
  553. dSprintf(buffer, 64, "opvr_axis_none%d", i);
  554. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_AXISNONE[i]);
  555. dSprintf(buffer, 64, "opvr_axis_trackpad%d", i);
  556. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_AXISTRACKPAD[i]);
  557. dSprintf(buffer, 64, "opvr_axis_joystick%d", i);
  558. INPUTMGR->addVirtualMap(buffer, SI_POS, OVR_AXISJOYSTICK[i]);
  559. dSprintf(buffer, 64, "opvr_axis_trigger%d", i);
  560. INPUTMGR->addVirtualMap(buffer, SI_INT, OVR_AXISTRIGGER[i]);
  561. }
  562. }
  563. bool OpenVRProvider::process()
  564. {
  565. if (!mHMD)
  566. return true;
  567. if (!vr::VRCompositor())
  568. return true;
  569. if (smRotateYawWithMoveActions)
  570. {
  571. smHMDmvYaw += MoveManager::mRightAction - MoveManager::mLeftAction + MoveManager::mXAxis_L;
  572. }
  573. // Update HMD rotation offset
  574. smHMDRotOffset.z += smHMDmvYaw;
  575. smHMDRotOffset.x += smHMDmvPitch;
  576. while (smHMDRotOffset.x < -M_PI_F)
  577. smHMDRotOffset.x += M_2PI_F;
  578. while (smHMDRotOffset.x > M_PI_F)
  579. smHMDRotOffset.x -= M_2PI_F;
  580. while (smHMDRotOffset.z < -M_PI_F)
  581. smHMDRotOffset.z += M_2PI_F;
  582. while (smHMDRotOffset.z > M_PI_F)
  583. smHMDRotOffset.z -= M_2PI_F;
  584. smHMDmvYaw = 0;
  585. smHMDmvPitch = 0;
  586. // Process SteamVR events
  587. vr::VREvent_t event;
  588. while (mHMD->PollNextEvent(&event, sizeof(event)))
  589. {
  590. processVREvent(event);
  591. }
  592. // process overlay events
  593. for (U32 i = 0; i < mOverlays.size(); i++)
  594. {
  595. mOverlays[i]->handleOpenVREvents();
  596. }
  597. // Process SteamVR controller state
  598. for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; unDevice++)
  599. {
  600. vr::VRControllerState_t state;
  601. if (mHMD->GetControllerState(unDevice, &state))
  602. {
  603. mCurrentControllerState[unDevice] = state;
  604. }
  605. }
  606. // Update input poses
  607. updateTrackedPoses();
  608. submitInputChanges();
  609. return true;
  610. }
  611. bool OpenVRProvider::providesFrameEyePose() const
  612. {
  613. return mHMD != NULL;
  614. }
  615. inline Point3F OpenVRVecToTorqueVec(vr::HmdVector3_t vec)
  616. {
  617. return Point3F(-vec.v[0], vec.v[2], -vec.v[1]);
  618. }
  619. void OpenVRTransformToRotPos(MatrixF mat, QuatF &outRot, Point3F &outPos)
  620. {
  621. // Directly set the rotation and position from the eye transforms
  622. MatrixF torqueMat(1);
  623. OpenVRUtil::convertTransformFromOVR(mat, torqueMat);
  624. Point3F pos = torqueMat.getPosition();
  625. outRot = QuatF(torqueMat);
  626. outPos = pos;
  627. outRot.mulP(pos, &outPos); // jamesu - position needs to be multiplied by rotation in this case
  628. }
  629. void OpenVRTransformToRotPosMat(MatrixF mat, QuatF &outRot, Point3F &outPos, MatrixF &outMat)
  630. {
  631. // Directly set the rotation and position from the eye transforms
  632. MatrixF torqueMat(1);
  633. OpenVRUtil::convertTransformFromOVR(mat, torqueMat);
  634. Point3F pos = torqueMat.getPosition();
  635. outRot = QuatF(torqueMat);
  636. outPos = pos;
  637. outRot.mulP(pos, &outPos); // jamesu - position needs to be multiplied by rotation in this case
  638. outMat = torqueMat;
  639. }
  640. void OpenVRProvider::getFrameEyePose(IDevicePose *pose, S32 eyeId) const
  641. {
  642. AssertFatal(eyeId >= -1 && eyeId < 2, "Out of bounds eye");
  643. if (eyeId == -1)
  644. {
  645. // NOTE: this is codename for "head"
  646. MatrixF mat = mHMDRenderState.mHMDPose; // same order as in the openvr example
  647. #ifdef DEBUG_DISPLAY_POSE
  648. pose->originalMatrix = mat;
  649. OpenVRTransformToRotPosMat(mat, pose->orientation, pose->position, pose->actualMatrix);
  650. #else
  651. OpenVRTransformToRotPos(mat, pose->orientation, pose->position);
  652. #endif
  653. pose->velocity = Point3F(0);
  654. pose->angularVelocity = Point3F(0);
  655. }
  656. else
  657. {
  658. MatrixF mat = mHMDRenderState.mEyePose[eyeId] * mHMDRenderState.mHMDPose; // same order as in the openvr example
  659. //mat = mHMDRenderState.mHMDPose * mHMDRenderState.mEyePose[eyeId]; // same order as in the openvr example
  660. #ifdef DEBUG_DISPLAY_POSE
  661. pose->originalMatrix = mat;
  662. OpenVRTransformToRotPosMat(mat, pose->orientation, pose->position, pose->actualMatrix);
  663. #else
  664. OpenVRTransformToRotPos(mat, pose->orientation, pose->position);
  665. #endif
  666. pose->velocity = Point3F(0);
  667. pose->angularVelocity = Point3F(0);
  668. }
  669. }
  670. bool OpenVRProvider::providesEyeOffsets() const
  671. {
  672. return mHMD != NULL;
  673. }
  674. /// Returns eye offset not taking into account any position tracking info
  675. void OpenVRProvider::getEyeOffsets(Point3F *dest) const
  676. {
  677. dest[0] = mHMDRenderState.mEyePose[0].getPosition();
  678. dest[1] = mHMDRenderState.mEyePose[1].getPosition();
  679. dest[0] = Point3F(-dest[0].x, dest[0].y, dest[0].z); // convert from vr-space
  680. dest[1] = Point3F(-dest[1].x, dest[1].y, dest[1].z);
  681. }
  682. bool OpenVRProvider::providesFovPorts() const
  683. {
  684. return mHMD != NULL;
  685. }
  686. void OpenVRProvider::getFovPorts(FovPort *out) const
  687. {
  688. dMemcpy(out, mHMDRenderState.mEyeFov, sizeof(mHMDRenderState.mEyeFov));
  689. }
  690. void OpenVRProvider::getStereoViewports(RectI *out) const
  691. {
  692. out[0] = mHMDRenderState.mEyeViewport[0];
  693. out[1] = mHMDRenderState.mEyeViewport[1];
  694. }
  695. void OpenVRProvider::getStereoTargets(GFXTextureTarget **out) const
  696. {
  697. out[0] = mHMDRenderState.mStereoRT;
  698. out[1] = mHMDRenderState.mStereoRT;
  699. }
  700. void OpenVRProvider::setDrawCanvas(GuiCanvas *canvas)
  701. {
  702. vr::EVRInitError peError = vr::VRInitError_None;
  703. if (!vr::VRCompositor())
  704. {
  705. Con::errorf("VR: Compositor initialization failed. See log file for details\n");
  706. return;
  707. }
  708. if (mDrawCanvas != canvas || mHMDRenderState.mHMD == NULL)
  709. {
  710. mHMDRenderState.setupRenderTargets(GFXDevice::RS_Standard);
  711. }
  712. mDrawCanvas = canvas;
  713. }
  714. void OpenVRProvider::setDrawMode(GFXDevice::GFXDeviceRenderStyles style)
  715. {
  716. mHMDRenderState.setupRenderTargets(style);
  717. }
  718. void OpenVRProvider::setCurrentConnection(GameConnection *connection)
  719. {
  720. mGameConnection = connection;
  721. }
  722. GameConnection* OpenVRProvider::getCurrentConnection()
  723. {
  724. return mGameConnection;
  725. }
  726. GFXTexHandle OpenVRProvider::getPreviewTexture()
  727. {
  728. return mHMDRenderState.mStereoRenderTexture; // TODO: render distortion preview
  729. }
  730. void OpenVRProvider::onStartFrame()
  731. {
  732. if (!mHMD)
  733. return;
  734. }
  735. void OpenVRProvider::onEndFrame()
  736. {
  737. if (!mHMD)
  738. return;
  739. }
  740. void OpenVRProvider::onEyeRendered(U32 index)
  741. {
  742. if (!mHMD)
  743. return;
  744. vr::EVRCompositorError err = vr::VRCompositorError_None;
  745. vr::VRTextureBounds_t bounds;
  746. U32 textureIdxToSubmit = index;
  747. GFXTexHandle eyeTex = mHMDRenderState.mOutputEyeTextures.getTextureHandle();
  748. if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate)
  749. {
  750. mHMDRenderState.mStereoRT->resolveTo(eyeTex);
  751. mHMDRenderState.mOutputEyeTextures.advance();
  752. }
  753. else
  754. {
  755. // assuming side-by-side, so the right eye will be next
  756. if (index == 1)
  757. {
  758. mHMDRenderState.mStereoRT->resolveTo(eyeTex);
  759. mHMDRenderState.mOutputEyeTextures.advance();
  760. }
  761. else
  762. {
  763. return;
  764. }
  765. }
  766. if (GFX->getAdapterType() == Direct3D11)
  767. {
  768. vr::Texture_t eyeTexture;
  769. if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate)
  770. {
  771. // whatever eye we are on
  772. eyeTexture = { (void*)static_cast<GFXD3D11TextureObject*>(eyeTex.getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma };
  773. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[index], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  774. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture, &bounds);
  775. }
  776. else
  777. {
  778. // left & right at the same time
  779. eyeTexture = { (void*)static_cast<GFXD3D11TextureObject*>(eyeTex.getPointer())->get2DTex(), vr::API_DirectX, vr::ColorSpace_Gamma };
  780. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[0], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  781. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left), &eyeTexture, &bounds);
  782. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[1], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  783. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Right), &eyeTexture, &bounds);
  784. }
  785. }
  786. #ifdef TORQUE_OPENGL
  787. else if (GFX->getAdapterType() == OpenGL)
  788. {
  789. vr::Texture_t eyeTexture;
  790. if (mHMDRenderState.mRenderMode == GFXDevice::RS_StereoSeparate)
  791. {
  792. // whatever eye we are on
  793. eyeTexture = { (void*)static_cast<GFXGLTextureObject*>(eyeTex.getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Gamma };
  794. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[index], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  795. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left + index), &eyeTexture, &bounds);
  796. }
  797. else
  798. {
  799. // left & right at the same time
  800. eyeTexture = { (void*)static_cast<GFXGLTextureObject*>(eyeTex.getPointer())->getHandle(), vr::API_OpenGL, vr::ColorSpace_Gamma };
  801. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[0], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  802. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Left), &eyeTexture, &bounds);
  803. bounds = OpenVRUtil::TorqueRectToBounds(mHMDRenderState.mEyeViewport[1], mHMDRenderState.mStereoRenderTexture.getWidthHeight());
  804. err = vr::VRCompositor()->Submit((vr::EVREye)(vr::Eye_Right), &eyeTexture, &bounds);
  805. }
  806. }
  807. #endif
  808. AssertFatal(err == vr::VRCompositorError_None, "VR compositor error!");
  809. }
  810. void OpenVRProvider::setRoomTracking(bool room)
  811. {
  812. vr::IVRCompositor* compositor = vr::VRCompositor();
  813. mTrackingSpace = room ? vr::TrackingUniverseStanding : vr::TrackingUniverseSeated;
  814. if (compositor) compositor->SetTrackingSpace(mTrackingSpace);
  815. }
  816. bool OpenVRProvider::_handleDeviceEvent(GFXDevice::GFXDeviceEventType evt)
  817. {
  818. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  819. {
  820. return true;
  821. }
  822. switch (evt)
  823. {
  824. case GFXDevice::deStartOfFrame:
  825. // Start of frame
  826. onStartFrame();
  827. break;
  828. case GFXDevice::dePostFrame:
  829. // End of frame
  830. onEndFrame();
  831. break;
  832. case GFXDevice::deDestroy:
  833. // Need to reinit rendering
  834. break;
  835. case GFXDevice::deLeftStereoFrameRendered:
  836. //
  837. onEyeRendered(0);
  838. break;
  839. case GFXDevice::deRightStereoFrameRendered:
  840. //
  841. onEyeRendered(1);
  842. break;
  843. default:
  844. break;
  845. }
  846. return true;
  847. }
  848. S32 OpenVRProvider::getDisplayDeviceId() const
  849. {
  850. #if defined(TORQUE_OS_WIN64) || defined(TORQUE_OS_WIN32)
  851. if (GFX && GFX->getAdapterType() == Direct3D11)
  852. {
  853. Vector<GFXAdapter*> adapterList;
  854. GFXD3D11Device::enumerateAdapters(adapterList);
  855. for (U32 i = 0, sz = adapterList.size(); i < sz; i++)
  856. {
  857. GFXAdapter* adapter = adapterList[i];
  858. if (dMemcmp(&adapter->mLUID, &mLUID, sizeof(mLUID)) == 0)
  859. {
  860. return adapter->mIndex;
  861. }
  862. }
  863. }
  864. #endif
  865. return -1;
  866. }
  867. void OpenVRProvider::processVREvent(const vr::VREvent_t & evt)
  868. {
  869. mVREventSignal.trigger(evt);
  870. switch (evt.eventType)
  871. {
  872. case vr::VREvent_InputFocusCaptured:
  873. //Con::executef()
  874. break;
  875. case vr::VREvent_TrackedDeviceActivated:
  876. {
  877. // Setup render model
  878. }
  879. break;
  880. case vr::VREvent_TrackedDeviceDeactivated:
  881. {
  882. // Deactivated
  883. }
  884. break;
  885. case vr::VREvent_TrackedDeviceUpdated:
  886. {
  887. // Updated
  888. }
  889. break;
  890. }
  891. }
  892. void OpenVRProvider::updateTrackedPoses()
  893. {
  894. if (!mHMD)
  895. return;
  896. vr::IVRCompositor* compositor = vr::VRCompositor();
  897. if (!compositor)
  898. return;
  899. if (compositor->GetTrackingSpace() != mTrackingSpace)
  900. {
  901. compositor->SetTrackingSpace(mTrackingSpace);
  902. }
  903. compositor->WaitGetPoses(mTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0);
  904. // Make sure we're using the latest eye offset in case user has changed IPD
  905. mHMDRenderState.updateHMDProjection();
  906. mValidPoseCount = 0;
  907. for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
  908. {
  909. IDevicePose &inPose = mCurrentDevicePose[nDevice];
  910. if (mTrackedDevicePose[nDevice].bPoseIsValid)
  911. {
  912. mValidPoseCount++;
  913. MatrixF mat = OpenVRUtil::convertSteamVRAffineMatrixToMatrixFPlain(mTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking);
  914. if (nDevice == vr::k_unTrackedDeviceIndex_Hmd)
  915. {
  916. mHMDRenderState.mHMDPose = mat;
  917. /*
  918. MatrixF rotOffset(1);
  919. EulerF localRot(-smHMDRotOffset.x, -smHMDRotOffset.z, smHMDRotOffset.y);
  920. // NOTE: offsetting before is probably the best we're going to be able to do here, since if we apply the matrix AFTER
  921. // we will get correct movements relative to the camera HOWEVER this also distorts any future movements from the HMD since
  922. // we will then be on a really weird rotation axis.
  923. QuatF(localRot).setMatrix(&rotOffset);
  924. rotOffset.inverse();
  925. mHMDRenderState.mHMDPose = mat = rotOffset * mHMDRenderState.mHMDPose;
  926. */
  927. // jamesu - store the last rotation for temp debugging
  928. MatrixF torqueMat(1);
  929. OpenVRUtil::convertTransformFromOVR(mat, torqueMat);
  930. gLastMoveRot = AngAxisF(torqueMat);
  931. //Con::printf("gLastMoveRot = %f,%f,%f,%f", gLastMoveRot.axis.x, gLastMoveRot.axis.y, gLastMoveRot.axis.z, gLastMoveRot.angle);
  932. mHMDRenderState.mHMDPose.inverse();
  933. }
  934. vr::TrackedDevicePose_t &outPose = mTrackedDevicePose[nDevice];
  935. OpenVRTransformToRotPos(mat, inPose.orientation, inPose.position);
  936. #ifdef DEBUG_DISPLAY_POSE
  937. OpenVRUtil::convertTransformFromOVR(mat, inPose.actualMatrix);
  938. inPose.originalMatrix = mat;
  939. #endif
  940. inPose.state = outPose.eTrackingResult;
  941. inPose.valid = outPose.bPoseIsValid;
  942. inPose.connected = outPose.bDeviceIsConnected;
  943. inPose.velocity = OpenVRVecToTorqueVec(outPose.vVelocity);
  944. inPose.angularVelocity = OpenVRVecToTorqueVec(outPose.vAngularVelocity);
  945. }
  946. else
  947. {
  948. inPose.valid = false;
  949. }
  950. }
  951. }
  952. void OpenVRProvider::submitInputChanges()
  953. {
  954. // Diff current frame with previous frame
  955. for (U32 i = 0; i < vr::k_unMaxTrackedDeviceCount; i++)
  956. {
  957. IDevicePose curPose = mCurrentDevicePose[i];
  958. IDevicePose prevPose = mPreviousInputTrackedDevicePose[i];
  959. S32 eventIdx = -1;
  960. if (!mDeviceEventMap.tryGetValue(i, eventIdx) || eventIdx < 0)
  961. continue;
  962. if (!curPose.valid || !curPose.connected)
  963. continue;
  964. if (curPose.orientation != prevPose.orientation)
  965. {
  966. AngAxisF axisAA(curPose.orientation);
  967. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_ROT, OVR_SENSORROT[eventIdx], SI_MOVE, axisAA);
  968. }
  969. if (curPose.position != prevPose.position)
  970. {
  971. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_POS, OVR_SENSORPOSITION[eventIdx], SI_MOVE, curPose.position);
  972. }
  973. if (curPose.velocity != prevPose.velocity)
  974. {
  975. // Convert angles to degrees
  976. VectorF angles;
  977. angles.x = curPose.velocity.x;
  978. angles.y = curPose.velocity.y;
  979. angles.z = curPose.velocity.z;
  980. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_POS, OVR_SENSORVELOCITY[eventIdx], SI_MOVE, angles);
  981. }
  982. if (curPose.angularVelocity != prevPose.angularVelocity)
  983. {
  984. // Convert angles to degrees
  985. VectorF angles;
  986. angles[0] = mRadToDeg(curPose.velocity.x);
  987. angles[1] = mRadToDeg(curPose.velocity.y);
  988. angles[2] = mRadToDeg(curPose.velocity.z);
  989. INPUTMGR->buildInputEvent(mDeviceType, 0, SI_POS, OVR_SENSORANGVEL[eventIdx], SI_MOVE, angles);
  990. }
  991. /*
  992. if (curPose.connected != prevPose.connected)
  993. {
  994. if (Con::isFunction("onOVRConnectionChanged"))
  995. {
  996. Con::executef("onOVRConnectionStatus", curPose.connected);
  997. }
  998. }*/
  999. if (curPose.state != prevPose.state)
  1000. {
  1001. if (Con::isFunction("onOVRStateChanged"))
  1002. {
  1003. Con::executef("onOVRStateChanged", curPose.state);
  1004. }
  1005. }
  1006. }
  1007. dMemcpy(mPreviousInputTrackedDevicePose, mCurrentDevicePose, sizeof(mPreviousInputTrackedDevicePose));
  1008. }
  1009. void OpenVRProvider::resetSensors()
  1010. {
  1011. if (mHMD)
  1012. {
  1013. mHMD->ResetSeatedZeroPose();
  1014. }
  1015. }
  1016. void OpenVRProvider::mapDeviceToEvent(U32 deviceIdx, S32 eventIdx)
  1017. {
  1018. mDeviceEventMap[deviceIdx] = eventIdx;
  1019. }
  1020. void OpenVRProvider::resetEventMap()
  1021. {
  1022. mDeviceEventMap.clear();
  1023. }
  1024. IDevicePose OpenVRProvider::getTrackedDevicePose(U32 idx)
  1025. {
  1026. if (idx >= vr::k_unMaxTrackedDeviceCount)
  1027. {
  1028. IDevicePose ret;
  1029. ret.connected = ret.valid = false;
  1030. return ret;
  1031. }
  1032. return mCurrentDevicePose[idx];
  1033. }
  1034. void OpenVRProvider::registerOverlay(OpenVROverlay* overlay)
  1035. {
  1036. mOverlays.push_back(overlay);
  1037. }
  1038. void OpenVRProvider::unregisterOverlay(OpenVROverlay* overlay)
  1039. {
  1040. S32 index = mOverlays.find_next(overlay);
  1041. if (index != -1)
  1042. {
  1043. mOverlays.erase(index);
  1044. }
  1045. }
  1046. const S32 OpenVRProvider::preloadRenderModelTexture(U32 index)
  1047. {
  1048. S32 idx = -1;
  1049. if (mLoadedTextureLookup.tryGetValue(index, idx))
  1050. return idx;
  1051. char buffer[256];
  1052. dSprintf(buffer, sizeof(buffer), "openvrtex_%u", index);
  1053. OpenVRProvider::LoadedRenderTexture loadedTexture;
  1054. loadedTexture.vrTextureId = index;
  1055. loadedTexture.vrTexture = NULL;
  1056. loadedTexture.texture = NULL;
  1057. loadedTexture.textureError = vr::VRRenderModelError_Loading;
  1058. loadedTexture.targetTexture = new NamedTexTarget();
  1059. loadedTexture.targetTexture->registerWithName(buffer);
  1060. mLoadedTextures.push_back(loadedTexture);
  1061. mLoadedTextureLookup[index] = mLoadedTextures.size() - 1;
  1062. return mLoadedTextures.size() - 1;
  1063. }
  1064. const S32 OpenVRProvider::preloadRenderModel(StringTableEntry name)
  1065. {
  1066. S32 idx = -1;
  1067. if (mLoadedModelLookup.tryGetValue(name, idx))
  1068. return idx;
  1069. OpenVRProvider::LoadedRenderModel loadedModel;
  1070. loadedModel.name = name;
  1071. loadedModel.model = NULL;
  1072. loadedModel.vrModel = NULL;
  1073. loadedModel.modelError = vr::VRRenderModelError_Loading;
  1074. loadedModel.loadedTexture = false;
  1075. loadedModel.textureId = -1;
  1076. mLoadedModels.push_back(loadedModel);
  1077. mLoadedModelLookup[name] = mLoadedModels.size() - 1;
  1078. return mLoadedModels.size() - 1;
  1079. }
  1080. bool OpenVRProvider::getRenderModel(S32 idx, OpenVRRenderModel **ret, bool &failed)
  1081. {
  1082. if (idx < 0 || idx > mLoadedModels.size())
  1083. {
  1084. failed = true;
  1085. return true;
  1086. }
  1087. OpenVRProvider::LoadedRenderModel &loadedModel = mLoadedModels[idx];
  1088. //Con::printf("RenderModel[%i] STAGE 1", idx);
  1089. failed = false;
  1090. if (loadedModel.modelError > vr::VRRenderModelError_Loading)
  1091. {
  1092. failed = true;
  1093. return true;
  1094. }
  1095. // Stage 1 : model
  1096. if (!loadedModel.model)
  1097. {
  1098. loadedModel.modelError = vr::VRRenderModels()->LoadRenderModel_Async(loadedModel.name, &loadedModel.vrModel);
  1099. //Con::printf(" vr::VRRenderModels()->LoadRenderModel_Async(\"%s\", %x); -> %i", loadedModel.name, &loadedModel.vrModel, loadedModel.modelError);
  1100. if (loadedModel.modelError == vr::VRRenderModelError_None)
  1101. {
  1102. if (loadedModel.vrModel == NULL)
  1103. {
  1104. failed = true;
  1105. return true;
  1106. }
  1107. // Load the model
  1108. loadedModel.model = new OpenVRRenderModel();
  1109. }
  1110. else if (loadedModel.modelError == vr::VRRenderModelError_Loading)
  1111. {
  1112. return false;
  1113. }
  1114. }
  1115. //Con::printf("RenderModel[%i] STAGE 2 (texId == %i)", idx, loadedModel.vrModel->diffuseTextureId);
  1116. // Stage 2 : texture
  1117. if (!loadedModel.loadedTexture && loadedModel.model)
  1118. {
  1119. if (loadedModel.textureId == -1)
  1120. {
  1121. loadedModel.textureId = preloadRenderModelTexture(loadedModel.vrModel->diffuseTextureId);
  1122. }
  1123. if (loadedModel.textureId == -1)
  1124. {
  1125. failed = true;
  1126. return true;
  1127. }
  1128. if (!getRenderModelTexture(loadedModel.textureId, NULL, failed))
  1129. {
  1130. return false;
  1131. }
  1132. if (failed)
  1133. {
  1134. return true;
  1135. }
  1136. loadedModel.loadedTexture = true;
  1137. //Con::printf("RenderModel[%i] GOT TEXTURE");
  1138. // Now we can load the model. Note we first need to get a Material for the mapped texture
  1139. NamedTexTarget *namedTexture = mLoadedTextures[loadedModel.textureId].targetTexture;
  1140. String materialName = MATMGR->getMapEntry(namedTexture->getName().c_str());
  1141. if (materialName.isEmpty())
  1142. {
  1143. char buffer[256];
  1144. dSprintf(buffer, sizeof(buffer), "#%s", namedTexture->getName().c_str());
  1145. materialName = buffer;
  1146. //Con::printf("RenderModel[%i] materialName == %s", idx, buffer);
  1147. Material* mat = new Material();
  1148. mat->mMapTo = namedTexture->getName();
  1149. mat->mDiffuseMapFilename[0] = buffer;
  1150. mat->mEmissive[0] = true;
  1151. dSprintf(buffer, sizeof(buffer), "%s_Material", namedTexture->getName().c_str());
  1152. if (!mat->registerObject(buffer))
  1153. {
  1154. Con::errorf("Couldn't create placeholder openvr material %s!", buffer);
  1155. failed = true;
  1156. return true;
  1157. }
  1158. materialName = buffer;
  1159. }
  1160. loadedModel.model->init(*loadedModel.vrModel, materialName);
  1161. }
  1162. if ((loadedModel.modelError > vr::VRRenderModelError_Loading) ||
  1163. (loadedModel.textureId >= 0 && mLoadedTextures[loadedModel.textureId].textureError > vr::VRRenderModelError_Loading))
  1164. {
  1165. failed = true;
  1166. }
  1167. if (!failed && ret)
  1168. {
  1169. *ret = loadedModel.model;
  1170. }
  1171. return true;
  1172. }
  1173. bool OpenVRProvider::getRenderModelTexture(S32 idx, GFXTextureObject **outTex, bool &failed)
  1174. {
  1175. if (idx < 0 || idx > mLoadedModels.size())
  1176. {
  1177. failed = true;
  1178. return true;
  1179. }
  1180. failed = false;
  1181. OpenVRProvider::LoadedRenderTexture &loadedTexture = mLoadedTextures[idx];
  1182. if (loadedTexture.textureError > vr::VRRenderModelError_Loading)
  1183. {
  1184. failed = true;
  1185. return true;
  1186. }
  1187. if (!loadedTexture.texture)
  1188. {
  1189. if (!loadedTexture.vrTexture)
  1190. {
  1191. loadedTexture.textureError = vr::VRRenderModels()->LoadTexture_Async(loadedTexture.vrTextureId, &loadedTexture.vrTexture);
  1192. if (loadedTexture.textureError == vr::VRRenderModelError_None)
  1193. {
  1194. // Load the texture
  1195. GFXTexHandle tex;
  1196. const U32 sz = loadedTexture.vrTexture->unWidth * loadedTexture.vrTexture->unHeight * 4;
  1197. GBitmap *bmp = new GBitmap(loadedTexture.vrTexture->unWidth, loadedTexture.vrTexture->unHeight, false, GFXFormatR8G8B8A8);
  1198. Swizzles::bgra.ToBuffer(bmp->getAddress(0,0,0), loadedTexture.vrTexture->rubTextureMapData, sz);
  1199. char buffer[256];
  1200. dSprintf(buffer, 256, "OVRTEX-%i.png", loadedTexture.vrTextureId);
  1201. FileStream fs;
  1202. fs.open(buffer, Torque::FS::File::Write);
  1203. bmp->writeBitmap("PNG", fs);
  1204. fs.close();
  1205. tex.set(bmp, &GFXStaticTextureSRGBProfile, true, "OpenVR Texture");
  1206. //tex.set(loadedTexture.vrTexture->unWidth, loadedTexture.vrTexture->unHeight, 1, (void*)pixels, GFXFormatR8G8B8A8, &GFXDefaultStaticDiffuseProfile, "OpenVR Texture", 1);
  1207. loadedTexture.targetTexture->setTexture(tex);
  1208. loadedTexture.texture = tex;
  1209. }
  1210. else if (loadedTexture.textureError == vr::VRRenderModelError_Loading)
  1211. {
  1212. return false;
  1213. }
  1214. }
  1215. }
  1216. if (loadedTexture.textureError > vr::VRRenderModelError_Loading)
  1217. {
  1218. failed = true;
  1219. }
  1220. if (!failed && outTex)
  1221. {
  1222. *outTex = loadedTexture.texture;
  1223. }
  1224. return true;
  1225. }
  1226. bool OpenVRProvider::getRenderModelTextureName(S32 idx, String &outName)
  1227. {
  1228. if (idx < 0 || idx >= mLoadedTextures.size())
  1229. return false;
  1230. if (mLoadedTextures[idx].targetTexture)
  1231. {
  1232. outName = mLoadedTextures[idx].targetTexture->getName();
  1233. return true;
  1234. }
  1235. return false;
  1236. }
  1237. void OpenVRProvider::resetRenderModels()
  1238. {
  1239. for (U32 i = 0, sz = mLoadedModels.size(); i < sz; i++)
  1240. {
  1241. SAFE_DELETE(mLoadedModels[i].model);
  1242. if (mLoadedModels[i].vrModel) mRenderModels->FreeRenderModel(mLoadedModels[i].vrModel);
  1243. }
  1244. for (U32 i = 0, sz = mLoadedTextures.size(); i < sz; i++)
  1245. {
  1246. SAFE_DELETE(mLoadedTextures[i].targetTexture);
  1247. if (mLoadedTextures[i].vrTexture) mRenderModels->FreeTexture(mLoadedTextures[i].vrTexture);
  1248. }
  1249. mLoadedModels.clear();
  1250. mLoadedTextures.clear();
  1251. mLoadedModelLookup.clear();
  1252. mLoadedTextureLookup.clear();
  1253. }
  1254. OpenVROverlay *OpenVRProvider::getGamepadFocusOverlay()
  1255. {
  1256. return NULL;
  1257. }
  1258. void OpenVRProvider::setOverlayNeighbour(vr::EOverlayDirection dir, OpenVROverlay *overlay)
  1259. {
  1260. }
  1261. bool OpenVRProvider::isDashboardVisible()
  1262. {
  1263. return false;
  1264. }
  1265. void OpenVRProvider::showDashboard(const char *overlayToShow)
  1266. {
  1267. }
  1268. vr::TrackedDeviceIndex_t OpenVRProvider::getPrimaryDashboardDevice()
  1269. {
  1270. return -1;
  1271. }
  1272. void OpenVRProvider::setKeyboardTransformAbsolute(const MatrixF &xfm)
  1273. {
  1274. // mTrackingSpace
  1275. }
  1276. void OpenVRProvider::setKeyboardPositionForOverlay(OpenVROverlay *overlay, const RectI &rect)
  1277. {
  1278. }
  1279. void OpenVRProvider::getControllerDeviceIndexes(vr::TrackedDeviceClass &deviceClass, Vector<S32> &outList)
  1280. {
  1281. for (U32 i = 0; i<vr::k_unMaxTrackedDeviceCount; i++)
  1282. {
  1283. if (!mCurrentDevicePose[i].connected)
  1284. continue;
  1285. vr::TrackedDeviceClass klass = mHMD->GetTrackedDeviceClass(i);
  1286. if (klass == deviceClass)
  1287. {
  1288. outList.push_back(i);
  1289. }
  1290. }
  1291. }
  1292. StringTableEntry OpenVRProvider::getControllerModel(U32 idx)
  1293. {
  1294. if (idx >= vr::k_unMaxTrackedDeviceCount || !mRenderModels)
  1295. return NULL;
  1296. String str = GetTrackedDeviceString(mHMD, idx, vr::Prop_RenderModelName_String, NULL);
  1297. return StringTable->insert(str, true);
  1298. }
  1299. DefineEngineStaticMethod(OpenVR, getControllerDeviceIndexes, const char*, (OpenVRTrackedDeviceClass klass),,
  1300. "@brief Gets the indexes of devices which match the required device class")
  1301. {
  1302. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1303. {
  1304. return "";
  1305. }
  1306. Vector<S32> outList;
  1307. OPENVR->getControllerDeviceIndexes(klass, outList);
  1308. return EngineMarshallData<Vector<S32>>(outList);
  1309. }
  1310. DefineEngineStaticMethod(OpenVR, getControllerModel, const char*, (S32 idx), ,
  1311. "@brief Gets the indexes of devices which match the required device class")
  1312. {
  1313. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1314. {
  1315. return "";
  1316. }
  1317. return OPENVR->getControllerModel(idx);
  1318. }
  1319. DefineEngineStaticMethod(OpenVR, isDeviceActive, bool, (), ,
  1320. "@brief Used to determine if the OpenVR input device is active\n\n"
  1321. "The OpenVR device is considered active when the library has been "
  1322. "initialized and either a real of simulated HMD is present.\n\n"
  1323. "@return True if the OpenVR input device is active.\n"
  1324. "@ingroup Game")
  1325. {
  1326. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1327. {
  1328. return false;
  1329. }
  1330. return OPENVR->getActive();
  1331. }
  1332. DefineEngineStaticMethod(OpenVR, setEnabled, bool, (bool value), ,
  1333. "@brief Used to determine if the OpenVR input device is active\n\n"
  1334. "The OpenVR device is considered active when the library has been "
  1335. "initialized and either a real of simulated HMD is present.\n\n"
  1336. "@return True if the OpenVR input device is active.\n"
  1337. "@ingroup Game")
  1338. {
  1339. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1340. {
  1341. return false;
  1342. }
  1343. return value ? OPENVR->enable() : OPENVR->disable();
  1344. }
  1345. DefineEngineStaticMethod(OpenVR, setHMDAsGameConnectionDisplayDevice, bool, (GameConnection* conn), ,
  1346. "@brief Sets the first HMD to be a GameConnection's display device\n\n"
  1347. "@param conn The GameConnection to set.\n"
  1348. "@return True if the GameConnection display device was set.\n"
  1349. "@ingroup Game")
  1350. {
  1351. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1352. {
  1353. Con::errorf("setOVRHMDAsGameConnectionDisplayDevice(): No Oculus VR Device present.");
  1354. return false;
  1355. }
  1356. if (!conn)
  1357. {
  1358. Con::errorf("setOVRHMDAsGameConnectionDisplayDevice(): Invalid GameConnection.");
  1359. return false;
  1360. }
  1361. conn->setDisplayDevice(OPENVR);
  1362. return true;
  1363. }
  1364. DefineEngineStaticMethod(OpenVR, getDisplayDeviceId, S32, (), ,
  1365. "@brief MacOS display ID.\n\n"
  1366. "@param index The HMD index.\n"
  1367. "@return The ID of the HMD display device, if any.\n"
  1368. "@ingroup Game")
  1369. {
  1370. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1371. {
  1372. return -1;
  1373. }
  1374. return OPENVR->getDisplayDeviceId();
  1375. }
  1376. DefineEngineStaticMethod(OpenVR, resetSensors, void, (), ,
  1377. "@brief Resets all Oculus VR sensors.\n\n"
  1378. "This resets all sensor orientations such that their 'normal' rotation "
  1379. "is defined when this function is called. This defines an HMD's forwards "
  1380. "and up direction, for example."
  1381. "@ingroup Game")
  1382. {
  1383. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1384. {
  1385. return;
  1386. }
  1387. OPENVR->resetSensors();
  1388. }
  1389. DefineEngineStaticMethod(OpenVR, mapDeviceToEvent, void, (S32 deviceId, S32 eventId), ,
  1390. "@brief Maps a device to an event code.\n\n"
  1391. "@ingroup Game")
  1392. {
  1393. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1394. {
  1395. return;
  1396. }
  1397. OPENVR->mapDeviceToEvent(deviceId, eventId);
  1398. }
  1399. DefineEngineStaticMethod(OpenVR, resetEventMap, void, (), ,
  1400. "@brief Resets event map.\n\n"
  1401. "@ingroup Game")
  1402. {
  1403. if (!ManagedSingleton<OpenVRProvider>::instanceOrNull())
  1404. {
  1405. return;
  1406. }
  1407. OPENVR->resetEventMap();
  1408. }
  1409. // Overlay stuff
  1410. DefineEngineFunction(OpenVRIsCompiledIn, bool, (), , "")
  1411. {
  1412. return true;
  1413. }