From a04b7ae297794644cda46d1caacfc3ca2f8dcc1e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 15 Nov 2016 11:45:09 -0800 Subject: [PATCH] fix hover-drive in HMD --- interface/src/avatar/MyAvatar.cpp | 32 +++++++++++++------ libraries/physics/src/CharacterController.cpp | 14 +++++--- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 431b971dc6..72675d7a48 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -465,7 +465,9 @@ void MyAvatar::simulate(float deltaTime) { // update sensorToWorldMatrix for camera and hand controllers // before we perform rig animations and IK. - updateSensorToWorldMatrix(_enableVerticalComfortMode ? SensorToWorldUpdateMode::VerticalComfort : SensorToWorldUpdateMode::Vertical); + if (_characterController.getState() != CharacterController::State::Hover) { + updateSensorToWorldMatrix(_enableVerticalComfortMode ? SensorToWorldUpdateMode::VerticalComfort : SensorToWorldUpdateMode::Vertical); + } { PerformanceTimer perfTimer("skeleton"); @@ -1356,7 +1358,8 @@ void MyAvatar::updateMotors() { } if (qApp->isHMDMode()) { - // OUTOFBODY_HACK: motors are applied differently in HMDMode + // OUTOFBODY_HACK: in HMDMode motors are applied differently: a "follow" motor is added + // during the CharacterController's substep } else { if (_isPushing || _isBraking || !_isBeingPushed) { _characterController.addMotor(_actionMotorVelocity, motorRotation, DEFAULT_MOTOR_TIMESCALE, INVALID_MOTOR_TIMESCALE); @@ -1887,12 +1890,17 @@ void MyAvatar::updateActionMotor(float deltaTime) { } void MyAvatar::applyVelocityToSensorToWorldMatrix(const glm::vec3& velocity, float deltaTime) { - glm::vec3 horizontalVelocity(velocity.x, 0.0f, velocity.z); - float speed2 = glm::length2(horizontalVelocity); + glm::vec3 newVelocity = velocity; + if (_characterController.getState() != CharacterController::State::Hover) { + newVelocity -= glm::dot(newVelocity, _worldUpDirection); + } + float speed2 = glm::length2(newVelocity); if (speed2 > MIN_AVATAR_SPEED_SQUARED) { - glm::vec3 position = extractTranslation(_sensorToWorldMatrix) + deltaTime * horizontalVelocity; + glm::vec3 position = extractTranslation(_sensorToWorldMatrix) + deltaTime * newVelocity; // update the position column of matrix - _sensorToWorldMatrix[3] = glm::vec4(position, 1); + glm::mat4 newSensorToWorldMatrix = _sensorToWorldMatrix; + newSensorToWorldMatrix[3] = glm::vec4(position, 1.0f); + setSensorToWorldMatrix(newSensorToWorldMatrix); } } @@ -1929,16 +1937,19 @@ void MyAvatar::updatePosition(float deltaTime) { } if (qApp->isHMDMode()) { - // Apply _actionMotorVelocity directly to the sensorToWorld matrix. glm::quat motorRotation; glm::vec3 worldVelocity = glm::vec3(0.0f); if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) { - glm::quat liftRotation; - swingTwistDecomposition(glmExtractRotation(_sensorToWorldMatrix * getHMDSensorMatrix()), _worldUpDirection, liftRotation, motorRotation); + if (_characterController.getState() == CharacterController::State::Hover || + _characterController.getCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { + motorRotation = glmExtractRotation(_sensorToWorldMatrix * getHMDSensorMatrix()); + } else { + glm::quat liftRotation; + swingTwistDecomposition(glmExtractRotation(_sensorToWorldMatrix * getHMDSensorMatrix()), _worldUpDirection, liftRotation, motorRotation); + } worldVelocity = motorRotation * _actionMotorVelocity; } - // Apply _scriptedMotorVelocity to the sensorToWorld matrix. if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { motorRotation = getHead()->getCameraOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); @@ -1955,6 +1966,7 @@ void MyAvatar::updatePosition(float deltaTime) { const float THRUST_DAMPING_FACTOR = 0.25f; worldVelocity += THRUST_DAMPING_FACTOR * _thrust; + // apply velocity directly to _sensorToWorldMatrix. if (glm::length2(worldVelocity) > FLT_EPSILON) { glm::mat4 worldBodyMatrix = _sensorToWorldMatrix * _bodySensorMatrix; glm::vec3 position = extractTranslation(worldBodyMatrix); diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index b348a773e4..100905dc5b 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -277,10 +277,15 @@ void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar } vel += _followVelocity; const float HORIZONTAL_FOLLOW_TIMESCALE = 0.05f; - const float VERTICAL_FOLLOW_TIMESCALE = (_state == State::Hover) ? HORIZONTAL_FOLLOW_TIMESCALE : 20.0f; + float verticalFollowTimescale = 20.0f; + if (_state == State::Hover) { + verticalFollowTimescale = HORIZONTAL_FOLLOW_TIMESCALE; + } else { + // remove vertical component + vel -= vel.dot(_currentUp) * _currentUp; + } glm::quat worldFrameRotation; // identity - vel.setY(0.0f); // don't allow any vertical component of the follow velocity to enter the _targetVelocity. - addMotor(bulletToGLM(vel), worldFrameRotation, HORIZONTAL_FOLLOW_TIMESCALE, VERTICAL_FOLLOW_TIMESCALE); + addMotor(bulletToGLM(vel), worldFrameRotation, HORIZONTAL_FOLLOW_TIMESCALE, verticalFollowTimescale); } // angular part uses incremental teleports @@ -773,7 +778,8 @@ void CharacterController::updateState() { const btScalar MAX_WALKING_SPEED = 2.5f; bool flyingFast = _state == State::Hover && actualHorizVelocity.length() > (MAX_WALKING_SPEED * 0.75f); - if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) { + if ((_floorDistance < MIN_HOVER_HEIGHT) && + !(jumpButtonHeld || flyingFast || (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD)) { SET_STATE(State::InAir, "near ground"); } else if (((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport) && !flyingFast) { SET_STATE(State::Ground, "touching ground");