Fixes for flying and rotation re-centering in wikiplanet

This commit is contained in:
Anthony J. Thibault 2017-08-18 16:26:50 -07:00
parent 963ddce7bc
commit 8e56404c40
4 changed files with 23 additions and 57 deletions

View file

@ -2497,7 +2497,8 @@ void Application::paintGL() {
_myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection()));
renderArgs._context->enableStereo(true);
mat4 eyeOffsets[2];
auto baseProjection = renderArgs.getViewFrustum().getProjection();
mat4 eyeProjections[2];
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
float IPDScale = hmdInterface->getIPDScale();
@ -2505,6 +2506,12 @@ void Application::paintGL() {
float heightRatio = getMyAvatar()->getEyeHeight() / getMyAvatar()->getUserEyeHeight();
IPDScale *= heightRatio;
// adjust near clip plane by heightRatio
auto baseProjection = glm::perspective(renderArgs.getViewFrustum().getFieldOfView(),
renderArgs.getViewFrustum().getAspectRatio(),
renderArgs.getViewFrustum().getNearClip() * heightRatio,
renderArgs.getViewFrustum().getFarClip());
// FIXME we probably don't need to set the projection matrix every frame,
// only when the display plugin changes (or in non-HMD modes when the user
// changes the FOV manually, which right now I don't think they can.

View file

@ -1884,38 +1884,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
snapTurn = true;
}
// use head/HMD orientation to turn while flying
if (getCharacterController()->getState() == CharacterController::State::Hover) {
// This is the direction the user desires to fly in.
glm::vec3 desiredFacing = getMyHead()->getHeadOrientation() * Vectors::UNIT_Z;
desiredFacing.y = 0.0f;
// This is our reference frame, it is captured when the user begins to move.
glm::vec3 referenceFacing = transformVectorFast(_sensorToWorldMatrix, _hoverReferenceCameraFacing);
referenceFacing.y = 0.0f;
referenceFacing = glm::normalize(referenceFacing);
glm::vec3 referenceRight(referenceFacing.z, 0.0f, -referenceFacing.x);
const float HOVER_FLY_ROTATION_PERIOD = 0.5f;
float tau = glm::clamp(deltaTime / HOVER_FLY_ROTATION_PERIOD, 0.0f, 1.0f);
// new facing is a linear interpolation between the desired and reference vectors.
glm::vec3 newFacing = glm::normalize((1.0f - tau) * referenceFacing + tau * desiredFacing);
// calcualte the signed delta yaw angle to apply so that we match our newFacing.
float sign = copysignf(1.0f, glm::dot(desiredFacing, referenceRight));
float deltaAngle = sign * acosf(glm::clamp(glm::dot(referenceFacing, newFacing), -1.0f, 1.0f));
// speedFactor is 0 when we are at rest adn 1.0 when we are at max flying speed.
const float MAX_FLYING_SPEED = 30.0f;
float speedFactor = glm::min(glm::length(getVelocity()) / MAX_FLYING_SPEED, 1.0f);
// apply our delta, but scale it by the speed factor, so we turn faster when we are flying faster.
totalBodyYaw += (speedFactor * deltaAngle * (180.0f / PI));
}
// Use head/HMD roll to turn while walking or flying, but not when standing still
if (qApp->isHMDMode() && _hmdRollControlEnabled && hasDriveInput()) {
// Use head/HMD roll to turn while flying, but not when standing still.
if (qApp->isHMDMode() && getCharacterController()->getState() == CharacterController::State::Hover && _hmdRollControlEnabled && hasDriveInput()) {
// Turn with head roll.
const float MIN_CONTROL_SPEED = 0.01f;
float speed = glm::length(getVelocity());
@ -2067,18 +2037,6 @@ void MyAvatar::updatePosition(float deltaTime) {
_characterController.setStepUpEnabled(result.walkable);
}
}
// capture the head rotation, in sensor space, when the user first indicates they would like to move/fly.
if (!_hoverReferenceCameraFacingIsCaptured &&
(fabs(getDriveKey(TRANSLATE_Z)) > 0.1f || fabs(getDriveKey(TRANSLATE_X)) > 0.1f)) {
_hoverReferenceCameraFacingIsCaptured = true;
// transform the camera facing vector into sensor space.
_hoverReferenceCameraFacing = transformVectorFast(glm::inverse(_sensorToWorldMatrix),
getMyHead()->getHeadOrientation() * Vectors::UNIT_Z);
} else if (_hoverReferenceCameraFacingIsCaptured &&
(fabs(getDriveKey(TRANSLATE_Z)) <= 0.1f && fabs(getDriveKey(TRANSLATE_X)) <= 0.1f)) {
_hoverReferenceCameraFacingIsCaptured = false;
}
}
void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) {
@ -2756,7 +2714,6 @@ bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, co
}
bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
// -z axis of currentBodyMatrix in world space.
glm::vec3 forward = glm::normalize(glm::vec3(-currentBodyMatrix[0][2], -currentBodyMatrix[1][2], -currentBodyMatrix[2][2]));
// x axis of currentBodyMatrix in world space.
@ -2780,7 +2737,6 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar,
}
bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
const float CYLINDER_TOP = 0.1f;
const float CYLINDER_BOTTOM = -1.5f;
@ -2807,6 +2763,16 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * desiredBodyMatrix;
glm::mat4 currentWorldMatrix = myAvatar.getSensorToWorldMatrix() * currentBodyMatrix;
glm::vec4 RED(1.0f, 0.0f, 0.0f, 1.0f);
glm::vec4 GREEN(0.0f, 1.0f, 0.0f, 1.0f);
glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f);
glm::vec4 WHITE(1.0f, 1.0f, 1.0f, 1.0f);
glm::vec4 desiredColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(desiredBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? RED : GREEN;
glm::vec4 currentColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(currentBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? BLUE : WHITE;
DebugDraw::getInstance().addMarker("desiredBody", glmExtractRotation(desiredWorldMatrix), extractTranslation(desiredWorldMatrix), desiredColor);
DebugDraw::getInstance().addMarker("currentBody", glmExtractRotation(currentWorldMatrix), extractTranslation(currentWorldMatrix), currentColor);
AnimPose followWorldPose(currentWorldMatrix);
// remove scale present from sensorToWorldMatrix
@ -2846,7 +2812,6 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co
glm::mat4 newBodyMat = createMatFromQuatAndPos(sensorAngularDisplacement * glmExtractRotation(currentBodyMatrix),
sensorLinearDisplacement + extractTranslation(currentBodyMatrix));
return newBodyMat;
} else {
return currentBodyMatrix;
}

View file

@ -774,8 +774,6 @@ private:
AtRestDetector _hmdAtRestDetector;
bool _lastIsMoving { false };
bool _hoverReferenceCameraFacingIsCaptured { false };
glm::vec3 _hoverReferenceCameraFacing { 0.0f, 0.0f, -1.0f }; // hmd sensor space
// all poses are in sensor-frame
std::map<controller::Action, controller::Pose> _controllerPoseMap;

View file

@ -265,13 +265,9 @@ void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar
btVector3 endPos = startPos + linearDisplacement;
btQuaternion startRot = bodyTransform.getRotation();
glm::vec2 currentFacing = getFacingDir2D(bulletToGLM(startRot));
glm::vec2 currentRight(currentFacing.y, -currentFacing.x);
glm::vec2 desiredFacing = getFacingDir2D(bulletToGLM(_followDesiredBodyTransform.getRotation()));
float deltaAngle = acosf(glm::clamp(glm::dot(currentFacing, desiredFacing), -1.0f, 1.0f));
float angularSpeed = deltaAngle / _followTimeRemaining;
float sign = copysignf(1.0f, glm::dot(desiredFacing, currentRight));
btQuaternion angularDisplacement = btQuaternion(btVector3(0.0f, 1.0f, 0.0f), sign * angularSpeed * dt);
btQuaternion deltaRot = _followDesiredBodyTransform.getRotation() * startRot.inverse();
float angularSpeed = deltaRot.getAngle() / _followTimeRemaining;
btQuaternion angularDisplacement = btQuaternion(deltaRot.getAxis(), angularSpeed * dt);
btQuaternion endRot = angularDisplacement * startRot;
// in order to accumulate displacement of avatar position, we need to take _shapeLocalOffset into account.