Files
bgfx/src/hmd_ovr.cpp
Branimir Karadžić 3b83f53ab1 Happy New Year!
2017-01-01 00:18:41 -08:00

211 lines
5.2 KiB
C++

/*
* Copyright 2011-2017 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "bgfx_p.h"
#if BGFX_CONFIG_USE_OVR
#include "hmd_ovr.h"
namespace bgfx
{
#define _OVR_CHECK(_call) \
BX_MACRO_BLOCK_BEGIN \
ovrResult __result__ = _call; \
BX_CHECK(OVR_SUCCESS(__result__), #_call " FAILED %d", __result__); \
BX_MACRO_BLOCK_END
#if BGFX_CONFIG_DEBUG
# define OVR_CHECK(_call) _OVR_CHECK(_call)
#else
# define OVR_CHECK(_call) _call
#endif // BGFX_CONFIG_DEBUG
VRImplOVR::VRImplOVR()
: m_session(NULL)
{
}
VRImplOVR::~VRImplOVR()
{
if (NULL != g_platformData.session)
{
return;
}
BX_CHECK(NULL == m_session, "OVR not shutdown properly.");
}
bool VRImplOVR::init()
{
if (NULL != g_platformData.session)
{
return true;
}
ovrResult initialized = ovr_Initialize(NULL);
if (!OVR_SUCCESS(initialized))
{
BX_TRACE("Unable to initialize OVR runtime.");
return false;
}
return true;
}
void VRImplOVR::shutdown()
{
if (NULL != g_platformData.session)
{
return;
}
ovr_Shutdown();
}
void VRImplOVR::connect(VRDesc* _desc)
{
if (NULL == g_platformData.session)
{
ovrGraphicsLuid luid;
ovrResult result = ovr_Create(&m_session, &luid);
if (!OVR_SUCCESS(result))
{
BX_TRACE("Failed to create OVR device.");
return;
}
}
else
{
m_session = (ovrSession)g_platformData.session;
}
ovrHmdDesc hmdDesc = ovr_GetHmdDesc(m_session);
_desc->m_deviceType = hmdDesc.Type;
_desc->m_refreshRate = hmdDesc.DisplayRefreshRate;
_desc->m_deviceSize.m_w = hmdDesc.Resolution.w;
_desc->m_deviceSize.m_h = hmdDesc.Resolution.h;
BX_TRACE("OVR HMD: %s, %s, firmware: %d.%d"
, hmdDesc.ProductName
, hmdDesc.Manufacturer
, hmdDesc.FirmwareMajor
, hmdDesc.FirmwareMinor
);
ovrSizei eyeSize[2] =
{
ovr_GetFovTextureSize(m_session, ovrEye_Left, hmdDesc.DefaultEyeFov[0], 1.0f),
ovr_GetFovTextureSize(m_session, ovrEye_Right, hmdDesc.DefaultEyeFov[0], 1.0f),
};
for (int eye = 0; eye < 2; ++eye)
{
BX_STATIC_ASSERT(sizeof(_desc->m_eyeFov[eye]) == sizeof(hmdDesc.DefaultEyeFov[eye]));
memcpy(&_desc->m_eyeFov[eye], &hmdDesc.DefaultEyeFov[eye], sizeof(_desc->m_eyeFov[eye]));
_desc->m_eyeSize[eye].m_w = eyeSize[eye].w;
_desc->m_eyeSize[eye].m_h = eyeSize[eye].h;
}
float neckOffset[2] = {OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL};
ovr_GetFloatArray(m_session, OVR_KEY_NECK_TO_EYE_DISTANCE, neckOffset, 2);
_desc->m_neckOffset[0] = neckOffset[0];
_desc->m_neckOffset[1] = neckOffset[1];
// build constant layer settings
m_renderLayer.Header.Type = ovrLayerType_EyeFov;
m_renderLayer.Header.Flags = 0;
m_renderLayer.Fov[0] = hmdDesc.DefaultEyeFov[0];
m_renderLayer.Fov[1] = hmdDesc.DefaultEyeFov[1];
m_renderLayer.Viewport[0].Pos.x = 0;
m_renderLayer.Viewport[0].Pos.y = 0;
m_renderLayer.Viewport[0].Size.w = _desc->m_eyeSize[0].m_w;
m_renderLayer.Viewport[0].Size.h = _desc->m_eyeSize[0].m_h;
m_renderLayer.Viewport[1].Pos.x = _desc->m_eyeSize[0].m_w+1;
m_renderLayer.Viewport[1].Pos.y = 0;
m_renderLayer.Viewport[1].Size.w = _desc->m_eyeSize[1].m_w;
m_renderLayer.Viewport[1].Size.h = _desc->m_eyeSize[1].m_h;
m_viewScale.HmdSpaceToWorldScaleInMeters = 1.0f;
for (int eye = 0; eye < 2; ++eye)
{
ovrEyeRenderDesc erd = ovr_GetRenderDesc(m_session, static_cast<ovrEyeType>(eye), hmdDesc.DefaultEyeFov[eye]);
m_viewScale.HmdToEyeOffset[eye] = erd.HmdToEyeOffset;
m_eyeFov[eye] = erd.Fov;
m_pixelsPerTanAngleAtCenter[eye] = erd.PixelsPerTanAngleAtCenter;
}
}
void VRImplOVR::disconnect()
{
if (NULL != g_platformData.session)
{
return;
}
if (NULL != m_session)
{
ovr_Destroy(m_session);
m_session = NULL;
}
}
bool VRImplOVR::updateTracking(HMD& _hmd)
{
if (NULL == m_session)
{
return false;
}
ovr_GetEyePoses(m_session, 0, ovrTrue, m_viewScale.HmdToEyeOffset, m_renderLayer.RenderPose, &m_renderLayer.SensorSampleTime);
for (int eye = 0; eye < 2; ++eye)
{
const ovrPosef& pose = m_renderLayer.RenderPose[eye];
HMD::Eye& hmdEye = _hmd.eye[eye];
hmdEye.rotation[0] = pose.Orientation.x;
hmdEye.rotation[1] = pose.Orientation.y;
hmdEye.rotation[2] = pose.Orientation.z;
hmdEye.rotation[3] = pose.Orientation.w;
hmdEye.translation[0] = pose.Position.x;
hmdEye.translation[1] = pose.Position.y;
hmdEye.translation[2] = pose.Position.z;
hmdEye.viewOffset[0] = -m_viewScale.HmdToEyeOffset[eye].x;
hmdEye.viewOffset[1] = -m_viewScale.HmdToEyeOffset[eye].y;
hmdEye.viewOffset[2] = -m_viewScale.HmdToEyeOffset[eye].z;
hmdEye.pixelsPerTanAngle[0] = m_pixelsPerTanAngleAtCenter[eye].x;
hmdEye.pixelsPerTanAngle[1] = m_pixelsPerTanAngleAtCenter[eye].y;
ovrMatrix4f projection = ovrMatrix4f_Projection(m_eyeFov[eye], 0.1f, 1000.0f, ovrProjection_LeftHanded);
for (uint32_t ii = 0; ii < 4; ++ii)
{
for (uint32_t jj = 0; jj < 4; ++jj)
{
hmdEye.projection[4*ii + jj] = projection.M[jj][ii];
}
}
}
return true;
}
void VRImplOVR::updateInput(HMD& /* _hmd */)
{
}
void VRImplOVR::recenter()
{
if (NULL != m_session)
{
ovr_RecenterTrackingOrigin(m_session);
}
}
} // namespace bgfx
#endif // BGFX_CONFIG_USE_OVR