1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-15 16:09:40 +00:00

Improved frame pose prediction by barriering slave access as well. Slaves were updating on either the old frame timing or new by chance, causing jittery tracking. Accounted for morrowind's unit length (1 unit = 64 yards)

This commit is contained in:
Mads Buvik Sandvei 2020-01-25 14:27:13 +01:00
parent 2accdc4441
commit 51125d4f3e
12 changed files with 39 additions and 80 deletions

View file

@ -11,6 +11,6 @@ void OMW::Engine::initVr()
throw std::logic_error("mViewer must be initialized before calling initVr()");
mXR = new MWVR::OpenXRManager();
mXRViewer = new MWVR::OpenXRViewer(mXR, mViewer, 1.f);
mXRViewer = new MWVR::OpenXRViewer(mXR, mViewer, 64.f * 0.9144);
}

View file

@ -414,68 +414,6 @@ namespace MWVR
, mHandPoseAction(std::move(createAction(XR_ACTION_TYPE_POSE_INPUT, "hand_pose", "Hand Pose", { LEFT_HAND, RIGHT_HAND })))
, mHapticsAction(std::move(createAction(XR_ACTION_TYPE_VIBRATION_OUTPUT, "vibrate_hand", "Vibrate Hand", { LEFT_HAND, RIGHT_HAND })))
{
//{ mHandPoseAction, mPosePath[LEFT_HAND]},
//{ mHandPoseAction, mPosePath[RIGHT_HAND] },
//{ mHapticsAction, mHapticPath[LEFT_HAND] },
//{ mHapticsAction, mHapticPath[RIGHT_HAND] },
//{ mLookLeftRight, mThumbstickXPath[RIGHT_HAND] },
//{ mMoveLeftRight, mThumbstickXPath[LEFT_HAND] },
//{ mMoveForwardBackward, mThumbstickYPath[LEFT_HAND] },
//{ mActivate, mSqueezeClickPath[RIGHT_HAND] },
//{ mUse, mTriggerClickPath[RIGHT_HAND] },
//{ mJump, mTriggerValuePath[LEFT_HAND] },
//{ mWeapon, mAPath[RIGHT_HAND] },
//{ mSpell, mAPath[RIGHT_HAND] },
//{ mCycleSpellLeft, mThumbstickClickPath[LEFT_HAND] },
//{ mCycleSpellRight, mThumbstickClickPath[RIGHT_HAND] },
//{ mCycleWeaponLeft, mThumbstickClickPath[LEFT_HAND] },
//{ mCycleWeaponRight, mThumbstickClickPath[RIGHT_HAND] },
//{ mSneak, mXPath[LEFT_HAND] },
//{ mInventory, mBPath[RIGHT_HAND] },
//{ mQuickMenu, mYPath[LEFT_HAND] },
//{ mSpellModifier, mSqueezeClickPath[LEFT_HAND] },
//{ mGameMenu, mMenuClickPath[LEFT_HAND] },
// There are not enough actions on controllers to assign everything.
//mUnused = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "Unused", "Unused", { }));
//mScreenshot = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "Screenshot", "Screenshot", { }));
//mConsole = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "Console", "Console", { }));
//mMoveLeft = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "MoveLeft", "MoveLeft", { }));
//mMoveRight = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "MoveRight", "MoveRight", { }));
//mMoveForward = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "MoveForward", "MoveForward", { }));
//mMoveBackward = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "MoveBackward", "MoveBackward", { }));
//mAutoMove = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "AutoMove", "AutoMove", { }));
//mRest = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "Rest", "Rest", { }));
//mJournal = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "Journal", "Journal", { }));
//mRun = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "Run", "Run", { }));
//mAlwaysRun = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "AlwaysRun", "AlwaysRun", { }));
//mQuickSave = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickSave", "QuickSave", { }));
//mQuickLoad = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickLoad", "QuickLoad", { }));
//mToggleWeapon = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "ToggleWeapon", "ToggleWeapon", { }));
//mToggleSpell = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "ToggleSpell", "ToggleSpell", { }));
//mTogglePOV = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "TogglePOV", "TogglePOV", { }));
//mQuickKey1 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey1", "QuickKey1", { }));
//mQuickKey2 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey2", "QuickKey2", { }));
//mQuickKey3 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey3", "QuickKey3", { }));
//mQuickKey4 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey4", "QuickKey4", { }));
//mQuickKey5 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey5", "QuickKey5", { }));
//mQuickKey6 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey6", "QuickKey6", { }));
//mQuickKey7 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey7", "QuickKey7", { }));
//mQuickKey8 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey8", "QuickKey8", { }));
//mQuickKey9 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey9", "QuickKey9", { }));
//mQuickKey10 = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKey10", "QuickKey10", { }));
//mQuickKeysMenu = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "QuickKeysMenu", "QuickKeysMenu", { }));
//mToggleHUD = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "ToggleHUD", "ToggleHUD", { }));
//mToggleDebug = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "ToggleDebug", "ToggleDebug", { }));
//mToggleSneak = std::move(createAction(XR_ACTION_TYPE_BOOLEAN_INPUT, "ToggleSneak", "ToggleSneak", { }));
//mLookUpDown = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "LookUpDown", "LookUpDown", { }));
//mZoomIn = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "ZoomIn", "ZoomIn", { }));
//mZoomOut = std::move(createAction(XR_ACTION_TYPE_FLOAT_INPUT, "ZoomOut", "ZoomOut", { }));
{ // Set up default bindings for the oculus
XrPath oculusTouchInteractionProfilePath;
CHECK_XRCMD(

View file

@ -39,6 +39,6 @@ namespace MWVR {
if (!mLayers[1])
return nullptr;
return nullptr;
}
}

View file

@ -44,7 +44,7 @@ namespace MWVR
OpenXRManager::frameIndex()
{
if (realized())
return impl().frameIndex;
return impl().mFrameIndex;
return -1;
}
@ -67,10 +67,10 @@ namespace MWVR
return impl().waitFrame();
}
void OpenXRManager::beginFrame()
void OpenXRManager::beginFrame(long long frameIndex)
{
if (realized())
return impl().beginFrame();
return impl().beginFrame(frameIndex);
}
void OpenXRManager::endFrame()

View file

@ -96,7 +96,7 @@ namespace MWVR
void handleEvents();
void waitFrame();
void beginFrame();
void beginFrame(long long frameIndex);
void endFrame();
void updateControls();
void updatePoses();

View file

@ -275,8 +275,9 @@ namespace MWVR
}
void
OpenXRManagerImpl::beginFrame()
OpenXRManagerImpl::beginFrame(long long frameIndex)
{
Log(Debug::Verbose) << "frameIndex = " << frameIndex;
if (!mSessionRunning)
return;
@ -284,11 +285,12 @@ namespace MWVR
// We need to wait for the frame to become idle or ready
// (There is no guarantee osg won't get us here before endFrame() returns)
while (mFrameStatus == OPENXR_FRAME_STATUS_ENDING)
while (mFrameStatus == OPENXR_FRAME_STATUS_ENDING || mFrameIndex < frameIndex)
mFrameStatusSignal.wait(lock);
if (mFrameStatus == OPENXR_FRAME_STATUS_IDLE)
{
Log(Debug::Verbose) << "beginFrame()";
handleEvents();
waitFrame();
@ -356,6 +358,7 @@ namespace MWVR
frameEndInfo.layers = mLayerStack.layerHeaders();
CHECK_XRCMD(xrEndFrame(mSession, &frameEndInfo));
mFrameStatus = OPENXR_FRAME_STATUS_IDLE;
mFrameIndex++;
mFrameStatusSignal.notify_all();
}

View file

@ -56,7 +56,7 @@ namespace MWVR
const XrEventDataBaseHeader* nextEvent();
void waitFrame();
void beginFrame();
void beginFrame(long long frameIndex);
void endFrame();
std::array<XrView, 2> getStageViews();
std::array<XrView, 2> getHmdViews();
@ -69,7 +69,7 @@ namespace MWVR
void HandleSessionStateChanged(const XrEventDataSessionStateChanged& stateChangedEvent);
bool initialized = false;
long long frameIndex = 0;
long long mFrameIndex = 0;
XrInstance mInstance = XR_NULL_HANDLE;
XrSession mSession = XR_NULL_HANDLE;
XrSpace mSpace = XR_NULL_HANDLE;

View file

@ -55,6 +55,8 @@ namespace MWVR
mLayer->pose.position = osg::toXR(pose.position);
mLayer->pose.orientation = osg::toXR(-pose.orientation);
mPositionNeedsUpdate = false;
Log(Debug::Verbose) << "Menu pose updated to: " << pose;
}
void OpenXRMenu::postrenderCallback(osg::RenderInfo& info)

View file

@ -71,7 +71,8 @@ namespace MWVR {
void OpenXRView::prerenderCallback(osg::RenderInfo& renderInfo)
{
mXR->beginFrame();
Log(Debug::Verbose) << "prerenderCallback";
mXR->beginFrame(mFrameIndex);
if(mSwapchain)
mSwapchain->beginFrame(renderInfo.getState()->getGraphicsContext());
}
@ -81,6 +82,7 @@ namespace MWVR {
if (mSwapchain)
mSwapchain->endFrame(renderInfo.getState()->getGraphicsContext());
mXR->viewerBarrier();
mFrameIndex++;
}
bool OpenXRView::realize(osg::ref_ptr<osg::State> state)

View file

@ -66,11 +66,14 @@ namespace MWVR
OpenXRSwapchain& swapchain(void) { return *mSwapchain; }
//! Create the view surface
bool realize(osg::ref_ptr<osg::State> state);
//! Current frame being rendered
long long frameIndex() { return mFrameIndex; };
protected:
osg::ref_ptr<OpenXRManager> mXR;
std::unique_ptr<OpenXRSwapchain> mSwapchain;
OpenXRSwapchain::Config mSwapchainConfig;
long long mFrameIndex{ 0 };
};
}

View file

@ -79,6 +79,7 @@ namespace MWVR
if (!context->makeCurrent())
{
throw std::logic_error("OpenXRViewer::configure() failed to make graphics context current.");
return;
}
mMainCamera = mViewer->getCamera();
@ -183,8 +184,8 @@ namespace MWVR
mMirrorTextureSwapchain->current()->blit(gc, 0, 0, mMirrorTextureSwapchain->width(), mMirrorTextureSwapchain->height());
gc->swapBuffersImplementation();
mMirrorTextureSwapchain->releaseSwapchainImage();
gc->swapBuffersImplementation();
}
@ -202,8 +203,8 @@ namespace MWVR
auto* camera = slave._camera.get();
auto name = camera->getName();
Log(Debug::Debug) << "Updating camera " << name;
Log(Debug::Verbose) << "Updating camera " << name;
mXR->beginFrame(mView->frameIndex());
auto viewMatrix = view.getCamera()->getViewMatrix() * mView->viewMatrix();
auto projMatrix = mView->projectionMatrix();

View file

@ -80,7 +80,7 @@ namespace MWVR
auto hmdViews = mXR->impl().getHmdViews();
float near = Settings::Manager::getFloat("near clip", "Camera");
float far = Settings::Manager::getFloat("viewing distance", "Camera");
float far = Settings::Manager::getFloat("viewing distance", "Camera") * mMetersPerUnit;
//return perspectiveFovMatrix()
return perspectiveFovMatrix(near, far, hmdViews[mView].fov);
}
@ -90,17 +90,26 @@ namespace MWVR
osg::Matrix viewMatrix;
auto hmdViews = mXR->impl().getHmdViews();
auto pose = hmdViews[mView].pose;
osg::Vec3 position = osg::Vec3(pose.position.x, pose.position.y, pose.position.z);
osg::Vec3 position = osg::fromXR(pose.position);
auto stageViews = mXR->impl().getStageViews();
auto stagePose = stageViews[mView].pose;
// Comfort shortcut.
// TODO: STAGE movement should affect in-game movement but not like this.
// This method should only be using HEAD view.
// But for comfort i'm keeping this until such movement has been implemented.
#if 1
position = -osg::fromXR(stagePose.position);
position.y() += 0.9144 * 2.;
#endif
// invert orientation (conjugate of Quaternion) and position to apply to the view matrix as offset
viewMatrix.setTrans(position);
viewMatrix.setTrans(position * mMetersPerUnit);
viewMatrix.postMultRotate(osg::fromXR(stagePose.orientation).conj());
// Scale to world units
viewMatrix.postMultScale(osg::Vec3d(mMetersPerUnit, mMetersPerUnit, mMetersPerUnit));
//viewMatrix.postMultScale(osg::Vec3d(1.f / mMetersPerUnit, 1.f / mMetersPerUnit, 1.f / mMetersPerUnit));
return viewMatrix;
}
@ -116,6 +125,7 @@ namespace MWVR
setWidth(config.recommendedImageRectWidth);
setHeight(config.recommendedImageRectHeight);
setSamples(config.recommendedSwapchainSampleCount);
realize(state);
// XR->setViewSubImage(view, mSwapchain->subImage());
}