mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 04:57:58 +02:00
Merge pull request #14647 from hyperlogic/feature/improve-eye-look-at-interest-calculation
Update eye look at interest calculation
This commit is contained in:
commit
bdac7fe298
3 changed files with 78 additions and 32 deletions
|
@ -1531,35 +1531,74 @@ ScriptAvatarData* MyAvatar::getTargetAvatar() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::updateLookAtTargetAvatar() {
|
static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myPosition, const glm::vec3& otherForward, const glm::vec3& otherPosition,
|
||||||
//
|
bool otherIsTalking, bool lookingAtOtherAlready) {
|
||||||
// Look at the avatar whose eyes are closest to the ray in direction of my avatar's head
|
const float DISTANCE_FACTOR = 3.14f;
|
||||||
// And set the correctedLookAt for all (nearby) avatars that are looking at me.
|
const float MY_ANGLE_FACTOR = 1.0f;
|
||||||
_lookAtTargetAvatar.reset();
|
const float OTHER_ANGLE_FACTOR = 1.0f;
|
||||||
_targetAvatarPosition = glm::vec3(0.0f);
|
const float OTHER_IS_TALKING_TERM = otherIsTalking ? 1.0f : 0.0f;
|
||||||
|
const float LOOKING_AT_OTHER_ALREADY_TERM = lookingAtOtherAlready ? -0.2f : 0.0f;
|
||||||
|
|
||||||
glm::vec3 lookForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD;
|
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; // meters
|
||||||
glm::vec3 cameraPosition = qApp->getCamera().getPosition();
|
const float MAX_MY_ANGLE = PI / 8.0f; // 22.5 degrees, Don't look too far away from the head facing.
|
||||||
|
const float MAX_OTHER_ANGLE = (3.0f * PI) / 4.0f; // 135 degrees, Don't stare at the back of another avatars head.
|
||||||
|
|
||||||
float smallestAngleTo = glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES) / 2.0f;
|
glm::vec3 d = otherPosition - myPosition;
|
||||||
const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f;
|
float distance = glm::length(d);
|
||||||
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f;
|
glm::vec3 dUnit = d / distance;
|
||||||
|
float myAngle = acosf(glm::dot(myForward, dUnit));
|
||||||
|
float otherAngle = acosf(glm::dot(otherForward, -dUnit));
|
||||||
|
|
||||||
AvatarHash hash = DependencyManager::get<AvatarManager>()->getHashCopy();
|
if (distance > GREATEST_LOOKING_AT_DISTANCE || myAngle > MAX_MY_ANGLE || otherAngle > MAX_OTHER_ANGLE) {
|
||||||
|
return FLT_MAX;
|
||||||
|
} else {
|
||||||
|
return (DISTANCE_FACTOR * distance +
|
||||||
|
MY_ANGLE_FACTOR * myAngle +
|
||||||
|
OTHER_ANGLE_FACTOR * otherAngle +
|
||||||
|
OTHER_IS_TALKING_TERM +
|
||||||
|
LOOKING_AT_OTHER_ALREADY_TERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (const AvatarSharedPointer& avatarPointer, hash) {
|
void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) {
|
||||||
auto avatar = static_pointer_cast<Avatar>(avatarPointer);
|
glm::vec3 myForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD;
|
||||||
bool isCurrentTarget = avatar->getIsLookAtTarget();
|
glm::vec3 myPosition = getHead()->getEyePosition();
|
||||||
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
CameraMode mode = qApp->getCamera().getMode();
|
||||||
avatar->setIsLookAtTarget(false);
|
if (mode == CAMERA_MODE_FIRST_PERSON) {
|
||||||
if (!avatar->isMyAvatar() && avatar->isInitialized() &&
|
myPosition = qApp->getCamera().getPosition();
|
||||||
(distanceTo < GREATEST_LOOKING_AT_DISTANCE * getModelScale())) {
|
}
|
||||||
float radius = glm::length(avatar->getHead()->getEyePosition() - avatar->getHead()->getRightEyePosition());
|
|
||||||
float angleTo = coneSphereAngle(getHead()->getEyePosition(), lookForward, avatar->getHead()->getEyePosition(), radius);
|
float bestCost = FLT_MAX;
|
||||||
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
|
std::shared_ptr<Avatar> bestAvatar;
|
||||||
_lookAtTargetAvatar = avatarPointer;
|
|
||||||
_targetAvatarPosition = avatarPointer->getWorldPosition();
|
foreach (const AvatarSharedPointer& avatarData, hash) {
|
||||||
|
std::shared_ptr<Avatar> avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||||
|
if (!avatar->isMyAvatar() && avatar->isInitialized()) {
|
||||||
|
glm::vec3 otherForward = avatar->getHead()->getForwardDirection();
|
||||||
|
glm::vec3 otherPosition = avatar->getHead()->getEyePosition();
|
||||||
|
const float TIME_WITHOUT_TALKING_THRESHOLD = 1.0f;
|
||||||
|
bool otherIsTalking = avatar->getHead()->getTimeWithoutTalking() <= TIME_WITHOUT_TALKING_THRESHOLD;
|
||||||
|
bool lookingAtOtherAlready = _lookAtTargetAvatar.lock().get() == avatar.get();
|
||||||
|
float cost = lookAtCostFunction(myForward, myPosition, otherForward, otherPosition, otherIsTalking, lookingAtOtherAlready);
|
||||||
|
if (cost < bestCost) {
|
||||||
|
bestCost = cost;
|
||||||
|
bestAvatar = avatar;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestAvatar) {
|
||||||
|
_lookAtTargetAvatar = bestAvatar;
|
||||||
|
_targetAvatarPosition = bestAvatar->getWorldPosition();
|
||||||
|
} else {
|
||||||
|
_lookAtTargetAvatar.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash) {
|
||||||
|
foreach (const AvatarSharedPointer& avatarData, hash) {
|
||||||
|
std::shared_ptr<Avatar> avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||||
|
if (!avatar->isMyAvatar() && avatar->isInitialized()) {
|
||||||
if (_lookAtSnappingEnabled && avatar->getLookAtSnappingEnabled() && isLookingAtMe(avatar)) {
|
if (_lookAtSnappingEnabled && avatar->getLookAtSnappingEnabled() && isLookingAtMe(avatar)) {
|
||||||
|
|
||||||
// Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face.
|
// Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face.
|
||||||
|
@ -1614,10 +1653,19 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
||||||
avatar->getHead()->clearCorrectedLookAtPosition();
|
avatar->getHead()->clearCorrectedLookAtPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto avatarPointer = _lookAtTargetAvatar.lock();
|
}
|
||||||
if (avatarPointer) {
|
|
||||||
static_pointer_cast<Avatar>(avatarPointer)->setIsLookAtTarget(true);
|
void MyAvatar::updateLookAtTargetAvatar() {
|
||||||
}
|
|
||||||
|
// The AvatarManager is a mutable class shared by many threads. We make a thread-safe deep copy of it,
|
||||||
|
// to avoid having to hold a lock while we iterate over all the avatars within.
|
||||||
|
AvatarHash hash = DependencyManager::get<AvatarManager>()->getHashCopy();
|
||||||
|
|
||||||
|
// determine what the best look at target for my avatar should be.
|
||||||
|
computeMyLookAtTarget(hash);
|
||||||
|
|
||||||
|
// snap look at position for avatars that are looking at me.
|
||||||
|
snapOtherAvatarLookAtTargetsToMe(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::clearLookAtTargetAvatar() {
|
void MyAvatar::clearLookAtTargetAvatar() {
|
||||||
|
|
|
@ -832,6 +832,8 @@ public:
|
||||||
|
|
||||||
AvatarWeakPointer getLookAtTargetAvatar() const { return _lookAtTargetAvatar; }
|
AvatarWeakPointer getLookAtTargetAvatar() const { return _lookAtTargetAvatar; }
|
||||||
void updateLookAtTargetAvatar();
|
void updateLookAtTargetAvatar();
|
||||||
|
void computeMyLookAtTarget(const AvatarHash& hash);
|
||||||
|
void snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash);
|
||||||
void clearLookAtTargetAvatar();
|
void clearLookAtTargetAvatar();
|
||||||
|
|
||||||
virtual void setJointRotations(const QVector<glm::quat>& jointRotations) override;
|
virtual void setJointRotations(const QVector<glm::quat>& jointRotations) override;
|
||||||
|
|
|
@ -156,9 +156,6 @@ public:
|
||||||
|
|
||||||
virtual void postUpdate(float deltaTime, const render::ScenePointer& scene);
|
virtual void postUpdate(float deltaTime, const render::ScenePointer& scene);
|
||||||
|
|
||||||
//setters
|
|
||||||
void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; }
|
|
||||||
bool getIsLookAtTarget() const { return _isLookAtTarget; }
|
|
||||||
//getters
|
//getters
|
||||||
bool isInitialized() const { return _initialized; }
|
bool isInitialized() const { return _initialized; }
|
||||||
SkeletonModelPointer getSkeletonModel() { return _skeletonModel; }
|
SkeletonModelPointer getSkeletonModel() { return _skeletonModel; }
|
||||||
|
@ -595,7 +592,6 @@ protected:
|
||||||
int _rightPointerGeometryID { 0 };
|
int _rightPointerGeometryID { 0 };
|
||||||
int _nameRectGeometryID { 0 };
|
int _nameRectGeometryID { 0 };
|
||||||
bool _initialized { false };
|
bool _initialized { false };
|
||||||
bool _isLookAtTarget { false };
|
|
||||||
bool _isAnimatingScale { false };
|
bool _isAnimatingScale { false };
|
||||||
bool _mustFadeIn { false };
|
bool _mustFadeIn { false };
|
||||||
bool _isFading { false };
|
bool _isFading { false };
|
||||||
|
|
Loading…
Reference in a new issue