mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-18 04:53:06 +01:00
211 lines
5.2 KiB
C++
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
|