From 5c3bd5fe879e842496948422e89f7cc3437fef6b Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Sat, 27 Apr 2013 09:33:58 -0700 Subject: [PATCH] improved collisions between avatars --- eve/src/main.cpp | 2 +- interface/src/Avatar.cpp | 91 +++++++++++++++++++++++++--------------- interface/src/Avatar.h | 30 ++++++------- interface/src/main.cpp | 2 +- 4 files changed, 72 insertions(+), 53 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index b4e6675ca0..d0ac737e2d 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -121,7 +121,7 @@ int main(int argc, const char* argv[]) { // put her hand out so somebody can shake it eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2, - 0.25, + 0.32, // this is the same as the pelvis standing height (as of 4/26/13) eve.getPosition()[2] + 0.1)); // read eve's audio data AudioInjector eveAudioInjector("eve.raw"); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 100f5e1430..7654ca03ef 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -328,11 +328,7 @@ void Avatar::simulate(float deltaTime) { Avatar *otherAvatar = (Avatar *)agent->getLinkedData(); // check for collisions with other avatars and respond - updateAvatarCollisionDetectionAndResponse(otherAvatar->getPosition(), - 0.1, - 0.1, - otherAvatar->getBodyUpDirection(), - deltaTime); + updateCollisionWithOtherAvatar(otherAvatar, deltaTime ); // test other avatar hand position for proximity glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); @@ -381,12 +377,8 @@ void Avatar::simulate(float deltaTime) { } if (usingBigSphereCollisionTest) { - // test for avatar collision response (using a big sphere :) - updateAvatarCollisionDetectionAndResponse(_TEST_bigSpherePosition, - _TEST_bigSphereRadius, - _TEST_bigSphereRadius, - glm::vec3( 0.0, 1.0, 0.0 ), - deltaTime); + // test for avatar collision response with the big sphere + updateCollisionWithSphere( _TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime ); } if ( AVATAR_GRAVITY ) { @@ -540,31 +532,22 @@ void Avatar::simulate(float deltaTime) { } } -float Avatar::getGirth() { - return COLLISION_BODY_RADIUS; -} - float Avatar::getHeight() { - return COLLISION_HEIGHT; + return _height; } -// This is a workspace for testing avatar body collision detection and response -void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPosition, - float collisionGirth, - float collisionHeight, - glm::vec3 collisionUpVector, - float deltaTime) { - + +void Avatar::updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ) { float myBodyApproximateBoundingRadius = 1.0f; - glm::vec3 vectorFromMyBodyToBigSphere(_position - collisionPosition); + glm::vec3 vectorFromMyBodyToBigSphere(_position - position); bool jointCollision = false; float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); - if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth ) { + if ( distanceToBigSphere < myBodyApproximateBoundingRadius + radius ) { for (int b = 0; b < NUM_AVATAR_BONES; b++) { - glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - collisionPosition); + glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - position); float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter); - float combinedRadius = _bone[b].radius + collisionGirth; + float combinedRadius = _bone[b].radius + radius; if ( distanceToBigSphereCenter < combinedRadius ) { jointCollision = true; @@ -576,7 +559,7 @@ void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPositi _bone[b].springyVelocity += collisionForce * 30.0f * deltaTime; _velocity += collisionForce * 100.0f * deltaTime; - _bone[b].springyPosition = collisionPosition + directionVector * combinedRadius; + _bone[b].springyPosition = position + directionVector * combinedRadius; } } } @@ -590,6 +573,38 @@ void Avatar::updateAvatarCollisionDetectionAndResponse(glm::vec3 collisionPositi } } + +void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTime ) { + + glm::vec3 vectorBetweenBoundingSpheres(_position - otherAvatar->_position); + + if ( glm::length(vectorBetweenBoundingSpheres) < _height * ONE_HALF + otherAvatar->_height * ONE_HALF ) { + + for (int b=1; b_bone[o].springyPosition); + float distanceBetweenJoints = glm::length(vectorBetweenJoints); + + if ( distanceBetweenJoints > 0.0 ) { + float combinedRadius = _bone[b].radius + otherAvatar->_bone[o].radius; + + if ( distanceBetweenJoints < combinedRadius * 1.8) { + glm::vec3 directionVector = vectorBetweenJoints / distanceBetweenJoints; + + _bone[b].springyVelocity += directionVector * 0.1f * deltaTime; + _velocity += directionVector * 3.0f * deltaTime; + + float momentum = 1.0 - COLLISION_FRICTION * deltaTime; + if ( momentum < 0.0 ) { momentum = 0.0;} + _velocity *= momentum; + } + } + } + } + } +} + void Avatar::setDisplayingHead( bool displayingHead ) { _displayingHead = displayingHead; } @@ -965,12 +980,22 @@ void Avatar::initializeSkeleton() { calculateBoneLengths(); _pelvisStandingHeight = - _bone[ AVATAR_BONE_PELVIS_SPINE ].length + - _bone[ AVATAR_BONE_LEFT_THIGH ].length + + _bone[ AVATAR_BONE_LEFT_FOOT ].radius + _bone[ AVATAR_BONE_LEFT_SHIN ].length + - _bone[ AVATAR_BONE_LEFT_FOOT ].length + - _bone[ AVATAR_BONE_RIGHT_FOOT ].radius; - + _bone[ AVATAR_BONE_LEFT_THIGH ].length + + _bone[ AVATAR_BONE_PELVIS_SPINE ].length; + //printf( "_pelvisStandingHeight = %f\n", _pelvisStandingHeight ); + + _height = + ( + _pelvisStandingHeight + + _bone[ AVATAR_BONE_MID_SPINE ].length + + _bone[ AVATAR_BONE_CHEST_SPINE].length + + _bone[ AVATAR_BONE_NECK ].length + + _bone[ AVATAR_BONE_HEAD ].length + + _bone[ AVATAR_BONE_HEAD ].radius + ); + // generate world positions updateSkeleton(); } diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 0e6d600a32..bb0da768ba 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -32,8 +32,7 @@ const float YAW_MAG = 500.0; //JJV - changed from 300.0; const float TEST_YAW_DECAY = 5.0; const float LIN_VEL_DECAY = 5.0; -const float COLLISION_BODY_RADIUS = 0.1; -const float COLLISION_HEIGHT = 1.5; +const float COLLISION_FRICTION = 0.5; enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; @@ -103,7 +102,7 @@ struct AvatarBone glm::vec3 position; // the position at the "end" of the bone 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::dvec3 springyVelocity; // used for special effects ( the velocity of the springy 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 bone rotation off the parent @@ -255,25 +254,20 @@ private: Avatar* _interactingOther; bool _interactingOtherIsNearby; float _pelvisStandingHeight; + float _height; Balls* _balls; AvatarTouch _avatarTouch; bool _displayingHead; // should be false if in first-person view - // private methods... - void initializeSkeleton(); - void updateSkeleton(); - void initializeBodySprings(); - void updateBodySprings( float deltaTime ); - void calculateBoneLengths(); - void readSensors(); - void updateAvatarCollisionDetectionAndResponse - ( - glm::vec3 collisionPosition, - float collisionGirth, - float collisionHeight, - glm::vec3 collisionUpVector, - float deltaTime - ); + // private methods... + void initializeSkeleton(); + void updateSkeleton(); + void initializeBodySprings(); + void updateBodySprings( float deltaTime ); + void calculateBoneLengths(); + void readSensors(); + void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); + void updateCollisionWithOtherAvatar( Avatar * other, float deltaTime ); }; #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 291c665132..a926d77d5a 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -103,7 +103,7 @@ int HEIGHT = 800; int fullscreen = 0; float aspectRatio = 1.0f; -bool USING_FIRST_PERSON_EFFECT = true; +bool USING_FIRST_PERSON_EFFECT = false; bool wantColorRandomizer = true; // for addSphere and load file