diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 2594bb8a0a..24af81dfdf 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -116,10 +116,7 @@ Avatar::Avatar(bool isMine) { _sphere = NULL; _interactingOther = NULL; _interactingOtherIsNearby = false; - - _handHolding.position = glm::vec3( 0.0, 0.0, 0.0 ); - _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); - _handHolding.force = 10.0f; + _handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 ); initializeSkeleton(); @@ -309,8 +306,7 @@ void Avatar::simulate(float deltaTime) { if ( !_interactingOtherIsNearby ) { //initialize _handHolding - _handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position; - _handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 ); + _handHoldingPosition = _bone[ AVATAR_BONE_RIGHT_HAND ].position; } _interactingOtherIsNearby = false; @@ -337,27 +333,20 @@ void Avatar::simulate(float deltaTime) { float distance = glm::length( v ); if ( distance < _maxArmLength + _maxArmLength ) { - //if ( distance < closestDistance ) { // perhaps I don't need this if we want to allow multi-avatar interactions - { - closestDistance = distance; - _interactingOther = otherAvatar; - _interactingOtherIsNearby = true; - - // if I am holding hands with another avatar, a force is applied - if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) { - glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHolding.position; - glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position; - - _handHolding.velocity *= 0.7; - _handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime; - _handHolding.position += _handHolding.velocity; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position; - } - } + closestDistance = distance; + _interactingOther = otherAvatar; + _interactingOtherIsNearby = true; - _avatarTouch.setMyHandPosition( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); - _avatarTouch.setYourPosition( otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ) ); + // if I am holding hands with another avatar, a force is applied + if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) { + glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHoldingPosition; + glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHoldingPosition; + _handHoldingPosition += vectorToOtherHand * YOUR_HAND_HOLDING_PULL; + _handHoldingPosition += vectorToMyHand * MY_HAND_HOLDING_PULL; + _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHoldingPosition; + } + + _avatarTouch.setYourHandPosition( _interactingOther->_handPosition ); } } } @@ -370,8 +359,13 @@ void Avatar::simulate(float deltaTime) { }//if ( _isMine ) + //constrain right arm length and re-adjust elbow position as it bends updateArmIKAndConstraints( deltaTime ); + if (_isMine) { + _avatarTouch.setMyHandPosition( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); + } + if (!_interactingOtherIsNearby) { _interactingOther = NULL; } @@ -545,21 +539,23 @@ void Avatar::updateCollisionWithSphere( glm::vec3 position, float radius, float float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); if ( distanceToBigSphere < myBodyApproximateBoundingRadius + radius ) { for (int b = 0; b < NUM_AVATAR_BONES; b++) { - glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - position); - float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter); - float combinedRadius = _bone[b].radius + radius; - - if ( distanceToBigSphereCenter < combinedRadius ) { - jointCollision = true; - if (distanceToBigSphereCenter > 0.0) { - glm::vec3 directionVector = vectorFromJointToBigSphereCenter / distanceToBigSphereCenter; - - float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius); - glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration; - - _bone[b].springyVelocity += collisionForce * 30.0f * deltaTime; - _velocity += collisionForce * 100.0f * deltaTime; - _bone[b].springyPosition = position + directionVector * combinedRadius; + if ( _bone[b].isCollidable ) { + glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - position); + float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter); + float combinedRadius = _bone[b].radius + radius; + + if ( distanceToBigSphereCenter < combinedRadius ) { + jointCollision = true; + if (distanceToBigSphereCenter > 0.0) { + glm::vec3 directionVector = vectorFromJointToBigSphereCenter / distanceToBigSphereCenter; + + float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius); + glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration; + + _bone[b].springyVelocity += collisionForce * 30.0f * deltaTime; + _velocity += collisionForce * 100.0f * deltaTime; + _bone[b].springyPosition = position + directionVector * combinedRadius; + } } } } @@ -583,27 +579,32 @@ void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTi // loop through the bones of each avatar to check for every possible collision for (int b=1; b_bone[o].springyPosition); + float distanceBetweenJoints = glm::length(vectorBetweenJoints); - glm::vec3 vectorBetweenJoints(_bone[b].springyPosition - otherAvatar->_bone[o].springyPosition); - float distanceBetweenJoints = glm::length(vectorBetweenJoints); - - // to avoid divide by zero - if ( distanceBetweenJoints > 0.0 ) { - float combinedRadius = _bone[b].radius + otherAvatar->_bone[o].radius; + // to avoid divide by zero + if ( distanceBetweenJoints > 0.0 ) { + float combinedRadius = _bone[b].radius + otherAvatar->_bone[o].radius; - // check for collision - if ( distanceBetweenJoints < combinedRadius * COLLISION_RADIUS_SCALAR) { - glm::vec3 directionVector = vectorBetweenJoints / distanceBetweenJoints; + // check for collision + if ( distanceBetweenJoints < combinedRadius * COLLISION_RADIUS_SCALAR) { + glm::vec3 directionVector = vectorBetweenJoints / distanceBetweenJoints; - // push ball away from colliding other ball and puch avatar body (_velocity) as well - _bone[b].springyVelocity += directionVector * COLLISION_BALL_FORCE * deltaTime; - _velocity += directionVector * COLLISION_BODY_FORCE * deltaTime; - - // apply fruction to _velocity - float momentum = 1.0 - COLLISION_FRICTION * deltaTime; - if ( momentum < 0.0 ) { momentum = 0.0;} - _velocity *= momentum; + // push ball away from colliding other ball and puch avatar body (_velocity) as well + _bone[b].springyVelocity += directionVector * COLLISION_BALL_FORCE * deltaTime; + _velocity += directionVector * COLLISION_BODY_FORCE * deltaTime; + + // apply fruction to _velocity + float momentum = 1.0 - COLLISION_FRICTION * deltaTime; + if ( momentum < 0.0 ) { momentum = 0.0;} + _velocity *= momentum; + } + } } } } @@ -867,19 +868,6 @@ void Avatar::renderHead(bool lookingInMirror) { glPopMatrix(); } - -void Avatar::startHandMovement() { - - if (!_usingBodySprings) { - initializeBodySprings(); - _usingBodySprings = true; - } -} - -void Avatar::stopHandMovement() { - //_usingBodySprings = false; -} - void Avatar::setHandMovementValues( glm::vec3 handOffset ) { _movedHandOffset = handOffset; } @@ -891,6 +879,7 @@ AvatarMode Avatar::getMode() { void Avatar::initializeSkeleton() { for (int b=0; b _maxArmLength ) { // reset right hand to be constrained to maximum arm length _bone[ AVATAR_BONE_RIGHT_HAND ].position = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 08d3977d90..8f5a7fe41d 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -36,10 +36,11 @@ const float COLLISION_RADIUS_SCALAR = 1.8; const float COLLISION_BALL_FORCE = 0.1; const float COLLISION_BODY_FORCE = 3.0; +const float MY_HAND_HOLDING_PULL = 0.2; +const float YOUR_HAND_HOLDING_PULL = 1.0; + enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; - - enum DriveKeys { FWD = 0, @@ -107,18 +108,10 @@ enum AvatarBoneID NUM_AVATAR_BONES }; - -struct AvatarHandHolding //think of this as one half of a distributed spring :) -{ - glm::vec3 position; - glm::vec3 velocity; - float force; -}; - struct AvatarBone { AvatarBoneID parent; // which bone is this bone connected to? - glm::vec3 position; // the position at the "end" of the bone + glm::vec3 position; // the position at the "end" of the bone - 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) @@ -130,6 +123,7 @@ struct AvatarBone Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll float length; // the length of the bone float radius; // used for detecting collisions for certain physical effects + bool isCollidable; // when false, the bone position will not register a collision }; struct AvatarHead @@ -215,8 +209,6 @@ public: void renderBody(); void renderHead(bool lookingInMirror); void simulate(float); - void startHandMovement(); - void stopHandMovement(); void setHandMovementValues( glm::vec3 movement ); void updateHandMovement( float deltaTime ); void updateArmIKAndConstraints( float deltaTime ); @@ -257,7 +249,7 @@ private: glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion AvatarBone _bone[ NUM_AVATAR_BONES ]; AvatarMode _mode; - AvatarHandHolding _handHolding; + glm::vec3 _handHoldingPosition; glm::vec3 _velocity; glm::vec3 _thrust; float _speed; diff --git a/interface/src/AvatarTouch.cpp b/interface/src/AvatarTouch.cpp index bd99cecd2b..ad4f0ccf33 100644 --- a/interface/src/AvatarTouch.cpp +++ b/interface/src/AvatarTouch.cpp @@ -3,41 +3,61 @@ // interface // // Created by Jeffrey Ventrella -// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // - #include #include +#include #include "AvatarTouch.h" #include "InterfaceConfig.h" + AvatarTouch::AvatarTouch() { _myHandPosition = glm::vec3( 0.0f, 0.0f, 0.0f ); _yourHandPosition = glm::vec3( 0.0f, 0.0f, 0.0f ); + + for (int p=0; pbegin(); agent != agentList->end(); agent++) { if (agent->getLinkedData() != NULL) {