mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 17:24:24 +02:00
Merge pull request #1516 from ada-tv/fix/xr-cleanup2
OpenXR cleanup 2, electric boogaloo
This commit is contained in:
commit
98722b3128
13 changed files with 137 additions and 170 deletions
|
@ -3,8 +3,8 @@
|
||||||
"channels": [
|
"channels": [
|
||||||
{ "from": "OpenXR.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] },
|
{ "from": "OpenXR.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] },
|
||||||
|
|
||||||
{ "from": "OpenXR.LT", "to": "Standard.LT", "filters": [{"type": "deadZone", "min": 0.05}]},
|
{ "from": "OpenXR.LT", "to": "Standard.LT", "filters": [{"type": "deadZone", "min": 0.05}] },
|
||||||
{ "from": "OpenXR.RT", "to": "Standard.RT", "filters": [{"type": "deadZone", "min": 0.05}]},
|
{ "from": "OpenXR.RT", "to": "Standard.RT", "filters": [{"type": "deadZone", "min": 0.05}] },
|
||||||
{ "from": "OpenXR.LTClick", "to": "Standard.LTClick" },
|
{ "from": "OpenXR.LTClick", "to": "Standard.LTClick" },
|
||||||
{ "from": "OpenXR.RTClick", "to": "Standard.RTClick" },
|
{ "from": "OpenXR.RTClick", "to": "Standard.RTClick" },
|
||||||
|
|
||||||
|
@ -14,10 +14,7 @@
|
||||||
{ "from": "OpenXR.LX", "to": "Standard.LX", "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
{ "from": "OpenXR.LX", "to": "Standard.LX", "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
||||||
{ "from": "OpenXR.LY", "to": "Standard.LY", "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
{ "from": "OpenXR.LY", "to": "Standard.LY", "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
||||||
|
|
||||||
{ "from": "OpenXR.LX", "to": "Actions.TranslateX", "peek": true, "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
{ "from": "OpenXR.RX", "to": "Standard.RX" },
|
||||||
{ "from": "OpenXR.LY", "to": "Actions.TranslateZ", "peek": true, "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
|
||||||
|
|
||||||
{ "from": "OpenXR.RX", "to": "Standard.RX"},
|
|
||||||
{ "from": "OpenXR.RY", "to": "Standard.RY" },
|
{ "from": "OpenXR.RY", "to": "Standard.RY" },
|
||||||
|
|
||||||
{ "from": "OpenXR.LS", "to": "Standard.LS" },
|
{ "from": "OpenXR.LS", "to": "Standard.LS" },
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "Standard to Action",
|
"name": "Standard to Action",
|
||||||
"channels": [
|
"channels": [
|
||||||
{ "from": "Standard.LY",
|
{ "from": "Standard.LY",
|
||||||
"when": ["Application.RightHandDominant", "!Standard.RY"],
|
"when": ["Application.RightHandDominant"],
|
||||||
"to": "Actions.TranslateZ"
|
"to": "Actions.TranslateZ"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
{ "from": "Standard.LX",
|
{ "from": "Standard.LX",
|
||||||
"when": [
|
"when": [
|
||||||
"Application.InHMD", "!Application.AdvancedMovement", "Application.RightHandDominant",
|
"Application.InHMD", "!Application.AdvancedMovement", "Application.RightHandDominant",
|
||||||
"Application.SnapTurn", "!Standard.RX"
|
"Application.SnapTurn"
|
||||||
],
|
],
|
||||||
"to": "Actions.StepYaw",
|
"to": "Actions.StepYaw",
|
||||||
"filters":
|
"filters":
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{ "from": "Standard.RY",
|
{ "from": "Standard.RY",
|
||||||
"when": ["Application.LeftHandDominant", "!Standard.LY"],
|
"when": ["Application.LeftHandDominant"],
|
||||||
"to": "Actions.TranslateZ"
|
"to": "Actions.TranslateZ"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
{ "from": "Standard.RX",
|
{ "from": "Standard.RX",
|
||||||
"when": [
|
"when": [
|
||||||
"Application.InHMD", "!Application.AdvancedMovement", "Application.LeftHandDominant",
|
"Application.InHMD", "!Application.AdvancedMovement", "Application.LeftHandDominant",
|
||||||
"Application.SnapTurn", "!Standard.RX"
|
"Application.SnapTurn"
|
||||||
],
|
],
|
||||||
"to": "Actions.StepYaw",
|
"to": "Actions.StepYaw",
|
||||||
"filters":
|
"filters":
|
||||||
|
|
|
@ -745,13 +745,6 @@ void OpenGLDisplayPlugin::present(const std::shared_ptr<RefreshRateController>&
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory());
|
gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory());
|
||||||
|
|
||||||
// Drop current frame after presenting it once.
|
|
||||||
// This is required for the OpenXR frame cycle, since we call xrEndFrame after presenting.
|
|
||||||
// xrEndFrame must not be called multiple times.
|
|
||||||
if (_presentOnlyOnce) {
|
|
||||||
_currentFrame.reset();
|
|
||||||
}
|
|
||||||
} else if (alwaysPresent()) {
|
} else if (alwaysPresent()) {
|
||||||
refreshRateController->clockEndTime();
|
refreshRateController->clockEndTime();
|
||||||
internalPresent();
|
internalPresent();
|
||||||
|
|
|
@ -205,8 +205,6 @@ protected:
|
||||||
QImage getScreenshot(float aspectRatio);
|
QImage getScreenshot(float aspectRatio);
|
||||||
QImage getSecondaryCameraScreenshot();
|
QImage getSecondaryCameraScreenshot();
|
||||||
|
|
||||||
bool _presentOnlyOnce = false;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Setting::Handle<bool> _extraLinearToSRGBConversionSetting;
|
static Setting::Handle<bool> _extraLinearToSRGBConversionSetting;
|
||||||
};
|
};
|
||||||
|
|
|
@ -455,7 +455,11 @@ inline Transform::Mat4& Transform::getRotationScaleMatrixInverse(Mat4& result) c
|
||||||
|
|
||||||
inline Transform& Transform::evalFromRawMatrix(const Mat4& matrix) {
|
inline Transform& Transform::evalFromRawMatrix(const Mat4& matrix) {
|
||||||
// for now works only in the case of TRS transformation
|
// for now works only in the case of TRS transformation
|
||||||
if ((matrix[0][3] == 0.0f) && (matrix[1][3] == 0.0f) && (matrix[2][3] == 0.0f) && (matrix[3][3] == 1.0f)) {
|
constexpr float MATRIX_CHECK_EPSILON = 0.0001f;
|
||||||
|
if ((fabsf(matrix[0][3]) <= MATRIX_CHECK_EPSILON)
|
||||||
|
&& (fabsf(matrix[1][3]) <= MATRIX_CHECK_EPSILON)
|
||||||
|
&& (fabsf(matrix[2][3]) <= MATRIX_CHECK_EPSILON)
|
||||||
|
&& (fabsf(1.0f - matrix[3][3]) <= MATRIX_CHECK_EPSILON)) {
|
||||||
setTranslation(extractTranslation(matrix));
|
setTranslation(extractTranslation(matrix));
|
||||||
evalFromRawMatrix(Mat3(matrix));
|
evalFromRawMatrix(Mat3(matrix));
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,6 +304,8 @@ void handleOpenVrEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetEventTypeNameFromEnum is unimplemented in OpenComposite and xrizer
|
||||||
|
#if 0
|
||||||
#if DEV_BUILD
|
#if DEV_BUILD
|
||||||
//qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
|
//qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
|
||||||
// FIXME: Reinstate the line above and remove the following lines once the problem with excessive occurrences of
|
// FIXME: Reinstate the line above and remove the following lines once the problem with excessive occurrences of
|
||||||
|
@ -317,6 +319,7 @@ void handleOpenVrEvents() {
|
||||||
qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
|
qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,4 +28,4 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
target_compile_definitions(openxr PRIVATE -DDONT_REDEFINE_LERP)
|
target_compile_definitions(openxr PRIVATE -DDONT_REDEFINE_LERP)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_property(TARGET openxr PROPERTY CXX_STANDARD 20)
|
set_property(TARGET openxr PROPERTY CXX_STANDARD 20)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "OpenXrContext.h"
|
#include "OpenXrContext.h"
|
||||||
#include <qloggingcategory.h>
|
#include <QLoggingCategory>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
|
||||||
|
@ -67,8 +67,10 @@ OpenXrContext::~OpenXrContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXrContext::initInstance() {
|
bool OpenXrContext::initInstance() {
|
||||||
if (static_cast<QGuiApplication*>(qApp)->platformName() == "wayland") {
|
auto myApp = static_cast<QGuiApplication*>(qApp);
|
||||||
qCCritical(xr_context_cat, "The OpenXR plugin does not support Wayland yet! Use the QT_QPA_PLATFORM=xcb environment variable to force Overte to launch with X11.");
|
if (myApp->platformName() == "wayland") {
|
||||||
|
auto msg = QString::fromUtf8("The OpenXR plugin does not support Wayland yet! Use the QT_QPA_PLATFORM=xcb environment variable to force Overte to launch with X11.");
|
||||||
|
qCCritical(xr_context_cat) << msg;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,32 +260,45 @@ bool OpenXrContext::initGraphics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXrContext::requestExitSession() {
|
bool OpenXrContext::requestExitSession() {
|
||||||
|
if (_session == XR_NULL_HANDLE) { return true; }
|
||||||
|
|
||||||
XrResult result = xrRequestExitSession(_session);
|
XrResult result = xrRequestExitSession(_session);
|
||||||
return xrCheck(_instance, result, "Failed to request exit session!");
|
return xrCheck(_instance, result, "Failed to request exit session!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXrContext::initSession() {
|
bool OpenXrContext::initSession() {
|
||||||
|
if (_session != XR_NULL_HANDLE) { return true; }
|
||||||
|
|
||||||
|
XrSessionCreateInfo info = {
|
||||||
|
.type = XR_TYPE_SESSION_CREATE_INFO,
|
||||||
|
.next = nullptr,
|
||||||
|
.systemId = _systemId,
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
XrGraphicsBindingOpenGLXlibKHR binding = {
|
// if (wayland) {
|
||||||
|
// blah blah...
|
||||||
|
// info.next = &wlBinding;
|
||||||
|
// } else
|
||||||
|
XrGraphicsBindingOpenGLXlibKHR xlibBinding = {
|
||||||
.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR,
|
.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR,
|
||||||
.xDisplay = XOpenDisplay(nullptr),
|
.xDisplay = XOpenDisplay(nullptr),
|
||||||
.glxDrawable = glXGetCurrentDrawable(),
|
.glxDrawable = glXGetCurrentDrawable(),
|
||||||
.glxContext = glXGetCurrentContext(),
|
.glxContext = glXGetCurrentContext(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
info.next = &xlibBinding;
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
XrGraphicsBindingOpenGLWin32KHR binding = {
|
XrGraphicsBindingOpenGLWin32KHR binding = {
|
||||||
.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
|
.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
|
||||||
.hDC = wglGetCurrentDC(),
|
.hDC = wglGetCurrentDC(),
|
||||||
.hGLRC = wglGetCurrentContext(),
|
.hGLRC = wglGetCurrentContext(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
info.next = &binding;
|
||||||
#else
|
#else
|
||||||
#error "Unsupported platform"
|
#error "Unsupported platform"
|
||||||
#endif
|
#endif
|
||||||
XrSessionCreateInfo info = {
|
|
||||||
.type = XR_TYPE_SESSION_CREATE_INFO,
|
|
||||||
.next = &binding,
|
|
||||||
.systemId = _systemId,
|
|
||||||
};
|
|
||||||
|
|
||||||
XrResult result = xrCreateSession(_instance, &info, &_session);
|
XrResult result = xrCreateSession(_instance, &info, &_session);
|
||||||
return xrCheck(_instance, result, "Failed to create session");
|
return xrCheck(_instance, result, "Failed to create session");
|
||||||
|
@ -398,6 +413,7 @@ bool OpenXrContext::updateSessionState(XrSessionState newState) {
|
||||||
return false;
|
return false;
|
||||||
_shouldQuit = true;
|
_shouldQuit = true;
|
||||||
_shouldRunFrameCycle = false;
|
_shouldRunFrameCycle = false;
|
||||||
|
_session = XR_NULL_HANDLE;
|
||||||
qCDebug(xr_context_cat, "Destroyed session");
|
qCDebug(xr_context_cat, "Destroyed session");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,6 @@ constexpr GLint XR_PREFERRED_COLOR_FORMAT = GL_SRGB8_ALPHA8;
|
||||||
|
|
||||||
OpenXrDisplayPlugin::OpenXrDisplayPlugin(std::shared_ptr<OpenXrContext> c) {
|
OpenXrDisplayPlugin::OpenXrDisplayPlugin(std::shared_ptr<OpenXrContext> c) {
|
||||||
_context = c;
|
_context = c;
|
||||||
_presentOnlyOnce = true;
|
|
||||||
_lastFrameTime = 1.0f / 90.0f;
|
|
||||||
_estimatedTargetFramerate = 90.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXrDisplayPlugin::isSupported() const {
|
bool OpenXrDisplayPlugin::isSupported() const {
|
||||||
|
@ -84,11 +81,9 @@ glm::mat4 OpenXrDisplayPlugin::getCullingProjection(const glm::mat4& baseProject
|
||||||
return getEyeProjection(Left, baseProjection);
|
return getEyeProjection(Left, baseProjection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenXR doesn't give us a target framerate,
|
|
||||||
// but it does do vsync on its own,
|
|
||||||
// so just push out frames as vsync allows
|
|
||||||
float OpenXrDisplayPlugin::getTargetFrameRate() const {
|
float OpenXrDisplayPlugin::getTargetFrameRate() const {
|
||||||
return std::numeric_limits<float>::max();
|
// predictedDisplayPeriod is delta nanoseconds, so convert it to frames per second
|
||||||
|
return std::max(1.0f, 1.0f / (_lastFrameState.predictedDisplayPeriod / 1e9f));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXrDisplayPlugin::initViews() {
|
bool OpenXrDisplayPlugin::initViews() {
|
||||||
|
@ -260,15 +255,6 @@ void OpenXrDisplayPlugin::init() {
|
||||||
emit deviceConnected(getName());
|
emit deviceConnected(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: For some reason, OpenVR and OVR don't need this,
|
|
||||||
// and the game tick counter works as expected. In XR, it
|
|
||||||
// doesn't behave properly, so we have to emulate vsync delay manually.
|
|
||||||
void OpenXrDisplayPlugin::idle() {
|
|
||||||
float remainingUntilFrame = std::max(0.0f, _lastFrameTime - (1.0f / _estimatedTargetFramerate));
|
|
||||||
std::chrono::duration<float, std::ratio<1>> duration(remainingUntilFrame);
|
|
||||||
std::this_thread::sleep_for(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString OpenXrDisplayPlugin::getName() const {
|
const QString OpenXrDisplayPlugin::getName() const {
|
||||||
return QString("OpenXR: %1").arg(_context->_systemName);
|
return QString("OpenXR: %1").arg(_context->_systemName);
|
||||||
}
|
}
|
||||||
|
@ -337,8 +323,6 @@ void OpenXrDisplayPlugin::resetSensors() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
bool OpenXrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
std::chrono::time_point measureStart = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
_context->pollEvents();
|
_context->pollEvents();
|
||||||
|
|
||||||
if (_context->_shouldQuit) {
|
if (_context->_shouldQuit) {
|
||||||
|
@ -347,112 +331,24 @@ bool OpenXrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_context->_shouldRunFrameCycle) {
|
if (!_context->_shouldRunFrameCycle) {
|
||||||
qCWarning(xr_display_cat, "beginFrameRender: Shoudln't run frame cycle. Skipping renderin frame %d", frameIndex);
|
qCWarning(xr_display_cat, "beginFrameRender: Shouldn't run frame cycle. Skipping renderin frame %d", frameIndex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for present thread
|
|
||||||
// Actually wait for xrEndFrame to happen.
|
|
||||||
bool haveFrameToSubmit = true;
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_haveFrameMutex);
|
|
||||||
haveFrameToSubmit = _haveFrameToSubmit;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (haveFrameToSubmit) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_haveFrameMutex);
|
|
||||||
haveFrameToSubmit = _haveFrameToSubmit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastFrameState = { .type = XR_TYPE_FRAME_STATE };
|
|
||||||
XrResult result = xrWaitFrame(_context->_session, nullptr, &_lastFrameState);
|
|
||||||
|
|
||||||
if (!xrCheck(_context->_instance, result, "xrWaitFrame failed"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!_context->beginFrame())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_context->_lastPredictedDisplayTime = _lastFrameState.predictedDisplayTime;
|
|
||||||
|
|
||||||
std::vector<XrView> eye_views(_viewCount);
|
|
||||||
for (uint32_t i = 0; i < _viewCount; i++) {
|
|
||||||
eye_views[i].type = XR_TYPE_VIEW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Probably shouldn't call xrLocateViews twice. Use only view space views?
|
|
||||||
XrViewLocateInfo eyeViewLocateInfo = {
|
|
||||||
.type = XR_TYPE_VIEW_LOCATE_INFO,
|
|
||||||
.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
|
|
||||||
.displayTime = _lastFrameState.predictedDisplayTime,
|
|
||||||
.space = _context->_viewSpace,
|
|
||||||
};
|
|
||||||
|
|
||||||
XrViewState eyeViewState = { .type = XR_TYPE_VIEW_STATE };
|
|
||||||
|
|
||||||
result = xrLocateViews(_context->_session, &eyeViewLocateInfo, &eyeViewState, _viewCount, &_viewCount, eye_views.data());
|
|
||||||
if (!xrCheck(_context->_instance, result, "Could not locate views"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 2; i++) {
|
|
||||||
vec3 eyePosition = xrVecToGlm(eye_views[i].pose.position);
|
|
||||||
quat eyeOrientation = xrQuatToGlm(eye_views[i].pose.orientation);
|
|
||||||
_eyeOffsets[i] = controller::Pose(eyePosition, eyeOrientation).getMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastViewState = { .type = XR_TYPE_VIEW_STATE };
|
|
||||||
|
|
||||||
XrViewLocateInfo viewLocateInfo = {
|
|
||||||
.type = XR_TYPE_VIEW_LOCATE_INFO,
|
|
||||||
.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
|
|
||||||
.displayTime = _lastFrameState.predictedDisplayTime,
|
|
||||||
.space = _context->_stageSpace,
|
|
||||||
};
|
|
||||||
|
|
||||||
result = xrLocateViews(_context->_session, &viewLocateInfo, &_lastViewState, _viewCount, &_viewCount, _views.value().data());
|
|
||||||
if (!xrCheck(_context->_instance, result, "Could not locate views"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < _viewCount; i++) {
|
|
||||||
_projectionLayerViews[i].pose = _views.value()[i].pose;
|
|
||||||
_projectionLayerViews[i].fov = _views.value()[i].fov;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrSpaceLocation headLocation = {
|
|
||||||
.type = XR_TYPE_SPACE_LOCATION,
|
|
||||||
.pose = XR_INDENTITY_POSE,
|
|
||||||
};
|
|
||||||
xrLocateSpace(_context->_viewSpace, _context->_stageSpace, _lastFrameState.predictedDisplayTime, &headLocation);
|
|
||||||
|
|
||||||
glm::vec3 headPosition = xrVecToGlm(headLocation.pose.position);
|
|
||||||
glm::quat headOrientation = xrQuatToGlm(headLocation.pose.orientation);
|
|
||||||
_context->_lastHeadPose = controller::Pose(headPosition, headOrientation);
|
|
||||||
|
|
||||||
_currentRenderFrameInfo = FrameInfo();
|
_currentRenderFrameInfo = FrameInfo();
|
||||||
_currentRenderFrameInfo.renderPose = _context->_lastHeadPose.getMatrix();
|
_currentRenderFrameInfo.predictedDisplayTime = _lastFrameState.predictedDisplayTime / 1e9;
|
||||||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
|
||||||
|
|
||||||
std::chrono::time_point measureEnd = std::chrono::high_resolution_clock::now();
|
withNonPresentThreadLock([&] {
|
||||||
std::chrono::duration<double, std::ratio<1>> delta = measureEnd - measureStart;
|
_currentRenderFrameInfo.renderPose = _context->_lastHeadPose.getMatrix();
|
||||||
_lastFrameTime = delta.count();
|
_currentRenderFrameInfo.presentPose = _context->_lastHeadPose.getMatrix();
|
||||||
auto newEstimatedFramerate =(1.0f / _lastFrameTime);
|
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||||
if (_estimatedTargetFramerate < newEstimatedFramerate) {
|
});
|
||||||
_estimatedTargetFramerate = newEstimatedFramerate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HmdDisplayPlugin::beginFrameRender(frameIndex);
|
return HmdDisplayPlugin::beginFrameRender(frameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXrDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) {
|
void OpenXrDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) {
|
||||||
OpenGLDisplayPlugin::submitFrame(newFrame);
|
OpenGLDisplayPlugin::submitFrame(newFrame);
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_haveFrameMutex);
|
|
||||||
_haveFrameToSubmit = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXrDisplayPlugin::compositeLayers() {
|
void OpenXrDisplayPlugin::compositeLayers() {
|
||||||
|
@ -468,11 +364,20 @@ void OpenXrDisplayPlugin::compositeLayers() {
|
||||||
|
|
||||||
void OpenXrDisplayPlugin::hmdPresent() {
|
void OpenXrDisplayPlugin::hmdPresent() {
|
||||||
if (!_context->_shouldRunFrameCycle) {
|
if (!_context->_shouldRunFrameCycle) {
|
||||||
qCWarning(xr_display_cat, "hmdPresent: Shoudln't run frame cycle. Skipping renderin frame %d",
|
qCWarning(xr_display_cat, "hmdPresent: Shouldn't run frame cycle. Skipping renderin frame %d",
|
||||||
_currentFrame->frameIndex);
|
_currentFrame->frameIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_lastFrameState = { .type = XR_TYPE_FRAME_STATE };
|
||||||
|
XrResult result = xrWaitFrame(_context->_session, nullptr, &_lastFrameState);
|
||||||
|
|
||||||
|
if (!xrCheck(_context->_instance, result, "xrWaitFrame failed"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_context->beginFrame())
|
||||||
|
return;
|
||||||
|
|
||||||
if (_lastFrameState.shouldRender) {
|
if (_lastFrameState.shouldRender) {
|
||||||
// TODO: Use multiview swapchain
|
// TODO: Use multiview swapchain
|
||||||
for (uint32_t i = 0; i < 2; i++) {
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
@ -509,11 +414,6 @@ void OpenXrDisplayPlugin::hmdPresent() {
|
||||||
endFrame();
|
endFrame();
|
||||||
|
|
||||||
_presentRate.increment();
|
_presentRate.increment();
|
||||||
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_haveFrameMutex);
|
|
||||||
_haveFrameToSubmit = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXrDisplayPlugin::endFrame() {
|
bool OpenXrDisplayPlugin::endFrame() {
|
||||||
|
@ -561,6 +461,67 @@ bool OpenXrDisplayPlugin::isHmdMounted() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXrDisplayPlugin::updatePresentPose() {
|
void OpenXrDisplayPlugin::updatePresentPose() {
|
||||||
|
if (_lastFrameState.predictedDisplayTime == 0) { return; }
|
||||||
|
|
||||||
|
_context->_lastPredictedDisplayTime = _lastFrameState.predictedDisplayTime;
|
||||||
|
|
||||||
|
auto predictedDisplayTime = _lastFrameState.predictedDisplayTime;
|
||||||
|
|
||||||
|
std::vector<XrView> eye_views(_viewCount);
|
||||||
|
for (uint32_t i = 0; i < _viewCount; i++) {
|
||||||
|
eye_views[i].type = XR_TYPE_VIEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Probably shouldn't call xrLocateViews twice. Use only view space views?
|
||||||
|
XrViewLocateInfo eyeViewLocateInfo = {
|
||||||
|
.type = XR_TYPE_VIEW_LOCATE_INFO,
|
||||||
|
.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
|
||||||
|
.displayTime = predictedDisplayTime,
|
||||||
|
.space = _context->_viewSpace,
|
||||||
|
};
|
||||||
|
|
||||||
|
XrViewState eyeViewState = { .type = XR_TYPE_VIEW_STATE };
|
||||||
|
|
||||||
|
XrResult result = xrLocateViews(_context->_session, &eyeViewLocateInfo, &eyeViewState, _viewCount, &_viewCount, eye_views.data());
|
||||||
|
if (!xrCheck(_context->_instance, result, "Could not locate views"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
vec3 eyePosition = xrVecToGlm(eye_views[i].pose.position);
|
||||||
|
quat eyeOrientation = xrQuatToGlm(eye_views[i].pose.orientation);
|
||||||
|
_eyeOffsets[i] = controller::Pose(eyePosition, eyeOrientation).getMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastViewState = { .type = XR_TYPE_VIEW_STATE };
|
||||||
|
|
||||||
|
XrViewLocateInfo viewLocateInfo = {
|
||||||
|
.type = XR_TYPE_VIEW_LOCATE_INFO,
|
||||||
|
.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
|
||||||
|
.displayTime = predictedDisplayTime,
|
||||||
|
.space = _context->_stageSpace,
|
||||||
|
};
|
||||||
|
|
||||||
|
result = xrLocateViews(_context->_session, &viewLocateInfo, &_lastViewState, _viewCount, &_viewCount, _views.value().data());
|
||||||
|
if (!xrCheck(_context->_instance, result, "Could not locate views"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < _viewCount; i++) {
|
||||||
|
_projectionLayerViews[i].pose = _views.value()[i].pose;
|
||||||
|
_projectionLayerViews[i].fov = _views.value()[i].fov;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSpaceLocation headLocation = {
|
||||||
|
.type = XR_TYPE_SPACE_LOCATION,
|
||||||
|
.pose = XR_INDENTITY_POSE,
|
||||||
|
};
|
||||||
|
xrLocateSpace(_context->_viewSpace, _context->_stageSpace, predictedDisplayTime, &headLocation);
|
||||||
|
|
||||||
|
glm::vec3 headPosition = xrVecToGlm(headLocation.pose.position);
|
||||||
|
glm::quat headOrientation = xrQuatToGlm(headLocation.pose.orientation);
|
||||||
|
_context->_lastHeadPose = controller::Pose(headPosition, headOrientation);
|
||||||
|
|
||||||
|
_currentPresentFrameInfo.presentPose = _context->_lastHeadPose.getMatrix();
|
||||||
|
_currentPresentFrameInfo.predictedDisplayTime = _lastFrameState.predictedDisplayTime / 1e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpenXrDisplayPlugin::getRequiredThreadCount() const {
|
int OpenXrDisplayPlugin::getRequiredThreadCount() const {
|
||||||
|
|
|
@ -26,8 +26,6 @@ public:
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void idle() override;
|
|
||||||
|
|
||||||
float getTargetFrameRate() const override;
|
float getTargetFrameRate() const override;
|
||||||
bool hasAsyncReprojection() const override { return true; }
|
bool hasAsyncReprojection() const override { return true; }
|
||||||
|
|
||||||
|
@ -86,7 +84,4 @@ private:
|
||||||
|
|
||||||
bool _haveFrameToSubmit = false;
|
bool _haveFrameToSubmit = false;
|
||||||
std::mutex _haveFrameMutex;
|
std::mutex _haveFrameMutex;
|
||||||
|
|
||||||
float _lastFrameTime;
|
|
||||||
float _estimatedTargetFramerate;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -114,11 +114,6 @@ OpenXrInputPlugin::InputDevice::InputDevice(std::shared_ptr<OpenXrContext> c) :
|
||||||
qCInfo(xr_input_cat) << "Hand tracking supported:" << _context->_handTrackingSupported;
|
qCInfo(xr_input_cat) << "Hand tracking supported:" << _context->_handTrackingSupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenXrInputPlugin::InputDevice::~InputDevice() {
|
|
||||||
if (_handTracker[0] != XR_NULL_HANDLE) { _context->xrDestroyHandTrackerEXT(_handTracker[0]); }
|
|
||||||
if (_handTracker[1] != XR_NULL_HANDLE) { _context->xrDestroyHandTrackerEXT(_handTracker[1]); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenXrInputPlugin::InputDevice::focusOutEvent() {
|
void OpenXrInputPlugin::InputDevice::focusOutEvent() {
|
||||||
_axisStateMap.clear();
|
_axisStateMap.clear();
|
||||||
_buttonPressedMap.clear();
|
_buttonPressedMap.clear();
|
||||||
|
@ -141,6 +136,10 @@ bool OpenXrInputPlugin::InputDevice::triggerHapticPulse(float strength, float du
|
||||||
|
|
||||||
auto path = (index == 0) ? "left_haptic" : "right_haptic";
|
auto path = (index == 0) ? "left_haptic" : "right_haptic";
|
||||||
|
|
||||||
|
// FIXME: sometimes something bugs out and hammers this,
|
||||||
|
// and the controller vibrates really loudly until another
|
||||||
|
// haptic pulse is triggered
|
||||||
|
// The OpenVR plugin has a lock protecting these
|
||||||
if (!_actions.at(path)->applyHaptic(xrDuration, XR_FREQUENCY_UNSPECIFIED, 0.5f * strength)) {
|
if (!_actions.at(path)->applyHaptic(xrDuration, XR_FREQUENCY_UNSPECIFIED, 0.5f * strength)) {
|
||||||
qCCritical(xr_input_cat) << "Failed to apply haptic feedback!";
|
qCCritical(xr_input_cat) << "Failed to apply haptic feedback!";
|
||||||
}
|
}
|
||||||
|
@ -418,6 +417,9 @@ bool OpenXrInputPlugin::InputDevice::initActions() {
|
||||||
if (!xrCheck(instance, result, "Failed to create action set."))
|
if (!xrCheck(instance, result, "Failed to create action set."))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// NOTE: The "squeeze" actions have quite a high deadzone in the controller config.
|
||||||
|
// A lot of our controller scripts currently only check for (squeeze > 0),
|
||||||
|
// which means controllers like the Index ones will be way too sensitive.
|
||||||
std::map<std::string, std::pair<std::string, XrActionType>> actionTypes = {
|
std::map<std::string, std::pair<std::string, XrActionType>> actionTypes = {
|
||||||
{"left_primary_click", {"Left Primary", XR_ACTION_TYPE_BOOLEAN_INPUT}},
|
{"left_primary_click", {"Left Primary", XR_ACTION_TYPE_BOOLEAN_INPUT}},
|
||||||
{"left_secondary_click", {"Left Secondary (Tablet)", XR_ACTION_TYPE_BOOLEAN_INPUT}},
|
{"left_secondary_click", {"Left Secondary (Tablet)", XR_ACTION_TYPE_BOOLEAN_INPUT}},
|
||||||
|
|
|
@ -75,8 +75,6 @@ private:
|
||||||
public:
|
public:
|
||||||
InputDevice(std::shared_ptr<OpenXrContext> c);
|
InputDevice(std::shared_ptr<OpenXrContext> c);
|
||||||
|
|
||||||
~InputDevice();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
controller::Input::NamedVector getAvailableInputs() const override;
|
controller::Input::NamedVector getAvailableInputs() const override;
|
||||||
QString getDefaultMappingConfig() const override;
|
QString getDefaultMappingConfig() const override;
|
||||||
|
|
|
@ -51,9 +51,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value === 1 && Controller.Hardware.OculusTouch !== undefined) {
|
if (Controller.Hardware.Vive !== undefined) {
|
||||||
rotate180();
|
|
||||||
} else if (Controller.Hardware.Vive !== undefined) {
|
|
||||||
if (value > 0.75 && inFlipTurn === false) {
|
if (value > 0.75 && inFlipTurn === false) {
|
||||||
inFlipTurn = true;
|
inFlipTurn = true;
|
||||||
rotate180();
|
rotate180();
|
||||||
|
@ -61,6 +59,8 @@
|
||||||
inFlipTurn = false;
|
inFlipTurn = false;
|
||||||
}, TURN_RATE);
|
}, TURN_RATE);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
rotate180();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
@ -71,9 +71,7 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value === 1 && Controller.Hardware.OculusTouch !== undefined) {
|
if (Controller.Hardware.Vive !== undefined) {
|
||||||
rotate180();
|
|
||||||
} else if (Controller.Hardware.Vive !== undefined) {
|
|
||||||
if (value > 0.75 && inFlipTurn === false) {
|
if (value > 0.75 && inFlipTurn === false) {
|
||||||
inFlipTurn = true;
|
inFlipTurn = true;
|
||||||
rotate180();
|
rotate180();
|
||||||
|
@ -81,6 +79,8 @@
|
||||||
inFlipTurn = false;
|
inFlipTurn = false;
|
||||||
}, TURN_RATE);
|
}, TURN_RATE);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
rotate180();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
registerBasicMapping();
|
registerBasicMapping();
|
||||||
|
|
||||||
Script.setTimeout(function() {
|
Script.setTimeout(function() {
|
||||||
if (MyAvatar.useAdvanceMovementControls) {
|
if (MyAvatar.useAdvancedMovementControls) {
|
||||||
Controller.disableMapping(DRIVING_MAPPING_NAME);
|
Controller.disableMapping(DRIVING_MAPPING_NAME);
|
||||||
} else {
|
} else {
|
||||||
Controller.enableMapping(DRIVING_MAPPING_NAME);
|
Controller.enableMapping(DRIVING_MAPPING_NAME);
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
|
|
||||||
HMD.displayModeChanged.connect(function(isHMDMode) {
|
HMD.displayModeChanged.connect(function(isHMDMode) {
|
||||||
if (isHMDMode) {
|
if (isHMDMode) {
|
||||||
if (Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) {
|
if (Controller.Hardware.OpenXR !== undefined || Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) {
|
||||||
if (MyAvatar.useAdvancedMovementControls) {
|
if (MyAvatar.useAdvancedMovementControls) {
|
||||||
Controller.disableMapping(DRIVING_MAPPING_NAME);
|
Controller.disableMapping(DRIVING_MAPPING_NAME);
|
||||||
} else {
|
} else {
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
|
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
if ((Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) && HMD.active) {
|
if ((Controller.Hardware.OpenXR !== undefined || Controller.Hardware.Vive !== undefined || Controller.Hardware.OculusTouch !== undefined) && HMD.active) {
|
||||||
var flying = MyAvatar.getFlyingEnabled();
|
var flying = MyAvatar.getFlyingEnabled();
|
||||||
var driving = MyAvatar.useAdvancedMovementControls;
|
var driving = MyAvatar.useAdvancedMovementControls;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue