From 1054e8fcde8d7a117c3b51e5a47c9feb2bc93713 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 17 Sep 2019 17:15:16 -0700 Subject: [PATCH] Selfie camera and updated camera menus --- .../resources/controllers/keyboardMouse.json | 49 +++++++++++-- interface/src/Application.cpp | 58 ++++++++++++---- interface/src/Menu.cpp | 15 ++-- interface/src/Menu.h | 2 + interface/src/avatar/MyAvatar.cpp | 69 ++++++++++++------- interface/src/avatar/MyAvatar.h | 11 ++- libraries/shared/src/shared/Camera.cpp | 4 ++ libraries/shared/src/shared/Camera.h | 1 + 8 files changed, 158 insertions(+), 51 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index c48269b83b..39b44a646e 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -3,8 +3,8 @@ "channels": [ { "from": "Keyboard.A", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" }, { "from": "Keyboard.D", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" }, - { "from": "Keyboard.E", "when": "!Keyboard.Control", "to": "Actions.LATERAL_RIGHT" }, - { "from": "Keyboard.Q", "when": "!Keyboard.Control", "to": "Actions.LATERAL_LEFT" }, + { "from": "Keyboard.E", "when": ["!Application.CameraLookAt", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" }, + { "from": "Keyboard.Q", "when": ["!Application.CameraLookAt", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" }, { "from": "Keyboard.T", "when": "!Keyboard.Control", "to": "Actions.TogglePushToTalk" }, { "comment" : "Mouse turn need to be small continuous increments", @@ -39,7 +39,6 @@ ] }, - { "from": { "makeAxis" : [ ["Keyboard.Left" ], ["Keyboard.Right"] @@ -95,6 +94,15 @@ "to": "Actions.Yaw" }, + { "from": { "makeAxis" : [ + ["Keyboard.Left"], + ["Keyboard.Right"] + ] + }, + "when": ["Application.CameraSelfie", "!Keyboard.Shift"], + "to": "Actions.Yaw" + }, + { "from": { "makeAxis" : [ ["Keyboard.A"], ["Keyboard.D"] @@ -113,12 +121,21 @@ "to": "Actions.Yaw" }, + { "from": { "makeAxis" : [ + ["Keyboard.Q"], + ["Keyboard.E"] + ] + }, + "when": ["Application.CameraLookAt", "!Keyboard.Control"], + "to": "Actions.Yaw" + }, + { "from": { "makeAxis" : [ ["Keyboard.A"], ["Keyboard.D"] ] }, - "when": ["Application.CameraLookAt", "!Keyboard.Control"], + "when": ["Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.Yaw" }, @@ -149,6 +166,15 @@ "to": "Actions.Yaw" }, + { "from": { "makeAxis" : [ + ["Keyboard.TouchpadLeft"], + ["Keyboard.TouchpadRight"] + ] + }, + "when": "Application.CameraSelfie", + "to": "Actions.Yaw" + }, + { "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] }, "when": "Keyboard.RightMouseButton", "to": "Actions.DeltaYaw", @@ -159,7 +185,16 @@ }, { "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] }, - "when": "Keyboard.RightMouseButton", + "when": ["!Application.CameraSelfie", "Keyboard.RightMouseButton"], + "to": "Actions.DeltaPitch", + "filters": + [ + { "type": "scale", "scale": 0.6 } + ] + }, + + { "from": { "makeAxis" : ["Keyboard.MouseMoveDown", "Keyboard.MouseMoveUp"] }, + "when": ["Application.CameraSelfie", "Keyboard.RightMouseButton"], "to": "Actions.DeltaPitch", "filters": [ @@ -169,6 +204,8 @@ { "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" }, { "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" }, + { "from": "Keyboard.A", "when": "Application.CameraLookAt", "to": "Actions.LATERAL_LEFT" }, + { "from": "Keyboard.D", "when": "Application.CameraLookAt", "to": "Actions.LATERAL_RIGHT" }, { "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" }, { "from": "Keyboard.C", "when": "!Keyboard.Control", "to": "Actions.VERTICAL_DOWN" }, { "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" }, @@ -176,9 +213,11 @@ { "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" }, { "from": "Keyboard.Up", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_FORWARD" }, { "from": "Keyboard.Up", "when": "Application.CameraLookAt", "to": "Actions.LONGITUDINAL_FORWARD" }, + { "from": "Keyboard.Up", "when": "Application.CameraSelfie", "to": "Actions.LONGITUDINAL_FORWARD" }, { "from": "Keyboard.Down", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_BACKWARD" }, { "from": "Keyboard.Down", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_BACKWARD" }, { "from": "Keyboard.Down", "when": "Application.CameraLookAt", "to": "Actions.LONGITUDINAL_BACKWARD" }, + { "from": "Keyboard.Down", "when": "Application.CameraSelfie", "to": "Actions.LONGITUDINAL_BACKWARD" }, { "from": "Keyboard.PgDown", "to": "Actions.VERTICAL_DOWN" }, { "from": "Keyboard.PgUp", "to": "Actions.VERTICAL_UP" }, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e45d0b4c57..ab7fda9201 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -710,6 +710,7 @@ static const QString STATE_CAMERA_THIRD_PERSON = "CameraThirdPerson"; static const QString STATE_CAMERA_ENTITY = "CameraEntity"; static const QString STATE_CAMERA_INDEPENDENT = "CameraIndependent"; static const QString STATE_CAMERA_LOOK_AT = "CameraLookAt"; +static const QString STATE_CAMERA_SELFIE = "CameraSelfie"; static const QString STATE_SNAP_TURN = "SnapTurn"; static const QString STATE_ADVANCED_MOVEMENT_CONTROLS = "AdvancedMovement"; static const QString STATE_GROUNDED = "Grounded"; @@ -926,7 +927,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, - STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, + STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE, STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED, STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } }); DependencyManager::set(); @@ -1876,6 +1877,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _applicationStateDevice->setInputVariant(STATE_CAMERA_LOOK_AT, []() -> float { return qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT ? 1 : 0; }); + _applicationStateDevice->setInputVariant(STATE_CAMERA_SELFIE, []() -> float { + return qApp->getCamera().getMode() == CAMERA_MODE_SELFIE ? 1 : 0; + }); _applicationStateDevice->setInputVariant(STATE_CAMERA_ENTITY, []() -> float { return qApp->getCamera().getMode() == CAMERA_MODE_ENTITY ? 1 : 0; }); @@ -3611,7 +3615,9 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { _myCamera.setPosition(myAvatar->getDefaultEyePosition()); _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); } - } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON || _myCamera.getMode() == CAMERA_MODE_LOOK_AT) { + } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON || + _myCamera.getMode() == CAMERA_MODE_LOOK_AT || + _myCamera.getMode() == CAMERA_MODE_SELFIE) { if (isHMDMode()) { if (!_thirdPersonHMDCameraBoomValid) { @@ -3640,8 +3646,12 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { + myAvatar->getWorldOrientation() * boomOffset); } } else { + glm::quat lookAtOffset = myAvatar->getLookAtOffset(); + if (_myCamera.getMode() == CAMERA_MODE_SELFIE) { + lookAtOffset = lookAtOffset * glm::angleAxis(PI, myAvatar->getWorldOrientation() * Vectors::UP); + } _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + myAvatar->getLookAtOffset() * boomOffset); + + lookAtOffset * boomOffset); _myCamera.lookAt(myAvatar->getDefaultEyePosition()); } } @@ -3683,8 +3693,7 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { glm::vec3(0.0f, 0.0f, -1.0f) * myAvatar->getBoomLength() * _scaleMirror); } renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; - } - else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) { + } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) { _thirdPersonHMDCameraBoomValid= false; EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer(); if (cameraEntity != nullptr) { @@ -4401,15 +4410,19 @@ void Application::keyPressEvent(QKeyEvent* event) { } case Qt::Key_2: { Menu* menu = Menu::getInstance(); - menu->triggerOption(MenuOption::FullscreenMirror); + menu->triggerOption(MenuOption::SelfieScreen); break; } case Qt::Key_3: { Menu* menu = Menu::getInstance(); - menu->triggerOption(MenuOption::ThirdPerson); + menu->triggerOption(MenuOption::LookAtScreen); + break; + } + case Qt::Key_4: { + Menu* menu = Menu::getInstance(); + menu->triggerOption(MenuOption::FullscreenMirror); break; } - case Qt::Key_4: case Qt::Key_5: case Qt::Key_6: case Qt::Key_7: @@ -5968,11 +5981,16 @@ void Application::cycleCamera() { } else if (menu->isOptionChecked(MenuOption::FirstPerson)) { menu->setIsOptionChecked(MenuOption::FirstPerson, false); - menu->setIsOptionChecked(MenuOption::ThirdPerson, true); + menu->setIsOptionChecked(MenuOption::LookAtScreen, true); - } else if (menu->isOptionChecked(MenuOption::ThirdPerson)) { + } else if (menu->isOptionChecked(MenuOption::LookAtScreen)) { - menu->setIsOptionChecked(MenuOption::ThirdPerson, false); + menu->setIsOptionChecked(MenuOption::LookAtScreen, false); + menu->setIsOptionChecked(MenuOption::SelfieScreen, true); + + } else if (menu->isOptionChecked(MenuOption::SelfieScreen)) { + + menu->setIsOptionChecked(MenuOption::SelfieScreen, false); menu->setIsOptionChecked(MenuOption::FullscreenMirror, true); } @@ -5985,7 +6003,10 @@ void Application::cameraModeChanged() { Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true); break; case CAMERA_MODE_LOOK_AT: - Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); + Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtScreen, true); + break; + case CAMERA_MODE_SELFIE: + Menu::getInstance()->setIsOptionChecked(MenuOption::SelfieScreen, true); break; case CAMERA_MODE_MIRROR: Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); @@ -6027,13 +6048,20 @@ void Application::cameraMenuChanged() { _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); } - } else if (menu->isOptionChecked(MenuOption::ThirdPerson)) { + } else if (menu->isOptionChecked(MenuOption::LookAtScreen)) { if (_myCamera.getMode() != CAMERA_MODE_LOOK_AT) { _myCamera.setMode(CAMERA_MODE_LOOK_AT); if (getMyAvatar()->getBoomLength() == MyAvatar::ZOOM_MIN) { getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT); } } + } else if (menu->isOptionChecked(MenuOption::SelfieScreen)) { + if (_myCamera.getMode() != CAMERA_MODE_SELFIE) { + _myCamera.setMode(CAMERA_MODE_SELFIE); + if (getMyAvatar()->getBoomLength() == MyAvatar::ZOOM_MIN) { + getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT); + } + } } } @@ -9117,9 +9145,11 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { cameraMenuChanged(); } - // Remove the mirror camera option from menu if in HMD mode + // Remove the mirror and selfie camera options from menu if in HMD mode auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror); mirrorAction->setVisible(!isHmd); + auto selfieAction = menu->getActionForOption(MenuOption::SelfieScreen); + selfieAction->setVisible(!isHmd); } Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8c6292681b..82fcade805 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -177,12 +177,19 @@ Menu::Menu() { firstPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); - // View > Third Person - auto thirdPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( - viewMenu, MenuOption::ThirdPerson, 0, + // View > Look At + auto lookAtAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( + viewMenu, MenuOption::LookAtScreen, 0, false, qApp, SLOT(cameraMenuChanged()))); - thirdPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); + lookAtAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); + + // View > Selfie + auto selfieAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( + viewMenu, MenuOption::SelfieScreen, 0, + false, qApp, SLOT(cameraMenuChanged()))); + + selfieAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup)); // View > Mirror auto viewMirrorAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7dff264adc..9db06b40e7 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -129,6 +129,7 @@ namespace MenuOption { const QString Login = "Login/Sign Up"; const QString Log = "Log"; const QString LogExtraTimings = "Log Extra Timing Details"; + const QString LookAtScreen = "Look At"; const QString LowVelocityFilter = "Low Velocity Filter"; const QString MeshVisible = "Draw Mesh"; const QString MuteEnvironment = "Mute Environment"; @@ -181,6 +182,7 @@ namespace MenuOption { const QString RunTimingTests = "Run Timing Tests"; const QString ScriptedMotorControl = "Enable Scripted Motor Control"; const QString ShowTrackedObjects = "Show Tracked Objects"; + const QString SelfieScreen = "Selfie"; const QString SendWrongDSConnectVersion = "Send wrong DS connect version"; const QString SendWrongProtocolVersion = "Send wrong protocol version"; const QString SetHomeLocation = "Set Home Location"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ea443ef068..36d3ad3156 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -455,7 +455,7 @@ QByteArray MyAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropF _globalBoundingBoxDimensions.y = _characterController.getCapsuleHalfHeight(); _globalBoundingBoxDimensions.z = _characterController.getCapsuleRadius(); _globalBoundingBoxOffset = _characterController.getCapsuleLocalOffset(); - if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT || mode == CAMERA_MODE_LOOK_AT) { + if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) { // fake the avatar position that is sent up to the AvatarMixer glm::vec3 oldPosition = getWorldPosition(); setWorldPosition(getSkeletonPosition()); @@ -940,7 +940,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) { head->setPosition(headPosition); head->setScale(getModelScale()); head->simulate(deltaTime); - if (_scriptControlsHeadLookAt || qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT) { + if (_scriptControlsHeadLookAt || qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT || qApp->getCamera().getMode() == CAMERA_MODE_SELFIE) { updateHeadLookAt(deltaTime); } else if (_headLookAtActive){ resetHeadLookAt(); @@ -2566,7 +2566,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN glm::vec3 MyAvatar::getSkeletonPosition() const { CameraMode mode = qApp->getCamera().getMode(); - if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT || mode == CAMERA_MODE_LOOK_AT) { + if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) { // The avatar is rotated PI about the yAxis, so we have to correct for it // to get the skeleton offset contribution in the world-frame. const glm::quat FLIP = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); @@ -3333,13 +3333,15 @@ void MyAvatar::setRotationThreshold(float angleRadians) { void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys float targetSpeed = getDriveKey(YAW) * _yawSpeed; - bool faceForward = false; - const float FPS = 60.0f; - if (qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT) { - float TIMESCALE_SPEED_CORRECTOR = deltaTime != 0.0f ? 1.0f / (FPS * deltaTime) : 1.0f; - targetSpeed = (getDriveKey(YAW) + getDriveKey(STEP_YAW) + getDriveKey(DELTA_YAW)) * _yawSpeed * TIMESCALE_SPEED_CORRECTOR; - faceForward = getDriveKey(TRANSLATE_Z) != 0.0f || getDriveKey(TRANSLATE_X) != 0.0f; + bool computeCameraLookAt = (qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT || + qApp->getCamera().getMode() == CAMERA_MODE_SELFIE) && isReadyForPhysics(); + if (computeCameraLookAt) { + // Rotate directly proportional to delta yaw and delta pitch from right-click mouse movement. + float speedFromDeltaYaw = deltaTime > FLT_EPSILON ? getDriveKey(DELTA_YAW) / deltaTime : 0.0f; + speedFromDeltaYaw *= _yawSpeed / YAW_SPEED_DEFAULT; + targetSpeed += speedFromDeltaYaw; } + if (targetSpeed != 0.0f) { const float ROTATION_RAMP_TIMESCALE = 0.5f; float blend = deltaTime / ROTATION_RAMP_TIMESCALE; @@ -3362,13 +3364,9 @@ void MyAvatar::updateOrientation(float deltaTime) { } } float totalBodyYaw = _bodyYawDelta * deltaTime; - - // Rotate directly proportional to delta yaw and delta pitch from right-click mouse movement. - bool computeCameraLookAt = qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT && isReadyForPhysics(); if (!computeCameraLookAt) { totalBodyYaw += getDriveKey(DELTA_YAW) * _yawSpeed / YAW_SPEED_DEFAULT; } - // Comfort Mode: If you press any of the left/right rotation drive keys or input, you'll // get an instantaneous 15 degree turn. If you keep holding the key down you'll get another // snap turn every half second. @@ -3377,7 +3375,6 @@ void MyAvatar::updateOrientation(float deltaTime) { totalBodyYaw += getDriveKey(STEP_YAW); snapTurn = true; } - // Use head/HMD roll to turn while flying, but not when standing still. if (qApp->isHMDMode() && getCharacterController()->getState() == CharacterController::State::Hover && _hmdRollControlEnabled && hasDriveInput()) { @@ -3413,6 +3410,10 @@ void MyAvatar::updateOrientation(float deltaTime) { // update body orientation by movement inputs glm::quat initialOrientation = getOrientationOutbound(); glm::vec3 eyesPosition = getDefaultEyePosition(); + const float FPS = 60.0f; + float timeScale = deltaTime * FPS; + + bool faceForward = false; if (!computeCameraLookAt) { setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f)))); _lookAtCameraTarget = eyesPosition + getWorldOrientation() * Vectors::FRONT; @@ -3423,8 +3424,9 @@ void MyAvatar::updateOrientation(float deltaTime) { if (totalBodyYaw != 0.0f) { _lookAtOffsetYaw = _lookAtOffsetYaw * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))); } + float deltalPitchSign = 1.0f;// qApp->getCamera().getMode() == CAMERA_MODE_SELFIE ? -1.0f : 1.0f; float pitchIncrement = getDriveKey(PITCH) * _pitchSpeed * deltaTime - + getDriveKey(DELTA_PITCH) * _pitchSpeed / PITCH_SPEED_DEFAULT; + + deltalPitchSign * getDriveKey(DELTA_PITCH) * _pitchSpeed / PITCH_SPEED_DEFAULT; if (pitchIncrement != 0.0f) { glm::quat _previousLookAtOffsetPitch = _lookAtOffsetPitch; _lookAtOffsetPitch = _lookAtOffsetPitch * glm::quat(glm::radians(glm::vec3(pitchIncrement, 0.0f, 0.0f))); @@ -3435,15 +3437,21 @@ void MyAvatar::updateOrientation(float deltaTime) { _lookAtOffsetPitch = _previousLookAtOffsetPitch; } } - + bool isMovingFwdBwd = getDriveKey(TRANSLATE_Z) != 0.0f; + bool isMovingSideways = getDriveKey(TRANSLATE_X) != 0.0f; + faceForward = computeCameraLookAt && (isMovingFwdBwd || isMovingSideways); // Blend the avatar orientation with the camera look at if moving forward. - if (faceForward || _shouldTurnToFaceCamera != 0) { - const float FACE_FORWARD_BLEND = 0.25f; - const float FACE_TURN_BLEND = 0.03f; + if (faceForward || _shouldTurnToFaceCamera) { + const float REORIENT_FORWARD_BLEND = 0.25f; + const float REORIENT_TURN_BLEND = 0.03f; const float DIAGONAL_TURN_BLEND = 0.02f; - float blend = _shouldTurnToFaceCamera ? FACE_TURN_BLEND : FACE_FORWARD_BLEND; + float blend = (_shouldTurnToFaceCamera ? REORIENT_TURN_BLEND : REORIENT_FORWARD_BLEND) * timeScale; + if (blend > 1.0f) { + blend = 1.0f; + } glm::quat faceRotation = _lookAtOffsetYaw; - if (getDriveKey(TRANSLATE_Z) != 0.0f && getDriveKey(TRANSLATE_X) != 0.0f) { + if (isMovingFwdBwd && isMovingSideways) { + // Reorient avatar to face camera diagonal blend = DIAGONAL_TURN_BLEND; if (getDriveKey(TRANSLATE_X) > 0.0f) { faceRotation = _lookAtOffsetYaw * glm::angleAxis(-0.25f * PI, Vectors::UP); @@ -3451,7 +3459,7 @@ void MyAvatar::updateOrientation(float deltaTime) { faceRotation = _lookAtOffsetYaw * glm::angleAxis(0.25f * PI, Vectors::UP); } } - setWorldOrientation(glm::slerp(getWorldOrientation(), faceRotation, blend * deltaTime * FPS)); + setWorldOrientation(glm::slerp(getWorldOrientation(), faceRotation, blend)); } } @@ -3527,11 +3535,14 @@ void MyAvatar::updateOrientation(float deltaTime) { const float TARGET_DISTANCE_FROM_EYES = 20.0f; glm::vec3 targetPoint = eyesPosition + TARGET_DISTANCE_FROM_EYES * glm::normalize(cameraVector); - // const float LOOKAT_MIX_ALPHA = 0.05f; + // const float LOOKAT_MIX_ALPHA = 0.25f; if (getDriveKey(TRANSLATE_Y) == 0.0f) { // Approximate the head's look at vector to the camera look at vector with some delay. - float mixAlpha = (frontBackDot > 0.0f ? _backLookAtSpeed : _frontLookAtSpeed) * deltaTime * FPS; + float mixAlpha = (frontBackDot > 0.0f ? _backLookAtSpeed : _frontLookAtSpeed) * timeScale; + if (mixAlpha > 1.0f) { + mixAlpha = 1.0f; + } _lookAtCameraTarget = glm::mix(_lookAtCameraTarget, targetPoint, mixAlpha); } else { _lookAtCameraTarget = targetPoint; @@ -6459,6 +6470,7 @@ void MyAvatar::updateHeadLookAt(float deltaTime) { glm::vec3 lookAtTarget = _scriptControlsHeadLookAt ? _lookAtScriptTarget : _lookAtCameraTarget; glm::vec3 avatarXVector = glm::normalize(getWorldOrientation() * Vectors::UNIT_X); glm::vec3 avatarYVector = glm::normalize(getWorldOrientation() * Vectors::UNIT_Y); + glm::vec3 avatarZVector = glm::normalize(getWorldOrientation() * Vectors::UNIT_Z); glm::vec3 headToTargetVector = lookAtTarget - getDefaultEyePosition(); if (glm::length(headToTargetVector) > EPSILON) { headToTargetVector = glm::normalize(headToTargetVector); @@ -6469,6 +6481,11 @@ void MyAvatar::updateHeadLookAt(float deltaTime) { float xDot = glm::dot(avatarXVector, headToTargetVector); float yDot = glm::dot(avatarYVector, headToTargetVector); + float zDot = glm::dot(avatarZVector, headToTargetVector); + // Force the head to look at one of the sides when the look at point is behind the avatar + if (zDot > 0.0f && xDot != 0.0f) { + //xDot /= fabsf(xDot); + } // Make sure dot products are in range to avoid acosf returning NaN xDot = glm::min(glm::max(xDot, -1.0f), 1.0f); @@ -6496,9 +6513,9 @@ void MyAvatar::updateHeadLookAt(float deltaTime) { } } -void MyAvatar::headLookAt(const glm::vec3& lookAtTarget) { +void MyAvatar::setHeadLookAt(const glm::vec3& lookAtTarget) { if (QThread::currentThread() != thread()) { - BLOCKING_INVOKE_METHOD(this, "headLookAt", + BLOCKING_INVOKE_METHOD(this, "setHeadLookAt", Q_ARG(const glm::vec3&, lookAtTarget)); return; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 7c3091bf6a..90a2c0887a 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1749,10 +1749,17 @@ public: /**jsdoc * Turn the avatar's head until it faces the target point within the 90/-90 degrees range. - * @function MyAvatar.headLookAt + * @function MyAvatar.setHeadLookAt * @param {Vec3} lookAtTarget - The target 3D point. */ - Q_INVOKABLE void headLookAt(const glm::vec3& lookAtTarget); + Q_INVOKABLE void setHeadLookAt(const glm::vec3& lookAtTarget); + + /**jsdoc + * Returns the current head look at target point in world coordenates. + * @function MyAvatar.getHeadLookAt + * @returns {Vec3} Default position between your avatar's eyes in world coordinates. + */ + Q_INVOKABLE glm::vec3 getHeadLookAt() { return _lookAtCameraTarget; } glm::quat getLookAtOffset() { return _lookAtOffsetYaw * _lookAtOffsetPitch; } diff --git a/libraries/shared/src/shared/Camera.cpp b/libraries/shared/src/shared/Camera.cpp index 4716713a2b..c87b30b499 100644 --- a/libraries/shared/src/shared/Camera.cpp +++ b/libraries/shared/src/shared/Camera.cpp @@ -69,6 +69,8 @@ CameraMode stringToMode(const QString& mode) { return CAMERA_MODE_ENTITY; } else if (mode == "look at") { return CAMERA_MODE_LOOK_AT; + } else if (mode == "selfie") { + return CAMERA_MODE_SELFIE; } return CAMERA_MODE_NULL; } @@ -86,6 +88,8 @@ QString modeToString(CameraMode mode) { return "entity"; } else if (mode == CAMERA_MODE_LOOK_AT) { return "look at"; + } else if (mode == CAMERA_MODE_SELFIE) { + return "selfie"; } return "unknown"; } diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index bae4b9aeae..eecad34838 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -24,6 +24,7 @@ enum CameraMode CAMERA_MODE_INDEPENDENT, CAMERA_MODE_ENTITY, CAMERA_MODE_LOOK_AT, + CAMERA_MODE_SELFIE, NUM_CAMERA_MODES };