openVRProvider.cpp 52 KB

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