Angles instead dot product and fix API

This commit is contained in:
luiscuenca 2019-09-10 18:10:02 -07:00
parent 1f458d195e
commit 2f33e37eb6
No known key found for this signature in database
GPG key ID: 2387ECD129A6961D
4 changed files with 89 additions and 41 deletions

View file

@ -5527,7 +5527,7 @@ void Application::loadSettings() {
// dictated that we should be in first person
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, isFirstPerson);
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !isFirstPerson);
_myCamera.setMode((isFirstPerson) ? CAMERA_MODE_FIRST_PERSON : CAMERA_MODE_THIRD_PERSON);
_myCamera.setMode((isFirstPerson) ? CAMERA_MODE_FIRST_PERSON : CAMERA_MODE_LOOK_AT);
cameraMenuChanged();
auto inputs = pluginManager->getInputPlugins();
@ -5984,7 +5984,7 @@ void Application::cameraModeChanged() {
case CAMERA_MODE_FIRST_PERSON:
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
break;
case CAMERA_MODE_THIRD_PERSON:
case CAMERA_MODE_LOOK_AT:
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
break;
case CAMERA_MODE_MIRROR:
@ -6006,7 +6006,7 @@ void Application::changeViewAsNeeded(float boomLength) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
cameraMenuChanged();
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON && !boomLengthGreaterThanMinimum) {
} else if (_myCamera.getMode() == CAMERA_MODE_LOOK_AT && !boomLengthGreaterThanMinimum) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, false);
cameraMenuChanged();
@ -6028,8 +6028,8 @@ void Application::cameraMenuChanged() {
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN);
}
} else if (menu->isOptionChecked(MenuOption::ThirdPerson)) {
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
if (_myCamera.getMode() != CAMERA_MODE_LOOK_AT) {
_myCamera.setMode(CAMERA_MODE_LOOK_AT);
if (getMyAvatar()->getBoomLength() == MyAvatar::ZOOM_MIN) {
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT);
}

View file

@ -99,6 +99,10 @@ static const QString USER_RECENTER_MODEL_FORCE_STAND = QStringLiteral("ForceStan
static const QString USER_RECENTER_MODEL_AUTO = QStringLiteral("Auto");
static const QString USER_RECENTER_MODEL_DISABLE_HMD_LEAN = QStringLiteral("DisableHMDLean");
const QString HEAD_BLENDING_NAME = "lookAroundAlpha";
const QString HEAD_ALPHA_NAME = "additiveBlendAlpha";
const float HEAD_ALPHA_BLENDING = 1.0f;
MyAvatar::SitStandModelType stringToUserRecenterModel(const QString& str) {
if (str == USER_RECENTER_MODEL_FORCE_SIT) {
return MyAvatar::ForceSit;
@ -936,6 +940,12 @@ 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) {
updateHeadLookAt(deltaTime);
} else if (_headLookAtActive){
resetHeadLookAt();
_headLookAtActive = false;
}
}
// Record avatars movements.
@ -3402,6 +3412,9 @@ void MyAvatar::updateOrientation(float deltaTime) {
glm::quat initialOrientation = getOrientationOutbound();
if (qApp->getCamera().getMode() != CAMERA_MODE_LOOK_AT) {
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
_lookAtCameraTarget = getHead()->getPosition() + getWorldOrientation() * Vectors::FRONT;
_lookAtOffsetYaw = getWorldOrientation();
_lookAtOffsetPitch = Quaternions::IDENTITY;
} else {
// Set look at vector
float pitchIncrement = getDriveKey(PITCH) * _pitchSpeed * deltaTime
@ -3439,12 +3452,12 @@ void MyAvatar::updateOrientation(float deltaTime) {
head->setBasePitch(0.0f);
head->setBaseRoll(0.0f);
// Attenuate head pitch
glm::vec3 cameraVector = (faceForward ? _lookAtOffsetPitch * getWorldOrientation() : getLookAtOffset()) * Vectors::UNIT_Z;
glm::vec3 cameraYawVector = _lookAtOffsetYaw * Vectors::UNIT_Z;
float upDownDirection = glm::dot(cameraVector, Vectors::UNIT_Y);
glm::vec3 cameraVector = (faceForward ? _lookAtOffsetPitch * getWorldOrientation() : getLookAtOffset()) * Vectors::FRONT;
glm::vec3 cameraYawVector = _lookAtOffsetYaw * Vectors::FRONT;
float upDownDirection = glm::dot(cameraVector, Vectors::UP);
float upDownValue = abs(upDownDirection);
const float LOOK_UP_MIN_DOT = 0.25f;
const float LOOK_DOWN_MIN_DOT = 0.75f;
const float LOOK_UP_MIN_DOT = 0.35f;
const float LOOK_DOWN_MIN_DOT = 0.25f;
if (upDownDirection < 0.0f) {
float lookUpAttenuation = upDownValue > LOOK_UP_MIN_DOT ? (upDownValue - LOOK_UP_MIN_DOT) / (1.0f - LOOK_UP_MIN_DOT) : 0.0f;
cameraVector = glm::mix(cameraVector, cameraYawVector, 1.0f - lookUpAttenuation);
@ -3454,8 +3467,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
}
// Calculate the camera target point.
glm::vec3 cameraPos = qApp->getCamera().getPosition();
float distanceTargetFromCamera = 2.0f * glm::length(cameraPos - getWorldPosition());
glm::vec3 targetPoint = qApp->getCamera().getPosition() + distanceTargetFromCamera * cameraVector;
const float targetDistanceFromHead = 2.0f;
glm::vec3 targetPoint = getHead()->getPosition() + targetDistanceFromHead * glm::normalize(cameraVector);
const float LOOKAT_MIX_ALPHA = 0.05f;
const float FPS = 60.0f;
@ -3464,9 +3477,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
float mixAlpha = LOOKAT_MIX_ALPHA * deltaTime * FPS;
mixAlpha = targetSpeed != 0.0f ? mixAlpha * abs(targetSpeed) / _yawSpeed : mixAlpha;
_lookAtCameraTarget = glm::mix(_lookAtCameraTarget, targetPoint, mixAlpha);
// Set the head look at target
QMetaObject::invokeMethod(this, "headLookAt", Q_ARG(const glm::vec3&, _lookAtCameraTarget));
_headLookAtActive = true;
} else {
head->setBaseYaw(0.0f);
head->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime
@ -3538,11 +3549,7 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig
}
} else {
// Desktop mode.
if (qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT) {
direction = (zSpeed * forward) + (xSpeed * right);
} else {
direction = (zSpeed * forward) + (xSpeed * right);
}
auto length = glm::length(direction);
if (length > EPSILON) {
@ -6348,29 +6355,62 @@ void MyAvatar::endSit(const glm::vec3& position, const glm::quat& rotation) {
}
}
void MyAvatar::resetHeadLookAt() {
if (_rigEnabled) {
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLENDING_NAME, glm::vec3(),
HEAD_ALPHA_NAME, HEAD_ALPHA_BLENDING);
}
}
void MyAvatar::updateHeadLookAt(float deltaTime) {
if (_rigEnabled) {
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 headToTargetVector = lookAtTarget - getHead()->getPosition();
if (glm::length(headToTargetVector) > EPSILON) {
headToTargetVector = glm::normalize(headToTargetVector);
}
else {
// The target point is the avatar head
return;
}
float xDot = glm::dot(avatarXVector, headToTargetVector);
float yDot = glm::dot(avatarYVector, headToTargetVector);
bool isLookingUp = yDot >= 0.0f;
float xAngle = acosf(xDot);
float yAngle = acosf(yDot);
// xBlend and yBlend are the values from -1.0 to 1.0 that set the directional blending.
// We compute them using the angles (0 to PI/2) => (1.0 to 0.0) and (PI/2 to PI) => (0.0 to -1.0)
float xBlend = -(xAngle - 0.5f * PI) / (0.5f * PI);
float yBlend = -(yAngle - 0.5f * PI) / (0.5f * PI);
glm::vec3 lookAtBlend = glm::vec3(xBlend, yBlend, 0.0f);
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLENDING_NAME, lookAtBlend,
HEAD_ALPHA_NAME, HEAD_ALPHA_BLENDING);
if (_scriptControlsHeadLookAt) {
_scriptHeadControlSinceUpdate += deltaTime;
if (_scriptHeadControlSinceUpdate > MAX_LOOK_AT_TIME_SCRIPT_CONTROL) {
_scriptHeadControlSinceUpdate = 0.0f;
_scriptControlsHeadLookAt = false;
_lookAtCameraTarget = _lookAtScriptTarget;
}
}
}
}
void MyAvatar::headLookAt(const glm::vec3& lookAtTarget) {
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "headLookAt",
Q_ARG(const glm::vec3&, lookAtTarget));
return;
}
if (_rigEnabled) {
glm::vec3 avatarXVector = getWorldOrientation() * Vectors::UNIT_X;
glm::vec3 avatarYVector = getWorldOrientation() * Vectors::UNIT_Y;
glm::vec3 headToTargetVector = lookAtTarget - getHead()->getPosition();
if (glm::length(headToTargetVector) > EPSILON) {
headToTargetVector = glm::normalize(headToTargetVector);
} else {
// The target point is the avatar head
return;
}
float xOffset = -glm::dot(avatarXVector, headToTargetVector);
float yOffset = -glm::dot(avatarYVector, headToTargetVector);
const QString HEAD_BLENDING_NAME = "lookAroundAlpha";
const QString HEAD_ALPHA_NAME = "additiveBlendAlpha";
const float HEAD_ALPHA_BLENDING = 1.0f;
glm::vec3 lookAtBlend = glm::vec3(xOffset, yOffset, 0.0f);
_skeletonModel->getRig().setDirectionalBlending(HEAD_BLENDING_NAME, lookAtBlend,
HEAD_ALPHA_NAME, HEAD_ALPHA_BLENDING);
}
_headLookAtActive = true;
_scriptControlsHeadLookAt = true;
_scriptHeadControlSinceUpdate = 0.0f;
_lookAtScriptTarget = lookAtTarget;
}

View file

@ -2627,9 +2627,15 @@ private:
glm::vec3 _trackedHeadPosition;
const float MAX_LOOK_AT_TIME_SCRIPT_CONTROL = 2.0f;
glm::quat _lookAtOffsetPitch;
glm::quat _lookAtOffsetYaw;
glm::vec3 _lookAtCameraTarget;
glm::vec3 _lookAtScriptTarget;
bool _headLookAtActive { false };
bool _scriptControlsHeadLookAt { false };
float _scriptHeadControlSinceUpdate { 0.0f };
Setting::Handle<float> _realWorldFieldOfView;
Setting::Handle<bool> _useAdvancedMovementControls;
@ -2655,6 +2661,8 @@ private:
void initHeadBones();
void initAnimGraph();
void initFlowFromFST();
void updateHeadLookAt(float deltaTime);
void resetHeadLookAt();
// Avatar Preferences
QUrl _fullAvatarURLFromPreferences;

View file

@ -183,7 +183,7 @@ private:
void recompose();
void decompose();
CameraMode _mode{ CAMERA_MODE_THIRD_PERSON };
CameraMode _mode{ CAMERA_MODE_LOOK_AT };
glm::mat4 _transform;
glm::mat4 _projection;