mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 14:54:29 +02:00
working on lookat (eye contact)
This commit is contained in:
parent
7117e4a76c
commit
f53b49c496
7 changed files with 193 additions and 162 deletions
|
@ -293,7 +293,9 @@ bool Avatar::getIsNearInteractingOther() {
|
|||
void Avatar::simulate(float deltaTime) {
|
||||
|
||||
//figure out if the mouse cursor is over any body spheres...
|
||||
if (_isMine) {
|
||||
checkForMouseRayTouching();
|
||||
}
|
||||
|
||||
// update balls
|
||||
if (_balls) { _balls->simulate(deltaTime); }
|
||||
|
@ -519,6 +521,9 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
|||
}
|
||||
|
||||
if (_interactingOther) {
|
||||
|
||||
_head.setLookatPosition( _interactingOther->getSpringyHeadPosition());
|
||||
|
||||
_avatarTouch.setYourBodyPosition(_interactingOther->_position);
|
||||
_avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
|
||||
_avatarTouch.setYourHandState (_interactingOther->_handState);
|
||||
|
@ -592,115 +597,6 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::updateHead(float deltaTime) {
|
||||
|
||||
/*
|
||||
// Decay head back to center if turned on
|
||||
if (_isMine && _returnHeadToCenter) {
|
||||
// Decay back toward center
|
||||
_headPitch *= (1.0f - DECAY * _head.returnSpringScale * 2 * deltaTime);
|
||||
_headYaw *= (1.0f - DECAY * _head.returnSpringScale * 2 * deltaTime);
|
||||
_headRoll *= (1.0f - DECAY * _head.returnSpringScale * 2 * deltaTime);
|
||||
}
|
||||
|
||||
// For invensense gyro, decay only slightly when roughly centered
|
||||
if (_isMine) {
|
||||
const float RETURN_RANGE = 15.0;
|
||||
const float RETURN_STRENGTH = 2.0;
|
||||
if (fabs(_headPitch) < RETURN_RANGE) { _headPitch *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
||||
if (fabs(_headYaw) < RETURN_RANGE) { _headYaw *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
||||
if (fabs(_headRoll) < RETURN_RANGE) { _headRoll *= (1.0f - RETURN_STRENGTH * deltaTime); }
|
||||
}
|
||||
|
||||
if (_head.noise) {
|
||||
// Move toward new target
|
||||
_headPitch += (_head.pitchTarget - _headPitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ;
|
||||
_headYaw += (_head.yawTarget - _headYaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime);
|
||||
_headRoll *= 1.f - (DECAY * deltaTime);
|
||||
}
|
||||
|
||||
_head.leanForward *= (1.f - DECAY * 30 * deltaTime);
|
||||
_head.leanSideways *= (1.f - DECAY * 30 * deltaTime);
|
||||
|
||||
// Update where the avatar's eyes are
|
||||
//
|
||||
// First, decide if we are making eye contact or not
|
||||
if (randFloat() < 0.005) {
|
||||
_head.eyeContact = !_head.eyeContact;
|
||||
_head.eyeContact = 1;
|
||||
if (!_head.eyeContact) {
|
||||
// If we just stopped making eye contact,move the eyes markedly away
|
||||
_head.eyeballPitch[0] = _head.eyeballPitch[1] = _head.eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10;
|
||||
_head.eyeballYaw [0] = _head.eyeballYaw [1] = _head.eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5;
|
||||
} else {
|
||||
// If now making eye contact, turn head to look right at viewer
|
||||
SetNewHeadTarget(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
const float DEGREES_BETWEEN_VIEWER_EYES = 3;
|
||||
const float DEGREES_TO_VIEWER_MOUTH = 7;
|
||||
|
||||
if (_head.eyeContact) {
|
||||
// Should we pick a new eye contact target?
|
||||
if (randFloat() < 0.01) {
|
||||
// Choose where to look next
|
||||
if (randFloat() < 0.1) {
|
||||
_head.eyeContactTarget = MOUTH;
|
||||
} else {
|
||||
if (randFloat() < 0.5) _head.eyeContactTarget = LEFT_EYE; else _head.eyeContactTarget = RIGHT_EYE;
|
||||
}
|
||||
}
|
||||
// Set eyeball pitch and yaw to make contact
|
||||
float eye_target_yaw_adjust = 0;
|
||||
float eye_target_pitch_adjust = 0;
|
||||
if (_head.eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES;
|
||||
if (_head.eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES;
|
||||
if (_head.eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH;
|
||||
|
||||
_head.eyeballPitch[0] = _head.eyeballPitch[1] = -_headPitch + eye_target_pitch_adjust;
|
||||
_head.eyeballYaw[0] = _head.eyeballYaw[1] = -_headYaw + eye_target_yaw_adjust;
|
||||
}
|
||||
|
||||
if (_head.noise)
|
||||
{
|
||||
_headPitch += (randFloat() - 0.5) * 0.2 * _head.noiseEnvelope;
|
||||
_headYaw += (randFloat() - 0.5) * 0.3 *_head.noiseEnvelope;
|
||||
//PupilSize += (randFloat() - 0.5) * 0.001*NoiseEnvelope;
|
||||
|
||||
if (randFloat() < 0.005) _head.mouthWidth = MouthWidthChoices[rand()%3];
|
||||
|
||||
if (!_head.eyeContact) {
|
||||
if (randFloat() < 0.01) _head.eyeballPitch[0] = _head.eyeballPitch[1] = (randFloat() - 0.5) * 20;
|
||||
if (randFloat() < 0.01) _head.eyeballYaw[0] = _head.eyeballYaw[1] = (randFloat()- 0.5) * 10;
|
||||
}
|
||||
|
||||
if ((randFloat() < 0.005) && (fabs(_head.pitchTarget - _headPitch) < 1.0) && (fabs(_head.yawTarget - _headYaw) < 1.0)) {
|
||||
SetNewHeadTarget((randFloat()-0.5) * 20.0, (randFloat()-0.5) * 45.0);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
|
||||
// Pick new target
|
||||
_head.pitchTarget = (randFloat() - 0.5) * 45;
|
||||
_head.yawTarget = (randFloat() - 0.5) * 22;
|
||||
}
|
||||
if (randFloat() < 0.01)
|
||||
{
|
||||
_head.eyebrowPitch[0] = _head.eyebrowPitch[1] = BrowPitchAngle[rand()%3];
|
||||
_head.eyebrowRoll [0] = _head.eyebrowRoll[1] = BrowRollAngle[rand()%5];
|
||||
_head.eyebrowRoll [1] *=-1;
|
||||
}
|
||||
}
|
||||
|
||||
// Update audio trailing average for rendering facial animations
|
||||
const float AUDIO_AVERAGING_SECS = 0.05;
|
||||
_head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness +
|
||||
(deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
float Avatar::getHeight() {
|
||||
return _height;
|
||||
}
|
||||
|
|
|
@ -195,9 +195,6 @@ private:
|
|||
glm::vec3 _mouseRayDirection;
|
||||
glm::vec3 _cameraPosition;
|
||||
|
||||
//AvatarJointID _jointTouched;
|
||||
|
||||
|
||||
// private methods...
|
||||
void initializeSkeleton();
|
||||
void updateSkeleton();
|
||||
|
@ -205,7 +202,6 @@ private:
|
|||
void updateBodySprings( float deltaTime );
|
||||
void calculateBoneLengths();
|
||||
void readSensors();
|
||||
void updateHead( float deltaTime );
|
||||
void updateHandMovementAndTouching(float deltaTime);
|
||||
void updateAvatarCollisions(float deltaTime);
|
||||
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#include "Head.h"
|
||||
#include "Util.h"
|
||||
#include <vector>
|
||||
#include <SharedUtil.h>
|
||||
#include <lodepng.h>
|
||||
|
@ -15,6 +16,8 @@ using namespace std;
|
|||
|
||||
const float HEAD_MOTION_DECAY = 0.1;
|
||||
|
||||
const bool TESTING_LOOKAT = false;
|
||||
|
||||
|
||||
float _browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
||||
float _mouthColor[] = {1, 0, 0};
|
||||
|
@ -49,6 +52,7 @@ void Head::initialize() {
|
|||
audioLoudness = 0.0;
|
||||
skinColor = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
lookatPosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
yaw = 0.0f;
|
||||
pitch = 0.0f;
|
||||
roll = 0.0f;
|
||||
|
@ -219,11 +223,21 @@ void Head::simulate(float deltaTime, bool isMine) {
|
|||
const float AUDIO_AVERAGING_SECS = 0.05;
|
||||
averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * averageLoudness +
|
||||
(deltaTime / AUDIO_AVERAGING_SECS) * audioLoudness;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Head::setLookatPosition(glm::vec3 l) {
|
||||
lookatPosition = l;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Head::render(bool lookingInMirror, float bodyYaw) {
|
||||
|
||||
|
||||
//float a = angleBetween( &position, &position);
|
||||
|
||||
int side = 0;
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
@ -306,8 +320,21 @@ void Head::render(bool lookingInMirror, float bodyYaw) {
|
|||
glutSolidCube(0.5);
|
||||
glPopMatrix();
|
||||
|
||||
glTranslatef(0, 1.0, 0);
|
||||
renderEyeBalls();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
if (TESTING_LOOKAT) {
|
||||
//the irises are special - they have the ability to look at specific targets in the world (code still not finished yet)
|
||||
renderIrises(bodyYaw + yaw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Head::renderEyeBalls() {
|
||||
|
||||
glTranslatef(0, 1.0, 0);
|
||||
|
||||
glTranslatef(-interPupilDistance/2.0,-0.68,0.7);
|
||||
// Right Eye
|
||||
|
@ -322,6 +349,7 @@ void Head::render(bool lookingInMirror, float bodyYaw) {
|
|||
}
|
||||
glPopMatrix();
|
||||
|
||||
if (!TESTING_LOOKAT) {
|
||||
// Right Pupil
|
||||
if (sphere == NULL) {
|
||||
sphere = gluNewQuadric();
|
||||
|
@ -344,8 +372,10 @@ void Head::render(bool lookingInMirror, float bodyYaw) {
|
|||
gluSphere(sphere, pupilSize, 15, 15);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
// Left Eye
|
||||
glColor3fv(_eyeColor);
|
||||
glTranslatef(interPupilDistance, 0, 0);
|
||||
|
@ -357,6 +387,8 @@ void Head::render(bool lookingInMirror, float bodyYaw) {
|
|||
glutSolidSphere(0.25, 30, 30);
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
if (!TESTING_LOOKAT) {
|
||||
// Left Pupil
|
||||
glPushMatrix();
|
||||
{
|
||||
|
@ -371,7 +403,95 @@ void Head::render(bool lookingInMirror, float bodyYaw) {
|
|||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// the code below is still in the prototyping stages....
|
||||
//---------------------------------------------------------
|
||||
void Head::renderIrises(float yaw) {
|
||||
Orientation orientation;
|
||||
orientation.setToPitchYawRoll( pitch, yaw, roll);
|
||||
|
||||
// Render lines originating from the eyes and converging on the lookatPosition
|
||||
float rightShift = scale * 0.22f;
|
||||
float upShift = scale * 0.38f;
|
||||
float frontShift = scale * 0.9f;
|
||||
|
||||
glm::vec3 leftEyePosition = position + orientation.getRight() * rightShift
|
||||
+ orientation.getUp () * upShift
|
||||
+ orientation.getFront() * frontShift;
|
||||
glm::vec3 rightEyePosition = position - orientation.getRight() * rightShift
|
||||
+ orientation.getUp () * upShift
|
||||
+ orientation.getFront() * frontShift;
|
||||
|
||||
debugRenderLookatVectors(leftEyePosition, rightEyePosition, lookatPosition);
|
||||
|
||||
glColor3fv(_eyeColor);
|
||||
|
||||
if (sphere == NULL) {
|
||||
sphere = gluNewQuadric();
|
||||
gluQuadricTexture(sphere, GL_TRUE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
gluQuadricOrientation(sphere, GLU_OUTSIDE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]);
|
||||
}
|
||||
|
||||
//render left iris
|
||||
glPushMatrix();
|
||||
{
|
||||
glTranslatef(leftEyePosition.x, leftEyePosition.y, leftEyePosition.z);
|
||||
glm::vec3 targetLookatAxis = glm::normalize(lookatPosition - leftEyePosition);
|
||||
|
||||
glPushMatrix();
|
||||
glm::vec3 pitchRotationAxis = glm::cross(targetLookatAxis, orientation.getRight());
|
||||
glm::vec3 yawRotationAxis = glm::cross(targetLookatAxis, orientation.getUp());
|
||||
|
||||
glRotatef(90.0f, yawRotationAxis.x, yawRotationAxis.y, yawRotationAxis.z);
|
||||
glRotatef(90.0f, pitchRotationAxis.x, pitchRotationAxis.y, pitchRotationAxis.z);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
gluSphere(sphere, 0.01, 15, 15);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glPopMatrix();
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
//render right iris
|
||||
glPushMatrix();
|
||||
{
|
||||
glTranslatef(rightEyePosition.x, rightEyePosition.y, rightEyePosition.z);
|
||||
glm::vec3 targetLookatAxis = glm::normalize(lookatPosition - rightEyePosition);
|
||||
|
||||
glPushMatrix();
|
||||
glm::vec3 pitchRotationAxis = glm::cross(targetLookatAxis, orientation.getRight());
|
||||
glm::vec3 yawRotationAxis = glm::cross(targetLookatAxis, orientation.getUp());
|
||||
|
||||
glRotatef(90.0f, yawRotationAxis.x, yawRotationAxis.y, yawRotationAxis.z);
|
||||
glRotatef(90.0f, pitchRotationAxis.x, pitchRotationAxis.y, pitchRotationAxis.z);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
gluSphere(sphere, 0.01, 15, 15);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glPopMatrix();
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void Head::debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
||||
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glLineWidth(3.0);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(leftEyePosition.x, leftEyePosition.y, leftEyePosition.z);
|
||||
glVertex3f(lookatPosition.x, lookatPosition.y, lookatPosition.z);
|
||||
glEnd();
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(rightEyePosition.x, rightEyePosition.y, rightEyePosition.z);
|
||||
glVertex3f(lookatPosition.x, lookatPosition.y, lookatPosition.z);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "SerialInterface.h"
|
||||
#include "Orientation.h"
|
||||
|
||||
enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
||||
|
||||
|
@ -30,6 +31,7 @@ public:
|
|||
void render(bool lookingInMirror, float bodyYaw);
|
||||
void setNewTarget(float, float);
|
||||
void setSpringScale(float s) { returnSpringScale = s; }
|
||||
void setLookatPosition(glm::vec3 lookatPosition);
|
||||
|
||||
// Do you want head to try to return to center (depends on interface detected)
|
||||
void setReturnToCenter(bool r) { returnHeadToCenter = r; }
|
||||
|
@ -43,6 +45,7 @@ public:
|
|||
glm::vec3 skinColor;
|
||||
glm::vec3 position;
|
||||
glm::vec3 rotation;
|
||||
glm::vec3 lookatPosition;
|
||||
float yaw;
|
||||
float pitch;
|
||||
float roll;
|
||||
|
@ -85,6 +88,12 @@ public:
|
|||
|
||||
// Strength of return springs
|
||||
float returnSpringScale;
|
||||
|
||||
private:
|
||||
void renderEyeBalls();
|
||||
void renderIrises(float yaw);
|
||||
void debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1059,6 +1059,7 @@ void display(void)
|
|||
myCamera.setTargetRotation(myAvatar.getBodyYaw() + myAvatar.getHeadYaw(), -myAvatar.getHeadPitch(), myAvatar.getHeadRoll());
|
||||
|
||||
} else if (myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
myCamera.setTightness (100.0f);
|
||||
myCamera.setTargetPosition(myAvatar.getSpringyHeadPosition());
|
||||
myCamera.setTargetRotation(myAvatar.getBodyYaw() - 180.0f, 0.0f, 0.0f);
|
||||
|
||||
|
@ -1086,7 +1087,6 @@ void display(void)
|
|||
glPopMatrix();
|
||||
*/
|
||||
|
||||
|
||||
// Note: whichCamera is used to pick between the normal camera myCamera for our
|
||||
// main camera, vs, an alternate camera. The alternate camera we support right now
|
||||
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
||||
|
|
|
@ -25,6 +25,15 @@ void Orientation::setToIdentity() {
|
|||
front = glm::vec3(IDENTITY_FRONT);
|
||||
}
|
||||
|
||||
void Orientation::setToPitchYawRoll(float p, float y, float r) {
|
||||
|
||||
setToIdentity();
|
||||
pitch(p);
|
||||
yaw (y);
|
||||
roll (r);
|
||||
}
|
||||
|
||||
|
||||
void Orientation::set(Orientation o) {
|
||||
|
||||
quat = o.quat;
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
Orientation();
|
||||
|
||||
void set(Orientation);
|
||||
void setToPitchYawRoll(float p, float y, float r);
|
||||
void setToIdentity();
|
||||
|
||||
void pitch(float p);
|
||||
|
|
Loading…
Reference in a new issue