diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4dd3dba178..fe84ec4748 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1100,7 +1100,7 @@ void Application::idle() { } } } - + // Update audio stats for procedural sounds #ifndef _WIN32 _audio.setLastAcceleration(_myAvatar.getThrust()); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 4dd95d6a16..46a4d302ca 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -33,11 +33,9 @@ const float YOUR_HAND_HOLDING_PULL = 1.0; const float BODY_SPRING_DEFAULT_TIGHTNESS = 1000.0f; const float BODY_SPRING_FORCE = 300.0f; const float BODY_SPRING_DECAY = 16.0f; -const float COLLISION_RADIUS_SCALAR = 1.8; -const float COLLISION_BALL_FORCE = 1.0; -const float COLLISION_BODY_FORCE = 6.0; -const float COLLISION_BALL_FRICTION = 60.0; -const float COLLISION_BODY_FRICTION = 0.5; +const float COLLISION_RADIUS_SCALAR = 1.2; //pertains to avatar-to-avatar collisions +const float COLLISION_BALL_FORCE = 200.0; //pertains to avatar-to-avatar collisions +const float COLLISION_BODY_FORCE = 30.0; //pertains to avatar-to-avatar collisions const float HEAD_ROTATION_SCALE = 0.70; const float HEAD_ROLL_SCALE = 0.40; const float HEAD_MAX_PITCH = 45; @@ -46,7 +44,7 @@ const float HEAD_MAX_YAW = 85; const float HEAD_MIN_YAW = -85; const float PERIPERSONAL_RADIUS = 1.0f; const float AVATAR_BRAKING_STRENGTH = 40.0f; -const float JOINT_TOUCH_RANGE = 0.0005f; +const float JOINT_TOUCH_RANGE = 0.01f; const float FLOATING_HEIGHT = 0.13f; const bool USING_HEAD_LEAN = false; const float LEAN_SENSITIVITY = 0.15; @@ -99,8 +97,15 @@ Avatar::Avatar(Agent* owningAgent) : _driveKeys[i] = false; } - initializeSkeleton(); + _skeleton.initialize(); + initializeBodyBalls(); + + _height = _skeleton.getHeight() + _bodyBall[ AVATAR_JOINT_LEFT_HEEL ].radius + _bodyBall[ AVATAR_JOINT_HEAD_BASE ].radius; + _maxArmLength = _skeleton.getArmLength(); + _pelvisStandingHeight = _skeleton.getPelvisStandingHeight() + _bodyBall[ AVATAR_JOINT_LEFT_HEEL ].radius; + _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight() + _bodyBall[ AVATAR_JOINT_LEFT_HEEL ].radius; + _avatarTouch.setReachableRadius(PERIPERSONAL_RADIUS); if (BALLS_ON) { @@ -110,6 +115,56 @@ Avatar::Avatar(Agent* owningAgent) : } } + +void Avatar::initializeBodyBalls() { + + for (int b=0; bsimulate(deltaTime); } + + // update avatar skeleton + _skeleton.update(deltaTime, getOrientation(), _position); - // if other avatar, update head position from network data - - // update avatar skeleton - updateSkeleton(); - + // 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) { updateAvatarCollisions(deltaTime); @@ -238,8 +296,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { updateCollisionWithEnvironment(); } - // update body springs - updateBodySprings(deltaTime); + // update body balls + updateBodyBalls(deltaTime); // test for avatar collision response with the big sphere if (usingBigSphereCollisionTest) { @@ -391,29 +449,29 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { } } - //apply the head lean values to the springy position... + //apply the head lean values to the ball positions... if (USING_HEAD_LEAN) { if (fabs(_head.getLeanSideways() + _head.getLeanForward()) > 0.0f) { glm::vec3 headLean = right * _head.getLeanSideways() + front * _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; + _bodyBall[ AVATAR_JOINT_TORSO ].position += headLean * 0.1f; + _bodyBall[ AVATAR_JOINT_CHEST ].position += headLean * 0.4f; + _bodyBall[ AVATAR_JOINT_NECK_BASE ].position += headLean * 0.7f; + _bodyBall[ AVATAR_JOINT_HEAD_BASE ].position += 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; + _bodyBall[ AVATAR_JOINT_LEFT_COLLAR ].position += headLean * 0.6f; + _bodyBall[ AVATAR_JOINT_LEFT_SHOULDER ].position += headLean * 0.6f; + _bodyBall[ AVATAR_JOINT_LEFT_ELBOW ].position += headLean * 0.2f; + _bodyBall[ AVATAR_JOINT_LEFT_WRIST ].position += headLean * 0.1f; + _bodyBall[ AVATAR_JOINT_LEFT_FINGERTIPS ].position += 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; + _bodyBall[ AVATAR_JOINT_RIGHT_COLLAR ].position += headLean * 0.6f; + _bodyBall[ AVATAR_JOINT_RIGHT_SHOULDER ].position += headLean * 0.6f; + _bodyBall[ AVATAR_JOINT_RIGHT_ELBOW ].position += headLean * 0.2f; + _bodyBall[ AVATAR_JOINT_RIGHT_WRIST ].position += headLean * 0.1f; + _bodyBall[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += headLean * 0.0f; } } @@ -426,9 +484,9 @@ 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.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); + _head.setPosition(_bodyBall[ AVATAR_JOINT_HEAD_BASE ].position); + _head.setScale (_bodyBall[ AVATAR_JOINT_HEAD_BASE ].radius); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); _head.simulate(deltaTime, !_owningAgent); @@ -444,13 +502,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(_bodyBall[b].position - _mouseRayOrigin); float dot = glm::dot(directionToBodySphere, _mouseRayDirection); - if (dot > (1.0f - JOINT_TOUCH_RANGE)) { - _joint[b].touchForce = (dot - (1.0f - JOINT_TOUCH_RANGE)) / JOINT_TOUCH_RANGE; + float range = _bodyBall[b].radius * JOINT_TOUCH_RANGE; + + if (dot > (1.0f - range)) { + _bodyBall[b].touchForce = (dot - (1.0f - range)) / range; } else { - _joint[b].touchForce = 0.0; + _bodyBall[b].touchForce = 0.0; } } } @@ -473,15 +533,15 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { // reset hand and arm positions according to hand movement glm::vec3 right = orientation * AVATAR_RIGHT; - glm::vec3 up = orientation * AVATAR_UP; + glm::vec3 up = orientation * AVATAR_UP; glm::vec3 front = orientation * AVATAR_FRONT; glm::vec3 transformedHandMovement = right * _movedHandOffset.x * 2.0f - + up * -_movedHandOffset.y * 2.0f - + front * -_movedHandOffset.z * 2.0f; + + up * -_movedHandOffset.y * 2.0f + + front * -_movedHandOffset.y * 2.0f; - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement; + _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement; if (!_owningAgent) { _avatarTouch.setMyBodyPosition(_position); @@ -519,8 +579,8 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { _avatarTouch.setHasInteractingOther(true); _avatarTouch.setYourBodyPosition(_interactingOther->_position); + _avatarTouch.setYourHandPosition(_interactingOther->_bodyBall[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); _avatarTouch.setYourOrientation (_interactingOther->getOrientation()); - _avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition); _avatarTouch.setYourHandState (_interactingOther->_handState); //if hand-holding is initiated by either avatar, turn on hand-holding... @@ -535,8 +595,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); @@ -558,10 +618,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) { @@ -581,7 +641,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; @@ -590,7 +650,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { } _avatarTouch.setMyHandState(_handState); - _avatarTouch.setMyHandPosition(_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition); + _avatarTouch.setMyHandPosition(_bodyBall[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); } } @@ -602,9 +662,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(_bodyBall[b].position - position); float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter); - float combinedRadius = _joint[b].radius + radius; + float combinedRadius = _bodyBall[b].radius + radius; if (distanceToBigSphereCenter < combinedRadius) { jointCollision = true; @@ -614,9 +674,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; + _bodyBall[b].velocity += collisionForce * 0.0f * deltaTime; _velocity += collisionForce * 40.0f * deltaTime; - _joint[b].springyPosition = position + directionVector * combinedRadius; + _bodyBall[b].position = position + directionVector * combinedRadius; } } } @@ -674,16 +734,17 @@ void Avatar::updateAvatarCollisions(float deltaTime) { for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { Avatar *otherAvatar = (Avatar *)agent->getLinkedData(); - + // check if the bounding spheres of the two avatars are colliding glm::vec3 vectorBetweenBoundingSpheres(_position - otherAvatar->_position); + if (glm::length(vectorBetweenBoundingSpheres) < _height * ONE_HALF + otherAvatar->_height * ONE_HALF) { - //apply forces from collision - applyCollisionWithOtherAvatar(otherAvatar, deltaTime); + //apply forces from collision + applyCollisionWithOtherAvatar(otherAvatar, 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); @@ -696,43 +757,34 @@ void Avatar::updateAvatarCollisions(float deltaTime) { //detect collisions with other avatars and respond void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime) { - - float bodyMomentum = 1.0f; + glm::vec3 bodyPushForce = glm::vec3(0.0f, 0.0f, 0.0f); // loop through the joints of each avatar to check for every possible collision for (int b=1; b_joint[o].isCollidable) { + if (otherAvatar->_bodyBall[o].isCollidable) { - glm::vec3 vectorBetweenJoints(_joint[b].springyPosition - otherAvatar->_joint[o].springyPosition); + glm::vec3 vectorBetweenJoints(_bodyBall[b].position - otherAvatar->_bodyBall[o].position); 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 = _bodyBall[b].radius + otherAvatar->_bodyBall[o].radius; // check for collision if (distanceBetweenJoints < combinedRadius * COLLISION_RADIUS_SCALAR) { glm::vec3 directionVector = vectorBetweenJoints / distanceBetweenJoints; // push balls away from each other and apply friction - glm::vec3 ballPushForce = directionVector * COLLISION_BALL_FORCE * deltaTime; - - float ballMomentum = 1.0 - COLLISION_BALL_FRICTION * deltaTime; - if (ballMomentum < 0.0) { ballMomentum = 0.0;} - - _joint[b].springyVelocity += ballPushForce; - otherAvatar->_joint[o].springyVelocity -= ballPushForce; + float penetration = 1.0f - (distanceBetweenJoints / (combinedRadius * COLLISION_RADIUS_SCALAR)); - _joint[b].springyVelocity *= ballMomentum; - otherAvatar->_joint[o].springyVelocity *= ballMomentum; - - // accumulate forces and frictions to apply to the velocities of avatar bodies - bodyPushForce += directionVector * COLLISION_BODY_FORCE * deltaTime; - bodyMomentum -= COLLISION_BODY_FRICTION * deltaTime; - if (bodyMomentum < 0.0) { bodyMomentum = 0.0;} + glm::vec3 ballPushForce = directionVector * COLLISION_BALL_FORCE * penetration * deltaTime; + bodyPushForce += directionVector * COLLISION_BODY_FORCE * penetration * deltaTime; + + _bodyBall[b].velocity += ballPushForce; + otherAvatar->_bodyBall[o].velocity -= ballPushForce; }// check for collision } // to avoid divide by zero @@ -741,12 +793,8 @@ void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime } // b loop } // collidable - - //apply forces and frictions on the bodies of both avatars - _velocity += bodyPushForce; - otherAvatar->_velocity -= bodyPushForce; - _velocity *= bodyMomentum; - otherAvatar->_velocity *= bodyMomentum; + //apply force on the whole body + _velocity += bodyPushForce; } @@ -809,11 +857,12 @@ void Avatar::render(bool lookingInMirror) { } glPushMatrix(); - glm::vec3 chatPosition = _joint[AVATAR_JOINT_HEAD_BASE].springyPosition + getBodyUpDirection() * chatMessageHeight; + glm::vec3 chatPosition = _bodyBall[AVATAR_JOINT_HEAD_BASE].position + getBodyUpDirection() * chatMessageHeight; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); glRotatef(glm::angle(chatRotation), chatAxis.x, chatAxis.y, chatAxis.z); + glColor3f(0, 0.8, 0); glRotatef(180, 0, 1, 0); @@ -843,252 +892,71 @@ void Avatar::render(bool lookingInMirror) { } } -void Avatar::initializeSkeleton() { - - for (int b=0; b BEYOND_BODY_SPRING_RANGE) { - initializeBodySprings(); + if (glm::length(_position - _bodyBall[AVATAR_JOINT_PELVIS].position) > BEYOND_BODY_SPRING_RANGE) { + resetBodyBalls(); } for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - glm::vec3 springVector(_joint[b].springyPosition); + glm::vec3 springVector(_bodyBall[b].position); - 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 -= _bodyBall[ _skeleton.joint[b].parent ].position; } float length = glm::length(springVector); if (length > 0.0f) { // to avoid divide by zero glm::vec3 springDirection = springVector / length; + + float force = (length - _skeleton.joint[b].length) * BODY_SPRING_FORCE * deltaTime; + _bodyBall[b].velocity -= springDirection * force; - float force = (length - _joint[b].length) * BODY_SPRING_FORCE * deltaTime; - - _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) { + _bodyBall[_skeleton.joint[b].parent].velocity += 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; + // apply tightness force - (causing ball position to be close to skeleton joint position) + _bodyBall[b].velocity += (_skeleton.joint[b].position - _bodyBall[b].position) * _bodyBall[b].jointTightness * deltaTime; // apply decay float decay = 1.0 - BODY_SPRING_DECAY * deltaTime; if (decay > 0.0) { - _joint[b].springyVelocity *= decay; + _bodyBall[b].velocity *= decay; } else { - _joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + _bodyBall[b].velocity = 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; + _bodyBall[b].position += _bodyBall[b].velocity * 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); @@ -1096,29 +964,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; - newElbowPosition += armVector * ONE_HALF; + glm::vec3 newElbowPosition = _skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position + armVector * ONE_HALF; - glm::vec3 perpendicular = glm::cross(getBodyFrontDirection(), armVector); + glm::vec3 perpendicular = glm::cross(getBodyRightDirection(), 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; } glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { @@ -1144,7 +1011,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 = lookingInMirror ? 1.0f : glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f); @@ -1166,26 +1033,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] + _bodyBall[b].touchForce * 0.3f, + SKIN_COLOR[1] - _bodyBall[b].touchForce * 0.2f, + SKIN_COLOR[2] - _bodyBall[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] + _bodyBall[b].touchForce * 0.3f, + SKIN_COLOR[1] - _bodyBall[b].touchForce * 0.2f, + SKIN_COLOR[2] - _bodyBall[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(_bodyBall[b].position.x, _bodyBall[b].position.y, _bodyBall[b].position.z); + glutSolidSphere(_bodyBall[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 ) @@ -1197,15 +1064,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 = _bodyBall[_skeleton.joint[b].parent ].radius * 0.8; + float r2 = _bodyBall[b ].radius * 0.8; if (b == AVATAR_JOINT_HEAD_BASE) { r1 *= 0.5f; } renderJointConnectingCone ( - _joint[_joint[b].parent ].springyPosition, - _joint[b ].springyPosition, r2, r2 + _bodyBall[_skeleton.joint[b].parent ].position, + _bodyBall[b ].position, r2, r2 ); } } diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index d272514ed1..6746ba51cd 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -64,24 +64,28 @@ public: void setOrientation (const glm::quat& orientation); //getters - 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;} + + float getHeadYawRate () const { return _head.yawRate;} + float getBodyYaw () const { return _bodyYaw;} + bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();} + const glm::vec3& getHeadPosition () const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;} + const glm::vec3& getSpringyHeadPosition () const { return _bodyBall[ AVATAR_JOINT_HEAD_BASE ].position;} + const glm::vec3& getJointPosition (AvatarJointID j) const { return _bodyBall[j].position;} + glm::vec3 getBodyRightDirection () const { return getOrientation() * AVATAR_RIGHT; } glm::vec3 getBodyUpDirection () const { return getOrientation() * AVATAR_UP; } glm::vec3 getBodyFrontDirection () const { return getOrientation() * AVATAR_FRONT; } - const glm::vec3& getVelocity () const { return _velocity;} - float getSpeed () const { return _speed;} - float getHeight () const { return _height;} - AvatarMode getMode () const { return _mode;} - float getAbsoluteHeadYaw () const; - float getAbsoluteHeadPitch () const; - Head& getHead () { return _head; } - glm::quat getOrientation () const; - glm::quat getWorldAlignedOrientation () const; + + + const glm::vec3& getVelocity () const { return _velocity;} + float getSpeed () const { return _speed;} + float getHeight () const { return _height;} + AvatarMode getMode () const { return _mode;} + 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 void setDriveKeys(int key, bool val) { _driveKeys[key] = val; }; @@ -100,19 +104,14 @@ private: Avatar(const Avatar&); Avatar& operator= (const Avatar&); - struct AvatarJoint + struct AvatarBall { - 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 orientation; // this will eventually replace yaw, pitch and roll (and maybe orientation) - 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) + glm::vec3 position; + glm::vec3 velocity; + float jointTightness; + float radius; + bool isCollidable; + float touchForce; }; Head _head; @@ -124,7 +123,8 @@ private: float _bodyYawDelta; float _bodyRollDelta; glm::vec3 _movedHandOffset; - AvatarJoint _joint[ NUM_AVATAR_JOINTS ]; + glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion + AvatarBall _bodyBall[ NUM_AVATAR_JOINTS ]; AvatarMode _mode; glm::vec3 _cameraPosition; glm::vec3 _handHoldingPosition; @@ -152,10 +152,9 @@ private: 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 initializeSkeleton(); - void updateSkeleton(); - void initializeBodySprings(); - void updateBodySprings( float deltaTime ); + void initializeBodyBalls(); + void resetBodyBalls(); + void updateBodyBalls( float deltaTime ); void calculateBoneLengths(); void readSensors(); void updateHandMovementAndTouching(float deltaTime); diff --git a/interface/src/AvatarTouch.cpp b/interface/src/AvatarTouch.cpp index 2415d030c8..1e06663b01 100644 --- a/interface/src/AvatarTouch.cpp +++ b/interface/src/AvatarTouch.cpp @@ -43,6 +43,10 @@ void AvatarTouch::simulate (float deltaTime) { glm::vec3 vectorBetweenBodies = _yourBodyPosition - _myBodyPosition; float distanceBetweenBodies = glm::length(vectorBetweenBodies); + + //KEEP THIS - it is another variation that we are considering getting rid of + //the following code take into account of the two avatars are facing each other + /* glm::vec3 directionBetweenBodies = vectorBetweenBodies / distanceBetweenBodies; bool facingEachOther = false; @@ -50,12 +54,14 @@ void AvatarTouch::simulate (float deltaTime) { glm::vec3 myFront = _myOrientation * AVATAR_FRONT; 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 + 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; } - - if (distanceBetweenBodies < _reachableRadius) { + */ + + if (distanceBetweenBodies < _reachableRadius) + { _canReachToOtherAvatar = true; _vectorBetweenHands = _yourHandPosition - _myHandPosition; diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 21e60c0cc5..4227e623ff 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -32,7 +32,7 @@ Camera::Camera() { _needsToInitialize = true; _frustumNeedsReshape = true; - _modeShift = 0.0f; + _modeShift = 1.0f; _modeShiftRate = 1.0f; _linearModeShift = 0.0f; _mode = CAMERA_MODE_THIRD_PERSON; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d1ee699dc8..bbf773a8a9 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -20,7 +20,6 @@ const float EYE_RIGHT_OFFSET = 0.27f; const float EYE_UP_OFFSET = 0.36f; const float EYE_FRONT_OFFSET = 0.8f; const float EAR_RIGHT_OFFSET = 1.0; -//const float MOUTH_FRONT_OFFSET = 0.9f; const float MOUTH_UP_OFFSET = -0.3f; const float HEAD_MOTION_DECAY = 0.1; const float MINIMUM_EYE_ROTATION_DOT = 0.5f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off @@ -276,7 +275,7 @@ void Head::renderMohawk(glm::vec3 cameraPosition) { glm::vec3 mid2 = _hairTuft[t].midPosition + midPerpendicular * _hairTuft[t].thickness * ONE_HALF * ONE_HALF; glColor3f(_mohawkColors[t].x, _mohawkColors[t].y, _mohawkColors[t].z); - + glBegin(GL_TRIANGLES); glVertex3f(base1.x, base1.y, base1.z ); glVertex3f(base2.x, base2.y, base2.z ); @@ -374,7 +373,7 @@ void Head::renderMouth() { rightTop = _position + glm::normalize(rightTop - _position) * constrainedRadius; leftBottom = _position + glm::normalize(leftBottom - _position) * constrainedRadius; rightBottom = _position + glm::normalize(rightBottom - _position) * constrainedRadius; - + glColor3f(0.2f, 0.0f, 0.0f); glBegin(GL_TRIANGLES); diff --git a/interface/src/Skeleton.cpp b/interface/src/Skeleton.cpp index 49e8dea053..64a8645247 100644 --- a/interface/src/Skeleton.cpp +++ b/interface/src/Skeleton.cpp @@ -6,15 +6,129 @@ #include "Skeleton.h" +const float BODY_SPRING_DEFAULT_TIGHTNESS = 1000.0f; +const float FLOATING_HEIGHT = 0.13f; + Skeleton::Skeleton() { } void Skeleton::initialize() { + + for (int b=0; b +#include + enum AvatarJointID { AVATAR_JOINT_NULL = -1, @@ -45,10 +48,24 @@ public: Skeleton(); void initialize(); - void simulate(float deltaTime); + void update(float deltaTime, const glm::quat&, glm::vec3 position); void render(); -private: -}; + 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::quat rotation; // the parent-relative rotation (orientation) of the joint as a quaternion + float length; // the length of vector connecting the joint and its parent + }; + + AvatarJoint joint[ NUM_AVATAR_JOINTS ]; + }; #endif