diff --git a/interface/resources/shaders/SkyFromAtmosphere.frag b/interface/resources/shaders/SkyFromAtmosphere.frag index b640f5f952..dbefc8270e 100644 --- a/interface/resources/shaders/SkyFromAtmosphere.frag +++ b/interface/resources/shaders/SkyFromAtmosphere.frag @@ -1,106 +1,106 @@ -#version 120 - -// -// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html: -// -// NVIDIA Statement on the Software -// -// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are -// detailed. -// -// No Warranty -// -// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL -// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// -// Limitation of Liability -// -// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR -// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT -// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY -// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH -// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS. -// - -// -// Atmospheric scattering fragment shader -// -// Author: Sean O'Neil -// -// Copyright (c) 2004 Sean O'Neil -// - -uniform vec3 v3CameraPos; // The camera's current position -uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels -uniform float fInnerRadius; // The inner (planetary) radius -uniform float fKrESun; // Kr * ESun -uniform float fKmESun; // Km * ESun -uniform float fKr4PI; // Kr * 4 * PI -uniform float fKm4PI; // Km * 4 * PI -uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) -uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) -uniform float fScaleOverScaleDepth; // fScale / fScaleDepth - -const int nSamples = 2; -const float fSamples = 2.0; - -uniform vec3 v3LightPos; -uniform float g; -uniform float g2; - -varying vec3 position; - -float scale(float fCos) -{ - float x = 1.0 - fCos; - return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); -} - -void main (void) -{ - // Get the ray from the camera to the vertex, and its length (which is the far point of the ray passing through the atmosphere) - vec3 v3Pos = position; - vec3 v3Ray = v3Pos - v3CameraPos; - float fFar = length(v3Ray); - v3Ray /= fFar; - - // Calculate the ray's starting position, then calculate its scattering offset - vec3 v3Start = v3CameraPos; - float fHeight = length(v3Start); - float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); - float fStartAngle = dot(v3Ray, v3Start) / fHeight; - float fStartOffset = fDepth * scale(fStartAngle); - - // Initialize the scattering loop variables - //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); - float fSampleLength = fFar / fSamples; - float fScaledLength = fSampleLength * fScale; - vec3 v3SampleRay = v3Ray * fSampleLength; - vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; - - // Now loop through the sample rays - vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); - for(int i=0; iisChecked()) { position = camera.getPosition(); } else { - position = _myAvatar.getHeadPosition(); + position = _myAvatar.getHeadJointPosition(); } float fov = camera.getFieldOfView(); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 995cb12a7f..bf100d733b 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -143,7 +143,7 @@ int audioCallback (const void* inputBuffer, unsigned char *currentPacketPtr = dataPacket + 1; // memcpy the three float positions - memcpy(currentPacketPtr, &interfaceAvatar->getHeadPosition(), sizeof(float) * 3); + memcpy(currentPacketPtr, &interfaceAvatar->getHeadJointPosition(), sizeof(float) * 3); currentPacketPtr += (sizeof(float) * 3); // tell the mixer not to add additional attenuation to our source diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 46a4d302ca..3949120737 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), @@ -101,10 +102,10 @@ Avatar::Avatar(Agent* owningAgent) : initializeBodyBalls(); - _height = _skeleton.getHeight() + _bodyBall[ AVATAR_JOINT_LEFT_HEEL ].radius + _bodyBall[ AVATAR_JOINT_HEAD_BASE ].radius; + _height = _skeleton.getHeight() + _bodyBall[ BODY_BALL_LEFT_HEEL ].radius + _bodyBall[ BODY_BALL_HEAD_BASE ].radius; _maxArmLength = _skeleton.getArmLength(); - _pelvisStandingHeight = _skeleton.getPelvisStandingHeight() + _bodyBall[ AVATAR_JOINT_LEFT_HEEL ].radius; - _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight() + _bodyBall[ AVATAR_JOINT_LEFT_HEEL ].radius; + _pelvisStandingHeight = _skeleton.getPelvisStandingHeight() + _bodyBall[ BODY_BALL_LEFT_HEEL ].radius; + _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight() + _bodyBall[ BODY_BALL_LEFT_HEEL ].radius; _avatarTouch.setReachableRadius(PERIPERSONAL_RADIUS); @@ -118,49 +119,142 @@ Avatar::Avatar(Agent* owningAgent) : void Avatar::initializeBodyBalls() { - for (int b=0; b (1.0f - range)) { _bodyBall[b].touchForce = (dot - (1.0f - range)) / range; @@ -557,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); @@ -579,7 +687,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { _avatarTouch.setHasInteractingOther(true); _avatarTouch.setYourBodyPosition(_interactingOther->_position); - _avatarTouch.setYourHandPosition(_interactingOther->_bodyBall[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); + _avatarTouch.setYourHandPosition(_interactingOther->_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].position); _avatarTouch.setYourOrientation (_interactingOther->getOrientation()); _avatarTouch.setYourHandState (_interactingOther->_handState); @@ -650,32 +758,29 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { } _avatarTouch.setMyHandState(_handState); - _avatarTouch.setMyHandPosition(_bodyBall[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); + _avatarTouch.setMyHandPosition(_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].position); } } void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float deltaTime) { float myBodyApproximateBoundingRadius = 1.0f; glm::vec3 vectorFromMyBodyToBigSphere(_position - position); - bool jointCollision = false; float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); if (distanceToBigSphere < myBodyApproximateBoundingRadius + radius) { - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - glm::vec3 vectorFromJointToBigSphereCenter(_bodyBall[b].position - position); - float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter); + for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { + glm::vec3 vectorFromBallToBigSphereCenter(_bodyBall[b].position - position); + float distanceToBigSphereCenter = glm::length(vectorFromBallToBigSphereCenter); float combinedRadius = _bodyBall[b].radius + radius; if (distanceToBigSphereCenter < combinedRadius) { - jointCollision = true; 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; - - _bodyBall[b].velocity += collisionForce * 0.0f * deltaTime; - _velocity += collisionForce * 40.0f * deltaTime; + glm::vec3 collisionForce = vectorFromBallToBigSphereCenter * penetration; + + _velocity += collisionForce * 40.0f * deltaTime; _bodyBall[b].position = position + directionVector * combinedRadius; } } @@ -729,7 +834,7 @@ void Avatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar _distanceToNearestAvatar = std::numeric_limits::max(); - //loop through all the other avatars for potential interactions... + // loop through all the other avatars for potential interactions... AgentList* agentList = AgentList::getInstance(); for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { @@ -739,7 +844,7 @@ void Avatar::updateAvatarCollisions(float deltaTime) { glm::vec3 vectorBetweenBoundingSpheres(_position - otherAvatar->_position); if (glm::length(vectorBetweenBoundingSpheres) < _height * ONE_HALF + otherAvatar->_height * ONE_HALF) { - //apply forces from collision + // apply forces from collision applyCollisionWithOtherAvatar(otherAvatar, deltaTime); } @@ -755,30 +860,30 @@ void Avatar::updateAvatarCollisions(float deltaTime) { } } -//detect collisions with other avatars and respond +// detect collisions with other avatars and respond void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime) { glm::vec3 bodyPushForce = glm::vec3(0.0f, 0.0f, 0.0f); - // loop through the joints of each avatar to check for every possible collision - for (int b=1; b_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; @@ -793,7 +898,7 @@ void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime } // b loop } // collidable - //apply force on the whole body + // apply force on the whole body _velocity += bodyPushForce; } @@ -833,7 +938,7 @@ void Avatar::render(bool lookingInMirror) { // render a simple round on the ground projected down from the avatar's position renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), 0.1f, 0.2f); - //render body + // render body renderBody(lookingInMirror); // if this is my avatar, then render my interactions with the other avatar @@ -857,7 +962,7 @@ void Avatar::render(bool lookingInMirror) { } glPushMatrix(); - glm::vec3 chatPosition = _bodyBall[AVATAR_JOINT_HEAD_BASE].position + getBodyUpDirection() * chatMessageHeight; + glm::vec3 chatPosition = _bodyBall[BODY_BALL_HEAD_BASE].position + getBodyUpDirection() * chatMessageHeight; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); @@ -893,61 +998,73 @@ void Avatar::render(bool lookingInMirror) { } void Avatar::resetBodyBalls() { - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - _bodyBall[b].position = _skeleton.joint[b].position; + for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { + + 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); } } void Avatar::updateBodyBalls(float deltaTime) { - // Check for a large repositioning, and re-initialize balls if this has happened + // Check for a large repositioning, and re-initialize balls if this has happened const float BEYOND_BODY_SPRING_RANGE = 2.f; - if (glm::length(_position - _bodyBall[AVATAR_JOINT_PELVIS].position) > BEYOND_BODY_SPRING_RANGE) { + if (glm::length(_position - _bodyBall[BODY_BALL_PELVIS].position) > BEYOND_BODY_SPRING_RANGE) { resetBodyBalls(); } - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - glm::vec3 springVector(_bodyBall[b].position); - - if (_skeleton.joint[b].parent == AVATAR_JOINT_NULL) { - 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; + for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { + + 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; if (decay > 0.0) { _bodyBall[b].velocity *= decay; - } - else { + } else { _bodyBall[b].velocity = glm::vec3(0.0f, 0.0f, 0.0f); } /* - //apply forces from touch... - if (_skeleton.joint[b].touchForce > 0.0) { - _skeleton.joint[b].springyVelocity += _mouseRayDirection * _skeleton.joint[b].touchForce * 0.7f; + // apply forces from touch... + if (_bodyBall[b].touchForce > 0.0) { + _bodyBall[b].velocity += _mouseRayDirection * _bodyBall[b].touchForce * 0.7f; } */ - //update position by velocity... + // update position by velocity... _bodyBall[b].position += _bodyBall[b].velocity * deltaTime; } } @@ -1010,8 +1127,8 @@ void Avatar::renderBody(bool lookingInMirror) { const float RENDER_TRANSLUCENT_BEYOND = 0.5f; // Render the body as balls and cones - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - float distanceToCamera = glm::length(_cameraPosition - _skeleton.joint[b].position); + for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { + float distanceToCamera = glm::length(_cameraPosition - _bodyBall[b].position); float alpha = lookingInMirror ? 1.0f : glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f); @@ -1021,18 +1138,18 @@ void Avatar::renderBody(bool lookingInMirror) { } // Always render other people, and render myself when beyond threshold distance - if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special + if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special if (lookingInMirror || _owningAgent || distanceToCamera > RENDER_OPAQUE_BEYOND * 0.5) { _head.render(lookingInMirror, _cameraPosition, alpha); } } else if (_owningAgent || distanceToCamera > RENDER_TRANSLUCENT_BEYOND - || b == AVATAR_JOINT_RIGHT_ELBOW - || b == AVATAR_JOINT_RIGHT_WRIST - || b == AVATAR_JOINT_RIGHT_FINGERTIPS ) { - // Render the sphere at the joint - if (_owningAgent || b == AVATAR_JOINT_RIGHT_ELBOW - || b == AVATAR_JOINT_RIGHT_WRIST - || b == AVATAR_JOINT_RIGHT_FINGERTIPS ) { + || b == BODY_BALL_RIGHT_ELBOW + || b == BODY_BALL_RIGHT_WRIST + || b == BODY_BALL_RIGHT_FINGERTIPS ) { + // Render the body ball sphere + if (_owningAgent || b == BODY_BALL_RIGHT_ELBOW + || b == BODY_BALL_RIGHT_WRIST + || b == BODY_BALL_RIGHT_FINGERTIPS ) { glColor3f(SKIN_COLOR[0] + _bodyBall[b].touchForce * 0.3f, SKIN_COLOR[1] - _bodyBall[b].touchForce * 0.2f, SKIN_COLOR[2] - _bodyBall[b].touchForce * 0.1f); @@ -1043,36 +1160,36 @@ void Avatar::renderBody(bool lookingInMirror) { alpha); } - if ((b != AVATAR_JOINT_HEAD_TOP ) - && (b != AVATAR_JOINT_HEAD_BASE )) { + if ((b != BODY_BALL_HEAD_TOP ) + && (b != BODY_BALL_HEAD_BASE )) { glPushMatrix(); glTranslatef(_bodyBall[b].position.x, _bodyBall[b].position.y, _bodyBall[b].position.z); glutSolidSphere(_bodyBall[b].radius, 20.0f, 20.0f); glPopMatrix(); } - // Render the cone connecting this joint to its parent - if (_skeleton.joint[b].parent != AVATAR_JOINT_NULL) { - if ((b != AVATAR_JOINT_HEAD_TOP ) - && (b != AVATAR_JOINT_HEAD_BASE ) - && (b != AVATAR_JOINT_PELVIS ) - && (b != AVATAR_JOINT_TORSO ) - && (b != AVATAR_JOINT_CHEST ) - && (b != AVATAR_JOINT_LEFT_COLLAR ) - && (b != AVATAR_JOINT_LEFT_SHOULDER ) - && (b != AVATAR_JOINT_RIGHT_COLLAR ) - && (b != AVATAR_JOINT_RIGHT_SHOULDER)) { + // Render the cone connecting this ball to its parent + if (_bodyBall[b].parentBall != BODY_BALL_NULL) { + if ((b != BODY_BALL_HEAD_TOP ) + && (b != BODY_BALL_HEAD_BASE ) + && (b != BODY_BALL_PELVIS ) + && (b != BODY_BALL_TORSO ) + && (b != BODY_BALL_CHEST ) + && (b != BODY_BALL_LEFT_COLLAR ) + && (b != BODY_BALL_LEFT_SHOULDER ) + && (b != BODY_BALL_RIGHT_COLLAR ) + && (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; - if (b == AVATAR_JOINT_HEAD_BASE) { + 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 ); } } @@ -1110,7 +1227,7 @@ void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity _head.setYaw (angles.x); _head.setPitch(angles.y); _head.setRoll (angles.z); - //printLog("Y/P/R: %3.1f, %3.1f, %3.1f\n", angles.x, angles.y, angles.z); + // printLog("Y/P/R: %3.1f, %3.1f, %3.1f\n", angles.x, angles.y, angles.z); } } diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 6746ba51cd..3809678cd5 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -20,6 +20,40 @@ #include "Skeleton.h" #include "Transmitter.h" + +enum AvatarBodyBallID +{ + BODY_BALL_NULL = -1, + BODY_BALL_PELVIS, + BODY_BALL_TORSO, + BODY_BALL_CHEST, + BODY_BALL_NECK_BASE, + BODY_BALL_HEAD_BASE, + BODY_BALL_HEAD_TOP, + BODY_BALL_LEFT_COLLAR, + BODY_BALL_LEFT_SHOULDER, + BODY_BALL_LEFT_ELBOW, + BODY_BALL_LEFT_WRIST, + BODY_BALL_LEFT_FINGERTIPS, + BODY_BALL_RIGHT_COLLAR, + BODY_BALL_RIGHT_SHOULDER, + BODY_BALL_RIGHT_ELBOW, + BODY_BALL_RIGHT_WRIST, + BODY_BALL_RIGHT_FINGERTIPS, + BODY_BALL_LEFT_HIP, + BODY_BALL_LEFT_KNEE, + BODY_BALL_LEFT_HEEL, + BODY_BALL_LEFT_TOES, + BODY_BALL_RIGHT_HIP, + BODY_BALL_RIGHT_KNEE, + BODY_BALL_RIGHT_HEEL, + BODY_BALL_RIGHT_TOES, + +//TEST! +//BODY_BALL_LEFT_MID_THIGH, + NUM_AVATAR_BODY_BALLS +}; + enum DriveKeys { FWD = 0, @@ -64,19 +98,14 @@ public: void setOrientation (const glm::quat& orientation); //getters - - float getHeadYawRate () const { return _head.yawRate;} - float getBodyYaw () const { return _bodyYaw;} - bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();} - const glm::vec3& getHeadPosition () const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;} - const glm::vec3& getSpringyHeadPosition () const { return _bodyBall[ AVATAR_JOINT_HEAD_BASE ].position;} - const glm::vec3& getJointPosition (AvatarJointID j) const { return _bodyBall[j].position;} - - glm::vec3 getBodyRightDirection () const { return getOrientation() * AVATAR_RIGHT; } - glm::vec3 getBodyUpDirection () const { return getOrientation() * AVATAR_UP; } - glm::vec3 getBodyFrontDirection () const { return getOrientation() * AVATAR_FRONT; } - - + float getHeadYawRate () const { return _head.yawRate;} + float getBodyYaw () const { return _bodyYaw;} + bool getIsNearInteractingOther () const { return _avatarTouch.getAbleToReachOtherAvatar();} + const glm::vec3& getHeadJointPosition () const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;} + const glm::vec3& getBallPosition (AvatarJointID j) const { return _bodyBall[j].position;} + glm::vec3 getBodyRightDirection () const { return getOrientation() * AVATAR_RIGHT; } + glm::vec3 getBodyUpDirection () const { return getOrientation() * AVATAR_UP; } + glm::vec3 getBodyFrontDirection () const { return getOrientation() * AVATAR_FRONT; } const glm::vec3& getVelocity () const { return _velocity;} float getSpeed () const { return _speed;} float getHeight () const { return _height;} @@ -106,16 +135,21 @@ private: struct AvatarBall { - 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; @@ -123,8 +157,7 @@ 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_JOINTS ]; + AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; AvatarMode _mode; glm::vec3 _cameraPosition; glm::vec3 _handHoldingPosition; diff --git a/interface/src/Skeleton.cpp b/interface/src/Skeleton.cpp index 64a8645247..55c6210068 100644 --- a/interface/src/Skeleton.cpp +++ b/interface/src/Skeleton.cpp @@ -14,7 +14,7 @@ Skeleton::Skeleton() { void Skeleton::initialize() { - for (int b=0; b