Advertisement
PromitRoy

OpenVR framework code

Jan 23rd, 2017
597
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.57 KB | None | 0 0
  1. #include "VRSupport.h"
  2. #include "GraphicsContext.h"
  3. #include <KataCore/PlatformHelp.h>
  4. #include <KataPlatform/KataPlatform.h>
  5. #include "OpenGL/Texture_GL.h"
  6. #include "Direct3D11/Texture_D3D11.h"
  7.  
  8. bool VRSupport::Initialize(GraphicsContext* context)
  9. {
  10.     K_ASSERT(context);
  11.     _context = context;
  12.  
  13.     //Initialize all of the VR/HMD relevant bits
  14.     auto err = vr::VRInitError_None;
  15.     _hmd = vr::VR_Init(&err, vr::VRApplication_Scene);
  16.     if(err != vr::VRInitError_None)
  17.     {
  18.         _hmd = nullptr; //should already be, but let's make sure
  19.         return false;
  20.     }
  21.  
  22.     //_renderModels = (vr::IVRRenderModels*) vr::VR_GetGenericInterface(vr::IVRRenderModels_Version, &err);
  23.     //K_ASSERT(err == vr::VRInitError_None);
  24.  
  25.     _hmd->GetRecommendedRenderTargetSize(&RenderSize.x, &RenderSize.y);
  26.     context->Viewport = V2i(RenderSize.x, RenderSize.y);
  27.     LeftEyeColor = context->CreateTexture("VR_LeftEyeColor", RenderSize.x, RenderSize.y, DataFormat::Rgba8, TextureFlags::BindRenderTarget | TextureFlags::BindShaderResource, nullptr);
  28.     LeftEyeDepth = context->CreateTexture("VR_LeftEyeDepth", RenderSize.x, RenderSize.y, DataFormat::Depth32F, TextureFlags::BindDepthStencil, nullptr);
  29.     LeftEyeFB = context->CreateFrameBuffer("VR_LeftEyeFB", LeftEyeColor, LeftEyeDepth);
  30.     RightEyeColor = context->CreateTexture("VR_RightEyeColor", RenderSize.x, RenderSize.y, DataFormat::Rgba8, TextureFlags::BindRenderTarget | TextureFlags::BindShaderResource, nullptr);
  31.     RightEyeDepth = context->CreateTexture("VR_RightEyeDepth", RenderSize.x, RenderSize.y, DataFormat::Depth32F, TextureFlags::BindDepthStencil, nullptr);
  32.     RightEyeFB = context->CreateFrameBuffer("VR_RightEyeFB", RightEyeColor, RightEyeDepth);
  33.  
  34.     auto vrcomp = vr::VRCompositor();
  35.     K_ASSERT(vrcomp);
  36.  
  37.     vr::HmdMatrix34_t matEyeLeft = _hmd->GetEyeToHeadTransform(vr::Eye_Left);
  38.     Matrix4x4 matLeft = ConvertSteamVRMatrix(matEyeLeft);
  39.     MatrixInverse(_eyeMatLeft, matLeft);
  40.  
  41.     vr::HmdMatrix34_t matEyeRight = _hmd->GetEyeToHeadTransform(vr::Eye_Right);
  42.     Matrix4x4 matRight = ConvertSteamVRMatrix(matEyeRight);
  43.     MatrixInverse(_eyeMatRight, matRight);
  44.  
  45.     for(uint32_t unTrackedDevice = vr::k_unTrackedDeviceIndex_Hmd + 1; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++)
  46.     {
  47.         if(!_hmd->IsTrackedDeviceConnected(unTrackedDevice))
  48.             continue;
  49.  
  50.         SetupRenderModelForTrackedDevice(unTrackedDevice);
  51.     }
  52.  
  53.     return true;
  54. }
  55.  
  56. void VRSupport::UpdateEvents()
  57. {
  58.     vr::VREvent_t event;
  59.     while(_hmd->PollNextEvent(&event, sizeof(event)))
  60.     {
  61.         switch(event.eventType)
  62.         {
  63.         case vr::VREvent_TrackedDeviceActivated:
  64.         {
  65.             SetupRenderModelForTrackedDevice(event.trackedDeviceIndex);
  66.             printf("Device %u attached. Setting up render model.\n", event.trackedDeviceIndex);
  67.         }
  68.         break;
  69.         case vr::VREvent_TrackedDeviceDeactivated:
  70.         {
  71.             printf("Device %u detached.\n", event.trackedDeviceIndex);
  72.         }
  73.         break;
  74.         case vr::VREvent_TrackedDeviceUpdated:
  75.         {
  76.             printf("Device %u updated.\n", event.trackedDeviceIndex);
  77.         }
  78.         break;
  79.         }
  80.     }
  81.  
  82.     // Process SteamVR controller state
  83.     for(int i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i)
  84.     {
  85.         _hmd->GetControllerState(i, &_controllerStates[i]);
  86.     }
  87. }
  88.  
  89. void VRSupport::UpdateHMD()
  90. {
  91.     vr::VRCompositor()->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0);
  92.  
  93.     _validPoseCount = 0;
  94.     _poseClasses = "";
  95.     for(int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
  96.     {
  97.         if(_trackedDevicePose[nDevice].bPoseIsValid)
  98.         {
  99.             _validPoseCount++;
  100.             _deviceMat[nDevice] = ConvertSteamVRMatrix(_trackedDevicePose[nDevice].mDeviceToAbsoluteTracking);
  101.             Matrix4x4 scaling;
  102.             MatrixScaling(scaling, 1, 1, -1);
  103.             _deviceMat[nDevice] = _deviceMat[nDevice] * scaling;
  104.             if(_deviceClassChar[nDevice] == 0)
  105.             {
  106.                 switch(_hmd->GetTrackedDeviceClass(nDevice))
  107.                 {
  108.                 case vr::TrackedDeviceClass_Controller:        _deviceClassChar[nDevice] = 'C'; break;
  109.                 case vr::TrackedDeviceClass_HMD:               _deviceClassChar[nDevice] = 'H'; break;
  110.                 case vr::TrackedDeviceClass_Invalid:           _deviceClassChar[nDevice] = 'I'; break;
  111.                 case vr::TrackedDeviceClass_Other:             _deviceClassChar[nDevice] = 'O'; break;
  112.                 case vr::TrackedDeviceClass_TrackingReference: _deviceClassChar[nDevice] = 'T'; break;
  113.                 default:                                       _deviceClassChar[nDevice] = '?'; break;
  114.                 }
  115.             }
  116.             _poseClasses += _deviceClassChar[nDevice];
  117.         }
  118.     }
  119.  
  120.     if(_trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid)
  121.     {
  122.         _hmdMat = _deviceMat[vr::k_unTrackedDeviceIndex_Hmd];
  123.         MatrixInverse(_hmdViewMat, _hmdMat);
  124.     }
  125. }
  126.  
  127. void VRSupport::Submit()
  128. {
  129.     auto api = PlatformGetInt(PV_Windows_RenderingApi);
  130.     if(api == WINRA_OpenGL)
  131.     {
  132.         TextureGL* left = (TextureGL*) _context->GetRawTexture(LeftEyeColor);
  133.         vr::Texture_t leftEyeTex = { (void*)left->_texture, vr::API_OpenGL, vr::ColorSpace_Gamma };
  134.         vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTex);
  135.         TextureGL* right = (TextureGL*) _context->GetRawTexture(RightEyeColor);
  136.         vr::Texture_t rightEyeTex = { (void*)right->_texture, vr::API_OpenGL, vr::ColorSpace_Gamma };
  137.         vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTex);
  138.     }
  139.     else if(api == WINRA_Direct3D11)
  140.     {
  141.         Texture_D3D11* left = (Texture_D3D11*)_context->GetRawTexture(LeftEyeColor);
  142.         vr::Texture_t leftEyeTex = { (void*)left->_texture, vr::API_DirectX, vr::ColorSpace_Gamma };
  143.         vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTex);
  144.         Texture_D3D11* right = (Texture_D3D11*)_context->GetRawTexture(RightEyeColor);
  145.         vr::Texture_t rightEyeTex = { (void*)right->_texture, vr::API_DirectX, vr::ColorSpace_Gamma };
  146.         vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTex);
  147.     }
  148. }
  149.  
  150. void VRSupport::SetSceneProperties(V3 cameraPosition, float sceneScale)
  151. {
  152.     _cameraPosition = cameraPosition;
  153.     _sceneScale = sceneScale;
  154. }
  155.  
  156. std::string VRSupport::GetTrackedDeviceString(vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError)
  157. {
  158.     uint32_t unRequiredBufferLen = _hmd->GetStringTrackedDeviceProperty(unDevice, prop, NULL, 0, peError);
  159.     if(unRequiredBufferLen == 0)
  160.         return "";
  161.  
  162.     char *pchBuffer = new char[unRequiredBufferLen];
  163.     unRequiredBufferLen = _hmd->GetStringTrackedDeviceProperty(unDevice, prop, pchBuffer, unRequiredBufferLen, peError);
  164.     std::string sResult = pchBuffer;
  165.     delete[] pchBuffer;
  166.     return sResult;
  167. }
  168.  
  169. VRRenderModel* VRSupport::FindOrLoadRenderModel(const char *pchRenderModelName)
  170. {
  171.     VRRenderModel* pRenderModel = NULL;
  172.     for(auto i = _renderModels.begin(); i != _renderModels.end(); i++)
  173.     {
  174.         if(!stricmp((*i)->GetName().c_str(), pchRenderModelName))
  175.         {
  176.             pRenderModel = *i;
  177.             break;
  178.         }
  179.     }
  180.  
  181.     // load the model if we didn't find one
  182.     if(!pRenderModel)
  183.     {
  184.         vr::RenderModel_t *pModel;
  185.         vr::EVRRenderModelError error;
  186.         while(1)
  187.         {
  188.             error = vr::VRRenderModels()->LoadRenderModel_Async(pchRenderModelName, &pModel);
  189.             if(error != vr::VRRenderModelError_Loading)
  190.                 break;
  191.  
  192.             PlatformHelp::Sleep(1);
  193.         }
  194.  
  195.         if(error != vr::VRRenderModelError_None)
  196.         {
  197.             kprintf(LP_Warning, "Unable to load render model %s - %s\n", pchRenderModelName, vr::VRRenderModels()->GetRenderModelErrorNameFromEnum(error));
  198.             return NULL; // move on to the next tracked device
  199.         }
  200.  
  201.         vr::RenderModel_TextureMap_t *pTexture;
  202.         while(1)
  203.         {
  204.             error = vr::VRRenderModels()->LoadTexture_Async(pModel->diffuseTextureId, &pTexture);
  205.             if(error != vr::VRRenderModelError_Loading)
  206.                 break;
  207.  
  208.             PlatformHelp::Sleep(1);
  209.         }
  210.  
  211.         if(error != vr::VRRenderModelError_None)
  212.         {
  213.             kprintf(LP_Warning, "Unable to load render texture id:%d for render model %s\n", pModel->diffuseTextureId, pchRenderModelName);
  214.             vr::VRRenderModels()->FreeRenderModel(pModel);
  215.             return NULL; // move on to the next tracked device
  216.         }
  217.  
  218.         /*pRenderModel = new VRRenderModel_GL(pchRenderModelName);
  219.         if(!pRenderModel->Init(*pModel, *pTexture))
  220.         {
  221.             kprintf(LP_Warning, "Unable to create GL model from render model %s\n", pchRenderModelName);
  222.             delete pRenderModel;
  223.             pRenderModel = NULL;
  224.         }
  225.         else
  226.         {
  227.             _renderModels.push_back(pRenderModel);
  228.         }
  229.         vr::VRRenderModels()->FreeRenderModel(pModel);
  230.         vr::VRRenderModels()->FreeTexture(pTexture);*/
  231.     }
  232.     return pRenderModel;
  233. }
  234.  
  235. void VRSupport::SetupRenderModelForTrackedDevice(vr::TrackedDeviceIndex_t unTrackedDeviceIndex)
  236. {
  237.     if(unTrackedDeviceIndex >= vr::k_unMaxTrackedDeviceCount)
  238.         return;
  239.  
  240.     // try to find a model we've already set up
  241.     std::string sRenderModelName = GetTrackedDeviceString(unTrackedDeviceIndex, vr::Prop_RenderModelName_String);
  242.     VRRenderModel* pRenderModel = FindOrLoadRenderModel(sRenderModelName.c_str());
  243.     if(!pRenderModel)
  244.     {
  245.         std::string sTrackingSystemName = GetTrackedDeviceString(unTrackedDeviceIndex, vr::Prop_TrackingSystemName_String);
  246.         kprintf(LP_Warning, "Unable to load render model for tracked device %d (%s.%s)", unTrackedDeviceIndex, sTrackingSystemName.c_str(), sRenderModelName.c_str());
  247.     }
  248.     else
  249.     {
  250.         _trackedDeviceToRenderModel[unTrackedDeviceIndex] = pRenderModel;
  251.         _showTrackedDevice[unTrackedDeviceIndex] = true;
  252.     }
  253. }
  254.  
  255. void VRSupport::DrawRenderModels()
  256. {
  257.     bool bIsInputCapturedByAnotherProcess = _hmd->IsInputFocusCapturedByAnotherProcess();
  258.     //Draw VR render models
  259.     for(uint32_t unTrackedDevice = 0; unTrackedDevice < vr::k_unMaxTrackedDeviceCount; unTrackedDevice++)
  260.     {
  261.         if(!_trackedDeviceToRenderModel[unTrackedDevice] || !_showTrackedDevice[unTrackedDevice])
  262.             continue;
  263.  
  264.         const vr::TrackedDevicePose_t & pose = _trackedDevicePose[unTrackedDevice];
  265.         if(!pose.bPoseIsValid)
  266.             continue;
  267.  
  268.         if(bIsInputCapturedByAnotherProcess && _hmd->GetTrackedDeviceClass(unTrackedDevice) == vr::TrackedDeviceClass_Controller)
  269.             continue;
  270.  
  271.         Matrix4x4 vrScaleMat, vrTransMat;
  272.         MatrixScaling(vrScaleMat, 1.0f / _sceneScale, 1.0f / _sceneScale, 1.0f / _sceneScale);
  273.         MatrixTranslation(vrTransMat, _cameraPosition.x, _cameraPosition.y, _cameraPosition.z);
  274.         Matrix4x4 matDeviceToTracking = _deviceMat[unTrackedDevice] * vrScaleMat * vrTransMat;
  275.         _context->Pipeline.SetWorld(matDeviceToTracking);
  276.         _context->Pipeline.ModulateColor = V4(1.3f);
  277.         _context->Commit();
  278.         gl::VertexAttrib4f(VE_Diffuse, 1.3f, 1.3f, 1.3f, 1.3f);
  279.         _trackedDeviceToRenderModel[unTrackedDevice]->Draw();
  280.         //_context->DrawModelGeometry(_context->Models.Sphere);
  281.     }
  282. }
  283.  
  284. Matrix4x4 VRSupport::GetProjMatrixForEye(vr::Hmd_Eye eye) const
  285. {
  286.     vr::HmdMatrix44_t mat = _hmd->GetProjectionMatrix(eye, 0.1f, 250.0f, vr::API_DirectX);
  287.  
  288.     Matrix4x4 proj = {
  289.         mat.m[0][0], mat.m[1][0], mat.m[2][0], mat.m[3][0],
  290.         mat.m[0][1], mat.m[1][1], mat.m[2][1], mat.m[3][1],
  291.         mat.m[0][2], mat.m[1][2], mat.m[2][2], mat.m[3][2],
  292.         mat.m[0][3], mat.m[1][3], mat.m[2][3], mat.m[3][3]
  293.     };
  294.     Matrix4x4 scaling;
  295.     MatrixScaling(scaling, 1, 1, 1);
  296.     return scaling * proj;
  297. }
  298.  
  299. Matrix4x4 VRSupport::GetViewMatrixForEye(vr::Hmd_Eye eye) const
  300. {
  301.     Matrix4x4 vrScaleMat, vrTransMat;
  302.     MatrixScaling(vrScaleMat, _sceneScale, _sceneScale, _sceneScale);
  303.     MatrixTranslation(vrTransMat, -_cameraPosition.x, -_cameraPosition.y, -_cameraPosition.z);
  304.     if(eye == vr::Eye_Left)
  305.     {
  306.         return vrTransMat * vrScaleMat * _hmdViewMat * _eyeMatLeft;
  307.     }
  308.     else if(eye == vr::Eye_Right)
  309.     {
  310.         return vrTransMat * vrScaleMat * _hmdViewMat * _eyeMatRight;
  311.     }
  312.  
  313.     return Matrix4x4::Identity;
  314. }
  315.  
  316. Vector3D VRSupport::GetHmdPosition() const
  317. {
  318.     return _hmdMat.GetPosition() + _cameraPosition;
  319. }
  320.  
  321. Vector3D VRSupport::GetDevicePosition(int device) const
  322. {
  323.     return GetDevicePose(device).GetPosition();
  324. }
  325.  
  326. Matrix4x4 VRSupport::GetDevicePose(int device) const
  327. {
  328.     Matrix4x4 vrScaleMat, vrTransMat;
  329.     MatrixScaling(vrScaleMat, 1.0f / _sceneScale, 1.0f / _sceneScale, 1.0f / _sceneScale);
  330.     MatrixTranslation(vrTransMat, _cameraPosition.x, _cameraPosition.y, _cameraPosition.z);
  331.     Matrix4x4 matDeviceToTracking = _deviceMat[device] * vrScaleMat * vrTransMat;
  332.     return matDeviceToTracking;
  333. }
  334.  
  335. bool VRSupport::IsController(int device) const
  336. {
  337.     auto deviceClass = _hmd->GetTrackedDeviceClass(device);
  338.     return deviceClass == vr::TrackedDeviceClass_Controller;
  339. }
  340.  
  341. bool VRSupport::IsHmd(int device) const
  342. {
  343.     auto deviceClass = _hmd->GetTrackedDeviceClass(device);
  344.     return deviceClass == vr::TrackedDeviceClass_HMD;
  345. }
  346.  
  347. bool VRSupport::GetButtonState(int controller, vr::EVRButtonId button) const
  348. {
  349.     return (_controllerStates[controller].ulButtonPressed & ButtonMaskFromId(button)) != 0;
  350. }
  351.  
  352. V2 VRSupport::GetAxisState(int device, int axis) const
  353. {
  354.     const auto& ctrlAxis = _controllerStates[device].rAxis[axis];
  355.     return V2(ctrlAxis.x, ctrlAxis.y);
  356. }
  357.  
  358. void VRSupport::HapticPulse(int device, int axis, unsigned short strength)
  359. {
  360.     strength = clamp(strength, 0, 3999);
  361.     _hmd->TriggerHapticPulse(device, axis, strength);
  362. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement