From be446f4e962670f97639db5afc8e85ea30222ba6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 1 Mar 2016 15:36:09 -0800 Subject: [PATCH 1/6] MyAvatar: separate rotation, horizontal and vertical HMD follow --- interface/src/avatar/MyAvatar.cpp | 114 +++++++++++++++++++++++------- interface/src/avatar/MyAvatar.h | 19 ++++- 2 files changed, 106 insertions(+), 27 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index fc715eebe9..2b734a29c6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1884,58 +1884,122 @@ void MyAvatar::lateUpdatePalms() { static const float FOLLOW_TIME = 0.5f; -void MyAvatar::FollowHelper::deactivate() { - _timeRemaining = 0.0f; +MyAvatar::FollowHelper::FollowHelper() { + deactivate(); } -void MyAvatar::FollowHelper::activate() { +void MyAvatar::FollowHelper::deactivate() { + for (int i = 0; i < NumFollowTypes; i++) { + deactivate((FollowType)i); + } +} + +void MyAvatar::FollowHelper::deactivate(FollowType type) { + assert(type >= 0 && type < NumFollowTypes); + _timeRemaining[(int)type] = 0.0f; +} + +void MyAvatar::FollowHelper::activate(FollowType type) { + assert(type >= 0 && type < NumFollowTypes); // TODO: Perhaps, the follow time should be proportional to the displacement. - _timeRemaining = FOLLOW_TIME; + _timeRemaining[(int)type] = FOLLOW_TIME; +} + +bool MyAvatar::FollowHelper::isActive(FollowType type) const { + assert(type >= 0 && type < NumFollowTypes); + return _timeRemaining[(int)type] > 0.0f; } bool MyAvatar::FollowHelper::isActive() const { - return _timeRemaining > 0.0f; + for (int i = 0; i < NumFollowTypes; i++) { + if (isActive((FollowType)i)) { + return true; + } + } + return false; } -bool MyAvatar::FollowHelper::shouldActivate(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { - - const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 4.0f); - - glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); - if (glm::dot(myAvatar.getHMDSensorFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD) { - return true; +float MyAvatar::FollowHelper::getMaxTimeRemaining() const { + float max = 0.0f; + for (int i = 0; i < NumFollowTypes; i++) { + if (_timeRemaining[i] > max) { + max = _timeRemaining[i]; + } } + return max; +} - const float CYLINDER_TOP = 0.1f; - const float CYLINDER_BOTTOM = -0.5f; - const float CYLINDER_RADIUS = 0.15f; +void MyAvatar::FollowHelper::decrementTimeRemaining(float dt) { + for (int i = 0; i < NumFollowTypes; i++) { + _timeRemaining[i] -= dt; + } +} + +bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { + const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 4.0f); + glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); + return glm::dot(myAvatar.getHMDSensorFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; +} + +bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { + + const float CYLINDER_RADIUS = 0.15f; glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix); glm::vec3 radialOffset(offset.x, 0.0f, offset.z); float radialDistance = glm::length(radialOffset); - return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM) || (radialDistance > CYLINDER_RADIUS); + return radialDistance > CYLINDER_RADIUS; +} + +bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { + + const float CYLINDER_TOP = 0.1f; + const float CYLINDER_BOTTOM = -1.0f; + + glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix); + glm::vec3 radialOffset(offset.x, 0.0f, offset.z); + float radialDistance = glm::length(radialOffset); + + return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM); } void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) { _desiredBodyMatrix = desiredBodyMatrix; - if (!isActive() && shouldActivate(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { - activate(); + if (!isActive(Rotation) && shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { + activate(Rotation); + } + if (!isActive(Horizontal) && shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { + activate(Horizontal); + } + if (!isActive(Vertical) && shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { + activate(Vertical); } - if (isActive()) { - glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * _desiredBodyMatrix; - myAvatar.getCharacterController()->setFollowParameters(desiredWorldMatrix, _timeRemaining); - } else { - glm::mat4 currentWorldMatrix = myAvatar.getSensorToWorldMatrix() * currentBodyMatrix; - myAvatar.getCharacterController()->setFollowParameters(currentWorldMatrix, 0.0f); + glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * _desiredBodyMatrix; + glm::mat4 currentWorldMatrix = myAvatar.getSensorToWorldMatrix() * currentBodyMatrix; + + AnimPose followWorldPose(currentWorldMatrix); + if (isActive(Rotation)) { + followWorldPose.rot = glmExtractRotation(desiredWorldMatrix); } + if (isActive(Horizontal)) { + glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix); + followWorldPose.trans.x = desiredTranslation.x; + followWorldPose.trans.z = desiredTranslation.z; + } + if (isActive(Vertical)) { + glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix); + followWorldPose.trans.y = desiredTranslation.y; + } + + myAvatar.getCharacterController()->setFollowParameters(followWorldPose, getMaxTimeRemaining()); } glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix) { if (isActive()) { float dt = myAvatar.getCharacterController()->getFollowTime(); - _timeRemaining -= dt; + decrementTimeRemaining(dt); // apply follow displacement to the body matrix. glm::vec3 worldLinearDisplacement = myAvatar.getCharacterController()->getFollowLinearDisplacement(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 637baa3c22..3950e6895f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -392,13 +392,28 @@ private: glm::mat4 _sensorToWorldMatrix; struct FollowHelper { + FollowHelper(); + + enum FollowType { + Rotation = 0, + Horizontal, + Vertical, + NumFollowTypes + }; glm::mat4 _desiredBodyMatrix; - float _timeRemaining { 0.0f }; + float _timeRemaining[NumFollowTypes]; void deactivate(); + void deactivate(FollowType type); void activate(); + void activate(FollowType type); bool isActive() const; - bool shouldActivate(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const; + bool isActive(FollowType followType) const; + float getMaxTimeRemaining() const; + void decrementTimeRemaining(float dt); + bool shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const; + bool shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const; + bool shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const; void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix); glm::mat4 postPhysicsUpdate(const MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix); }; From 2dfc517d146eb2da172b887ea3af11600228bb4e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 1 Mar 2016 16:45:36 -0800 Subject: [PATCH 2/6] MyAvatar: re-center vertically, on x & z drive keys --- interface/src/avatar/MyAvatar.cpp | 7 ++++--- interface/src/avatar/MyAvatar.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2b734a29c6..ac49514d09 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1097,7 +1097,8 @@ void MyAvatar::prepareForPhysicsSimulation() { _characterController.setTargetVelocity(getTargetVelocity()); _characterController.setPositionAndOrientation(getPosition(), getOrientation()); if (qApp->isHMDMode()) { - _follow.prePhysicsUpdate(*this, deriveBodyFromHMDSensor(), _bodySensorMatrix); + bool hasDriveInput = fabsf(_driveKeys[TRANSLATE_X]) > 0.0f || fabsf(_driveKeys[TRANSLATE_Z]) > 0.0f; + _follow.prePhysicsUpdate(*this, deriveBodyFromHMDSensor(), _bodySensorMatrix, hasDriveInput); } else { _follow.deactivate(); } @@ -1964,7 +1965,7 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM); } -void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) { +void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput) { _desiredBodyMatrix = desiredBodyMatrix; if (!isActive(Rotation) && shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { activate(Rotation); @@ -1972,7 +1973,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat if (!isActive(Horizontal) && shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { activate(Horizontal); } - if (!isActive(Vertical) && shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { + if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { activate(Vertical); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 3950e6895f..731cba8153 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -414,7 +414,7 @@ private: bool shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const; bool shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const; bool shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const; - void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix); + void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput); glm::mat4 postPhysicsUpdate(const MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix); }; FollowHelper _follow; From 6e80665107c29c4d294509b66e9f77cbf9e73684 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 1 Mar 2016 17:45:16 -0800 Subject: [PATCH 3/6] MyAvatar: reduced rotation re-center threshold to 30 degrees Also, warning fix for Linux. --- interface/src/avatar/MyAvatar.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ac49514d09..ed5d2b0430 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1937,7 +1937,7 @@ void MyAvatar::FollowHelper::decrementTimeRemaining(float dt) { } bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { - const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 4.0f); + const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); return glm::dot(myAvatar.getHMDSensorFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; } @@ -1959,9 +1959,6 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co const float CYLINDER_BOTTOM = -1.0f; glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix); - glm::vec3 radialOffset(offset.x, 0.0f, offset.z); - float radialDistance = glm::length(radialOffset); - return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM); } From dc456cbdbebbabf7c1518cc8e79db0aed3d720e7 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 4 Mar 2016 11:15:11 -0800 Subject: [PATCH 4/6] MyAvatar: dropped vertical recenter limit. --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ed5d2b0430..92a449f1dc 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1956,7 +1956,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { const float CYLINDER_TOP = 0.1f; - const float CYLINDER_BOTTOM = -1.0f; + const float CYLINDER_BOTTOM = -1.5f; glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix); return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM); From 37ba0ecd9f4b6cdb94fa28279edfaf4d8f8147af Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 4 Mar 2016 11:48:55 -0800 Subject: [PATCH 5/6] MyAvatar: prevent face from being visible when crouching Overall, this should fix many of the issues with the head being visible when it shouldn't. --- interface/src/avatar/MyAvatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 92a449f1dc..21eff99f48 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1340,11 +1340,11 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { _prevShouldDrawHead = shouldDrawHead; } -const float RENDER_HEAD_CUTOFF_DISTANCE = 0.6f; +const float RENDER_HEAD_CUTOFF_DISTANCE = 0.3f; bool MyAvatar::cameraInsideHead() const { const glm::vec3 cameraPosition = qApp->getCamera()->getPosition(); - return glm::length(cameraPosition - getDefaultEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); + return glm::length(cameraPosition - getHeadPosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); } bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { From 0de19d13c4b0af5c3ab285f3d9f5f61140646da3 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 4 Mar 2016 15:28:38 -0800 Subject: [PATCH 6/6] MyAvatar: open up horizontal leaning threshold --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 21eff99f48..642af5c3e9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1944,7 +1944,7 @@ bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, co bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { - const float CYLINDER_RADIUS = 0.15f; + const float CYLINDER_RADIUS = 0.3f; glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix); glm::vec3 radialOffset(offset.x, 0.0f, offset.z);