From 26bbb9917b7b9ab096e3238048a4a800f510b6e2 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Mon, 3 Jun 2013 16:23:55 -0700 Subject: [PATCH] more work on avatar touch --- interface/src/Application.cpp | 2 +- interface/src/Avatar.cpp | 242 +++++++++++++++++++++++----------- interface/src/Avatar.h | 23 ++-- interface/src/Skeleton.cpp | 1 + interface/src/Skeleton.h | 1 + 5 files changed, 185 insertions(+), 84 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 130bd5e7fe..1480b81050 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -50,7 +50,7 @@ using namespace std; -const bool TESTING_AVATAR_TOUCH = false; +const bool TESTING_AVATAR_TOUCH = true; // Starfield information static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 4fb2846a0f..99ddd65853 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -44,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.01f; +const float MOUSE_RAY_TOUCH_RANGE = 0.01f; const float FLOATING_HEIGHT = 0.13f; const bool USING_HEAD_LEAN = false; const float LEAN_SENSITIVITY = 0.15; @@ -64,7 +64,8 @@ float chatMessageHeight = 0.20; Avatar::Avatar(Agent* owningAgent) : AvatarData(owningAgent), _head(this), - _TEST_bigSphereRadius(0.4f), + _ballSpringsInitialized(false), + _TEST_bigSphereRadius(0.5f), _TEST_bigSpherePosition(5.0f, _TEST_bigSphereRadius, 5.0f), _mousePressed(false), _bodyPitchDelta(0.0f), @@ -118,6 +119,8 @@ Avatar::Avatar(Agent* owningAgent) : void Avatar::initializeBodyBalls() { + _ballSpringsInitialized = false; //this gets set to true on the first update pass... + for (int b=0; b (1.0f - range)) { _bodyBall[b].touchForce = (dot - (1.0f - range)) / range; @@ -585,11 +670,6 @@ 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, getBodyFrontDirection())); - // test whether shoulders are close enough to allow for reaching to touch hands glm::vec3 v(_position - otherAvatar->_position); float distance = glm::length(v); @@ -689,16 +769,16 @@ 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_BODY_BALLS; b++) { - glm::vec3 vectorFromJointToBigSphereCenter(_bodyBall[b].position - position); - float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter); + glm::vec3 vectorFromBallToBigSphereCenter(_bodyBall[b].position - position); + float distanceToBigSphereCenter = glm::length(vectorFromBallToBigSphereCenter); float combinedRadius = _bodyBall[b].radius + radius; if (distanceToBigSphereCenter < combinedRadius) { if (distanceToBigSphereCenter > 0.0) { - glm::vec3 directionVector = vectorFromJointToBigSphereCenter / distanceToBigSphereCenter; + glm::vec3 directionVector = vectorFromBallToBigSphereCenter / distanceToBigSphereCenter; float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius); - glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration; + glm::vec3 collisionForce = vectorFromBallToBigSphereCenter * penetration; _velocity += collisionForce * 40.0f * deltaTime; _bodyBall[b].position = position + directionVector * combinedRadius; @@ -792,18 +872,18 @@ void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime for (int o=b+1; o_bodyBall[o].isCollidable) { - glm::vec3 vectorBetweenJoints(_bodyBall[b].position - otherAvatar->_bodyBall[o].position); - float distanceBetweenJoints = glm::length(vectorBetweenJoints); + glm::vec3 vectorBetweenBalls(_bodyBall[b].position - otherAvatar->_bodyBall[o].position); + float distanceBetweenBalls = glm::length(vectorBetweenBalls); - if (distanceBetweenJoints > 0.0) { // to avoid divide by zero + if (distanceBetweenBalls > 0.0) { // to avoid divide by zero float combinedRadius = _bodyBall[b].radius + otherAvatar->_bodyBall[o].radius; // check for collision - if (distanceBetweenJoints < combinedRadius * COLLISION_RADIUS_SCALAR) { - glm::vec3 directionVector = vectorBetweenJoints / distanceBetweenJoints; + if (distanceBetweenBalls < combinedRadius * COLLISION_RADIUS_SCALAR) { + glm::vec3 directionVector = vectorBetweenBalls / distanceBetweenBalls; // push balls away from each other and apply friction - float penetration = 1.0f - (distanceBetweenJoints / (combinedRadius * COLLISION_RADIUS_SCALAR)); + float penetration = 1.0f - (distanceBetweenBalls / (combinedRadius * COLLISION_RADIUS_SCALAR)); glm::vec3 ballPushForce = directionVector * COLLISION_BALL_FORCE * penetration * deltaTime; bodyPushForce += directionVector * COLLISION_BODY_FORCE * penetration * deltaTime; @@ -919,7 +999,12 @@ void Avatar::render(bool lookingInMirror) { void Avatar::resetBodyBalls() { for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - _bodyBall[b].position = _skeleton.joint[b].position; // put balls on joints + + glm::vec3 targetPosition + = _skeleton.joint[_bodyBall[b].parentJoint].position + + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; + + _bodyBall[b].position = targetPosition; // put ball on target position _bodyBall[b].velocity = glm::vec3(0.0f, 0.0f, 0.0f); } } @@ -931,30 +1016,39 @@ void Avatar::updateBodyBalls(float deltaTime) { resetBodyBalls(); } for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - glm::vec3 springVector(_bodyBall[b].position); - - if (b == BODY_BALL_PELVIS) { - springVector -= _position; - } - else { - 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; + + if (_ballSpringsInitialized) { + + //apply spring forces + glm::vec3 springVector(_bodyBall[b].position); - if (_skeleton.joint[b].parent != AVATAR_JOINT_NULL) { - _bodyBall[_skeleton.joint[b].parent].velocity += springDirection * force; + if (b == BODY_BALL_PELVIS) { + springVector -= _position; } + else { + springVector -= _bodyBall[_bodyBall[b].parentBall].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; + + if (_bodyBall[b].parentBall != BODY_BALL_NULL) { + _bodyBall[_bodyBall[b].parentBall].velocity += springDirection * force; + } + } } // 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; + glm::vec3 targetPosition + = _skeleton.joint[_bodyBall[b].parentJoint].position + + _skeleton.joint[_bodyBall[b].parentJoint].rotation * _bodyBall[b].parentOffset; + + _bodyBall[b].velocity += (targetPosition - _bodyBall[b].position) * _bodyBall[b].jointTightness * deltaTime; // apply decay float decay = 1.0 - BODY_SPRING_DECAY * deltaTime; @@ -1077,7 +1171,7 @@ void Avatar::renderBody(bool lookingInMirror) { } // Render the cone connecting this ball to its parent - if (_skeleton.joint[b].parent != AVATAR_JOINT_NULL) { + if (_bodyBall[b].parentBall != BODY_BALL_NULL) { if ((b != BODY_BALL_HEAD_TOP ) && (b != BODY_BALL_HEAD_BASE ) && (b != BODY_BALL_PELVIS ) @@ -1089,15 +1183,15 @@ void Avatar::renderBody(bool lookingInMirror) { && (b != BODY_BALL_RIGHT_SHOULDER)) { glColor3fv(DARK_SKIN_COLOR); - float r1 = _bodyBall[_skeleton.joint[b].parent ].radius * 0.8; - float r2 = _bodyBall[b ].radius * 0.8; + float r1 = _bodyBall[_bodyBall[b].parentBall ].radius * 0.8; + float r2 = _bodyBall[b].radius * 0.8; if (b == BODY_BALL_HEAD_BASE) { r1 *= 0.5f; } renderJointConnectingCone ( - _bodyBall[_skeleton.joint[b].parent ].position, - _bodyBall[b ].position, r2, r2 + _bodyBall[_bodyBall[b].parentBall].position, + _bodyBall[b].position, r2, r2 ); } } diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 8b5a67c7fb..3809678cd5 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -48,6 +48,9 @@ enum AvatarBodyBallID BODY_BALL_RIGHT_KNEE, BODY_BALL_RIGHT_HEEL, BODY_BALL_RIGHT_TOES, + +//TEST! +//BODY_BALL_LEFT_MID_THIGH, NUM_AVATAR_BODY_BALLS }; @@ -132,18 +135,21 @@ private: struct AvatarBall { - AvatarJointID parentJoint; - glm::vec3 parentOffset; - glm::vec3 position; - glm::vec3 velocity; - float jointTightness; - float radius; - bool isCollidable; - float touchForce; + AvatarJointID parentJoint; // the skeletal joint that serves as a reference for determining the position + glm::vec3 parentOffset; // a 3D vector in the frame of reference of the parent skeletal joint + AvatarBodyBallID parentBall; // the ball to which this ball is constrained for spring forces + glm::vec3 position; // the actual dynamic position of the ball at any given time + glm::vec3 velocity; // the velocity of the ball + float springLength; // the ideal length of the spring between this ball and its parentBall + float jointTightness; // how tightly the ball position attempts to stay at its ideal position (determined by parentOffset) + float radius; // the radius of the ball + bool isCollidable; // whether or not the ball responds to collisions + float touchForce; // a scalar determining the amount that the cursor (or hand) is penetrating the ball }; Head _head; Skeleton _skeleton; + bool _ballSpringsInitialized; float _TEST_bigSphereRadius; glm::vec3 _TEST_bigSpherePosition; bool _mousePressed; @@ -151,7 +157,6 @@ private: float _bodyYawDelta; float _bodyRollDelta; glm::vec3 _movedHandOffset; - glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; AvatarMode _mode; glm::vec3 _cameraPosition; diff --git a/interface/src/Skeleton.cpp b/interface/src/Skeleton.cpp index 64a8645247..e360b0f97f 100644 --- a/interface/src/Skeleton.cpp +++ b/interface/src/Skeleton.cpp @@ -101,6 +101,7 @@ void Skeleton::update(float deltaTime, const glm::quat& orientation, glm::vec3 p } } + float Skeleton::getArmLength() { return joint[ AVATAR_JOINT_RIGHT_ELBOW ].length + joint[ AVATAR_JOINT_RIGHT_WRIST ].length diff --git a/interface/src/Skeleton.h b/interface/src/Skeleton.h index 28d3a6e81e..5b979b47f3 100644 --- a/interface/src/Skeleton.h +++ b/interface/src/Skeleton.h @@ -55,6 +55,7 @@ public: float getHeight(); float getPelvisStandingHeight(); float getPelvisFloatingHeight(); + //glm::vec3 getJointVectorFromParent(AvatarJointID jointID) {return joint[jointID].position - joint[joint[jointID].parent].position; } struct AvatarJoint {