mirror of
https://github.com/overte-org/overte.git
synced 2025-04-29 23:22:44 +02:00
Angles instead dot product and fix API
This commit is contained in:
parent
1f458d195e
commit
2f33e37eb6
4 changed files with 89 additions and 41 deletions
|
@ -5527,7 +5527,7 @@ void Application::loadSettings() {
|
||||||
// dictated that we should be in first person
|
// dictated that we should be in first person
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, isFirstPerson);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, isFirstPerson);
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !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();
|
cameraMenuChanged();
|
||||||
|
|
||||||
auto inputs = pluginManager->getInputPlugins();
|
auto inputs = pluginManager->getInputPlugins();
|
||||||
|
@ -5984,7 +5984,7 @@ void Application::cameraModeChanged() {
|
||||||
case CAMERA_MODE_FIRST_PERSON:
|
case CAMERA_MODE_FIRST_PERSON:
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
|
||||||
break;
|
break;
|
||||||
case CAMERA_MODE_THIRD_PERSON:
|
case CAMERA_MODE_LOOK_AT:
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
|
||||||
break;
|
break;
|
||||||
case CAMERA_MODE_MIRROR:
|
case CAMERA_MODE_MIRROR:
|
||||||
|
@ -6006,7 +6006,7 @@ void Application::changeViewAsNeeded(float boomLength) {
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
|
||||||
cameraMenuChanged();
|
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::FirstPerson, true);
|
||||||
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, false);
|
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, false);
|
||||||
cameraMenuChanged();
|
cameraMenuChanged();
|
||||||
|
@ -6028,8 +6028,8 @@ void Application::cameraMenuChanged() {
|
||||||
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN);
|
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN);
|
||||||
}
|
}
|
||||||
} else if (menu->isOptionChecked(MenuOption::ThirdPerson)) {
|
} else if (menu->isOptionChecked(MenuOption::ThirdPerson)) {
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
|
if (_myCamera.getMode() != CAMERA_MODE_LOOK_AT) {
|
||||||
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
_myCamera.setMode(CAMERA_MODE_LOOK_AT);
|
||||||
if (getMyAvatar()->getBoomLength() == MyAvatar::ZOOM_MIN) {
|
if (getMyAvatar()->getBoomLength() == MyAvatar::ZOOM_MIN) {
|
||||||
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT);
|
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_AUTO = QStringLiteral("Auto");
|
||||||
static const QString USER_RECENTER_MODEL_DISABLE_HMD_LEAN = QStringLiteral("DisableHMDLean");
|
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) {
|
MyAvatar::SitStandModelType stringToUserRecenterModel(const QString& str) {
|
||||||
if (str == USER_RECENTER_MODEL_FORCE_SIT) {
|
if (str == USER_RECENTER_MODEL_FORCE_SIT) {
|
||||||
return MyAvatar::ForceSit;
|
return MyAvatar::ForceSit;
|
||||||
|
@ -936,6 +940,12 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
||||||
head->setPosition(headPosition);
|
head->setPosition(headPosition);
|
||||||
head->setScale(getModelScale());
|
head->setScale(getModelScale());
|
||||||
head->simulate(deltaTime);
|
head->simulate(deltaTime);
|
||||||
|
if (_scriptControlsHeadLookAt || qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT) {
|
||||||
|
updateHeadLookAt(deltaTime);
|
||||||
|
} else if (_headLookAtActive){
|
||||||
|
resetHeadLookAt();
|
||||||
|
_headLookAtActive = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record avatars movements.
|
// Record avatars movements.
|
||||||
|
@ -3402,6 +3412,9 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
glm::quat initialOrientation = getOrientationOutbound();
|
glm::quat initialOrientation = getOrientationOutbound();
|
||||||
if (qApp->getCamera().getMode() != CAMERA_MODE_LOOK_AT) {
|
if (qApp->getCamera().getMode() != CAMERA_MODE_LOOK_AT) {
|
||||||
setWorldOrientation(getWorldOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
|
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 {
|
} else {
|
||||||
// Set look at vector
|
// Set look at vector
|
||||||
float pitchIncrement = getDriveKey(PITCH) * _pitchSpeed * deltaTime
|
float pitchIncrement = getDriveKey(PITCH) * _pitchSpeed * deltaTime
|
||||||
|
@ -3439,12 +3452,12 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
head->setBasePitch(0.0f);
|
head->setBasePitch(0.0f);
|
||||||
head->setBaseRoll(0.0f);
|
head->setBaseRoll(0.0f);
|
||||||
// Attenuate head pitch
|
// Attenuate head pitch
|
||||||
glm::vec3 cameraVector = (faceForward ? _lookAtOffsetPitch * getWorldOrientation() : getLookAtOffset()) * Vectors::UNIT_Z;
|
glm::vec3 cameraVector = (faceForward ? _lookAtOffsetPitch * getWorldOrientation() : getLookAtOffset()) * Vectors::FRONT;
|
||||||
glm::vec3 cameraYawVector = _lookAtOffsetYaw * Vectors::UNIT_Z;
|
glm::vec3 cameraYawVector = _lookAtOffsetYaw * Vectors::FRONT;
|
||||||
float upDownDirection = glm::dot(cameraVector, Vectors::UNIT_Y);
|
float upDownDirection = glm::dot(cameraVector, Vectors::UP);
|
||||||
float upDownValue = abs(upDownDirection);
|
float upDownValue = abs(upDownDirection);
|
||||||
const float LOOK_UP_MIN_DOT = 0.25f;
|
const float LOOK_UP_MIN_DOT = 0.35f;
|
||||||
const float LOOK_DOWN_MIN_DOT = 0.75f;
|
const float LOOK_DOWN_MIN_DOT = 0.25f;
|
||||||
if (upDownDirection < 0.0f) {
|
if (upDownDirection < 0.0f) {
|
||||||
float lookUpAttenuation = upDownValue > LOOK_UP_MIN_DOT ? (upDownValue - LOOK_UP_MIN_DOT) / (1.0f - LOOK_UP_MIN_DOT) : 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);
|
cameraVector = glm::mix(cameraVector, cameraYawVector, 1.0f - lookUpAttenuation);
|
||||||
|
@ -3454,8 +3467,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
}
|
}
|
||||||
// Calculate the camera target point.
|
// Calculate the camera target point.
|
||||||
glm::vec3 cameraPos = qApp->getCamera().getPosition();
|
glm::vec3 cameraPos = qApp->getCamera().getPosition();
|
||||||
float distanceTargetFromCamera = 2.0f * glm::length(cameraPos - getWorldPosition());
|
const float targetDistanceFromHead = 2.0f;
|
||||||
glm::vec3 targetPoint = qApp->getCamera().getPosition() + distanceTargetFromCamera * cameraVector;
|
glm::vec3 targetPoint = getHead()->getPosition() + targetDistanceFromHead * glm::normalize(cameraVector);
|
||||||
|
|
||||||
const float LOOKAT_MIX_ALPHA = 0.05f;
|
const float LOOKAT_MIX_ALPHA = 0.05f;
|
||||||
const float FPS = 60.0f;
|
const float FPS = 60.0f;
|
||||||
|
@ -3464,9 +3477,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
float mixAlpha = LOOKAT_MIX_ALPHA * deltaTime * FPS;
|
float mixAlpha = LOOKAT_MIX_ALPHA * deltaTime * FPS;
|
||||||
mixAlpha = targetSpeed != 0.0f ? mixAlpha * abs(targetSpeed) / _yawSpeed : mixAlpha;
|
mixAlpha = targetSpeed != 0.0f ? mixAlpha * abs(targetSpeed) / _yawSpeed : mixAlpha;
|
||||||
_lookAtCameraTarget = glm::mix(_lookAtCameraTarget, targetPoint, mixAlpha);
|
_lookAtCameraTarget = glm::mix(_lookAtCameraTarget, targetPoint, mixAlpha);
|
||||||
|
_headLookAtActive = true;
|
||||||
// Set the head look at target
|
|
||||||
QMetaObject::invokeMethod(this, "headLookAt", Q_ARG(const glm::vec3&, _lookAtCameraTarget));
|
|
||||||
} else {
|
} else {
|
||||||
head->setBaseYaw(0.0f);
|
head->setBaseYaw(0.0f);
|
||||||
head->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime
|
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 {
|
} else {
|
||||||
// Desktop mode.
|
// Desktop mode.
|
||||||
if (qApp->getCamera().getMode() == CAMERA_MODE_LOOK_AT) {
|
direction = (zSpeed * forward) + (xSpeed * right);
|
||||||
direction = (zSpeed * forward) + (xSpeed * right);
|
|
||||||
} else {
|
|
||||||
direction = (zSpeed * forward) + (xSpeed * right);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto length = glm::length(direction);
|
auto length = glm::length(direction);
|
||||||
if (length > EPSILON) {
|
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) {
|
void MyAvatar::headLookAt(const glm::vec3& lookAtTarget) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
BLOCKING_INVOKE_METHOD(this, "headLookAt",
|
BLOCKING_INVOKE_METHOD(this, "headLookAt",
|
||||||
Q_ARG(const glm::vec3&, lookAtTarget));
|
Q_ARG(const glm::vec3&, lookAtTarget));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_rigEnabled) {
|
_headLookAtActive = true;
|
||||||
glm::vec3 avatarXVector = getWorldOrientation() * Vectors::UNIT_X;
|
_scriptControlsHeadLookAt = true;
|
||||||
glm::vec3 avatarYVector = getWorldOrientation() * Vectors::UNIT_Y;
|
_scriptHeadControlSinceUpdate = 0.0f;
|
||||||
glm::vec3 headToTargetVector = lookAtTarget - getHead()->getPosition();
|
_lookAtScriptTarget = lookAtTarget;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -2627,9 +2627,15 @@ private:
|
||||||
|
|
||||||
glm::vec3 _trackedHeadPosition;
|
glm::vec3 _trackedHeadPosition;
|
||||||
|
|
||||||
|
const float MAX_LOOK_AT_TIME_SCRIPT_CONTROL = 2.0f;
|
||||||
glm::quat _lookAtOffsetPitch;
|
glm::quat _lookAtOffsetPitch;
|
||||||
glm::quat _lookAtOffsetYaw;
|
glm::quat _lookAtOffsetYaw;
|
||||||
glm::vec3 _lookAtCameraTarget;
|
glm::vec3 _lookAtCameraTarget;
|
||||||
|
glm::vec3 _lookAtScriptTarget;
|
||||||
|
bool _headLookAtActive { false };
|
||||||
|
bool _scriptControlsHeadLookAt { false };
|
||||||
|
float _scriptHeadControlSinceUpdate { 0.0f };
|
||||||
|
|
||||||
|
|
||||||
Setting::Handle<float> _realWorldFieldOfView;
|
Setting::Handle<float> _realWorldFieldOfView;
|
||||||
Setting::Handle<bool> _useAdvancedMovementControls;
|
Setting::Handle<bool> _useAdvancedMovementControls;
|
||||||
|
@ -2655,6 +2661,8 @@ private:
|
||||||
void initHeadBones();
|
void initHeadBones();
|
||||||
void initAnimGraph();
|
void initAnimGraph();
|
||||||
void initFlowFromFST();
|
void initFlowFromFST();
|
||||||
|
void updateHeadLookAt(float deltaTime);
|
||||||
|
void resetHeadLookAt();
|
||||||
|
|
||||||
// Avatar Preferences
|
// Avatar Preferences
|
||||||
QUrl _fullAvatarURLFromPreferences;
|
QUrl _fullAvatarURLFromPreferences;
|
||||||
|
|
|
@ -183,7 +183,7 @@ private:
|
||||||
void recompose();
|
void recompose();
|
||||||
void decompose();
|
void decompose();
|
||||||
|
|
||||||
CameraMode _mode{ CAMERA_MODE_THIRD_PERSON };
|
CameraMode _mode{ CAMERA_MODE_LOOK_AT };
|
||||||
glm::mat4 _transform;
|
glm::mat4 _transform;
|
||||||
glm::mat4 _projection;
|
glm::mat4 _projection;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue