committing latest skeleton-separation changes (more to come as Andrzej and I work on it more)

This commit is contained in:
Jeffrey Ventrella 2013-05-31 11:51:03 -07:00
parent 885cd951ce
commit 108ce62d1a
5 changed files with 360 additions and 300 deletions

View file

@ -107,7 +107,11 @@ Avatar::Avatar(Agent* owningAgent) :
_driveKeys[i] = false;
}
initializeSkeleton();
_skeleton.initialize();
_maxArmLength = _skeleton.getArmLength();
_pelvisStandingHeight = _skeleton.getPelvisStandingHeight();
_pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight();
_avatarTouch.setReachableRadius(PERIPERSONAL_RADIUS);
@ -218,10 +222,20 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
// update balls
if (_balls) { _balls->simulate(deltaTime); }
// if other avatar, update head position from network data
// create orientation directions based on yaw/pitch/roll...
_orientation.setToIdentity();
_orientation.yaw (_bodyYaw );
_orientation.pitch(_bodyPitch);
_orientation.roll (_bodyRoll );
_orientation.rotate(_righting);
// update avatar skeleton
updateSkeleton();
_skeleton.update(deltaTime, _orientation, _position);
// if this is not my avatar, then hand position comes from transmitted data
if (_owningAgent) {
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition;
}
//detect and respond to collisions with other avatars...
if (!_owningAgent) {
@ -405,22 +419,22 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
_orientation.getRight() * _head.getLeanSideways() +
_orientation.getFront() * _head.getLeanForward();
_joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f;
_joint[ AVATAR_JOINT_CHEST ].springyPosition += headLean * 0.4f;
_joint[ AVATAR_JOINT_NECK_BASE ].springyPosition += headLean * 0.7f;
_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition += headLean * 1.0f;
_skeleton.joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f;
_skeleton.joint[ AVATAR_JOINT_CHEST ].springyPosition += headLean * 0.4f;
_skeleton.joint[ AVATAR_JOINT_NECK_BASE ].springyPosition += headLean * 0.7f;
_skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition += headLean * 1.0f;
_joint[ AVATAR_JOINT_LEFT_COLLAR ].springyPosition += headLean * 0.6f;
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].springyPosition += headLean * 0.6f;
_joint[ AVATAR_JOINT_LEFT_ELBOW ].springyPosition += headLean * 0.2f;
_joint[ AVATAR_JOINT_LEFT_WRIST ].springyPosition += headLean * 0.1f;
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].springyPosition += headLean * 0.0f;
_skeleton.joint[ AVATAR_JOINT_LEFT_COLLAR ].springyPosition += headLean * 0.6f;
_skeleton.joint[ AVATAR_JOINT_LEFT_SHOULDER ].springyPosition += headLean * 0.6f;
_skeleton.joint[ AVATAR_JOINT_LEFT_ELBOW ].springyPosition += headLean * 0.2f;
_skeleton.joint[ AVATAR_JOINT_LEFT_WRIST ].springyPosition += headLean * 0.1f;
_skeleton.joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].springyPosition += headLean * 0.0f;
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].springyPosition += headLean * 0.6f;
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].springyPosition += headLean * 0.6f;
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].springyPosition += headLean * 0.2f;
_joint[ AVATAR_JOINT_RIGHT_WRIST ].springyPosition += headLean * 0.1f;
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition += headLean * 0.0f;
_skeleton.joint[ AVATAR_JOINT_RIGHT_COLLAR ].springyPosition += headLean * 0.6f;
_skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].springyPosition += headLean * 0.6f;
_skeleton.joint[ AVATAR_JOINT_RIGHT_ELBOW ].springyPosition += headLean * 0.2f;
_skeleton.joint[ AVATAR_JOINT_RIGHT_WRIST ].springyPosition += headLean * 0.1f;
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition += headLean * 0.0f;
}
}
@ -434,8 +448,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
}
_head.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
_head.setPosition(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
_head.setScale (_joint[ AVATAR_JOINT_HEAD_BASE ].radius);
_head.setPosition(_skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
_head.setScale (_skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].radius);
_head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]));
_head.simulate(deltaTime, !_owningAgent);
@ -451,15 +465,15 @@ void Avatar::checkForMouseRayTouching() {
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
glm::vec3 directionToBodySphere = glm::normalize(_joint[b].springyPosition - _mouseRayOrigin);
glm::vec3 directionToBodySphere = glm::normalize(_skeleton.joint[b].springyPosition - _mouseRayOrigin);
float dot = glm::dot(directionToBodySphere, _mouseRayDirection);
float range = _joint[b].radius * JOINT_TOUCH_RANGE;
float range = _skeleton.joint[b].radius * JOINT_TOUCH_RANGE;
if (dot > (1.0f - range)) {
_joint[b].touchForce = (dot - (1.0f - range)) / range;
_skeleton.joint[b].touchForce = (dot - (1.0f - range)) / range;
} else {
_joint[b].touchForce = 0.0;
_skeleton.joint[b].touchForce = 0.0;
}
}
}
@ -477,7 +491,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
+ _orientation.getUp() * -_movedHandOffset.y * 2.0f
+ _orientation.getFront() * -_movedHandOffset.y * 2.0f;
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement;
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement;
if (!_owningAgent) {
_avatarTouch.setMyBodyPosition(_position);
@ -516,7 +530,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
_avatarTouch.setHasInteractingOther(true);
_avatarTouch.setYourBodyPosition(_interactingOther->_position);
_avatarTouch.setYourOrientation (_interactingOther->_orientation);
_avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
_avatarTouch.setYourHandPosition(_interactingOther->_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
_avatarTouch.setYourHandState (_interactingOther->_handState);
//if hand-holding is initiated by either avatar, turn on hand-holding...
@ -531,8 +545,8 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
glm::vec3 vectorFromMyHandToYourHand
(
_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position -
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position
_interactingOther->_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position -
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position
);
float distanceBetweenOurHands = glm::length(vectorFromMyHandToYourHand);
@ -554,10 +568,10 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
//if holding hands, apply the appropriate forces
if (_avatarTouch.getHoldingHands()) {
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position +=
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position +=
(
_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position
- _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position
_interactingOther->_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position
- _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position
) * 0.5f;
if (distanceBetweenOurHands > 0.3) {
@ -577,7 +591,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
//Set right hand position and state to be transmitted, and also tell AvatarTouch about it
if (!_owningAgent) {
setHandPosition(_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position);
setHandPosition(_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position);
if (_mousePressed) {
_handState = HAND_STATE_GRASPING;
@ -586,7 +600,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
}
_avatarTouch.setMyHandState(_handState);
_avatarTouch.setMyHandPosition(_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
_avatarTouch.setMyHandPosition(_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
}
}
@ -598,9 +612,9 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d
float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere);
if (distanceToBigSphere < myBodyApproximateBoundingRadius + radius) {
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
glm::vec3 vectorFromJointToBigSphereCenter(_joint[b].springyPosition - position);
glm::vec3 vectorFromJointToBigSphereCenter(_skeleton.joint[b].springyPosition - position);
float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter);
float combinedRadius = _joint[b].radius + radius;
float combinedRadius = _skeleton.joint[b].radius + radius;
if (distanceToBigSphereCenter < combinedRadius) {
jointCollision = true;
@ -610,9 +624,9 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d
float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius);
glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration;
_joint[b].springyVelocity += collisionForce * 0.0f * deltaTime;
_skeleton.joint[b].springyVelocity += collisionForce * 0.0f * deltaTime;
_velocity += collisionForce * 40.0f * deltaTime;
_joint[b].springyPosition = position + directionVector * combinedRadius;
_skeleton.joint[b].springyPosition = position + directionVector * combinedRadius;
}
}
}
@ -669,7 +683,7 @@ void Avatar::updateAvatarCollisions(float deltaTime) {
}
// test other avatar hand position for proximity
glm::vec3 v(_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position);
glm::vec3 v(_skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position);
v -= otherAvatar->getPosition();
float distance = glm::length(v);
@ -688,16 +702,16 @@ void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime
// loop through the joints of each avatar to check for every possible collision
for (int b=1; b<NUM_AVATAR_JOINTS; b++) {
if (_joint[b].isCollidable) {
if (_skeleton.joint[b].isCollidable) {
for (int o=b+1; o<NUM_AVATAR_JOINTS; o++) {
if (otherAvatar->_joint[o].isCollidable) {
if (otherAvatar->_skeleton.joint[o].isCollidable) {
glm::vec3 vectorBetweenJoints(_joint[b].springyPosition - otherAvatar->_joint[o].springyPosition);
glm::vec3 vectorBetweenJoints(_skeleton.joint[b].springyPosition - otherAvatar->_skeleton.joint[o].springyPosition);
float distanceBetweenJoints = glm::length(vectorBetweenJoints);
if (distanceBetweenJoints > 0.0) { // to avoid divide by zero
float combinedRadius = _joint[b].radius + otherAvatar->_joint[o].radius;
float combinedRadius = _skeleton.joint[b].radius + otherAvatar->_skeleton.joint[o].radius;
// check for collision
if (distanceBetweenJoints < combinedRadius * COLLISION_RADIUS_SCALAR) {
@ -715,21 +729,21 @@ void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime
if (ballMomentum < 0.0) { ballMomentum = 0.0;}
*/
_joint[b].springyVelocity += ballPushForce;
otherAvatar->_joint[o].springyVelocity -= ballPushForce;
_skeleton.joint[b].springyVelocity += ballPushForce;
otherAvatar->_skeleton.joint[o].springyVelocity -= ballPushForce;
/*
float shift = distanceBetweenJoints - combinedRadius * COLLISION_RADIUS_SCALAR;
_joint[b].springyPosition += directionVector * 2.0f * deltaTime;
otherAvatar->_joint[o].springyPosition -= directionVector * 2.0f * deltaTime;
_skeleton.joint[b].springyPosition += directionVector * 2.0f * deltaTime;
otherAvatar->_skeleton.joint[o].springyPosition -= directionVector * 2.0f * deltaTime;
*/
/*
_joint[b].springyVelocity *= ballMomentum;
otherAvatar->_joint[o].springyVelocity *= ballMomentum;
_skeleton.joint[b].springyVelocity *= ballMomentum;
otherAvatar->_skeleton.joint[o].springyVelocity *= ballMomentum;
*/
// accumulate forces and frictions to apply to the velocities of avatar bodies
@ -810,9 +824,9 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
float modelview[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
glTranslatef(_joint[AVATAR_JOINT_HEAD_BASE].springyPosition.x,
_joint[AVATAR_JOINT_HEAD_BASE].springyPosition.y + chatMessageHeight,
_joint[AVATAR_JOINT_HEAD_BASE].springyPosition.z);
glTranslatef(_skeleton.joint[AVATAR_JOINT_HEAD_BASE].springyPosition.x,
_skeleton.joint[AVATAR_JOINT_HEAD_BASE].springyPosition.y + chatMessageHeight,
_skeleton.joint[AVATAR_JOINT_HEAD_BASE].springyPosition.z);
glRotatef(atan2(-modelview[2], -modelview[10]) * 180 / PI, 0, 1, 0);
glColor3f(0, 0.8, 0);
@ -842,219 +856,20 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
}
}
void Avatar::initializeSkeleton() {
for (int b=0; b<NUM_AVATAR_JOINTS; b++) {
_joint[b].isCollidable = true;
_joint[b].parent = AVATAR_JOINT_NULL;
_joint[b].position = 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].springyVelocity = glm::vec3(0.0, 0.0, 0.0);
_joint[b].rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
_joint[b].yaw = 0.0;
_joint[b].pitch = 0.0;
_joint[b].roll = 0.0;
_joint[b].length = 0.0;
_joint[b].radius = 0.0;
_joint[b].touchForce = 0.0;
_joint[b].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[b].orientation.setToIdentity();
}
// specify the parental hierarchy
_joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL;
_joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS;
_joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO;
_joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST;
_joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE;
_joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE;
_joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST;
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR;
_joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER;
_joint[ AVATAR_JOINT_LEFT_WRIST ].parent = AVATAR_JOINT_LEFT_ELBOW;
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].parent = AVATAR_JOINT_LEFT_WRIST;
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].parent = AVATAR_JOINT_CHEST;
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].parent = AVATAR_JOINT_RIGHT_COLLAR;
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].parent = AVATAR_JOINT_RIGHT_SHOULDER;
_joint[ AVATAR_JOINT_RIGHT_WRIST ].parent = AVATAR_JOINT_RIGHT_ELBOW;
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].parent = AVATAR_JOINT_RIGHT_WRIST;
_joint[ AVATAR_JOINT_LEFT_HIP ].parent = AVATAR_JOINT_PELVIS;
_joint[ AVATAR_JOINT_LEFT_KNEE ].parent = AVATAR_JOINT_LEFT_HIP;
_joint[ AVATAR_JOINT_LEFT_HEEL ].parent = AVATAR_JOINT_LEFT_KNEE;
_joint[ AVATAR_JOINT_LEFT_TOES ].parent = AVATAR_JOINT_LEFT_HEEL;
_joint[ AVATAR_JOINT_RIGHT_HIP ].parent = AVATAR_JOINT_PELVIS;
_joint[ AVATAR_JOINT_RIGHT_KNEE ].parent = AVATAR_JOINT_RIGHT_HIP;
_joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE;
_joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL;
// specify the default pose position
_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_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_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_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_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_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_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_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_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_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_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_TOES ].defaultPosePosition = glm::vec3( -0.00, -0.03, 0.05 );
// specify the radii of the joints
_joint[ AVATAR_JOINT_PELVIS ].radius = 0.07;
_joint[ AVATAR_JOINT_TORSO ].radius = 0.065;
_joint[ AVATAR_JOINT_CHEST ].radius = 0.08;
_joint[ AVATAR_JOINT_NECK_BASE ].radius = 0.03;
_joint[ AVATAR_JOINT_HEAD_BASE ].radius = 0.07;
_joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.04;
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.03;
_joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.02;
_joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.02;
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01;
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.04;
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.03;
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.02;
_joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.02;
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].radius = 0.01;
_joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.04;
_joint[ AVATAR_JOINT_LEFT_KNEE ].radius = 0.025;
_joint[ AVATAR_JOINT_LEFT_HEEL ].radius = 0.025;
_joint[ AVATAR_JOINT_LEFT_TOES ].radius = 0.025;
_joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.04;
_joint[ AVATAR_JOINT_RIGHT_KNEE ].radius = 0.025;
_joint[ AVATAR_JOINT_RIGHT_HEEL ].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
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].isCollidable = false;
_joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false;
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].isCollidable = false;
// calculate bone length
calculateBoneLengths();
_pelvisStandingHeight =
_joint[ AVATAR_JOINT_LEFT_HEEL ].radius +
_joint[ AVATAR_JOINT_LEFT_HEEL ].length +
_joint[ AVATAR_JOINT_LEFT_KNEE ].length;
//printf("_pelvisStandingHeight = %f\n", _pelvisStandingHeight);
_pelvisFloatingHeight = _pelvisStandingHeight + FLOATING_HEIGHT;
_height =
(
_pelvisStandingHeight +
_joint[ AVATAR_JOINT_LEFT_HEEL ].radius +
_joint[ AVATAR_JOINT_LEFT_HEEL ].length +
_joint[ AVATAR_JOINT_LEFT_KNEE ].length +
_joint[ AVATAR_JOINT_PELVIS ].length +
_joint[ AVATAR_JOINT_TORSO ].length +
_joint[ AVATAR_JOINT_CHEST ].length +
_joint[ AVATAR_JOINT_NECK_BASE ].length +
_joint[ AVATAR_JOINT_HEAD_BASE ].length +
_joint[ AVATAR_JOINT_HEAD_BASE ].radius
);
//printf("_height = %f\n", _height);
// generate joint positions by updating the skeleton
updateSkeleton();
//set spring positions to be in the skeleton bone positions
initializeBodySprings();
}
void Avatar::calculateBoneLengths() {
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
_joint[b].length = glm::length(_joint[b].defaultPosePosition);
}
_maxArmLength
= _joint[ AVATAR_JOINT_RIGHT_ELBOW ].length
+ _joint[ AVATAR_JOINT_RIGHT_WRIST ].length
+ _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].length;
}
void Avatar::updateSkeleton() {
// rotate body...
_orientation.setToIdentity();
_orientation.yaw (_bodyYaw );
_orientation.pitch(_bodyPitch);
_orientation.roll (_bodyRoll );
_orientation.rotate(_righting);
// calculate positions of all bones by traversing the skeleton tree:
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
if (_joint[b].parent == AVATAR_JOINT_NULL) {
_joint[b].orientation.set(_orientation);
_joint[b].position = _position;
}
else {
_joint[b].orientation.set(_joint[ _joint[b].parent ].orientation);
_joint[b].position = _joint[ _joint[b].parent ].position;
}
// if this is not my avatar, then hand position comes from transmitted data
if (_owningAgent) {
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition;
}
// the following will be replaced by a proper rotation...close
float xx = glm::dot(_joint[b].defaultPosePosition, _joint[b].orientation.getRight());
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::quat myQuat (myEuler);
_joint[b].position += rotatedJointVector;
}
}
void Avatar::initializeBodySprings() {
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
_joint[b].springyPosition = _joint[b].position;
_joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
}
}
void Avatar::updateBodySprings(float deltaTime) {
// Check for a large repositioning, and re-initialize body springs if this has happened
const float BEYOND_BODY_SPRING_RANGE = 2.f;
if (glm::length(_position - _joint[AVATAR_JOINT_PELVIS].springyPosition) > BEYOND_BODY_SPRING_RANGE) {
initializeBodySprings();
if (glm::length(_position - _skeleton.joint[AVATAR_JOINT_PELVIS].springyPosition) > BEYOND_BODY_SPRING_RANGE) {
_skeleton.initializeBodySprings();
}
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
glm::vec3 springVector(_joint[b].springyPosition);
glm::vec3 springVector(_skeleton.joint[b].springyPosition);
if (_joint[b].parent == AVATAR_JOINT_NULL) {
if (_skeleton.joint[b].parent == AVATAR_JOINT_NULL) {
springVector -= _position;
}
else {
springVector -= _joint[ _joint[b].parent ].springyPosition;
springVector -= _skeleton.joint[ _skeleton.joint[b].parent ].springyPosition;
}
float length = glm::length(springVector);
@ -1062,44 +877,44 @@ void Avatar::updateBodySprings(float deltaTime) {
if (length > 0.0f) { // to avoid divide by zero
glm::vec3 springDirection = springVector / length;
float force = (length - _joint[b].length) * BODY_SPRING_FORCE * deltaTime;
float force = (length - _skeleton.joint[b].length) * BODY_SPRING_FORCE * deltaTime;
_joint[b].springyVelocity -= springDirection * force;
_skeleton.joint[b].springyVelocity -= springDirection * force;
if (_joint[b].parent != AVATAR_JOINT_NULL) {
_joint[_joint[b].parent].springyVelocity += springDirection * force;
if (_skeleton.joint[b].parent != AVATAR_JOINT_NULL) {
_skeleton.joint[_skeleton.joint[b].parent].springyVelocity += springDirection * force;
}
}
// 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;
_skeleton.joint[b].springyVelocity += (_skeleton.joint[b].position - _skeleton.joint[b].springyPosition) * _skeleton.joint[b].springBodyTightness * deltaTime;
// apply decay
float decay = 1.0 - BODY_SPRING_DECAY * deltaTime;
if (decay > 0.0) {
_joint[b].springyVelocity *= decay;
_skeleton.joint[b].springyVelocity *= decay;
}
else {
_joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
_skeleton.joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
}
/*
//apply forces from touch...
if (_joint[b].touchForce > 0.0) {
_joint[b].springyVelocity += _mouseRayDirection * _joint[b].touchForce * 0.7f;
if (_skeleton.joint[b].touchForce > 0.0) {
_skeleton.joint[b].springyVelocity += _mouseRayDirection * _skeleton.joint[b].touchForce * 0.7f;
}
*/
//update position by velocity...
_joint[b].springyPosition += _joint[b].springyVelocity * deltaTime;
_skeleton.joint[b].springyPosition += _skeleton.joint[b].springyVelocity * deltaTime;
}
}
void Avatar::updateArmIKAndConstraints(float deltaTime) {
// determine the arm vector
glm::vec3 armVector = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position;
armVector -= _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
glm::vec3 armVector = _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position;
armVector -= _skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
// test to see if right hand is being dragged beyond maximum arm length
float distance = glm::length(armVector);
@ -1107,28 +922,28 @@ void Avatar::updateArmIKAndConstraints(float deltaTime) {
// don't let right hand get dragged beyond maximum arm length...
if (distance > _maxArmLength) {
// reset right hand to be constrained to maximum arm length
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
glm::vec3 armNormal = armVector / distance;
armVector = armNormal * _maxArmLength;
distance = _maxArmLength;
glm::vec3 constrainedPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
glm::vec3 constrainedPosition = _skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position;
constrainedPosition += armVector;
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = constrainedPosition;
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = constrainedPosition;
}
// set elbow position
glm::vec3 newElbowPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position + armVector * ONE_HALF;
glm::vec3 newElbowPosition = _skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position + armVector * ONE_HALF;
glm::vec3 perpendicular = glm::cross( _orientation.getRight(), armVector);
newElbowPosition += perpendicular * (1.0f - (_maxArmLength / distance)) * ONE_HALF;
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].position = newElbowPosition;
_skeleton.joint[ AVATAR_JOINT_RIGHT_ELBOW ].position = newElbowPosition;
// set wrist position
glm::vec3 vv(_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position);
vv -= _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position;
glm::vec3 newWristPosition = _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position + vv * 0.7f;
_joint[ AVATAR_JOINT_RIGHT_WRIST ].position = newWristPosition;
glm::vec3 vv(_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position);
vv -= _skeleton.joint[ AVATAR_JOINT_RIGHT_ELBOW ].position;
glm::vec3 newWristPosition = _skeleton.joint[ AVATAR_JOINT_RIGHT_ELBOW ].position + vv * 0.7f;
_skeleton.joint[ AVATAR_JOINT_RIGHT_WRIST ].position = newWristPosition;
}
@ -1139,7 +954,7 @@ void Avatar::renderBody(bool lookingInMirror) {
// Render the body as balls and cones
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
float distanceToCamera = glm::length(_cameraPosition - _joint[b].position);
float distanceToCamera = glm::length(_cameraPosition - _skeleton.joint[b].position);
float alpha = glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f);
@ -1160,26 +975,26 @@ void Avatar::renderBody(bool lookingInMirror) {
if (_owningAgent || b == AVATAR_JOINT_RIGHT_ELBOW
|| b == AVATAR_JOINT_RIGHT_WRIST
|| b == AVATAR_JOINT_RIGHT_FINGERTIPS ) {
glColor3f(SKIN_COLOR[0] + _joint[b].touchForce * 0.3f,
SKIN_COLOR[1] - _joint[b].touchForce * 0.2f,
SKIN_COLOR[2] - _joint[b].touchForce * 0.1f);
glColor3f(SKIN_COLOR[0] + _skeleton.joint[b].touchForce * 0.3f,
SKIN_COLOR[1] - _skeleton.joint[b].touchForce * 0.2f,
SKIN_COLOR[2] - _skeleton.joint[b].touchForce * 0.1f);
} else {
glColor4f(SKIN_COLOR[0] + _joint[b].touchForce * 0.3f,
SKIN_COLOR[1] - _joint[b].touchForce * 0.2f,
SKIN_COLOR[2] - _joint[b].touchForce * 0.1f,
glColor4f(SKIN_COLOR[0] + _skeleton.joint[b].touchForce * 0.3f,
SKIN_COLOR[1] - _skeleton.joint[b].touchForce * 0.2f,
SKIN_COLOR[2] - _skeleton.joint[b].touchForce * 0.1f,
alpha);
}
if ((b != AVATAR_JOINT_HEAD_TOP )
&& (b != AVATAR_JOINT_HEAD_BASE )) {
glPushMatrix();
glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z);
glutSolidSphere(_joint[b].radius, 20.0f, 20.0f);
glTranslatef(_skeleton.joint[b].springyPosition.x, _skeleton.joint[b].springyPosition.y, _skeleton.joint[b].springyPosition.z);
glutSolidSphere(_skeleton.joint[b].radius, 20.0f, 20.0f);
glPopMatrix();
}
// Render the cone connecting this joint to its parent
if (_joint[b].parent != AVATAR_JOINT_NULL) {
if (_skeleton.joint[b].parent != AVATAR_JOINT_NULL) {
if ((b != AVATAR_JOINT_HEAD_TOP )
&& (b != AVATAR_JOINT_HEAD_BASE )
&& (b != AVATAR_JOINT_PELVIS )
@ -1191,15 +1006,15 @@ void Avatar::renderBody(bool lookingInMirror) {
&& (b != AVATAR_JOINT_RIGHT_SHOULDER)) {
glColor3fv(DARK_SKIN_COLOR);
float r1 = _joint[_joint[b].parent ].radius * 0.8;
float r2 = _joint[b ].radius * 0.8;
float r1 = _skeleton.joint[_skeleton.joint[b].parent ].radius * 0.8;
float r2 = _skeleton.joint[b ].radius * 0.8;
if (b == AVATAR_JOINT_HEAD_BASE) {
r1 *= 0.5f;
}
renderJointConnectingCone
(
_joint[_joint[b].parent ].springyPosition,
_joint[b ].springyPosition, r2, r2
_skeleton.joint[_skeleton.joint[b].parent ].springyPosition,
_skeleton.joint[b ].springyPosition, r2, r2
);
}
}

View file

@ -67,9 +67,9 @@ public:
float getHeadYawRate () const { return _head.yawRate;}
float getBodyYaw () const { return _bodyYaw;}
bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();}
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& getJointPosition (AvatarJointID j) const { return _joint[j].springyPosition;}
const glm::vec3& getHeadPosition () const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;}
const glm::vec3& getSpringyHeadPosition () const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition;}
const glm::vec3& getJointPosition (AvatarJointID j) const { return _skeleton.joint[j].springyPosition;}
const glm::vec3& getBodyUpDirection () const { return _orientation.getUp();}
const glm::vec3& getVelocity () const { return _velocity;}
float getSpeed () const { return _speed;}
@ -96,6 +96,7 @@ private:
Avatar(const Avatar&);
Avatar& operator= (const Avatar&);
/*
struct AvatarJoint
{
AvatarJointID parent; // which joint is this joint connected to?
@ -114,6 +115,7 @@ private:
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)
};
*/
Head _head;
Skeleton _skeleton;
@ -125,7 +127,7 @@ private:
float _bodyRollDelta;
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;
glm::vec3 _cameraPosition;
glm::vec3 _handHoldingPosition;
@ -153,7 +155,6 @@ private:
glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat)
void renderBody(bool lookingInMirror);
void initializeSkeleton();
void updateSkeleton();
void initializeBodySprings();
void updateBodySprings( float deltaTime );
void calculateBoneLengths();

View file

@ -30,7 +30,7 @@ Camera::Camera() {
_needsToInitialize = true;
_frustumNeedsReshape = true;
_modeShift = 0.0f;
_modeShift = 1.0f;
_modeShiftRate = 1.0f;
_linearModeShift = 0.0f;
_mode = CAMERA_MODE_THIRD_PERSON;

View file

@ -6,15 +6,225 @@
#include "Skeleton.h"
const float BODY_SPRING_DEFAULT_TIGHTNESS = 1000.0f;
const float FLOATING_HEIGHT = 0.13f;
float test = 0.0f;
/*
float testYaw = 0.0f;
float testPitch = 0.0f;
float testRoll = 0.0f;
*/
Skeleton::Skeleton() {
}
void Skeleton::initialize() {
for (int b=0; b<NUM_AVATAR_JOINTS; b++) {
joint[b].isCollidable = true;
joint[b].parent = AVATAR_JOINT_NULL;
joint[b].position = 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].springyVelocity = glm::vec3(0.0, 0.0, 0.0);
joint[b].rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
joint[b].yaw = 0.0;
joint[b].pitch = 0.0;
joint[b].roll = 0.0;
joint[b].length = 0.0;
joint[b].radius = 0.0;
joint[b].touchForce = 0.0;
joint[b].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
joint[b].orientation.setToIdentity();
}
// specify the parental hierarchy
joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL;
joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS;
joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO;
joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST;
joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE;
joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE;
joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST;
joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR;
joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER;
joint[ AVATAR_JOINT_LEFT_WRIST ].parent = AVATAR_JOINT_LEFT_ELBOW;
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].parent = AVATAR_JOINT_LEFT_WRIST;
joint[ AVATAR_JOINT_RIGHT_COLLAR ].parent = AVATAR_JOINT_CHEST;
joint[ AVATAR_JOINT_RIGHT_SHOULDER ].parent = AVATAR_JOINT_RIGHT_COLLAR;
joint[ AVATAR_JOINT_RIGHT_ELBOW ].parent = AVATAR_JOINT_RIGHT_SHOULDER;
joint[ AVATAR_JOINT_RIGHT_WRIST ].parent = AVATAR_JOINT_RIGHT_ELBOW;
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].parent = AVATAR_JOINT_RIGHT_WRIST;
joint[ AVATAR_JOINT_LEFT_HIP ].parent = AVATAR_JOINT_PELVIS;
joint[ AVATAR_JOINT_LEFT_KNEE ].parent = AVATAR_JOINT_LEFT_HIP;
joint[ AVATAR_JOINT_LEFT_HEEL ].parent = AVATAR_JOINT_LEFT_KNEE;
joint[ AVATAR_JOINT_LEFT_TOES ].parent = AVATAR_JOINT_LEFT_HEEL;
joint[ AVATAR_JOINT_RIGHT_HIP ].parent = AVATAR_JOINT_PELVIS;
joint[ AVATAR_JOINT_RIGHT_KNEE ].parent = AVATAR_JOINT_RIGHT_HIP;
joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE;
joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL;
// specify the default pose position
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_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_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_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_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_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_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_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_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_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_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_TOES ].defaultPosePosition = glm::vec3( -0.00, -0.03, 0.05 );
// specify the radii of the joints
joint[ AVATAR_JOINT_PELVIS ].radius = 0.07;
joint[ AVATAR_JOINT_TORSO ].radius = 0.065;
joint[ AVATAR_JOINT_CHEST ].radius = 0.08;
joint[ AVATAR_JOINT_NECK_BASE ].radius = 0.03;
joint[ AVATAR_JOINT_HEAD_BASE ].radius = 0.07;
joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.04;
joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.03;
joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.02;
joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.02;
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01;
joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.04;
joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.03;
joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.02;
joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.02;
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].radius = 0.01;
joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.04;
joint[ AVATAR_JOINT_LEFT_KNEE ].radius = 0.025;
joint[ AVATAR_JOINT_LEFT_HEEL ].radius = 0.025;
joint[ AVATAR_JOINT_LEFT_TOES ].radius = 0.025;
joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.04;
joint[ AVATAR_JOINT_RIGHT_KNEE ].radius = 0.025;
joint[ AVATAR_JOINT_RIGHT_HEEL ].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
joint[ AVATAR_JOINT_RIGHT_ELBOW ].isCollidable = false;
joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false;
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS].isCollidable = false;
// calculate bone length
calculateBoneLengths();
//set spring positions to be in the skeleton bone positions
initializeBodySprings();
}
void Skeleton::render() {
void Skeleton::update(float deltaTime, Orientation orientation, glm::vec3 position) {
// calculate positions of all bones by traversing the skeleton tree:
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
if (joint[b].parent == AVATAR_JOINT_NULL) {
joint[b].orientation.set(orientation);
joint[b].position = position;
}
else {
joint[b].orientation.set(joint[joint[b].parent ].orientation);
joint[b].position = joint[joint[b].parent ].position;
}
/*
test += 0.01f * deltaTime;
float testYaw = 5.0f * sinf( 1.0f * test);
float testPitch = 5.0f * sinf( 1.3f * test);
float testRoll = 5.0f * sinf( 1.5f * test);
joint[b].orientation.yaw (testYaw );
joint[b].orientation.pitch(testPitch);
joint[b].orientation.roll (testRoll );
*/
// the following will be replaced by a proper rotation...close
float xx = glm::dot(joint[b].defaultPosePosition, joint[b].orientation.getRight());
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);
joint[b].position += rotatedJointVector;
}
}
void Skeleton::simulate(float deltaTime) {
void Skeleton::initializeBodySprings() {
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
joint[b].springyPosition = joint[b].position;
joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
}
}
void Skeleton::calculateBoneLengths() {
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
joint[b].length = glm::length(joint[b].defaultPosePosition);
}
}
float Skeleton::getArmLength() {
return joint[ AVATAR_JOINT_RIGHT_ELBOW ].length
+ joint[ AVATAR_JOINT_RIGHT_WRIST ].length
+ joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].length;
}
float Skeleton::getHeight() {
return
joint[ AVATAR_JOINT_LEFT_HEEL ].radius +
joint[ AVATAR_JOINT_LEFT_HEEL ].length +
joint[ AVATAR_JOINT_LEFT_KNEE ].length +
joint[ AVATAR_JOINT_PELVIS ].length +
joint[ AVATAR_JOINT_TORSO ].length +
joint[ AVATAR_JOINT_CHEST ].length +
joint[ AVATAR_JOINT_NECK_BASE ].length +
joint[ AVATAR_JOINT_HEAD_BASE ].length +
joint[ AVATAR_JOINT_HEAD_BASE ].radius;
}
float Skeleton::getPelvisStandingHeight() {
return joint[ AVATAR_JOINT_LEFT_HEEL ].radius +
joint[ AVATAR_JOINT_LEFT_HEEL ].length +
joint[ AVATAR_JOINT_LEFT_KNEE ].length;
}
float Skeleton::getPelvisFloatingHeight() {
return joint[ AVATAR_JOINT_LEFT_HEEL ].radius +
joint[ AVATAR_JOINT_LEFT_HEEL ].length +
joint[ AVATAR_JOINT_LEFT_KNEE ].length +
FLOATING_HEIGHT;
}

View file

@ -8,6 +8,10 @@
#ifndef hifi_Skeleton_h
#define hifi_Skeleton_h
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <Orientation.h>
enum AvatarJointID
{
AVATAR_JOINT_NULL = -1,
@ -45,10 +49,40 @@ public:
Skeleton();
void initialize();
void simulate(float deltaTime);
void initializeBodySprings();
void update(float deltaTime, Orientation orientation, glm::vec3 position);
void render();
float getArmLength();
float getHeight();
float getPelvisStandingHeight();
float getPelvisFloatingHeight();
struct AvatarJoint
{
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 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 springyVelocity; // used for special effects ( the velocity of the springy 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)
float yaw; // the yaw Euler angle of the joint rotation off the parent
float pitch; // the pitch Euler angle of the joint rotation off the parent
float roll; // the roll Euler angle of the joint rotation off the parent
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)
};
AvatarJoint joint[ NUM_AVATAR_JOINTS ];
private:
};
void calculateBoneLengths();
};
#endif