Selfie camera and updated camera menus

This commit is contained in:
luiscuenca 2019-09-17 17:15:16 -07:00
parent 481917ae8a
commit 1054e8fcde
No known key found for this signature in database
GPG key ID: 2387ECD129A6961D
8 changed files with 158 additions and 51 deletions

View file

@ -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" },

View file

@ -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<AudioInjectorManager>();
DependencyManager::set<MessagesClient>();
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<UserInputMapper>();
@ -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");

View file

@ -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(

View file

@ -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";

View file

@ -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;
}

View file

@ -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; }

View file

@ -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";
}

View file

@ -24,6 +24,7 @@ enum CameraMode
CAMERA_MODE_INDEPENDENT,
CAMERA_MODE_ENTITY,
CAMERA_MODE_LOOK_AT,
CAMERA_MODE_SELFIE,
NUM_CAMERA_MODES
};