started changes suggested by code review, ie mode computation

This commit is contained in:
amantley 2018-07-06 18:17:13 -07:00
parent 0ebc7fc29e
commit defd6f88e6
2 changed files with 72 additions and 46 deletions

View file

@ -88,6 +88,7 @@ const float MyAvatar::ZOOM_MIN = 0.5f;
const float MyAvatar::ZOOM_MAX = 25.0f; const float MyAvatar::ZOOM_MAX = 25.0f;
const float MyAvatar::ZOOM_DEFAULT = 1.5f; const float MyAvatar::ZOOM_DEFAULT = 1.5f;
const float MIN_SCALE_CHANGED_DELTA = 0.001f; const float MIN_SCALE_CHANGED_DELTA = 0.001f;
const int MODE_READINGS_RING_BUFFER_SIZE = 500;
//#define DEBUG_DRAW_HMD_MOVING_AVERAGE //#define DEBUG_DRAW_HMD_MOVING_AVERAGE
@ -116,7 +117,8 @@ MyAvatar::MyAvatar(QThread* thread) :
_goToOrientation(), _goToOrientation(),
_prevShouldDrawHead(true), _prevShouldDrawHead(true),
_audioListenerMode(FROM_HEAD), _audioListenerMode(FROM_HEAD),
_hmdAtRestDetector(glm::vec3(0), glm::quat()) _hmdAtRestDetector(glm::vec3(0), glm::quat()),
_recentModeReadings(MODE_READINGS_RING_BUFFER_SIZE)
{ {
// give the pointer to our head to inherited _headData variable from AvatarData // give the pointer to our head to inherited _headData variable from AvatarData
@ -2178,7 +2180,8 @@ void MyAvatar::setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement)
} }
void MyAvatar::setRotationRecenterFilterLength(float length) { void MyAvatar::setRotationRecenterFilterLength(float length) {
if (length > 0.01f) { const float MINIMUM_ROTATION_RECENTER_FILTER_LENGTH = 0.01f;
if (length > MINIMUM_ROTATION_RECENTER_FILTER_LENGTH) {
_rotationRecenterFilterLength = length; _rotationRecenterFilterLength = length;
} else { } else {
_rotationRecenterFilterLength = 0.01f; _rotationRecenterFilterLength = 0.01f;
@ -3152,11 +3155,11 @@ glm::mat4 MyAvatar::deriveBodyUsingCgModel() const {
return worldToSensorMat * avatarToWorldMat * avatarHipsMat; return worldToSensorMat * avatarToWorldMat * avatarHipsMat;
} }
static bool isInsideLine(glm::vec3 a, glm::vec3 b, glm::vec3 c) { static bool isInsideLine(const glm::vec3& a, const glm::vec3& b, const glm::vec3& c) {
return (((b.x - a.x) * (c.z - a.z) - (b.z - a.z) * (c.x - a.x)) > 0); return (((b.x - a.x) * (c.z - a.z) - (b.z - a.z) * (c.x - a.x)) > 0);
} }
static bool withinBaseOfSupport(controller::Pose head) { static bool withinBaseOfSupport(const controller::Pose& head) {
float userScale = 1.0f; float userScale = 1.0f;
glm::vec3 frontLeft(-DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD, 0.0f, -DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD); glm::vec3 frontLeft(-DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD, 0.0f, -DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD);
@ -3175,7 +3178,7 @@ static bool withinBaseOfSupport(controller::Pose head) {
return isWithinSupport; return isWithinSupport;
} }
static bool headAngularVelocityBelowThreshold(controller::Pose head) { static bool headAngularVelocityBelowThreshold(const controller::Pose& head) {
glm::vec3 xzPlaneAngularVelocity(0.0f, 0.0f, 0.0f); glm::vec3 xzPlaneAngularVelocity(0.0f, 0.0f, 0.0f);
if (head.isValid()) { if (head.isValid()) {
xzPlaneAngularVelocity.x = head.getAngularVelocity().x; xzPlaneAngularVelocity.x = head.getAngularVelocity().x;
@ -3187,7 +3190,7 @@ static bool headAngularVelocityBelowThreshold(controller::Pose head) {
return isBelowThreshold; return isBelowThreshold;
} }
static bool isWithinThresholdHeightMode(controller::Pose head, float newMode) { static bool isWithinThresholdHeightMode(const controller::Pose& head,const float& newMode) {
bool isWithinThreshold = true; bool isWithinThreshold = true;
if (head.isValid()) { if (head.isValid()) {
isWithinThreshold = (head.getTranslation().y - newMode) > DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD; isWithinThreshold = (head.getTranslation().y - newMode) > DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD;
@ -3195,68 +3198,84 @@ static bool isWithinThresholdHeightMode(controller::Pose head, float newMode) {
return isWithinThreshold; return isWithinThreshold;
} }
float MyAvatar::computeStandingHeightMode(controller::Pose head) { float MyAvatar::computeStandingHeightMode(const controller::Pose& head) {
const float CENTIMETERS_PER_METER = 100.0f; const float CENTIMETERS_PER_METER = 100.0f;
const float MODE_CORRECTION_FACTOR = 0.02f; const float MODE_CORRECTION_FACTOR = 0.02f;
const int MAX_INT = 2147483647; int greatestFrequency = 0;
int mode = 0;
// init mode in meters to the current mode // init mode in meters to the current mode
float modeInMeters = getStandingHeightMode(); float modeInMeters = getStandingHeightMode();
if (head.isValid()) { if (head.isValid()) {
float newReading = head.getTranslation().y; float newReading = head.getTranslation().y;
int newReadingInCentimeters = glm::floor(newReading * CENTIMETERS_PER_METER); int newReadingInCentimeters = glm::floor(newReading * CENTIMETERS_PER_METER);
_heightFrequencyMap[newReadingInCentimeters] += 1; _recentModeReadings.insert(newReadingInCentimeters);
if (_heightFrequencyMap[newReadingInCentimeters] > _greatestFrequency) { RingBufferHistory<quint64>::Iterator recentModeReadingsIterator = _recentModeReadings.begin();
_greatestFrequency = _heightFrequencyMap[newReadingInCentimeters]; RingBufferHistory<quint64>::Iterator end = _recentModeReadings.end();
modeInMeters = ((float)newReadingInCentimeters) / CENTIMETERS_PER_METER; std::map<int, int> freq;
// we need to deal with possible overflow error here do {
if (_greatestFrequency > (MAX_INT/2)) { ++recentModeReadingsIterator;
for (auto & heightValue : _heightFrequencyMap) { freq[*recentModeReadingsIterator] += 1;
if (heightValue.second == _greatestFrequency) { if ((freq[*recentModeReadingsIterator] > greatestFrequency) ||
heightValue.second = 100; (freq[*recentModeReadingsIterator] == MODE_READINGS_RING_BUFFER_SIZE)) {
} else { greatestFrequency = freq[*recentModeReadingsIterator];
heightValue.second = 0; mode = *recentModeReadingsIterator;
}
} }
_greatestFrequency = 100; } while (recentModeReadingsIterator != end);
modeInMeters = ((float)mode) / CENTIMETERS_PER_METER;
if (!(modeInMeters > getStandingHeightMode())) {
// if not greater check for a reset
if (getResetMode() && qApp->isHMDMode()) {
setResetMode(false);
float resetModeInCentimeters = glm::floor((newReading - MODE_CORRECTION_FACTOR)*CENTIMETERS_PER_METER);
modeInMeters = (resetModeInCentimeters / CENTIMETERS_PER_METER);
} else {
// if not greater and no reset, keep the mode as it is
modeInMeters = getStandingHeightMode();
} }
} }
} }
return modeInMeters; return modeInMeters;
} }
static bool handDirectionMatchesHeadDirection(controller::Pose leftHand, controller::Pose rightHand, controller::Pose head) { static bool handDirectionMatchesHeadDirection(const controller::Pose& leftHand, const controller::Pose& rightHand, const controller::Pose& head) {
const float VELOCITY_EPSILON = 0.02f; const float VELOCITY_EPSILON = 0.02f;
bool leftHandDirectionMatchesHead = true; bool leftHandDirectionMatchesHead = true;
bool rightHandDirectionMatchesHead = true; bool rightHandDirectionMatchesHead = true;
glm::vec3 xzHeadVelocity(head.velocity.x, 0.0f, head.velocity.z);
if (leftHand.isValid() && head.isValid()) { if (leftHand.isValid() && head.isValid()) {
leftHand.velocity.y = 0.0f; glm::vec3 xzLeftHandVelocity(leftHand.velocity.x, 0.0f, leftHand.velocity.z);
float handDotHeadLeft = glm::dot(glm::normalize(leftHand.getVelocity()), glm::normalize(head.getVelocity())); float handDotHeadLeft = glm::dot(glm::normalize(xzLeftHandVelocity), glm::normalize(xzHeadVelocity));
leftHandDirectionMatchesHead = ((handDotHeadLeft > DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD) && (glm::length(leftHand.getVelocity()) > VELOCITY_EPSILON)); leftHandDirectionMatchesHead = ((handDotHeadLeft > DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD) && (glm::length(leftHand.getVelocity()) > VELOCITY_EPSILON));
} }
if (rightHand.isValid() && head.isValid()) { if (rightHand.isValid() && head.isValid()) {
rightHand.velocity.y = 0.0f; glm::vec3 xzRightHandVelocity(rightHand.velocity.x, 0.0f, rightHand.velocity.z);
float handDotHeadRight = glm::dot(glm::normalize(rightHand.getVelocity()), glm::normalize(head.getVelocity())); float handDotHeadRight = glm::dot(glm::normalize(xzRightHandVelocity), glm::normalize(xzHeadVelocity));
rightHandDirectionMatchesHead = ((handDotHeadRight > DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD) && (glm::length(rightHand.getVelocity()) > VELOCITY_EPSILON)); rightHandDirectionMatchesHead = ((handDotHeadRight > DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD) && (glm::length(rightHand.getVelocity()) > VELOCITY_EPSILON));
} }
return leftHandDirectionMatchesHead && rightHandDirectionMatchesHead; return leftHandDirectionMatchesHead && rightHandDirectionMatchesHead;
} }
static bool handAngularVelocityBelowThreshold(controller::Pose leftHand, controller::Pose rightHand) { static bool handAngularVelocityBelowThreshold(const controller::Pose& leftHand, const controller::Pose& rightHand) {
float leftHandXZAngularVelocity = 0.0f; float leftHandXZAngularVelocity = 0.0f;
float rightHandXZAngularVelocity = 0.0f; float rightHandXZAngularVelocity = 0.0f;
if (leftHand.isValid()) { if (leftHand.isValid()) {
leftHand.angularVelocity.y = 0.0f; glm::vec3 xzLeftHandAngularVelocity(leftHand.angularVelocity.x, 0.0f, leftHand.angularVelocity.z);
leftHandXZAngularVelocity = glm::length(leftHand.getAngularVelocity()); leftHandXZAngularVelocity = glm::length(xzLeftHandAngularVelocity);
} }
if (rightHand.isValid()) { if (rightHand.isValid()) {
rightHand.angularVelocity.y = 0.0f; glm::vec3 xzRightHandAngularVelocity(rightHand.angularVelocity.x, 0.0f, rightHand.angularVelocity.z);
rightHandXZAngularVelocity = glm::length(rightHand.getAngularVelocity()); rightHandXZAngularVelocity = glm::length(xzRightHandAngularVelocity);
} }
return ((leftHandXZAngularVelocity < DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD) && return ((leftHandXZAngularVelocity < DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD) &&
(rightHandXZAngularVelocity < DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD)); (rightHandXZAngularVelocity < DEFAULT_HANDS_ANGULAR_VELOCITY_STEPPING_THRESHOLD));
} }
static bool headVelocityGreaterThanThreshold(controller::Pose head) { static bool headVelocityGreaterThanThreshold(const controller::Pose& head) {
float headVelocityMagnitude = 0.0f; float headVelocityMagnitude = 0.0f;
if (head.isValid()) { if (head.isValid()) {
headVelocityMagnitude = glm::length(head.getVelocity()); headVelocityMagnitude = glm::length(head.getVelocity());
@ -3264,12 +3283,12 @@ static bool headVelocityGreaterThanThreshold(controller::Pose head) {
return headVelocityMagnitude > DEFAULT_HEAD_VELOCITY_STEPPING_THRESHOLD; return headVelocityMagnitude > DEFAULT_HEAD_VELOCITY_STEPPING_THRESHOLD;
} }
glm::quat MyAvatar::computeAverageHeadRotation(controller::Pose head) { glm::quat MyAvatar::computeAverageHeadRotation(const controller::Pose& head) {
const float AVERAGING_RATE = 0.03f; const float AVERAGING_RATE = 0.03f;
return slerp(_averageHeadRotation, head.getRotation(), AVERAGING_RATE); return safeLerp(_averageHeadRotation, head.getRotation(), AVERAGING_RATE);
} }
static bool isHeadLevel(controller::Pose head, glm::quat averageHeadRotation) { static bool isHeadLevel(const controller::Pose& head, const glm::quat& averageHeadRotation) {
glm::vec3 diffFromAverageEulers(0.0f, 0.0f, 0.0f); glm::vec3 diffFromAverageEulers(0.0f, 0.0f, 0.0f);
if (head.isValid()) { if (head.isValid()) {
glm::vec3 averageHeadEulers = glm::degrees(safeEulerAngles(averageHeadRotation)); glm::vec3 averageHeadEulers = glm::degrees(safeEulerAngles(averageHeadRotation));
@ -3521,22 +3540,29 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
activate(Rotation); activate(Rotation);
} }
if (!isActive(Horizontal) && (shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { if (myAvatar.getCenterOfGravityModelEnabled()){
activate(Horizontal); if (!isActive(Horizontal) && (shouldActivateHorizontalCG(myAvatar) || hasDriveInput)) {
activate(Horizontal);
}
} else {
if (!isActive(Horizontal) && (shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
activate(Horizontal);
}
} }
if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
activate(Vertical); activate(Vertical);
} }
} else { } else {
if (!isActive(Rotation) && (getForceActivateRotation() || shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { if (!isActive(Rotation) && getForceActivateRotation()) {
activate(Rotation); activate(Rotation);
setForceActivateRotation(false); setForceActivateRotation(false);
} }
if (!isActive(Horizontal) && (getForceActivateHorizontal() || shouldActivateHorizontalCG(myAvatar) || hasDriveInput)) { if (!isActive(Horizontal) && getForceActivateHorizontal()) {
activate(Horizontal); activate(Horizontal);
setForceActivateHorizontal(false); setForceActivateHorizontal(false);
} }
if (!isActive(Vertical) && (getForceActivateVertical() || shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { if (!isActive(Vertical) && getForceActivateVertical()) {
activate(Vertical); activate(Vertical);
setForceActivateVertical(false); setForceActivateVertical(false);
} }

View file

@ -31,6 +31,7 @@
#include "AtRestDetector.h" #include "AtRestDetector.h"
#include "MyCharacterController.h" #include "MyCharacterController.h"
#include "RingBufferHistory.h"
#include <ThreadSafeValueCache.h> #include <ThreadSafeValueCache.h>
class AvatarActionHold; class AvatarActionHold;
@ -1023,8 +1024,8 @@ public:
bool isReadyForPhysics() const; bool isReadyForPhysics() const;
float computeStandingHeightMode(controller::Pose head); float computeStandingHeightMode(const controller::Pose& head);
glm::quat computeAverageHeadRotation(controller::Pose head); glm::quat computeAverageHeadRotation(const controller::Pose& head);
public slots: public slots:
@ -1527,8 +1528,7 @@ private:
float _standingHeightMode { 0.0f }; float _standingHeightMode { 0.0f };
bool _resetMode { true }; bool _resetMode { true };
std::map<long int, long int> _heightFrequencyMap; RingBufferHistory<quint64> _recentModeReadings;
long int _greatestFrequency { 0 };
// cache of the current body position and orientation of the avatar's body, // cache of the current body position and orientation of the avatar's body,
// in sensor space. // in sensor space.
@ -1608,7 +1608,7 @@ private:
mutable std::mutex _controllerPoseMapMutex; mutable std::mutex _controllerPoseMapMutex;
bool _centerOfGravityModelEnabled { true }; bool _centerOfGravityModelEnabled { true };
bool _hmdLeanRecenterEnabled { false }; bool _hmdLeanRecenterEnabled { true };
bool _sprint { false }; bool _sprint { false };
AnimPose _prePhysicsRoomPose; AnimPose _prePhysicsRoomPose;