Merge pull request #7395 from hyperlogic/tony/openvr-crash-on-exit

openvr crash on exit fix
This commit is contained in:
Andrew Meadows 2016-03-21 13:04:45 -07:00
commit 47c4b226ea
13 changed files with 42 additions and 37 deletions

View file

@ -1420,6 +1420,8 @@ void Application::paintGL() {
// FIXME not needed anymore? // FIXME not needed anymore?
_offscreenContext->makeCurrent(); _offscreenContext->makeCurrent();
displayPlugin->updateHeadPose(_frameCount);
// update the avatar with a fresh HMD pose // update the avatar with a fresh HMD pose
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose()); getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
@ -1600,12 +1602,7 @@ void Application::paintGL() {
auto baseProjection = renderArgs._viewFrustum->getProjection(); auto baseProjection = renderArgs._viewFrustum->getProjection();
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>(); auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
float IPDScale = hmdInterface->getIPDScale(); float IPDScale = hmdInterface->getIPDScale();
mat4 headPose = displayPlugin->getHeadPose();
// Tell the plugin what pose we're using to render. In this case we're just using the
// unmodified head pose because the only plugin that cares (the Oculus plugin) uses it
// for rotational timewarp. If we move to support positonal timewarp, we need to
// ensure this contains the full pose composed with the eye offsets.
mat4 headPose = displayPlugin->getHeadPose(_frameCount);
// FIXME we probably don't need to set the projection matrix every frame, // FIXME we probably don't need to set the projection matrix every frame,
// only when the display plugin changes (or in non-HMD modes when the user // only when the display plugin changes (or in non-HMD modes when the user
@ -1622,6 +1619,10 @@ void Application::paintGL() {
mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * IPDScale); mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * IPDScale);
eyeOffsets[eye] = eyeOffsetTransform; eyeOffsets[eye] = eyeOffsetTransform;
// Tell the plugin what pose we're using to render. In this case we're just using the
// unmodified head pose because the only plugin that cares (the Oculus plugin) uses it
// for rotational timewarp. If we move to support positonal timewarp, we need to
// ensure this contains the full pose composed with the eye offsets.
displayPlugin->setEyeRenderPose(_frameCount, eye, headPose * glm::inverse(eyeOffsetTransform)); displayPlugin->setEyeRenderPose(_frameCount, eye, headPose * glm::inverse(eyeOffsetTransform));
eyeProjections[eye] = displayPlugin->getEyeProjection(eye, baseProjection); eyeProjections[eye] = displayPlugin->getEyeProjection(eye, baseProjection);
@ -2977,7 +2978,7 @@ void Application::updateMyAvatarLookAtPosition() {
lookAtPosition.x = -lookAtPosition.x; lookAtPosition.x = -lookAtPosition.x;
} }
if (isHMD) { if (isHMD) {
glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose(_frameCount); glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose();
glm::quat hmdRotation = glm::quat_cast(headPose); glm::quat hmdRotation = glm::quat_cast(headPose);
lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition); lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition);
} else { } else {
@ -4929,7 +4930,7 @@ mat4 Application::getEyeOffset(int eye) const {
mat4 Application::getHMDSensorPose() const { mat4 Application::getHMDSensorPose() const {
if (isHMDMode()) { if (isHMDMode()) {
return getActiveDisplayPlugin()->getHeadPose(_frameCount); return getActiveDisplayPlugin()->getHeadPose();
} }
return mat4(); return mat4();
} }

View file

@ -30,7 +30,6 @@ void AvatarUpdate::synchronousProcess() {
// Keep our own updated value, so that our asynchronous code can consult it. // Keep our own updated value, so that our asynchronous code can consult it.
_isHMDMode = qApp->isHMDMode(); _isHMDMode = qApp->isHMDMode();
auto frameCount = qApp->getFrameCount();
QSharedPointer<AvatarManager> manager = DependencyManager::get<AvatarManager>(); QSharedPointer<AvatarManager> manager = DependencyManager::get<AvatarManager>();
MyAvatar* myAvatar = manager->getMyAvatar(); MyAvatar* myAvatar = manager->getMyAvatar();
@ -38,7 +37,7 @@ void AvatarUpdate::synchronousProcess() {
// transform the head pose from the displayPlugin into avatar coordinates. // transform the head pose from the displayPlugin into avatar coordinates.
glm::mat4 invAvatarMat = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition())); glm::mat4 invAvatarMat = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()));
_headPose = invAvatarMat * (myAvatar->getSensorToWorldMatrix() * qApp->getActiveDisplayPlugin()->getHeadPose(frameCount)); _headPose = invAvatarMat * (myAvatar->getSensorToWorldMatrix() * qApp->getActiveDisplayPlugin()->getHeadPose());
if (!isThreaded()) { if (!isThreaded()) {
process(); process();

View file

@ -1258,7 +1258,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl
if (qApp->isHMDMode()) { if (qApp->isHMDMode()) {
glm::vec3 cameraPosition = qApp->getCamera()->getPosition(); glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
glm::mat4 headPose = qApp->getActiveDisplayPlugin()->getHeadPose(qApp->getFrameCount()); glm::mat4 headPose = qApp->getActiveDisplayPlugin()->getHeadPose();
glm::mat4 leftEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Left); glm::mat4 leftEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Left);
leftEyePose = leftEyePose * headPose; leftEyePose = leftEyePose * headPose;
glm::vec3 leftEyePosition = extractTranslation(leftEyePose); glm::vec3 leftEyePosition = extractTranslation(leftEyePose);

View file

@ -342,7 +342,7 @@ void CompositorHelper::computeHmdPickRay(const glm::vec2& cursorPos, glm::vec3&
} }
glm::mat4 CompositorHelper::getUiTransform() const { glm::mat4 CompositorHelper::getUiTransform() const {
return _currentCamera * glm::inverse(_currentDisplayPlugin->getHeadPose(_currentFrame)); return _currentCamera * glm::inverse(_currentDisplayPlugin->getHeadPose());
} }
//Finds the collision point of a world space ray //Finds the collision point of a world space ray

View file

@ -161,3 +161,7 @@ void HmdDisplayPlugin::updateFrameData() {
Lock lock(_mutex); Lock lock(_mutex);
_currentRenderEyePoses = _renderEyePoses[_currentRenderFrameIndex]; _currentRenderEyePoses = _renderEyePoses[_currentRenderFrameIndex];
} }
glm::mat4 HmdDisplayPlugin::getHeadPose() const {
return _headPoseCache.get();
}

View file

@ -7,6 +7,8 @@
// //
#pragma once #pragma once
#include <ThreadSafeValueCache.h>
#include <QtGlobal> #include <QtGlobal>
#include "../OpenGLDisplayPlugin.h" #include "../OpenGLDisplayPlugin.h"
@ -24,7 +26,7 @@ public:
void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final; void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final;
bool isDisplayVisible() const override { return isHmdMounted(); } bool isDisplayVisible() const override { return isHmdMounted(); }
virtual glm::mat4 getHeadPose() const override;
protected: protected:
virtual void hmdPresent() = 0; virtual void hmdPresent() = 0;
@ -46,6 +48,7 @@ protected:
using EyePoses = std::array<glm::mat4, 2>; using EyePoses = std::array<glm::mat4, 2>;
QMap<uint32_t, EyePoses> _renderEyePoses; QMap<uint32_t, EyePoses> _renderEyePoses;
EyePoses _currentRenderEyePoses; EyePoses _currentRenderEyePoses;
ThreadSafeValueCache<glm::mat4> _headPoseCache { glm::mat4() };
private: private:
bool _enablePreview { false }; bool _enablePreview { false };

View file

@ -121,8 +121,12 @@ public:
static const glm::mat4 transform; return transform; static const glm::mat4 transform; return transform;
} }
virtual glm::mat4 getHeadPose(uint32_t frameIndex) const { // will query the underlying hmd api to compute the most recent head pose
static const glm::mat4 pose; return pose; virtual void updateHeadPose(uint32_t frameIndex) {}
// returns a copy of the most recent head pose, computed via updateHeadPose
virtual glm::mat4 getHeadPose() const {
return glm::mat4();
} }
// Needed for timewarp style features // Needed for timewarp style features

View file

@ -15,14 +15,11 @@ void OculusBaseDisplayPlugin::resetSensors() {
ovr_RecenterPose(_session); ovr_RecenterPose(_session);
} }
glm::mat4 OculusBaseDisplayPlugin::getHeadPose(uint32_t frameIndex) const { void OculusBaseDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
static uint32_t lastFrameSeen = 0;
auto displayTime = ovr_GetPredictedDisplayTime(_session, frameIndex); auto displayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
auto trackingState = ovr_GetTrackingState(_session, displayTime, frameIndex > lastFrameSeen); auto trackingState = ovr_GetTrackingState(_session, displayTime, true);
if (frameIndex > lastFrameSeen) { mat4 headPose = toGlm(trackingState.HeadPose.ThePose);
lastFrameSeen = frameIndex; _headPoseCache.set(headPose);
}
return toGlm(trackingState.HeadPose.ThePose);
} }
bool OculusBaseDisplayPlugin::isSupported() const { bool OculusBaseDisplayPlugin::isSupported() const {

View file

@ -20,7 +20,7 @@ public:
// Stereo specific methods // Stereo specific methods
virtual void resetSensors() override final; virtual void resetSensors() override final;
virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override; virtual void updateHeadPose(uint32_t frameIndex) override;
protected: protected:
void customizeContext() override; void customizeContext() override;

View file

@ -35,14 +35,10 @@ void OculusLegacyDisplayPlugin::resetSensors() {
ovrHmd_RecenterPose(_hmd); ovrHmd_RecenterPose(_hmd);
} }
glm::mat4 OculusLegacyDisplayPlugin::getHeadPose(uint32_t frameIndex) const { void OculusLegacyDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
static uint32_t lastFrameSeen = 0;
if (frameIndex > lastFrameSeen) {
Lock lock(_mutex); Lock lock(_mutex);
_trackingState = ovrHmd_GetTrackingState(_hmd, ovr_GetTimeInSeconds()); _trackingState = ovrHmd_GetTrackingState(_hmd, ovr_GetTimeInSeconds());
lastFrameSeen = frameIndex; _headPoseCache.set(toGlm(_trackingState.HeadPose.ThePose));
}
return toGlm(_trackingState.HeadPose.ThePose);
} }
bool OculusLegacyDisplayPlugin::isSupported() const { bool OculusLegacyDisplayPlugin::isSupported() const {

View file

@ -26,7 +26,7 @@ public:
// Stereo specific methods // Stereo specific methods
virtual void resetSensors() override; virtual void resetSensors() override;
virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override; virtual void updateHeadPose(uint32_t frameIndex) override;
virtual float getTargetFrameRate() override; virtual float getTargetFrameRate() override;

View file

@ -112,7 +112,7 @@ void OpenVrDisplayPlugin::resetSensors() {
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m)); _sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
} }
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const { void OpenVrDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float); float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
float frameDuration = 1.f / displayFrequency; float frameDuration = 1.f / displayFrequency;
@ -139,7 +139,8 @@ glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
_trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity)); _trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity));
_trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity)); _trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity));
} }
return _trackedDevicePoseMat4[0];
_headPoseCache.set(_trackedDevicePoseMat4[0]);
} }
void OpenVrDisplayPlugin::hmdPresent() { void OpenVrDisplayPlugin::hmdPresent() {

View file

@ -27,7 +27,7 @@ public:
// Stereo specific methods // Stereo specific methods
virtual void resetSensors() override; virtual void resetSensors() override;
virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override; virtual void updateHeadPose(uint32_t frameIndex) override;
protected: protected:
void internalActivate() override; void internalActivate() override;