From ac8869eb61d8f7f869dbeeabb6ea1eada6bfceb2 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 5 Nov 2018 16:21:19 -0800 Subject: [PATCH 1/2] Bug fix for head trackers in desktop mode Sitting and standing modes work even in desktop mode. We were inadvertently checking for HMD Mode instead of if the head was valid. * A change was made to the ViveControllerManager to return head poses in the correct standing universe when in desktop mode. * The default sensorToWorld matrix in desktop mode is similar to the one returned by the system for Vive and Oculus sensor frame; y = 0 is at floor level. * Sitting mode, walking mode and recentering flags are now visible in the AnimStats. --- interface/resources/qml/AnimStats.qml | 9 ++++++ interface/src/Application.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 16 +++++++---- interface/src/avatar/MyAvatar.h | 6 +++- interface/src/ui/AnimStats.cpp | 29 ++++++++++++++++++++ interface/src/ui/AnimStats.h | 12 ++++++++ plugins/openvr/src/ViveControllerManager.cpp | 10 +------ plugins/openvr/src/ViveControllerManager.h | 4 +-- 8 files changed, 68 insertions(+), 20 deletions(-) diff --git a/interface/resources/qml/AnimStats.qml b/interface/resources/qml/AnimStats.qml index b1900cf0a7..d06a0484cb 100644 --- a/interface/resources/qml/AnimStats.qml +++ b/interface/resources/qml/AnimStats.qml @@ -50,6 +50,9 @@ Item { StatText { text: root.positionText } + StatText { + text: root.recenterText + } StatText { text: "Anim Vars:--------------------------------------------------------------------------------" } @@ -92,6 +95,9 @@ Item { StatText { text: root.rotationText } + StatText { + text: root.sittingText + } StatText { text: "State Machines:---------------------------------------------------------------------------" } @@ -122,6 +128,9 @@ Item { StatText { text: root.velocityText } + StatText { + text: root.walkingText + } StatText { text: "Alpha Values:--------------------------------------------------------------------------" } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 245e6c0017..fab58428ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6471,7 +6471,7 @@ void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const { void Application::resetSensors(bool andReload) { DependencyManager::get()->reset(); DependencyManager::get()->reset(); - getActiveDisplayPlugin()->resetSensors(); + //getActiveDisplayPlugin()->resetSensors(); _overlayConductor.centerUI(); getMyAvatar()->reset(true, andReload); QMetaObject::invokeMethod(DependencyManager::get().data(), "reset", Qt::QueuedConnection); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b3a66f70b8..2592f62da9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -471,7 +471,7 @@ void MyAvatar::updateSitStandState(float newHeightReading, float dt) { const float STANDING_TIMEOUT = 0.3333f; // 1/3 second const float SITTING_UPPER_BOUND = 1.52f; if (!getIsSitStandStateLocked()) { - if (!getIsAway() && qApp->isHMDMode()) { + if (!getIsAway() && getControllerPoseInAvatarFrame(controller::Action::HEAD).isValid()) { if (getIsInSittingState()) { if (newHeightReading > (STANDING_HEIGHT_MULTIPLE * _tippingPoint)) { // if we recenter upwards then no longer in sitting state @@ -720,6 +720,10 @@ void MyAvatar::recalculateChildCauterization() const { _cauterizationNeedsUpdate = true; } +bool MyAvatar::isFollowActive(FollowHelper::FollowType followType) const { + return _follow.isActive(followType); +} + void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object, bool cauterize) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); @@ -1067,9 +1071,9 @@ void MyAvatar::updateSensorToWorldMatrix() { void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedRotation; - bool inHmd = qApp->isHMDMode(); + bool hasHead = getControllerPoseInAvatarFrame(controller::Action::HEAD).isValid(); bool playing = DependencyManager::get()->isPlaying(); - if (inHmd && playing) { + if (hasHead && playing) { return; } @@ -1103,7 +1107,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { Head* head = getHead(); - if (inHmd || playing) { + if (hasHead || playing) { head->setDeltaPitch(estimatedRotation.x); head->setDeltaYaw(estimatedRotation.y); head->setDeltaRoll(estimatedRotation.z); @@ -3480,7 +3484,7 @@ void MyAvatar::triggerRotationRecenter() { // old school meat hook style glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { - glm::vec3 headPosition; + glm::vec3 headPosition(0.0f, _userHeight.get(), 0.0f); glm::quat headOrientation; auto headPose = getControllerPoseInSensorFrame(controller::Action::HEAD); if (headPose.isValid()) { @@ -3799,7 +3803,7 @@ float MyAvatar::computeStandingHeightMode(const controller::Pose& head) { modeInMeters = ((float)mode) / CENTIMETERS_PER_METER; if (!(modeInMeters > getCurrentStandingHeight())) { // if not greater check for a reset - if (getResetMode() && qApp->isHMDMode()) { + if (getResetMode() && getControllerPoseInAvatarFrame(controller::Action::HEAD).isValid()) { setResetMode(false); float resetModeInCentimeters = glm::floor((head.getTranslation().y - MODE_CORRECTION_FACTOR)*CENTIMETERS_PER_METER); modeInMeters = (resetModeInCentimeters / CENTIMETERS_PER_METER); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 799427530a..d4a6f1b4bb 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -54,6 +54,7 @@ Q_DECLARE_METATYPE(AudioListenerMode); class MyAvatar : public Avatar { Q_OBJECT + friend class AnimStats; /**jsdoc * Your avatar is your in-world representation of you. The MyAvatar API is used to manipulate the avatar. @@ -1163,7 +1164,7 @@ public: virtual QVariantList getAttachmentsVariant() const override; virtual void setAttachmentsVariant(const QVariantList& variant) override; - glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); }; + glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); } public slots: @@ -1780,8 +1781,11 @@ private: std::atomic _forceActivateHorizontal { false }; std::atomic _toggleHipsFollowing { true }; }; + FollowHelper _follow; + bool isFollowActive(FollowHelper::FollowType followType) const; + bool _goToPending { false }; bool _physicsSafetyPending { false }; bool _goToSafe { true }; diff --git a/interface/src/ui/AnimStats.cpp b/interface/src/ui/AnimStats.cpp index e3579fa2dc..6317c069f4 100644 --- a/interface/src/ui/AnimStats.cpp +++ b/interface/src/ui/AnimStats.cpp @@ -65,6 +65,35 @@ void AnimStats::updateStats(bool force) { arg(QString::number(localVelocity.z, 'f', 2)); emit velocityTextChanged(); + // print if we are recentering or not. + _recenterText = "Recenter: "; + if (myAvatar->isFollowActive(MyAvatar::FollowHelper::Rotation)) { + _recenterText += "Rotation "; + } + if (myAvatar->isFollowActive(MyAvatar::FollowHelper::Horizontal)) { + _recenterText += "Horizontal "; + } + if (myAvatar->isFollowActive(MyAvatar::FollowHelper::Vertical)) { + _recenterText += "Vertical "; + } + emit recenterTextChanged(); + + // print current standing vs sitting state. + if (myAvatar->getIsInSittingState()) { + _sittingText = "SittingState: Sit"; + } else { + _sittingText = "SittingState: Stand"; + } + emit sittingTextChanged(); + + // print current walking vs leaning state. + if (myAvatar->getIsInWalkingState()) { + _walkingText = "WalkingState: Walk"; + } else { + _walkingText = "WalkingState: Lean"; + } + emit walkingTextChanged(); + // update animation debug alpha values QStringList newAnimAlphaValues; qint64 now = usecTimestampNow(); diff --git a/interface/src/ui/AnimStats.h b/interface/src/ui/AnimStats.h index 7b6aaf7b54..57d2a4f1a6 100644 --- a/interface/src/ui/AnimStats.h +++ b/interface/src/ui/AnimStats.h @@ -22,6 +22,9 @@ class AnimStats : public QQuickItem { Q_PROPERTY(QString positionText READ positionText NOTIFY positionTextChanged) Q_PROPERTY(QString rotationText READ rotationText NOTIFY rotationTextChanged) Q_PROPERTY(QString velocityText READ velocityText NOTIFY velocityTextChanged) + Q_PROPERTY(QString recenterText READ recenterText NOTIFY recenterTextChanged) + Q_PROPERTY(QString sittingText READ sittingText NOTIFY sittingTextChanged) + Q_PROPERTY(QString walkingText READ walkingText NOTIFY walkingTextChanged) public: static AnimStats* getInstance(); @@ -37,6 +40,9 @@ public: QString positionText() const { return _positionText; } QString rotationText() const { return _rotationText; } QString velocityText() const { return _velocityText; } + QString recenterText() const { return _recenterText; } + QString sittingText() const { return _sittingText; } + QString walkingText() const { return _walkingText; } public slots: void forceUpdateStats() { updateStats(true); } @@ -49,6 +55,9 @@ signals: void positionTextChanged(); void rotationTextChanged(); void velocityTextChanged(); + void recenterTextChanged(); + void sittingTextChanged(); + void walkingTextChanged(); private: QStringList _animAlphaValues; @@ -64,6 +73,9 @@ private: QString _positionText; QString _rotationText; QString _velocityText; + QString _recenterText; + QString _sittingText; + QString _walkingText; }; #endif // hifi_AnimStats_h diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 69797340dd..af4f4da18c 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -180,9 +180,6 @@ void ViveControllerManager::setConfigurationSettings(const QJsonObject configura if (isSupported()) { if (configurationSettings.contains("desktopMode")) { _desktopMode = configurationSettings["desktopMode"].toBool(); - if (!_desktopMode) { - _resetMatCalculated = false; - } } if (configurationSettings.contains("hmdDesktopTracking")) { @@ -267,13 +264,8 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu } if (isDesktopMode() && _desktopMode) { - if (!_resetMatCalculated) { - _resetMat = calculateResetMat(); - _resetMatCalculated = true; - } - _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, _nextSimPoseData.vrPoses, vr::k_unMaxTrackedDeviceCount); - _nextSimPoseData.update(_resetMat); + _nextSimPoseData.update(Matrices::IDENTITY); } else if (isDesktopMode()) { _nextSimPoseData.resetToInvalid(); } diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 06e13e1c49..647702ae77 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -213,12 +213,10 @@ private: bool isDesktopMode(); bool _registeredWithInputMapper { false }; bool _modelLoaded { false }; - bool _resetMatCalculated { false }; bool _desktopMode { false }; bool _hmdDesktopTracking { false }; - - glm::mat4 _resetMat { glm::mat4() }; + graphics::Geometry _modelGeometry; gpu::TexturePointer _texture; From ac8281075b5efbe4e7bae99cf3983fe9c1763202 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 5 Nov 2018 17:25:00 -0800 Subject: [PATCH 2/2] Code review feedback Added comment to explain removal of displayPlugin->resetSensors from Application::resetSensors() --- interface/src/Application.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fab58428ca..0f2c5390b2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6468,10 +6468,13 @@ void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const { viewOut = _displayViewFrustum; } +// resentSensors() is a bit of vestigial feature. It used to be used for Oculus DK2 to recenter the view around +// the current head orientation. With the introduction of "room scale" tracking we no longer need that particular +// feature. However, we still use this to reset face trackers, eye trackers, audio and to optionally re-load the avatar +// rig and animations from scratch. void Application::resetSensors(bool andReload) { DependencyManager::get()->reset(); DependencyManager::get()->reset(); - //getActiveDisplayPlugin()->resetSensors(); _overlayConductor.centerUI(); getMyAvatar()->reset(true, andReload); QMetaObject::invokeMethod(DependencyManager::get().data(), "reset", Qt::QueuedConnection);