mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-15 21:18:06 +02:00
Fix VR recentering cases that gave incorrect vertical position.
Fix for MyAvatar sometimes hovering off the ground after foot tracking was enabled. MyAvatar's body is now recentered when foot-tracking starts or ends (in MyAvatar::update). Repro: - Start without foot tracking, 'Allow my avatar to stand: Always'. - Crouch, and wait a few seconds for the avatar to pop back to the standing position. - Slowly stand straight so that the avatar raises off the ground without recentering (PS: is this a bug?). If it recenters, retry from previous step. - Calibrate foot tracking. Previously the avatar would remain hovering off the ground until MyAvatar::centerBody was called. Fix for MyAvatar popping to a standing position if the left foot lost tracking. The recentering now takes into account if either of the feet are tracked. Repro: - Enable foot tracking (and ideally hips tracking). - Sit on the floor. - Cover the left foot sensor so it loses tracking. Previously the avatar and viewpoint would pop to a standing position. Optimisation: MyAvatar::update now stores bools indicating which body parts are tracked (_isBodyPartTracked). This avoid unnecessary computations that came from using getControllerPoseInAvatarFrame to convert controller::Pose from sensor space to world space and then to avatar space, only to check if the pose was valid.
This commit is contained in:
parent
3e25e32f18
commit
2be87fe7dc
2 changed files with 43 additions and 23 deletions
|
@ -595,7 +595,7 @@ void MyAvatar::updateSitStandState(float newHeightReading, float dt) {
|
|||
const float SITTING_TIMEOUT = 4.0f; // 4 seconds
|
||||
const float STANDING_TIMEOUT = 0.3333f; // 1/3 second
|
||||
const float SITTING_UPPER_BOUND = 1.52f;
|
||||
if (!getIsAway() && getControllerPoseInAvatarFrame(controller::Action::HEAD).isValid()) {
|
||||
if (!getIsAway() && _isBodyPartTracked._head) {
|
||||
if (getIsInSittingState()) {
|
||||
if (newHeightReading > (STANDING_HEIGHT_MULTIPLE * _tippingPoint)) {
|
||||
// if we recenter upwards then no longer in sitting state
|
||||
|
@ -659,10 +659,35 @@ void MyAvatar::update(float deltaTime) {
|
|||
float tau = deltaTime / HMD_FACING_TIMESCALE;
|
||||
setHipToHandController(computeHandAzimuth());
|
||||
|
||||
// Determine which body parts are under direct control (tracked).
|
||||
{
|
||||
_isBodyPartTracked._leftHand = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND).isValid();
|
||||
_isBodyPartTracked._rightHand = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND).isValid();
|
||||
_isBodyPartTracked._head = getControllerPoseInSensorFrame(controller::Action::HEAD).isValid();
|
||||
|
||||
// Check for either foot so that if one foot loses tracking, we don't break out of foot-tracking behaviour
|
||||
// (in terms of avatar recentering for example).
|
||||
_isBodyPartTracked._feet = _isBodyPartTracked._head && // Feet can't be tracked unless head is tracked.
|
||||
(getControllerPoseInSensorFrame(controller::Action::LEFT_FOOT).isValid() ||
|
||||
getControllerPoseInSensorFrame(controller::Action::RIGHT_FOOT).isValid());
|
||||
|
||||
_isBodyPartTracked._hips = _isBodyPartTracked._feet && // Hips can't be tracked unless feet are tracked.
|
||||
getControllerPoseInSensorFrame(controller::Action::HIPS).isValid();
|
||||
}
|
||||
|
||||
// Recenter the body when foot tracking starts or ends.
|
||||
{
|
||||
static bool prevFeetWereTracked = _isBodyPartTracked._feet;
|
||||
if (_isBodyPartTracked._feet != prevFeetWereTracked) {
|
||||
centerBodyInternal(false);
|
||||
prevFeetWereTracked = _isBodyPartTracked._feet;
|
||||
}
|
||||
}
|
||||
|
||||
// put the average hand azimuth into sensor space.
|
||||
// then mix it with head facing direction to determine rotation recenter
|
||||
int spine2Index = _skeletonModel->getRig().indexOfJoint("Spine2");
|
||||
if (getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND).isValid() && getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND).isValid() && !(spine2Index < 0)) {
|
||||
if (_isBodyPartTracked._leftHand && _isBodyPartTracked._rightHand && !(spine2Index < 0)) {
|
||||
|
||||
// use the spine for the azimuth origin.
|
||||
glm::quat spine2Rot = getAbsoluteJointRotationInObjectFrame(spine2Index);
|
||||
|
@ -2760,8 +2785,7 @@ void MyAvatar::prepareForPhysicsSimulation() {
|
|||
_characterController.setScaleFactor(getSensorToWorldScale());
|
||||
|
||||
_characterController.setPositionAndOrientation(getWorldPosition(), getWorldOrientation());
|
||||
auto headPose = getControllerPoseInAvatarFrame(controller::Action::HEAD);
|
||||
if (headPose.isValid()) {
|
||||
if (_isBodyPartTracked._head) {
|
||||
_follow.prePhysicsUpdate(*this, deriveBodyFromHMDSensor(), _bodySensorMatrix, hasDriveInput());
|
||||
} else {
|
||||
_follow.deactivate();
|
||||
|
@ -5146,7 +5170,7 @@ float MyAvatar::computeStandingHeightMode(const controller::Pose& head) {
|
|||
modeInMeters = ((float)mode) / CENTIMETERS_PER_METER;
|
||||
if (!(modeInMeters > getCurrentStandingHeight())) {
|
||||
// if not greater check for a reset
|
||||
if (getResetMode() && getControllerPoseInAvatarFrame(controller::Action::HEAD).isValid()) {
|
||||
if (getResetMode() && _isBodyPartTracked._head) {
|
||||
setResetMode(false);
|
||||
float resetModeInCentimeters = glm::floor((head.getTranslation().y - MODE_CORRECTION_FACTOR)*CENTIMETERS_PER_METER);
|
||||
modeInMeters = (resetModeInCentimeters / CENTIMETERS_PER_METER);
|
||||
|
@ -5746,8 +5770,6 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar,
|
|||
const glm::mat4& desiredBodyMatrix,
|
||||
const glm::mat4& currentBodyMatrix,
|
||||
bool hasDriveInput) {
|
||||
const bool feetAreTracked = myAvatar.areFeetTracked();
|
||||
|
||||
if (myAvatar.getHMDLeanRecenterEnabled()) {
|
||||
|
||||
// Rotation recenter
|
||||
|
@ -5763,8 +5785,8 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar,
|
|||
|
||||
// Horizontal and rotation recenter
|
||||
|
||||
if ((feetAreTracked || getForceActivateHorizontal()) && !isActive(CharacterController::FollowType::Horizontal)) {
|
||||
activate(CharacterController::FollowType::Horizontal, feetAreTracked);
|
||||
if ((myAvatar.areFeetTracked() || getForceActivateHorizontal()) && !isActive(CharacterController::FollowType::Horizontal)) {
|
||||
activate(CharacterController::FollowType::Horizontal, myAvatar.areFeetTracked());
|
||||
setForceActivateHorizontal(false);
|
||||
} else {
|
||||
if ((myAvatar.getAllowAvatarLeaningPreference() != MyAvatar::AllowAvatarLeaningPreference::AlwaysNoRecenter) &&
|
||||
|
@ -7030,21 +7052,10 @@ bool MyAvatar::isAllowedToLean() const {
|
|||
!getIsInSittingState());
|
||||
}
|
||||
|
||||
// Determine if the feet are under direct control (tracked).
|
||||
bool MyAvatar::areFeetTracked() const {
|
||||
// Foot tracking only activates when both feet are tracked, so we only need to test one.
|
||||
return getControllerPoseInSensorFrame(controller::Action::LEFT_FOOT).isValid();
|
||||
}
|
||||
|
||||
// Determine if the hips are under direct control (tracked).
|
||||
bool MyAvatar::areHipsTracked() const {
|
||||
return getControllerPoseInSensorFrame(controller::Action::HIPS).isValid();
|
||||
}
|
||||
|
||||
// Determine if crouch recentering is enabled (making the avatar stand when the user is sitting in the real world).
|
||||
bool MyAvatar::getHMDCrouchRecenterEnabled() const {
|
||||
return (!_characterController.getSeated() &&
|
||||
(_allowAvatarStandingPreference.get() == AllowAvatarStandingPreference::Always) && !areFeetTracked());
|
||||
(_allowAvatarStandingPreference.get() == AllowAvatarStandingPreference::Always) && !_isBodyPartTracked._feet);
|
||||
}
|
||||
|
||||
bool MyAvatar::setPointAt(const glm::vec3& pointAtTarget) {
|
||||
|
|
|
@ -2008,8 +2008,8 @@ public:
|
|||
bool isJumping();
|
||||
bool getHMDCrouchRecenterEnabled() const;
|
||||
bool isAllowedToLean() const;
|
||||
bool areFeetTracked() const;
|
||||
bool areHipsTracked() const;
|
||||
bool areFeetTracked() const { return _isBodyPartTracked._feet; }; // Determine if the feet are under direct control.
|
||||
bool areHipsTracked() const { return _isBodyPartTracked._hips; }; // Determine if the hips are under direct control.
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -2730,6 +2730,15 @@ private:
|
|||
bool _isBraking { false };
|
||||
bool _isAway { false };
|
||||
|
||||
// Indicates which parts of the body are under direct control (tracked).
|
||||
struct {
|
||||
bool _feet{ false }; // Left or right foot.
|
||||
bool _hips{ false };
|
||||
bool _leftHand{ false };
|
||||
bool _rightHand{ false };
|
||||
bool _head{ false };
|
||||
} _isBodyPartTracked;
|
||||
|
||||
float _boomLength { ZOOM_DEFAULT };
|
||||
float _yawSpeed; // degrees/sec
|
||||
float _pitchSpeed; // degrees/sec
|
||||
|
|
Loading…
Reference in a new issue