1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 23:19:56 +00:00

More refactoring/cleanup

This commit is contained in:
Mads Buvik Sandvei 2020-06-24 21:26:11 +02:00
parent 1cf97fd7ad
commit df45ee1690
19 changed files with 253 additions and 230 deletions

View file

@ -32,7 +32,7 @@ bool OpenXRAction::getFloat(XrPath subactionPath, float& value)
getInfo.subactionPath = subactionPath;
XrActionStateFloat xrValue{ XR_TYPE_ACTION_STATE_FLOAT };
CHECK_XRCMD(xrGetActionStateFloat(xr->impl().mSession, &getInfo, &xrValue));
CHECK_XRCMD(xrGetActionStateFloat(xr->impl().xrSession(), &getInfo, &xrValue));
if (xrValue.isActive)
value = xrValue.currentState;
@ -47,7 +47,7 @@ bool OpenXRAction::getBool(XrPath subactionPath, bool& value)
getInfo.subactionPath = subactionPath;
XrActionStateBoolean xrValue{ XR_TYPE_ACTION_STATE_BOOLEAN };
CHECK_XRCMD(xrGetActionStateBoolean(xr->impl().mSession, &getInfo, &xrValue));
CHECK_XRCMD(xrGetActionStateBoolean(xr->impl().xrSession(), &getInfo, &xrValue));
if (xrValue.isActive)
value = xrValue.currentState;
@ -63,7 +63,7 @@ bool OpenXRAction::getPoseIsActive(XrPath subactionPath)
getInfo.subactionPath = subactionPath;
XrActionStatePose xrValue{ XR_TYPE_ACTION_STATE_POSE };
CHECK_XRCMD(xrGetActionStatePose(xr->impl().mSession, &getInfo, &xrValue));
CHECK_XRCMD(xrGetActionStatePose(xr->impl().xrSession(), &getInfo, &xrValue));
return xrValue.isActive;
}
@ -81,7 +81,7 @@ bool OpenXRAction::applyHaptics(XrPath subactionPath, float amplitude)
XrHapticActionInfo hapticActionInfo{ XR_TYPE_HAPTIC_ACTION_INFO };
hapticActionInfo.action = mAction;
hapticActionInfo.subactionPath = subactionPath;
CHECK_XRCMD(xrApplyHapticFeedback(xr->impl().mSession, &hapticActionInfo, (XrHapticBaseHeader*)&vibration));
CHECK_XRCMD(xrApplyHapticFeedback(xr->impl().xrSession(), &hapticActionInfo, (XrHapticBaseHeader*)&vibration));
return true;
}
}

View file

@ -103,7 +103,7 @@ OpenXRInput::OpenXRInput(const std::vector<SuggestedBindings>& suggestedBindings
XrSessionActionSetsAttachInfo attachInfo{ XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO };
attachInfo.countActionSets = 1;
attachInfo.actionSets = &mActionSet;
CHECK_XRCMD(xrAttachSessionActionSets(xr->impl().mSession, &attachInfo));
CHECK_XRCMD(xrAttachSessionActionSets(xr->impl().xrSession(), &attachInfo));
}
};
@ -144,7 +144,7 @@ OpenXRInput::createActionSet()
strcpy_s(createInfo.actionSetName, "gameplay");
strcpy_s(createInfo.localizedActionSetName, "Gameplay");
createInfo.priority = 0;
CHECK_XRCMD(xrCreateActionSet(xr->impl().mInstance, &createInfo, &actionSet));
CHECK_XRCMD(xrCreateActionSet(xr->impl().xrInstance(), &createInfo, &actionSet));
return actionSet;
}
@ -153,7 +153,7 @@ void OpenXRInput::suggestBindings(const SuggestedBindings& mwSuggestedBindings)
auto* xr = Environment::get().getManager();
XrPath oculusTouchInteractionProfilePath;
CHECK_XRCMD(
xrStringToPath(xr->impl().mInstance, mwSuggestedBindings.controllerPath.c_str(), &oculusTouchInteractionProfilePath));
xrStringToPath(xr->impl().xrInstance(), mwSuggestedBindings.controllerPath.c_str(), &oculusTouchInteractionProfilePath));
std::vector<XrActionSuggestedBinding> suggestedBindings =
{
@ -178,7 +178,7 @@ void OpenXRInput::suggestBindings(const SuggestedBindings& mwSuggestedBindings)
xrSuggestedBindings.interactionProfile = oculusTouchInteractionProfilePath;
xrSuggestedBindings.suggestedBindings = suggestedBindings.data();
xrSuggestedBindings.countSuggestedBindings = (uint32_t)suggestedBindings.size();
CHECK_XRCMD(xrSuggestInteractionProfileBindings(xr->impl().mInstance, &xrSuggestedBindings));
CHECK_XRCMD(xrSuggestInteractionProfileBindings(xr->impl().xrInstance(), &xrSuggestedBindings));
}
void
@ -192,8 +192,8 @@ OpenXRInput::generateControllerActionPaths(
std::string left = std::string("/user/hand/left") + controllerAction;
std::string right = std::string("/user/hand/right") + controllerAction;
CHECK_XRCMD(xrStringToPath(xr->impl().mInstance, left.c_str(), &actionPaths[(int)Side::LEFT_SIDE]));
CHECK_XRCMD(xrStringToPath(xr->impl().mInstance, right.c_str(), &actionPaths[(int)Side::RIGHT_SIDE]));
CHECK_XRCMD(xrStringToPath(xr->impl().xrInstance(), left.c_str(), &actionPaths[(int)Side::LEFT_SIDE]));
CHECK_XRCMD(xrStringToPath(xr->impl().xrInstance(), right.c_str(), &actionPaths[(int)Side::RIGHT_SIDE]));
mPathMap[actionPath] = actionPaths;
}
@ -221,7 +221,7 @@ void
OpenXRInput::updateControls()
{
auto* xr = Environment::get().getManager();
if (!xr->impl().mSessionRunning)
if (!xr->impl().xrSessionRunning())
return;
@ -229,7 +229,7 @@ OpenXRInput::updateControls()
XrActionsSyncInfo syncInfo{ XR_TYPE_ACTIONS_SYNC_INFO };
syncInfo.countActiveActionSets = 1;
syncInfo.activeActionSets = &activeActionSet;
CHECK_XRCMD(xrSyncActions(xr->impl().mSession, &syncInfo));
CHECK_XRCMD(xrSyncActions(xr->impl().xrSession(), &syncInfo));
// Note on update order:
@ -246,7 +246,7 @@ XrPath OpenXRInput::generateXrPath(const std::string& path)
{
auto* xr = Environment::get().getManager();
XrPath xrpath = 0;
CHECK_XRCMD(xrStringToPath(xr->impl().mInstance, path.c_str(), &xrpath));
CHECK_XRCMD(xrStringToPath(xr->impl().xrInstance(), path.c_str(), &xrpath));
return xrpath;
}

View file

@ -40,10 +40,10 @@ namespace MWVR
return !!mPrivate;
}
bool OpenXRManager::sessionRunning()
bool OpenXRManager::xrSessionRunning()
{
if (realized())
return impl().mSessionRunning;
return impl().xrSessionRunning();
return false;
}
@ -71,12 +71,6 @@ namespace MWVR
return impl().endFrame(displayTime, layerCount, layerStack);
}
void OpenXRManager::updateControls()
{
if (realized())
return impl().updateControls();
}
void
OpenXRManager::realize(
osg::GraphicsContext* gc)
@ -97,13 +91,6 @@ namespace MWVR
}
}
int OpenXRManager::eyes()
{
if (realized())
return impl().eyes();
return 0;
}
void OpenXRManager::enablePredictions()
{
return impl().enablePredictions();
@ -114,21 +101,31 @@ namespace MWVR
return impl().disablePredictions();
}
std::array<View, 2> OpenXRManager::getPredictedViews(int64_t predictedDisplayTime, TrackedSpace space)
std::array<View, 2> OpenXRManager::getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space)
{
return impl().getPredictedViews(predictedDisplayTime, space);
}
MWVR::Pose OpenXRManager::getPredictedHeadPose(int64_t predictedDisplayTime, TrackedSpace space)
MWVR::Pose OpenXRManager::getPredictedHeadPose(int64_t predictedDisplayTime, ReferenceSpace space)
{
return impl().getPredictedHeadPose(predictedDisplayTime, space);
}
long long OpenXRManager::getLastPredictedDisplayTime()
{
return impl().getLastPredictedDisplayTime();
}
long long OpenXRManager::getLastPredictedDisplayPeriod()
{
return impl().getLastPredictedDisplayPeriod();
}
std::array<SwapchainConfig, 2> OpenXRManager::getRecommendedSwapchainConfig() const
{
return impl().getRecommendedSwapchainConfig();
}
void
OpenXRManager::RealizeOperation::operator()(
osg::GraphicsContext* gc)

View file

@ -53,26 +53,47 @@ namespace MWVR
bool realized();
long long frameIndex();
bool sessionRunning();
void handleEvents();
//! Forward call to xrWaitFrame()
void waitFrame();
void beginFrame();
void endFrame(int64_t displayTime, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack);
void updateControls();
//! Forward call to xrBeginFrame()
void beginFrame();
//! Forward call to xrEndFrame()
void endFrame(int64_t displayTime, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack);
//! Whether the openxr session is currently in a running state
bool xrSessionRunning();
//! Process all openxr events
void handleEvents();
//! Instantiate implementation
void realize(osg::GraphicsContext* gc);
int eyes();
//! Enable pose predictions. Exist to police that predictions are never made out of turn.
void enablePredictions();
//! Disable pose predictions.
void disablePredictions();
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, TrackedSpace space);
MWVR::Pose getPredictedHeadPose(int64_t predictedDisplayTime, TrackedSpace space);
//! Get poses and fov of both eyes at the predicted time, relative to the given reference space. \note Will throw if predictions are disabled.
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space);
//! Get the pose of the player's head at the predicted time, relative to the given reference space. \note Will throw if predictions are disabled.
MWVR::Pose getPredictedHeadPose(int64_t predictedDisplayTime, ReferenceSpace space);
//! Last predicted display time returned from xrWaitFrame();
long long getLastPredictedDisplayTime();
//! Last predicted display period returned from xrWaitFrame();
long long getLastPredictedDisplayPeriod();
//! Configuration hints for instantiating swapchains, queried from openxr.
std::array<SwapchainConfig, 2> getRecommendedSwapchainConfig() const;
OpenXRManagerImpl& impl() { return *mPrivate; }
const OpenXRManagerImpl& impl() const { return *mPrivate; }
private:
std::shared_ptr<OpenXRManagerImpl> mPrivate;

View file

@ -1,5 +1,5 @@
#include "openxrmanagerimpl.hpp"
#include "openxrswapchain.hpp"
#include "openxrswapchainimpl.hpp"
#include "vrtexture.hpp"
#include <components/debug/debuglog.hpp>
@ -173,6 +173,11 @@ namespace MWVR
return res;
}
std::string XrResultString(XrResult res)
{
return to_string(res);
}
OpenXRManagerImpl::~OpenXRManagerImpl()
{
@ -259,12 +264,6 @@ namespace MWVR
Log(Debug::Verbose) << ss.str();
}
XrFrameState OpenXRManagerImpl::frameState()
{
std::unique_lock<std::mutex> lock(mFrameStateMutex);
return mFrameState;
}
void
OpenXRManagerImpl::waitFrame()
{
@ -294,7 +293,7 @@ namespace MWVR
{
XrCompositionLayerProjectionView xrLayer;
xrLayer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
xrLayer.subImage = layer.swapchain->subImage();
xrLayer.subImage = layer.swapchain->impl().xrSubImage();
xrLayer.pose = toXR(layer.pose);
xrLayer.fov = toXR(layer.fov);
xrLayer.next = nullptr;
@ -316,7 +315,7 @@ namespace MWVR
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE] = toXR(layerStack[(int)Side::RIGHT_SIDE]);
XrCompositionLayerProjection layer{};
layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
layer.space = getReferenceSpace(TrackedSpace::STAGE);
layer.space = getReferenceSpace(ReferenceSpace::STAGE);
layer.viewCount = 2;
layer.views = compositionLayerProjectionViews.data();
auto* xrLayerStack = reinterpret_cast<XrCompositionLayerBaseHeader*>(&layer);
@ -334,7 +333,7 @@ namespace MWVR
std::array<View, 2>
OpenXRManagerImpl::getPredictedViews(
int64_t predictedDisplayTime,
TrackedSpace space)
ReferenceSpace space)
{
if (!mPredictionsEnabled)
{
@ -350,10 +349,10 @@ namespace MWVR
viewLocateInfo.displayTime = predictedDisplayTime;
switch (space)
{
case TrackedSpace::STAGE:
case ReferenceSpace::STAGE:
viewLocateInfo.space = mReferenceSpaceStage;
break;
case TrackedSpace::VIEW:
case ReferenceSpace::VIEW:
viewLocateInfo.space = mReferenceSpaceView;
break;
}
@ -369,7 +368,7 @@ namespace MWVR
MWVR::Pose OpenXRManagerImpl::getPredictedHeadPose(
int64_t predictedDisplayTime,
TrackedSpace space)
ReferenceSpace space)
{
if (!mPredictionsEnabled)
{
@ -382,10 +381,10 @@ namespace MWVR
switch (space)
{
case TrackedSpace::STAGE:
case ReferenceSpace::STAGE:
referenceSpace = mReferenceSpaceStage;
break;
case TrackedSpace::VIEW:
case ReferenceSpace::VIEW:
referenceSpace = mReferenceSpaceView;
break;
}
@ -398,16 +397,11 @@ namespace MWVR
location.pose.orientation.w = 1;
}
return MWVR::Pose{
osg::fromXR(location.pose.position),
osg::fromXR(location.pose.orientation)
fromXR(location.pose.position),
fromXR(location.pose.orientation)
};
}
int OpenXRManagerImpl::eyes()
{
return mConfigViews.size();
}
void OpenXRManagerImpl::handleEvents()
{
std::unique_lock<std::mutex> lock(mEventMutex);
@ -435,9 +429,6 @@ namespace MWVR
}
}
void OpenXRManagerImpl::updateControls()
{
}
void
OpenXRManagerImpl::HandleSessionStateChanged(
const XrEventDataSessionStateChanged& stateChangedEvent)
@ -495,12 +486,12 @@ namespace MWVR
MWVR::Pose fromXR(XrPosef pose)
{
return MWVR::Pose{ osg::fromXR(pose.position), osg::fromXR(pose.orientation) };
return MWVR::Pose{ fromXR(pose.position), fromXR(pose.orientation) };
}
XrPosef toXR(MWVR::Pose pose)
{
return XrPosef{ osg::toXR(pose.orientation), osg::toXR(pose.position) };
return XrPosef{ toXR(pose.orientation), toXR(pose.position) };
}
MWVR::FieldOfView fromXR(XrFovf fov)
@ -513,12 +504,12 @@ namespace MWVR
return XrFovf{ fov.angleLeft, fov.angleRight, fov.angleUp, fov.angleDown };
}
XrSpace OpenXRManagerImpl::getReferenceSpace(TrackedSpace space)
XrSpace OpenXRManagerImpl::getReferenceSpace(ReferenceSpace space)
{
XrSpace referenceSpace = XR_NULL_HANDLE;
if (space == TrackedSpace::STAGE)
if (space == ReferenceSpace::STAGE)
referenceSpace = mReferenceSpaceStage;
if (space == TrackedSpace::VIEW)
if (space == ReferenceSpace::VIEW)
referenceSpace = mReferenceSpaceView;
return referenceSpace;
}
@ -533,32 +524,48 @@ namespace MWVR
mPredictionsEnabled = false;
}
long long OpenXRManagerImpl::getLastPredictedDisplayTime()
{
return mFrameState.predictedDisplayTime;
}
long long OpenXRManagerImpl::getLastPredictedDisplayPeriod()
{
return mFrameState.predictedDisplayPeriod;
}
std::array<SwapchainConfig, 2> OpenXRManagerImpl::getRecommendedSwapchainConfig() const
{
std::array<SwapchainConfig, 2> config{};
for (uint32_t i = 0; i < 2; i++)
config[i] = SwapchainConfig{
mConfigViews[i].recommendedImageRectWidth,
mConfigViews[i].maxImageRectWidth,
mConfigViews[i].recommendedImageRectHeight,
mConfigViews[i].maxImageRectHeight,
mConfigViews[i].recommendedSwapchainSampleCount,
mConfigViews[i].recommendedSwapchainSampleCount,
};
return config;
}
namespace osg
osg::Vec3 fromXR(XrVector3f v)
{
Vec3 fromXR(XrVector3f v)
{
return Vec3{ v.x, -v.z, v.y };
return osg::Vec3{ v.x, -v.z, v.y };
}
Quat fromXR(XrQuaternionf quat)
osg::Quat fromXR(XrQuaternionf quat)
{
return Quat{ quat.x, -quat.z, quat.y, quat.w };
return osg::Quat{ quat.x, -quat.z, quat.y, quat.w };
}
XrVector3f toXR(Vec3 v)
XrVector3f toXR(osg::Vec3 v)
{
return XrVector3f{ v.x(), v.z(), -v.y() };
}
XrQuaternionf toXR(Quat quat)
XrQuaternionf toXR(osg::Quat quat)
{
return XrQuaternionf{ quat.x(), quat.z(), -quat.y(), quat.w() };
}
}

View file

@ -22,27 +22,29 @@
#include <thread>
#include <chrono>
namespace osg {
Vec3 fromXR(XrVector3f);
Quat fromXR(XrQuaternionf quat);
XrVector3f toXR(Vec3 v);
XrQuaternionf toXR(Quat quat);
}
namespace MWVR
{
// Error management macros and functions. Should be used on every openxr call.
#define CHK_STRINGIFY(x) #x
#define TOSTRING(x) CHK_STRINGIFY(x)
#define FILE_AND_LINE __FILE__ ":" TOSTRING(__LINE__)
#define CHECK_XRCMD(cmd) CheckXrResult(cmd, #cmd, FILE_AND_LINE);
#define CHECK_XRRESULT(res, cmdStr) CheckXrResult(res, cmdStr, FILE_AND_LINE);
XrResult CheckXrResult(XrResult res, const char* originator = nullptr, const char* sourceLocation = nullptr);
std::string XrResultString(XrResult res);
/// Conversion methods from openxr types to osg/mwvr types. Includes managing the differing conventions.
MWVR::Pose fromXR(XrPosef pose);
XrPosef toXR(MWVR::Pose pose);
MWVR::FieldOfView fromXR(XrFovf fov);
osg::Vec3 fromXR(XrVector3f);
osg::Quat fromXR(XrQuaternionf quat);
/// Conversion methods from osg/mwvr types to openxr types. Includes managing the differing conventions.
XrPosef toXR(MWVR::Pose pose);
XrFovf toXR(MWVR::FieldOfView fov);
XrVector3f toXR(osg::Vec3 v);
XrQuaternionf toXR(osg::Quat quat);
XrCompositionLayerProjectionView toXR(MWVR::CompositionLayerProjectionView layer);
@ -51,26 +53,30 @@ namespace MWVR
OpenXRManagerImpl(void);
~OpenXRManagerImpl(void);
void LogLayersAndExtensions();
void LogInstanceInfo();
void LogReferenceSpaces();
const XrEventDataBaseHeader* nextEvent();
void waitFrame();
void beginFrame();
void endFrame(int64_t displayTime, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack);
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, TrackedSpace space);
MWVR::Pose getPredictedHeadPose(int64_t predictedDisplayTime, TrackedSpace space);
int eyes();
bool xrSessionRunning() const { return mSessionRunning; }
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space);
MWVR::Pose getPredictedHeadPose(int64_t predictedDisplayTime, ReferenceSpace space);
void handleEvents();
void updateControls();
void HandleSessionStateChanged(const XrEventDataSessionStateChanged& stateChangedEvent);
XrFrameState frameState();
XrSpace getReferenceSpace(TrackedSpace space);
void enablePredictions();
void disablePredictions();
long long getLastPredictedDisplayTime();
long long getLastPredictedDisplayPeriod();
std::array<SwapchainConfig, 2> getRecommendedSwapchainConfig() const;
XrSpace getReferenceSpace(ReferenceSpace space);
XrSession xrSession() const { return mSession; };
XrInstance xrInstance() const { return mInstance; };
protected:
void LogLayersAndExtensions();
void LogInstanceInfo();
void LogReferenceSpaces();
const XrEventDataBaseHeader* nextEvent();
void HandleSessionStateChanged(const XrEventDataSessionStateChanged& stateChangedEvent);
private:
bool initialized = false;
bool mPredictionsEnabled = false;
XrInstance mInstance = XR_NULL_HANDLE;
@ -91,12 +97,6 @@ namespace MWVR
bool mSessionRunning = false;
std::mutex mFrameStateMutex{};
std::mutex mEventMutex{};
XrActionSet mActionSet = nullptr;
XrAction mHandPoseAction = nullptr;
XrSpace mHandSpaces[2]{ nullptr, nullptr };
XrPath mSubactionPaths[2]{ 0, 0 };
XrPath mPosePath[2]{ 0, 0 };
};
}

View file

@ -24,7 +24,7 @@ namespace MWVR {
SUBVIEW_MAX = RIGHT_VIEW, //!< Used to size subview arrays. Not a valid input.
};
OpenXRSwapchainImpl(osg::ref_ptr<osg::State> state, OpenXRSwapchain::Config config);
OpenXRSwapchainImpl(osg::ref_ptr<osg::State> state, SwapchainConfig config);
~OpenXRSwapchainImpl();
void beginFrame(osg::GraphicsContext* gc);
@ -53,10 +53,10 @@ namespace MWVR {
bool mIsAcquired{ false };
};
OpenXRSwapchainImpl::OpenXRSwapchainImpl(osg::ref_ptr<osg::State> state, OpenXRSwapchain::Config config)
: mWidth(config.width)
, mHeight(config.height)
, mSamples(config.samples)
OpenXRSwapchainImpl::OpenXRSwapchainImpl(osg::ref_ptr<osg::State> state, SwapchainConfig config)
: mWidth(config.recommendedWidth)
, mHeight(config.recommendedHeight)
, mSamples(config.recommendedSamples)
{
if (mWidth <= 0)
throw std::invalid_argument("Width must be a positive integer");
@ -69,9 +69,9 @@ namespace MWVR {
// Select a swapchain format.
uint32_t swapchainFormatCount;
CHECK_XRCMD(xrEnumerateSwapchainFormats(xr->impl().mSession, 0, &swapchainFormatCount, nullptr));
CHECK_XRCMD(xrEnumerateSwapchainFormats(xr->impl().xrSession(), 0, &swapchainFormatCount, nullptr));
std::vector<int64_t> swapchainFormats(swapchainFormatCount);
CHECK_XRCMD(xrEnumerateSwapchainFormats(xr->impl().mSession, (uint32_t)swapchainFormats.size(), &swapchainFormatCount, swapchainFormats.data()));
CHECK_XRCMD(xrEnumerateSwapchainFormats(xr->impl().xrSession(), (uint32_t)swapchainFormats.size(), &swapchainFormatCount, swapchainFormats.data()));
// List of supported color swapchain formats.
constexpr int64_t SupportedColorSwapchainFormats[] = {
@ -100,7 +100,7 @@ namespace MWVR {
swapchainCreateInfo.faceCount = 1;
swapchainCreateInfo.sampleCount = mSamples;
swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
CHECK_XRCMD(xrCreateSwapchain(xr->impl().mSession, &swapchainCreateInfo, &mSwapchain));
CHECK_XRCMD(xrCreateSwapchain(xr->impl().xrSession(), &swapchainCreateInfo, &mSwapchain));
uint32_t imageCount = 0;
CHECK_XRCMD(xrEnumerateSwapchainImages(mSwapchain, 0, &imageCount, nullptr));
@ -176,7 +176,7 @@ namespace MWVR {
CHECK_XRCMD(xrReleaseSwapchainImage(mSwapchain, &releaseInfo));
}
OpenXRSwapchain::OpenXRSwapchain(osg::ref_ptr<osg::State> state, OpenXRSwapchain::Config config)
OpenXRSwapchain::OpenXRSwapchain(osg::ref_ptr<osg::State> state, SwapchainConfig config)
: mPrivate(new OpenXRSwapchainImpl(state, config))
{
}

View file

@ -21,7 +21,7 @@ namespace MWVR
};
public:
OpenXRSwapchain(osg::ref_ptr<osg::State> state, Config config);
OpenXRSwapchain(osg::ref_ptr<osg::State> state, SwapchainConfig config);
~OpenXRSwapchain();
public:

View file

@ -31,7 +31,7 @@ PoseAction::PoseAction(std::unique_ptr<OpenXRAction> xrAction)
createInfo.action = *mXRAction;
createInfo.poseInActionSpace.orientation.w = 1.f;
createInfo.subactionPath = XR_NULL_PATH;
CHECK_XRCMD(xrCreateActionSpace(xr->impl().mSession, &createInfo, &mXRSpace));
CHECK_XRCMD(xrCreateActionSpace(xr->impl().xrSession(), &createInfo, &mXRSpace));
}
void PoseAction::update(long long time)
@ -39,7 +39,7 @@ void PoseAction::update(long long time)
mPrevious = mValue;
auto* xr = Environment::get().getManager();
XrSpace referenceSpace = xr->impl().getReferenceSpace(TrackedSpace::STAGE);
XrSpace referenceSpace = xr->impl().getReferenceSpace(ReferenceSpace::STAGE);
XrSpaceLocation location{ XR_TYPE_SPACE_LOCATION };
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
@ -51,8 +51,8 @@ void PoseAction::update(long long time)
location.pose.orientation.w = 1;
mValue = Pose{
osg::fromXR(location.pose.position),
osg::fromXR(location.pose.orientation)
fromXR(location.pose.position),
fromXR(location.pose.orientation)
};
}

View file

@ -94,7 +94,7 @@ osg::Matrix VRSession::viewMatrix(FramePhase phase, Side side)
bool VRSession::isRunning() const {
auto* xr = Environment::get().getManager();
return xr->sessionRunning();
return xr->xrSessionRunning();
}
void VRSession::swapBuffers(osg::GraphicsContext* gc, VRViewer& viewer)
@ -254,13 +254,13 @@ void VRSession::prepareFrame()
PoseSet predictedPoses{};
xr->enablePredictions();
predictedPoses.head = xr->getPredictedHeadPose(predictedDisplayTime, TrackedSpace::STAGE) * mPlayerScale;
auto hmdViews = xr->getPredictedViews(predictedDisplayTime, TrackedSpace::VIEW);
predictedPoses.head = xr->getPredictedHeadPose(predictedDisplayTime, ReferenceSpace::STAGE) * mPlayerScale;
auto hmdViews = xr->getPredictedViews(predictedDisplayTime, ReferenceSpace::VIEW);
predictedPoses.view[(int)Side::LEFT_SIDE].pose = hmdViews[(int)Side::LEFT_SIDE].pose * mPlayerScale;
predictedPoses.view[(int)Side::RIGHT_SIDE].pose = hmdViews[(int)Side::RIGHT_SIDE].pose * mPlayerScale;
predictedPoses.view[(int)Side::LEFT_SIDE].fov = hmdViews[(int)Side::LEFT_SIDE].fov;
predictedPoses.view[(int)Side::RIGHT_SIDE].fov = hmdViews[(int)Side::RIGHT_SIDE].fov;
auto stageViews = xr->getPredictedViews(predictedDisplayTime, TrackedSpace::STAGE);
auto stageViews = xr->getPredictedViews(predictedDisplayTime, ReferenceSpace::STAGE);
predictedPoses.eye[(int)Side::LEFT_SIDE] = stageViews[(int)Side::LEFT_SIDE].pose * mPlayerScale;
predictedPoses.eye[(int)Side::RIGHT_SIDE] = stageViews[(int)Side::RIGHT_SIDE].pose * mPlayerScale;

View file

@ -17,6 +17,8 @@ namespace MWVR
extern void getEulerAngles(const osg::Quat& quat, float& yaw, float& pitch, float& roll);
//! Manages VR logic, such as managing frames, predicting their poses, and handling frame synchronization.
//! Should not be confused with the openxr session object.
class VRSession
{
public:

View file

@ -13,33 +13,32 @@
namespace MWVR
{
VRTexture::VRTexture(
osg::ref_ptr<osg::State> state,
std::size_t width,
std::size_t height,
uint32_t msaaSamples)
VRTexture::VRTexture(osg::ref_ptr<osg::State> state, std::size_t width, std::size_t height, uint32_t msaaSamples, uint32_t colorBuffer, uint32_t depthBuffer)
: mState(state)
, mWidth(width)
, mHeight(height)
, mSamples(msaaSamples)
, mColorBuffer(colorBuffer)
, mDepthBuffer(depthBuffer)
{
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
gl->glGenFramebuffers(1, &mBlitFBO);
gl->glBindFramebuffer(GL_FRAMEBUFFER_EXT, mBlitFBO);
gl->glGenFramebuffers(1, &mFBO);
glGenTextures(1, &mDepthBuffer);
glGenTextures(1, &mColorBuffer);
if (mSamples == 0)
if (mSamples <= 1)
mTextureTarget = GL_TEXTURE_2D;
else
mTextureTarget = GL_TEXTURE_2D_MULTISAMPLE;
if (mColorBuffer == 0)
{
glGenTextures(1, &mColorBuffer);
glBindTexture(mTextureTarget, mColorBuffer);
if (mSamples == 0)
if (mSamples <= 1)
glTexImage2D(mTextureTarget, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_INT, nullptr);
else
gl->glTexImage2DMultisample(mTextureTarget, mSamples, GL_RGBA, mWidth, mHeight, false);
@ -48,9 +47,13 @@ namespace MWVR
glTexParameteri(mTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(mTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(mTextureTarget, GL_TEXTURE_MAX_LEVEL, 0);
}
if (mDepthBuffer == 0)
{
glGenTextures(1, &mDepthBuffer);
glBindTexture(mTextureTarget, mDepthBuffer);
if (mSamples == 0)
if (mSamples <= 1)
glTexImage2D(mTextureTarget, 0, GL_DEPTH_COMPONENT24, mWidth, mHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
else
gl->glTexImage2DMultisample(mTextureTarget, mSamples, GL_DEPTH_COMPONENT, mWidth, mHeight, false);
@ -59,6 +62,7 @@ namespace MWVR
glTexParameteri(mTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(mTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(mTextureTarget, GL_TEXTURE_MAX_LEVEL, 0);
}
gl->glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFBO);

View file

@ -13,7 +13,7 @@ namespace MWVR
class VRTexture : public osg::Referenced
{
public:
VRTexture(osg::ref_ptr<osg::State> state, std::size_t width, std::size_t height, uint32_t msaaSamples);
VRTexture(osg::ref_ptr<osg::State> state, std::size_t width, std::size_t height, uint32_t msaaSamples, uint32_t colorBuffer = 0, uint32_t depthBuffer = 0);
~VRTexture();
void destroy(osg::State* state);

View file

@ -172,13 +172,13 @@ std::ostream& operator <<(
std::ostream& operator <<(
std::ostream& os,
TrackedSpace limb)
ReferenceSpace limb)
{
switch (limb)
{
case TrackedSpace::STAGE:
case ReferenceSpace::STAGE:
os << "STAGE"; break;
case TrackedSpace::VIEW:
case ReferenceSpace::VIEW:
os << "VIEW"; break;
}
return os;

View file

@ -24,7 +24,7 @@ enum class TrackedLimb
};
//! Describes what space to track the limb in
enum class TrackedSpace
enum class ReferenceSpace
{
STAGE = 0, //!< Track limb in the VR stage space. Meaning a space with a floor level origin and fixed horizontal orientation.
VIEW = 1 //!< Track limb in the VR view space. Meaning a space with the head as origin and orientation.
@ -58,7 +58,7 @@ struct Pose
bool operator==(const Pose& rhs) const;
};
//! Represents the field of view of an eye
//! Fov of a single eye
struct FieldOfView {
float angleLeft;
float angleRight;
@ -97,13 +97,23 @@ struct CompositionLayerProjectionView
FieldOfView fov;
};
struct SwapchainConfig
{
uint32_t recommendedWidth = -1;
uint32_t maxWidth = -1;
uint32_t recommendedHeight = -1;
uint32_t maxHeight = -1;
uint32_t recommendedSamples = -1;
uint32_t maxSamples = -1;
};
// Serialization methods for VR types.
std::ostream& operator <<(std::ostream& os, const Pose& pose);
std::ostream& operator <<(std::ostream& os, const FieldOfView& fov);
std::ostream& operator <<(std::ostream& os, const View& view);
std::ostream& operator <<(std::ostream& os, const PoseSet& poseSet);
std::ostream& operator <<(std::ostream& os, TrackedLimb limb);
std::ostream& operator <<(std::ostream& os, TrackedSpace space);
std::ostream& operator <<(std::ostream& os, ReferenceSpace space);
std::ostream& operator <<(std::ostream& os, Side side);
}

View file

@ -26,7 +26,7 @@ namespace MWVR {
VRView::VRView(
std::string name,
OpenXRSwapchain::Config config,
SwapchainConfig config,
osg::ref_ptr<osg::State> state)
: mSwapchainConfig{ config }
, mSwapchain(new OpenXRSwapchain(state, mSwapchainConfig))

View file

@ -36,7 +36,7 @@ namespace MWVR
};
public:
VRView(std::string name, OpenXRSwapchain::Config config, osg::ref_ptr<osg::State> state);
VRView(std::string name, SwapchainConfig config, osg::ref_ptr<osg::State> state);
virtual ~VRView();
public:
@ -52,7 +52,7 @@ namespace MWVR
void swapBuffers(osg::GraphicsContext* gc);
public:
OpenXRSwapchain::Config mSwapchainConfig;
SwapchainConfig mSwapchainConfig;
std::unique_ptr<OpenXRSwapchain> mSwapchain;
std::string mName{};
bool mRendering{ false };

View file

@ -67,17 +67,10 @@ namespace MWVR
xr->handleEvents();
OpenXRSwapchain::Config leftConfig;
leftConfig.width = xr->impl().mConfigViews[(int)Side::LEFT_SIDE].recommendedImageRectWidth;
leftConfig.height = xr->impl().mConfigViews[(int)Side::LEFT_SIDE].recommendedImageRectHeight;
leftConfig.samples = xr->impl().mConfigViews[(int)Side::LEFT_SIDE].recommendedSwapchainSampleCount;
OpenXRSwapchain::Config rightConfig;
rightConfig.width = xr->impl().mConfigViews[(int)Side::RIGHT_SIDE].recommendedImageRectWidth;
rightConfig.height = xr->impl().mConfigViews[(int)Side::RIGHT_SIDE].recommendedImageRectHeight;
rightConfig.samples = xr->impl().mConfigViews[(int)Side::RIGHT_SIDE].recommendedSwapchainSampleCount;
auto config = xr->getRecommendedSwapchainConfig();
auto leftView = new VRView("LeftEye", leftConfig, context->getState());
auto rightView = new VRView("RightEye", rightConfig, context->getState());
auto leftView = new VRView("LeftEye", config[(int)Side::LEFT_SIDE], context->getState());
auto rightView = new VRView("RightEye", config[(int)Side::RIGHT_SIDE], context->getState());
mViews["LeftEye"] = leftView;
mViews["RightEye"] = rightView;
@ -118,15 +111,7 @@ namespace MWVR
mViewer->setReleaseContextAtEndOfFrameHint(false);
OpenXRSwapchain::Config config;
config.width = mainCamera->getViewport()->width();
config.height = mainCamera->getViewport()->height();
config.samples = 1;
// Mirror texture doesn't have to be an OpenXR swapchain.
// It was just convenient at the time.
mMirrorTextureSwapchain.reset(new OpenXRSwapchain(context->getState(), config));
mMirrorTexture.reset(new VRTexture(context->getState(), mainCamera->getViewport()->width(), mainCamera->getViewport()->height(), 0));
mViewer->getSlave(0)._updateSlaveCallback = new VRView::UpdateSlaveCallback(leftView, context);
mViewer->getSlave(1)._updateSlaveCallback = new VRView::UpdateSlaveCallback(rightView, context);
@ -151,18 +136,16 @@ namespace MWVR
void VRViewer::blitEyesToMirrorTexture(osg::GraphicsContext* gc)
{
int mirror_width = mMirrorTextureSwapchain->width() / 2;
mMirrorTextureSwapchain->beginFrame(gc);
mViews["RightEye"]->swapchain().renderBuffer()->blit(gc, 0, 0, mirror_width, mMirrorTextureSwapchain->height());
mViews["LeftEye"]->swapchain().renderBuffer()->blit(gc, mirror_width, 0, 2 * mirror_width, mMirrorTextureSwapchain->height());
mMirrorTextureSwapchain->endFrame(gc);
auto* state = gc->getState();
auto* gl = osg::GLExtensions::Get(state->getContextID(), false);
int mirror_width = mMirrorTexture->width() / 2;
mMirrorTexture->beginFrame(gc);
mViews["RightEye"]->swapchain().renderBuffer()->blit(gc, 0, 0, mirror_width, mMirrorTexture->height());
mViews["LeftEye"]->swapchain().renderBuffer()->blit(gc, mirror_width, 0, 2 * mirror_width, mMirrorTexture->height());
gl->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
mMirrorTextureSwapchain->renderBuffer()->blit(gc, 0, 0, mMirrorTextureSwapchain->width(), mMirrorTextureSwapchain->height());
mMirrorTexture->blit(gc, 0, 0, mMirrorTexture->width(), mMirrorTexture->height());
}

View file

@ -91,8 +91,7 @@ namespace MWVR
osg::ref_ptr<PredrawCallback> mPreDraw{ nullptr };
osg::ref_ptr<PostdrawCallback> mPostDraw{ nullptr };
osg::GraphicsContext* mMainCameraGC{ nullptr };
std::unique_ptr<OpenXRSwapchain> mMirrorTextureSwapchain{ nullptr };
std::unique_ptr<VRTexture> mMirrorTexture{ nullptr };
std::mutex mMutex;