mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-16 13:52:42 +02:00
OpenXR cleanup 2, electric boogaloo
This commit is contained in:
parent
87132819a8
commit
2f34081d13
8 changed files with 107 additions and 117 deletions
|
@ -11,13 +11,10 @@
|
|||
{ "from": "OpenXR.LeftGrip", "to": "Standard.LeftGrip", "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
||||
{ "from": "OpenXR.RightGrip", "to": "Standard.RightGrip", "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.LX", "to": "Standard.LX" },
|
||||
{ "from": "OpenXR.LY", "to": "Standard.LY" },
|
||||
|
||||
{ "from": "OpenXR.LX", "to": "Actions.TranslateX", "peek": true, "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
||||
{ "from": "OpenXR.LY", "to": "Actions.TranslateZ", "peek": true, "filters": [{ "type": "deadZone", "min": 0.05 }] },
|
||||
|
||||
{ "from": "OpenXR.RX", "to": "Standard.RX"},
|
||||
{ "from": "OpenXR.RX", "to": "Standard.RX" },
|
||||
{ "from": "OpenXR.RY", "to": "Standard.RY" },
|
||||
|
||||
{ "from": "OpenXR.LS", "to": "Standard.LS" },
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Standard to Action",
|
||||
"channels": [
|
||||
{ "from": "Standard.LY",
|
||||
"when": ["Application.RightHandDominant", "!Standard.RY"],
|
||||
"when": ["Application.RightHandDominant"],
|
||||
"to": "Actions.TranslateZ"
|
||||
},
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
|||
{ "from": "Standard.LX",
|
||||
"when": [
|
||||
"Application.InHMD", "!Application.AdvancedMovement", "Application.RightHandDominant",
|
||||
"Application.SnapTurn", "!Standard.RX"
|
||||
"Application.SnapTurn"
|
||||
],
|
||||
"to": "Actions.StepYaw",
|
||||
"filters":
|
||||
|
@ -58,7 +58,7 @@
|
|||
},
|
||||
|
||||
{ "from": "Standard.RY",
|
||||
"when": ["Application.LeftHandDominant", "!Standard.LY"],
|
||||
"when": ["Application.LeftHandDominant"],
|
||||
"to": "Actions.TranslateZ"
|
||||
},
|
||||
|
||||
|
@ -70,7 +70,7 @@
|
|||
{ "from": "Standard.RX",
|
||||
"when": [
|
||||
"Application.InHMD", "!Application.AdvancedMovement", "Application.LeftHandDominant",
|
||||
"Application.SnapTurn", "!Standard.RX"
|
||||
"Application.SnapTurn"
|
||||
],
|
||||
"to": "Actions.StepYaw",
|
||||
"filters":
|
||||
|
|
|
@ -304,6 +304,8 @@ void handleOpenVrEvents() {
|
|||
}
|
||||
}
|
||||
|
||||
// GetEventTypeNameFromEnum is unimplemented in OpenComposite and xrizer
|
||||
#if 0
|
||||
#if DEV_BUILD
|
||||
//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
|
||||
|
@ -317,6 +319,7 @@ void handleOpenVrEvents() {
|
|||
qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,4 +28,4 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
|||
target_compile_definitions(openxr PRIVATE -DDONT_REDEFINE_LERP)
|
||||
endif()
|
||||
|
||||
set_property(TARGET openxr PROPERTY CXX_STANDARD 20)
|
||||
set_property(TARGET openxr PROPERTY CXX_STANDARD 20)
|
||||
|
|
|
@ -30,9 +30,6 @@ constexpr GLint XR_PREFERRED_COLOR_FORMAT = GL_SRGB8_ALPHA8;
|
|||
|
||||
OpenXrDisplayPlugin::OpenXrDisplayPlugin(std::shared_ptr<OpenXrContext> c) {
|
||||
_context = c;
|
||||
_presentOnlyOnce = true;
|
||||
_lastFrameTime = 1.0f / 90.0f;
|
||||
_estimatedTargetFramerate = 90.0f;
|
||||
}
|
||||
|
||||
bool OpenXrDisplayPlugin::isSupported() const {
|
||||
|
@ -88,7 +85,8 @@ glm::mat4 OpenXrDisplayPlugin::getCullingProjection(const glm::mat4& baseProject
|
|||
// but it does do vsync on its own,
|
||||
// so just push out frames as vsync allows
|
||||
float OpenXrDisplayPlugin::getTargetFrameRate() const {
|
||||
return std::numeric_limits<float>::max();
|
||||
// predictedDisplayPeriod is delta nanoseconds, so convert it to frames per second
|
||||
return std::min(1.0f, 1.0f / (_lastFrameState.predictedDisplayPeriod / 1e9f));
|
||||
}
|
||||
|
||||
bool OpenXrDisplayPlugin::initViews() {
|
||||
|
@ -260,15 +258,6 @@ void OpenXrDisplayPlugin::init() {
|
|||
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 {
|
||||
return QString("OpenXR: %1").arg(_context->_systemName);
|
||||
}
|
||||
|
@ -337,8 +326,6 @@ void OpenXrDisplayPlugin::resetSensors() {
|
|||
}
|
||||
|
||||
bool OpenXrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
std::chrono::time_point measureStart = std::chrono::high_resolution_clock::now();
|
||||
|
||||
_context->pollEvents();
|
||||
|
||||
if (_context->_shouldQuit) {
|
||||
|
@ -347,7 +334,7 @@ bool OpenXrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -367,83 +354,8 @@ bool OpenXrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
_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.renderPose = _context->_lastHeadPose.getMatrix();
|
||||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
|
||||
std::chrono::time_point measureEnd = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double, std::ratio<1>> delta = measureEnd - measureStart;
|
||||
_lastFrameTime = delta.count();
|
||||
auto newEstimatedFramerate =(1.0f / _lastFrameTime);
|
||||
if (_estimatedTargetFramerate < newEstimatedFramerate) {
|
||||
_estimatedTargetFramerate = newEstimatedFramerate;
|
||||
}
|
||||
|
||||
return HmdDisplayPlugin::beginFrameRender(frameIndex);
|
||||
}
|
||||
|
||||
|
@ -468,11 +380,22 @@ void OpenXrDisplayPlugin::compositeLayers() {
|
|||
|
||||
void OpenXrDisplayPlugin::hmdPresent() {
|
||||
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);
|
||||
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;
|
||||
|
||||
updatePresentPose();
|
||||
|
||||
if (_lastFrameState.shouldRender) {
|
||||
// TODO: Use multiview swapchain
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
|
@ -561,6 +484,67 @@ bool OpenXrDisplayPlugin::isHmdMounted() const {
|
|||
}
|
||||
|
||||
void OpenXrDisplayPlugin::updatePresentPose() {
|
||||
_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 };
|
||||
|
||||
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 = _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;
|
||||
|
||||
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.renderPose = _context->_lastHeadPose.getMatrix();
|
||||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||
|
||||
_currentPresentFrameInfo.renderPose = _currentRenderFrameInfo.renderPose;
|
||||
_currentPresentFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||
}
|
||||
|
||||
int OpenXrDisplayPlugin::getRequiredThreadCount() const {
|
||||
|
|
|
@ -26,8 +26,6 @@ public:
|
|||
|
||||
void init() override;
|
||||
|
||||
void idle() override;
|
||||
|
||||
float getTargetFrameRate() const override;
|
||||
bool hasAsyncReprojection() const override { return true; }
|
||||
|
||||
|
@ -86,7 +84,4 @@ private:
|
|||
|
||||
bool _haveFrameToSubmit = false;
|
||||
std::mutex _haveFrameMutex;
|
||||
|
||||
float _lastFrameTime;
|
||||
float _estimatedTargetFramerate;
|
||||
};
|
||||
|
|
|
@ -56,6 +56,8 @@ QString OpenXrInputPlugin::configurationLayout() {
|
|||
bool OpenXrInputPlugin::activate() {
|
||||
InputPlugin::activate();
|
||||
|
||||
qCCritical(xr_input_cat) << "OpenXrInputPlugin::activate";
|
||||
|
||||
loadSettings();
|
||||
|
||||
// register with UserInputMapper
|
||||
|
@ -69,6 +71,8 @@ bool OpenXrInputPlugin::activate() {
|
|||
void OpenXrInputPlugin::deactivate() {
|
||||
InputPlugin::deactivate();
|
||||
|
||||
qCCritical(xr_input_cat) << "OpenXrInputPlugin::deactivate";
|
||||
|
||||
_inputDevice->_poseStateMap.clear();
|
||||
|
||||
// unregister with UserInputMapper
|
||||
|
@ -117,6 +121,10 @@ OpenXrInputPlugin::InputDevice::InputDevice(std::shared_ptr<OpenXrContext> c) :
|
|||
OpenXrInputPlugin::InputDevice::~InputDevice() {
|
||||
if (_handTracker[0] != XR_NULL_HANDLE) { _context->xrDestroyHandTrackerEXT(_handTracker[0]); }
|
||||
if (_handTracker[1] != XR_NULL_HANDLE) { _context->xrDestroyHandTrackerEXT(_handTracker[1]); }
|
||||
|
||||
// so we don't accidentally try to destroy them twice
|
||||
_handTracker[0] = XR_NULL_HANDLE;
|
||||
_handTracker[1] = XR_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void OpenXrInputPlugin::InputDevice::focusOutEvent() {
|
||||
|
@ -141,6 +149,9 @@ bool OpenXrInputPlugin::InputDevice::triggerHapticPulse(float strength, float du
|
|||
|
||||
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
|
||||
if (!_actions.at(path)->applyHaptic(xrDuration, XR_FREQUENCY_UNSPECIFIED, 0.5f * strength)) {
|
||||
qCCritical(xr_input_cat) << "Failed to apply haptic feedback!";
|
||||
}
|
||||
|
|
|
@ -51,9 +51,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if (value === 1 && Controller.Hardware.OculusTouch !== undefined) {
|
||||
rotate180();
|
||||
} else if (Controller.Hardware.Vive !== undefined) {
|
||||
if (Controller.Hardware.Vive !== undefined) {
|
||||
if (value > 0.75 && inFlipTurn === false) {
|
||||
inFlipTurn = true;
|
||||
rotate180();
|
||||
|
@ -61,6 +59,8 @@
|
|||
inFlipTurn = false;
|
||||
}, TURN_RATE);
|
||||
}
|
||||
} else {
|
||||
rotate180();
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
@ -71,9 +71,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if (value === 1 && Controller.Hardware.OculusTouch !== undefined) {
|
||||
rotate180();
|
||||
} else if (Controller.Hardware.Vive !== undefined) {
|
||||
if (Controller.Hardware.Vive !== undefined) {
|
||||
if (value > 0.75 && inFlipTurn === false) {
|
||||
inFlipTurn = true;
|
||||
rotate180();
|
||||
|
@ -81,6 +79,8 @@
|
|||
inFlipTurn = false;
|
||||
}, TURN_RATE);
|
||||
}
|
||||
} else {
|
||||
rotate180();
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
@ -96,7 +96,7 @@
|
|||
registerBasicMapping();
|
||||
|
||||
Script.setTimeout(function() {
|
||||
if (MyAvatar.useAdvanceMovementControls) {
|
||||
if (MyAvatar.useAdvancedMovementControls) {
|
||||
Controller.disableMapping(DRIVING_MAPPING_NAME);
|
||||
} else {
|
||||
Controller.enableMapping(DRIVING_MAPPING_NAME);
|
||||
|
@ -112,7 +112,7 @@
|
|||
|
||||
HMD.displayModeChanged.connect(function(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) {
|
||||
Controller.disableMapping(DRIVING_MAPPING_NAME);
|
||||
} else {
|
||||
|
@ -131,7 +131,7 @@
|
|||
|
||||
|
||||
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 driving = MyAvatar.useAdvancedMovementControls;
|
||||
|
||||
|
|
Loading…
Reference in a new issue