Rewrite of tracking logic.
parent
6e5d9d39dd
commit
d1aaa74193
@ -0,0 +1,141 @@
|
||||
#include "openxrinput.hpp"
|
||||
#include "openxrmanagerimpl.hpp"
|
||||
#include "openxrplatform.hpp"
|
||||
#include "openxrtracker.hpp"
|
||||
#include "openxrtypeconversions.hpp"
|
||||
#include "vrenvironment.hpp"
|
||||
#include "vrinputmanager.hpp"
|
||||
#include "vrsession.hpp"
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
OpenXRTracker::OpenXRTracker(const std::string& name, XrSpace referenceSpace)
|
||||
: VRTrackingSource(name)
|
||||
, mReferenceSpace(referenceSpace)
|
||||
, mTrackingSpaces()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
OpenXRTracker::~OpenXRTracker()
|
||||
{
|
||||
}
|
||||
|
||||
void OpenXRTracker::addTrackingSpace(VRPath path, XrSpace space)
|
||||
{
|
||||
mTrackingSpaces[path] = space;
|
||||
notifyAvailablePosesChanged();
|
||||
}
|
||||
|
||||
void OpenXRTracker::deleteTrackingSpace(VRPath path)
|
||||
{
|
||||
mTrackingSpaces.erase(path);
|
||||
notifyAvailablePosesChanged();
|
||||
}
|
||||
|
||||
void OpenXRTracker::setReferenceSpace(XrSpace referenceSpace)
|
||||
{
|
||||
mReferenceSpace = referenceSpace;
|
||||
}
|
||||
|
||||
std::vector<VRPath> OpenXRTracker::listSupportedTrackingPosePaths() const
|
||||
{
|
||||
std::vector<VRPath> path;
|
||||
for (auto& e : mTrackingSpaces)
|
||||
path.push_back(e.first);
|
||||
return path;
|
||||
}
|
||||
|
||||
void OpenXRTracker::updateTracking(DisplayTime predictedDisplayTime)
|
||||
{
|
||||
Environment::get().getInputManager()->xrInput().getActionSet(ActionSet::Tracking).updateControls();
|
||||
auto* xr = Environment::get().getManager();
|
||||
auto* session = Environment::get().getSession();
|
||||
|
||||
auto& frame = session->getFrame(VRSession::FramePhase::Update);
|
||||
frame->mViews[(int)ReferenceSpace::STAGE] = locateViews(predictedDisplayTime, xr->impl().getReferenceSpace(ReferenceSpace::STAGE));
|
||||
frame->mViews[(int)ReferenceSpace::VIEW] = locateViews(predictedDisplayTime, xr->impl().getReferenceSpace(ReferenceSpace::VIEW));
|
||||
}
|
||||
|
||||
XrSpace OpenXRTracker::getSpace(VRPath path)
|
||||
{
|
||||
auto it = mTrackingSpaces.find(path);
|
||||
if (it != mTrackingSpaces.end())
|
||||
return it->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
VRTrackingPose OpenXRTracker::getTrackingPose(DisplayTime predictedDisplayTime, VRPath path, VRPath reference)
|
||||
{
|
||||
VRTrackingPose pose;
|
||||
pose.status = TrackingStatus::Good;
|
||||
XrSpace space = getSpace(path);
|
||||
XrSpace ref = reference == 0 ? mReferenceSpace : getSpace(reference);
|
||||
if (space == 0 || ref == 0)
|
||||
pose.status = TrackingStatus::NotTracked;
|
||||
if (!!pose.status)
|
||||
locate(pose, space, ref, predictedDisplayTime);
|
||||
return pose;
|
||||
}
|
||||
|
||||
void OpenXRTracker::locate(VRTrackingPose& pose, XrSpace space, XrSpace reference, DisplayTime predictedDisplayTime)
|
||||
{
|
||||
XrSpaceLocation location{ XR_TYPE_SPACE_LOCATION };
|
||||
auto res = xrLocateSpace(space, mReferenceSpace, predictedDisplayTime, &location);
|
||||
|
||||
if (XR_FAILED(res))
|
||||
{
|
||||
// Call failed, exit.
|
||||
CHECK_XRRESULT(res, "xrLocateSpace");
|
||||
pose.status = TrackingStatus::RuntimeFailure;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that everything is being tracked
|
||||
if (!(location.locationFlags & (XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT | XR_SPACE_LOCATION_POSITION_TRACKED_BIT)))
|
||||
{
|
||||
// It's not, data is stale
|
||||
pose.status = TrackingStatus::Stale;
|
||||
}
|
||||
|
||||
// Check that data is valid
|
||||
if (!(location.locationFlags & (XR_SPACE_LOCATION_ORIENTATION_VALID_BIT | XR_SPACE_LOCATION_POSITION_VALID_BIT)))
|
||||
{
|
||||
// It's not, we've lost tracking
|
||||
pose.status = TrackingStatus::Lost;
|
||||
}
|
||||
|
||||
pose.pose = MWVR::Pose{
|
||||
fromXR(location.pose.position),
|
||||
fromXR(location.pose.orientation)
|
||||
};
|
||||
}
|
||||
|
||||
std::array<View, 2> OpenXRTracker::locateViews(DisplayTime predictedDisplayTime, XrSpace reference)
|
||||
{
|
||||
std::array<XrView, 2> xrViews{ {{XR_TYPE_VIEW}, {XR_TYPE_VIEW}} };
|
||||
XrViewState viewState{ XR_TYPE_VIEW_STATE };
|
||||
uint32_t viewCount = 2;
|
||||
|
||||
XrViewLocateInfo viewLocateInfo{ XR_TYPE_VIEW_LOCATE_INFO };
|
||||
viewLocateInfo.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
|
||||
viewLocateInfo.displayTime = predictedDisplayTime;
|
||||
viewLocateInfo.space = reference;
|
||||
|
||||
auto* xr = Environment::get().getManager();
|
||||
CHECK_XRCMD(xrLocateViews(xr->impl().xrSession(), &viewLocateInfo, &viewState, viewCount, &viewCount, xrViews.data()));
|
||||
|
||||
std::array<View, 2> vrViews{};
|
||||
vrViews[(int)Side::LEFT_SIDE].pose = fromXR(xrViews[(int)Side::LEFT_SIDE].pose);
|
||||
vrViews[(int)Side::RIGHT_SIDE].pose = fromXR(xrViews[(int)Side::RIGHT_SIDE].pose);
|
||||
vrViews[(int)Side::LEFT_SIDE].fov = fromXR(xrViews[(int)Side::LEFT_SIDE].fov);
|
||||
vrViews[(int)Side::RIGHT_SIDE].fov = fromXR(xrViews[(int)Side::RIGHT_SIDE].fov);
|
||||
return vrViews;
|
||||
}
|
||||
|
||||
OpenXRTrackingToWorldBinding::OpenXRTrackingToWorldBinding()
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
#ifndef OPENXR_TRACKER_HPP
|
||||
#define OPENXR_TRACKER_HPP
|
||||
|
||||
#include <openxr/openxr.h>
|
||||
#include "vrtracking.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
//! Serves as a C++ wrapper of openxr spaces, but also bridges stage coordinates and game coordinates.
|
||||
//! Supports the compulsory sets of paths.
|
||||
class OpenXRTracker : public VRTrackingSource
|
||||
{
|
||||
public:
|
||||
OpenXRTracker(const std::string& name, XrSpace referenceSpace);
|
||||
~OpenXRTracker();
|
||||
|
||||
void addTrackingSpace(VRPath path, XrSpace space);
|
||||
void deleteTrackingSpace(VRPath path);
|
||||
|
||||
//! The base space used to reference everything else.
|
||||
void setReferenceSpace(XrSpace referenceSpace);
|
||||
|
||||
VRTrackingPose getTrackingPose(DisplayTime predictedDisplayTime, VRPath path, VRPath reference = 0) override;
|
||||
|
||||
std::vector<VRPath> listSupportedTrackingPosePaths() const override;
|
||||
void updateTracking(DisplayTime predictedDisplayTime) override;
|
||||
|
||||
private:
|
||||
std::array<View, 2> locateViews(DisplayTime predictedDisplayTime, XrSpace reference);
|
||||
void locate(VRTrackingPose& pose, XrSpace space, XrSpace reference, DisplayTime predictedDisplayTime);
|
||||
XrSpace getSpace(VRPath);
|
||||
|
||||
XrSpace mReferenceSpace;
|
||||
std::map<VRPath, XrSpace> mTrackingSpaces;
|
||||
};
|
||||
|
||||
//! Ties a tracked pose to the game world.
|
||||
//! A movement tracking pose is selected by passing its path to the constructor.
|
||||
//! All poses are transformed in the horizontal plane by moving the x,y origin to the position of the movement tracking pose, and then reoriented using the current orientation.
|
||||
//! The movement tracking pose is effectively always at the x,y origin
|
||||
//! The movement of the movement tracking pose is accumulated and can be read using the movement() call.
|
||||
//! If this movement is ever consumed (such as by moving the character to follow the player) the consumed movement must be reported using consumeMovement().
|
||||
class OpenXRTrackingToWorldBinding
|
||||
{
|
||||
public:
|
||||
OpenXRTrackingToWorldBinding();
|
||||
|
||||
//! Re-orient the stage.
|
||||
void setOrientation(float yaw, bool adjust);
|
||||
osg::Quat getOrientation() const { return mOrientation; }
|
||||
|
||||
void setEyeLevel(float eyeLevel) { mEyeLevel = eyeLevel; }
|
||||
float getEyeLevel() const { return mEyeLevel; }
|
||||
|
||||
void setSeatedPlay(bool seatedPlay) { mSeatedPlay = seatedPlay; }
|
||||
bool getSeatedPlay() const { return mSeatedPlay; }
|
||||
|
||||
//! The player's movement within the VR stage. This accumulates until the movement has been consumed by calling consumeMovement()
|
||||
osg::Vec3 movement() const;
|
||||
|
||||
//! Consume movement
|
||||
void consumeMovement(const osg::Vec3& movement);
|
||||
|
||||
//! Recenter tracking by consuming all movement.
|
||||
void recenter(bool resetZ);
|
||||
|
||||
void update(Pose movementTrackingPose);
|
||||
|
||||
//! Transforms a stage-referenced pose to be world-aligned.
|
||||
//! \note Unlike VRTrackingSource::getTrackingPose() this does not take a reference path, as re-alignment is only needed when fetching a stage-referenced pose.
|
||||
void alignPose(Pose& pose);
|
||||
|
||||
private:
|
||||
bool mSeatedPlay = false;
|
||||
bool mHasTrackingData = false;
|
||||
float mEyeLevel = 0;
|
||||
Pose mLastPose = Pose();
|
||||
osg::Vec3 mMovement = osg::Vec3(0,0,0);
|
||||
osg::Quat mOrientation = osg::Quat(0,0,0,1);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,76 @@
|
||||
#include "openxrtypeconversions.hpp"
|
||||
#include "openxrswapchain.hpp"
|
||||
#include "openxrswapchainimpl.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
osg::Vec3 fromXR(XrVector3f v)
|
||||
{
|
||||
return osg::Vec3{ v.x, -v.z, v.y };
|
||||
}
|
||||
|
||||
osg::Quat fromXR(XrQuaternionf quat)
|
||||
{
|
||||
return osg::Quat{ quat.x, -quat.z, quat.y, quat.w };
|
||||
}
|
||||
|
||||
XrVector3f toXR(osg::Vec3 v)
|
||||
{
|
||||
return XrVector3f{ v.x(), v.z(), -v.y() };
|
||||
}
|
||||
|
||||
XrQuaternionf toXR(osg::Quat quat)
|
||||
{
|
||||
return XrQuaternionf{ static_cast<float>(quat.x()), static_cast<float>(quat.z()), static_cast<float>(-quat.y()), static_cast<float>(quat.w()) };
|
||||
}
|
||||
|
||||
MWVR::Pose fromXR(XrPosef pose)
|
||||
{
|
||||
return MWVR::Pose{ fromXR(pose.position), fromXR(pose.orientation) };
|
||||
}
|
||||
|
||||
XrPosef toXR(MWVR::Pose pose)
|
||||
{
|
||||
return XrPosef{ toXR(pose.orientation), toXR(pose.position) };
|
||||
}
|
||||
|
||||
MWVR::FieldOfView fromXR(XrFovf fov)
|
||||
{
|
||||
return MWVR::FieldOfView{ fov.angleLeft, fov.angleRight, fov.angleUp, fov.angleDown };
|
||||
}
|
||||
|
||||
XrFovf toXR(MWVR::FieldOfView fov)
|
||||
{
|
||||
return XrFovf{ fov.angleLeft, fov.angleRight, fov.angleUp, fov.angleDown };
|
||||
}
|
||||
|
||||
XrCompositionLayerProjectionView toXR(MWVR::CompositionLayerProjectionView layer)
|
||||
{
|
||||
XrCompositionLayerProjectionView xrLayer;
|
||||
xrLayer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
||||
xrLayer.subImage = toXR(layer.subImage, false);
|
||||
xrLayer.pose = toXR(layer.pose);
|
||||
xrLayer.fov = toXR(layer.fov);
|
||||
xrLayer.next = nullptr;
|
||||
|
||||
return xrLayer;
|
||||
}
|
||||
|
||||
XrSwapchainSubImage toXR(MWVR::SubImage subImage, bool depthImage)
|
||||
{
|
||||
XrSwapchainSubImage xrSubImage{};
|
||||
if (depthImage)
|
||||
xrSubImage.swapchain = subImage.swapchain->impl().xrSwapchainDepth();
|
||||
else
|
||||
xrSubImage.swapchain = subImage.swapchain->impl().xrSwapchain();
|
||||
xrSubImage.imageRect.extent.width = subImage.width;
|
||||
xrSubImage.imageRect.extent.height = subImage.height;
|
||||
xrSubImage.imageRect.offset.x = subImage.x;
|
||||
xrSubImage.imageRect.offset.y = subImage.y;
|
||||
xrSubImage.imageArrayIndex = 0;
|
||||
return xrSubImage;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,25 @@
|
||||
#ifndef MWVR_OPENXRTYPECONVERSIONS_H
|
||||
#define MWVR_OPENXRTYPECONVERSIONS_H
|
||||
|
||||
#include <openxr/openxr.h>
|
||||
#include "vrtypes.hpp"
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Quat>
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
/// Conversion methods between openxr types to osg/mwvr types. Includes managing the differing conventions.
|
||||
Pose fromXR(XrPosef pose);
|
||||
FieldOfView fromXR(XrFovf fov);
|
||||
osg::Vec3 fromXR(XrVector3f);
|
||||
osg::Quat fromXR(XrQuaternionf quat);
|
||||
XrPosef toXR(Pose pose);
|
||||
XrFovf toXR(FieldOfView fov);
|
||||
XrVector3f toXR(osg::Vec3 v);
|
||||
XrQuaternionf toXR(osg::Quat quat);
|
||||
|
||||
XrCompositionLayerProjectionView toXR(CompositionLayerProjectionView layer);
|
||||
XrSwapchainSubImage toXR(SubImage, bool depthImage);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,76 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
#ifndef MWVR_VRSHADOW_H
|
||||
#define MWVR_VRSHADOW_H
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <components/sceneutil/mwshadowtechnique.hpp>
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
|
||||
class UpdateShadowMapSlaveCallback : public osg::View::Slave::UpdateSlaveCallback
|
||||
{
|
||||
public:
|
||||
void updateSlave(osg::View& view, osg::View::Slave& slave) override;
|
||||
};
|
||||
|
||||
class VrShadow
|
||||
{
|
||||
using SharedShadowMapConfig = SceneUtil::MWShadowTechnique::SharedShadowMapConfig;
|
||||
public:
|
||||
VrShadow();
|
||||
|
||||
void configureShadowsForCamera(osg::Camera* camera, bool master);
|
||||
|
||||
void updateShadowConfig(osg::View& view);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<SharedShadowMapConfig> mMasterConfig;
|
||||
osg::ref_ptr<SharedShadowMapConfig> mSlaveConfig;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,315 @@
|
||||
#include "vrtracking.hpp"
|
||||
#include "vrenvironment.hpp"
|
||||
#include "vrsession.hpp"
|
||||
#include "openxrmanagerimpl.hpp"
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
VRTrackingManager::VRTrackingManager()
|
||||
{
|
||||
mHandDirectedMovement = Settings::Manager::getBool("hand directed movement", "VR");
|
||||
mHeadPath = stringToVRPath("/user/head/input/pose");
|
||||
mHandPath = stringToVRPath("/user/hand/left/input/aim/pose");
|
||||
}
|
||||
|
||||
VRTrackingManager::~VRTrackingManager()
|
||||
{
|
||||
}
|
||||
|
||||
void VRTrackingManager::registerTrackingSource(VRTrackingSource* source, const std::string& name)
|
||||
{
|
||||
mSources.emplace(name, source);
|
||||
notifySourceChanged(name);
|
||||
}
|
||||
|
||||
void VRTrackingManager::unregisterTrackingSource(VRTrackingSource* source)
|
||||
{
|
||||
std::string name = "";
|
||||
{
|
||||
auto it = mSources.begin();
|
||||
while (it->second != source) it++;
|
||||
name = it->first;
|
||||
mSources.erase(it);
|
||||
}
|
||||
notifySourceChanged(name);
|
||||
}
|
||||
|
||||
VRTrackingSource* VRTrackingManager::getSource(const std::string& name)
|
||||
{
|
||||
auto it = mSources.find(name);
|
||||
if (it != mSources.end())
|
||||
return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VRTrackingManager::movementAngles(float& yaw, float& pitch)
|
||||
{
|
||||
yaw = mMovementYaw;
|
||||
pitch = mMovementPitch;
|
||||
}
|
||||
|
||||
void VRTrackingManager::processChangedSettings(const std::set<std::pair<std::string, std::string>>& changed)
|
||||
{
|
||||
mHandDirectedMovement = Settings::Manager::getBool("hand directed movement", "VR");
|
||||
}
|
||||
|
||||
void VRTrackingManager::notifySourceChanged(const std::string& name)
|
||||
{
|
||||
auto* source = getSource(name);
|
||||
for (auto& it : mBindings)
|
||||
{
|
||||
if (it.second == name)
|
||||
{
|
||||
if (source)
|
||||
it.first->onTrackingAttached(*source);
|
||||
else
|
||||
it.first->onTrackingDetached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VRTrackingManager::updateMovementAngles(DisplayTime predictedDisplayTime)
|
||||
{
|
||||
if (mHandDirectedMovement)
|
||||
{
|
||||
float headYaw = 0.f;
|
||||
float headPitch = 0.f;
|
||||
float headsWillRoll = 0.f;
|
||||
|
||||
float handYaw = 0.f;
|
||||
float handPitch = 0.f;
|
||||
float handRoll = 0.f;
|
||||
|
||||
auto pcsource = getSource("pcstage");
|
||||
|
||||
if (pcsource)
|
||||
{
|
||||
auto tpHead = pcsource->getTrackingPose(predictedDisplayTime, mHeadPath);
|
||||
auto tpHand = pcsource->getTrackingPose(predictedDisplayTime, mHandPath);
|
||||
|
||||
if (!!tpHead.status && !!tpHand.status)
|
||||
{
|
||||
getEulerAngles(tpHead.pose.orientation, headYaw, headPitch, headsWillRoll);
|
||||
getEulerAngles(tpHand.pose.orientation, handYaw, handPitch, handRoll);
|
||||
|
||||
mMovementYaw = handYaw - headYaw;
|
||||
mMovementPitch = handPitch - headPitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMovementYaw = 0;
|
||||
mMovementPitch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VRTrackingManager::bind(VRTrackingListener* listener, std::string sourceName)
|
||||
{
|
||||
unbind(listener);
|
||||
mBindings.emplace(listener, sourceName);
|
||||
|
||||
auto* source = getSource(sourceName);
|
||||
if (source)
|
||||
listener->onTrackingAttached(*source);
|
||||
else
|
||||
listener->onTrackingDetached();
|
||||
}
|
||||
|
||||
void VRTrackingManager::unbind(VRTrackingListener* listener)
|
||||
{
|
||||
auto it = mBindings.find(listener);
|
||||
if (it != mBindings.end())
|
||||
{
|
||||
listener->onTrackingDetached();
|
||||
mBindings.erase(listener);
|
||||
}
|
||||
}
|
||||
|
||||
VRPath VRTrackingManager::stringToVRPath(const std::string& path)
|
||||
{
|
||||
// Empty path is invalid
|
||||
if (path.empty())
|
||||
{
|
||||
Log(Debug::Error) << "Empty path";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return path immediately if it already exists
|
||||
auto it = mPathIdentifiers.find(path);
|
||||
if (it != mPathIdentifiers.end())
|
||||
return it->second;
|
||||
|
||||
// Add new path and return it
|
||||
auto res = mPathIdentifiers.emplace(path, mPathIdentifiers.size() + 1);
|
||||
return res.first->second;
|
||||
}
|
||||
|
||||
std::string VRTrackingManager::trackingPathToString(VRPath path)
|
||||
{
|
||||
// Find the identifier in the map and return the corresponding string.
|
||||
for (auto& e : mPathIdentifiers)
|
||||
if (e.second == path)
|
||||
return e.first;
|
||||
|
||||
// No path found, return empty string
|
||||
Log(Debug::Warning) << "No such path identifier (" << path << ")";
|
||||
return "";
|
||||
}
|
||||
|
||||
void VRTrackingManager::updateTracking()
|
||||
{
|
||||
MWVR::Environment::get().getSession()->endFrame();
|
||||
MWVR::Environment::get().getSession()->beginFrame();
|
||||
auto& frame = Environment::get().getSession()->getFrame(VRSession::FramePhase::Update);
|
||||
|
||||
if (frame->mFrameInfo.runtimePredictedDisplayTime == 0)
|
||||
return;
|
||||
|
||||
for (auto source : mSources)
|
||||
source.second->updateTracking(frame->mFrameInfo.runtimePredictedDisplayTime);
|
||||
|
||||
updateMovementAngles(frame->mFrameInfo.runtimePredictedDisplayTime);
|
||||
|
||||
for (auto& binding : mBindings)
|
||||
{
|
||||
auto* listener = binding.first;
|
||||
auto* source = getSource(binding.second);
|
||||
if (source)
|
||||
{
|
||||
if (source->availablePosesChanged())
|
||||
listener->onAvailablePosesChanged(*source);
|
||||
listener->onTrackingUpdated(*source, frame->mFrameInfo.runtimePredictedDisplayTime);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto source : mSources)
|
||||
source.second->clearAvailablePosesChanged();
|
||||
}
|
||||
|
||||
VRTrackingSource::VRTrackingSource(const std::string& name)
|
||||
{
|
||||
Environment::get().getTrackingManager()->registerTrackingSource(this, name);
|
||||
}
|
||||
|
||||
VRTrackingSource::~VRTrackingSource()
|
||||
{
|
||||
Environment::get().getTrackingManager()->unregisterTrackingSource(this);
|
||||
}
|
||||
|
||||
bool VRTrackingSource::availablePosesChanged() const
|
||||
{
|
||||
return mAvailablePosesChanged;
|
||||
}
|
||||
|
||||
void VRTrackingSource::clearAvailablePosesChanged()
|
||||
{
|
||||
mAvailablePosesChanged = false;
|
||||
}
|
||||
|
||||
void VRTrackingSource::notifyAvailablePosesChanged()
|
||||
{
|
||||
mAvailablePosesChanged = true;
|
||||
}
|
||||
|
||||
VRTrackingListener::~VRTrackingListener()
|
||||
{
|
||||
Environment::get().getTrackingManager()->unbind(this);
|
||||
}
|
||||
|
||||
VRTrackingToWorldBinding::VRTrackingToWorldBinding(const std::string& name, VRTrackingSource* source, VRPath movementReference)
|
||||
: VRTrackingSource(name)
|
||||
, mMovementReference(movementReference)
|
||||
, mSource(source)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void VRTrackingToWorldBinding::setWorldOrientation(float yaw, bool adjust)
|
||||
{
|
||||
auto yawQuat = osg::Quat(yaw, osg::Vec3(0, 0, -1));
|
||||
if (adjust)
|
||||
mOrientation = yawQuat * mOrientation;
|
||||
else
|
||||
mOrientation = yawQuat;
|
||||
}
|
||||
|
||||
osg::Vec3 VRTrackingToWorldBinding::movement() const
|
||||
{
|
||||
return mMovement;
|
||||
}
|
||||
|
||||
void VRTrackingToWorldBinding::consumeMovement(const osg::Vec3& movement)
|
||||
{
|
||||
mMovement.x() -= movement.x();
|
||||
mMovement.y() -= movement.y();
|
||||
}
|
||||
|
||||
void VRTrackingToWorldBinding::recenter(bool resetZ)
|
||||
{
|
||||
mMovement.x() = 0;
|
||||
mMovement.y() = 0;
|
||||
if (resetZ)
|
||||
{
|
||||
if (mSeatedPlay)
|
||||
mMovement.z() = mEyeLevel;
|
||||
else
|
||||
mMovement.z() = mLastPose.position.z();
|
||||
}
|
||||
}
|
||||
|
||||
VRTrackingPose VRTrackingToWorldBinding::getTrackingPose(DisplayTime predictedDisplayTime, VRPath path, VRPath reference)
|
||||
{
|
||||
auto tp = mSource->getTrackingPose(predictedDisplayTime, path, reference);
|
||||
tp.pose.position *= Constants::UnitsPerMeter;
|
||||
|
||||
if (reference == 0 && !!tp.status)
|
||||
{
|
||||
tp.pose.position -= mLastPose.position;
|
||||
tp.pose.position = mOrientation * tp.pose.position;
|
||||
tp.pose.position += mMovement;
|
||||
tp.pose.orientation = tp.pose.orientation * mOrientation;
|
||||
|
||||
if(mOrigin)
|
||||
tp.pose.position += mOriginWorldPose.position;
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
|
||||
std::vector<VRPath> VRTrackingToWorldBinding::listSupportedTrackingPosePaths() const
|
||||
{
|
||||
return mSource->listSupportedTrackingPosePaths();
|
||||
}
|
||||
|
||||
void VRTrackingToWorldBinding::updateTracking(DisplayTime predictedDisplayTime)
|
||||
{
|
||||
mOriginWorldPose = Pose();
|
||||
if (mOrigin)
|
||||
{
|
||||
auto worldMatrix = osg::computeLocalToWorld(mOrigin->getParentalNodePaths()[0]);
|
||||
mOriginWorldPose.position = worldMatrix.getTrans();
|
||||
mOriginWorldPose.orientation = worldMatrix.getRotate();
|
||||
}
|
||||
|
||||
auto mtp = mSource->getTrackingPose(predictedDisplayTime, mMovementReference, 0);
|
||||
if (!!mtp.status)
|
||||
{
|
||||
mtp.pose.position *= Constants::UnitsPerMeter;
|
||||
osg::Vec3 vrMovement = mtp.pose.position - mLastPose.position;
|
||||
mLastPose = mtp.pose;
|
||||
if (mHasTrackingData)
|
||||
mMovement += mOrientation * vrMovement;
|
||||
else
|
||||
mMovement.z() = mLastPose.position.z();
|
||||
mHasTrackingData = true;
|
||||
}
|
||||
|
||||
mAvailablePosesChanged = mSource->availablePosesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,216 @@
|
||||
#ifndef MWVR_VRTRACKING_H
|
||||
#define MWVR_VRTRACKING_H
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include "vrtypes.hpp"
|
||||
|
||||
namespace MWVR
|
||||
{
|
||||
class VRAnimation;
|
||||
|
||||
//! Describes the status of the tracking data. Note that there are multiple success statuses, and predicted poses should be used whenever the status is a non-negative integer.
|
||||
enum class TrackingStatus : signed
|
||||
{
|
||||
Unknown = 0, //!< No data has been written (default value)
|
||||
Good = 1, //!< Accurate, up-to-date tracking data was used.
|
||||
Stale = 2, //!< Inaccurate, stale tracking data was used. This code is a status warning, not an error, and the tracking pose should be used.
|
||||
NotTracked = -1, //!< No tracking data was returned because the tracking source does not track that
|
||||
Lost = -2, //!< No tracking data was returned because the tracking source could not be read (occluded controller, network connectivity issues, etc.).
|
||||
RuntimeFailure = -3 //!< No tracking data was returned because of a runtime failure.
|
||||
};
|
||||
|
||||
inline bool operator!(TrackingStatus status)
|
||||
{
|
||||
return static_cast<signed>(status) < static_cast<signed>(TrackingStatus::Good);
|
||||
}
|
||||
|
||||
//! @brief An identifier representing an OpenXR path. 0 represents no path.
|
||||
//! A VRPath can be optained from the string representation of a path using VRTrackingManager::getTrackingPath()
|
||||
//! \note Support is determined by each VRTrackingSource. ALL strings are convertible to VRPaths but won't be useful unless they match a supported string.
|
||||
//! \sa VRTrackingManager::getTrackingPath()
|
||||
using VRPath = uint64_t;
|
||||
|
||||
//! A single tracked pose
|
||||
struct VRTrackingPose
|
||||
{
|
||||
TrackingStatus status = TrackingStatus::Unknown; //!< State of the prediction.
|
||||
Pose pose = {}; //!< The predicted pose.
|
||||
};
|
||||
|
||||
//! Source for tracking data. Converts paths to poses at predicted times.
|
||||
//! \par The following paths are compulsory and must be supported by the implementation.
|
||||
//! - /user/head/input/pose
|
||||
//! - /user/hand/left/input/aim/pose
|
||||
//! - /user/hand/right/input/aim/pose
|
||||
//! - /user/hand/left/input/grip/pose (Not actually implemented yet)
|
||||
//! - /user/hand/right/input/grip/pose (Not actually implemented yet)
|
||||
//! \note A path being *supported* does not guarantee tracking data will be available at any given time (or ever).
|
||||
//! \note Implementations may expand this list.
|
||||
//! \sa OpenXRTracker VRGUITracking OpenXRTrackingToWorldBinding
|
||||
class VRTrackingSource
|
||||
{
|
||||
public:
|
||||
VRTrackingSource(const std::string& name);
|
||||
virtual ~VRTrackingSource();
|
||||
|
||||
//! @brief Predicted pose of the given path at the predicted time
|
||||
//!
|
||||
//! \arg predictedDisplayTime[in] Time to predict. This is normally the predicted display time.
|
||||
//! \arg path[in] path of the pose requested. Should match an available pose path.
|
||||
//! \arg reference[in] path of the pose to use as reference. If 0, pose is referenced to the VR stage.
|
||||
//!
|
||||
//! \return A structure describing a pose and the tracking status.
|
||||
virtual VRTrackingPose getTrackingPose(DisplayTime predictedDisplayTime, VRPath path, VRPath reference = 0) = 0;
|
||||
|
||||
//! List currently supported tracking paths.
|
||||
virtual std::vector<VRPath> listSupportedTrackingPosePaths() const = 0;
|
||||
|
||||
//! Returns true if the available poses changed since the last frame, false otherwise.
|
||||
bool availablePosesChanged() const;
|
||||
|
||||
void clearAvailablePosesChanged();
|
||||
|
||||
//! Call once per frame, after (or at the end of) OSG update traversals and before cull traversals.
|
||||
//! Predict tracked poses for the given display time.
|
||||
//! \arg predictedDisplayTime [in] the predicted display time. The pose shall be predicted for this time based on current tracking data.
|
||||
virtual void updateTracking(DisplayTime predictedDisplayTime) = 0;
|
||||
|
||||
protected:
|
||||
void notifyAvailablePosesChanged();
|
||||
|
||||
bool mAvailablePosesChanged = true;
|
||||
};
|
||||
|
||||
//! Ties a tracking source to the game world.
|
||||
//! A reference pose is selected by passing its path to the constructor.
|
||||
//! All poses are transformed in the horizontal plane by moving the x,y origin to the position of the reference pose, and then reoriented using the current orientation of the player character.
|
||||
//! The reference pose is effectively always at the x,y origin, and its movement is accumulated and can be read using the movement() call.
|
||||
//! If this movement is ever consumed (such as by moving the character to follow the player) the consumed movement must be reported using consumeMovement().
|
||||
class VRTrackingToWorldBinding : public VRTrackingSource
|
||||
{
|
||||
public:
|
||||
VRTrackingToWorldBinding(const std::string& name, VRTrackingSource* source, VRPath reference);
|
||||
|
||||
void setWorldOrientation(float yaw, bool adjust);
|
||||
osg::Quat getWorldOrientation() const { return mOrientation; }
|
||||
|
||||
void setEyeLevel(float eyeLevel) { mEyeLevel = eyeLevel; }
|
||||
float getEyeLevel() const { return mEyeLevel; }
|
||||
|
||||
void setSeatedPlay(bool seatedPlay) { mSeatedPlay = seatedPlay; }
|
||||
bool getSeatedPlay() const { return mSeatedPlay; }
|
||||
|
||||
//! The player's movement within the VR stage. This accumulates until the movement has been consumed by calling consumeMovement()
|
||||
osg::Vec3 movement() const;
|
||||
|
||||
//! Consume movement
|
||||
void consumeMovement(const osg::Vec3& movement);
|
||||
|
||||
//! Recenter tracking by consuming all movement.
|
||||
void recenter(bool resetZ);
|
||||
|
||||
//! World origin is the point that ties the stage and the world. (0,0,0 in the world-aligned stage is this node).
|
||||
//! If no node is set, the world-aligned stage and the world correspond 1-1.
|
||||
void setOriginNode(osg::Node* origin) { mOrigin = origin; }
|
||||
|
||||
protected:
|
||||
//! Fetches a pose from the source, and then aligns it with the game world if the reference is 0 (stage).
|
||||
VRTrackingPose getTrackingPose(DisplayTime predictedDisplayTime, VRPath path, VRPath movementReference = 0) override;
|
||||
|
||||
//! List currently supported tracking paths.
|
||||
std::vector<VRPath> listSupportedTrackingPosePaths() const override;
|
||||
|
||||
//! Call once per frame, after (or at the end of) OSG update traversals and before cull traversals.
|
||||
//! Predict tracked poses for the given display time.
|
||||
//! \arg predictedDisplayTime [in] the predicted display time. The pose shall be predicted for this time based on current tracking data.
|
||||
void updateTracking(DisplayTime predictedDisplayTime) override;
|
||||
|
||||
private:
|
||||
VRPath mMovementReference;
|
||||
VRTrackingSource* mSource;
|
||||
osg::Node* mOrigin = nullptr;
|
||||
bool mSeatedPlay = false;
|
||||
bool mHasTrackingData = false;
|
||||
float mEyeLevel = 0;
|
||||
Pose mOriginWorldPose = Pose();
|
||||
Pose mLastPose = Pose();
|
||||
osg::Vec3 mMovement = osg::Vec3(0, 0, 0);
|
||||
osg::Quat mOrientation = osg::Quat(0, 0, 0, 1);
|
||||
};
|
||||
|
||||
class VRTrackingListener
|
||||
{
|
||||
public:
|
||||
virtual ~VRTrackingListener();
|
||||
|
||||
//! Notify that available tracking poses have changed.
|
||||
virtual void onAvailablePosesChanged(VRTrackingSource& source) {};
|
||||
|
||||
//! Notify that a tracking source has been attached
|
||||
virtual void onTrackingAttached(VRTrackingSource& source) {};
|
||||
|
||||
//! Notify that a tracking source has been detached.
|
||||
virtual void onTrackingDetached() {};
|
||||
|
||||
//! Called every frame after tracking poses have been updated
|
||||
virtual void onTrackingUpdated(VRTrackingSource& source, DisplayTime predictedDisplayTime) {};
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class VRTrackingManager
|
||||
{
|
||||
public:
|
||||
VRTrackingManager();
|
||||
~VRTrackingManager();
|
||||
|
||||
//! Angles to be used for overriding movement direction
|
||||
//void movementAngles(float& yaw, float& pitch);
|
||||
|
||||
void updateTracking();
|
||||
|
||||
//! Bind listener to source, listener will receive tracking updates from source until unbound.
|
||||
//! \note A single listener can only receive tracking updates from one source.
|
||||
void bind(VRTrackingListener* listener, std::string source);
|
||||
|
||||
//! Unbind listener, listener will no longer receive tracking updates.
|
||||
void unbind(VRTrackingListener* listener);
|
||||
|
||||
//! Converts a string representation of a path to a VRTrackerPath identifier
|
||||
VRPath stringToVRPath(const std::string& path);
|
||||
|
||||
//! Converts a path identifier back to string. Returns an empty string if no such identifier exists.
|
||||
std::string VRPathToString(VRPath path);
|
||||
|
||||
//! Get a tracking source by name
|
||||
VRTrackingSource* getSource(const std::string& name);
|
||||
|
||||
//! Angles to be used for overriding movement direction
|
||||
void movementAngles(float& yaw, float& pitch);
|
||||
|
||||
void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed);
|
||||
|
||||
private:
|
||||
friend class VRTrackingSource;
|
||||
void registerTrackingSource(VRTrackingSource* source, const std::string& name);
|
||||
void unregisterTrackingSource(VRTrackingSource* source);
|
||||
void notifySourceChanged(const std::string& name);
|
||||
void updateMovementAngles(DisplayTime predictedDisplayTime);
|
||||
|
||||
std::map<std::string, VRTrackingSource*> mSources;
|
||||
std::map<VRTrackingListener*, std::string> mBindings;
|
||||
std::map<std::string, VRPath> mPathIdentifiers;
|
||||
|
||||
bool mHandDirectedMovement = 0.f;
|
||||
VRPath mHeadPath = 0;
|
||||
VRPath mHandPath = 0;
|
||||
float mMovementYaw = 0.f;
|
||||
float mMovementPitch = 0.f;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,138 +0,0 @@
|
||||
//#include "vrview.hpp"
|
||||
//
|
||||
//#include "openxrmanager.hpp"
|
||||
//#include "openxrmanagerimpl.hpp"
|
||||
//#include "vrsession.hpp"
|
||||
//#include "vrenvironment.hpp"
|
||||
//
|
||||
//#include <components/debug/debuglog.hpp>
|
||||
//
|
||||
//#include <osgViewer/Renderer>
|
||||
//
|
||||
//namespace MWVR {
|
||||
//
|
||||
// VRView::VRView(
|
||||
// std::string name,
|
||||
// SwapchainConfig config,
|
||||
// osg::ref_ptr<osg::State> state)
|
||||
// : mSwapchainConfig{ config }
|
||||
// , mSwapchain(new OpenXRSwapchain(state, mSwapchainConfig))
|
||||
// , mName(name)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// VRView::~VRView()
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// class CullCallback : public osg::NodeCallback
|
||||
// {
|
||||
// void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
// {
|
||||
// const auto& name = node->getName();
|
||||
// if (name == "LeftEye")
|
||||
// Environment::get().getSession()->beginPhase(VRSession::FramePhase::Cull);
|
||||
// traverse(node, nv);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// osg::Camera* VRView::createCamera(int order, const osg::Vec4& clearColor, osg::GraphicsContext* gc)
|
||||
// {
|
||||
// osg::ref_ptr<osg::Camera> camera = new osg::Camera();
|
||||
// camera->setClearColor(clearColor);
|
||||
// camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
// camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
// camera->setRenderOrder(osg::Camera::PRE_RENDER, order);
|
||||
// camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
// camera->setAllowEventFocus(false);
|
||||
// camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
// camera->setViewport(0, 0, mSwapchain->width(), mSwapchain->height());
|
||||
// camera->setGraphicsContext(gc);
|
||||
//
|
||||
// camera->setInitialDrawCallback(new VRView::InitialDrawCallback());
|
||||
// camera->setCullCallback(new CullCallback);
|
||||
//
|
||||
// return camera.release();
|
||||
// }
|
||||
//
|
||||
// void VRView::prerenderCallback(osg::RenderInfo& renderInfo)
|
||||
// {
|
||||
// if(Environment::get().getSession()->getFrame(VRSession::FramePhase::Draw)->mShouldRender)
|
||||
// mSwapchain->beginFrame(renderInfo.getState()->getGraphicsContext());
|
||||
// }
|
||||
//
|
||||
// void VRView::InitialDrawCallback::operator()(osg::RenderInfo& renderInfo) const
|
||||
// {
|
||||
// const auto& name = renderInfo.getCurrentCamera()->getName();
|
||||
// if (name == "LeftEye")
|
||||
// Environment::get().getSession()->beginPhase(VRSession::FramePhase::Draw);
|
||||
//
|
||||
// osg::GraphicsOperation* graphicsOperation = renderInfo.getCurrentCamera()->getRenderer();
|
||||
// osgViewer::Renderer* renderer = dynamic_cast<osgViewer::Renderer*>(graphicsOperation);
|
||||
// if (renderer != nullptr)
|
||||
// {
|
||||
// // Disable normal OSG FBO camera setup
|
||||
// renderer->setCameraRequiresSetUp(false);
|
||||
// }
|
||||
// }
|
||||
// void VRView::UpdateSlaveCallback::updateSlave(
|
||||
// osg::View& view,
|
||||
// osg::View::Slave& slave)
|
||||
// {
|
||||
// mView->updateSlave(view, slave);
|
||||
// }
|
||||
//
|
||||
// void VRView::postrenderCallback(osg::RenderInfo& renderInfo)
|
||||
// {
|
||||
// auto name = renderInfo.getCurrentCamera()->getName();
|
||||
// }
|
||||
//
|
||||
// void VRView::swapBuffers(osg::GraphicsContext* gc)
|
||||
// {
|
||||
// mSwapchain->endFrame(gc);
|
||||
// }
|
||||
// void VRView::updateSlave(osg::View& view, osg::View::Slave& slave)
|
||||
// {
|
||||
// auto* camera = slave._camera.get();
|
||||
//
|
||||
// // Update current cached cull mask of camera if it is active
|
||||
// auto mask = camera->getCullMask();
|
||||
// if (mask == 0)
|
||||
// camera->setCullMask(mCullMask);
|
||||
// else
|
||||
// mCullMask = mask;
|
||||
//
|
||||
// // If the session is not active, we do not want to waste resources rendering frames.
|
||||
// if (Environment::get().getSession()->getFrame(VRSession::FramePhase::Update)->mShouldRender)
|
||||
// {
|
||||
// Side side = Side::RIGHT_SIDE;
|
||||
// if (mName == "LeftEye")
|
||||
// {
|
||||
//
|
||||
// Environment::get().getViewer()->vrShadow().updateShadowConfig(view);
|
||||
// side = Side::LEFT_SIDE;
|
||||
// }
|
||||
//
|
||||
// auto* session = Environment::get().getSession();
|
||||
// auto viewMatrix = view.getCamera()->getViewMatrix();
|
||||
//
|
||||
// // If the camera does not have a view, use the VR stage directly
|
||||
// bool useStage = !(viewMatrix.getTrans().length() > 0.01);
|
||||
//
|
||||
// // If the view matrix is still the identity matrix, conventions have to be swapped around.
|
||||
// bool swapConventions = viewMatrix.isIdentity();
|
||||
//
|
||||
// viewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Update, side, !useStage, !swapConventions);
|
||||
//
|
||||
// camera->setViewMatrix(viewMatrix);
|
||||
//
|
||||
// auto projectionMatrix = session->projectionMatrix(VRSession::FramePhase::Update, side);
|
||||
// camera->setProjectionMatrix(projectionMatrix);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// camera->setCullMask(0);
|
||||
// }
|
||||
// slave.updateSlaveImplementation(view);
|
||||
// }
|
||||
//}
|
@ -1,65 +0,0 @@
|
||||
//#ifndef MWVR_VRVIEW_H
|
||||
//#define MWVR_VRVIEW_H
|
||||
//
|
||||
//#include <cassert>
|
||||
//#include "openxrmanager.hpp"
|
||||
//#include "openxrswapchain.hpp"
|
||||
//
|
||||
//struct XrSwapchainSubImage;
|
||||
//
|
||||
//namespace MWVR
|
||||
//{
|
||||
// class VRViewer;
|
||||
//
|
||||
// /// \brief Manipulates a slave camera by replacing its framebuffer with one destined for openxr
|
||||
// class VRView : public osg::Referenced
|
||||
// {
|
||||
// public:
|
||||
//
|
||||
// class InitialDrawCallback : public osg::Camera::DrawCallback
|
||||
// {
|
||||
// public:
|
||||
// virtual void operator()(osg::RenderInfo& renderInfo) const;
|
||||
// };
|
||||
//
|
||||
// class UpdateSlaveCallback : public osg::View::Slave::UpdateSlaveCallback
|
||||
// {
|
||||
// public:
|
||||
// UpdateSlaveCallback(osg::ref_ptr<VRView> view) : mView(view) {}
|
||||
// void updateSlave(osg::View& view, osg::View::Slave& slave) override;
|
||||
//
|
||||
// private:
|
||||
// osg::ref_ptr<VRView> mView;
|
||||
// };
|
||||
//
|
||||
// public:
|
||||
// VRView(std::string name, SwapchainConfig config, osg::ref_ptr<osg::State> state);
|
||||
// virtual ~VRView();
|
||||
//
|
||||
// public:
|
||||
// //! Prepare for render (set FBO)
|
||||
// virtual void prerenderCallback(osg::RenderInfo& renderInfo);
|
||||
//
|
||||
// //! Finalize render
|
||||
// virtual void postrenderCallback(osg::RenderInfo& renderInfo);
|
||||
//
|
||||
// //! Create camera for this view
|
||||
// osg::Camera* createCamera(int order, const osg::Vec4& clearColor, osg::GraphicsContext* gc);
|
||||
//
|
||||
// //! Get the view surface
|
||||
// OpenXRSwapchain& swapchain(void) { return *mSwapchain; }
|
||||
//
|
||||
// //! Present to the openxr swapchain
|
||||
// void swapBuffers(osg::GraphicsContext* gc);
|
||||
//
|
||||
// void updateSlave(osg::View& view, osg::View::Slave& slave);
|
||||
// public:
|
||||
// SwapchainConfig mSwapchainConfig;
|
||||
// std::unique_ptr<OpenXRSwapchain> mSwapchain;
|
||||
// std::string mName{};
|
||||
// osg::Node::NodeMask mCullMask;
|
||||
// bool mRendering{ false };
|
||||
// };
|
||||
//}
|
||||
//
|
||||
//#endif
|
Loading…
Reference in New Issue