From d8f1f4e6b98c9e46d042d726fbff432e4a99aade Mon Sep 17 00:00:00 2001 From: Kung-vr <38249782+Kung-vr@users.noreply.github.com> Date: Fri, 3 Jan 2020 01:25:49 +0900 Subject: [PATCH] Add friction feature to motion tab #344 --- .../motion_page/gravity/GravityGroupBox.qml | 49 +++++++++-- src/settings/internal/settings_controller.h | 4 + src/settings/settings.h | 1 + .../MoveCenterTabController.cpp | 82 +++++++++++++++---- src/tabcontrollers/MoveCenterTabController.h | 8 ++ 5 files changed, 120 insertions(+), 24 deletions(-) diff --git a/src/res/qml/motion_page/gravity/GravityGroupBox.qml b/src/res/qml/motion_page/gravity/GravityGroupBox.qml index 08349ce..975e911 100644 --- a/src/res/qml/motion_page/gravity/GravityGroupBox.qml +++ b/src/res/qml/motion_page/gravity/GravityGroupBox.qml @@ -113,6 +113,43 @@ GroupBox { } } + Item { + Layout.preferredWidth: 40 + } + + MyText { + text: "Friction:" + horizontalAlignment: Text.AlignRight + Layout.rightMargin: 2 + } + + MyTextField { + id: frictionPercentText + text: "0%" + keyBoardUID: 156 + Layout.preferredWidth: 130 + Layout.leftMargin: 5 + horizontalAlignment: Text.AlignHCenter + function onInputEvent(input) { + var val = parseInt(input) + if (!isNaN(val)) { + if ( val > 999 ) + { + val = 999 + } + if ( val < 0 ) + { + val = 0 + } + + MoveCenterTabController.frictionPercent = val + text = MoveCenterTabController.frictionPercent + "%" + } else { + text = MoveCenterTabController.frictionPercent + "%" + } + } + } + Item { Layout.fillWidth: true } @@ -166,14 +203,6 @@ GroupBox { } } - MyPushButton2 { - Layout.preferredWidth: 50 - text: "4x" - onClicked: { - MoveCenterTabController.flingStrength = 4.0 - } - } - } } @@ -183,6 +212,7 @@ GroupBox { gravityStrengthText.text = MoveCenterTabController.gravityStrength.toFixed(2) momentumToggleButton.checked = MoveCenterTabController.momentumSave flingStrengthText.text = MoveCenterTabController.flingStrength.toFixed(2) + frictionPercentText.text = MoveCenterTabController.frictionPercent + "%" } Connections { @@ -200,5 +230,8 @@ GroupBox { onFlingStrengthChanged: { flingStrengthText.text = MoveCenterTabController.flingStrength.toFixed(2) } + onFrictionPercentChanged: { + frictionPercentText.text = MoveCenterTabController.frictionPercent + "%" + } } } diff --git a/src/settings/internal/settings_controller.h b/src/settings/internal/settings_controller.h index 14d5d89..05083ce 100644 --- a/src/settings/internal/settings_controller.h +++ b/src/settings/internal/settings_controller.h @@ -455,6 +455,10 @@ private: SettingCategory::Playspace, QtInfo{ "turnComfortFactor" }, 0 }, + IntSettingValue{ IntSetting::PLAYSPACE_frictionPercent, + SettingCategory::Playspace, + QtInfo{ "frictionPercent" }, + 0 }, IntSettingValue{ IntSetting::APPLICATION_debugState, SettingCategory::Application, diff --git a/src/settings/settings.h b/src/settings/settings.h index 26dc546..c24ccd8 100644 --- a/src/settings/settings.h +++ b/src/settings/settings.h @@ -90,6 +90,7 @@ enum class IntSetting PLAYSPACE_smoothTurnRate, PLAYSPACE_dragComfortFactor, PLAYSPACE_turnComfortFactor, + PLAYSPACE_frictionPercent, APPLICATION_debugState, APPLICATION_customTickRateMs, diff --git a/src/tabcontrollers/MoveCenterTabController.cpp b/src/tabcontrollers/MoveCenterTabController.cpp index 535a714..4a28d62 100644 --- a/src/tabcontrollers/MoveCenterTabController.cpp +++ b/src/tabcontrollers/MoveCenterTabController.cpp @@ -464,6 +464,12 @@ int MoveCenterTabController::smoothTurnRate() const settings::IntSetting::PLAYSPACE_smoothTurnRate ); } +int MoveCenterTabController::frictionPercent() const +{ + return settings::getSetting( + settings::IntSetting::PLAYSPACE_frictionPercent ); +} + void MoveCenterTabController::setSmoothTurnRate( int value, bool notify ) { settings::setSetting( settings::IntSetting::PLAYSPACE_smoothTurnRate, @@ -475,6 +481,17 @@ void MoveCenterTabController::setSmoothTurnRate( int value, bool notify ) } } +void MoveCenterTabController::setFrictionPercent( int value, bool notify ) +{ + settings::setSetting( settings::IntSetting::PLAYSPACE_frictionPercent, + value ); + + if ( notify ) + { + emit frictionPercentChanged( value ); + } +} + bool MoveCenterTabController::adjustChaperone() const { return settings::getSetting( @@ -1929,12 +1946,6 @@ void MoveCenterTabController::gravityToggleAction( void MoveCenterTabController::gravityReverseAction( bool gravityReverseHeld ) { - // detect new press or new release - if ( ( gravityReverseHeld && !m_gravityReversed ) - || ( !gravityReverseHeld && m_gravityReversed ) ) - { - setGravityStrength( gravityStrength() * -1.0f ); - } m_gravityReversed = gravityReverseHeld; } @@ -2374,6 +2385,50 @@ void MoveCenterTabController::updateHandTurn( void MoveCenterTabController::updateGravity() { + float currentGravity = gravityStrength(); + if ( m_gravityReversed ) + { + currentGravity *= -1.0f; + } + double secondsSinceLastGravityUpdate + = std::chrono::duration( std::chrono::steady_clock::now() + - m_lastGravityUpdateTimePoint ) + .count(); + + // apply friction + if ( frictionPercent() > 0 ) + { + // if we have friction and all velocity components are less than + // halt speed, we stop. + if ( abs( m_velocity[0] ) < k_frictionHalt_mps + && abs( m_velocity[1] ) < k_frictionHalt_mps + && abs( m_velocity[2] ) < k_frictionHalt_mps ) + { + m_velocity[0] = 0.0; + m_velocity[1] = 0.0; + m_velocity[2] = 0.0; + } + else + { + // frictionPercent() * 10 is scaler such that at 90fps we + // reduce from terminal velocity (50m/s) to about 1mm/s in 1 + // second using 100% friction. This is an arbitrary scaler, + // but doing a more accurate job would require a performance + // hit of the math pow() function to an arbitrary exponent. + double frictionVelocityMultiplier + = ( 100.0 + - ( static_cast( frictionPercent() * 10 ) + * secondsSinceLastGravityUpdate ) ) + / 100.0; + frictionVelocityMultiplier + = std::clamp( frictionVelocityMultiplier, 0.0, 1.0 ); + + m_velocity[0] *= frictionVelocityMultiplier; + m_velocity[1] *= frictionVelocityMultiplier; + m_velocity[2] *= frictionVelocityMultiplier; + } + } + // prevent velocity underflow if ( std::isnan( m_velocity[0] ) ) { @@ -2405,23 +2460,18 @@ void MoveCenterTabController::updateGravity() m_velocity[2] = 0.0; } - double secondsSinceLastGravityUpdate - = std::chrono::duration( std::chrono::steady_clock::now() - - m_lastGravityUpdateTimePoint ) - .count(); - // are we falling? // note: up is negative y - // note: set to always fall if gravity reversed (strength < 0) - if ( ( m_offsetY < m_gravityFloor ) || ( gravityStrength() < 0 ) ) + // note: set to always fall if gravity reversed (currentGravity < 0) + if ( ( m_offsetY < m_gravityFloor ) || ( currentGravity < 0 ) ) { // check if we're about to land - // note: we don't land if gravity is reversed (strength < 0) + // note: we don't land if gravity is reversed (currentGravity < 0) if ( ( m_offsetY + static_cast( m_velocity[1] * secondsSinceLastGravityUpdate ) >= m_gravityFloor ) - && gravityStrength() >= 0 ) + && currentGravity >= 0 ) { // get ratio of how much from y velocity applied to overcome y // offset and get down to ground. @@ -2462,7 +2512,7 @@ void MoveCenterTabController::updateGravity() // accelerate downward velocity for the next update // note: downward is positive y m_velocity[1] = m_velocity[1] - + ( static_cast( gravityStrength() ) + + ( static_cast( currentGravity ) * secondsSinceLastGravityUpdate ); return; } diff --git a/src/tabcontrollers/MoveCenterTabController.h b/src/tabcontrollers/MoveCenterTabController.h index e8478f8..2ab6b28 100644 --- a/src/tabcontrollers/MoveCenterTabController.h +++ b/src/tabcontrollers/MoveCenterTabController.h @@ -17,6 +17,9 @@ constexpr double k_radiansToCentidegrees = 18000.0 / M_PI; constexpr double k_quaternionInvalidValue = -1000.0; constexpr double k_quaternionUnderIsInvalidValueThreshold = -900.0; constexpr double k_terminalVelocity_mps = 50.0; +// k_frictionHalt_mps must be sufficiently small to allow a single tick of +// gravity through +constexpr double k_frictionHalt_mps = 0.0000001; // give the max offset a buffer to avoid crossing when traveling at astronomical // velocities constexpr double k_maxOpenvrWorkingSetOffest = 39900.0; @@ -53,6 +56,8 @@ class MoveCenterTabController : public QObject NOTIFY snapTurnAngleChanged ) Q_PROPERTY( int smoothTurnRate READ smoothTurnRate WRITE setSmoothTurnRate NOTIFY smoothTurnRateChanged ) + Q_PROPERTY( int frictionPercent READ frictionPercent WRITE + setFrictionPercent NOTIFY frictionPercentChanged ) Q_PROPERTY( bool adjustChaperone READ adjustChaperone WRITE setAdjustChaperone NOTIFY adjustChaperoneChanged ) Q_PROPERTY( bool moveShortcutRight READ moveShortcutRight WRITE @@ -214,6 +219,7 @@ public: int tempRotation() const; int snapTurnAngle() const; int smoothTurnRate() const; + int frictionPercent() const; bool adjustChaperone() const; bool moveShortcutRight() const; bool moveShortcutLeft() const; @@ -285,6 +291,7 @@ public slots: void setTempRotation( int value, bool notify = true ); void setSnapTurnAngle( int value, bool notify = true ); void setSmoothTurnRate( int value, bool notify = true ); + void setFrictionPercent( int value, bool notify = true ); void setAdjustChaperone( bool value, bool notify = true ); void setMoveShortcutRight( bool value, bool notify = true ); @@ -336,6 +343,7 @@ signals: void tempRotationChanged( int value ); void snapTurnAngleChanged( int value ); void smoothTurnRateChanged( int value ); + void frictionPercentChanged( int value ); void adjustChaperoneChanged( bool value ); void moveShortcutRightChanged( bool value ); void moveShortcutLeftChanged( bool value );