mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 17:03:58 +02:00
expose _measured_ MyAvatar velocity to JS
This commit is contained in:
parent
fb8b3020e5
commit
7be411b4ca
5 changed files with 150 additions and 267 deletions
|
@ -50,12 +50,13 @@ Avatar::Avatar() :
|
|||
AvatarData(),
|
||||
_skeletonModel(this),
|
||||
_bodyYawDelta(0.0f),
|
||||
_velocity(0.0f, 0.0f, 0.0f),
|
||||
_lastVelocity(0.0f, 0.0f, 0.0f),
|
||||
_acceleration(0.0f, 0.0f, 0.0f),
|
||||
_angularVelocity(0.0f, 0.0f, 0.0f),
|
||||
_lastAngularVelocity(0.0f, 0.0f, 0.0f),
|
||||
_angularAcceleration(0.0f, 0.0f, 0.0f),
|
||||
_lastPosition(0.0f),
|
||||
_velocity(0.0f),
|
||||
_lastVelocity(0.0f),
|
||||
_acceleration(0.0f),
|
||||
_angularVelocity(0.0f),
|
||||
_lastAngularVelocity(0.0f),
|
||||
_angularAcceleration(0.0f),
|
||||
_lastOrientation(),
|
||||
_leanScale(0.5f),
|
||||
_scale(1.0f),
|
||||
|
@ -185,11 +186,7 @@ void Avatar::simulate(float deltaTime) {
|
|||
_hair.simulate(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
// update position by velocity, and subtract the change added earlier for gravity
|
||||
_position += _velocity * deltaTime;
|
||||
updateAcceleration(deltaTime);
|
||||
|
||||
|
||||
// update animation for display name fade in/out
|
||||
if ( _displayNameTargetAlpha != _displayNameAlpha) {
|
||||
// the alpha function is
|
||||
|
@ -206,17 +203,22 @@ void Avatar::simulate(float deltaTime) {
|
|||
}
|
||||
_displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01f ? _displayNameTargetAlpha : _displayNameAlpha;
|
||||
}
|
||||
|
||||
measureMotionDerivatives(deltaTime);
|
||||
}
|
||||
|
||||
void Avatar::updateAcceleration(float deltaTime) {
|
||||
// Linear Component of Acceleration
|
||||
_acceleration = (_velocity - _lastVelocity) * (1.f / deltaTime);
|
||||
void Avatar::measureMotionDerivatives(float deltaTime) {
|
||||
// linear
|
||||
float invDeltaTime = 1.0f / deltaTime;
|
||||
_velocity = (_position - _lastPosition) * invDeltaTime;
|
||||
_lastPosition = _position;
|
||||
_acceleration = (_velocity - _lastVelocity) * invDeltaTime;
|
||||
_lastVelocity = _velocity;
|
||||
// Angular Component of Acceleration
|
||||
// angular
|
||||
glm::quat orientation = getOrientation();
|
||||
glm::quat delta = glm::inverse(_lastOrientation) * orientation;
|
||||
_angularVelocity = safeEulerAngles(delta) * (1.f / deltaTime);
|
||||
_angularAcceleration = (_angularVelocity - _lastAngularVelocity) * (1.f / deltaTime);
|
||||
_angularVelocity = safeEulerAngles(delta) * invDeltaTime;
|
||||
_angularAcceleration = (_angularVelocity - _lastAngularVelocity) * invDeltaTime;
|
||||
_lastOrientation = getOrientation();
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,6 @@ public:
|
|||
const QVector<Model*>& getAttachmentModels() const { return _attachmentModels; }
|
||||
glm::vec3 getChestPosition() const;
|
||||
float getScale() const { return _scale; }
|
||||
Q_INVOKABLE const glm::vec3& getVelocity() const { return _velocity; }
|
||||
const Head* getHead() const { return static_cast<const Head*>(_headData); }
|
||||
Head* getHead() { return static_cast<Head*>(_headData); }
|
||||
Hand* getHand() { return static_cast<Hand*>(_handData); }
|
||||
|
@ -152,6 +151,7 @@ public:
|
|||
Q_INVOKABLE glm::quat getJointCombinedRotation(int index) const;
|
||||
Q_INVOKABLE glm::quat getJointCombinedRotation(const QString& name) const;
|
||||
|
||||
Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; }
|
||||
Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; }
|
||||
Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; }
|
||||
Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; }
|
||||
|
@ -172,6 +172,12 @@ protected:
|
|||
SkeletonModel _skeletonModel;
|
||||
QVector<Model*> _attachmentModels;
|
||||
float _bodyYawDelta;
|
||||
|
||||
// These position histories and derivatives are in the world-frame.
|
||||
// The derivatives are the MEASURED results of all external and internal forces
|
||||
// and are therefor READ-ONLY --> motion control of the Avatar is NOT obtained
|
||||
// by setting these values.
|
||||
glm::vec3 _lastPosition;
|
||||
glm::vec3 _velocity;
|
||||
glm::vec3 _lastVelocity;
|
||||
glm::vec3 _acceleration;
|
||||
|
@ -179,6 +185,7 @@ protected:
|
|||
glm::vec3 _lastAngularVelocity;
|
||||
glm::vec3 _angularAcceleration;
|
||||
glm::quat _lastOrientation;
|
||||
|
||||
float _leanScale;
|
||||
float _scale;
|
||||
glm::vec3 _worldUpDirection;
|
||||
|
@ -195,7 +202,7 @@ protected:
|
|||
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
|
||||
void setScale(float scale);
|
||||
void updateAcceleration(float deltaTime);
|
||||
void measureMotionDerivatives(float deltaTime);
|
||||
|
||||
float getSkeletonHeight() const;
|
||||
float getHeadHeight() const;
|
||||
|
|
|
@ -62,9 +62,9 @@ MyAvatar::MyAvatar() :
|
|||
_mousePressed(false),
|
||||
_bodyPitchDelta(0.0f),
|
||||
_bodyRollDelta(0.0f),
|
||||
_shouldJump(false),
|
||||
_gravity(0.0f, 0.0f, 0.0f),
|
||||
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
||||
_shouldJump(false),
|
||||
_wasPushing(false),
|
||||
_isPushing(false),
|
||||
_isBraking(false),
|
||||
|
@ -74,7 +74,6 @@ MyAvatar::MyAvatar() :
|
|||
_motorTimescale(DEFAULT_MOTOR_TIMESCALE),
|
||||
_maxMotorSpeed(MAX_MOTOR_SPEED),
|
||||
_motionBehaviors(AVATAR_MOTION_DEFAULTS),
|
||||
_lastBodyPenetration(0.0f),
|
||||
_lastFloorContactPoint(0.0f),
|
||||
_lookAtTargetAvatar(),
|
||||
_shouldRender(true),
|
||||
|
@ -102,7 +101,7 @@ void MyAvatar::reset() {
|
|||
_skeletonModel.reset();
|
||||
getHead()->reset();
|
||||
|
||||
setVelocity(glm::vec3(0.0f));
|
||||
_velocity = glm::vec3(0.0f);
|
||||
setThrust(glm::vec3(0.0f));
|
||||
// Reset the pitch and roll components of the avatar's orientation, preserve yaw direction
|
||||
glm::vec3 eulers = safeEulerAngles(getOrientation());
|
||||
|
@ -1158,6 +1157,11 @@ void MyAvatar::updatePosition(float deltaTime) {
|
|||
boundingShape.getStartPoint(startCap);
|
||||
glm::vec3 bottom = startCap - boundingShape.getRadius() * _worldUpDirection;
|
||||
|
||||
// velocity is initialized to the measured _velocity but will be modified
|
||||
// by friction, external thrust, etc
|
||||
glm::vec3 velocity = _velocity;
|
||||
|
||||
// apply friction
|
||||
if (gravityLength > EPSILON) {
|
||||
float speedFromGravity = _scale * deltaTime * gravityLength;
|
||||
float distanceToFall = glm::distance(bottom, _lastFloorContactPoint);
|
||||
|
@ -1166,26 +1170,26 @@ void MyAvatar::updatePosition(float deltaTime) {
|
|||
if (walkingOnFloor) {
|
||||
// BEGIN HACK: to prevent the avatar from bouncing on a floor surface
|
||||
if (distanceToFall < deltaTime * speedFromGravity) {
|
||||
float verticalSpeed = glm::dot(_velocity, _worldUpDirection);
|
||||
float verticalSpeed = glm::dot(velocity, _worldUpDirection);
|
||||
if (fabs(verticalSpeed) < speedFromGravity) {
|
||||
// we're standing on a floor, and nearly at rest so we zero the vertical velocity component
|
||||
_velocity -= verticalSpeed * _worldUpDirection;
|
||||
velocity -= verticalSpeed * _worldUpDirection;
|
||||
}
|
||||
} else {
|
||||
// fall with gravity against floor
|
||||
_velocity -= speedFromGravity * _worldUpDirection;
|
||||
velocity -= speedFromGravity * _worldUpDirection;
|
||||
}
|
||||
// END HACK
|
||||
} else {
|
||||
if (!_isBraking) {
|
||||
// fall with gravity toward floor
|
||||
_velocity -= speedFromGravity * _worldUpDirection;
|
||||
velocity -= speedFromGravity * _worldUpDirection;
|
||||
}
|
||||
|
||||
if (_motionBehaviors & AVATAR_MOTION_STAND_ON_NEARBY_FLOORS) {
|
||||
const float MAX_VERTICAL_FLOOR_DETECTION_SPEED = _scale * MAX_WALKING_SPEED;
|
||||
if (keyboardInput && glm::dot(_motorVelocity, _worldUpDirection) > 0.0f &&
|
||||
glm::dot(_velocity, _worldUpDirection) > MAX_VERTICAL_FLOOR_DETECTION_SPEED) {
|
||||
glm::dot(velocity, _worldUpDirection) > MAX_VERTICAL_FLOOR_DETECTION_SPEED) {
|
||||
// disable local gravity when flying up
|
||||
setLocalGravity(glm::vec3(0.0f));
|
||||
} else {
|
||||
|
@ -1197,93 +1201,123 @@ void MyAvatar::updatePosition(float deltaTime) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((_collisionGroups & COLLISION_GROUP_VOXELS) &&
|
||||
_motionBehaviors & AVATAR_MOTION_STAND_ON_NEARBY_FLOORS) {
|
||||
const float MIN_FLOOR_DETECTION_SPEED = _scale * 1.0f;
|
||||
if (glm::length(_velocity) < MIN_FLOOR_DETECTION_SPEED ) {
|
||||
// scan for floor under avatar
|
||||
const float maxFloorDistance = _scale * NEARBY_FLOOR_THRESHOLD;
|
||||
if (computeDistanceToFloor(bottom) < maxFloorDistance) {
|
||||
// enable local gravity
|
||||
setLocalGravity(-_worldUpDirection);
|
||||
}
|
||||
} else if ((_collisionGroups & COLLISION_GROUP_VOXELS) &&
|
||||
_motionBehaviors & AVATAR_MOTION_STAND_ON_NEARBY_FLOORS) {
|
||||
const float MIN_FLOOR_DETECTION_SPEED = _scale * 1.0f;
|
||||
if (glm::length(_velocity) < MIN_FLOOR_DETECTION_SPEED ) {
|
||||
// scan for floor under avatar
|
||||
const float maxFloorDistance = _scale * NEARBY_FLOOR_THRESHOLD;
|
||||
if (computeDistanceToFloor(bottom) < maxFloorDistance) {
|
||||
// enable local gravity
|
||||
setLocalGravity(-_worldUpDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keyboardInput > 0.0f || glm::length2(_velocity) > 0.0f || glm::length2(_thrust) > 0.0f || ! walkingOnFloor) {
|
||||
// update motor and thrust
|
||||
updateMotorFromKeyboard(deltaTime, walkingOnFloor);
|
||||
applyMotor(deltaTime);
|
||||
applyThrust(deltaTime);
|
||||
float speed = glm::length(velocity);
|
||||
if (keyboardInput > 0.0f || speed > 0.0f || glm::length2(_thrust) > 0.0f || ! walkingOnFloor) {
|
||||
// update motor
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_KEYBOARD_ENABLED) {
|
||||
// Increase motor velocity until its length is equal to _maxMotorSpeed.
|
||||
glm::vec3 localVelocity = velocity;
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_USE_LOCAL_FRAME) {
|
||||
glm::quat orientation = getHead()->getCameraOrientation();
|
||||
localVelocity = glm::inverse(orientation) * velocity;
|
||||
}
|
||||
|
||||
// Compute keyboard input
|
||||
glm::vec3 front = (_driveKeys[FWD] - _driveKeys[BACK]) * IDENTITY_FRONT;
|
||||
glm::vec3 right = (_driveKeys[RIGHT] - _driveKeys[LEFT]) * IDENTITY_RIGHT;
|
||||
glm::vec3 up = (_driveKeys[UP] - _driveKeys[DOWN]) * IDENTITY_UP;
|
||||
|
||||
glm::vec3 direction = front + right + up;
|
||||
float directionLength = glm::length(direction);
|
||||
|
||||
// Compute motor magnitude
|
||||
if (directionLength > EPSILON) {
|
||||
direction /= directionLength;
|
||||
// the finalMotorSpeed depends on whether we are walking or not
|
||||
float finalMaxMotorSpeed = walkingOnFloor ? _scale * MAX_WALKING_SPEED : _scale * _maxMotorSpeed;
|
||||
|
||||
float motorLength = glm::length(_motorVelocity);
|
||||
if (motorLength < _scale * MIN_KEYBOARD_CONTROL_SPEED) {
|
||||
// an active keyboard motor should never be slower than this
|
||||
_motorVelocity = _scale * MIN_KEYBOARD_CONTROL_SPEED * direction;
|
||||
} else {
|
||||
float MOTOR_LENGTH_TIMESCALE = 1.5f;
|
||||
float tau = glm::clamp(deltaTime / MOTOR_LENGTH_TIMESCALE, 0.0f, 1.0f);
|
||||
float INCREASE_FACTOR = 2.0f;
|
||||
//_motorVelocity *= 1.0f + tau * INCREASE_FACTOR;
|
||||
motorLength *= 1.0f + tau * INCREASE_FACTOR;
|
||||
if (motorLength > finalMaxMotorSpeed) {
|
||||
motorLength = finalMaxMotorSpeed;
|
||||
}
|
||||
_motorVelocity = motorLength * direction;
|
||||
}
|
||||
_isPushing = true;
|
||||
} else {
|
||||
// motor opposes motion (wants to be at rest)
|
||||
_motorVelocity = - localVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
// apply motor
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_ENABLED) {
|
||||
glm::vec3 targetVelocity = _motorVelocity;
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_USE_LOCAL_FRAME) {
|
||||
// rotate _motorVelocity into world frame
|
||||
glm::quat rotation = getHead()->getCameraOrientation();
|
||||
targetVelocity = rotation * _motorVelocity;
|
||||
}
|
||||
|
||||
glm::vec3 targetDirection(0.0f);
|
||||
if (glm::length2(targetVelocity) > EPSILON) {
|
||||
targetDirection = glm::normalize(targetVelocity);
|
||||
}
|
||||
glm::vec3 deltaVelocity = targetVelocity - velocity;
|
||||
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_COLLISION_SURFACE_ONLY && glm::length2(_gravity) > EPSILON) {
|
||||
// For now we subtract the component parallel to gravity but what we need to do is:
|
||||
// TODO: subtract the component perp to the local surface normal (motor only pushes in surface plane).
|
||||
glm::vec3 gravityDirection = glm::normalize(_gravity);
|
||||
glm::vec3 parallelDelta = glm::dot(deltaVelocity, gravityDirection) * gravityDirection;
|
||||
if (glm::dot(targetVelocity, velocity) > 0.0f) {
|
||||
// remove parallel part from deltaVelocity
|
||||
deltaVelocity -= parallelDelta;
|
||||
}
|
||||
}
|
||||
|
||||
// simple critical damping
|
||||
float timescale = computeMotorTimescale(velocity);
|
||||
float tau = glm::clamp(deltaTime / timescale, 0.0f, 1.0f);
|
||||
velocity += tau * deltaVelocity;
|
||||
}
|
||||
|
||||
// apply thrust
|
||||
velocity += _thrust * deltaTime;
|
||||
speed = glm::length(velocity);
|
||||
if (speed > MAX_AVATAR_SPEED) {
|
||||
velocity *= MAX_AVATAR_SPEED / speed;
|
||||
speed = MAX_AVATAR_SPEED;
|
||||
}
|
||||
_thrust = glm::vec3(0.0f);
|
||||
|
||||
// update position
|
||||
if (glm::length2(_velocity) < EPSILON) {
|
||||
_velocity = glm::vec3(0.0f);
|
||||
} else {
|
||||
_position += _velocity * deltaTime;
|
||||
const float MIN_AVATAR_SPEED = 0.075f;
|
||||
if (speed > MIN_AVATAR_SPEED) {
|
||||
_position += velocity * deltaTime;
|
||||
}
|
||||
updateAcceleration(deltaTime);
|
||||
}
|
||||
|
||||
// update moving flag based on speed
|
||||
const float MOVING_SPEED_THRESHOLD = 0.01f;
|
||||
_moving = glm::length(_velocity) > MOVING_SPEED_THRESHOLD;
|
||||
_moving = speed > MOVING_SPEED_THRESHOLD;
|
||||
|
||||
updateChatCircle(deltaTime);
|
||||
measureMotionDerivatives(deltaTime);
|
||||
}
|
||||
|
||||
void MyAvatar::updateMotorFromKeyboard(float deltaTime, bool walking) {
|
||||
// Increase motor velocity until its length is equal to _maxMotorSpeed.
|
||||
if (!(_motionBehaviors & AVATAR_MOTION_MOTOR_KEYBOARD_ENABLED)) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec3 localVelocity = _velocity;
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_USE_LOCAL_FRAME) {
|
||||
glm::quat orientation = getHead()->getCameraOrientation();
|
||||
localVelocity = glm::inverse(orientation) * _velocity;
|
||||
}
|
||||
|
||||
// Compute keyboard input
|
||||
glm::vec3 front = (_driveKeys[FWD] - _driveKeys[BACK]) * IDENTITY_FRONT;
|
||||
glm::vec3 right = (_driveKeys[RIGHT] - _driveKeys[LEFT]) * IDENTITY_RIGHT;
|
||||
glm::vec3 up = (_driveKeys[UP] - _driveKeys[DOWN]) * IDENTITY_UP;
|
||||
|
||||
glm::vec3 direction = front + right + up;
|
||||
float directionLength = glm::length(direction);
|
||||
|
||||
// Compute motor magnitude
|
||||
if (directionLength > EPSILON) {
|
||||
direction /= directionLength;
|
||||
// the finalMotorSpeed depends on whether we are walking or not
|
||||
float finalMaxMotorSpeed = walking ? _scale * MAX_WALKING_SPEED : _scale * _maxMotorSpeed;
|
||||
|
||||
float motorLength = glm::length(_motorVelocity);
|
||||
if (motorLength < _scale * MIN_KEYBOARD_CONTROL_SPEED) {
|
||||
// an active keyboard motor should never be slower than this
|
||||
_motorVelocity = _scale * MIN_KEYBOARD_CONTROL_SPEED * direction;
|
||||
} else {
|
||||
float MOTOR_LENGTH_TIMESCALE = 1.5f;
|
||||
float tau = glm::clamp(deltaTime / MOTOR_LENGTH_TIMESCALE, 0.0f, 1.0f);
|
||||
float INCREASE_FACTOR = 2.0f;
|
||||
//_motorVelocity *= 1.0f + tau * INCREASE_FACTOR;
|
||||
motorLength *= 1.0f + tau * INCREASE_FACTOR;
|
||||
if (motorLength > finalMaxMotorSpeed) {
|
||||
motorLength = finalMaxMotorSpeed;
|
||||
}
|
||||
_motorVelocity = motorLength * direction;
|
||||
}
|
||||
_isPushing = true;
|
||||
} else {
|
||||
// motor opposes motion (wants to be at rest)
|
||||
_motorVelocity = - localVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
float MyAvatar::computeMotorTimescale() {
|
||||
float MyAvatar::computeMotorTimescale(const glm::vec3& velocity) {
|
||||
// The timescale of the motor is the approximate time it takes for the motor to
|
||||
// accomplish its intended velocity. A short timescale makes the motor strong,
|
||||
// and a long timescale makes it weak. The value of timescale to use depends
|
||||
|
@ -1303,7 +1337,7 @@ float MyAvatar::computeMotorTimescale() {
|
|||
timescale = _motorTimescale;
|
||||
_isBraking = false;
|
||||
} else {
|
||||
float speed = glm::length(_velocity);
|
||||
float speed = glm::length(velocity);
|
||||
_isBraking = _wasPushing || (_isBraking && speed > MIN_BRAKE_SPEED);
|
||||
if (_isBraking) {
|
||||
timescale = MIN_MOTOR_TIMESCALE;
|
||||
|
@ -1314,160 +1348,6 @@ float MyAvatar::computeMotorTimescale() {
|
|||
return timescale;
|
||||
}
|
||||
|
||||
void MyAvatar::applyMotor(float deltaTime) {
|
||||
// TODO: recover extra braking behavior when flying close to nearest avatar
|
||||
if (!( _motionBehaviors & AVATAR_MOTION_MOTOR_ENABLED)) {
|
||||
// nothing to do --> early exit
|
||||
return;
|
||||
}
|
||||
glm::vec3 targetVelocity = _motorVelocity;
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_USE_LOCAL_FRAME) {
|
||||
// rotate _motorVelocity into world frame
|
||||
glm::quat rotation = getHead()->getCameraOrientation();
|
||||
targetVelocity = rotation * _motorVelocity;
|
||||
}
|
||||
|
||||
glm::vec3 targetDirection(0.0f);
|
||||
if (glm::length2(targetVelocity) > EPSILON) {
|
||||
targetDirection = glm::normalize(targetVelocity);
|
||||
}
|
||||
glm::vec3 deltaVelocity = targetVelocity - _velocity;
|
||||
|
||||
if (_motionBehaviors & AVATAR_MOTION_MOTOR_COLLISION_SURFACE_ONLY && glm::length2(_gravity) > EPSILON) {
|
||||
// For now we subtract the component parallel to gravity but what we need to do is:
|
||||
// TODO: subtract the component perp to the local surface normal (motor only pushes in surface plane).
|
||||
glm::vec3 gravityDirection = glm::normalize(_gravity);
|
||||
glm::vec3 parallelDelta = glm::dot(deltaVelocity, gravityDirection) * gravityDirection;
|
||||
if (glm::dot(targetVelocity, _velocity) > 0.0f) {
|
||||
// remove parallel part from deltaVelocity
|
||||
deltaVelocity -= parallelDelta;
|
||||
}
|
||||
}
|
||||
|
||||
// simple critical damping
|
||||
float timescale = computeMotorTimescale();
|
||||
float tau = glm::clamp(deltaTime / timescale, 0.0f, 1.0f);
|
||||
_velocity += tau * deltaVelocity;
|
||||
}
|
||||
|
||||
void MyAvatar::applyThrust(float deltaTime) {
|
||||
_velocity += _thrust * deltaTime;
|
||||
float speed = glm::length(_velocity);
|
||||
// cap the speed that thrust can achieve
|
||||
if (speed > MAX_AVATAR_SPEED) {
|
||||
_velocity *= MAX_AVATAR_SPEED / speed;
|
||||
}
|
||||
// zero thrust so we don't pile up thrust from other sources
|
||||
_thrust = glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
/* Keep this code for the short term as reference in case we need to further tune the new model
|
||||
* to achieve legacy movement response.
|
||||
void MyAvatar::updateThrust(float deltaTime) {
|
||||
//
|
||||
// Gather thrust information from keyboard and sensors to apply to avatar motion
|
||||
//
|
||||
glm::quat orientation = getHead()->getCameraOrientation();
|
||||
glm::vec3 front = orientation * IDENTITY_FRONT;
|
||||
glm::vec3 right = orientation * IDENTITY_RIGHT;
|
||||
glm::vec3 up = orientation * IDENTITY_UP;
|
||||
|
||||
const float THRUST_MAG_UP = 800.0f;
|
||||
const float THRUST_MAG_DOWN = 300.0f;
|
||||
const float THRUST_MAG_FWD = 500.0f;
|
||||
const float THRUST_MAG_BACK = 300.0f;
|
||||
const float THRUST_MAG_LATERAL = 250.0f;
|
||||
const float THRUST_JUMP = 120.0f;
|
||||
|
||||
// Add Thrusts from keyboard
|
||||
_thrust += _driveKeys[FWD] * _scale * THRUST_MAG_FWD * _thrustMultiplier * deltaTime * front;
|
||||
_thrust -= _driveKeys[BACK] * _scale * THRUST_MAG_BACK * _thrustMultiplier * deltaTime * front;
|
||||
_thrust += _driveKeys[RIGHT] * _scale * THRUST_MAG_LATERAL * _thrustMultiplier * deltaTime * right;
|
||||
_thrust -= _driveKeys[LEFT] * _scale * THRUST_MAG_LATERAL * _thrustMultiplier * deltaTime * right;
|
||||
_thrust += _driveKeys[UP] * _scale * THRUST_MAG_UP * _thrustMultiplier * deltaTime * up;
|
||||
_thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up;
|
||||
|
||||
// attenuate thrust when in penetration
|
||||
if (glm::dot(_thrust, _lastBodyPenetration) > EPSILON) {
|
||||
const float MAX_BODY_PENETRATION_DEPTH = 0.6f * _skeletonModel.getBoundingShapeRadius();
|
||||
float penetrationFactor = glm::min(1.0f, glm::length(_lastBodyPenetration) / MAX_BODY_PENETRATION_DEPTH);
|
||||
glm::vec3 penetrationDirection = glm::normalize(_lastBodyPenetration);
|
||||
// attenuate parallel component
|
||||
glm::vec3 parallelThrust = glm::dot(_thrust, penetrationDirection) * penetrationDirection;
|
||||
// attenuate perpendicular component (friction)
|
||||
glm::vec3 perpendicularThrust = _thrust - parallelThrust;
|
||||
// recombine to get the final thrust
|
||||
_thrust = (1.0f - penetrationFactor) * parallelThrust + (1.0f - penetrationFactor * penetrationFactor) * perpendicularThrust;
|
||||
|
||||
// attenuate the growth of _thrustMultiplier when in penetration
|
||||
// otherwise the avatar will eventually be able to tunnel through the obstacle
|
||||
_thrustMultiplier *= (1.0f - penetrationFactor * penetrationFactor);
|
||||
} else if (_thrustMultiplier < 1.0f) {
|
||||
// rapid healing of attenuated thrustMultiplier after penetration event
|
||||
_thrustMultiplier = 1.0f;
|
||||
}
|
||||
_lastBodyPenetration = glm::vec3(0.0f);
|
||||
|
||||
// If thrust keys are being held down, slowly increase thrust to allow reaching great speeds
|
||||
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
|
||||
const float THRUST_INCREASE_RATE = 1.05f;
|
||||
const float MAX_THRUST_MULTIPLIER = 75.0f;
|
||||
_thrustMultiplier *= 1.0f + deltaTime * THRUST_INCREASE_RATE;
|
||||
if (_thrustMultiplier > MAX_THRUST_MULTIPLIER) {
|
||||
_thrustMultiplier = MAX_THRUST_MULTIPLIER;
|
||||
}
|
||||
} else {
|
||||
_thrustMultiplier = 1.0f;
|
||||
}
|
||||
|
||||
// Add one time jumping force if requested
|
||||
if (_shouldJump) {
|
||||
if (glm::length(_gravity) > EPSILON) {
|
||||
_thrust += _scale * THRUST_JUMP * up;
|
||||
}
|
||||
_shouldJump = false;
|
||||
}
|
||||
|
||||
// Update speed brake status
|
||||
const float MIN_SPEED_BRAKE_VELOCITY = _scale * 0.4f;
|
||||
if ((glm::length(_thrust) == 0.0f) && _isThrustOn && (glm::length(_velocity) > MIN_SPEED_BRAKE_VELOCITY)) {
|
||||
_speedBrakes = true;
|
||||
}
|
||||
_isThrustOn = (glm::length(_thrust) > EPSILON);
|
||||
|
||||
if (_isThrustOn || (_speedBrakes && (glm::length(_velocity) < MIN_SPEED_BRAKE_VELOCITY))) {
|
||||
_speedBrakes = false;
|
||||
}
|
||||
_velocity += _thrust * deltaTime;
|
||||
|
||||
// Zero thrust out now that we've added it to velocity in this frame
|
||||
_thrust = glm::vec3(0.0f);
|
||||
|
||||
// apply linear damping
|
||||
const float MAX_STATIC_FRICTION_SPEED = 0.5f;
|
||||
const float STATIC_FRICTION_STRENGTH = _scale * 20.0f;
|
||||
applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_SPEED, STATIC_FRICTION_STRENGTH);
|
||||
|
||||
const float LINEAR_DAMPING_STRENGTH = 0.5f;
|
||||
const float SPEED_BRAKE_POWER = _scale * 10.0f;
|
||||
const float SQUARED_DAMPING_STRENGTH = 0.007f;
|
||||
|
||||
const float SLOW_NEAR_RADIUS = 5.0f;
|
||||
float linearDamping = LINEAR_DAMPING_STRENGTH;
|
||||
const float NEAR_AVATAR_DAMPING_FACTOR = 50.0f;
|
||||
if (_distanceToNearestAvatar < _scale * SLOW_NEAR_RADIUS) {
|
||||
linearDamping *= 1.0f + NEAR_AVATAR_DAMPING_FACTOR *
|
||||
((SLOW_NEAR_RADIUS - _distanceToNearestAvatar) / SLOW_NEAR_RADIUS);
|
||||
}
|
||||
if (_speedBrakes) {
|
||||
applyDamping(deltaTime, _velocity, linearDamping * SPEED_BRAKE_POWER, SQUARED_DAMPING_STRENGTH * SPEED_BRAKE_POWER);
|
||||
} else {
|
||||
applyDamping(deltaTime, _velocity, linearDamping, SQUARED_DAMPING_STRENGTH);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) {
|
||||
glm::vec3 up = getBodyUpDirection();
|
||||
const float ENVIRONMENT_SURFACE_ELASTICITY = 0.0f;
|
||||
|
|
|
@ -53,7 +53,6 @@ public:
|
|||
|
||||
// setters
|
||||
void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; }
|
||||
void setVelocity(const glm::vec3 velocity) { _velocity = velocity; }
|
||||
void setLeanScale(float scale) { _leanScale = scale; }
|
||||
void setLocalGravity(glm::vec3 gravity);
|
||||
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; }
|
||||
|
@ -188,23 +187,23 @@ private:
|
|||
bool _mousePressed;
|
||||
float _bodyPitchDelta; // degrees
|
||||
float _bodyRollDelta; // degrees
|
||||
bool _shouldJump;
|
||||
float _driveKeys[MAX_DRIVE_KEYS];
|
||||
glm::vec3 _gravity;
|
||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||
|
||||
bool _shouldJump;
|
||||
float _driveKeys[MAX_DRIVE_KEYS];
|
||||
bool _wasPushing;
|
||||
bool _isPushing;
|
||||
bool _isBraking;
|
||||
float _trapDuration; // seconds that avatar has been trapped by collisions
|
||||
glm::vec3 _thrust; // final acceleration from outside sources for the current frame
|
||||
|
||||
glm::vec3 _motorVelocity; // intended velocity of avatar motion
|
||||
float _trapDuration; // seconds that avatar has been trapped by collisions
|
||||
glm::vec3 _thrust; // impulse accumulator for outside sources
|
||||
|
||||
glm::vec3 _motorVelocity; // intended velocity of avatar motion (relative to what it's standing on)
|
||||
float _motorTimescale; // timescale for avatar motor to achieve its desired velocity
|
||||
float _maxMotorSpeed;
|
||||
quint32 _motionBehaviors;
|
||||
|
||||
glm::vec3 _lastBodyPenetration;
|
||||
glm::vec3 _lastFloorContactPoint;
|
||||
QWeakPointer<AvatarData> _lookAtTargetAvatar;
|
||||
glm::vec3 _targetAvatarPosition;
|
||||
|
@ -221,10 +220,7 @@ private:
|
|||
float computeDistanceToFloor(const glm::vec3& startPoint);
|
||||
void updateOrientation(float deltaTime);
|
||||
void updatePosition(float deltaTime);
|
||||
void updateMotorFromKeyboard(float deltaTime, bool walking);
|
||||
float computeMotorTimescale();
|
||||
void applyMotor(float deltaTime);
|
||||
void applyThrust(float deltaTime);
|
||||
float computeMotorTimescale(const glm::vec3& velocity);
|
||||
void updateCollisionWithAvatars(float deltaTime);
|
||||
void updateCollisionWithEnvironment(float deltaTime, float radius);
|
||||
void updateCollisionWithVoxels(float deltaTime, float radius);
|
||||
|
|
|
@ -240,8 +240,6 @@ public:
|
|||
const HeadData* getHeadData() const { return _headData; }
|
||||
const HandData* getHandData() const { return _handData; }
|
||||
|
||||
virtual const glm::vec3& getVelocity() const { return vec3Zero; }
|
||||
|
||||
virtual bool findSphereCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue