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:
parent
2accdc4441
commit
51125d4f3e
12 changed files with 39 additions and 80 deletions
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -39,6 +39,6 @@ namespace MWVR {
|
|||
if (!mLayers[1])
|
||||
return nullptr;
|
||||
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace MWVR
|
|||
|
||||
void handleEvents();
|
||||
void waitFrame();
|
||||
void beginFrame();
|
||||
void beginFrame(long long frameIndex);
|
||||
void endFrame();
|
||||
void updateControls();
|
||||
void updatePoses();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue