summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/src/hmd_ovr.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/src/hmd_ovr.cpp')
-rw-r--r--3rdparty/bgfx/src/hmd_ovr.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/3rdparty/bgfx/src/hmd_ovr.cpp b/3rdparty/bgfx/src/hmd_ovr.cpp
new file mode 100644
index 00000000000..e8d465e4259
--- /dev/null
+++ b/3rdparty/bgfx/src/hmd_ovr.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+
+#include "hmd_ovr.h"
+
+#if BGFX_CONFIG_USE_OVR
+
+namespace bgfx
+{
+ OVR::OVR()
+ : m_hmd(NULL)
+ , m_isenabled(false)
+ , m_mirror(NULL)
+ , m_hmdFrameReady(-1)
+ , m_frameIndex(0)
+ , m_sensorSampleTime(0)
+ {
+ memset(m_eyeBuffers, 0, sizeof(m_eyeBuffers));
+ }
+
+ OVR::~OVR()
+ {
+ BX_CHECK(NULL == m_hmd, "OVR not shutdown properly.");
+ }
+
+ void OVR::init()
+ {
+ ovrResult initialized = ovr_Initialize(NULL);
+ ovrGraphicsLuid luid;
+
+ BX_WARN(initialized == ovrSuccess, "Unable to create OVR device.");
+
+ if (initialized != ovrSuccess)
+ {
+ return;
+ }
+
+ initialized = ovr_Create(&m_hmd, &luid);
+ if (initialized != ovrSuccess)
+ {
+ BX_WARN(initialized == ovrSuccess, "Unable to create OVR device.");
+ return;
+ }
+
+ m_hmdDesc = ovr_GetHmdDesc(m_hmd);
+
+ BX_TRACE("HMD: %s, %s, firmware: %d.%d"
+ , m_hmdDesc.ProductName
+ , m_hmdDesc.Manufacturer
+ , m_hmdDesc.FirmwareMajor
+ , m_hmdDesc.FirmwareMinor
+ );
+
+ ovrSizei sizeL = ovr_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmdDesc.DefaultEyeFov[0], 1.0f);
+ ovrSizei sizeR = ovr_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmdDesc.DefaultEyeFov[1], 1.0f);
+ m_hmdSize.w = sizeL.w + sizeR.w;
+ m_hmdSize.h = bx::uint32_max(sizeL.h, sizeR.h);
+ }
+
+ void OVR::shutdown()
+ {
+ BX_CHECK(!m_isenabled, "HMD not disabled.");
+
+ for (int i = 0; i < 2; i++)
+ {
+ if (m_eyeBuffers[i])
+ {
+ m_eyeBuffers[i]->destroy(m_hmd);
+ BX_DELETE(g_allocator, m_eyeBuffers[i]);
+ }
+ }
+
+ if (m_mirror)
+ {
+ m_mirror->destroy(m_hmd);
+ BX_DELETE(g_allocator, m_mirror);
+ }
+
+ ovr_Destroy(m_hmd);
+ m_hmd = NULL;
+ ovr_Shutdown();
+ }
+
+ void OVR::getViewport(uint8_t _eye, Rect* _viewport)
+ {
+ _viewport->m_x = 0;
+ _viewport->m_y = 0;
+ _viewport->m_width = m_eyeBuffers[_eye]->m_eyeTextureSize.w;
+ _viewport->m_height = m_eyeBuffers[_eye]->m_eyeTextureSize.h;
+ }
+
+ void OVR::renderEyeStart(uint8_t _eye)
+ {
+ m_eyeBuffers[_eye]->onRender(m_hmd);
+ }
+
+ bool OVR::postReset()
+ {
+ if (NULL == m_hmd)
+ {
+ return false;
+ }
+
+ for (int eyeIdx = 0; eyeIdx < ovrEye_Count; eyeIdx++)
+ {
+ m_erd[eyeIdx] = ovr_GetRenderDesc(m_hmd, (ovrEyeType)eyeIdx, m_hmdDesc.DefaultEyeFov[eyeIdx]);
+ }
+
+ m_isenabled = true;
+
+ return true;
+ }
+
+ void OVR::preReset()
+ {
+ if (m_isenabled)
+ {
+ // on window resize this will recreate the mirror texture in ovrPostReset
+ m_mirror->destroy(m_hmd);
+ BX_DELETE(g_allocator, m_mirror);
+ m_mirror = NULL;
+ m_isenabled = false;
+ }
+ }
+
+ void OVR::commitEye(uint8_t _eye)
+ {
+ if (m_isenabled)
+ {
+ m_hmdFrameReady = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[_eye]->m_swapTextureChain);
+ }
+ }
+
+ bool OVR::swap(HMD& _hmd, bool originBottomLeft)
+ {
+ _hmd.flags = BGFX_HMD_NONE;
+
+ if (NULL != m_hmd)
+ {
+ _hmd.flags |= BGFX_HMD_DEVICE_RESOLUTION;
+ _hmd.deviceWidth = m_hmdDesc.Resolution.w;
+ _hmd.deviceHeight = m_hmdDesc.Resolution.h;
+ }
+
+ if (!m_isenabled || !OVR_SUCCESS(m_hmdFrameReady))
+ {
+ return false;
+ }
+
+ _hmd.flags |= BGFX_HMD_RENDERING;
+
+ // finish frame for current eye
+ ovrViewScaleDesc viewScaleDesc;
+ viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
+ viewScaleDesc.HmdToEyeOffset[0] = m_hmdToEyeOffset[0];
+ viewScaleDesc.HmdToEyeOffset[1] = m_hmdToEyeOffset[1];
+
+ // create the main eye layer
+ ovrLayerEyeFov eyeLayer;
+ eyeLayer.Header.Type = ovrLayerType_EyeFov;
+ eyeLayer.Header.Flags = originBottomLeft ? ovrLayerFlag_TextureOriginAtBottomLeft : 0;
+
+ for (int eye = 0; eye < ovrEye_Count; eye++)
+ {
+ eyeLayer.ColorTexture[eye] = m_eyeBuffers[eye]->m_swapTextureChain;
+ eyeLayer.Viewport[eye].Pos.x = 0;
+ eyeLayer.Viewport[eye].Pos.y = 0;
+ eyeLayer.Viewport[eye].Size.w = m_eyeBuffers[eye]->m_eyeTextureSize.w;
+ eyeLayer.Viewport[eye].Size.h = m_eyeBuffers[eye]->m_eyeTextureSize.h;
+ eyeLayer.Fov[eye] = m_hmdDesc.DefaultEyeFov[eye];
+ eyeLayer.RenderPose[eye] = m_pose[eye];
+ eyeLayer.SensorSampleTime = m_sensorSampleTime;
+ }
+
+ // append all the layers to global list
+ ovrLayerHeader* layerList = &eyeLayer.Header;
+
+ ovr_SubmitFrame(m_hmd, m_frameIndex, NULL, &layerList, 1);
+
+ // perform mirror texture blit right after the entire frame is submitted to HMD
+ m_mirror->blit(m_hmd);
+
+ m_hmdToEyeOffset[0] = m_erd[0].HmdToEyeOffset;
+ m_hmdToEyeOffset[1] = m_erd[1].HmdToEyeOffset;
+
+ ovr_GetEyePoses(m_hmd, m_frameIndex, ovrTrue, m_hmdToEyeOffset, m_pose, &m_sensorSampleTime);
+
+ getEyePose(_hmd);
+
+ return true;
+ }
+
+ void OVR::recenter()
+ {
+ if (NULL != m_hmd)
+ {
+ ovr_RecenterTrackingOrigin(m_hmd);
+ }
+ }
+
+ void OVR::getEyePose(HMD& _hmd)
+ {
+ if (NULL != m_hmd)
+ {
+ for (int ii = 0; ii < 2; ++ii)
+ {
+ const ovrPosef& pose = m_pose[ii];
+ HMD::Eye& eye = _hmd.eye[ii];
+ eye.rotation[0] = pose.Orientation.x;
+ eye.rotation[1] = pose.Orientation.y;
+ eye.rotation[2] = pose.Orientation.z;
+ eye.rotation[3] = pose.Orientation.w;
+ eye.translation[0] = pose.Position.x;
+ eye.translation[1] = pose.Position.y;
+ eye.translation[2] = pose.Position.z;
+
+ const ovrEyeRenderDesc& erd = m_erd[ii];
+ eye.fov[0] = erd.Fov.UpTan;
+ eye.fov[1] = erd.Fov.DownTan;
+ eye.fov[2] = erd.Fov.LeftTan;
+ eye.fov[3] = erd.Fov.RightTan;
+
+ ovrMatrix4f eyeProj = ovrMatrix4f_Projection(m_erd[ii].Fov, 0.01f, 1000.0f, ovrProjection_LeftHanded);
+ for (int jj = 0; jj < 4; ++jj)
+ {
+ for (int kk = 0; kk < 4; ++kk)
+ {
+ eye.projection[4 * jj + kk] = eyeProj.M[kk][jj];
+ }
+ }
+
+ eye.viewOffset[0] = erd.HmdToEyeOffset.x;
+ eye.viewOffset[1] = erd.HmdToEyeOffset.y;
+ eye.viewOffset[2] = erd.HmdToEyeOffset.z;
+
+ eye.pixelsPerTanAngle[0] = erd.PixelsPerTanAngleAtCenter.x;
+ eye.pixelsPerTanAngle[1] = erd.PixelsPerTanAngleAtCenter.y;
+ }
+ }
+
+ _hmd.width = uint16_t(m_hmdSize.w);
+ _hmd.height = uint16_t(m_hmdSize.h);
+ }
+
+} // namespace bgfx
+
+#endif // BGFX_CONFIG_USE_OVR