mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 02:57:10 +02:00
- Divided the option "Avatar leaning behavior" into two options that work more usefully: "Allow my avatar to stand" and "Allow my avatar to lean" (PreferencesDialog.cpp). Made the necessary fixes so that the avatar can be set to stand only when the user is standing (more details below). - The logic controlling the direction of MyAvatar's action motor is now centralised in calculateScaledDirection (was previously split between there and updateMotors). calculateScaledDirection now returns a velocity in world space. - CharacterController::FollowHelper now uses separate follow timers for rotation, horizontal and vertical (previously followed all three based on the longest of their follow times). Where appropriate, FollowHelper can now snap immediately to the desired rotation/horizontal/vertical independently (see FOLLOW_TIME_IMMEDIATE_SNAP). - FollowHelper::FollowType has therefore moved to CharacterController::FollowType. - MyAvatar::FollowHelper::postPhysicsUpdate: If MyAvatar is not allowed to stand when the user is sitting, this now avoids recentring the body based on the head height. - Removed Q_PROPERTY(MyAvatar::SitStandModelType, as the sitting/standing/leaning model uses different enums now (see setAllowAvatarStandingPreference, setAllowAvatarLeaningPreference). - Removed Q_PROPERTY(bool isSitStandStateLocked which is no longer used, because we now always track the user's real-world sit/stand state, regardless of what we're doing with it. - MyAvatar::FollowHelper::shouldActivateHorizontal: If MyAvatar is not allowed to lean, this now returns true to recentre the footing if the head is outside the base of support. - MyAvatar::FollowHelper::shouldActivateHorizontalCG: If MyAvatar is not allowed to lean, this now always returns true to recentre the footing. Rearranged to avoid computing values that weren't used depending on the conditions. Resolved some duplicated code. - MyAvatar::setUserRecenterModel previously set HMDLeanRecenterEnabled based on the chosen mode, but it got reset when getting out of a sit. Now HMDLeanRecenterEnabled is only controlled by the scripts. - Added Rig::getUnscaledHipsHeight (like getUnscaledEyeHeight). Refactored a little to avoid duplicated code. Added DEFAULT_AVATAR_HIPS_HEIGHT which is the value that Rig::getUnscaledHipsHeight returns when using the default avatar. - Fix for recentring not behaving as requested by the user after getting up from click-to-sit (always behaving like 'Auto') : MyAvatar::endSit now passes false to centerBody for 'forceFollowYPos'. - Fix for incorrect vertical position of the avatar and viewpoint after changing lean recentre mode while not standing in the real world: MyAvatar::setAllowAvatarStandingPreference now calls centerBody with false for 'forceFollowYPos'. - computeHipsInSensorFrame: The code now matches the comments in that it only skips the dampening of the hips rotation if the centre-of-gravity model is being used.
208 lines
7.1 KiB
C++
208 lines
7.1 KiB
C++
//
|
|
// Created by Anthony J. Thibault 2018/08/06
|
|
// Copyright 2018 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#include "AnimStats.h"
|
|
|
|
#include <avatar/AvatarManager.h>
|
|
#include <OffscreenUi.h>
|
|
#include "Menu.h"
|
|
|
|
HIFI_QML_DEF(AnimStats)
|
|
|
|
static AnimStats* INSTANCE{ nullptr };
|
|
|
|
AnimStats* AnimStats::getInstance() {
|
|
Q_ASSERT(INSTANCE);
|
|
return INSTANCE;
|
|
}
|
|
|
|
AnimStats::AnimStats(QQuickItem* parent) : QQuickItem(parent) {
|
|
INSTANCE = this;
|
|
}
|
|
|
|
void AnimStats::updateStats(bool force) {
|
|
QQuickItem* parent = parentItem();
|
|
if (!force) {
|
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::AnimStats)) {
|
|
if (parent->isVisible()) {
|
|
parent->setVisible(false);
|
|
}
|
|
return;
|
|
} else if (!parent->isVisible()) {
|
|
parent->setVisible(true);
|
|
}
|
|
}
|
|
|
|
auto avatarManager = DependencyManager::get<AvatarManager>();
|
|
auto myAvatar = avatarManager->getMyAvatar();
|
|
auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap();
|
|
|
|
glm::vec3 position = myAvatar->getWorldPosition();
|
|
glm::quat rotation = myAvatar->getWorldOrientation();
|
|
glm::vec3 velocity = myAvatar->getWorldVelocity();
|
|
|
|
_positionText = QString("Position: (%1, %2, %3)").
|
|
arg(QString::number(position.x, 'f', 2)).
|
|
arg(QString::number(position.y, 'f', 2)).
|
|
arg(QString::number(position.z, 'f', 2));
|
|
emit positionTextChanged();
|
|
|
|
glm::vec3 eulerRotation = safeEulerAngles(rotation);
|
|
_rotationText = QString("Heading: %1").
|
|
arg(QString::number(glm::degrees(eulerRotation.y), 'f', 2));
|
|
emit rotationTextChanged();
|
|
|
|
// transform velocity into rig coordinate frame. z forward.
|
|
glm::vec3 localVelocity = Quaternions::Y_180 * glm::inverse(rotation) * velocity;
|
|
_velocityText = QString("Local Vel: (%1, %2, %3)").
|
|
arg(QString::number(localVelocity.x, 'f', 2)).
|
|
arg(QString::number(localVelocity.y, 'f', 2)).
|
|
arg(QString::number(localVelocity.z, 'f', 2));
|
|
emit velocityTextChanged();
|
|
|
|
// print if we are recentering or not.
|
|
_recenterText = "Recenter: ";
|
|
if (myAvatar->isFollowActive(CharacterController::FollowType::Rotation)) {
|
|
_recenterText += "Rotation ";
|
|
}
|
|
if (myAvatar->isFollowActive(CharacterController::FollowType::Horizontal)) {
|
|
_recenterText += "Horizontal ";
|
|
}
|
|
if (myAvatar->isFollowActive(CharacterController::FollowType::Vertical)) {
|
|
_recenterText += "Vertical ";
|
|
}
|
|
emit recenterTextChanged();
|
|
|
|
// print current standing vs sitting state.
|
|
if (myAvatar->getIsInSittingState()) {
|
|
_sittingText = "SittingState: Sit";
|
|
} else {
|
|
_sittingText = "SittingState: Stand";
|
|
}
|
|
emit sittingTextChanged();
|
|
|
|
// print current walking vs leaning state.
|
|
if (myAvatar->getIsInWalkingState()) {
|
|
_walkingText = "WalkingState: Walk";
|
|
} else {
|
|
_walkingText = "WalkingState: Lean";
|
|
}
|
|
emit walkingTextChanged();
|
|
|
|
// print current overrideJointText
|
|
int overrideJointCount = myAvatar->getOverrideJointCount();
|
|
_overrideJointText = QString("Override Joint Count: %1").arg(overrideJointCount);
|
|
emit overrideJointTextChanged();
|
|
|
|
// print current flowText
|
|
bool flowActive = myAvatar->getFlowActive();
|
|
_flowText = QString("Flow: %1").arg(flowActive ? "enabled" : "disabled");
|
|
emit flowTextChanged();
|
|
|
|
// print current networkGraphText
|
|
bool networkGraphActive = myAvatar->getNetworkGraphActive();
|
|
_networkGraphText = QString("Network Graph: %1").arg(networkGraphActive ? "enabled" : "disabled");
|
|
emit networkGraphTextChanged();
|
|
|
|
// update animation debug alpha values
|
|
QStringList newAnimAlphaValues;
|
|
qint64 now = usecTimestampNow();
|
|
for (auto& iter : debugAlphaMap) {
|
|
QString key = iter.first;
|
|
float alpha = std::get<0>(iter.second);
|
|
|
|
auto prevIter = _prevDebugAlphaMap.find(key);
|
|
if (prevIter != _prevDebugAlphaMap.end()) {
|
|
float prevAlpha = std::get<0>(prevIter->second);
|
|
if (prevAlpha != alpha) {
|
|
// change detected: reset timer
|
|
_animAlphaValueChangedTimers[key] = now;
|
|
}
|
|
} else {
|
|
// new value: start timer
|
|
_animAlphaValueChangedTimers[key] = now;
|
|
}
|
|
|
|
AnimNodeType type = std::get<1>(iter.second);
|
|
if (type == AnimNodeType::Clip) {
|
|
|
|
// figure out the grayScale color of this line.
|
|
const float LIT_TIME = 20.0f;
|
|
const float FADE_OUT_TIME = 1.0f;
|
|
float grayScale = 0.0f;
|
|
float secondsElapsed = (float)(now - _animAlphaValueChangedTimers[key]) / (float)USECS_PER_SECOND;
|
|
if (secondsElapsed < LIT_TIME) {
|
|
grayScale = 1.0f;
|
|
} else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) {
|
|
grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME;
|
|
} else {
|
|
grayScale = 0.0f;
|
|
}
|
|
|
|
if (grayScale > 0.0f) {
|
|
// append grayScaleColor to start of debug string
|
|
newAnimAlphaValues << QString::number(grayScale, 'f', 2) + "|" + key + ": " + QString::number(alpha, 'f', 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
_animAlphaValues = newAnimAlphaValues;
|
|
_prevDebugAlphaMap = debugAlphaMap;
|
|
|
|
emit animAlphaValuesChanged();
|
|
|
|
// update animation anim vars
|
|
_animVarsList.clear();
|
|
auto animVars = myAvatar->getSkeletonModel()->getRig().getAnimVars().toDebugMap();
|
|
for (auto& iter : animVars) {
|
|
QString key = iter.first;
|
|
QString value = iter.second;
|
|
|
|
auto prevIter = _prevAnimVars.find(key);
|
|
if (prevIter != _prevAnimVars.end()) {
|
|
QString prevValue = prevIter->second;
|
|
if (value != prevValue) {
|
|
// change detected: reset timer
|
|
_animVarChangedTimers[key] = now;
|
|
}
|
|
} else {
|
|
// new value: start timer
|
|
_animVarChangedTimers[key] = now;
|
|
}
|
|
|
|
// figure out the grayScale color of this line.
|
|
const float LIT_TIME = 20.0f;
|
|
const float FADE_OUT_TIME = 0.5f;
|
|
float grayScale = 0.0f;
|
|
float secondsElapsed = (float)(now - _animVarChangedTimers[key]) / (float)USECS_PER_SECOND;
|
|
if (secondsElapsed < LIT_TIME) {
|
|
grayScale = 1.0f;
|
|
} else if (secondsElapsed < LIT_TIME + FADE_OUT_TIME) {
|
|
grayScale = (FADE_OUT_TIME - (secondsElapsed - LIT_TIME)) / FADE_OUT_TIME;
|
|
} else {
|
|
grayScale = 0.0f;
|
|
}
|
|
|
|
if (grayScale > 0.0f) {
|
|
// append grayScaleColor to start of debug string
|
|
_animVarsList << QString::number(grayScale, 'f', 2) + "|" + key + ": " + value;
|
|
}
|
|
}
|
|
_prevAnimVars = animVars;
|
|
emit animVarsChanged();
|
|
|
|
// animation state machines
|
|
_animStateMachines.clear();
|
|
auto stateMachineMap = myAvatar->getSkeletonModel()->getRig().getStateMachineMap();
|
|
for (auto& iter : stateMachineMap) {
|
|
_animStateMachines << iter.second;
|
|
}
|
|
emit animStateMachinesChanged();
|
|
}
|
|
|
|
|