2020-05-24 16:00:42 +00:00
|
|
|
#include "vrviewer.hpp"
|
|
|
|
#include "vrsession.hpp"
|
2020-01-09 23:10:09 +00:00
|
|
|
#include "openxrmanagerimpl.hpp"
|
2020-06-21 21:40:07 +00:00
|
|
|
#include "openxrinput.hpp"
|
2020-03-15 14:31:38 +00:00
|
|
|
#include "vrenvironment.hpp"
|
2020-01-09 23:10:09 +00:00
|
|
|
#include "Windows.h"
|
2020-02-14 21:11:19 +00:00
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
#include "../mwworld/class.hpp"
|
|
|
|
#include "../mwworld/player.hpp"
|
|
|
|
#include "../mwworld/esmstore.hpp"
|
2020-05-20 23:01:15 +00:00
|
|
|
#include "../mwrender/vismask.hpp"
|
2020-02-14 21:11:19 +00:00
|
|
|
#include <components/esm/loadrace.hpp>
|
|
|
|
#include <osg/MatrixTransform>
|
2020-01-09 23:10:09 +00:00
|
|
|
|
|
|
|
namespace MWVR
|
|
|
|
{
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
VRViewer::VRViewer(
|
2020-02-23 10:02:38 +00:00
|
|
|
osg::ref_ptr<osgViewer::Viewer> viewer)
|
2020-05-24 16:00:42 +00:00
|
|
|
: mRealizeOperation(new RealizeOperation())
|
2020-01-09 23:10:09 +00:00
|
|
|
, mViewer(viewer)
|
2020-02-02 12:12:53 +00:00
|
|
|
, mPreDraw(new PredrawCallback(this))
|
|
|
|
, mPostDraw(new PostdrawCallback(this))
|
2020-02-15 19:01:11 +00:00
|
|
|
, mConfigured(false)
|
2020-01-09 23:10:09 +00:00
|
|
|
{
|
2020-01-23 23:14:23 +00:00
|
|
|
mViewer->setRealizeOperation(mRealizeOperation);
|
2020-05-24 16:00:42 +00:00
|
|
|
//this->setName("OpenXRRoot");
|
2020-01-09 23:10:09 +00:00
|
|
|
}
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
VRViewer::~VRViewer(void)
|
2020-01-09 23:10:09 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
void VRViewer::traversals()
|
2020-01-09 23:10:09 +00:00
|
|
|
{
|
2020-01-23 23:14:23 +00:00
|
|
|
mViewer->updateTraversal();
|
|
|
|
mViewer->renderingTraversals();
|
|
|
|
}
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
void VRViewer::realize(osg::GraphicsContext* context)
|
2020-01-23 23:14:23 +00:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(mMutex);
|
2020-05-24 16:00:42 +00:00
|
|
|
|
2020-01-23 23:14:23 +00:00
|
|
|
if (mConfigured)
|
2020-05-24 16:00:42 +00:00
|
|
|
{
|
2020-01-23 23:14:23 +00:00
|
|
|
return;
|
2020-05-24 16:00:42 +00:00
|
|
|
}
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-01-23 23:14:23 +00:00
|
|
|
if (!context->isCurrent())
|
2020-01-09 23:10:09 +00:00
|
|
|
if (!context->makeCurrent())
|
|
|
|
{
|
2020-05-24 16:00:42 +00:00
|
|
|
throw std::logic_error("VRViewer::configure() failed to make graphics context current.");
|
2020-01-25 13:27:13 +00:00
|
|
|
return;
|
2020-01-09 23:10:09 +00:00
|
|
|
}
|
|
|
|
|
2020-02-02 12:12:53 +00:00
|
|
|
auto mainCamera = mCameras["MainCamera"] = mViewer->getCamera();
|
|
|
|
mainCamera->setName("Main");
|
2020-05-24 16:00:42 +00:00
|
|
|
mainCamera->setInitialDrawCallback(new VRView::InitialDrawCallback());
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-02-02 12:12:53 +00:00
|
|
|
osg::Vec4 clearColor = mainCamera->getClearColor();
|
2020-01-23 23:14:23 +00:00
|
|
|
|
2020-03-15 14:31:38 +00:00
|
|
|
auto* xr = Environment::get().getManager();
|
2020-02-29 22:53:56 +00:00
|
|
|
if (!xr->realized())
|
|
|
|
xr->realize(context);
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
xr->handleEvents();
|
2020-01-26 19:06:47 +00:00
|
|
|
|
2020-06-24 19:26:11 +00:00
|
|
|
auto config = xr->getRecommendedSwapchainConfig();
|
|
|
|
|
|
|
|
auto leftView = new VRView("LeftEye", config[(int)Side::LEFT_SIDE], context->getState());
|
|
|
|
auto rightView = new VRView("RightEye", config[(int)Side::RIGHT_SIDE], context->getState());
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-02-02 12:12:53 +00:00
|
|
|
mViews["LeftEye"] = leftView;
|
|
|
|
mViews["RightEye"] = rightView;
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-02-02 12:12:53 +00:00
|
|
|
auto leftCamera = mCameras["LeftEye"] = leftView->createCamera(0, clearColor, context);
|
|
|
|
auto rightCamera = mCameras["RightEye"] = rightView->createCamera(1, clearColor, context);
|
|
|
|
|
|
|
|
leftCamera->setPreDrawCallback(mPreDraw);
|
|
|
|
rightCamera->setPreDrawCallback(mPreDraw);
|
|
|
|
|
2020-03-01 22:05:38 +00:00
|
|
|
leftCamera->setFinalDrawCallback(mPostDraw);
|
|
|
|
rightCamera->setFinalDrawCallback(mPostDraw);
|
2020-02-02 12:12:53 +00:00
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
// Stereo cameras should only draw the scene
|
|
|
|
leftCamera->setCullMask(~MWRender::Mask_GUI & ~MWRender::Mask_SimpleWater & ~MWRender::Mask_UpdateVisitor);
|
|
|
|
rightCamera->setCullMask(~MWRender::Mask_GUI & ~MWRender::Mask_SimpleWater & ~MWRender::Mask_UpdateVisitor);
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-02-02 12:12:53 +00:00
|
|
|
leftCamera->setName("LeftEye");
|
|
|
|
rightCamera->setName("RightEye");
|
2020-01-09 23:10:09 +00:00
|
|
|
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
osg::Camera::CullingMode cullingMode = osg::Camera::DEFAULT_CULLING|osg::Camera::FAR_PLANE_CULLING;
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
if (!Settings::Manager::getBool("small feature culling", "Camera"))
|
|
|
|
cullingMode &= ~(osg::CullStack::SMALL_FEATURE_CULLING);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto smallFeatureCullingPixelSize = Settings::Manager::getFloat("small feature culling pixel size", "Camera");
|
|
|
|
leftCamera->setSmallFeatureCullingPixelSize(smallFeatureCullingPixelSize);
|
|
|
|
rightCamera->setSmallFeatureCullingPixelSize(smallFeatureCullingPixelSize);
|
|
|
|
cullingMode |= osg::CullStack::SMALL_FEATURE_CULLING;
|
|
|
|
}
|
|
|
|
leftCamera->setCullingMode(cullingMode);
|
|
|
|
rightCamera->setCullingMode(cullingMode);
|
|
|
|
|
|
|
|
mViewer->addSlave(leftCamera, true);
|
|
|
|
mViewer->addSlave(rightCamera, true);
|
2020-01-09 23:10:09 +00:00
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
mViewer->setReleaseContextAtEndOfFrameHint(false);
|
2020-01-23 23:14:23 +00:00
|
|
|
|
2020-06-24 19:26:11 +00:00
|
|
|
mMirrorTexture.reset(new VRTexture(context->getState(), mainCamera->getViewport()->width(), mainCamera->getViewport()->height(), 0));
|
2020-06-24 20:22:09 +00:00
|
|
|
mMsaaResolveMirrorTexture[(int)Side::LEFT_SIDE].reset(new VRTexture(context->getState(),
|
|
|
|
leftView->swapchain().width(),
|
|
|
|
leftView->swapchain().height(),
|
|
|
|
0));
|
|
|
|
mMsaaResolveMirrorTexture[(int)Side::RIGHT_SIDE].reset(new VRTexture(context->getState(),
|
|
|
|
rightView->swapchain().width(),
|
|
|
|
rightView->swapchain().height(),
|
|
|
|
0));
|
2020-01-23 23:14:23 +00:00
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
mViewer->getSlave(0)._updateSlaveCallback = new VRView::UpdateSlaveCallback(leftView, context);
|
|
|
|
mViewer->getSlave(1)._updateSlaveCallback = new VRView::UpdateSlaveCallback(rightView, context);
|
2020-02-02 12:12:53 +00:00
|
|
|
|
2020-05-20 23:01:15 +00:00
|
|
|
mMainCameraGC = mainCamera->getGraphicsContext();
|
2020-05-24 16:00:42 +00:00
|
|
|
mMainCameraGC->setSwapCallback(new VRViewer::SwapBuffersCallback(this));
|
2020-02-02 12:12:53 +00:00
|
|
|
mainCamera->setGraphicsContext(nullptr);
|
2020-01-09 23:10:09 +00:00
|
|
|
mConfigured = true;
|
2020-02-02 12:12:53 +00:00
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
Log(Debug::Verbose) << "Realized";
|
2020-01-23 23:14:23 +00:00
|
|
|
}
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
void VRViewer::enableMainCamera(void)
|
2020-05-20 23:01:15 +00:00
|
|
|
{
|
|
|
|
mCameras["MainCamera"]->setGraphicsContext(mMainCameraGC);
|
|
|
|
}
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
void VRViewer::disableMainCamera(void)
|
2020-05-20 23:01:15 +00:00
|
|
|
{
|
|
|
|
mCameras["MainCamera"]->setGraphicsContext(nullptr);
|
|
|
|
}
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
void VRViewer::blitEyesToMirrorTexture(osg::GraphicsContext* gc)
|
2020-01-23 23:14:23 +00:00
|
|
|
{
|
2020-06-03 17:46:20 +00:00
|
|
|
auto* state = gc->getState();
|
|
|
|
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
|
2020-06-24 19:26:11 +00:00
|
|
|
|
2020-06-24 20:22:09 +00:00
|
|
|
int screenWidth = mCameras["MainCamera"]->getViewport()->width();
|
|
|
|
int mirrorWidth = screenWidth / 2;
|
|
|
|
int screenHeight = mCameras["MainCamera"]->getViewport()->height();
|
|
|
|
const char* viewNames[] = {
|
|
|
|
"RightEye",
|
|
|
|
"LeftEye"
|
|
|
|
};
|
2020-06-24 19:26:11 +00:00
|
|
|
|
2020-06-24 20:22:09 +00:00
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
auto& resolveTexture = *mMsaaResolveMirrorTexture[i];
|
|
|
|
resolveTexture.beginFrame(gc);
|
|
|
|
mViews[viewNames[i]]->swapchain().renderBuffer()->blit(gc, 0, 0, resolveTexture.width(), resolveTexture.height());
|
|
|
|
mMirrorTexture->beginFrame(gc);
|
|
|
|
resolveTexture.blit(gc, i * mirrorWidth, 0, (i + 1) * mirrorWidth, screenHeight);
|
|
|
|
}
|
2020-05-20 23:01:15 +00:00
|
|
|
|
2020-06-24 20:22:09 +00:00
|
|
|
gl->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
mMirrorTexture->blit(gc, 0, 0, screenWidth, screenHeight);
|
2020-01-23 23:14:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-24 16:00:42 +00:00
|
|
|
VRViewer::SwapBuffersCallback::swapBuffersImplementation(
|
2020-01-23 23:14:23 +00:00
|
|
|
osg::GraphicsContext* gc)
|
|
|
|
{
|
2020-03-15 14:31:38 +00:00
|
|
|
auto* session = Environment::get().getSession();
|
2020-05-24 16:00:42 +00:00
|
|
|
session->swapBuffers(gc, *mViewer);
|
2020-01-23 23:14:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-24 16:00:42 +00:00
|
|
|
VRViewer::RealizeOperation::operator()(
|
2020-01-23 23:14:23 +00:00
|
|
|
osg::GraphicsContext* gc)
|
|
|
|
{
|
|
|
|
OpenXRManager::RealizeOperation::operator()(gc);
|
2020-02-29 22:53:56 +00:00
|
|
|
|
2020-03-15 14:31:38 +00:00
|
|
|
Environment::get().getViewer()->realize(gc);
|
2020-01-23 23:14:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-05-24 16:00:42 +00:00
|
|
|
VRViewer::RealizeOperation::realized()
|
2020-01-23 23:14:23 +00:00
|
|
|
{
|
2020-03-15 14:31:38 +00:00
|
|
|
return Environment::get().getViewer()->realized();
|
2020-01-09 23:10:09 +00:00
|
|
|
}
|
2020-02-02 12:12:53 +00:00
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
void VRViewer::preDrawCallback(osg::RenderInfo& info)
|
2020-02-02 12:12:53 +00:00
|
|
|
{
|
|
|
|
auto* camera = info.getCurrentCamera();
|
|
|
|
auto name = camera->getName();
|
2020-06-03 17:46:20 +00:00
|
|
|
mViews[name]->prerenderCallback(info);
|
2020-02-02 12:12:53 +00:00
|
|
|
}
|
|
|
|
|
2020-05-24 16:00:42 +00:00
|
|
|
void VRViewer::postDrawCallback(osg::RenderInfo& info)
|
2020-02-02 12:12:53 +00:00
|
|
|
{
|
|
|
|
auto* camera = info.getCurrentCamera();
|
|
|
|
auto name = camera->getName();
|
|
|
|
auto& view = mViews[name];
|
|
|
|
|
|
|
|
view->postrenderCallback(info);
|
|
|
|
|
|
|
|
// OSG will sometimes overwrite the predraw callback.
|
|
|
|
if (camera->getPreDrawCallback() != mPreDraw)
|
|
|
|
{
|
|
|
|
camera->setPreDrawCallback(mPreDraw);
|
|
|
|
Log(Debug::Warning) << ("osg overwrote predraw");
|
|
|
|
}
|
|
|
|
}
|
2020-01-09 23:10:09 +00:00
|
|
|
}
|