mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 11:29:50 +02:00
Merge pull request #8462 from jherico/openvr_random_position_fix
Address issues with random camera locations
This commit is contained in:
commit
140b0c4d02
3 changed files with 62 additions and 31 deletions
|
@ -516,13 +516,23 @@ glm::mat4 MyAvatar::getSensorToWorldMatrix() const {
|
||||||
return _sensorToWorldMatrixCache.get();
|
return _sensorToWorldMatrixCache.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As far as I know no HMD system supports a play area of a kilometer in radius.
|
||||||
|
static const float MAX_HMD_ORIGIN_DISTANCE = 1000.0f;
|
||||||
// Pass a recent sample of the HMD to the avatar.
|
// Pass a recent sample of the HMD to the avatar.
|
||||||
// This can also update the avatar's position to follow the HMD
|
// This can also update the avatar's position to follow the HMD
|
||||||
// as it moves through the world.
|
// as it moves through the world.
|
||||||
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
// update the sensorMatrices based on the new hmd pose
|
// update the sensorMatrices based on the new hmd pose
|
||||||
_hmdSensorMatrix = hmdSensorMatrix;
|
_hmdSensorMatrix = hmdSensorMatrix;
|
||||||
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
auto newHmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
||||||
|
|
||||||
|
if (newHmdSensorPosition != _hmdSensorPosition &&
|
||||||
|
glm::length(newHmdSensorPosition) > MAX_HMD_ORIGIN_DISTANCE) {
|
||||||
|
qWarning() << "Invalid HMD sensor position " << newHmdSensorPosition;
|
||||||
|
// Ignore unreasonable HMD sensor data
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_hmdSensorPosition = newHmdSensorPosition;
|
||||||
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
|
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
|
||||||
_hmdSensorFacing = getFacingDir2D(_hmdSensorOrientation);
|
_hmdSensorFacing = getFacingDir2D(_hmdSensorOrientation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,19 +108,20 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateSource() {
|
void updateSource() {
|
||||||
Lock lock(_plugin._presentMutex);
|
_plugin.withNonPresentThreadLock([&] {
|
||||||
while (!_queue.empty()) {
|
while (!_queue.empty()) {
|
||||||
auto& front = _queue.front();
|
auto& front = _queue.front();
|
||||||
auto result = glClientWaitSync(front.fence, 0, 0);
|
auto result = glClientWaitSync(front.fence, 0, 0);
|
||||||
if (GL_TIMEOUT_EXPIRED == result && GL_WAIT_FAILED == result) {
|
if (GL_TIMEOUT_EXPIRED == result && GL_WAIT_FAILED == result) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteSync(front.fence);
|
glDeleteSync(front.fence);
|
||||||
front.fence = 0;
|
front.fence = 0;
|
||||||
_current = front;
|
_current = front;
|
||||||
_queue.pop();
|
_queue.pop();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() override {
|
void run() override {
|
||||||
|
@ -170,15 +171,28 @@ public:
|
||||||
PoseData nextRender, nextSim;
|
PoseData nextRender, nextSim;
|
||||||
nextRender.frameIndex = _plugin.presentCount();
|
nextRender.frameIndex = _plugin.presentCount();
|
||||||
vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount);
|
vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount);
|
||||||
{
|
|
||||||
Lock lock(_plugin._presentMutex);
|
// Copy invalid poses in nextSim from nextRender
|
||||||
_presentCount++;
|
for (uint32_t i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i) {
|
||||||
_presented.notify_one();
|
if (!nextSim.vrPoses[i].bPoseIsValid) {
|
||||||
_nextRender = nextRender;
|
nextSim.vrPoses[i] = nextRender.vrPoses[i];
|
||||||
_nextRender.update(_plugin._sensorResetMat);
|
}
|
||||||
_nextSim = nextSim;
|
|
||||||
_nextSim.update(_plugin._sensorResetMat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mat4 sensorResetMat;
|
||||||
|
_plugin.withNonPresentThreadLock([&] {
|
||||||
|
sensorResetMat = _plugin._sensorResetMat;
|
||||||
|
});
|
||||||
|
|
||||||
|
nextRender.update(sensorResetMat);
|
||||||
|
nextSim.update(sensorResetMat);
|
||||||
|
|
||||||
|
_plugin.withNonPresentThreadLock([&] {
|
||||||
|
_nextRender = nextRender;
|
||||||
|
_nextSim = nextSim;
|
||||||
|
++_presentCount;
|
||||||
|
_presented.notify_one();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_canvas.doneCurrent();
|
_canvas.doneCurrent();
|
||||||
}
|
}
|
||||||
|
@ -366,19 +380,20 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
_currentRenderFrameInfo = FrameInfo();
|
_currentRenderFrameInfo = FrameInfo();
|
||||||
|
|
||||||
|
PoseData nextSimPoseData;
|
||||||
withNonPresentThreadLock([&] {
|
withNonPresentThreadLock([&] {
|
||||||
_currentRenderFrameInfo.renderPose = _nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd];
|
nextSimPoseData = _nextSimPoseData;
|
||||||
});
|
});
|
||||||
|
|
||||||
// HACK: when interface is launched and steam vr is NOT running, openvr will return bad HMD poses for a few frames
|
// HACK: when interface is launched and steam vr is NOT running, openvr will return bad HMD poses for a few frames
|
||||||
// To workaround this, filter out any hmd poses that are obviously bad, i.e. beneath the floor.
|
// To workaround this, filter out any hmd poses that are obviously bad, i.e. beneath the floor.
|
||||||
if (isBadPose(&_nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking)) {
|
if (isBadPose(&nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking)) {
|
||||||
qDebug() << "WARNING: ignoring bad hmd pose from openvr";
|
qDebug() << "WARNING: ignoring bad hmd pose from openvr";
|
||||||
|
|
||||||
// use the last known good HMD pose
|
// use the last known good HMD pose
|
||||||
_nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking = _lastGoodHMDPose;
|
nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking = _lastGoodHMDPose;
|
||||||
} else {
|
} else {
|
||||||
_lastGoodHMDPose = _nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking;
|
_lastGoodHMDPose = nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
vr::TrackedDeviceIndex_t handIndices[2] { vr::k_unTrackedDeviceIndexInvalid, vr::k_unTrackedDeviceIndexInvalid };
|
vr::TrackedDeviceIndex_t handIndices[2] { vr::k_unTrackedDeviceIndexInvalid, vr::k_unTrackedDeviceIndexInvalid };
|
||||||
|
@ -387,7 +402,7 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
auto trackedCount = _system->GetSortedTrackedDeviceIndicesOfClass(vr::TrackedDeviceClass_Controller, controllerIndices, 2);
|
auto trackedCount = _system->GetSortedTrackedDeviceIndicesOfClass(vr::TrackedDeviceClass_Controller, controllerIndices, 2);
|
||||||
// Find the left and right hand controllers, if they exist
|
// Find the left and right hand controllers, if they exist
|
||||||
for (uint32_t i = 0; i < std::min<uint32_t>(trackedCount, 2); ++i) {
|
for (uint32_t i = 0; i < std::min<uint32_t>(trackedCount, 2); ++i) {
|
||||||
if (_nextSimPoseData.vrPoses[i].bPoseIsValid) {
|
if (nextSimPoseData.vrPoses[i].bPoseIsValid) {
|
||||||
auto role = _system->GetControllerRoleForTrackedDeviceIndex(controllerIndices[i]);
|
auto role = _system->GetControllerRoleForTrackedDeviceIndex(controllerIndices[i]);
|
||||||
if (vr::TrackedControllerRole_LeftHand == role) {
|
if (vr::TrackedControllerRole_LeftHand == role) {
|
||||||
handIndices[0] = controllerIndices[i];
|
handIndices[0] = controllerIndices[i];
|
||||||
|
@ -398,8 +413,7 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentRenderFrameInfo.renderPose = _nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd];
|
_currentRenderFrameInfo.renderPose = nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd];
|
||||||
|
|
||||||
bool keyboardVisible = isOpenVrKeyboardShown();
|
bool keyboardVisible = isOpenVrKeyboardShown();
|
||||||
|
|
||||||
std::array<mat4, 2> handPoses;
|
std::array<mat4, 2> handPoses;
|
||||||
|
@ -409,9 +423,9 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto deviceIndex = handIndices[i];
|
auto deviceIndex = handIndices[i];
|
||||||
const mat4& mat = _nextSimPoseData.poses[deviceIndex];
|
const mat4& mat = nextSimPoseData.poses[deviceIndex];
|
||||||
const vec3& linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex];
|
const vec3& linearVelocity = nextSimPoseData.linearVelocities[deviceIndex];
|
||||||
const vec3& angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex];
|
const vec3& angularVelocity = nextSimPoseData.angularVelocities[deviceIndex];
|
||||||
auto correctedPose = openVrControllerPoseToHandPose(i == 0, mat, linearVelocity, angularVelocity);
|
auto correctedPose = openVrControllerPoseToHandPose(i == 0, mat, linearVelocity, angularVelocity);
|
||||||
static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y);
|
static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y);
|
||||||
handPoses[i] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
|
handPoses[i] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
|
||||||
|
|
|
@ -66,8 +66,15 @@ struct PoseData {
|
||||||
vec3 linearVelocities[vr::k_unMaxTrackedDeviceCount];
|
vec3 linearVelocities[vr::k_unMaxTrackedDeviceCount];
|
||||||
vec3 angularVelocities[vr::k_unMaxTrackedDeviceCount];
|
vec3 angularVelocities[vr::k_unMaxTrackedDeviceCount];
|
||||||
|
|
||||||
|
PoseData() {
|
||||||
|
memset(vrPoses, 0, sizeof(vr::TrackedDevicePose_t) * vr::k_unMaxTrackedDeviceCount);
|
||||||
|
}
|
||||||
|
|
||||||
void update(const glm::mat4& resetMat) {
|
void update(const glm::mat4& resetMat) {
|
||||||
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||||
|
if (!vrPoses[i].bPoseIsValid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
poses[i] = resetMat * toGlm(vrPoses[i].mDeviceToAbsoluteTracking);
|
poses[i] = resetMat * toGlm(vrPoses[i].mDeviceToAbsoluteTracking);
|
||||||
linearVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vVelocity));
|
linearVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vVelocity));
|
||||||
angularVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vAngularVelocity));
|
angularVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vAngularVelocity));
|
||||||
|
|
Loading…
Reference in a new issue