mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-10-05 08:56:40 +00:00
Fixed recentering adjusting the player's orientation. Cell changes should now retain the proper orientation. Added support for seated play.
This commit is contained in:
parent
7986def3db
commit
3347cdfe30
17 changed files with 186 additions and 98 deletions
|
@ -158,10 +158,10 @@ namespace MWPhysics
|
||||||
// But 2. is not so obvious. I guess it's doable if i compute the direction between current position and the player's
|
// But 2. is not so obvious. I guess it's doable if i compute the direction between current position and the player's
|
||||||
// position in the VR stage, and just let it catch up at the character's own move speed, but it still needs to reach the position as exactly as possible.
|
// position in the VR stage, and just let it catch up at the character's own move speed, but it still needs to reach the position as exactly as possible.
|
||||||
|
|
||||||
if (isPlayer)
|
|
||||||
{
|
|
||||||
auto* session = MWVR::Environment::get().getSession();
|
auto* session = MWVR::Environment::get().getSession();
|
||||||
if (session)
|
if (session)
|
||||||
|
{
|
||||||
|
if (isPlayer)
|
||||||
{
|
{
|
||||||
float pitch = 0.f;
|
float pitch = 0.f;
|
||||||
float yaw = 0.f;
|
float yaw = 0.f;
|
||||||
|
@ -238,10 +238,18 @@ namespace MWPhysics
|
||||||
|
|
||||||
#ifdef USE_OPENXR
|
#ifdef USE_OPENXR
|
||||||
// Catch the player character up to the real world position of the player.
|
// Catch the player character up to the real world position of the player.
|
||||||
|
// But only if play is not seated.
|
||||||
// TODO: Hack.
|
// TODO: Hack.
|
||||||
if (isPlayer && !world->getPlayer().isDisabled())
|
if (isPlayer)
|
||||||
{
|
{
|
||||||
|
bool shouldMove = true;
|
||||||
|
if (session && session->seatedPlay())
|
||||||
|
shouldMove = false;
|
||||||
|
if (world->getPlayer().isDisabled())
|
||||||
|
shouldMove = false;
|
||||||
|
|
||||||
|
if (shouldMove)
|
||||||
|
{
|
||||||
auto* inputManager = reinterpret_cast<MWVR::VRCamera*>(MWBase::Environment::get().getWorld()->getRenderingManager().getCamera());
|
auto* inputManager = reinterpret_cast<MWVR::VRCamera*>(MWBase::Environment::get().getWorld()->getRenderingManager().getCamera());
|
||||||
|
|
||||||
osg::Vec3 headOffset = inputManager->headOffset();
|
osg::Vec3 headOffset = inputManager->headOffset();
|
||||||
|
@ -314,6 +322,7 @@ namespace MWPhysics
|
||||||
headOffset.y() -= moved.y();
|
headOffset.y() -= moved.y();
|
||||||
inputManager->setHeadOffset(headOffset);
|
inputManager->setHeadOffset(headOffset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -90,8 +90,13 @@ namespace MWVR
|
||||||
CHECK_XRCMD(xrCreateReferenceSpace(mSession, &createInfo, &mReferenceSpaceView));
|
CHECK_XRCMD(xrCreateReferenceSpace(mSession, &createInfo, &mReferenceSpaceView));
|
||||||
createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
|
createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
|
||||||
CHECK_XRCMD(xrCreateReferenceSpace(mSession, &createInfo, &mReferenceSpaceStage));
|
CHECK_XRCMD(xrCreateReferenceSpace(mSession, &createInfo, &mReferenceSpaceStage));
|
||||||
|
createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||||
|
CHECK_XRCMD(xrCreateReferenceSpace(mSession, &createInfo, &mReferenceSpaceLocal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default to using the stage
|
||||||
|
mReferenceSpace = mReferenceSpaceStage;
|
||||||
|
|
||||||
{ // Read and log graphics properties for the swapchain
|
{ // Read and log graphics properties for the swapchain
|
||||||
xrGetSystemProperties(mInstance, mSystemId, &mSystemProperties);
|
xrGetSystemProperties(mInstance, mSystemId, &mSystemProperties);
|
||||||
|
|
||||||
|
@ -302,7 +307,7 @@ namespace MWVR
|
||||||
compositionLayerProjectionViews[(int)Side::LEFT_SIDE] = toXR((*layerStack)[(int)Side::LEFT_SIDE]);
|
compositionLayerProjectionViews[(int)Side::LEFT_SIDE] = toXR((*layerStack)[(int)Side::LEFT_SIDE]);
|
||||||
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE] = toXR((*layerStack)[(int)Side::RIGHT_SIDE]);
|
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE] = toXR((*layerStack)[(int)Side::RIGHT_SIDE]);
|
||||||
layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
||||||
layer.space = getReferenceSpace(ReferenceSpace::STAGE);
|
layer.space = getReferenceSpace();
|
||||||
layer.viewCount = 2;
|
layer.viewCount = 2;
|
||||||
layer.views = compositionLayerProjectionViews.data();
|
layer.views = compositionLayerProjectionViews.data();
|
||||||
auto* xrLayerStack = reinterpret_cast<XrCompositionLayerBaseHeader*>(&layer);
|
auto* xrLayerStack = reinterpret_cast<XrCompositionLayerBaseHeader*>(&layer);
|
||||||
|
@ -591,14 +596,9 @@ namespace MWVR
|
||||||
return XrFovf{ fov.angleLeft, fov.angleRight, fov.angleUp, fov.angleDown };
|
return XrFovf{ fov.angleLeft, fov.angleRight, fov.angleUp, fov.angleDown };
|
||||||
}
|
}
|
||||||
|
|
||||||
XrSpace OpenXRManagerImpl::getReferenceSpace(ReferenceSpace space)
|
XrSpace OpenXRManagerImpl::getReferenceSpace()
|
||||||
{
|
{
|
||||||
XrSpace referenceSpace = XR_NULL_HANDLE;
|
return mReferenceSpace;
|
||||||
if (space == ReferenceSpace::STAGE)
|
|
||||||
referenceSpace = mReferenceSpaceStage;
|
|
||||||
if (space == ReferenceSpace::VIEW)
|
|
||||||
referenceSpace = mReferenceSpaceView;
|
|
||||||
return referenceSpace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRManagerImpl::xrExtensionIsEnabled(const char* extensionName) const
|
bool OpenXRManagerImpl::xrExtensionIsEnabled(const char* extensionName) const
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace MWVR
|
||||||
long long getLastPredictedDisplayTime();
|
long long getLastPredictedDisplayTime();
|
||||||
long long getLastPredictedDisplayPeriod();
|
long long getLastPredictedDisplayPeriod();
|
||||||
std::array<SwapchainConfig, 2> getRecommendedSwapchainConfig() const;
|
std::array<SwapchainConfig, 2> getRecommendedSwapchainConfig() const;
|
||||||
XrSpace getReferenceSpace(ReferenceSpace space);
|
XrSpace getReferenceSpace();
|
||||||
XrSession xrSession() const { return mSession; };
|
XrSession xrSession() const { return mSession; };
|
||||||
XrInstance xrInstance() const { return mInstance; };
|
XrInstance xrInstance() const { return mInstance; };
|
||||||
bool xrExtensionIsEnabled(const char* extensionName) const;
|
bool xrExtensionIsEnabled(const char* extensionName) const;
|
||||||
|
@ -69,6 +69,7 @@ namespace MWVR
|
||||||
void eraseFormat(int64_t format);
|
void eraseFormat(int64_t format);
|
||||||
OpenXRPlatform& platform() { return mPlatform; };
|
OpenXRPlatform& platform() { return mPlatform; };
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setupExtensionsAndLayers();
|
void setupExtensionsAndLayers();
|
||||||
void setupDebugMessenger(void);
|
void setupDebugMessenger(void);
|
||||||
|
@ -97,6 +98,8 @@ namespace MWVR
|
||||||
std::array<XrViewConfigurationView, 2> mConfigViews{ { {XR_TYPE_VIEW_CONFIGURATION_VIEW}, {XR_TYPE_VIEW_CONFIGURATION_VIEW} } };
|
std::array<XrViewConfigurationView, 2> mConfigViews{ { {XR_TYPE_VIEW_CONFIGURATION_VIEW}, {XR_TYPE_VIEW_CONFIGURATION_VIEW} } };
|
||||||
XrSpace mReferenceSpaceView = XR_NULL_HANDLE;
|
XrSpace mReferenceSpaceView = XR_NULL_HANDLE;
|
||||||
XrSpace mReferenceSpaceStage = XR_NULL_HANDLE;
|
XrSpace mReferenceSpaceStage = XR_NULL_HANDLE;
|
||||||
|
XrSpace mReferenceSpaceLocal = XR_NULL_HANDLE;
|
||||||
|
XrSpace mReferenceSpace = XR_NULL_HANDLE;
|
||||||
XrFrameState mFrameState{};
|
XrFrameState mFrameState{};
|
||||||
XrSessionState mSessionState = XR_SESSION_STATE_UNKNOWN;
|
XrSessionState mSessionState = XR_SESSION_STATE_UNKNOWN;
|
||||||
XrDebugUtilsMessengerEXT mDebugMessenger{ nullptr };
|
XrDebugUtilsMessengerEXT mDebugMessenger{ nullptr };
|
||||||
|
|
|
@ -469,6 +469,7 @@ namespace MWVR
|
||||||
float realHeight = Settings::Manager::getFloat("real height", "VR");
|
float realHeight = Settings::Manager::getFloat("real height", "VR");
|
||||||
float sizeFactor = charHeight / realHeight;
|
float sizeFactor = charHeight / realHeight;
|
||||||
Environment::get().getSession()->setPlayerScale(sizeFactor);
|
Environment::get().getSession()->setPlayerScale(sizeFactor);
|
||||||
|
Environment::get().getSession()->setEyeLevel(charHeightBase - 0.15f); // approximation
|
||||||
}
|
}
|
||||||
|
|
||||||
void VRAnimation::setFingerPointingMode(bool enabled)
|
void VRAnimation::setFingerPointingMode(bool enabled)
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/movement.hpp"
|
||||||
|
|
||||||
#include <osg/Quat>
|
#include <osg/Quat>
|
||||||
|
|
||||||
|
@ -45,16 +48,35 @@ namespace MWVR
|
||||||
|
|
||||||
// Move position of head to center of character
|
// Move position of head to center of character
|
||||||
// Z should not be affected
|
// Z should not be affected
|
||||||
mHeadOffset = osg::Vec3(0, 0, 0);
|
mHeadOffset.x() = 0;
|
||||||
mHeadOffset.z() = mHeadPose.position.z();
|
mHeadOffset.y() = 0;
|
||||||
|
|
||||||
// Adjust orientation to zero yaw
|
auto* session = Environment::get().getSession();
|
||||||
|
if (session->seatedPlay() && mShouldResetZ)
|
||||||
|
{
|
||||||
|
// Adjust offset to place the current pose roughly at eye level
|
||||||
|
mHeadOffset.z() = session->eyeLevel() * Constants::UnitsPerMeter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mHeadOffset.z() = mHeadPose.position.z();
|
||||||
|
}
|
||||||
|
mShouldResetZ = false;
|
||||||
|
|
||||||
|
// When the cell changes, the game rotates the character appropriately.
|
||||||
|
// To respect this, reset yaw offset to make our yaw match the character.
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
if (world)
|
||||||
|
{
|
||||||
|
auto& player = world->getPlayer();
|
||||||
|
auto playerPtr = player.getPlayer();
|
||||||
|
const auto& data = playerPtr.getRefData();
|
||||||
float yaw = 0.f;
|
float yaw = 0.f;
|
||||||
float pitch = 0.f;
|
float pitch = 0.f;
|
||||||
float roll = 0.f;
|
float roll = 0.f;
|
||||||
getEulerAngles(mHeadPose.orientation, yaw, pitch, roll);
|
getEulerAngles(mHeadPose.orientation, yaw, pitch, roll);
|
||||||
mYawOffset = -yaw;
|
mYawOffset = data.getPosition().rot[2] - yaw;
|
||||||
|
}
|
||||||
mShouldRecenter = false;
|
mShouldRecenter = false;
|
||||||
Log(Debug::Verbose) << "Recentered";
|
Log(Debug::Verbose) << "Recentered";
|
||||||
}
|
}
|
||||||
|
@ -194,4 +216,12 @@ namespace MWVR
|
||||||
{
|
{
|
||||||
return osg::Quat(mYawOffset, osg::Vec3(0, 0, -1));
|
return osg::Quat(mYawOffset, osg::Vec3(0, 0, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VRCamera::requestRecenter(bool resetZ)
|
||||||
|
{
|
||||||
|
mShouldRecenter = true;
|
||||||
|
|
||||||
|
// Use OR so we don't a pending reset of Z.
|
||||||
|
mShouldResetZ |= resetZ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace MWVR
|
||||||
|
|
||||||
void rotateStage(float yaw) { mYawOffset += yaw; }
|
void rotateStage(float yaw) { mYawOffset += yaw; }
|
||||||
|
|
||||||
void requestRecenter() { mShouldRecenter = true; }
|
void requestRecenter(bool resetZ);
|
||||||
|
|
||||||
const osg::Vec3& headOffset() const { return mHeadOffset; }
|
const osg::Vec3& headOffset() const { return mHeadOffset; }
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ namespace MWVR
|
||||||
Pose mHeadPose{};
|
Pose mHeadPose{};
|
||||||
osg::Vec3 mHeadOffset{ 0,0,0 };
|
osg::Vec3 mHeadOffset{ 0,0,0 };
|
||||||
bool mShouldRecenter{ true };
|
bool mShouldRecenter{ true };
|
||||||
|
bool mShouldResetZ{ true };
|
||||||
bool mHasTrackingData{ false };
|
bool mHasTrackingData{ false };
|
||||||
float mYawOffset{ 0.f };
|
float mYawOffset{ 0.f };
|
||||||
bool mShouldTrackPlayerCharacter{ false };
|
bool mShouldTrackPlayerCharacter{ false };
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace MWVR
|
||||||
mPrevious = mValue;
|
mPrevious = mValue;
|
||||||
|
|
||||||
auto* xr = Environment::get().getManager();
|
auto* xr = Environment::get().getManager();
|
||||||
XrSpace referenceSpace = xr->impl().getReferenceSpace(ReferenceSpace::STAGE);
|
XrSpace referenceSpace = xr->impl().getReferenceSpace();
|
||||||
|
|
||||||
XrSpaceLocation location{ XR_TYPE_SPACE_LOCATION };
|
XrSpaceLocation location{ XR_TYPE_SPACE_LOCATION };
|
||||||
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
|
XrSpaceVelocity velocity{ XR_TYPE_SPACE_VELOCITY };
|
||||||
|
|
|
@ -280,10 +280,10 @@ namespace MWVR
|
||||||
mAxisDeadzone->setDeadzoneRadius(deadzoneRadius);
|
mAxisDeadzone->setDeadzoneRadius(deadzoneRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VRInputManager::requestRecenter()
|
void VRInputManager::requestRecenter(bool resetZ)
|
||||||
{
|
{
|
||||||
// TODO: Hack, should have a cleaner way of accessing this
|
// TODO: Hack, should have a cleaner way of accessing this
|
||||||
reinterpret_cast<VRCamera*>(MWBase::Environment::get().getWorld()->getRenderingManager().getCamera())->requestRecenter();
|
reinterpret_cast<VRCamera*>(MWBase::Environment::get().getWorld()->getRenderingManager().getCamera())->requestRecenter(resetZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
VRInputManager::VRInputManager(
|
VRInputManager::VRInputManager(
|
||||||
|
@ -723,7 +723,7 @@ namespace MWVR
|
||||||
case A_Recenter:
|
case A_Recenter:
|
||||||
vrGuiManager->updateTracking();
|
vrGuiManager->updateTracking();
|
||||||
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
requestRecenter();
|
requestRecenter(true);
|
||||||
break;
|
break;
|
||||||
case MWInput::A_Use:
|
case MWInput::A_Use:
|
||||||
if (mActivationIndication || MWBase::Environment::get().getWindowManager()->isGuiMode())
|
if (mActivationIndication || MWBase::Environment::get().getWindowManager()->isGuiMode())
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace MWVR
|
||||||
void update(float dt, bool disableControls = false, bool disableEvents = false) override;
|
void update(float dt, bool disableControls = false, bool disableEvents = false) override;
|
||||||
|
|
||||||
/// Set current offset to 0 and re-align VR stage.
|
/// Set current offset to 0 and re-align VR stage.
|
||||||
void requestRecenter();
|
void requestRecenter(bool resetZ);
|
||||||
|
|
||||||
/// Tracking pose of the given limb at the given predicted time
|
/// Tracking pose of the given limb at the given predicted time
|
||||||
Pose getLimbPose(int64_t time, TrackedLimb limb);
|
Pose getLimbPose(int64_t time, TrackedLimb limb);
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/statemanager.hpp"
|
#include "../mwbase/statemanager.hpp"
|
||||||
#include "vrmetamenu.hpp"
|
|
||||||
|
#include "vrenvironment.hpp"
|
||||||
|
#include "vrinputmanager.hpp"
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
|
@ -94,6 +96,11 @@ namespace MWVR
|
||||||
MWBase::Environment::get().getStateManager()->quickSave();
|
MWBase::Environment::get().getStateManager()->quickSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VrMetaMenu::onRecenter()
|
||||||
|
{
|
||||||
|
Environment::get().getInputManager()->requestRecenter(true);
|
||||||
|
}
|
||||||
|
|
||||||
void VrMetaMenu::close()
|
void VrMetaMenu::close()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_VrMetaMenu);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_VrMetaMenu);
|
||||||
|
@ -119,6 +126,8 @@ namespace MWVR
|
||||||
onQuickLoad();
|
onQuickLoad();
|
||||||
else if (name == "quicksave")
|
else if (name == "quicksave")
|
||||||
onQuickSave();
|
onQuickSave();
|
||||||
|
else if (name == "recenter")
|
||||||
|
onRecenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VrMetaMenu::exit()
|
bool VrMetaMenu::exit()
|
||||||
|
@ -128,7 +137,7 @@ namespace MWVR
|
||||||
|
|
||||||
void VrMetaMenu::updateMenu()
|
void VrMetaMenu::updateMenu()
|
||||||
{
|
{
|
||||||
static std::vector<std::string> buttons{ "return", "quicksave", "quickload", "console", "inventory", "journal", "rest", "quickmenu", "gamemenu" };
|
static std::vector<std::string> buttons{ "return", "recenter", "quicksave", "quickload", "console", "inventory", "journal", "rest", "quickmenu", "gamemenu" };
|
||||||
|
|
||||||
if(mButtons.empty())
|
if(mButtons.empty())
|
||||||
for (std::string& buttonId : buttons)
|
for (std::string& buttonId : buttons)
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace MWVR
|
||||||
void onQuickMenu();
|
void onQuickMenu();
|
||||||
void onQuickLoad();
|
void onQuickLoad();
|
||||||
void onQuickSave();
|
void onQuickSave();
|
||||||
|
void onRecenter();
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void updateMenu();
|
void updateMenu();
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace MWVR
|
||||||
VRSession::VRSession()
|
VRSession::VRSession()
|
||||||
{
|
{
|
||||||
mHandDirectedMovement = Settings::Manager::getBool("hand directed movement", "VR");
|
mHandDirectedMovement = Settings::Manager::getBool("hand directed movement", "VR");
|
||||||
|
mSeatedPlay = Settings::Manager::getBool("seated play", "VR");
|
||||||
}
|
}
|
||||||
|
|
||||||
VRSession::~VRSession()
|
VRSession::~VRSession()
|
||||||
|
@ -70,11 +71,9 @@ namespace MWVR
|
||||||
void VRSession::processChangedSettings(const std::set<std::pair<std::string, std::string>>& changed)
|
void VRSession::processChangedSettings(const std::set<std::pair<std::string, std::string>>& changed)
|
||||||
{
|
{
|
||||||
for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it)
|
for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it)
|
||||||
{
|
|
||||||
if (it->first == "VR" && it->second == "hand directed movement")
|
|
||||||
{
|
{
|
||||||
mHandDirectedMovement = Settings::Manager::getBool("hand directed movement", "VR");
|
mHandDirectedMovement = Settings::Manager::getBool("hand directed movement", "VR");
|
||||||
}
|
setSeatedPlay(Settings::Manager::getBool("seated play", "VR"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +97,15 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VRSession::setSeatedPlay(bool seatedPlay)
|
||||||
|
{
|
||||||
|
std::swap(mSeatedPlay, seatedPlay);
|
||||||
|
if (mSeatedPlay != seatedPlay)
|
||||||
|
{
|
||||||
|
Environment::get().getInputManager()->requestRecenter(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
osg::Matrix VRSession::viewMatrix(osg::Vec3 position, osg::Quat orientation)
|
osg::Matrix VRSession::viewMatrix(osg::Vec3 position, osg::Quat orientation)
|
||||||
{
|
{
|
||||||
position = position * Constants::UnitsPerMeter;
|
position = position * Constants::UnitsPerMeter;
|
||||||
|
|
|
@ -66,9 +66,13 @@ namespace MWVR
|
||||||
|
|
||||||
void beginPhase(FramePhase phase);
|
void beginPhase(FramePhase phase);
|
||||||
std::unique_ptr<VRFrameMeta>& getFrame(FramePhase phase);
|
std::unique_ptr<VRFrameMeta>& getFrame(FramePhase phase);
|
||||||
|
bool seatedPlay() const { return mSeatedPlay; }
|
||||||
|
|
||||||
float playerScale() const { return mPlayerScale; }
|
float playerScale() const { return mPlayerScale; }
|
||||||
float setPlayerScale(float scale) { return mPlayerScale = scale; }
|
void setPlayerScale(float scale) { mPlayerScale = scale; }
|
||||||
|
|
||||||
|
float eyeLevel() const { return mEyeLevel; }
|
||||||
|
void setEyeLevel(float eyeLevel) { mEyeLevel = eyeLevel; }
|
||||||
|
|
||||||
osg::Matrix viewMatrix(osg::Vec3 position, osg::Quat orientation);
|
osg::Matrix viewMatrix(osg::Vec3 position, osg::Quat orientation);
|
||||||
osg::Matrix viewMatrix(FramePhase phase, Side side, bool offset, bool glConvention);
|
osg::Matrix viewMatrix(FramePhase phase, Side side, bool offset, bool glConvention);
|
||||||
|
@ -81,11 +85,15 @@ namespace MWVR
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
void endFrame();
|
void endFrame();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setSeatedPlay(bool seatedPlay);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mutex mMutex{};
|
std::mutex mMutex{};
|
||||||
std::condition_variable mCondition{};
|
std::condition_variable mCondition{};
|
||||||
|
|
||||||
bool mHandDirectedMovement{ false };
|
bool mHandDirectedMovement{ false };
|
||||||
|
bool mSeatedPlay{ false };
|
||||||
long long mFrames{ 0 };
|
long long mFrames{ 0 };
|
||||||
long long mLastRenderedFrame{ 0 };
|
long long mLastRenderedFrame{ 0 };
|
||||||
long long mLastPredictedDisplayTime{ 0 };
|
long long mLastPredictedDisplayTime{ 0 };
|
||||||
|
@ -95,6 +103,7 @@ namespace MWVR
|
||||||
std::chrono::steady_clock::time_point mLastRenderedFrameTimestamp{ std::chrono::steady_clock::now() };
|
std::chrono::steady_clock::time_point mLastRenderedFrameTimestamp{ std::chrono::steady_clock::now() };
|
||||||
|
|
||||||
float mPlayerScale{ 1.f };
|
float mPlayerScale{ 1.f };
|
||||||
|
float mEyeLevel{ 1.f };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -964,7 +964,7 @@ namespace MWWorld
|
||||||
#ifdef USE_OPENXR
|
#ifdef USE_OPENXR
|
||||||
auto* xrInput = MWVR::Environment::get().getInputManager();
|
auto* xrInput = MWVR::Environment::get().getInputManager();
|
||||||
if (xrInput)
|
if (xrInput)
|
||||||
xrInput->requestRecenter();
|
xrInput->requestRecenter(false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,7 +987,7 @@ namespace MWWorld
|
||||||
#ifdef USE_OPENXR
|
#ifdef USE_OPENXR
|
||||||
auto* xrInput = MWVR::Environment::get().getInputManager();
|
auto* xrInput = MWVR::Environment::get().getInputManager();
|
||||||
if (xrInput)
|
if (xrInput)
|
||||||
xrInput->requestRecenter();
|
xrInput->requestRecenter(false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -595,7 +595,17 @@
|
||||||
<Property key="Caption" value="Hand directed movement"/>
|
<Property key="Caption" value="Hand directed movement"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="HBox" skin="" position="4 154 350 24">
|
<Widget type="HBox" skin="" position="4 154 260 24">
|
||||||
|
<Widget type="AutoSizedButton" skin="MW_Button" position="0 0 24 24" align="Left Top">
|
||||||
|
<UserString key="SettingCategory" value="VR"/>
|
||||||
|
<UserString key="SettingName" value="seated play"/>
|
||||||
|
<UserString key="SettingType" value="CheckButton"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="AutoSizedTextBox" skin="SandText" position="28 4 71 16" align="Left Top">
|
||||||
|
<Property key="Caption" value="Seated play"/>
|
||||||
|
</Widget>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="HBox" skin="" position="4 184 350 24">
|
||||||
<Widget type="ComboBox" skin="MW_ComboBox" position="0 0 85 24" align="Left Top" name="VRLeftHudPosition">
|
<Widget type="ComboBox" skin="MW_ComboBox" position="0 0 85 24" align="Left Top" name="VRLeftHudPosition">
|
||||||
<Property key="AddItem" value="Wrist"/>
|
<Property key="AddItem" value="Wrist"/>
|
||||||
<Property key="AddItem" value="Top"/>
|
<Property key="AddItem" value="Top"/>
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
<Property key="FontHeight" value="32"/>
|
<Property key="FontHeight" value="32"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
|
<Widget type="AutoSizedButton" skin="MW_Button" name="recenter" align="HCenter">
|
||||||
|
<Property key="Caption" value="Recenter"/>
|
||||||
|
<Property key="FontHeight" value="32"/>
|
||||||
|
</Widget>
|
||||||
|
|
||||||
<Widget type="Spacer"/>
|
<Widget type="Spacer"/>
|
||||||
<Widget type="Widget" skin="IB_T" align="HCenter" position="0 0 125 4">
|
<Widget type="Widget" skin="IB_T" align="HCenter" position="0 0 125 4">
|
||||||
<Widget type="Widget"/>
|
<Widget type="Widget"/>
|
||||||
|
|
|
@ -1023,6 +1023,8 @@ left hand hud position = wrist
|
||||||
# As the general quality of OpenXR DirectX runtimes is better than OpenGL runtimes, i default this to true.
|
# As the general quality of OpenXR DirectX runtimes is better than OpenGL runtimes, i default this to true.
|
||||||
Prefer DirectX swapchains = true
|
Prefer DirectX swapchains = true
|
||||||
|
|
||||||
|
seated play = false
|
||||||
|
|
||||||
[VR Debug]
|
[VR Debug]
|
||||||
# If true, OpenMW-VR will enable gamma postprocessing
|
# If true, OpenMW-VR will enable gamma postprocessing
|
||||||
gamma postprocessing = true
|
gamma postprocessing = true
|
||||||
|
|
Loading…
Reference in a new issue