Avatar snap-turn rotation smoothing (sent out from the local client outward).

This commit is contained in:
trent 2017-04-27 16:12:25 -04:00
parent 2963d3d212
commit 53f47c132f
3 changed files with 51 additions and 2 deletions

View file

@ -375,6 +375,10 @@ void MyAvatar::update(float deltaTime) {
float tau = deltaTime / HMD_FACING_TIMESCALE;
_hmdSensorFacingMovingAverage = lerp(_hmdSensorFacingMovingAverage, _hmdSensorFacing, tau);
if (_smoothOrientationTimer < _smoothOrientationTime) {
_smoothOrientationTimer = min(_smoothOrientationTimer + deltaTime, _smoothOrientationTime);
}
#ifdef DEBUG_DRAW_HMD_MOVING_AVERAGE
glm::vec3 p = transformPoint(getSensorToWorldMatrix(), _hmdSensorPosition + glm::vec3(_hmdSensorFacingMovingAverage.x, 0.0f, _hmdSensorFacingMovingAverage.y));
DebugDraw::getInstance().addMarker("facing-avg", getOrientation(), p, glm::vec4(1.0f));
@ -1742,8 +1746,10 @@ void MyAvatar::updateOrientation(float deltaTime) {
// Comfort Mode: If you press any of the left/right rotation drive keys or input, you'll
// get an instantaneous 15 degree turn. If you keep holding the key down you'll get another
// snap turn every half second.
bool snapTurn = false;
if (getDriveKey(STEP_YAW) != 0.0f) {
totalBodyYaw += getDriveKey(STEP_YAW);
snapTurn = true;
}
// use head/HMD orientation to turn while flying
@ -1776,10 +1782,17 @@ void MyAvatar::updateOrientation(float deltaTime) {
totalBodyYaw += (speedFactor * deltaAngle * (180.0f / PI));
}
// update body orientation by movement inputs
glm::quat initialOrientation = getOrientation();
setOrientation(getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
if (snapTurn) {
// Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position.
_smoothOrientationInitial = initialOrientation;
_smoothOrientationTarget = getOrientation();
_smoothOrientationTimer = 0.0f;
}
getHead()->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime);
if (qApp->isHMDMode()) {

View file

@ -67,7 +67,11 @@ AvatarData::AvatarData() :
_displayNameAlpha(1.0f),
_errorLogExpiry(0),
_owningAvatarMixer(),
_targetVelocity(0.0f)
_targetVelocity(0.0f),
_smoothOrientationTime(SMOOTH_TIME_ORIENTATION),
_smoothOrientationTimer(std::numeric_limits<float>::max()),
_smoothOrientationInitial(),
_smoothOrientationTarget()
{
setBodyPitch(0.0f);
setBodyYaw(-90.0f);
@ -1460,6 +1464,17 @@ void AvatarData::parseAvatarIdentityPacket(const QByteArray& data, Identity& ide
packetStream >> identityOut.uuid >> identityOut.skeletonModelURL >> identityOut.attachmentData >> identityOut.displayName >> identityOut.sessionDisplayName >> identityOut.avatarEntityData;
}
glm::quat AvatarData::getLocalOrientation() const {
if (!isMyAvatar() || (_smoothOrientationTimer > _smoothOrientationTime)) {
return (SpatiallyNestable::getLocalOrientation());
}
// Smooth the remote avatar movement.
float t = _smoothOrientationTimer / _smoothOrientationTime;
float l = easeInOutQuad(glm::clamp(t, 0.0f, 1.0f));
return (slerp(_smoothOrientationInitial, _smoothOrientationTarget, l));
}
static const QUrl emptyURL("");
QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const {
// We don't put file urls on the wire, but instead convert to empty.

View file

@ -603,6 +603,9 @@ public:
bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_UPDATE_TIMEOUT; }
// Overload the local orientation function for this.
virtual glm::quat getLocalOrientation() const override;
static const float OUT_OF_VIEW_PENALTY;
static void sortAvatars(
@ -619,7 +622,16 @@ public:
static float _avatarSortCoefficientCenter;
static float _avatarSortCoefficientAge;
// Basic ease-in-ease-out function for smoothing values.
static inline float easeInOutQuad(float lerpValue) {
assert(!((lerpValue < 0.0f) || (lerpValue > 1.0f)));
if (lerpValue < 0.5f) {
return (2.0f * lerpValue * lerpValue);
}
return (lerpValue*(4.0f - 2.0f * lerpValue) - 1.0f);
}
signals:
void displayNameChanged();
@ -778,6 +790,15 @@ protected:
quint64 _audioLoudnessChanged { 0 };
float _audioAverageLoudness { 0.0f };
// Smoothing.
const float SMOOTH_TIME_ORIENTATION = 0.15f;
// Smoothing data for blending from one position/orientation to another on remote agents.
float _smoothOrientationTime;
float _smoothOrientationTimer;
glm::quat _smoothOrientationInitial;
glm::quat _smoothOrientationTarget;
private:
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
static QUrl _defaultFullAvatarModelUrl;