From 74c5b6038f093ac2a02935569a0192bf91c14e49 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Wed, 2 Aug 2023 22:00:12 +0200 Subject: [PATCH] Lower inertia for more precise controls --- interface/src/avatar/MyAvatar.cpp | 19 ++++++++++++------- interface/src/avatar/MyAvatar.h | 6 ++++++ interface/src/ui/PreferencesDialog.cpp | 10 ++++++++++ libraries/physics/src/CharacterController.cpp | 5 +++-- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 258685662d..58c86e5e8a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -79,6 +79,7 @@ using namespace std; const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f; const float YAW_SPEED_DEFAULT = 100.0f; // degrees/sec +const float HMD_YAW_SPEED_DEFAULT = 300.0f; // degrees/sec const float PITCH_SPEED_DEFAULT = 75.0f; // degrees/sec const float MAX_BOOST_SPEED = 0.5f * DEFAULT_AVATAR_MAX_WALKING_SPEED; // action motor gets additive boost below this speed @@ -190,6 +191,7 @@ static int beginEndReactionNameToIndex(const QString& reactionName) { MyAvatar::MyAvatar(QThread* thread) : Avatar(thread), _yawSpeed(YAW_SPEED_DEFAULT), + _hmdYawSpeed(HMD_YAW_SPEED_DEFAULT), _pitchSpeed(PITCH_SPEED_DEFAULT), _scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME), @@ -222,6 +224,7 @@ MyAvatar::MyAvatar(QThread* thread) : _headPitchSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "", 0.0f), _scaleSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "scale", _targetScale), _yawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "yawSpeed", _yawSpeed), + _hmdYawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "hmdYawSpeed", _hmdYawSpeed), _pitchSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "pitchSpeed", _pitchSpeed), _fullAvatarURLSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()), @@ -1335,6 +1338,7 @@ void MyAvatar::saveData() { _headPitchSetting.set(getHead()->getBasePitch()); _scaleSetting.set(_targetScale); _yawSpeedSetting.set(_yawSpeed); + _hmdYawSpeedSetting.set(_hmdYawSpeed); _pitchSpeedSetting.set(_pitchSpeed); // only save the fullAvatarURL if it has not been overwritten on command line @@ -2094,6 +2098,7 @@ void MyAvatar::loadData() { getHead()->setBasePitch(_headPitchSetting.get()); _yawSpeed = _yawSpeedSetting.get(_yawSpeed); + _hmdYawSpeed = _hmdYawSpeedSetting.get(_hmdYawSpeed); _pitchSpeed = _pitchSpeedSetting.get(_pitchSpeed); _prefOverrideAnimGraphUrl.set(_animGraphURLSetting.get().toString()); @@ -2801,8 +2806,8 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act void MyAvatar::updateMotors() { _characterController.clearMotors(); - const float FLYING_MOTOR_TIMESCALE = 0.05f; - const float WALKING_MOTOR_TIMESCALE = 0.2f; + const float FLYING_MOTOR_TIMESCALE = 0.0002f; // Originally 0.05f; + const float WALKING_MOTOR_TIMESCALE = 0.0002f; // Originally 0.2f; const float INVALID_MOTOR_TIMESCALE = 1.0e6f; float horizontalMotorTimescale; @@ -3540,7 +3545,7 @@ void MyAvatar::setRotationThreshold(float angleRadians) { void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys - float targetSpeed = getDriveKey(YAW) * _yawSpeed; + float targetSpeed = getDriveKey(YAW) * (qApp->isHMDMode() ? _hmdYawSpeed : _yawSpeed); CameraMode mode = qApp->getCamera().getMode(); bool computeLookAt = isReadyForPhysics() && !qApp->isHMDMode() && (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE); @@ -3553,7 +3558,7 @@ void MyAvatar::updateOrientation(float deltaTime) { } if (targetSpeed != 0.0f) { - const float ROTATION_RAMP_TIMESCALE = 0.5f; + const float ROTATION_RAMP_TIMESCALE = (qApp->isHMDMode() ? 0.02f : 0.5f); float blend = deltaTime / ROTATION_RAMP_TIMESCALE; if (blend > 1.0f) { blend = 1.0f; @@ -3561,7 +3566,7 @@ void MyAvatar::updateOrientation(float deltaTime) { _bodyYawDelta = (1.0f - blend) * _bodyYawDelta + blend * targetSpeed; } else if (_bodyYawDelta != 0.0f) { // attenuate body rotation speed - const float ROTATION_DECAY_TIMESCALE = 0.05f; + const float ROTATION_DECAY_TIMESCALE = (qApp->isHMDMode() ? 0.001f : 0.05f); float attenuation = 1.0f - deltaTime / ROTATION_DECAY_TIMESCALE; if (attenuation < 0.0f) { attenuation = 0.0f; @@ -3594,7 +3599,7 @@ void MyAvatar::updateOrientation(float deltaTime) { const glm::vec3 characterForward = getWorldOrientation() * Vectors::UNIT_NEG_Z; float forwardSpeed = glm::dot(characterForward, getWorldVelocity()); - // only enable roll-turns if we are moving forward or backward at greater then MIN_CONTROL_SPEED + // only enable roll-turns if we are moving forward or backward at greater than MIN_CONTROL_SPEED if (fabsf(forwardSpeed) >= MIN_CONTROL_SPEED) { float direction = forwardSpeed > 0.0f ? 1.0f : -1.0f; @@ -4086,7 +4091,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { float finalMaxMotorSpeed = sensorToWorldScale * DEFAULT_AVATAR_MAX_FLYING_SPEED * _walkSpeedScalar; float speedGrowthTimescale = 2.0f; float speedIncreaseFactor = 1.8f * _walkSpeedScalar; - motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale, 0.0f, 1.0f) * speedIncreaseFactor; + motorSpeed *= 1.0f + glm::pow(glm::clamp(deltaTime / speedGrowthTimescale, 0.0f, 1.0f), 0.7f) * speedIncreaseFactor; // use feedback from CharacterController to prevent tunneling under high motorspeed motorSpeed *= _characterController.getCollisionBrakeAttenuationFactor(); const float maxBoostSpeed = sensorToWorldScale * MAX_BOOST_SPEED; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 12104c0ad5..e0653a86ba 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -404,6 +404,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(bool showPlayArea READ getShowPlayArea WRITE setShowPlayArea) Q_PROPERTY(float yawSpeed MEMBER _yawSpeed) + Q_PROPERTY(float hmdYawSpeed MEMBER _hmdYawSpeed) Q_PROPERTY(float pitchSpeed MEMBER _pitchSpeed) Q_PROPERTY(bool hmdRollControlEnabled READ getHMDRollControlEnabled WRITE setHMDRollControlEnabled) @@ -1416,6 +1417,9 @@ public: float getYawSpeed() const { return _yawSpeed; } void setYawSpeed(float speed) { _yawSpeed = speed; } + float getHMDYawSpeed() const { return _hmdYawSpeed; } + void setHMDYawSpeed(float speed) { _hmdYawSpeed = speed; } + static const float ZOOM_MIN; static const float ZOOM_MAX; static const float ZOOM_DEFAULT; @@ -2755,6 +2759,7 @@ private: float _boomLength { ZOOM_DEFAULT }; float _yawSpeed; // degrees/sec + float _hmdYawSpeed; // degrees/sec float _pitchSpeed; // degrees/sec float _driveGear1 { DEFAULT_GEAR_1 }; float _driveGear2 { DEFAULT_GEAR_2 }; @@ -3040,6 +3045,7 @@ private: Setting::Handle _headPitchSetting; Setting::Handle _scaleSetting; Setting::Handle _yawSpeedSetting; + Setting::Handle _hmdYawSpeedSetting; Setting::Handle _pitchSpeedSetting; Setting::Handle _fullAvatarURLSetting; Setting::Handle _fullAvatarModelNameSetting; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index e8c2166d26..dcd9ccb409 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -400,6 +400,16 @@ void setupPreferences() { preference->setItems(items); preferences->addPreference(preference); } + { + auto getter = [myAvatar]()->float { return myAvatar->getHMDYawSpeed(); }; + auto setter = [myAvatar](float value) { myAvatar->setHMDYawSpeed(value); }; + auto preference = new SpinnerSliderPreference(VR_MOVEMENT, "HMD smooth turning sensitivity:", getter, setter); + preference->setMin(50.0f); + preference->setMax(400.0f); + preference->setStep(1); + preference->setDecimals(0); + preferences->addPreference(preference); + } { auto getter = [myAvatar]()->float { return qApp->getCamera().getSensitivity(); }; auto setter = [myAvatar](float value) { qApp->getCamera().setSensitivity(value); }; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 2eaf771ae2..78a3072023 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -927,9 +927,9 @@ void CharacterController::updateState() { const btScalar FLY_TO_GROUND_THRESHOLD = 0.1f * _radius; const btScalar GROUND_TO_FLY_THRESHOLD = 0.8f * _radius + _halfHeight; - const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 250 * MSECS_PER_SECOND; + const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 5 * MSECS_PER_SECOND; // Originally 250 ms const btScalar MIN_HOVER_HEIGHT = _scaleFactor * DEFAULT_AVATAR_MIN_HOVER_HEIGHT; - const quint64 JUMP_TO_HOVER_PERIOD = _scaleFactor < 1.0f ? _scaleFactor * 1100 * MSECS_PER_SECOND : 1100 * MSECS_PER_SECOND; + const quint64 JUMP_TO_HOVER_PERIOD = _scaleFactor < 1.0f ? _scaleFactor * 350 * MSECS_PER_SECOND : 350 * MSECS_PER_SECOND; // Originally 1100 ms // scan for distant floor // rayStart is at center of bottom sphere @@ -1012,6 +1012,7 @@ void CharacterController::updateState() { SET_STATE(State::InAir, "takeoff done"); // compute jumpSpeed based on the scaled jump height for the default avatar in default gravity. + // TODO: we should add scriptable jump height independent of avatar size - it would make making platforming games possible const float jumpHeight = std::max(_scaleFactor * DEFAULT_AVATAR_JUMP_HEIGHT, DEFAULT_AVATAR_MIN_JUMP_HEIGHT); const float jumpSpeed = sqrtf(2.0f * -DEFAULT_AVATAR_GRAVITY * jumpHeight); velocity += jumpSpeed * _currentUp;