diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index ae7fd2f8cb..c5ea4bc625 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -483,12 +483,10 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { Avatar *otherAvatar = (Avatar *)agent->getLinkedData(); - /* - // Test: Show angle between your fwd vector and nearest avatar - glm::vec3 vectorBetweenUs = otherAvatar->getJointPosition(AVATAR_JOINT_PELVIS) - - getJointPosition(AVATAR_JOINT_PELVIS); - printLog("Angle between: %f\n", angleBetween(vectorBetweenUs, _orientation.getFront())); - */ + //Test: Show angle between your fwd vector and nearest avatar + //glm::vec3 vectorBetweenUs = otherAvatar->getJointPosition(AVATAR_JOINT_PELVIS) - + // getJointPosition(AVATAR_JOINT_PELVIS); + //printLog("Angle between: %f\n", angleBetween(vectorBetweenUs, _orientation.getFront())); // test whether shoulders are close enough to allow for reaching to touch hands glm::vec3 v(_position - otherAvatar->_position); @@ -505,26 +503,60 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { _avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition); _avatarTouch.setYourHandState (_interactingOther->_handState); - if ( _avatarTouch.getAbleToReachOtherAvatar()) { - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = - _interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition; + //if hand-holding is initiated by either avatar, turn on hand-holding... + if (_avatarTouch.getHandsCloseEnoughToGrasp()) { + if ((_handState == HAND_STATE_GRASPING ) || (_interactingOther->_handState == HAND_STATE_GRASPING)) { + if (!_avatarTouch.getHoldingHands()) + { + _avatarTouch.setHoldingHands(true); + } + } + } + + if (!_avatarTouch.getAbleToReachOtherAvatar()) { + _avatarTouch.setHoldingHands(false); + } + + if ((_handState != HAND_STATE_GRASPING ) && (_interactingOther->_handState != HAND_STATE_GRASPING)) { + _avatarTouch.setHoldingHands(false); } } + //if holding hands, apply the appropriate forces + if (_avatarTouch.getHoldingHands()) { + + glm::vec3 vectorToOtherHand = _interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition - _handHoldingPosition; + glm::vec3 vectorToMyHand = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - _handHoldingPosition; + + float myInfluence = 30.0f; + float yourInfluence = 30.0f; + + glm::vec3 myForce = vectorToMyHand * myInfluence * deltaTime; + glm::vec3 yourForce = vectorToOtherHand * yourInfluence * deltaTime; + + if (_handState == HAND_STATE_GRASPING) {myForce *= 2.0f; } + if (_interactingOther->_handState == HAND_STATE_GRASPING) {yourForce *= 2.0f; } + + _handHoldingPosition += myForce + yourForce; + + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handHoldingPosition; + } else { + _handHoldingPosition = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position; + } }//if (_isMine) //constrain right arm length and re-adjust elbow position as it bends // NOTE - the following must be called on all avatars - not just _isMine updateArmIKAndConstraints(deltaTime); + //Set right hand position and state to be transmitted, and also tell AvatarTouch about it if (_isMine) { - //Set the vector we send for hand position to other people to be our right hand setHandPosition(_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); if (_mousePressed) { - _handState = 1; + _handState = HAND_STATE_GRASPING; } else { - _handState = 0; + _handState = HAND_STATE_NULL; } _avatarTouch.setMyHandState(_handState); @@ -546,7 +578,7 @@ void Avatar::updateHead(float deltaTime) { _orientation.getRight() * _head.leanSideways + _orientation.getFront() * _head.leanForward; - // this is not a long-term solution, but it works ok for initial purposes... + // this is not a long-term solution, but it works ok for initial purposes of making the avatar lean _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; diff --git a/interface/src/AvatarTouch.cpp b/interface/src/AvatarTouch.cpp index 1c8374b9a4..3c08a5f3cb 100644 --- a/interface/src/AvatarTouch.cpp +++ b/interface/src/AvatarTouch.cpp @@ -13,6 +13,7 @@ #include "Util.h" const float THREAD_RADIUS = 0.012; +const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.1; AvatarTouch::AvatarTouch() { @@ -21,9 +22,10 @@ AvatarTouch::AvatarTouch() { _myBodyPosition = glm::vec3(0.0f, 0.0f, 0.0f); _yourBodyPosition = glm::vec3(0.0f, 0.0f, 0.0f); _vectorBetweenHands = glm::vec3(0.0f, 0.0f, 0.0f); - _myHandState = 0; - _yourHandState = 0; + _myHandState = HAND_STATE_NULL; + _yourHandState = HAND_STATE_NULL; _reachableRadius = 0.0f; + _weAreHoldingHands = false; _canReachToOtherAvatar = false; _handsCloseEnoughToGrasp = false; @@ -61,19 +63,63 @@ void AvatarTouch::setReachableRadius(float r) { _reachableRadius = r; } + +void AvatarTouch::simulate (float deltaTime) { + + glm::vec3 vectorBetweenBodies = _yourBodyPosition - _myBodyPosition; + float distanceBetweenBodies = glm::length(vectorBetweenBodies); + + if (distanceBetweenBodies < _reachableRadius) { + _vectorBetweenHands = _yourHandPosition - _myHandPosition; + + float distanceBetweenHands = glm::length(_vectorBetweenHands); + if (distanceBetweenHands < HANDS_CLOSE_ENOUGH_TO_GRASP) { + _handsCloseEnoughToGrasp = true; + } else { + _handsCloseEnoughToGrasp = false; + } + + _canReachToOtherAvatar = true; + } else { + _canReachToOtherAvatar = false; + } + } + + + void AvatarTouch::render(glm::vec3 cameraPosition) { -if (_canReachToOtherAvatar) { + if (_canReachToOtherAvatar) { + //show circle indicating that we can reach out to each other... glColor4f(0.3, 0.4, 0.5, 0.5); glm::vec3 p(_yourBodyPosition); p.y = 0.0005f; renderCircle(p, _reachableRadius, glm::vec3(0.0f, 1.0f, 0.0f), 30); + // show is we are golding hands... + if (_weAreHoldingHands) { + glColor4f(0.9, 0.3, 0.3, 0.5); + renderSphereOutline(_myHandPosition, HANDS_CLOSE_ENOUGH_TO_GRASP * 0.3f, 20, cameraPosition); + renderSphereOutline(_myHandPosition, HANDS_CLOSE_ENOUGH_TO_GRASP * 0.2f, 20, cameraPosition); + renderSphereOutline(_myHandPosition, HANDS_CLOSE_ENOUGH_TO_GRASP * 0.1f, 20, cameraPosition); + + renderSphereOutline(_yourHandPosition, HANDS_CLOSE_ENOUGH_TO_GRASP * 0.3f, 20, cameraPosition); + renderSphereOutline(_yourHandPosition, HANDS_CLOSE_ENOUGH_TO_GRASP * 0.2f, 20, cameraPosition); + renderSphereOutline(_yourHandPosition, HANDS_CLOSE_ENOUGH_TO_GRASP * 0.1f, 20, cameraPosition); + } + + //render the beam between our hands indicting that we can reach out and grasp hands... renderBeamBetweenHands(); + //show that our hands are close enough to grasp.. + if (_handsCloseEnoughToGrasp) { + glColor4f(0.9, 0.3, 0.3, 0.5); + renderSphereOutline(_myHandPosition, HANDS_CLOSE_ENOUGH_TO_GRASP / 3.0f, 20, cameraPosition); + } + // if your hand is grasping, show it... - if (_yourHandState == 1) { + if (_yourHandState == HAND_STATE_GRASPING) { glPushMatrix(); glTranslatef(_yourHandPosition.x, _yourHandPosition.y, _yourHandPosition.z); glColor4f(1.0, 1.0, 0.8, 0.3); glutSolidSphere(0.020f, 10.0f, 10.0f); @@ -84,7 +130,7 @@ if (_canReachToOtherAvatar) { } // if my hand is grasping, show it... - if (_myHandState == 1) { + if (_myHandState == HAND_STATE_GRASPING) { glPushMatrix(); glTranslatef(_myHandPosition.x, _myHandPosition.y, _myHandPosition.z); glColor4f(1.0, 1.0, 0.8, 0.3); glutSolidSphere(0.020f, 10.0f, 10.0f); @@ -94,34 +140,6 @@ if (_canReachToOtherAvatar) { } } -void AvatarTouch::simulate (float deltaTime) { - - _vectorBetweenHands = _yourBodyPosition - _myBodyPosition; - float distance = glm::length(_vectorBetweenHands); - - if (distance < _reachableRadius) { - _canReachToOtherAvatar = true; - generateBeamBetweenHands(); - } else { - _canReachToOtherAvatar = false; - } - - - - } - -void AvatarTouch::generateBeamBetweenHands() { - - for (int p=0; p -const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.1; +enum AvatarHandState +{ + HAND_STATE_NULL = -1, + HAND_STATE_OPEN, + HAND_STATE_GRASPING, + HAND_STATE_POINTING, + NUM_HAND_STATES +}; class AvatarTouch { public: @@ -28,16 +35,20 @@ public: void setMyHandState (int state); void setYourHandState (int state); void setReachableRadius (float r); + void setAbleToReachOtherAvatar (bool a) {_canReachToOtherAvatar = a;} void setHandsCloseEnoughToGrasp(bool h) {_handsCloseEnoughToGrasp = h;} + void setHoldingHands (bool h) {_weAreHoldingHands = h;} - bool getAbleToReachOtherAvatar () const {return _canReachToOtherAvatar;} + bool getAbleToReachOtherAvatar () const {return _canReachToOtherAvatar; } bool getHandsCloseEnoughToGrasp() const {return _handsCloseEnoughToGrasp;} + bool getHoldingHands () const {return _weAreHoldingHands; } private: static const int NUM_POINTS = 100; + bool _weAreHoldingHands; glm::vec3 _point [NUM_POINTS]; glm::vec3 _myBodyPosition; glm::vec3 _yourBodyPosition; @@ -50,7 +61,6 @@ private: bool _handsCloseEnoughToGrasp; float _reachableRadius; - void generateBeamBetweenHands(); void renderBeamBetweenHands(); }; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index fbfbcc85fb..27f28d175f 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1892,10 +1892,11 @@ glm::vec3 getGravity(glm::vec3 pos) { return glm::vec3(0.f, 0.f, 0.f); } } - + + void mouseFunc(int button, int state, int x, int y) { - //catch mouse actiond on the menu + //catch mouse actions on the menu bool menuClickedOrUnclicked = menu.mouseClick(x, y); if (!menuClickedOrUnclicked) {