From caac600030ced8cc1ebed1349f68a1376a605131 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Sat, 27 Apr 2013 22:00:02 -0700 Subject: [PATCH 1/2] improved hand holding algorithm --- interface/src/Avatar.cpp | 61 ++++++++++++----------------------- interface/src/Avatar.h | 17 +++------- interface/src/AvatarTouch.cpp | 32 ++++++++++++++---- interface/src/AvatarTouch.h | 8 +++-- interface/src/main.cpp | 5 ++- 5 files changed, 59 insertions(+), 64 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 2594bb8a0a..076d4d2c18 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; } @@ -867,19 +861,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; } @@ -1135,7 +1116,7 @@ void Avatar::updateArmIKAndConstraints( float deltaTime ) { // test to see if right hand is being dragged beyond maximum arm length float distance = glm::length( armVector ); - // if right hand is being dragged beyond maximum arm length... + // don't let right hand get dragged beyond maximum arm length... if ( distance > _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 ab1f993bf5..925ac15cae 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -37,10 +37,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, @@ -108,14 +109,6 @@ 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? @@ -216,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 ); @@ -258,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) { From 4e4521325d7b3c3e073f968118a7e864ba96fdf2 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 29 Apr 2013 10:38:29 -0700 Subject: [PATCH 2/2] added 'isCollidable' to avatar bone so that some bones do not collide (for handshaking) --- interface/src/Avatar.cpp | 87 ++++++++++++++++++++++------------------ interface/src/Avatar.h | 3 +- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 076d4d2c18..24af81dfdf 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -539,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; + } } } } @@ -577,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; + } + } } } } @@ -872,6 +879,7 @@ AvatarMode Avatar::getMode() { void Avatar::initializeSkeleton() { for (int b=0; b