/* * Copyright 2011-2017 Branimir Karadzic. All rights reserved. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause */ #include "hmd.h" namespace bgfx { VR::VR() : m_impl(NULL) , m_framesUntilReconnect(0) , m_enabled(false) { } void VR::init(VRImplI* _impl) { if (NULL == _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 (NULL == m_impl) { return; } m_impl->destroySwapChain(); if (m_impl->isConnected() ) { m_impl->disconnect(); } m_impl->shutdown(); m_impl = NULL; m_enabled = false; } void VR::getViewport(uint8_t _eye, Rect* _viewport) const { _viewport->m_x = uint16_t(_eye * (m_desc.m_eyeSize[_eye].m_w + 1) ); _viewport->m_y = 0; _viewport->m_width = uint16_t(m_desc.m_eyeSize[_eye].m_w); _viewport->m_height = uint16_t(m_desc.m_eyeSize[_eye].m_h); } void VR::makeRenderTargetActive() { BX_CHECK(m_enabled, "VR::renderEyeStart called while not enabled - render usage error"); if (NULL != m_impl) { m_impl->makeRenderTargetActive(m_desc); } } void VR::recenter() { if (NULL != m_impl) { m_impl->recenter(); } } void VR::preReset() { if (NULL != m_impl) { m_impl->destroyMirror(); } m_enabled = false; } void VR::postReset(int _msaaSamples, int _mirrorWidth, int _mirrorHeight) { if (NULL != m_impl && m_impl->createSwapChain(m_desc, _msaaSamples, _mirrorWidth, _mirrorHeight) ) { m_enabled = true; } } void VR::flip() { if (NULL == 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 (NULL == 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 = uint16_t(m_hmdSize.m_w); _hmd.height = uint16_t(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