Merge pull request #2628 from AndrewMeadows/oculus-with-thrust

fix glitchy oculus when looking directly behind
This commit is contained in:
Philip Rosedale 2014-04-09 21:59:11 -07:00
commit d4bfffe518
4 changed files with 116 additions and 93 deletions

View file

@ -65,7 +65,8 @@ MyAvatar::MyAvatar() :
_moveTargetStepCounter(0), _moveTargetStepCounter(0),
_lookAtTargetAvatar(), _lookAtTargetAvatar(),
_shouldRender(true), _shouldRender(true),
_billboardValid(false) _billboardValid(false),
_oculusYawOffset(0.0f)
{ {
for (int i = 0; i < MAX_DRIVE_KEYS; i++) { for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
_driveKeys[i] = 0.0f; _driveKeys[i] = 0.0f;
@ -88,10 +89,11 @@ void MyAvatar::reset() {
_skeletonModel.reset(); _skeletonModel.reset();
getHead()->reset(); getHead()->reset();
getHand()->reset(); getHand()->reset();
_oculusYawOffset = 0.0f;
setVelocity(glm::vec3(0.f)); setVelocity(glm::vec3(0.0f));
setThrust(glm::vec3(0.f)); setThrust(glm::vec3(0.0f));
setOrientation(glm::quat(glm::vec3(0.f))); setOrientation(glm::quat(glm::vec3(0.0f)));
} }
void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) {
@ -114,8 +116,8 @@ void MyAvatar::update(float deltaTime) {
// TODO? resurrect headMouse stuff? // TODO? resurrect headMouse stuff?
//glm::vec3 headVelocity = faceshift->getHeadAngularVelocity(); //glm::vec3 headVelocity = faceshift->getHeadAngularVelocity();
//// sets how quickly head angular rotation moves the head mouse //// sets how quickly head angular rotation moves the head mouse
//const float HEADMOUSE_FACESHIFT_YAW_SCALE = 40.f; //const float HEADMOUSE_FACESHIFT_YAW_SCALE = 40.0f;
//const float HEADMOUSE_FACESHIFT_PITCH_SCALE = 30.f; //const float HEADMOUSE_FACESHIFT_PITCH_SCALE = 30.0f;
//_headMouseX -= headVelocity.y * HEADMOUSE_FACESHIFT_YAW_SCALE; //_headMouseX -= headVelocity.y * HEADMOUSE_FACESHIFT_YAW_SCALE;
//_headMouseY -= headVelocity.x * HEADMOUSE_FACESHIFT_PITCH_SCALE; //_headMouseY -= headVelocity.x * HEADMOUSE_FACESHIFT_PITCH_SCALE;
// //
@ -124,16 +126,6 @@ void MyAvatar::update(float deltaTime) {
//_headMouseY = glm::clamp(_headMouseY, 0, _glWidget->height()); //_headMouseY = glm::clamp(_headMouseY, 0, _glWidget->height());
} }
if (OculusManager::isConnected()) {
float yaw, pitch, roll; // these angles will be in radians
OculusManager::getEulerAngles(yaw, pitch, roll);
// but these euler angles are stored in degrees
head->setBaseYaw(yaw * DEGREES_PER_RADIAN);
head->setBasePitch(pitch * DEGREES_PER_RADIAN);
head->setBaseRoll(roll * DEGREES_PER_RADIAN);
}
// Get audio loudness data from audio input device // Get audio loudness data from audio input device
Audio* audio = Application::getInstance()->getAudio(); Audio* audio = Application::getInstance()->getAudio();
head->setAudioLoudness(audio->getLastInputLoudness()); head->setAudioLoudness(audio->getLastInputLoudness());
@ -156,15 +148,15 @@ void MyAvatar::simulate(float deltaTime) {
_elapsedTimeSinceCollision += deltaTime; _elapsedTimeSinceCollision += deltaTime;
const float VELOCITY_MOVEMENT_TIMER_THRESHOLD = 0.2f; const float VELOCITY_MOVEMENT_TIMER_THRESHOLD = 0.2f;
if (glm::length(_velocity) < VELOCITY_MOVEMENT_TIMER_THRESHOLD) { if (glm::length(_velocity) < VELOCITY_MOVEMENT_TIMER_THRESHOLD) {
_elapsedTimeMoving = 0.f; _elapsedTimeMoving = 0.0f;
_elapsedTimeStopped += deltaTime; _elapsedTimeStopped += deltaTime;
} else { } else {
_elapsedTimeStopped = 0.f; _elapsedTimeStopped = 0.0f;
_elapsedTimeMoving += deltaTime; _elapsedTimeMoving += deltaTime;
} }
if (_scale != _targetScale) { if (_scale != _targetScale) {
float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale;
setScale(scale); setScale(scale);
Application::getInstance()->getCamera()->setScale(scale); Application::getInstance()->getCamera()->setScale(scale);
} }
@ -192,19 +184,19 @@ void MyAvatar::simulate(float deltaTime) {
// decay body rotation momentum // decay body rotation momentum
const float BODY_SPIN_FRICTION = 7.5f; const float BODY_SPIN_FRICTION = 7.5f;
float bodySpinMomentum = 1.f - BODY_SPIN_FRICTION * deltaTime; float bodySpinMomentum = 1.0f - BODY_SPIN_FRICTION * deltaTime;
if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; } if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; }
_bodyPitchDelta *= bodySpinMomentum; _bodyPitchDelta *= bodySpinMomentum;
_bodyYawDelta *= bodySpinMomentum; _bodyYawDelta *= bodySpinMomentum;
_bodyRollDelta *= bodySpinMomentum; _bodyRollDelta *= bodySpinMomentum;
float MINIMUM_ROTATION_RATE = 2.0f; float MINIMUM_ROTATION_RATE = 2.0f;
if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.f; } if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; }
if (fabs(_bodyRollDelta) < MINIMUM_ROTATION_RATE) { _bodyRollDelta = 0.f; } if (fabs(_bodyRollDelta) < MINIMUM_ROTATION_RATE) { _bodyRollDelta = 0.0f; }
if (fabs(_bodyPitchDelta) < MINIMUM_ROTATION_RATE) { _bodyPitchDelta = 0.f; } if (fabs(_bodyPitchDelta) < MINIMUM_ROTATION_RATE) { _bodyPitchDelta = 0.0f; }
const float MAX_STATIC_FRICTION_SPEED = 0.5f; const float MAX_STATIC_FRICTION_SPEED = 0.5f;
const float STATIC_FRICTION_STRENGTH = _scale * 20.f; const float STATIC_FRICTION_STRENGTH = _scale * 20.0f;
applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_SPEED, STATIC_FRICTION_STRENGTH); applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_SPEED, STATIC_FRICTION_STRENGTH);
// Damp avatar velocity // Damp avatar velocity
@ -212,11 +204,11 @@ void MyAvatar::simulate(float deltaTime) {
const float SPEED_BRAKE_POWER = _scale * 10.0f; const float SPEED_BRAKE_POWER = _scale * 10.0f;
const float SQUARED_DAMPING_STRENGTH = 0.007f; const float SQUARED_DAMPING_STRENGTH = 0.007f;
const float SLOW_NEAR_RADIUS = 5.f; const float SLOW_NEAR_RADIUS = 5.0f;
float linearDamping = LINEAR_DAMPING_STRENGTH; float linearDamping = LINEAR_DAMPING_STRENGTH;
const float NEAR_AVATAR_DAMPING_FACTOR = 50.f; const float NEAR_AVATAR_DAMPING_FACTOR = 50.0f;
if (_distanceToNearestAvatar < _scale * SLOW_NEAR_RADIUS) { if (_distanceToNearestAvatar < _scale * SLOW_NEAR_RADIUS) {
linearDamping *= 1.f + NEAR_AVATAR_DAMPING_FACTOR * linearDamping *= 1.0f + NEAR_AVATAR_DAMPING_FACTOR *
((SLOW_NEAR_RADIUS - _distanceToNearestAvatar) / SLOW_NEAR_RADIUS); ((SLOW_NEAR_RADIUS - _distanceToNearestAvatar) / SLOW_NEAR_RADIUS);
} }
if (_speedBrakes) { if (_speedBrakes) {
@ -225,6 +217,54 @@ void MyAvatar::simulate(float deltaTime) {
applyDamping(deltaTime, _velocity, linearDamping, SQUARED_DAMPING_STRENGTH); applyDamping(deltaTime, _velocity, linearDamping, SQUARED_DAMPING_STRENGTH);
} }
if (OculusManager::isConnected()) {
// these angles will be in radians
float yaw, pitch, roll;
OculusManager::getEulerAngles(yaw, pitch, roll);
// ... so they need to be converted to degrees before we do math...
// The neck is limited in how much it can yaw, so we check its relative
// yaw from the body and yaw the body if necessary.
yaw *= DEGREES_PER_RADIAN;
float bodyToHeadYaw = yaw - _oculusYawOffset;
const float MAX_NECK_YAW = 85.0f; // degrees
if ((fabs(bodyToHeadYaw) > 2.0f * MAX_NECK_YAW) && (yaw * _oculusYawOffset < 0.0f)) {
// We've wrapped around the range for yaw so adjust
// the measured yaw to be relative to _oculusYawOffset.
if (yaw > 0.0f) {
yaw -= 360.0f;
} else {
yaw += 360.0f;
}
bodyToHeadYaw = yaw - _oculusYawOffset;
}
float delta = fabs(bodyToHeadYaw) - MAX_NECK_YAW;
if (delta > 0.0f) {
yaw = MAX_NECK_YAW;
if (bodyToHeadYaw < 0.0f) {
delta *= -1.0f;
bodyToHeadYaw = -MAX_NECK_YAW;
} else {
bodyToHeadYaw = MAX_NECK_YAW;
}
// constrain _oculusYawOffset to be within range [-180,180]
_oculusYawOffset = fmod((_oculusYawOffset + delta) + 180.0f, 360.0f) - 180.0f;
// We must adjust the body orientation using a delta rotation (rather than
// doing yaw math) because the body's yaw ranges are not the same
// as what the Oculus API provides.
glm::vec3 UP_AXIS = glm::vec3(0.0f, 1.0f, 0.0f);
glm::quat bodyCorrection = glm::angleAxis(glm::radians(delta), UP_AXIS);
orientation = orientation * bodyCorrection;
}
Head* head = getHead();
head->setBaseYaw(bodyToHeadYaw);
head->setBasePitch(pitch * DEGREES_PER_RADIAN);
head->setBaseRoll(roll * DEGREES_PER_RADIAN);
}
// update the euler angles // update the euler angles
setOrientation(orientation); setOrientation(orientation);
@ -243,7 +283,7 @@ void MyAvatar::simulate(float deltaTime) {
// If a move target is set, update position explicitly // If a move target is set, update position explicitly
const float MOVE_FINISHED_TOLERANCE = 0.1f; const float MOVE_FINISHED_TOLERANCE = 0.1f;
const float MOVE_SPEED_FACTOR = 2.f; const float MOVE_SPEED_FACTOR = 2.0f;
const int MOVE_TARGET_MAX_STEPS = 250; const int MOVE_TARGET_MAX_STEPS = 250;
if ((glm::length(_moveTarget) > EPSILON) && (_moveTargetStepCounter < MOVE_TARGET_MAX_STEPS)) { if ((glm::length(_moveTarget) > EPSILON) && (_moveTargetStepCounter < MOVE_TARGET_MAX_STEPS)) {
if (glm::length(_position - _moveTarget) > MOVE_FINISHED_TOLERANCE) { if (glm::length(_position - _moveTarget) > MOVE_FINISHED_TOLERANCE) {
@ -283,7 +323,7 @@ void MyAvatar::simulate(float deltaTime) {
head->simulate(deltaTime, true); head->simulate(deltaTime, true);
// Zero thrust out now that we've added it to velocity in this frame // Zero thrust out now that we've added it to velocity in this frame
_thrust = glm::vec3(0.f); _thrust = glm::vec3(0.0f);
// now that we're done stepping the avatar forward in time, compute new collisions // now that we're done stepping the avatar forward in time, compute new collisions
if (_collisionFlags != 0) { if (_collisionFlags != 0) {
@ -291,7 +331,7 @@ void MyAvatar::simulate(float deltaTime) {
float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE; float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE;
if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON && !OculusManager::isConnected()) { if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON && !OculusManager::isConnected()) {
radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.f)); radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.0f));
radius *= COLLISION_RADIUS_SCALAR; radius *= COLLISION_RADIUS_SCALAR;
} }
@ -333,11 +373,11 @@ void MyAvatar::updateFromGyros(float deltaTime) {
// Rotate the body if the head is turned beyond the screen // Rotate the body if the head is turned beyond the screen
if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) { if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) {
const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f; const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f;
const float TRACKER_MIN_YAW_TURN = 15.f; const float TRACKER_MIN_YAW_TURN = 15.0f;
const float TRACKER_MAX_YAW_TURN = 50.f; const float TRACKER_MAX_YAW_TURN = 50.0f;
if ( (fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) && if ( (fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) &&
(fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) { (fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) {
if (estimatedRotation.y > 0.f) { if (estimatedRotation.y > 0.0f) {
_bodyYawDelta += (estimatedRotation.y - TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; _bodyYawDelta += (estimatedRotation.y - TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY;
} else { } else {
_bodyYawDelta += (estimatedRotation.y + TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; _bodyYawDelta += (estimatedRotation.y + TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY;
@ -375,20 +415,20 @@ void MyAvatar::moveWithLean() {
float leanSideways = head->getLeanSideways(); float leanSideways = head->getLeanSideways();
// Degrees of 'dead zone' when leaning, and amount of acceleration to apply to lean angle // Degrees of 'dead zone' when leaning, and amount of acceleration to apply to lean angle
const float LEAN_FWD_DEAD_ZONE = 15.f; const float LEAN_FWD_DEAD_ZONE = 15.0f;
const float LEAN_SIDEWAYS_DEAD_ZONE = 10.f; const float LEAN_SIDEWAYS_DEAD_ZONE = 10.0f;
const float LEAN_FWD_THRUST_SCALE = 4.f; const float LEAN_FWD_THRUST_SCALE = 4.0f;
const float LEAN_SIDEWAYS_THRUST_SCALE = 3.f; const float LEAN_SIDEWAYS_THRUST_SCALE = 3.0f;
if (fabs(leanForward) > LEAN_FWD_DEAD_ZONE) { if (fabs(leanForward) > LEAN_FWD_DEAD_ZONE) {
if (leanForward > 0.f) { if (leanForward > 0.0f) {
addThrust(front * -(leanForward - LEAN_FWD_DEAD_ZONE) * LEAN_FWD_THRUST_SCALE); addThrust(front * -(leanForward - LEAN_FWD_DEAD_ZONE) * LEAN_FWD_THRUST_SCALE);
} else { } else {
addThrust(front * -(leanForward + LEAN_FWD_DEAD_ZONE) * LEAN_FWD_THRUST_SCALE); addThrust(front * -(leanForward + LEAN_FWD_DEAD_ZONE) * LEAN_FWD_THRUST_SCALE);
} }
} }
if (fabs(leanSideways) > LEAN_SIDEWAYS_DEAD_ZONE) { if (fabs(leanSideways) > LEAN_SIDEWAYS_DEAD_ZONE) {
if (leanSideways > 0.f) { if (leanSideways > 0.0f) {
addThrust(right * -(leanSideways - LEAN_SIDEWAYS_DEAD_ZONE) * LEAN_SIDEWAYS_THRUST_SCALE); addThrust(right * -(leanSideways - LEAN_SIDEWAYS_DEAD_ZONE) * LEAN_SIDEWAYS_THRUST_SCALE);
} else { } else {
addThrust(right * -(leanSideways + LEAN_SIDEWAYS_DEAD_ZONE) * LEAN_SIDEWAYS_THRUST_SCALE); addThrust(right * -(leanSideways + LEAN_SIDEWAYS_DEAD_ZONE) * LEAN_SIDEWAYS_THRUST_SCALE);
@ -435,7 +475,7 @@ void MyAvatar::renderHeadMouse() const {
// TODO? resurrect headMouse stuff? // TODO? resurrect headMouse stuff?
/* /*
// Display small target box at center or head mouse target that can also be used to measure LOD // Display small target box at center or head mouse target that can also be used to measure LOD
glColor3f(1.f, 1.f, 1.f); glColor3f(1.0f, 1.0f, 1.0f);
glDisable(GL_LINE_SMOOTH); glDisable(GL_LINE_SMOOTH);
const int PIXEL_BOX = 16; const int PIXEL_BOX = 16;
glBegin(GL_LINES); glBegin(GL_LINES);
@ -445,7 +485,7 @@ void MyAvatar::renderHeadMouse() const {
glVertex2f(_headMouseX, _headMouseY + PIXEL_BOX/2); glVertex2f(_headMouseX, _headMouseY + PIXEL_BOX/2);
glEnd(); glEnd();
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
glColor3f(1.f, 0.f, 0.f); glColor3f(1.0f, 0.0f, 0.0f);
glPointSize(3.0f); glPointSize(3.0f);
glDisable(GL_POINT_SMOOTH); glDisable(GL_POINT_SMOOTH);
glBegin(GL_POINTS); glBegin(GL_POINTS);
@ -457,7 +497,7 @@ void MyAvatar::renderHeadMouse() const {
int eyeTargetX = (_glWidget->width() / 2) - _faceshift.getEstimatedEyeYaw() * EYE_TARGET_PIXELS_PER_DEGREE; int eyeTargetX = (_glWidget->width() / 2) - _faceshift.getEstimatedEyeYaw() * EYE_TARGET_PIXELS_PER_DEGREE;
int eyeTargetY = (_glWidget->height() / 2) - _faceshift.getEstimatedEyePitch() * EYE_TARGET_PIXELS_PER_DEGREE; int eyeTargetY = (_glWidget->height() / 2) - _faceshift.getEstimatedEyePitch() * EYE_TARGET_PIXELS_PER_DEGREE;
glColor3f(0.f, 1.f, 1.f); glColor3f(0.0f, 1.0f, 1.0f);
glDisable(GL_LINE_SMOOTH); glDisable(GL_LINE_SMOOTH);
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex2f(eyeTargetX - PIXEL_BOX/2, eyeTargetY); glVertex2f(eyeTargetX - PIXEL_BOX/2, eyeTargetY);
@ -578,11 +618,6 @@ void MyAvatar::clearLookAtTargetAvatar() {
_lookAtTargetAvatar.clear(); _lookAtTargetAvatar.clear();
} }
float MyAvatar::getAbsoluteHeadYaw() const {
const Head* head = static_cast<const Head*>(_headData);
return glm::yaw(head->getOrientation());
}
glm::vec3 MyAvatar::getUprightHeadPosition() const { glm::vec3 MyAvatar::getUprightHeadPosition() const {
return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f); return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f);
} }
@ -641,11 +676,11 @@ void MyAvatar::updateThrust(float deltaTime) {
glm::vec3 up = orientation * IDENTITY_UP; glm::vec3 up = orientation * IDENTITY_UP;
const float THRUST_MAG_UP = 800.0f; const float THRUST_MAG_UP = 800.0f;
const float THRUST_MAG_DOWN = 300.f; const float THRUST_MAG_DOWN = 300.0f;
const float THRUST_MAG_FWD = 500.f; const float THRUST_MAG_FWD = 500.0f;
const float THRUST_MAG_BACK = 300.f; const float THRUST_MAG_BACK = 300.0f;
const float THRUST_MAG_LATERAL = 250.f; const float THRUST_MAG_LATERAL = 250.0f;
const float THRUST_JUMP = 120.f; const float THRUST_JUMP = 120.0f;
// Add Thrusts from keyboard // Add Thrusts from keyboard
_thrust += _driveKeys[FWD] * _scale * THRUST_MAG_FWD * _thrustMultiplier * deltaTime * front; _thrust += _driveKeys[FWD] * _scale * THRUST_MAG_FWD * _thrustMultiplier * deltaTime * front;
@ -656,25 +691,25 @@ void MyAvatar::updateThrust(float deltaTime) {
_thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up; _thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up;
// attenuate thrust when in penetration // attenuate thrust when in penetration
if (glm::dot(_thrust, _lastBodyPenetration) > 0.f) { if (glm::dot(_thrust, _lastBodyPenetration) > 0.0f) {
const float MAX_BODY_PENETRATION_DEPTH = 0.6f * _skeletonModel.getBoundingShapeRadius(); const float MAX_BODY_PENETRATION_DEPTH = 0.6f * _skeletonModel.getBoundingShapeRadius();
float penetrationFactor = glm::min(1.f, glm::length(_lastBodyPenetration) / MAX_BODY_PENETRATION_DEPTH); float penetrationFactor = glm::min(1.0f, glm::length(_lastBodyPenetration) / MAX_BODY_PENETRATION_DEPTH);
glm::vec3 penetrationDirection = glm::normalize(_lastBodyPenetration); glm::vec3 penetrationDirection = glm::normalize(_lastBodyPenetration);
// attenuate parallel component // attenuate parallel component
glm::vec3 parallelThrust = glm::dot(_thrust, penetrationDirection) * penetrationDirection; glm::vec3 parallelThrust = glm::dot(_thrust, penetrationDirection) * penetrationDirection;
// attenuate perpendicular component (friction) // attenuate perpendicular component (friction)
glm::vec3 perpendicularThrust = _thrust - parallelThrust; glm::vec3 perpendicularThrust = _thrust - parallelThrust;
// recombine to get the final thrust // recombine to get the final thrust
_thrust = (1.f - penetrationFactor) * parallelThrust + (1.f - penetrationFactor * penetrationFactor) * perpendicularThrust; _thrust = (1.0f - penetrationFactor) * parallelThrust + (1.0f - penetrationFactor * penetrationFactor) * perpendicularThrust;
// attenuate the growth of _thrustMultiplier when in penetration // attenuate the growth of _thrustMultiplier when in penetration
// otherwise the avatar will eventually be able to tunnel through the obstacle // otherwise the avatar will eventually be able to tunnel through the obstacle
_thrustMultiplier *= (1.f - penetrationFactor * penetrationFactor); _thrustMultiplier *= (1.0f - penetrationFactor * penetrationFactor);
} else if (_thrustMultiplier < 1.f) { } else if (_thrustMultiplier < 1.0f) {
// rapid healing of attenuated thrustMultiplier after penetration event // rapid healing of attenuated thrustMultiplier after penetration event
_thrustMultiplier = 1.f; _thrustMultiplier = 1.0f;
} }
_lastBodyPenetration = glm::vec3(0.f); _lastBodyPenetration = glm::vec3(0.0f);
_bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime;
_bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime;
@ -684,12 +719,12 @@ void MyAvatar::updateThrust(float deltaTime) {
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) { if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
const float THRUST_INCREASE_RATE = 1.05f; const float THRUST_INCREASE_RATE = 1.05f;
const float MAX_THRUST_MULTIPLIER = 75.0f; const float MAX_THRUST_MULTIPLIER = 75.0f;
_thrustMultiplier *= 1.f + deltaTime * THRUST_INCREASE_RATE; _thrustMultiplier *= 1.0f + deltaTime * THRUST_INCREASE_RATE;
if (_thrustMultiplier > MAX_THRUST_MULTIPLIER) { if (_thrustMultiplier > MAX_THRUST_MULTIPLIER) {
_thrustMultiplier = MAX_THRUST_MULTIPLIER; _thrustMultiplier = MAX_THRUST_MULTIPLIER;
} }
} else { } else {
_thrustMultiplier = 1.f; _thrustMultiplier = 1.0f;
} }
// Add one time jumping force if requested // Add one time jumping force if requested
@ -794,11 +829,11 @@ void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity
if (penetrationLength > EPSILON) { if (penetrationLength > EPSILON) {
_elapsedTimeSinceCollision = 0.0f; _elapsedTimeSinceCollision = 0.0f;
glm::vec3 direction = penetration / penetrationLength; glm::vec3 direction = penetration / penetrationLength;
_velocity -= glm::dot(_velocity, direction) * direction * (1.f + elasticity); _velocity -= glm::dot(_velocity, direction) * direction * (1.0f + elasticity);
_velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f); _velocity *= glm::clamp(1.0f - damping, 0.0f, 1.0f);
if ((glm::length(_velocity) < HALTING_VELOCITY) && (glm::length(_thrust) == 0.f)) { if ((glm::length(_velocity) < HALTING_VELOCITY) && (glm::length(_thrust) == 0.0f)) {
// If moving really slowly after a collision, and not applying forces, stop altogether // If moving really slowly after a collision, and not applying forces, stop altogether
_velocity *= 0.f; _velocity *= 0.0f;
} }
} }
} }
@ -806,7 +841,7 @@ void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity
void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) { void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) {
// consider whether to have the collision make a sound // consider whether to have the collision make a sound
const float AUDIBLE_COLLISION_THRESHOLD = 0.02f; const float AUDIBLE_COLLISION_THRESHOLD = 0.02f;
const float COLLISION_LOUDNESS = 1.f; const float COLLISION_LOUDNESS = 1.0f;
const float DURATION_SCALING = 0.004f; const float DURATION_SCALING = 0.004f;
const float NOISE_SCALING = 0.1f; const float NOISE_SCALING = 0.1f;
glm::vec3 velocity = _velocity; glm::vec3 velocity = _velocity;
@ -826,10 +861,10 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim
// Noise is a function of the angle of collision // Noise is a function of the angle of collision
// Duration of the sound is a function of both base frequency and velocity of impact // Duration of the sound is a function of both base frequency and velocity of impact
Application::getInstance()->getAudio()->startCollisionSound( Application::getInstance()->getAudio()->startCollisionSound(
std::min(COLLISION_LOUDNESS * velocityTowardCollision, 1.f), std::min(COLLISION_LOUDNESS * velocityTowardCollision, 1.0f),
frequency * (1.f + velocityTangentToCollision / velocityTowardCollision), frequency * (1.0f + velocityTangentToCollision / velocityTowardCollision),
std::min(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.f), std::min(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.0f),
1.f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, true); 1.0f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, true);
} }
} }
@ -842,8 +877,8 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float
float halfHeights = 0.5 * (heightA + heightB); float halfHeights = 0.5 * (heightA + heightB);
if (yDistance < halfHeights) { if (yDistance < halfHeights) {
// cylinders collide // cylinders collide
if (xzDistance > 0.f) { if (xzDistance > 0.0f) {
positionBA.y = 0.f; positionBA.y = 0.0f;
// note, penetration should point from A into B // note, penetration should point from A into B
penetration = positionBA * ((radiusA + radiusB - xzDistance) / xzDistance); penetration = positionBA * ((radiusA + radiusB - xzDistance) / xzDistance);
return true; return true;
@ -853,7 +888,7 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float
} }
} else if (yDistance < halfHeights + radiusA + radiusB) { } else if (yDistance < halfHeights + radiusA + radiusB) {
// caps collide // caps collide
if (positionBA.y < 0.f) { if (positionBA.y < 0.0f) {
// A is above B // A is above B
positionBA.y += halfHeights; positionBA.y += halfHeights;
float BA = glm::length(positionBA); float BA = glm::length(positionBA);
@ -912,7 +947,7 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
ShapeCollider::shapeShape(myShape, theirShape, bodyCollisions); ShapeCollider::shapeShape(myShape, theirShape, bodyCollisions);
} }
} }
glm::vec3 totalPenetration(0.f); glm::vec3 totalPenetration(0.0f);
for (int j = 0; j < bodyCollisions.size(); ++j) { for (int j = 0; j < bodyCollisions.size(); ++j) {
CollisionInfo* collision = bodyCollisions.getCollision(j); CollisionInfo* collision = bodyCollisions.getCollision(j);
totalPenetration = addPenetrations(totalPenetration, collision->_penetration); totalPenetration = addPenetrations(totalPenetration, collision->_penetration);
@ -1076,15 +1111,15 @@ void MyAvatar::goHome() {
} }
void MyAvatar::increaseSize() { void MyAvatar::increaseSize() {
if ((1.f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) { if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) {
_targetScale *= (1.f + SCALING_RATIO); _targetScale *= (1.0f + SCALING_RATIO);
qDebug("Changed scale to %f", _targetScale); qDebug("Changed scale to %f", _targetScale);
} }
} }
void MyAvatar::decreaseSize() { void MyAvatar::decreaseSize() {
if (MIN_AVATAR_SCALE < (1.f - SCALING_RATIO) * _targetScale) { if (MIN_AVATAR_SCALE < (1.0f - SCALING_RATIO) * _targetScale) {
_targetScale *= (1.f - SCALING_RATIO); _targetScale *= (1.0f - SCALING_RATIO);
qDebug("Changed scale to %f", _targetScale); qDebug("Changed scale to %f", _targetScale);
} }
} }
@ -1160,8 +1195,8 @@ void MyAvatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& pe
if (leverLength > EPSILON) { if (leverLength > EPSILON) {
// compute lean perturbation angles // compute lean perturbation angles
glm::quat bodyRotation = getOrientation(); glm::quat bodyRotation = getOrientation();
glm::vec3 xAxis = bodyRotation * glm::vec3(1.f, 0.f, 0.f); glm::vec3 xAxis = bodyRotation * glm::vec3(1.0f, 0.0f, 0.0f);
glm::vec3 zAxis = bodyRotation * glm::vec3(0.f, 0.f, 1.f); glm::vec3 zAxis = bodyRotation * glm::vec3(0.0f, 0.0f, 1.0f);
leverAxis = leverAxis / leverLength; leverAxis = leverAxis / leverLength;
glm::vec3 effectivePenetration = penetration - glm::dot(penetration, leverAxis) * leverAxis; glm::vec3 effectivePenetration = penetration - glm::dot(penetration, leverAxis) * leverAxis;

View file

@ -57,7 +57,6 @@ public:
float getLeanScale() const { return _leanScale; } float getLeanScale() const { return _leanScale; }
float getElapsedTimeStopped() const { return _elapsedTimeStopped; } float getElapsedTimeStopped() const { return _elapsedTimeStopped; }
float getElapsedTimeMoving() const { return _elapsedTimeMoving; } float getElapsedTimeMoving() const { return _elapsedTimeMoving; }
float getAbsoluteHeadYaw() const; // degrees
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
glm::vec3 getGravity() const { return _gravity; } glm::vec3 getGravity() const { return _gravity; }
@ -128,8 +127,8 @@ private:
QWeakPointer<AvatarData> _lookAtTargetAvatar; QWeakPointer<AvatarData> _lookAtTargetAvatar;
glm::vec3 _targetAvatarPosition; glm::vec3 _targetAvatarPosition;
bool _shouldRender; bool _shouldRender;
bool _billboardValid; bool _billboardValid;
float _oculusYawOffset;
// private methods // private methods
void updateThrust(float deltaTime); void updateThrust(float deltaTime);

View file

@ -30,7 +30,6 @@ int OculusManager::_scaleLocation;
int OculusManager::_scaleInLocation; int OculusManager::_scaleInLocation;
int OculusManager::_hmdWarpParamLocation; int OculusManager::_hmdWarpParamLocation;
bool OculusManager::_isConnected = false; bool OculusManager::_isConnected = false;
float OculusManager::_yawOffset = 0.0f; // radians
#ifdef HAVE_LIBOVR #ifdef HAVE_LIBOVR
using namespace OVR; using namespace OVR;
@ -190,18 +189,9 @@ void OculusManager::reset() {
#endif #endif
} }
void OculusManager::updateYawOffset() {
#ifdef HAVE_LIBOVR
float yaw, pitch, roll;
_sensorFusion->GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
_yawOffset = yaw;
#endif
}
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) { void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
#ifdef HAVE_LIBOVR #ifdef HAVE_LIBOVR
_sensorFusion->GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll); _sensorFusion->GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
yaw = yaw - _yawOffset;
#endif #endif
} }

View file

@ -51,7 +51,6 @@ private:
static int _scaleInLocation; static int _scaleInLocation;
static int _hmdWarpParamLocation; static int _hmdWarpParamLocation;
static bool _isConnected; static bool _isConnected;
static float _yawOffset;
#ifdef HAVE_LIBOVR #ifdef HAVE_LIBOVR
static OVR::Ptr<OVR::DeviceManager> _deviceManager; static OVR::Ptr<OVR::DeviceManager> _deviceManager;