Merge pull request from hyperlogic/feature/improve-eye-look-at-interest-calculation

Update eye look at interest calculation
This commit is contained in:
Shannon Romano 2019-01-04 09:16:53 -08:00 committed by GitHub
commit bdac7fe298
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 32 deletions
interface/src/avatar
libraries/avatars-renderer/src/avatars-renderer

View file

@ -1531,35 +1531,74 @@ ScriptAvatarData* MyAvatar::getTargetAvatar() const {
}
}
void MyAvatar::updateLookAtTargetAvatar() {
//
// Look at the avatar whose eyes are closest to the ray in direction of my avatar's head
// And set the correctedLookAt for all (nearby) avatars that are looking at me.
_lookAtTargetAvatar.reset();
_targetAvatarPosition = glm::vec3(0.0f);
static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myPosition, const glm::vec3& otherForward, const glm::vec3& otherPosition,
bool otherIsTalking, bool lookingAtOtherAlready) {
const float DISTANCE_FACTOR = 3.14f;
const float MY_ANGLE_FACTOR = 1.0f;
const float OTHER_ANGLE_FACTOR = 1.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;
glm::vec3 cameraPosition = qApp->getCamera().getPosition();
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; // meters
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;
const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f;
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f;
glm::vec3 d = otherPosition - myPosition;
float distance = glm::length(d);
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) {
auto avatar = static_pointer_cast<Avatar>(avatarPointer);
bool isCurrentTarget = avatar->getIsLookAtTarget();
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
avatar->setIsLookAtTarget(false);
if (!avatar->isMyAvatar() && avatar->isInitialized() &&
(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);
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
_lookAtTargetAvatar = avatarPointer;
_targetAvatarPosition = avatarPointer->getWorldPosition();
void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) {
glm::vec3 myForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD;
glm::vec3 myPosition = getHead()->getEyePosition();
CameraMode mode = qApp->getCamera().getMode();
if (mode == CAMERA_MODE_FIRST_PERSON) {
myPosition = qApp->getCamera().getPosition();
}
float bestCost = FLT_MAX;
std::shared_ptr<Avatar> bestAvatar;
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)) {
// 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();
}
}
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() {

View file

@ -832,6 +832,8 @@ public:
AvatarWeakPointer getLookAtTargetAvatar() const { return _lookAtTargetAvatar; }
void updateLookAtTargetAvatar();
void computeMyLookAtTarget(const AvatarHash& hash);
void snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash);
void clearLookAtTargetAvatar();
virtual void setJointRotations(const QVector<glm::quat>& jointRotations) override;

View file

@ -156,9 +156,6 @@ public:
virtual void postUpdate(float deltaTime, const render::ScenePointer& scene);
//setters
void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; }
bool getIsLookAtTarget() const { return _isLookAtTarget; }
//getters
bool isInitialized() const { return _initialized; }
SkeletonModelPointer getSkeletonModel() { return _skeletonModel; }
@ -595,7 +592,6 @@ protected:
int _rightPointerGeometryID { 0 };
int _nameRectGeometryID { 0 };
bool _initialized { false };
bool _isLookAtTarget { false };
bool _isAnimatingScale { false };
bool _mustFadeIn { false };
bool _isFading { false };