1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 13:19:54 +00:00
openmw-tes3mp/apps/openmw/mwvr/vrshadow.cpp
2020-07-26 13:12:36 +02:00

76 lines
3 KiB
C++

#include "vrenvironment.hpp"
#include "vrsession.hpp"
#include "vrshadow.hpp"
#include "../mwrender/vismask.hpp"
#include <components/sceneutil/mwshadowtechnique.hpp>
#include <cassert>
namespace MWVR
{
VrShadow::VrShadow()
: mMasterConfig(new SharedShadowMapConfig)
, mSlaveConfig(new SharedShadowMapConfig)
{
mMasterConfig->_id = "VR";
mMasterConfig->_master = true;
mSlaveConfig->_id = "VR";
mSlaveConfig->_master = false;
}
void VrShadow::configureShadowsForCamera(osg::Camera* camera, bool master)
{
if(master)
camera->setUserData(mMasterConfig);
else
camera->setUserData(mSlaveConfig);
}
void VrShadow::updateShadowConfig(osg::View& view)
{
auto* session = Environment::get().getSession();
auto viewMatrix = view.getCamera()->getViewMatrix();
auto& poses = session->predictedPoses(VRSession::FramePhase::Update);
auto& leftView = poses.view[(int)Side::LEFT_SIDE];
auto& rightView = poses.view[(int)Side::RIGHT_SIDE];
osg::Vec3d leftEye = leftView.pose.position;
osg::Vec3d rightEye = rightView.pose.position;
// The shadow map will be computed from a position P slightly behind the eyes L and R
// where it creates the minimum frustum encompassing both eyes' frustums.
// Compute Frustum angles. A simple min/max.
FieldOfView fov;
fov.angleLeft = std::min(leftView.fov.angleLeft, rightView.fov.angleLeft);
fov.angleRight = std::max(leftView.fov.angleRight, rightView.fov.angleRight);
fov.angleDown = std::min(leftView.fov.angleDown, rightView.fov.angleDown);
fov.angleUp = std::max(leftView.fov.angleUp, rightView.fov.angleUp);
// Use the law of sines on the triangle spanning PLR to determine P
double angleLeft = std::abs(fov.angleLeft);
double angleRight = std::abs(fov.angleRight);
double lengthRL = (rightEye - leftEye).length();
double ratioRL = lengthRL / std::sin(osg::PI - angleLeft - angleRight);
double lengthLP = ratioRL * std::sin(angleRight);
osg::Vec3d directionLP = osg::Vec3(std::cos(-angleLeft), std::sin(-angleLeft), 0);
osg::Vec3d P = leftEye + directionLP * lengthLP;
// Generate the matrices
float near_ = Settings::Manager::getFloat("near clip", "Camera");
float far_ = Settings::Manager::getFloat("viewing distance", "Camera");
auto modifiedViewMatrix = viewMatrix * session->viewMatrix(P, osg::Quat(0, 0, 0, 1));
auto projectionMatrix = fov.perspectiveMatrix(near_, far_);
if (mMasterConfig->_projection == nullptr)
mMasterConfig->_projection = new osg::RefMatrix;
if (mMasterConfig->_modelView == nullptr)
mMasterConfig->_modelView = new osg::RefMatrix;
mMasterConfig->_referenceFrame = view.getCamera()->getReferenceFrame();
mMasterConfig->_modelView->set(modifiedViewMatrix);
mMasterConfig->_projection->set(projectionMatrix);
}
}