mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 17:00:13 +02:00
Merge pull request #466 from ey6es/reorient
Avatar orientation conversion: use quaternions rather than Orientation class, generalize rotations so that avatars can be reoriented based on gravity.
This commit is contained in:
commit
6712c40073
13 changed files with 448 additions and 380 deletions
|
@ -288,33 +288,22 @@ void Application::paintGL() {
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||||
_myCamera.setTightness (100.0f);
|
_myCamera.setTightness (100.0f);
|
||||||
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
||||||
_myCamera.setTargetRotation(_myAvatar.getBodyYaw() - 180.0f,
|
_myCamera.setTargetRotation(_myAvatar.getHead().getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f)));
|
||||||
0.0f,
|
|
||||||
0.0f);
|
|
||||||
} else if (OculusManager::isConnected()) {
|
} else if (OculusManager::isConnected()) {
|
||||||
_myCamera.setUpShift (0.0f);
|
_myCamera.setUpShift (0.0f);
|
||||||
_myCamera.setDistance (0.0f);
|
_myCamera.setDistance (0.0f);
|
||||||
_myCamera.setTightness (100.0f);
|
_myCamera.setTightness (100.0f);
|
||||||
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
||||||
_myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(),
|
_myCamera.setTargetRotation(_myAvatar.getHead().getOrientation());
|
||||||
_myAvatar.getHead().getPitch(),
|
|
||||||
-_myAvatar.getHead().getRoll());
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
||||||
_myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(),
|
_myCamera.setTargetRotation(_myAvatar.getHead().getWorldAlignedOrientation());
|
||||||
_myAvatar.getAbsoluteHeadPitch(),
|
|
||||||
0.0f);
|
|
||||||
// Take a look at whether we are inside head, don't render it if so.
|
|
||||||
const float HEAD_RENDER_DISTANCE = 0.5;
|
|
||||||
glm::vec3 distanceToHead(_myCamera.getPosition() - _myAvatar.getSpringyHeadPosition());
|
|
||||||
|
|
||||||
if (glm::length(distanceToHead) < HEAD_RENDER_DISTANCE) {
|
|
||||||
}
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
||||||
_myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(),
|
_myCamera.setTargetRotation(_myAvatar.getHead().getWorldAlignedOrientation());
|
||||||
_myAvatar.getAbsoluteHeadPitch(),
|
|
||||||
0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// important...
|
// important...
|
||||||
|
@ -344,11 +333,12 @@ void Application::paintGL() {
|
||||||
if (_viewFrustumFromOffset->isChecked() && _frustumOn->isChecked()) {
|
if (_viewFrustumFromOffset->isChecked() && _frustumOn->isChecked()) {
|
||||||
|
|
||||||
// set the camera to third-person view but offset so we can see the frustum
|
// set the camera to third-person view but offset so we can see the frustum
|
||||||
_viewFrustumOffsetCamera.setTargetYaw(_viewFrustumOffsetYaw + _myAvatar.getBodyYaw());
|
_viewFrustumOffsetCamera.setTargetPosition(_myCamera.getTargetPosition());
|
||||||
_viewFrustumOffsetCamera.setPitch (_viewFrustumOffsetPitch );
|
_viewFrustumOffsetCamera.setTargetRotation(_myCamera.getTargetRotation() * glm::quat(glm::radians(glm::vec3(
|
||||||
_viewFrustumOffsetCamera.setRoll (_viewFrustumOffsetRoll );
|
_viewFrustumOffsetPitch, _viewFrustumOffsetYaw, _viewFrustumOffsetRoll))));
|
||||||
_viewFrustumOffsetCamera.setUpShift (_viewFrustumOffsetUp );
|
_viewFrustumOffsetCamera.setUpShift (_viewFrustumOffsetUp );
|
||||||
_viewFrustumOffsetCamera.setDistance (_viewFrustumOffsetDistance);
|
_viewFrustumOffsetCamera.setDistance (_viewFrustumOffsetDistance);
|
||||||
|
_viewFrustumOffsetCamera.initialize(); // force immediate snap to ideal position and orientation
|
||||||
_viewFrustumOffsetCamera.update(1.f/_fps);
|
_viewFrustumOffsetCamera.update(1.f/_fps);
|
||||||
whichCamera = _viewFrustumOffsetCamera;
|
whichCamera = _viewFrustumOffsetCamera;
|
||||||
}
|
}
|
||||||
|
@ -1122,7 +1112,7 @@ void Application::initMenu() {
|
||||||
_window->setMenuBar(menuBar);
|
_window->setMenuBar(menuBar);
|
||||||
|
|
||||||
QMenu* fileMenu = menuBar->addMenu("File");
|
QMenu* fileMenu = menuBar->addMenu("File");
|
||||||
fileMenu->addAction("Quit", this, SLOT(quit()), (Qt::Key_Q || Qt::Key_Control));
|
fileMenu->addAction("Quit", this, SLOT(quit()), Qt::CTRL | Qt::Key_Q);
|
||||||
|
|
||||||
QMenu* pairMenu = menuBar->addMenu("Pair");
|
QMenu* pairMenu = menuBar->addMenu("Pair");
|
||||||
pairMenu->addAction("Pair", this, SLOT(pair()));
|
pairMenu->addAction("Pair", this, SLOT(pair()));
|
||||||
|
@ -1379,10 +1369,6 @@ void Application::updateAvatar(float deltaTime) {
|
||||||
void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
|
void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
|
||||||
// We will use these below, from either the camera or head vectors calculated above
|
// We will use these below, from either the camera or head vectors calculated above
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::vec3 direction;
|
|
||||||
glm::vec3 up;
|
|
||||||
glm::vec3 right;
|
|
||||||
float fov, nearClip, farClip;
|
|
||||||
|
|
||||||
// Camera or Head?
|
// Camera or Head?
|
||||||
if (_cameraFrustum->isChecked()) {
|
if (_cameraFrustum->isChecked()) {
|
||||||
|
@ -1391,15 +1377,14 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
|
||||||
position = _myAvatar.getHeadPosition();
|
position = _myAvatar.getHeadPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
fov = camera.getFieldOfView();
|
float fov = camera.getFieldOfView();
|
||||||
nearClip = camera.getNearClip();
|
float nearClip = camera.getNearClip();
|
||||||
farClip = camera.getFarClip();
|
float farClip = camera.getFarClip();
|
||||||
|
|
||||||
Orientation o = camera.getOrientation();
|
glm::quat rotation = camera.getRotation();
|
||||||
|
glm::vec3 direction = rotation * AVATAR_FRONT;
|
||||||
direction = o.getFront();
|
glm::vec3 up = rotation * AVATAR_UP;
|
||||||
up = o.getUp();
|
glm::vec3 right = rotation * AVATAR_RIGHT;
|
||||||
right = o.getRight();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
printf("position.x=%f, position.y=%f, position.z=%f\n", position.x, position.y, position.z);
|
printf("position.x=%f, position.y=%f, position.z=%f\n", position.x, position.y, position.z);
|
||||||
|
@ -1585,11 +1570,10 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
// transform view according to whichCamera
|
// transform view according to whichCamera
|
||||||
// could be myCamera (if in normal mode)
|
// could be myCamera (if in normal mode)
|
||||||
// or could be viewFrustumOffsetCamera if in offset mode
|
// or could be viewFrustumOffsetCamera if in offset mode
|
||||||
// I changed the ordering here - roll is FIRST (JJV)
|
|
||||||
|
|
||||||
glRotatef ( whichCamera.getRoll(), IDENTITY_FRONT.x, IDENTITY_FRONT.y, IDENTITY_FRONT.z);
|
glm::quat rotation = whichCamera.getRotation();
|
||||||
glRotatef ( whichCamera.getPitch(), IDENTITY_RIGHT.x, IDENTITY_RIGHT.y, IDENTITY_RIGHT.z);
|
glm::vec3 axis = glm::axis(rotation);
|
||||||
glRotatef (180.0 - whichCamera.getYaw(), IDENTITY_UP.x, IDENTITY_UP.y, IDENTITY_UP.z );
|
glRotatef(-glm::angle(rotation), axis.x, axis.y, axis.z);
|
||||||
|
|
||||||
glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
|
glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ const float HEAD_MIN_YAW = -85;
|
||||||
const float PERIPERSONAL_RADIUS = 1.0f;
|
const float PERIPERSONAL_RADIUS = 1.0f;
|
||||||
const float AVATAR_BRAKING_STRENGTH = 40.0f;
|
const float AVATAR_BRAKING_STRENGTH = 40.0f;
|
||||||
const float JOINT_TOUCH_RANGE = 0.0005f;
|
const float JOINT_TOUCH_RANGE = 0.0005f;
|
||||||
const float ANGULAR_RIGHTING_SPEED = 45.0f;
|
|
||||||
const float FLOATING_HEIGHT = 0.13f;
|
const float FLOATING_HEIGHT = 0.13f;
|
||||||
const bool USING_HEAD_LEAN = false;
|
const bool USING_HEAD_LEAN = false;
|
||||||
const float LEAN_SENSITIVITY = 0.15;
|
const float LEAN_SENSITIVITY = 0.15;
|
||||||
|
@ -78,7 +77,6 @@ Avatar::Avatar(Agent* owningAgent) :
|
||||||
_bodyYawDelta(0.0f),
|
_bodyYawDelta(0.0f),
|
||||||
_bodyRollDelta(0.0f),
|
_bodyRollDelta(0.0f),
|
||||||
_movedHandOffset(0.0f, 0.0f, 0.0f),
|
_movedHandOffset(0.0f, 0.0f, 0.0f),
|
||||||
_rotation(0.0f, 0.0f, 0.0f, 0.0f),
|
|
||||||
_mode(AVATAR_MODE_STANDING),
|
_mode(AVATAR_MODE_STANDING),
|
||||||
_cameraPosition(0.0f, 0.0f, 0.0f),
|
_cameraPosition(0.0f, 0.0f, 0.0f),
|
||||||
_handHoldingPosition(0.0f, 0.0f, 0.0f),
|
_handHoldingPosition(0.0f, 0.0f, 0.0f),
|
||||||
|
@ -86,11 +84,11 @@ Avatar::Avatar(Agent* owningAgent) :
|
||||||
_thrust(0.0f, 0.0f, 0.0f),
|
_thrust(0.0f, 0.0f, 0.0f),
|
||||||
_speed(0.0f),
|
_speed(0.0f),
|
||||||
_maxArmLength(0.0f),
|
_maxArmLength(0.0f),
|
||||||
_orientation(),
|
|
||||||
_pelvisStandingHeight(0.0f),
|
_pelvisStandingHeight(0.0f),
|
||||||
_pelvisFloatingHeight(0.0f),
|
_pelvisFloatingHeight(0.0f),
|
||||||
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
||||||
_gravity(0.0f, -1.0f, 0.0f),
|
_gravity(0.0f, -1.0f, 0.0f),
|
||||||
|
_worldUpDirection(0.0f, 1.0f, 0.0),
|
||||||
_mouseRayOrigin(0.0f, 0.0f, 0.0f),
|
_mouseRayOrigin(0.0f, 0.0f, 0.0f),
|
||||||
_mouseRayDirection(0.0f, 0.0f, 0.0f),
|
_mouseRayDirection(0.0f, 0.0f, 0.0f),
|
||||||
_interactingOther(NULL),
|
_interactingOther(NULL),
|
||||||
|
@ -157,11 +155,19 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa
|
||||||
}
|
}
|
||||||
|
|
||||||
float Avatar::getAbsoluteHeadYaw() const {
|
float Avatar::getAbsoluteHeadYaw() const {
|
||||||
return _bodyYaw + _head.getYaw();
|
return glm::yaw(_head.getOrientation());
|
||||||
}
|
}
|
||||||
|
|
||||||
float Avatar::getAbsoluteHeadPitch() const {
|
float Avatar::getAbsoluteHeadPitch() const {
|
||||||
return _bodyPitch + _head.getPitch();
|
return glm::pitch(_head.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat Avatar::getOrientation() const {
|
||||||
|
return glm::quat(glm::radians(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat Avatar::getWorldAlignedOrientation () const {
|
||||||
|
return computeRotationFromBodyToWorldUp() * getOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) {
|
void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) {
|
||||||
|
@ -218,9 +224,9 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
|
|
||||||
// if other avatar, update head position from network data
|
// if other avatar, update head position from network data
|
||||||
|
|
||||||
// update avatar skeleton
|
// update avatar skeleton
|
||||||
updateSkeleton();
|
updateSkeleton();
|
||||||
|
|
||||||
//detect and respond to collisions with other avatars...
|
//detect and respond to collisions with other avatars...
|
||||||
if (!_owningAgent) {
|
if (!_owningAgent) {
|
||||||
updateAvatarCollisions(deltaTime);
|
updateAvatarCollisions(deltaTime);
|
||||||
|
@ -238,7 +244,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
updateCollisionWithEnvironment();
|
updateCollisionWithEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// update body springs
|
// update body springs
|
||||||
updateBodySprings(deltaTime);
|
updateBodySprings(deltaTime);
|
||||||
|
|
||||||
// test for avatar collision response with the big sphere
|
// test for avatar collision response with the big sphere
|
||||||
|
@ -251,18 +257,23 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
updateCollisionWithVoxels();
|
updateCollisionWithVoxels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::quat orientation = getOrientation();
|
||||||
|
glm::vec3 front = orientation * AVATAR_FRONT;
|
||||||
|
glm::vec3 right = orientation * AVATAR_RIGHT;
|
||||||
|
glm::vec3 up = orientation * AVATAR_UP;
|
||||||
|
|
||||||
// driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely)
|
// driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely)
|
||||||
if (!_owningAgent) {
|
if (!_owningAgent) {
|
||||||
|
|
||||||
_thrust = glm::vec3(0.0f, 0.0f, 0.0f);
|
_thrust = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
// Add Thrusts from keyboard
|
// Add Thrusts from keyboard
|
||||||
if (_driveKeys[FWD ]) {_thrust += THRUST_MAG * deltaTime * _orientation.getFront();}
|
if (_driveKeys[FWD ]) {_thrust += THRUST_MAG * deltaTime * front;}
|
||||||
if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG * deltaTime * _orientation.getFront();}
|
if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG * deltaTime * front;}
|
||||||
if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG * deltaTime * _orientation.getRight();}
|
if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG * deltaTime * right;}
|
||||||
if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG * deltaTime * _orientation.getRight();}
|
if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG * deltaTime * right;}
|
||||||
if (_driveKeys[UP ]) {_thrust += THRUST_MAG * deltaTime * _orientation.getUp();}
|
if (_driveKeys[UP ]) {_thrust += THRUST_MAG * deltaTime * up;}
|
||||||
if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG * deltaTime * _orientation.getUp();}
|
if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG * deltaTime * up;}
|
||||||
if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;}
|
if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;}
|
||||||
if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;}
|
if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;}
|
||||||
|
|
||||||
|
@ -277,10 +288,10 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
const float TRANSMITTER_LIFT_SCALE = 3.f;
|
const float TRANSMITTER_LIFT_SCALE = 3.f;
|
||||||
const float TOUCH_POSITION_RANGE_HALF = 32767.f;
|
const float TOUCH_POSITION_RANGE_HALF = 32767.f;
|
||||||
if (fabs(rotation.z) > TRANSMITTER_MIN_RATE) {
|
if (fabs(rotation.z) > TRANSMITTER_MIN_RATE) {
|
||||||
_thrust += rotation.z * TRANSMITTER_LATERAL_FORCE_SCALE * deltaTime * _orientation.getRight();
|
_thrust += rotation.z * TRANSMITTER_LATERAL_FORCE_SCALE * deltaTime * right;
|
||||||
}
|
}
|
||||||
if (fabs(rotation.x) > TRANSMITTER_MIN_RATE) {
|
if (fabs(rotation.x) > TRANSMITTER_MIN_RATE) {
|
||||||
_thrust += -rotation.x * TRANSMITTER_FWD_FORCE_SCALE * deltaTime * _orientation.getFront();
|
_thrust += -rotation.x * TRANSMITTER_FWD_FORCE_SCALE * deltaTime * front;
|
||||||
}
|
}
|
||||||
if (fabs(rotation.y) > TRANSMITTER_MIN_YAW_RATE) {
|
if (fabs(rotation.y) > TRANSMITTER_MIN_YAW_RATE) {
|
||||||
_bodyYawDelta += rotation.y * TRANSMITTER_YAW_SCALE * deltaTime;
|
_bodyYawDelta += rotation.y * TRANSMITTER_YAW_SCALE * deltaTime;
|
||||||
|
@ -290,65 +301,52 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
(float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF *
|
(float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF *
|
||||||
TRANSMITTER_LIFT_SCALE *
|
TRANSMITTER_LIFT_SCALE *
|
||||||
deltaTime *
|
deltaTime *
|
||||||
_orientation.getUp();
|
up;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// update body yaw by body yaw delta
|
|
||||||
if (!_owningAgent) {
|
|
||||||
_bodyPitch += _bodyPitchDelta * deltaTime;
|
|
||||||
_bodyYaw += _bodyYawDelta * deltaTime;
|
|
||||||
_bodyRoll += _bodyRollDelta * deltaTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// decay body rotation momentum
|
// update body yaw by body yaw delta
|
||||||
|
if (!_owningAgent) {
|
||||||
|
orientation = orientation * glm::quat(glm::radians(
|
||||||
|
glm::vec3(_bodyPitchDelta, _bodyYawDelta, _bodyRollDelta) * deltaTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
// decay body rotation momentum
|
||||||
float bodySpinMomentum = 1.0 - BODY_SPIN_FRICTION * deltaTime;
|
float bodySpinMomentum = 1.0 - BODY_SPIN_FRICTION * deltaTime;
|
||||||
if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; }
|
if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; }
|
||||||
_bodyPitchDelta *= bodySpinMomentum;
|
_bodyPitchDelta *= bodySpinMomentum;
|
||||||
_bodyYawDelta *= bodySpinMomentum;
|
_bodyYawDelta *= bodySpinMomentum;
|
||||||
_bodyRollDelta *= bodySpinMomentum;
|
_bodyRollDelta *= bodySpinMomentum;
|
||||||
|
|
||||||
// add thrust to velocity
|
// add thrust to velocity
|
||||||
_velocity += _thrust * deltaTime;
|
_velocity += _thrust * deltaTime;
|
||||||
|
|
||||||
// calculate speed
|
// calculate speed
|
||||||
_speed = glm::length(_velocity);
|
_speed = glm::length(_velocity);
|
||||||
|
|
||||||
//pitch and roll the body as a function of forward speed and turning delta
|
//pitch and roll the body as a function of forward speed and turning delta
|
||||||
const float BODY_PITCH_WHILE_WALKING = 20.0;
|
const float BODY_PITCH_WHILE_WALKING = -20.0;
|
||||||
const float BODY_ROLL_WHILE_TURNING = 0.2;
|
const float BODY_ROLL_WHILE_TURNING = 0.2;
|
||||||
float forwardComponentOfVelocity = glm::dot(_orientation.getFront(), _velocity);
|
float forwardComponentOfVelocity = glm::dot(getBodyFrontDirection(), _velocity);
|
||||||
_bodyPitch += BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity;
|
orientation = orientation * glm::quat(glm::radians(glm::vec3(
|
||||||
_bodyRoll += BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta;
|
BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity, 0.0f,
|
||||||
|
BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta)));
|
||||||
// these forces keep the body upright...
|
|
||||||
float tiltDecay = 1.0 - BODY_UPRIGHT_FORCE * deltaTime;
|
|
||||||
if (tiltDecay < 0.0f) {tiltDecay = 0.0f;}
|
|
||||||
_bodyPitch *= tiltDecay;
|
|
||||||
_bodyRoll *= tiltDecay;
|
|
||||||
|
|
||||||
|
// these forces keep the body upright...
|
||||||
|
float tiltDecay = BODY_UPRIGHT_FORCE * deltaTime;
|
||||||
|
if (tiltDecay > 1.0f) {tiltDecay = 1.0f;}
|
||||||
|
|
||||||
|
// update the euler angles
|
||||||
|
setOrientation(orientation);
|
||||||
|
|
||||||
//the following will be used to make the avatar upright no matter what gravity is
|
//the following will be used to make the avatar upright no matter what gravity is
|
||||||
float gravityLength = glm::length(_gravity);
|
setOrientation(computeRotationFromBodyToWorldUp(tiltDecay) * orientation);
|
||||||
if (gravityLength > 0.0f) {
|
|
||||||
glm::vec3 targetUp = _gravity / -gravityLength;
|
|
||||||
const glm::vec3& currentUp = _righting * glm::vec3(0.0f, 1.0f, 0.0f);
|
|
||||||
float angle = glm::degrees(acosf(glm::dot(currentUp, targetUp)));
|
|
||||||
if (angle > 0.0f) {
|
|
||||||
glm::vec3 axis;
|
|
||||||
if (angle > 180.0f - EPSILON) { // 180 degree rotation; must use another axis
|
|
||||||
axis = _orientation.getRight();
|
|
||||||
} else {
|
|
||||||
axis = glm::normalize(glm::cross(currentUp, targetUp));
|
|
||||||
}
|
|
||||||
//_righting = glm::angleAxis(min(deltaTime * ANGULAR_RIGHTING_SPEED, angle), axis) * _righting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update position by velocity
|
// update position by velocity
|
||||||
_position += _velocity * deltaTime;
|
_position += _velocity * deltaTime;
|
||||||
|
|
||||||
// decay velocity
|
// decay velocity
|
||||||
float decay = 1.0 - VELOCITY_DECAY * deltaTime;
|
float decay = 1.0 - VELOCITY_DECAY * deltaTime;
|
||||||
if ( decay < 0.0 ) {
|
if ( decay < 0.0 ) {
|
||||||
_velocity = glm::vec3( 0.0f, 0.0f, 0.0f );
|
_velocity = glm::vec3( 0.0f, 0.0f, 0.0f );
|
||||||
|
@ -400,8 +398,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
if (USING_HEAD_LEAN) {
|
if (USING_HEAD_LEAN) {
|
||||||
if (fabs(_head.getLeanSideways() + _head.getLeanForward()) > 0.0f) {
|
if (fabs(_head.getLeanSideways() + _head.getLeanForward()) > 0.0f) {
|
||||||
glm::vec3 headLean =
|
glm::vec3 headLean =
|
||||||
_orientation.getRight() * _head.getLeanSideways() +
|
right * _head.getLeanSideways() +
|
||||||
_orientation.getFront() * _head.getLeanForward();
|
front * _head.getLeanForward();
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f;
|
_joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f;
|
||||||
_joint[ AVATAR_JOINT_CHEST ].springyPosition += headLean * 0.4f;
|
_joint[ AVATAR_JOINT_CHEST ].springyPosition += headLean * 0.4f;
|
||||||
|
@ -431,18 +429,18 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_head.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||||
_head.setPosition(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
|
_head.setPosition(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
|
||||||
_head.setScale (_joint[ AVATAR_JOINT_HEAD_BASE ].radius);
|
_head.setScale (_joint[ AVATAR_JOINT_HEAD_BASE ].radius);
|
||||||
_head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]));
|
_head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]));
|
||||||
_head.simulate(deltaTime, !_owningAgent);
|
_head.simulate(deltaTime, !_owningAgent);
|
||||||
|
|
||||||
// use speed and angular velocity to determine walking vs. standing
|
// use speed and angular velocity to determine walking vs. standing
|
||||||
if (_speed + fabs(_bodyYawDelta) > 0.2) {
|
if (_speed + fabs(_bodyYawDelta) > 0.2) {
|
||||||
_mode = AVATAR_MODE_WALKING;
|
_mode = AVATAR_MODE_WALKING;
|
||||||
} else {
|
} else {
|
||||||
_mode = AVATAR_MODE_INTERACTING;
|
_mode = AVATAR_MODE_INTERACTING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::checkForMouseRayTouching() {
|
void Avatar::checkForMouseRayTouching() {
|
||||||
|
@ -465,19 +463,32 @@ void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction ) {
|
||||||
_mouseRayDirection = direction;
|
_mouseRayDirection = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::setOrientation(const glm::quat& orientation) {
|
||||||
|
glm::vec3 eulerAngles = safeEulerAngles(orientation);
|
||||||
|
_bodyPitch = eulerAngles.x;
|
||||||
|
_bodyYaw = eulerAngles.y;
|
||||||
|
_bodyRoll = eulerAngles.z;
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
||||||
|
|
||||||
|
glm::quat orientation = getOrientation();
|
||||||
|
|
||||||
// reset hand and arm positions according to hand movement
|
// reset hand and arm positions according to hand movement
|
||||||
|
glm::vec3 right = orientation * AVATAR_RIGHT;
|
||||||
|
glm::vec3 up = orientation * AVATAR_UP;
|
||||||
|
glm::vec3 front = orientation * AVATAR_FRONT;
|
||||||
|
|
||||||
glm::vec3 transformedHandMovement
|
glm::vec3 transformedHandMovement
|
||||||
= _orientation.getRight() * _movedHandOffset.x * 2.0f
|
= right * _movedHandOffset.x * 2.0f
|
||||||
+ _orientation.getUp() * -_movedHandOffset.y * 2.0f
|
+ up * -_movedHandOffset.y * 2.0f
|
||||||
+ _orientation.getFront() * -_movedHandOffset.y * 2.0f;
|
+ front * -_movedHandOffset.z * 2.0f;
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement;
|
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement;
|
||||||
|
|
||||||
if (!_owningAgent) {
|
if (!_owningAgent) {
|
||||||
_avatarTouch.setMyBodyPosition(_position);
|
_avatarTouch.setMyBodyPosition(_position);
|
||||||
_avatarTouch.setMyOrientation(_orientation);
|
_avatarTouch.setMyOrientation(orientation);
|
||||||
|
|
||||||
float closestDistance = std::numeric_limits<float>::max();
|
float closestDistance = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
|
@ -492,7 +503,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
||||||
//Test: Show angle between your fwd vector and nearest avatar
|
//Test: Show angle between your fwd vector and nearest avatar
|
||||||
//glm::vec3 vectorBetweenUs = otherAvatar->getJointPosition(AVATAR_JOINT_PELVIS) -
|
//glm::vec3 vectorBetweenUs = otherAvatar->getJointPosition(AVATAR_JOINT_PELVIS) -
|
||||||
// getJointPosition(AVATAR_JOINT_PELVIS);
|
// getJointPosition(AVATAR_JOINT_PELVIS);
|
||||||
//printLog("Angle between: %f\n", angleBetween(vectorBetweenUs, _orientation.getFront()));
|
//printLog("Angle between: %f\n", angleBetween(vectorBetweenUs, getBodyFrontDirection()));
|
||||||
|
|
||||||
// test whether shoulders are close enough to allow for reaching to touch hands
|
// test whether shoulders are close enough to allow for reaching to touch hands
|
||||||
glm::vec3 v(_position - otherAvatar->_position);
|
glm::vec3 v(_position - otherAvatar->_position);
|
||||||
|
@ -511,7 +522,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
||||||
|
|
||||||
_avatarTouch.setHasInteractingOther(true);
|
_avatarTouch.setHasInteractingOther(true);
|
||||||
_avatarTouch.setYourBodyPosition(_interactingOther->_position);
|
_avatarTouch.setYourBodyPosition(_interactingOther->_position);
|
||||||
_avatarTouch.setYourOrientation (_interactingOther->_orientation);
|
_avatarTouch.setYourOrientation (_interactingOther->getOrientation());
|
||||||
_avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
|
_avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
|
||||||
_avatarTouch.setYourHandState (_interactingOther->_handState);
|
_avatarTouch.setYourHandState (_interactingOther->_handState);
|
||||||
|
|
||||||
|
@ -616,11 +627,12 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateCollisionWithEnvironment() {
|
void Avatar::updateCollisionWithEnvironment() {
|
||||||
|
glm::vec3 up = getBodyUpDirection();
|
||||||
float radius = _height * 0.125f;
|
float radius = _height * 0.125f;
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
if (Application::getInstance()->getEnvironment()->findCapsulePenetration(
|
if (Application::getInstance()->getEnvironment()->findCapsulePenetration(
|
||||||
_position - glm::vec3(0.0f, _pelvisFloatingHeight - radius, 0.0f),
|
_position - up * (_pelvisFloatingHeight - radius),
|
||||||
_position + glm::vec3(0.0f, _height - _pelvisFloatingHeight - radius, 0.0f), radius, penetration)) {
|
_position + up * (_height - _pelvisFloatingHeight - radius), radius, penetration)) {
|
||||||
applyCollisionWithScene(penetration);
|
applyCollisionWithScene(penetration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -740,6 +752,12 @@ static TextRenderer* textRenderer() {
|
||||||
void Avatar::setGravity(glm::vec3 gravity) {
|
void Avatar::setGravity(glm::vec3 gravity) {
|
||||||
_gravity = gravity;
|
_gravity = gravity;
|
||||||
_head.setGravity(_gravity);
|
_head.setGravity(_gravity);
|
||||||
|
|
||||||
|
// use the gravity to determine the new world up direction, if possible
|
||||||
|
float gravityLength = glm::length(gravity);
|
||||||
|
if (gravityLength > EPSILON) {
|
||||||
|
_worldUpDirection = _gravity / -gravityLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
||||||
|
@ -823,78 +841,74 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
||||||
|
|
||||||
void Avatar::initializeSkeleton() {
|
void Avatar::initializeSkeleton() {
|
||||||
|
|
||||||
for (int b=0; b<NUM_AVATAR_JOINTS; b++) {
|
for (int b=0; b<NUM_AVATAR_JOINTS; b++) {
|
||||||
_joint[b].isCollidable = true;
|
_joint[b].isCollidable = true;
|
||||||
_joint[b].parent = AVATAR_JOINT_NULL;
|
_joint[b].parent = AVATAR_JOINT_NULL;
|
||||||
_joint[b].position = glm::vec3(0.0, 0.0, 0.0);
|
_joint[b].position = glm::vec3(0.0, 0.0, 0.0);
|
||||||
_joint[b].defaultPosePosition = glm::vec3(0.0, 0.0, 0.0);
|
_joint[b].defaultPosePosition = glm::vec3(0.0, 0.0, 0.0);
|
||||||
_joint[b].springyPosition = glm::vec3(0.0, 0.0, 0.0);
|
_joint[b].springyPosition = glm::vec3(0.0, 0.0, 0.0);
|
||||||
_joint[b].springyVelocity = glm::vec3(0.0, 0.0, 0.0);
|
_joint[b].springyVelocity = glm::vec3(0.0, 0.0, 0.0);
|
||||||
_joint[b].rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
|
_joint[b].orientation = glm::quat(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
_joint[b].yaw = 0.0;
|
|
||||||
_joint[b].pitch = 0.0;
|
|
||||||
_joint[b].roll = 0.0;
|
|
||||||
_joint[b].length = 0.0;
|
_joint[b].length = 0.0;
|
||||||
_joint[b].radius = 0.0;
|
_joint[b].radius = 0.0;
|
||||||
_joint[b].touchForce = 0.0;
|
_joint[b].touchForce = 0.0;
|
||||||
_joint[b].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
|
_joint[b].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
|
||||||
_joint[b].orientation.setToIdentity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// specify the parental hierarchy
|
// specify the parental hierarchy
|
||||||
_joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL;
|
_joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL;
|
||||||
_joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS;
|
_joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS;
|
||||||
_joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO;
|
_joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO;
|
||||||
_joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST;
|
_joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST;
|
||||||
_joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE;
|
_joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE;
|
||||||
_joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE;
|
_joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE;
|
||||||
_joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST;
|
_joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST;
|
||||||
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR;
|
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR;
|
||||||
_joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER;
|
_joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER;
|
||||||
_joint[ AVATAR_JOINT_LEFT_WRIST ].parent = AVATAR_JOINT_LEFT_ELBOW;
|
_joint[ AVATAR_JOINT_LEFT_WRIST ].parent = AVATAR_JOINT_LEFT_ELBOW;
|
||||||
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].parent = AVATAR_JOINT_LEFT_WRIST;
|
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].parent = AVATAR_JOINT_LEFT_WRIST;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].parent = AVATAR_JOINT_CHEST;
|
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].parent = AVATAR_JOINT_CHEST;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].parent = AVATAR_JOINT_RIGHT_COLLAR;
|
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].parent = AVATAR_JOINT_RIGHT_COLLAR;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].parent = AVATAR_JOINT_RIGHT_SHOULDER;
|
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].parent = AVATAR_JOINT_RIGHT_SHOULDER;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_WRIST ].parent = AVATAR_JOINT_RIGHT_ELBOW;
|
_joint[ AVATAR_JOINT_RIGHT_WRIST ].parent = AVATAR_JOINT_RIGHT_ELBOW;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].parent = AVATAR_JOINT_RIGHT_WRIST;
|
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].parent = AVATAR_JOINT_RIGHT_WRIST;
|
||||||
_joint[ AVATAR_JOINT_LEFT_HIP ].parent = AVATAR_JOINT_PELVIS;
|
_joint[ AVATAR_JOINT_LEFT_HIP ].parent = AVATAR_JOINT_PELVIS;
|
||||||
_joint[ AVATAR_JOINT_LEFT_KNEE ].parent = AVATAR_JOINT_LEFT_HIP;
|
_joint[ AVATAR_JOINT_LEFT_KNEE ].parent = AVATAR_JOINT_LEFT_HIP;
|
||||||
_joint[ AVATAR_JOINT_LEFT_HEEL ].parent = AVATAR_JOINT_LEFT_KNEE;
|
_joint[ AVATAR_JOINT_LEFT_HEEL ].parent = AVATAR_JOINT_LEFT_KNEE;
|
||||||
_joint[ AVATAR_JOINT_LEFT_TOES ].parent = AVATAR_JOINT_LEFT_HEEL;
|
_joint[ AVATAR_JOINT_LEFT_TOES ].parent = AVATAR_JOINT_LEFT_HEEL;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_HIP ].parent = AVATAR_JOINT_PELVIS;
|
_joint[ AVATAR_JOINT_RIGHT_HIP ].parent = AVATAR_JOINT_PELVIS;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_KNEE ].parent = AVATAR_JOINT_RIGHT_HIP;
|
_joint[ AVATAR_JOINT_RIGHT_KNEE ].parent = AVATAR_JOINT_RIGHT_HIP;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE;
|
_joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL;
|
_joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL;
|
||||||
|
|
||||||
// specify the default pose position
|
// specify the default pose position
|
||||||
_joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 );
|
_joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 );
|
||||||
_joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.01 );
|
_joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
|
||||||
_joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.01 );
|
_joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
|
||||||
_joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.14, -0.01 );
|
_joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.14, 0.01 );
|
||||||
_joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.04, 0.00 );
|
_joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.04, 0.00 );
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, -0.01 );
|
_joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, 0.01 );
|
||||||
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.05, 0.0, -0.01 );
|
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.01 );
|
||||||
_joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
|
_joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
|
||||||
_joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
|
_joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
|
||||||
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
|
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, -0.01 );
|
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, 0.01 );
|
||||||
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.05, 0.0, -0.01 );
|
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.01 );
|
||||||
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
|
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
|
||||||
_joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
|
_joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
|
||||||
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
|
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.05, 0.0, -0.02 );
|
_joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.02 );
|
||||||
_joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.01, -0.25, 0.03 );
|
_joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.01, -0.25, -0.03 );
|
||||||
_joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.01, -0.22, -0.08 );
|
_joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.01, -0.22, 0.08 );
|
||||||
_joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, 0.05 );
|
_joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.05, 0.0, -0.02 );
|
_joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.02 );
|
||||||
_joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( -0.01, -0.25, 0.03 );
|
_joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( -0.01, -0.25, -0.03 );
|
||||||
_joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( -0.01, -0.22, -0.08 );
|
_joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( -0.01, -0.22, 0.08 );
|
||||||
_joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( -0.00, -0.03, 0.05 );
|
_joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
|
||||||
|
|
||||||
// specify the radii of the joints
|
// specify the radii of the joints
|
||||||
_joint[ AVATAR_JOINT_PELVIS ].radius = 0.07;
|
_joint[ AVATAR_JOINT_PELVIS ].radius = 0.07;
|
||||||
|
@ -905,29 +919,29 @@ void Avatar::initializeSkeleton() {
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.04;
|
_joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.04;
|
||||||
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.03;
|
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.03;
|
||||||
_joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.02;
|
_joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.02;
|
||||||
_joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.02;
|
_joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.02;
|
||||||
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01;
|
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01;
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.04;
|
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.04;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.03;
|
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.03;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.02;
|
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.02;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.02;
|
_joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.02;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].radius = 0.01;
|
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].radius = 0.01;
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.04;
|
_joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.04;
|
||||||
_joint[ AVATAR_JOINT_LEFT_KNEE ].radius = 0.025;
|
_joint[ AVATAR_JOINT_LEFT_KNEE ].radius = 0.025;
|
||||||
_joint[ AVATAR_JOINT_LEFT_HEEL ].radius = 0.025;
|
_joint[ AVATAR_JOINT_LEFT_HEEL ].radius = 0.025;
|
||||||
_joint[ AVATAR_JOINT_LEFT_TOES ].radius = 0.025;
|
_joint[ AVATAR_JOINT_LEFT_TOES ].radius = 0.025;
|
||||||
|
|
||||||
_joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.04;
|
_joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.04;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_KNEE ].radius = 0.025;
|
_joint[ AVATAR_JOINT_RIGHT_KNEE ].radius = 0.025;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.025;
|
_joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.025;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_TOES ].radius = 0.025;
|
_joint[ AVATAR_JOINT_RIGHT_TOES ].radius = 0.025;
|
||||||
|
|
||||||
// to aid in hand-shaking and hand-holding, the right hand is not collidable
|
// to aid in hand-shaking and hand-holding, the right hand is not collidable
|
||||||
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].isCollidable = false;
|
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].isCollidable = false;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false;
|
_joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].isCollidable = false;
|
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].isCollidable = false;
|
||||||
|
|
||||||
// calculate bone length
|
// calculate bone length
|
||||||
|
@ -970,27 +984,23 @@ void Avatar::calculateBoneLengths() {
|
||||||
|
|
||||||
_maxArmLength
|
_maxArmLength
|
||||||
= _joint[ AVATAR_JOINT_RIGHT_ELBOW ].length
|
= _joint[ AVATAR_JOINT_RIGHT_ELBOW ].length
|
||||||
+ _joint[ AVATAR_JOINT_RIGHT_WRIST ].length
|
+ _joint[ AVATAR_JOINT_RIGHT_WRIST ].length
|
||||||
+ _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].length;
|
+ _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateSkeleton() {
|
void Avatar::updateSkeleton() {
|
||||||
|
|
||||||
// rotate body...
|
// rotate body...
|
||||||
_orientation.setToIdentity();
|
glm::quat orientation = getOrientation();
|
||||||
_orientation.yaw (_bodyYaw );
|
|
||||||
_orientation.pitch(_bodyPitch);
|
|
||||||
_orientation.roll (_bodyRoll );
|
|
||||||
_orientation.rotate(_righting);
|
|
||||||
|
|
||||||
// calculate positions of all bones by traversing the skeleton tree:
|
// calculate positions of all bones by traversing the skeleton tree:
|
||||||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||||
if (_joint[b].parent == AVATAR_JOINT_NULL) {
|
if (_joint[b].parent == AVATAR_JOINT_NULL) {
|
||||||
_joint[b].orientation.set(_orientation);
|
_joint[b].orientation = orientation;
|
||||||
_joint[b].position = _position;
|
_joint[b].position = _position;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_joint[b].orientation.set(_joint[ _joint[b].parent ].orientation);
|
_joint[b].orientation = _joint[ _joint[b].parent ].orientation;
|
||||||
_joint[b].position = _joint[ _joint[b].parent ].position;
|
_joint[b].position = _joint[ _joint[b].parent ].position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1000,11 +1010,7 @@ void Avatar::updateSkeleton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// the following will be replaced by a proper rotation...close
|
// the following will be replaced by a proper rotation...close
|
||||||
float xx = glm::dot(_joint[b].defaultPosePosition, _joint[b].orientation.getRight());
|
glm::vec3 rotatedJointVector = _joint[b].orientation * _joint[b].defaultPosePosition;
|
||||||
float yy = glm::dot(_joint[b].defaultPosePosition, _joint[b].orientation.getUp ());
|
|
||||||
float zz = glm::dot(_joint[b].defaultPosePosition, _joint[b].orientation.getFront());
|
|
||||||
|
|
||||||
glm::vec3 rotatedJointVector(xx, yy, zz);
|
|
||||||
|
|
||||||
//glm::vec3 myEuler (0.0f, 0.0f, 0.0f);
|
//glm::vec3 myEuler (0.0f, 0.0f, 0.0f);
|
||||||
//glm::quat myQuat (myEuler);
|
//glm::quat myQuat (myEuler);
|
||||||
|
@ -1037,12 +1043,12 @@ void Avatar::updateBodySprings(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float length = glm::length(springVector);
|
float length = glm::length(springVector);
|
||||||
|
|
||||||
if (length > 0.0f) { // to avoid divide by zero
|
if (length > 0.0f) { // to avoid divide by zero
|
||||||
glm::vec3 springDirection = springVector / length;
|
glm::vec3 springDirection = springVector / length;
|
||||||
|
|
||||||
float force = (length - _joint[b].length) * BODY_SPRING_FORCE * deltaTime;
|
float force = (length - _joint[b].length) * BODY_SPRING_FORCE * deltaTime;
|
||||||
|
|
||||||
_joint[b].springyVelocity -= springDirection * force;
|
_joint[b].springyVelocity -= springDirection * force;
|
||||||
|
|
||||||
if (_joint[b].parent != AVATAR_JOINT_NULL) {
|
if (_joint[b].parent != AVATAR_JOINT_NULL) {
|
||||||
|
@ -1051,7 +1057,7 @@ void Avatar::updateBodySprings(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply tightness force - (causing springy position to be close to rigid body position)
|
// apply tightness force - (causing springy position to be close to rigid body position)
|
||||||
_joint[b].springyVelocity += (_joint[b].position - _joint[b].springyPosition) * _joint[b].springBodyTightness * deltaTime;
|
_joint[b].springyVelocity += (_joint[b].position - _joint[b].springyPosition) * _joint[b].springBodyTightness * deltaTime;
|
||||||
|
|
||||||
// apply decay
|
// apply decay
|
||||||
float decay = 1.0 - BODY_SPRING_DECAY * deltaTime;
|
float decay = 1.0 - BODY_SPRING_DECAY * deltaTime;
|
||||||
|
@ -1082,7 +1088,7 @@ void Avatar::updateArmIKAndConstraints(float deltaTime) {
|
||||||
|
|
||||||
// test to see if right hand is being dragged beyond maximum arm length
|
// test to see if right hand is being dragged beyond maximum arm length
|
||||||
float distance = glm::length(armVector);
|
float distance = glm::length(armVector);
|
||||||
|
|
||||||
// don't let right hand get dragged beyond maximum arm length...
|
// don't let right hand get dragged beyond maximum arm length...
|
||||||
if (distance > _maxArmLength) {
|
if (distance > _maxArmLength) {
|
||||||
// reset right hand to be constrained to maximum arm length
|
// reset right hand to be constrained to maximum arm length
|
||||||
|
@ -1099,7 +1105,7 @@ void Avatar::updateArmIKAndConstraints(float deltaTime) {
|
||||||
glm::vec3 newElbowPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
|
glm::vec3 newElbowPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
|
||||||
newElbowPosition += armVector * ONE_HALF;
|
newElbowPosition += armVector * ONE_HALF;
|
||||||
|
|
||||||
glm::vec3 perpendicular = glm::cross(_orientation.getFront(), armVector);
|
glm::vec3 perpendicular = glm::cross(getBodyFrontDirection(), armVector);
|
||||||
|
|
||||||
newElbowPosition += perpendicular * (1.0f - (_maxArmLength / distance)) * ONE_HALF;
|
newElbowPosition += perpendicular * (1.0f - (_maxArmLength / distance)) * ONE_HALF;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].position = newElbowPosition;
|
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].position = newElbowPosition;
|
||||||
|
@ -1111,6 +1117,21 @@ void Avatar::updateArmIKAndConstraints(float deltaTime) {
|
||||||
_joint[ AVATAR_JOINT_RIGHT_WRIST ].position = newWristPosition;
|
_joint[ AVATAR_JOINT_RIGHT_WRIST ].position = newWristPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||||
|
glm::quat orientation = getOrientation();
|
||||||
|
glm::vec3 currentUp = orientation * AVATAR_UP;
|
||||||
|
float angle = glm::degrees(acosf(glm::clamp(glm::dot(currentUp, _worldUpDirection), -1.0f, 1.0f)));
|
||||||
|
if (angle < EPSILON) {
|
||||||
|
return glm::quat();
|
||||||
|
}
|
||||||
|
glm::vec3 axis;
|
||||||
|
if (angle > 179.99f) { // 180 degree rotation; must use another axis
|
||||||
|
axis = orientation * AVATAR_RIGHT;
|
||||||
|
} else {
|
||||||
|
axis = glm::normalize(glm::cross(currentUp, _worldUpDirection));
|
||||||
|
}
|
||||||
|
return glm::angleAxis(angle * proportion, axis);
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::renderBody(bool lookingInMirror) {
|
void Avatar::renderBody(bool lookingInMirror) {
|
||||||
|
|
||||||
|
@ -1121,7 +1142,8 @@ void Avatar::renderBody(bool lookingInMirror) {
|
||||||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||||
float distanceToCamera = glm::length(_cameraPosition - _joint[b].position);
|
float distanceToCamera = glm::length(_cameraPosition - _joint[b].position);
|
||||||
|
|
||||||
float alpha = glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f);
|
float alpha = lookingInMirror ? 1.0f : glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) /
|
||||||
|
(RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f);
|
||||||
|
|
||||||
if (lookingInMirror || _owningAgent) {
|
if (lookingInMirror || _owningAgent) {
|
||||||
alpha = 1.0f;
|
alpha = 1.0f;
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
#include <Orientation.h>
|
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "AvatarTouch.h"
|
#include "AvatarTouch.h"
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
@ -31,15 +30,15 @@ enum DriveKeys
|
||||||
DOWN,
|
DOWN,
|
||||||
ROT_LEFT,
|
ROT_LEFT,
|
||||||
ROT_RIGHT,
|
ROT_RIGHT,
|
||||||
MAX_DRIVE_KEYS
|
MAX_DRIVE_KEYS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AvatarMode
|
enum AvatarMode
|
||||||
{
|
{
|
||||||
AVATAR_MODE_STANDING = 0,
|
AVATAR_MODE_STANDING = 0,
|
||||||
AVATAR_MODE_WALKING,
|
AVATAR_MODE_WALKING,
|
||||||
AVATAR_MODE_INTERACTING,
|
AVATAR_MODE_INTERACTING,
|
||||||
NUM_AVATAR_MODES
|
NUM_AVATAR_MODES
|
||||||
};
|
};
|
||||||
|
|
||||||
class Avatar : public AvatarData {
|
class Avatar : public AvatarData {
|
||||||
|
@ -62,22 +61,27 @@ public:
|
||||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors);}
|
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors);}
|
||||||
void setGravity (glm::vec3 gravity);
|
void setGravity (glm::vec3 gravity);
|
||||||
void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction);
|
void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction);
|
||||||
|
void setOrientation (const glm::quat& orientation);
|
||||||
|
|
||||||
//getters
|
//getters
|
||||||
float getHeadYawRate () const { return _head.yawRate;}
|
float getHeadYawRate () const { return _head.yawRate;}
|
||||||
float getBodyYaw () const { return _bodyYaw;}
|
float getBodyYaw () const { return _bodyYaw;}
|
||||||
bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();}
|
bool getIsNearInteractingOther () const { return _avatarTouch.getAbleToReachOtherAvatar();}
|
||||||
const glm::vec3& getHeadPosition () const { return _joint[ AVATAR_JOINT_HEAD_BASE ].position;}
|
const glm::vec3& getHeadPosition () const { return _joint[ AVATAR_JOINT_HEAD_BASE ].position;}
|
||||||
const glm::vec3& getSpringyHeadPosition () const { return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition;}
|
const glm::vec3& getSpringyHeadPosition () const { return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition;}
|
||||||
const glm::vec3& getJointPosition (AvatarJointID j) const { return _joint[j].springyPosition;}
|
const glm::vec3& getJointPosition (AvatarJointID j) const { return _joint[j].springyPosition;}
|
||||||
const glm::vec3& getBodyUpDirection () const { return _orientation.getUp();}
|
glm::vec3 getBodyRightDirection () const { return getOrientation() * AVATAR_RIGHT; }
|
||||||
const glm::vec3& getVelocity () const { return _velocity;}
|
glm::vec3 getBodyUpDirection () const { return getOrientation() * AVATAR_UP; }
|
||||||
float getSpeed () const { return _speed;}
|
glm::vec3 getBodyFrontDirection () const { return getOrientation() * AVATAR_FRONT; }
|
||||||
float getHeight () const { return _height;}
|
const glm::vec3& getVelocity () const { return _velocity;}
|
||||||
AvatarMode getMode () const { return _mode;}
|
float getSpeed () const { return _speed;}
|
||||||
float getAbsoluteHeadYaw () const;
|
float getHeight () const { return _height;}
|
||||||
float getAbsoluteHeadPitch () const;
|
AvatarMode getMode () const { return _mode;}
|
||||||
Head& getHead () {return _head; }
|
float getAbsoluteHeadYaw () const;
|
||||||
|
float getAbsoluteHeadPitch () const;
|
||||||
|
Head& getHead () { return _head; }
|
||||||
|
glm::quat getOrientation () const;
|
||||||
|
glm::quat getWorldAlignedOrientation () const;
|
||||||
|
|
||||||
// Set what driving keys are being pressed to control thrust levels
|
// Set what driving keys are being pressed to control thrust levels
|
||||||
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
|
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
|
||||||
|
@ -99,19 +103,15 @@ private:
|
||||||
struct AvatarJoint
|
struct AvatarJoint
|
||||||
{
|
{
|
||||||
AvatarJointID parent; // which joint is this joint connected to?
|
AvatarJointID parent; // which joint is this joint connected to?
|
||||||
glm::vec3 position; // the position at the "end" of the joint - in global space
|
glm::vec3 position; // the position at the "end" of the joint - in global space
|
||||||
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
||||||
glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position)
|
glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position)
|
||||||
glm::vec3 springyVelocity; // used for special effects ( the velocity of the springy position)
|
glm::vec3 springyVelocity; // used for special effects ( the velocity of the springy position)
|
||||||
float springBodyTightness; // how tightly the springy position tries to stay on the position
|
float springBodyTightness; // how tightly the springy position tries to stay on the position
|
||||||
glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation)
|
glm::quat orientation; // this will eventually replace yaw, pitch and roll (and maybe orientation)
|
||||||
float yaw; // the yaw Euler angle of the joint rotation off the parent
|
float length; // the length of vector connecting the joint and its parent
|
||||||
float pitch; // the pitch Euler angle of the joint rotation off the parent
|
float radius; // used for detecting collisions for certain physical effects
|
||||||
float roll; // the roll Euler angle of the joint rotation off the parent
|
bool isCollidable; // when false, the joint position will not register a collision
|
||||||
Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll
|
|
||||||
float length; // the length of vector connecting the joint and its parent
|
|
||||||
float radius; // used for detecting collisions for certain physical effects
|
|
||||||
bool isCollidable; // when false, the joint position will not register a collision
|
|
||||||
float touchForce; // if being touched, what's the degree of influence? (0 to 1)
|
float touchForce; // if being touched, what's the degree of influence? (0 to 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -124,16 +124,14 @@ private:
|
||||||
float _bodyYawDelta;
|
float _bodyYawDelta;
|
||||||
float _bodyRollDelta;
|
float _bodyRollDelta;
|
||||||
glm::vec3 _movedHandOffset;
|
glm::vec3 _movedHandOffset;
|
||||||
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
|
AvatarJoint _joint[ NUM_AVATAR_JOINTS ];
|
||||||
AvatarJoint _joint[ NUM_AVATAR_JOINTS ];
|
|
||||||
AvatarMode _mode;
|
AvatarMode _mode;
|
||||||
glm::vec3 _cameraPosition;
|
glm::vec3 _cameraPosition;
|
||||||
glm::vec3 _handHoldingPosition;
|
glm::vec3 _handHoldingPosition;
|
||||||
glm::vec3 _velocity;
|
glm::vec3 _velocity;
|
||||||
glm::vec3 _thrust;
|
glm::vec3 _thrust;
|
||||||
float _speed;
|
float _speed;
|
||||||
float _maxArmLength;
|
float _maxArmLength;
|
||||||
Orientation _orientation;
|
|
||||||
glm::quat _righting;
|
glm::quat _righting;
|
||||||
int _driveKeys[MAX_DRIVE_KEYS];
|
int _driveKeys[MAX_DRIVE_KEYS];
|
||||||
float _pelvisStandingHeight;
|
float _pelvisStandingHeight;
|
||||||
|
@ -143,6 +141,7 @@ private:
|
||||||
AvatarTouch _avatarTouch;
|
AvatarTouch _avatarTouch;
|
||||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
|
glm::vec3 _worldUpDirection;
|
||||||
glm::vec3 _mouseRayOrigin;
|
glm::vec3 _mouseRayOrigin;
|
||||||
glm::vec3 _mouseRayDirection;
|
glm::vec3 _mouseRayDirection;
|
||||||
Avatar* _interactingOther;
|
Avatar* _interactingOther;
|
||||||
|
@ -151,6 +150,7 @@ private:
|
||||||
|
|
||||||
// private methods...
|
// private methods...
|
||||||
glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat)
|
glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat)
|
||||||
|
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
|
||||||
void renderBody(bool lookingInMirror);
|
void renderBody(bool lookingInMirror);
|
||||||
void initializeSkeleton();
|
void initializeSkeleton();
|
||||||
void updateSkeleton();
|
void updateSkeleton();
|
||||||
|
|
|
@ -29,8 +29,6 @@ AvatarTouch::AvatarTouch() {
|
||||||
_canReachToOtherAvatar = false;
|
_canReachToOtherAvatar = false;
|
||||||
_handsCloseEnoughToGrasp = false;
|
_handsCloseEnoughToGrasp = false;
|
||||||
_hasInteractingOther = false;
|
_hasInteractingOther = false;
|
||||||
_myOrientation.setToIdentity();
|
|
||||||
_yourOrientation.setToIdentity();
|
|
||||||
|
|
||||||
for (int p=0; p<NUM_PARTICLE_POINTS; p++) {
|
for (int p=0; p<NUM_PARTICLE_POINTS; p++) {
|
||||||
_point[p] = glm::vec3(0.0, 0.0, 0.0);
|
_point[p] = glm::vec3(0.0, 0.0, 0.0);
|
||||||
|
@ -49,8 +47,11 @@ void AvatarTouch::simulate (float deltaTime) {
|
||||||
|
|
||||||
bool facingEachOther = false;
|
bool facingEachOther = false;
|
||||||
|
|
||||||
if (( glm::dot(_myOrientation.getFront(), _yourOrientation.getFront()) < -AVATAR_FACING_THRESHOLD) // we're facing each other
|
glm::vec3 myFront = _myOrientation * AVATAR_FRONT;
|
||||||
&& ( glm::dot(_myOrientation.getFront(), directionBetweenBodies ) > AVATAR_FACING_THRESHOLD)) { // I'm facing you
|
glm::vec3 yourFront = _yourOrientation * AVATAR_FRONT;
|
||||||
|
|
||||||
|
if (( glm::dot(myFront, yourFront) < -AVATAR_FACING_THRESHOLD) // we're facing each other
|
||||||
|
&& ( glm::dot(myFront, directionBetweenBodies ) > AVATAR_FACING_THRESHOLD)) { // I'm facing you
|
||||||
facingEachOther = true;
|
facingEachOther = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#define __interface__AvatarTouch__
|
#define __interface__AvatarTouch__
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include "Orientation.h"
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
|
#include <AvatarData.h>
|
||||||
|
|
||||||
enum AvatarHandState
|
enum AvatarHandState
|
||||||
{
|
{
|
||||||
|
@ -31,8 +33,8 @@ public:
|
||||||
void setHasInteractingOther(bool hasInteractingOther) { _hasInteractingOther = hasInteractingOther;}
|
void setHasInteractingOther(bool hasInteractingOther) { _hasInteractingOther = hasInteractingOther;}
|
||||||
void setMyHandPosition (glm::vec3 position ) { _myHandPosition = position;}
|
void setMyHandPosition (glm::vec3 position ) { _myHandPosition = position;}
|
||||||
void setYourHandPosition (glm::vec3 position ) { _yourHandPosition = position;}
|
void setYourHandPosition (glm::vec3 position ) { _yourHandPosition = position;}
|
||||||
void setMyOrientation (Orientation orientation ) { _myOrientation = orientation;}
|
void setMyOrientation (glm::quat orientation ) { _myOrientation = orientation;}
|
||||||
void setYourOrientation (Orientation orientation ) { _yourOrientation = orientation;}
|
void setYourOrientation (glm::quat orientation ) { _yourOrientation = orientation;}
|
||||||
void setMyBodyPosition (glm::vec3 position ) { _myBodyPosition = position;}
|
void setMyBodyPosition (glm::vec3 position ) { _myBodyPosition = position;}
|
||||||
void setYourBodyPosition (glm::vec3 position ) { _yourBodyPosition = position;}
|
void setYourBodyPosition (glm::vec3 position ) { _yourBodyPosition = position;}
|
||||||
void setMyHandState (int state ) { _myHandState = state;}
|
void setMyHandState (int state ) { _myHandState = state;}
|
||||||
|
@ -55,8 +57,8 @@ private:
|
||||||
glm::vec3 _yourBodyPosition;
|
glm::vec3 _yourBodyPosition;
|
||||||
glm::vec3 _myHandPosition;
|
glm::vec3 _myHandPosition;
|
||||||
glm::vec3 _yourHandPosition;
|
glm::vec3 _yourHandPosition;
|
||||||
Orientation _myOrientation;
|
glm::quat _myOrientation;
|
||||||
Orientation _yourOrientation;
|
glm::quat _yourOrientation;
|
||||||
glm::vec3 _vectorBetweenHands;
|
glm::vec3 _vectorBetweenHands;
|
||||||
int _myHandState;
|
int _myHandState;
|
||||||
int _yourHandState;
|
int _yourHandState;
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
//
|
//
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <VoxelConstants.h>
|
#include <VoxelConstants.h>
|
||||||
#include <OculusManager.h>
|
#include <OculusManager.h>
|
||||||
// #include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
const float CAMERA_MINIMUM_MODE_SHIFT_RATE = 0.5f;
|
const float CAMERA_MINIMUM_MODE_SHIFT_RATE = 0.5f;
|
||||||
|
|
||||||
|
@ -38,9 +40,6 @@ Camera::Camera() {
|
||||||
_fieldOfView = 60.0f; // default
|
_fieldOfView = 60.0f; // default
|
||||||
_nearClip = 0.08f; // default
|
_nearClip = 0.08f; // default
|
||||||
_farClip = 50.0f * TREE_SCALE; // default
|
_farClip = 50.0f * TREE_SCALE; // default
|
||||||
_yaw = 0.0f;
|
|
||||||
_pitch = 0.0f;
|
|
||||||
_roll = 0.0f;
|
|
||||||
_upShift = 0.0f;
|
_upShift = 0.0f;
|
||||||
_distance = 0.0f;
|
_distance = 0.0f;
|
||||||
_previousUpShift = 0.0f;
|
_previousUpShift = 0.0f;
|
||||||
|
@ -49,13 +48,9 @@ Camera::Camera() {
|
||||||
_newUpShift = 0.0f;
|
_newUpShift = 0.0f;
|
||||||
_newDistance = 0.0f;
|
_newDistance = 0.0f;
|
||||||
_newTightness = 0.0f;
|
_newTightness = 0.0f;
|
||||||
_idealYaw = 0.0f;
|
|
||||||
_idealPitch = 0.0f;
|
|
||||||
_idealRoll = 0.0f;
|
|
||||||
_targetPosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
_targetPosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_position = glm::vec3(0.0f, 0.0f, 0.0f);
|
_position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_idealPosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
_idealPosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_orientation.setToIdentity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::update(float deltaTime) {
|
void Camera::update(float deltaTime) {
|
||||||
|
@ -64,17 +59,6 @@ void Camera::update(float deltaTime) {
|
||||||
// use iterative forces to push the camera towards the target position and angle
|
// use iterative forces to push the camera towards the target position and angle
|
||||||
updateFollowMode(deltaTime);
|
updateFollowMode(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// do this AFTER making any changes to yaw pitch and roll....
|
|
||||||
generateOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate the ortho-normals for the orientation based on the three Euler angles
|
|
||||||
void Camera::generateOrientation() {
|
|
||||||
_orientation.setToIdentity();
|
|
||||||
_orientation.pitch(_pitch);
|
|
||||||
_orientation.yaw (_yaw );
|
|
||||||
_orientation.roll (_roll );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// use iterative forces to keep the camera at the desired position and angle
|
// use iterative forces to keep the camera at the desired position and angle
|
||||||
|
@ -104,26 +88,15 @@ void Camera::updateFollowMode(float deltaTime) {
|
||||||
t = 1.0;
|
t = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update Euler angles (before position!)
|
// update rotation (before position!)
|
||||||
if (_needsToInitialize || OculusManager::isConnected()) {
|
if (_needsToInitialize || OculusManager::isConnected()) {
|
||||||
_yaw = _idealYaw;
|
_rotation = _targetRotation;
|
||||||
_pitch = _idealPitch;
|
|
||||||
_roll = _idealRoll;
|
|
||||||
} else {
|
} else {
|
||||||
// pull Euler angles towards ideal Euler angles
|
// pull rotation towards ideal
|
||||||
_yaw += (_idealYaw - _yaw ) * t;
|
_rotation = safeMix(_rotation, _targetRotation, t);
|
||||||
_pitch += (_idealPitch - _pitch) * t;
|
|
||||||
_roll += (_idealRoll - _roll ) * t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float radian = (_yaw / 180.0) * PIE;
|
_idealPosition = _targetPosition + _rotation * glm::vec3(0.0f, _upShift, _distance);
|
||||||
|
|
||||||
// update _position
|
|
||||||
double x = -_distance * sin(radian);
|
|
||||||
double z = -_distance * cos(radian);
|
|
||||||
double y = _upShift;
|
|
||||||
|
|
||||||
_idealPosition = _targetPosition + glm::vec3(x, y, z);
|
|
||||||
|
|
||||||
if (_needsToInitialize) {
|
if (_needsToInitialize) {
|
||||||
_position = _idealPosition;
|
_position = _idealPosition;
|
||||||
|
@ -171,10 +144,8 @@ void Camera::setMode(CameraMode m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Camera::setTargetRotation( float yaw, float pitch, float roll ) {
|
void Camera::setTargetRotation( const glm::quat& targetRotation ) {
|
||||||
_idealYaw = yaw;
|
_targetRotation = targetRotation;
|
||||||
_idealPitch = pitch;
|
|
||||||
_idealRoll = roll;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setFieldOfView(float f) {
|
void Camera::setFieldOfView(float f) {
|
||||||
|
|
|
@ -30,40 +30,36 @@ public:
|
||||||
|
|
||||||
void update( float deltaTime );
|
void update( float deltaTime );
|
||||||
|
|
||||||
void setYaw ( float y ) { _yaw = y; }
|
void setUpShift ( float u ) { _upShift = u; }
|
||||||
void setPitch ( float p ) { _pitch = p; }
|
void setDistance ( float d ) { _distance = d; }
|
||||||
void setRoll ( float r ) { _roll = r; }
|
void setTargetPosition( const glm::vec3& t ) { _targetPosition = t; }
|
||||||
void setUpShift ( float u ) { _upShift = u; }
|
void setPosition ( const glm::vec3& p ) { _position = p; }
|
||||||
void setDistance ( float d ) { _distance = d; }
|
void setTightness ( float t ) { _tightness = t; }
|
||||||
void setTargetPosition( glm::vec3 t ) { _targetPosition = t; }
|
void setTargetRotation( const glm::quat& rotation );
|
||||||
void setTargetYaw ( float y ) { _idealYaw = y; }
|
|
||||||
void setPosition ( glm::vec3 p ) { _position = p; }
|
|
||||||
void setTightness ( float t ) { _tightness = t; }
|
|
||||||
void setTargetRotation( float yaw, float pitch, float roll );
|
|
||||||
|
|
||||||
void setMode ( CameraMode m );
|
void setMode ( CameraMode m );
|
||||||
void setModeShiftRate ( float r );
|
void setModeShiftRate ( float r );
|
||||||
void setFieldOfView ( float f );
|
void setFieldOfView ( float f );
|
||||||
void setAspectRatio ( float a );
|
void setAspectRatio ( float a );
|
||||||
void setNearClip ( float n );
|
void setNearClip ( float n );
|
||||||
void setFarClip ( float f );
|
void setFarClip ( float f );
|
||||||
void setEyeOffsetPosition ( const glm::vec3& p);
|
void setEyeOffsetPosition ( const glm::vec3& p );
|
||||||
void setEyeOffsetOrientation ( const glm::quat& o);
|
void setEyeOffsetOrientation( const glm::quat& o );
|
||||||
|
|
||||||
float getYaw () { return _yaw; }
|
const glm::vec3& getTargetPosition () { return _targetPosition; }
|
||||||
float getPitch () { return _pitch; }
|
const glm::vec3& getPosition () { return _position; }
|
||||||
float getRoll () { return _roll; }
|
const glm::quat& getTargetRotation () { return _targetRotation; }
|
||||||
glm::vec3 getPosition () { return _position; }
|
const glm::quat& getRotation () { return _rotation; }
|
||||||
Orientation getOrientation() { return _orientation; }
|
CameraMode getMode () { return _mode; }
|
||||||
CameraMode getMode () { return _mode; }
|
float getFieldOfView () { return _fieldOfView; }
|
||||||
float getFieldOfView() { return _fieldOfView; }
|
float getAspectRatio () { return _aspectRatio; }
|
||||||
float getAspectRatio() { return _aspectRatio; }
|
float getNearClip () { return _nearClip; }
|
||||||
float getNearClip () { return _nearClip; }
|
float getFarClip () { return _farClip; }
|
||||||
float getFarClip () { return _farClip; }
|
const glm::vec3& getEyeOffsetPosition () { return _eyeOffsetPosition; }
|
||||||
glm::vec3 getEyeOffsetPosition () { return _eyeOffsetPosition; }
|
const glm::quat& getEyeOffsetOrientation () { return _eyeOffsetOrientation; }
|
||||||
glm::quat getEyeOffsetOrientation () { return _eyeOffsetOrientation; }
|
|
||||||
bool getFrustumNeedsReshape(); // call to find out if the view frustum needs to be reshaped
|
bool getFrustumNeedsReshape(); // call to find out if the view frustum needs to be reshaped
|
||||||
void setFrustumWasReshaped(); // call this after reshaping the view frustum.
|
void setFrustumWasReshaped(); // call this after reshaping the view frustum.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -79,12 +75,8 @@ private:
|
||||||
float _farClip;
|
float _farClip;
|
||||||
glm::vec3 _eyeOffsetPosition;
|
glm::vec3 _eyeOffsetPosition;
|
||||||
glm::quat _eyeOffsetOrientation;
|
glm::quat _eyeOffsetOrientation;
|
||||||
float _yaw;
|
glm::quat _rotation;
|
||||||
float _pitch;
|
glm::quat _targetRotation;
|
||||||
float _roll;
|
|
||||||
float _idealYaw;
|
|
||||||
float _idealPitch;
|
|
||||||
float _idealRoll;
|
|
||||||
float _upShift;
|
float _upShift;
|
||||||
float _distance;
|
float _distance;
|
||||||
float _tightness;
|
float _tightness;
|
||||||
|
@ -94,12 +86,10 @@ private:
|
||||||
float _newUpShift;
|
float _newUpShift;
|
||||||
float _newDistance;
|
float _newDistance;
|
||||||
float _newTightness;
|
float _newTightness;
|
||||||
Orientation _orientation;
|
|
||||||
float _modeShift;
|
float _modeShift;
|
||||||
float _linearModeShift;
|
float _linearModeShift;
|
||||||
float _modeShiftRate;
|
float _modeShiftRate;
|
||||||
|
|
||||||
void generateOrientation();
|
|
||||||
void updateFollowMode( float deltaTime );
|
void updateFollowMode( float deltaTime );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,8 @@ glm::vec3 Environment::getGravity (const glm::vec3& position) {
|
||||||
foreach (const ServerData& serverData, _data) {
|
foreach (const ServerData& serverData, _data) {
|
||||||
foreach (const EnvironmentData& environmentData, serverData) {
|
foreach (const EnvironmentData& environmentData, serverData) {
|
||||||
glm::vec3 vector = environmentData.getAtmosphereCenter() - position;
|
glm::vec3 vector = environmentData.getAtmosphereCenter() - position;
|
||||||
if (glm::length(vector) < environmentData.getAtmosphereOuterRadius()) {
|
const float GRAVITY_RADIUS_MULTIPLIER = 1.5f;
|
||||||
|
if (glm::length(vector) < environmentData.getAtmosphereOuterRadius() * GRAVITY_RADIUS_MULTIPLIER) {
|
||||||
gravity += glm::normalize(vector) * environmentData.getGravity();
|
gravity += glm::normalize(vector) * environmentData.getGravity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
//
|
//
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
#include "Avatar.h"
|
||||||
#include "Head.h"
|
#include "Head.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -62,6 +64,7 @@ Head::Head(Avatar* owningAvatar) :
|
||||||
_audioAttack(0.0f),
|
_audioAttack(0.0f),
|
||||||
_returnSpringScale(1.0f),
|
_returnSpringScale(1.0f),
|
||||||
_bodyRotation(0.0f, 0.0f, 0.0f),
|
_bodyRotation(0.0f, 0.0f, 0.0f),
|
||||||
|
_lookingInMirror(false),
|
||||||
_renderLookatVectors(false),
|
_renderLookatVectors(false),
|
||||||
_mohawkTriangleFan(NULL),
|
_mohawkTriangleFan(NULL),
|
||||||
_mohawkColors(NULL)
|
_mohawkColors(NULL)
|
||||||
|
@ -84,13 +87,14 @@ void Head::reset() {
|
||||||
|
|
||||||
|
|
||||||
void Head::resetHairPhysics() {
|
void Head::resetHairPhysics() {
|
||||||
|
glm::vec3 up = getUpDirection();
|
||||||
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
|
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
|
||||||
|
|
||||||
_hairTuft[t].length = HAIR_LENGTH;
|
_hairTuft[t].length = HAIR_LENGTH;
|
||||||
_hairTuft[t].thickness = HAIR_THICKNESS;
|
_hairTuft[t].thickness = HAIR_THICKNESS;
|
||||||
_hairTuft[t].basePosition = _position + _orientation.getUp() * _scale * 0.9f;
|
_hairTuft[t].basePosition = _position + up * _scale * 0.9f;
|
||||||
_hairTuft[t].midPosition = _hairTuft[t].basePosition + _orientation.getUp() * _hairTuft[t].length * ONE_HALF;
|
_hairTuft[t].midPosition = _hairTuft[t].basePosition + up * _hairTuft[t].length * ONE_HALF;
|
||||||
_hairTuft[t].endPosition = _hairTuft[t].midPosition + _orientation.getUp() * _hairTuft[t].length * ONE_HALF;
|
_hairTuft[t].endPosition = _hairTuft[t].midPosition + up * _hairTuft[t].length * ONE_HALF;
|
||||||
_hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
_hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
_hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
_hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +160,7 @@ void Head::determineIfLookingAtSomething() {
|
||||||
_lookingAtSomething = false;
|
_lookingAtSomething = false;
|
||||||
} else {
|
} else {
|
||||||
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - caclulateAverageEyePosition());
|
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - caclulateAverageEyePosition());
|
||||||
float dot = glm::dot(targetLookatAxis, _orientation.getFront());
|
float dot = glm::dot(targetLookatAxis, getFrontDirection());
|
||||||
if (dot < MINIMUM_EYE_ROTATION_DOT) { // too far off from center for the eyes to rotate
|
if (dot < MINIMUM_EYE_ROTATION_DOT) { // too far off from center for the eyes to rotate
|
||||||
_lookingAtSomething = false;
|
_lookingAtSomething = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -165,57 +169,48 @@ void Head::determineIfLookingAtSomething() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Head::calculateGeometry(bool lookingInMirror) {
|
void Head::calculateGeometry() {
|
||||||
//generate orientation directions based on Euler angles...
|
//generate orientation directions
|
||||||
|
glm::quat orientation = getOrientation();
|
||||||
float pitch = _pitch;
|
glm::vec3 right = orientation * AVATAR_RIGHT;
|
||||||
float yaw = _yaw;
|
glm::vec3 up = orientation * AVATAR_UP;
|
||||||
float roll = _roll;
|
glm::vec3 front = orientation * AVATAR_FRONT;
|
||||||
|
|
||||||
if (lookingInMirror) {
|
|
||||||
yaw = -_yaw;
|
|
||||||
roll = -_roll;
|
|
||||||
}
|
|
||||||
|
|
||||||
_orientation.setToIdentity();
|
|
||||||
_orientation.roll (_bodyRotation.z + roll );
|
|
||||||
_orientation.pitch(_bodyRotation.x + pitch);
|
|
||||||
_orientation.yaw (_bodyRotation.y + yaw );
|
|
||||||
|
|
||||||
//calculate the eye positions
|
//calculate the eye positions
|
||||||
_leftEyePosition = _position
|
_leftEyePosition = _position
|
||||||
- _orientation.getRight() * _scale * EYE_RIGHT_OFFSET
|
- right * _scale * EYE_RIGHT_OFFSET
|
||||||
+ _orientation.getUp () * _scale * EYE_UP_OFFSET
|
+ up * _scale * EYE_UP_OFFSET
|
||||||
+ _orientation.getFront() * _scale * EYE_FRONT_OFFSET;
|
+ front * _scale * EYE_FRONT_OFFSET;
|
||||||
_rightEyePosition = _position
|
_rightEyePosition = _position
|
||||||
+ _orientation.getRight() * _scale * EYE_RIGHT_OFFSET
|
+ right * _scale * EYE_RIGHT_OFFSET
|
||||||
+ _orientation.getUp () * _scale * EYE_UP_OFFSET
|
+ up * _scale * EYE_UP_OFFSET
|
||||||
+ _orientation.getFront() * _scale * EYE_FRONT_OFFSET;
|
+ front * _scale * EYE_FRONT_OFFSET;
|
||||||
|
|
||||||
//calculate the eyebrow positions
|
//calculate the eyebrow positions
|
||||||
_leftEyeBrowPosition = _leftEyePosition;
|
_leftEyeBrowPosition = _leftEyePosition;
|
||||||
_rightEyeBrowPosition = _rightEyePosition;
|
_rightEyeBrowPosition = _rightEyePosition;
|
||||||
|
|
||||||
//calculate the ear positions
|
//calculate the ear positions
|
||||||
_leftEarPosition = _position - _orientation.getRight() * _scale * EAR_RIGHT_OFFSET;
|
_leftEarPosition = _position - right * _scale * EAR_RIGHT_OFFSET;
|
||||||
_rightEarPosition = _position + _orientation.getRight() * _scale * EAR_RIGHT_OFFSET;
|
_rightEarPosition = _position + right * _scale * EAR_RIGHT_OFFSET;
|
||||||
|
|
||||||
//calculate the mouth position
|
//calculate the mouth position
|
||||||
_mouthPosition = _position + _orientation.getUp () * _scale * MOUTH_UP_OFFSET
|
_mouthPosition = _position + up * _scale * MOUTH_UP_OFFSET
|
||||||
+ _orientation.getFront() * _scale;
|
+ front * _scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Head::render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha) {
|
void Head::render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha) {
|
||||||
|
|
||||||
_renderAlpha = alpha;
|
_renderAlpha = alpha;
|
||||||
|
_lookingInMirror = lookingInMirror;
|
||||||
|
|
||||||
calculateGeometry(lookingInMirror);
|
calculateGeometry();
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_RESCALE_NORMAL);
|
glEnable(GL_RESCALE_NORMAL);
|
||||||
|
|
||||||
renderMohawk(lookingInMirror, cameraPosition);
|
renderMohawk(cameraPosition);
|
||||||
renderHeadSphere();
|
renderHeadSphere();
|
||||||
renderEyeBalls();
|
renderEyeBalls();
|
||||||
renderEars();
|
renderEars();
|
||||||
|
@ -259,7 +254,7 @@ void Head::createMohawk() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Head::renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition) {
|
void Head::renderMohawk(glm::vec3 cameraPosition) {
|
||||||
|
|
||||||
if (!_mohawkTriangleFan) {
|
if (!_mohawkTriangleFan) {
|
||||||
createMohawk();
|
createMohawk();
|
||||||
|
@ -297,8 +292,8 @@ void Head::renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition) {
|
||||||
} else {
|
} else {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_position.x, _position.y, _position.z);
|
glTranslatef(_position.x, _position.y, _position.z);
|
||||||
glRotatef((lookingInMirror ? (_bodyRotation.y - _yaw) : (_bodyRotation.y + _yaw)), 0, 1, 0);
|
glRotatef((_lookingInMirror ? (_bodyRotation.y - _yaw) : (_bodyRotation.y + _yaw)), 0, 1, 0);
|
||||||
glRotatef(lookingInMirror ? _roll: -_roll, 0, 0, 1);
|
glRotatef(_lookingInMirror ? _roll: -_roll, 0, 0, 1);
|
||||||
glRotatef(-_pitch - _bodyRotation.x, 1, 0, 0);
|
glRotatef(-_pitch - _bodyRotation.x, 1, 0, 0);
|
||||||
|
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
@ -312,6 +307,16 @@ void Head::renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::quat Head::getOrientation() const {
|
||||||
|
return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(_lookingInMirror ?
|
||||||
|
glm::vec3(_pitch, -_yaw, -_roll) : glm::vec3(_pitch, _yaw, _roll)));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::quat Head::getWorldAlignedOrientation () const {
|
||||||
|
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);
|
||||||
|
return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(_lookingInMirror ?
|
||||||
|
glm::vec3(_pitch, -_yaw, -_roll) : glm::vec3(_pitch, _yaw, _roll)));
|
||||||
|
}
|
||||||
|
|
||||||
void Head::renderHeadSphere() {
|
void Head::renderHeadSphere() {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
@ -341,9 +346,14 @@ void Head::renderMouth() {
|
||||||
|
|
||||||
float s = sqrt(_averageLoudness);
|
float s = sqrt(_averageLoudness);
|
||||||
|
|
||||||
glm::vec3 r = _orientation.getRight() * _scale * (0.30f + s * 0.0014f );
|
glm::quat orientation = getOrientation();
|
||||||
glm::vec3 u = _orientation.getUp () * _scale * (0.05f + s * 0.0040f );
|
glm::vec3 right = orientation * AVATAR_RIGHT;
|
||||||
glm::vec3 f = _orientation.getFront() * _scale * 0.09f;
|
glm::vec3 up = orientation * AVATAR_UP;
|
||||||
|
glm::vec3 front = orientation * AVATAR_FRONT;
|
||||||
|
|
||||||
|
glm::vec3 r = right * _scale * (0.30f + s * 0.0014f );
|
||||||
|
glm::vec3 u = up * _scale * (0.05f + s * 0.0040f );
|
||||||
|
glm::vec3 f = front * _scale * 0.09f;
|
||||||
|
|
||||||
glm::vec3 middle = _mouthPosition;
|
glm::vec3 middle = _mouthPosition;
|
||||||
glm::vec3 leftCorner = _mouthPosition - r * 1.0f;
|
glm::vec3 leftCorner = _mouthPosition - r * 1.0f;
|
||||||
|
@ -403,11 +413,16 @@ void Head::renderEyeBrows() {
|
||||||
glm::vec3 rightTop = _leftEyePosition;
|
glm::vec3 rightTop = _leftEyePosition;
|
||||||
glm::vec3 leftBottom = _leftEyePosition;
|
glm::vec3 leftBottom = _leftEyePosition;
|
||||||
glm::vec3 rightBottom = _leftEyePosition;
|
glm::vec3 rightBottom = _leftEyePosition;
|
||||||
|
|
||||||
glm::vec3 r = _orientation.getRight() * length;
|
glm::quat orientation = getOrientation();
|
||||||
glm::vec3 u = _orientation.getUp() * height;
|
glm::vec3 right = orientation * AVATAR_RIGHT;
|
||||||
glm::vec3 t = _orientation.getUp() * (height + width);
|
glm::vec3 up = orientation * AVATAR_UP;
|
||||||
glm::vec3 f = _orientation.getFront() * _scale * -0.1f;
|
glm::vec3 front = orientation * AVATAR_FRONT;
|
||||||
|
|
||||||
|
glm::vec3 r = right * length;
|
||||||
|
glm::vec3 u = up * height;
|
||||||
|
glm::vec3 t = up * (height + width);
|
||||||
|
glm::vec3 f = front * _scale * -0.1f;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
|
|
||||||
|
@ -475,6 +490,8 @@ void Head::renderEyeBalls() {
|
||||||
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
|
glm::vec3 front = getFrontDirection();
|
||||||
|
|
||||||
// render left iris
|
// render left iris
|
||||||
glPushMatrix(); {
|
glPushMatrix(); {
|
||||||
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); //translate to eyeball position
|
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); //translate to eyeball position
|
||||||
|
@ -485,20 +502,20 @@ void Head::renderEyeBalls() {
|
||||||
|
|
||||||
//rotate the eyeball to aim towards the lookat position
|
//rotate the eyeball to aim towards the lookat position
|
||||||
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _leftEyePosition); // the lookat direction
|
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _leftEyePosition); // the lookat direction
|
||||||
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP);
|
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, AVATAR_UP);
|
||||||
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
float angle = 180.0f - angleBetween(targetLookatAxis, AVATAR_UP);
|
||||||
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||||
glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//rotate the eyeball to aim straight ahead
|
//rotate the eyeball to aim straight ahead
|
||||||
glm::vec3 rotationAxisToHeadFront = glm::cross(_orientation.getFront(), IDENTITY_UP);
|
glm::vec3 rotationAxisToHeadFront = glm::cross(front, AVATAR_UP);
|
||||||
float angleToHeadFront = 180.0f - angleBetween(_orientation.getFront(), IDENTITY_UP);
|
float angleToHeadFront = 180.0f - angleBetween(front, AVATAR_UP);
|
||||||
glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z);
|
glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z);
|
||||||
|
|
||||||
//set the amount of roll (for correction after previous rotations)
|
//set the amount of roll (for correction after previous rotations)
|
||||||
float rollRotation = angleBetween(_orientation.getFront(), IDENTITY_FRONT);
|
float rollRotation = angleBetween(front, AVATAR_FRONT);
|
||||||
float dot = glm::dot(_orientation.getFront(), -IDENTITY_RIGHT);
|
float dot = glm::dot(front, -AVATAR_RIGHT);
|
||||||
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
||||||
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
||||||
}
|
}
|
||||||
|
@ -529,21 +546,21 @@ void Head::renderEyeBalls() {
|
||||||
|
|
||||||
//rotate the eyeball to aim towards the lookat position
|
//rotate the eyeball to aim towards the lookat position
|
||||||
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _rightEyePosition);
|
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _rightEyePosition);
|
||||||
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP);
|
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, AVATAR_UP);
|
||||||
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
float angle = 180.0f - angleBetween(targetLookatAxis, AVATAR_UP);
|
||||||
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||||
glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//rotate the eyeball to aim straight ahead
|
//rotate the eyeball to aim straight ahead
|
||||||
glm::vec3 rotationAxisToHeadFront = glm::cross(_orientation.getFront(), IDENTITY_UP);
|
glm::vec3 rotationAxisToHeadFront = glm::cross(front, AVATAR_UP);
|
||||||
float angleToHeadFront = 180.0f - angleBetween(_orientation.getFront(), IDENTITY_UP);
|
float angleToHeadFront = 180.0f - angleBetween(front, AVATAR_UP);
|
||||||
glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z);
|
glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z);
|
||||||
|
|
||||||
//set the amount of roll (for correction after previous rotations)
|
//set the amount of roll (for correction after previous rotations)
|
||||||
float rollRotation = angleBetween(_orientation.getFront(), IDENTITY_FRONT);
|
float rollRotation = angleBetween(front, AVATAR_FRONT);
|
||||||
float dot = glm::dot(_orientation.getFront(), -IDENTITY_RIGHT);
|
float dot = glm::dot(front, -AVATAR_RIGHT);
|
||||||
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
||||||
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
||||||
}
|
}
|
||||||
|
@ -578,6 +595,11 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi
|
||||||
|
|
||||||
void Head::updateHairPhysics(float deltaTime) {
|
void Head::updateHairPhysics(float deltaTime) {
|
||||||
|
|
||||||
|
glm::quat orientation = getOrientation();
|
||||||
|
glm::vec3 right = orientation * AVATAR_RIGHT;
|
||||||
|
glm::vec3 up = orientation * AVATAR_UP;
|
||||||
|
glm::vec3 front = orientation * AVATAR_FRONT;
|
||||||
|
|
||||||
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
|
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
|
||||||
|
|
||||||
float fraction = (float)t / (float)(NUM_HAIR_TUFTS - 1);
|
float fraction = (float)t / (float)(NUM_HAIR_TUFTS - 1);
|
||||||
|
@ -586,8 +608,8 @@ void Head::updateHairPhysics(float deltaTime) {
|
||||||
|
|
||||||
float radian = angle * PI_OVER_180;
|
float radian = angle * PI_OVER_180;
|
||||||
glm::vec3 baseDirection
|
glm::vec3 baseDirection
|
||||||
= _orientation.getFront() * sinf(radian)
|
= front * sinf(radian)
|
||||||
+ _orientation.getUp() * cosf(radian);
|
+ up * cosf(radian);
|
||||||
|
|
||||||
_hairTuft[t].basePosition = _position + _scale * 0.9f * baseDirection;
|
_hairTuft[t].basePosition = _position + _scale * 0.9f * baseDirection;
|
||||||
|
|
||||||
|
@ -603,13 +625,13 @@ void Head::updateHairPhysics(float deltaTime) {
|
||||||
if (midLength > 0.0f) {
|
if (midLength > 0.0f) {
|
||||||
midDirection = midAxis / midLength;
|
midDirection = midAxis / midLength;
|
||||||
} else {
|
} else {
|
||||||
midDirection = _orientation.getUp();
|
midDirection = up;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endLength > 0.0f) {
|
if (endLength > 0.0f) {
|
||||||
endDirection = endAxis / endLength;
|
endDirection = endAxis / endLength;
|
||||||
} else {
|
} else {
|
||||||
endDirection = _orientation.getUp();
|
endDirection = up;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add spring force
|
// add spring force
|
||||||
|
@ -654,13 +676,13 @@ void Head::updateHairPhysics(float deltaTime) {
|
||||||
if (newMidLength > 0.0f) {
|
if (newMidLength > 0.0f) {
|
||||||
newMidDirection = newMidVector/newMidLength;
|
newMidDirection = newMidVector/newMidLength;
|
||||||
} else {
|
} else {
|
||||||
newMidDirection = _orientation.getUp();
|
newMidDirection = up;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newEndLength > 0.0f) {
|
if (newEndLength > 0.0f) {
|
||||||
newEndDirection = newEndVector/newEndLength;
|
newEndDirection = newEndVector/newEndLength;
|
||||||
} else {
|
} else {
|
||||||
newEndDirection = _orientation.getUp();
|
newEndDirection = up;
|
||||||
}
|
}
|
||||||
|
|
||||||
_hairTuft[t].endPosition = _hairTuft[t].midPosition + newEndDirection * _hairTuft[t].length * ONE_HALF;
|
_hairTuft[t].endPosition = _hairTuft[t].midPosition + newEndDirection * _hairTuft[t].length * ONE_HALF;
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "SerialInterface.h"
|
#include "SerialInterface.h"
|
||||||
#include "Orientation.h"
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
enum eyeContactTargets
|
enum eyeContactTargets
|
||||||
|
@ -35,7 +34,7 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
void simulate(float deltaTime, bool isMine);
|
void simulate(float deltaTime, bool isMine);
|
||||||
void render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha);
|
void render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha);
|
||||||
void renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition);
|
void renderMohawk(glm::vec3 cameraPosition);
|
||||||
|
|
||||||
void setScale (float scale ) { _scale = scale; }
|
void setScale (float scale ) { _scale = scale; }
|
||||||
void setPosition (glm::vec3 position ) { _position = position; }
|
void setPosition (glm::vec3 position ) { _position = position; }
|
||||||
|
@ -46,7 +45,14 @@ public:
|
||||||
void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; }
|
void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; }
|
||||||
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
|
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
|
||||||
void setRenderLookatVectors(bool onOff ) { _renderLookatVectors = onOff; }
|
void setRenderLookatVectors(bool onOff ) { _renderLookatVectors = onOff; }
|
||||||
|
|
||||||
|
glm::quat getOrientation() const;
|
||||||
|
glm::quat getWorldAlignedOrientation () const;
|
||||||
|
|
||||||
|
glm::vec3 getRightDirection() const { return getOrientation() * AVATAR_RIGHT; }
|
||||||
|
glm::vec3 getUpDirection () const { return getOrientation() * AVATAR_UP; }
|
||||||
|
glm::vec3 getFrontDirection() const { return getOrientation() * AVATAR_FRONT; }
|
||||||
|
|
||||||
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
|
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
|
||||||
float getAverageLoudness() {return _averageLoudness;};
|
float getAverageLoudness() {return _averageLoudness;};
|
||||||
glm::vec3 caclulateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; }
|
glm::vec3 caclulateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; }
|
||||||
|
@ -91,8 +97,8 @@ private:
|
||||||
float _averageLoudness;
|
float _averageLoudness;
|
||||||
float _audioAttack;
|
float _audioAttack;
|
||||||
float _returnSpringScale; //strength of return springs
|
float _returnSpringScale; //strength of return springs
|
||||||
Orientation _orientation;
|
|
||||||
glm::vec3 _bodyRotation;
|
glm::vec3 _bodyRotation;
|
||||||
|
bool _lookingInMirror;
|
||||||
bool _renderLookatVectors;
|
bool _renderLookatVectors;
|
||||||
HairTuft _hairTuft[NUM_HAIR_TUFTS];
|
HairTuft _hairTuft[NUM_HAIR_TUFTS];
|
||||||
glm::vec3* _mohawkTriangleFan;
|
glm::vec3* _mohawkTriangleFan;
|
||||||
|
@ -106,7 +112,7 @@ private:
|
||||||
void renderEars();
|
void renderEars();
|
||||||
void renderMouth();
|
void renderMouth();
|
||||||
void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition);
|
||||||
void calculateGeometry( bool lookingInMirror);
|
void calculateGeometry();
|
||||||
void determineIfLookingAtSomething();
|
void determineIfLookingAtSomething();
|
||||||
void resetHairPhysics();
|
void resetHairPhysics();
|
||||||
void updateHairPhysics(float deltaTime);
|
void updateHairPhysics(float deltaTime);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/noise.hpp>
|
#include <glm/gtc/noise.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
@ -71,6 +72,65 @@ float angleBetween(const glm::vec3& v1, const glm::vec3& v2) {
|
||||||
return acos((glm::dot(v1, v2)) / (glm::length(v1) * glm::length(v2))) * 180.f / PI;
|
return acos((glm::dot(v1, v2)) / (glm::length(v1) * glm::length(v2))) * 180.f / PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's
|
||||||
|
// http://www.geometrictools.com/Documentation/EulerAngles.pdf (via Clyde,
|
||||||
|
// https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java)
|
||||||
|
glm::vec3 safeEulerAngles(const glm::quat& q) {
|
||||||
|
float sy = 2.0f * (q.y * q.w - q.x * q.z);
|
||||||
|
if (sy < 1.0f - EPSILON) {
|
||||||
|
if (sy > -1.0f + EPSILON) {
|
||||||
|
return glm::degrees(glm::vec3(
|
||||||
|
atan2f(q.y * q.z + q.x * q.w, 0.5f - (q.x * q.x + q.y * q.y)),
|
||||||
|
asinf(sy),
|
||||||
|
atan2f(q.x * q.y + q.z * q.w, 0.5f - (q.y * q.y + q.z * q.z))));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// not a unique solution; x + z = atan2(-m21, m11)
|
||||||
|
return glm::degrees(glm::vec3(
|
||||||
|
0.0f,
|
||||||
|
PIf * -0.5f,
|
||||||
|
atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z))));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not a unique solution; x - z = atan2(-m21, m11)
|
||||||
|
return glm::degrees(glm::vec3(
|
||||||
|
0.0f,
|
||||||
|
PIf * 0.5f,
|
||||||
|
-atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe version of glm::mix; based on the code in Nick Bobick's article,
|
||||||
|
// http://www.gamasutra.com/features/19980703/quaternions_01.htm (via Clyde,
|
||||||
|
// https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java)
|
||||||
|
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
|
||||||
|
float cosa = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
|
||||||
|
float ox = q2.x, oy = q2.y, oz = q2.z, ow = q2.w, s0, s1;
|
||||||
|
|
||||||
|
// adjust signs if necessary
|
||||||
|
if (cosa < 0.0f) {
|
||||||
|
cosa = -cosa;
|
||||||
|
ox = -ox;
|
||||||
|
oy = -oy;
|
||||||
|
oz = -oz;
|
||||||
|
ow = -ow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate coefficients; if the angle is too close to zero, we must fall back
|
||||||
|
// to linear interpolation
|
||||||
|
if ((1.0f - cosa) > EPSILON) {
|
||||||
|
float angle = acosf(cosa), sina = sinf(angle);
|
||||||
|
s0 = sinf((1.0f - proportion) * angle) / sina;
|
||||||
|
s1 = sinf(proportion * angle) / sina;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
s0 = 1.0f - proportion;
|
||||||
|
s1 = proportion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return glm::normalize(glm::quat(s0 * q1.w + s1 * ow, s0 * q1.x + s1 * ox, s0 * q1.y + s1 * oy, s0 * q1.z + s1 * oz));
|
||||||
|
}
|
||||||
|
|
||||||
// Draw a 3D vector floating in space
|
// Draw a 3D vector floating in space
|
||||||
void drawVector(glm::vec3 * vector) {
|
void drawVector(glm::vec3 * vector) {
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
|
|
|
@ -46,6 +46,10 @@ void drawVector(glm::vec3* vector);
|
||||||
|
|
||||||
float angleBetween(const glm::vec3& v1, const glm::vec3& v2);
|
float angleBetween(const glm::vec3& v1, const glm::vec3& v2);
|
||||||
|
|
||||||
|
glm::vec3 safeEulerAngles(const glm::quat& q);
|
||||||
|
|
||||||
|
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha);
|
||||||
|
|
||||||
double diffclock(timeval *clock1,timeval *clock2);
|
double diffclock(timeval *clock1,timeval *clock2);
|
||||||
|
|
||||||
void drawGroundPlaneGrid(float size);
|
void drawGroundPlaneGrid(float size);
|
||||||
|
|
|
@ -20,6 +20,11 @@ const int WANT_RESIN_AT_BIT = 0;
|
||||||
const int WANT_COLOR_AT_BIT = 1;
|
const int WANT_COLOR_AT_BIT = 1;
|
||||||
const int WANT_DELTA_AT_BIT = 2;
|
const int WANT_DELTA_AT_BIT = 2;
|
||||||
|
|
||||||
|
// this is where the coordinate system is represented
|
||||||
|
const glm::vec3 AVATAR_RIGHT = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
|
const glm::vec3 AVATAR_UP = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
const glm::vec3 AVATAR_FRONT = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
|
||||||
enum KeyState
|
enum KeyState
|
||||||
{
|
{
|
||||||
NO_KEY_DOWN,
|
NO_KEY_DOWN,
|
||||||
|
|
Loading…
Reference in a new issue