Files
bgfx/src/hmd.cpp
Matthew Endsley d9dd4bceb5 Add platform agnostic bgfx::VR for renderers to interface
The new platform agnositic class bgfx::VR manages the
functionality that is shared across the various VR platforms.

The individual platform renderers no longer need
to interface with the internal VR tpyes (OVRRenderI) directly

This greatly simplifies the OVR object's surface area which
is now provided by the VRImplI interface. bgfx::VR now manages
core lifecycle issues of the headset.

The notable renderer API changes are the separation of sensor
sampling and rendering. We need these separate so we can control
the timing (later commit) of camera sampling with finer granularity
than at the start of the video frame.
2016-09-16 20:03:12 -07:00

206 lines
3.7 KiB
C++

/*
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "hmd.h"
namespace bgfx
{
VR::VR()
: m_framesUntilReconnect(0)
, m_enabled(false)
{
}
void VR::init(VRImplI* _impl)
{
if (!_impl)
{
return;
}
if (!_impl->init())
{
return;
}
m_impl = _impl;
m_impl->connect(&m_desc);
if (!m_impl->isConnected())
{
connectFailed();
return;
}
m_hmdSize.m_w = m_desc.m_eyeSize[0].m_w + m_desc.m_eyeSize[1].m_w;
m_hmdSize.m_h = bx::uint32_max(m_desc.m_eyeSize[0].m_h, m_desc.m_eyeSize[1].m_h);
}
void VR::shutdown()
{
if (!m_impl)
{
return;
}
m_impl->destroySwapChain();
if (m_impl->isConnected())
{
m_impl->disconnect();
}
m_impl->shutdown();
m_impl = NULL;
m_enabled = false;
}
void VR::renderEyeStart(uint8_t _eye, Rect* _viewport)
{
BX_CHECK(m_enabled, "VR::renderEyeStart called while not enabled - render usage error");
_viewport->m_x = 0;
_viewport->m_y = 0;
_viewport->m_width = m_desc.m_eyeSize[_eye].m_w;
_viewport->m_height = m_desc.m_eyeSize[_eye].m_h;
m_impl->renderEyeStart(m_desc, _eye);
}
void VR::recenter()
{
if (m_impl)
{
m_impl->recenter();
}
}
void VR::preReset()
{
if (m_impl)
{
m_impl->destroyMirror();
}
m_enabled = false;
}
void VR::postReset(int _msaaSamples, int _mirrorWidth, int _mirrorHeight)
{
if (m_impl && m_impl->createSwapChain(m_desc, _msaaSamples, _mirrorWidth, _mirrorHeight))
{
m_enabled = true;
}
}
void VR::flip()
{
if (!m_impl || !m_enabled)
{
return;
}
else if (!m_impl->isConnected() && !tryReconnect())
{
return;
}
if (!m_impl->submitSwapChain(m_desc))
{
m_impl->destroySwapChain();
m_impl->disconnect();
return;
}
}
void VR::swap(HMD& _hmd)
{
_hmd.flags = BGFX_HMD_NONE;
if (!m_impl)
{
return;
}
_hmd.flags = BGFX_HMD_DEVICE_RESOLUTION;
_hmd.deviceWidth = m_desc.m_deviceSize.m_w;
_hmd.deviceHeight = m_desc.m_deviceSize.m_h;
_hmd.width = m_hmdSize.m_w;
_hmd.height = m_hmdSize.m_h;
if (!m_impl->updateTracking(_hmd))
{
m_impl->destroySwapChain();
m_impl->disconnect();
}
if (!m_impl->isConnected())
{
return;
}
for (int eye = 0; eye < 2; ++eye)
{
_hmd.eye[eye].fov[0] = m_desc.m_eyeFov[eye].m_up;
_hmd.eye[eye].fov[1] = m_desc.m_eyeFov[eye].m_down;
_hmd.eye[eye].fov[2] = m_desc.m_eyeFov[eye].m_left;
_hmd.eye[eye].fov[3] = m_desc.m_eyeFov[eye].m_right;
}
m_impl->updateInput(_hmd);
if (m_enabled)
{
_hmd.flags |= BGFX_HMD_RENDERING;
}
}
bool VR::tryReconnect()
{
if (!m_impl)
{
return false;
}
BX_CHECK(!m_impl->isConnected(), "VR::tryReconnect called when already connected. Usage error");
--m_framesUntilReconnect;
if (m_framesUntilReconnect > 0)
{
return false;
}
m_framesUntilReconnect = 90;
m_impl->connect(&m_desc);
if (!m_impl->isConnected())
{
connectFailed();
return false;
}
m_hmdSize.m_w = m_desc.m_eyeSize[0].m_w + m_desc.m_eyeSize[1].m_w;
m_hmdSize.m_h = bx::uint32_max(m_desc.m_eyeSize[0].m_h, m_desc.m_eyeSize[1].m_h);
return true;
}
void VR::connectFailed()
{
// sane defaults
m_desc.m_deviceSize.m_w = 2160;
m_desc.m_deviceSize.m_h = 1200;
m_desc.m_deviceType = 0;
m_desc.m_refreshRate = 90.0f;
m_desc.m_neckOffset[0] = 0.0805f;
m_desc.m_neckOffset[1] = 0.075f;
for (int eye = 0; eye < 2; ++eye)
{
m_desc.m_eyeFov[eye].m_up = 1.32928634f;
m_desc.m_eyeFov[eye].m_down = 1.32928634f;
}
m_desc.m_eyeFov[0].m_left = 1.05865765f;
m_desc.m_eyeFov[0].m_right = 1.09236801f;
m_desc.m_eyeFov[1].m_left = 1.09236801f;
m_desc.m_eyeFov[1].m_right = 1.05865765f;
}
} // namesapce bgfx