From f4109b3fb4fe0e5c0f25d241966ed6ef71715b57 Mon Sep 17 00:00:00 2001 From: LionTurtle Date: Wed, 21 Aug 2013 13:24:54 -0700 Subject: [PATCH] Add MyAvatar subclass. For functions such as render() and simulate(), they have been edited so that there are MyAvatar and Avatar specific versions in their respective classes. isMyAvatar() has been removed. --- interface/src/Application.h | 5 +- interface/src/avatar/Avatar.cpp | 820 ++------------------------------ interface/src/avatar/Avatar.h | 126 ++--- interface/src/avatar/Hand.cpp | 2 +- 4 files changed, 69 insertions(+), 884 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 88cb86312f..75632d251f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -44,6 +44,7 @@ #include "Webcam.h" #include "PieMenu.h" #include "avatar/Avatar.h" +#include "avatar/MyAvatar.h" #include "avatar/HandControl.h" #include "renderer/GeometryCache.h" #include "renderer/GlowEffect.h" @@ -106,7 +107,7 @@ public: void updateParticleSystem(float deltaTime); QGLWidget* getGLWidget() { return _glWidget; } - Avatar* getAvatar() { return &_myAvatar; } + MyAvatar* getAvatar() { return &_myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } @@ -371,7 +372,7 @@ private: Oscilloscope _audioScope; - Avatar _myAvatar; // The rendered avatar of oneself + MyAvatar _myAvatar; // The rendered avatar of oneself Transmitter _myTransmitter; // Gets UDP data from transmitter app used to animate the avatar diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e561720eaf..58e622032d 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -58,60 +58,44 @@ const float SKIN_COLOR[] = {1.0, 0.84, 0.66}; const float DARK_SKIN_COLOR[] = {0.9, 0.78, 0.63}; const int NUM_BODY_CONE_SIDES = 9; -bool usingBigSphereCollisionTest = true; +const bool usingBigSphereCollisionTest = true; -float chatMessageScale = 0.0015; -float chatMessageHeight = 0.20; +const float chatMessageScale = 0.0015; +const float chatMessageHeight = 0.20; Avatar::Avatar(Node* owningNode) : AvatarData(owningNode), - _initialized(false), _head(this), _hand(this), _ballSpringsInitialized(false), _TEST_bigSphereRadius(0.5f), _TEST_bigSpherePosition(5.0f, _TEST_bigSphereRadius, 5.0f), - _mousePressed(false), - _bodyPitchDelta(0.0f), _bodyYawDelta(0.0f), - _bodyRollDelta(0.0f), + // _bodyRollDelta(0.0f), _movedHandOffset(0.0f, 0.0f, 0.0f), _mode(AVATAR_MODE_STANDING), - _handHoldingPosition(0.0f, 0.0f, 0.0f), _velocity(0.0f, 0.0f, 0.0f), _thrust(0.0f, 0.0f, 0.0f), - _shouldJump(false), _speed(0.0f), - _maxArmLength(0.0f), _leanScale(0.5f), - _pelvisStandingHeight(0.0f), + _pelvisFloatingHeight(0.0f), _scale(1.0f), - _distanceToNearestAvatar(std::numeric_limits::max()), - _gravity(0.0f, -1.0f, 0.0f), _worldUpDirection(DEFAULT_UP_DIRECTION), _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), - _interactingOther(NULL), - _isMouseTurningRight(false), - _elapsedTimeMoving(0.0f), - _elapsedTimeStopped(0.0f), - _elapsedTimeSinceCollision(0.0f), - _lastCollisionPosition(0, 0, 0), - _speedBrakes(false), - _isThrustOn(false), _isCollisionsOn(true), _leadingAvatar(NULL), - _voxels(this) + _voxels(this), + _initialized(false), + _handHoldingPosition(0.0f, 0.0f, 0.0f), + _maxArmLength(0.0f), + _pelvisStandingHeight(0.0f) { // give the pointer to our head to inherited _headData variable from AvatarData _headData = &_head; _handData = &_hand; - for (int i = 0; i < MAX_DRIVE_KEYS; i++) { - _driveKeys[i] = false; - } - _skeleton.initialize(); initializeBodyBalls(); @@ -130,8 +114,6 @@ Avatar::Avatar(Node* owningNode) : } else { _balls = NULL; } - - _collisionRadius = _height * 0.125f; } @@ -289,85 +271,6 @@ void Avatar::init() { _initialized = true; } -void Avatar::reset() { - _head.reset(); - _hand.reset(); -} - -// Update avatar head rotation with sensor data -void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, - float pitchFromTouch) { - SerialInterface* gyros = Application::getInstance()->getSerialHeadSensor(); - Webcam* webcam = Application::getInstance()->getWebcam(); - glm::vec3 estimatedPosition, estimatedRotation; - if (gyros->isActive()) { - estimatedRotation = gyros->getEstimatedRotation(); - - } else if (webcam->isActive()) { - estimatedRotation = webcam->getEstimatedRotation(); - - } else if (_leadingAvatar) { - _head.getFace().clearFrame(); - return; - } else { - _head.setMousePitch(pitchFromTouch); - _head.setPitch(pitchFromTouch); - _head.getFace().clearFrame(); - return; - } - _head.setMousePitch(pitchFromTouch); - - if (webcam->isActive()) { - estimatedPosition = webcam->getEstimatedPosition(); - - // apply face data - _head.getFace().setFrameFromWebcam(); - - // compute and store the joint rotations - const JointVector& joints = webcam->getEstimatedJoints(); - _joints.clear(); - for (int i = 0; i < NUM_AVATAR_JOINTS; i++) { - if (joints.size() > i && joints[i].isValid) { - JointData data = { i, joints[i].rotation }; - _joints.push_back(data); - - if (i == AVATAR_JOINT_CHEST) { - // if we have a chest rotation, don't apply lean based on head - estimatedPosition = glm::vec3(); - } - } - } - } else { - _head.getFace().clearFrame(); - } - - // Set the rotation of the avatar's head (as seen by others, not affecting view frustum) - // to be scaled. Pitch is greater to emphasize nodding behavior / synchrony. - const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f; - const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f; - const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f; - _head.setPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); - _head.setYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); - _head.setRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); - _head.setCameraFollowsHead(gyroLook); - - // Update torso lean distance based on accelerometer data - const float TORSO_LENGTH = _scale * 0.5f; - const float MAX_LEAN = 45.0f; - _head.setLeanSideways(glm::clamp(glm::degrees(atanf(estimatedPosition.x * _leanScale / TORSO_LENGTH)), - -MAX_LEAN, MAX_LEAN)); - _head.setLeanForward(glm::clamp(glm::degrees(atanf(estimatedPosition.z * _leanScale / TORSO_LENGTH)), - -MAX_LEAN, MAX_LEAN)); -} - -float Avatar::getAbsoluteHeadYaw() const { - return glm::yaw(_head.getOrientation()); -} - -float Avatar::getAbsoluteHeadPitch() const { - return glm::pitch(_head.getOrientation()); -} - glm::quat Avatar::getOrientation() const { return glm::quat(glm::radians(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll))); } @@ -376,144 +279,6 @@ glm::quat Avatar::getWorldAlignedOrientation () const { return computeRotationFromBodyToWorldUp() * getOrientation(); } -glm::vec3 Avatar::getUprightHeadPosition() const { - return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, _pelvisToHeadLength, 0.0f); -} - -glm::vec3 Avatar::getUprightEyeLevelPosition() const { - const float EYE_UP_OFFSET = 0.36f; - glm::vec3 up = getWorldAlignedOrientation() * IDENTITY_UP; - return _position + up * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET + glm::vec3(0.0f, _pelvisToHeadLength, 0.0f); -} - -glm::vec3 Avatar::getEyePosition() { - const float EYE_UP_OFFSET = 0.36f; - const float EYE_FRONT_OFFSET = 0.8f; - - glm::quat orientation = getWorldAlignedOrientation(); - glm::vec3 up = orientation * IDENTITY_UP; - glm::vec3 front = orientation * IDENTITY_FRONT; - - float scale = _scale * BODY_BALL_RADIUS_HEAD_BASE; - - return getHead().getPosition() + up * scale * EYE_UP_OFFSET + front * scale * EYE_FRONT_OFFSET; -} - -void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { - // - // Gather thrust information from keyboard and sensors to apply to avatar motion - // - glm::quat orientation = getHead().getCameraOrientation(); - glm::vec3 front = orientation * IDENTITY_FRONT; - glm::vec3 right = orientation * IDENTITY_RIGHT; - glm::vec3 up = orientation * IDENTITY_UP; - - const float THRUST_MAG_UP = 800.0f; - const float THRUST_MAG_DOWN = 300.f; - const float THRUST_MAG_FWD = 500.f; - const float THRUST_MAG_BACK = 300.f; - const float THRUST_MAG_LATERAL = 250.f; - const float THRUST_JUMP = 120.f; - - // Add Thrusts from keyboard - if (_driveKeys[FWD ]) {_thrust += _scale * THRUST_MAG_FWD * deltaTime * front;} - if (_driveKeys[BACK ]) {_thrust -= _scale * THRUST_MAG_BACK * deltaTime * front;} - if (_driveKeys[RIGHT ]) {_thrust += _scale * THRUST_MAG_LATERAL * deltaTime * right;} - if (_driveKeys[LEFT ]) {_thrust -= _scale * THRUST_MAG_LATERAL * deltaTime * right;} - if (_driveKeys[UP ]) {_thrust += _scale * THRUST_MAG_UP * deltaTime * up;} - if (_driveKeys[DOWN ]) {_thrust -= _scale * THRUST_MAG_DOWN * deltaTime * up;} - if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;} - if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;} - - // Add one time jumping force if requested - if (_shouldJump) { - _thrust += _scale * THRUST_JUMP * up; - _shouldJump = false; - } - - - // Add thrusts from leading avatar - const float FOLLOWING_RATE = 0.02f; - const float MIN_YAW = 5.0f; - const float MIN_PITCH = 1.0f; - const float PITCH_RATE = 0.1f; - const float MIN_YAW_BEFORE_PITCH = 30.0f; - - if (_leadingAvatar != NULL) { - glm::vec3 toTarget = _leadingAvatar->getPosition() - _position; - - if (glm::length(_position - _leadingAvatar->getPosition()) > _scale * _stringLength) { - _position += toTarget * FOLLOWING_RATE; - } else { - toTarget = _leadingAvatar->getHead().getLookAtPosition() - _head.getPosition(); - } - toTarget = glm::vec3(glm::dot(right, toTarget), - glm::dot(up , toTarget), - glm::dot(front, toTarget)); - - float yawAngle = angleBetween(-IDENTITY_FRONT, glm::vec3(toTarget.x, 0.f, toTarget.z)); - if (glm::abs(yawAngle) > MIN_YAW){ - if (IDENTITY_RIGHT.x * toTarget.x + IDENTITY_RIGHT.y * toTarget.y + IDENTITY_RIGHT.z * toTarget.z > 0) { - _bodyYawDelta -= yawAngle; - } else { - _bodyYawDelta += yawAngle; - } - } - - float pitchAngle = glm::abs(90.0f - angleBetween(IDENTITY_UP, toTarget)); - if (glm::abs(pitchAngle) > MIN_PITCH && yawAngle < MIN_YAW_BEFORE_PITCH){ - if (IDENTITY_UP.x * toTarget.x + IDENTITY_UP.y * toTarget.y + IDENTITY_UP.z * toTarget.z > 0) { - _head.setMousePitch(_head.getMousePitch() + PITCH_RATE * pitchAngle); - } else { - _head.setMousePitch(_head.getMousePitch() - PITCH_RATE * pitchAngle); - } - _head.setPitch(_head.getMousePitch()); - } - } - - - // Add thrusts from Transmitter - if (transmitter) { - transmitter->checkForLostTransmitter(); - glm::vec3 rotation = transmitter->getEstimatedRotation(); - const float TRANSMITTER_MIN_RATE = 1.f; - const float TRANSMITTER_MIN_YAW_RATE = 4.f; - const float TRANSMITTER_LATERAL_FORCE_SCALE = 5.f; - const float TRANSMITTER_FWD_FORCE_SCALE = 25.f; - const float TRANSMITTER_UP_FORCE_SCALE = 100.f; - const float TRANSMITTER_YAW_SCALE = 10.0f; - const float TRANSMITTER_LIFT_SCALE = 3.f; - const float TOUCH_POSITION_RANGE_HALF = 32767.f; - if (fabs(rotation.z) > TRANSMITTER_MIN_RATE) { - _thrust += rotation.z * TRANSMITTER_LATERAL_FORCE_SCALE * deltaTime * right; - } - if (fabs(rotation.x) > TRANSMITTER_MIN_RATE) { - _thrust += -rotation.x * TRANSMITTER_FWD_FORCE_SCALE * deltaTime * front; - } - if (fabs(rotation.y) > TRANSMITTER_MIN_YAW_RATE) { - _bodyYawDelta += rotation.y * TRANSMITTER_YAW_SCALE * deltaTime; - } - if (transmitter->getTouchState()->state == 'D') { - _thrust += TRANSMITTER_UP_FORCE_SCALE * - (float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF * - TRANSMITTER_LIFT_SCALE * - deltaTime * - up; - } - } - - // Update speed brake status - const float MIN_SPEED_BRAKE_VELOCITY = _scale * 0.4f; - if ((glm::length(_thrust) == 0.0f) && _isThrustOn && (glm::length(_velocity) > MIN_SPEED_BRAKE_VELOCITY)) { - _speedBrakes = true; - } - - if (_speedBrakes && (glm::length(_velocity) < MIN_SPEED_BRAKE_VELOCITY)) { - _speedBrakes = false; - } - _isThrustOn = (glm::length(_thrust) > EPSILON); -} - void Avatar::follow(Avatar* leadingAvatar) { const float MAX_STRING_LENGTH = 2; @@ -535,55 +300,16 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCamer glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; - // Update movement timers - if (isMyAvatar()) { - _elapsedTimeSinceCollision += deltaTime; - const float VELOCITY_MOVEMENT_TIMER_THRESHOLD = 0.2f; - if (glm::length(_velocity) < VELOCITY_MOVEMENT_TIMER_THRESHOLD) { - _elapsedTimeMoving = 0.f; - _elapsedTimeStopped += deltaTime; - } else { - _elapsedTimeStopped = 0.f; - _elapsedTimeMoving += deltaTime; - } - } - if (_leadingAvatar && !_leadingAvatar->getOwningNode()->isAlive()) { follow(NULL); } - // Ajust, scale, position and lookAt position when following an other avatar - if (isMyAvatar() && _leadingAvatar && _newScale != _leadingAvatar->getScale()) { - _newScale = _leadingAvatar->getScale(); - } - - if (isMyAvatar() && _scale != _newScale) { - float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _newScale; - setScale(scale); - Application::getInstance()->getCamera()->setScale(scale); - } - - if (!isMyAvatar() && _scale != _newScale) { + if (_scale != _newScale) { setScale(_newScale); } - // Collect thrust forces from keyboard and devices - if (isMyAvatar()) { - updateThrust(deltaTime, transmitter); - } - // copy velocity so we can use it later for acceleration glm::vec3 oldVelocity = getVelocity(); - - if (isMyAvatar()) { - // calculate speed - _speed = glm::length(_velocity); - } - - //figure out if the mouse cursor is over any body spheres... - if (isMyAvatar()) { - checkForMouseRayTouching(); - } // update balls if (_balls) { @@ -632,42 +358,11 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCamer } // if this is not my avatar, then hand position comes from transmitted data - if (!isMyAvatar()) { - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; - } + _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; //update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); _avatarTouch.simulate(deltaTime); - - if (isMyAvatar()) { - - // apply gravity - if (USING_AVATAR_GRAVITY) { - // For gravity, always move the avatar by the amount driven by gravity, so that the collision - // routines will detect it and collide every frame when pulled by gravity to a surface - // - const float MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY = 0.02f; - if (glm::length(_position - _lastCollisionPosition) > MIN_DISTANCE_AFTER_COLLISION_FOR_GRAVITY) { - _velocity += _scale * _gravity * (GRAVITY_EARTH * deltaTime); - } - } - - if (_isCollisionsOn) { - Camera* myCamera = Application::getInstance()->getCamera(); - - if (myCamera->getMode() == CAMERA_MODE_FIRST_PERSON) { - _collisionRadius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.f)); - _collisionRadius *= COLLISION_RADIUS_SCALAR; - } else { - _collisionRadius = _height * .125f; - } - - updateCollisionWithEnvironment(deltaTime); - updateCollisionWithVoxels(deltaTime); - updateAvatarCollisions(deltaTime); - } - } // update body balls updateBodyBalls(deltaTime); @@ -678,93 +373,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCamer updateCollisionWithSphere(_TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime); } - - if (isMyAvatar()) { - - // add thrust to velocity - _velocity += _thrust * deltaTime; - - // update body yaw by body yaw delta - orientation = orientation * glm::quat(glm::radians( - glm::vec3(_bodyPitchDelta, _bodyYawDelta, _bodyRollDelta) * deltaTime)); - // decay body rotation momentum - - const float BODY_SPIN_FRICTION = 7.5f; - float bodySpinMomentum = 1.0 - BODY_SPIN_FRICTION * deltaTime; - if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; } - _bodyPitchDelta *= bodySpinMomentum; - _bodyYawDelta *= bodySpinMomentum; - _bodyRollDelta *= bodySpinMomentum; - - float MINIMUM_ROTATION_RATE = 2.0f; - if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.f; } - if (fabs(_bodyRollDelta) < MINIMUM_ROTATION_RATE) { _bodyRollDelta = 0.f; } - if (fabs(_bodyPitchDelta) < MINIMUM_ROTATION_RATE) { _bodyPitchDelta = 0.f; } - - const float MAX_STATIC_FRICTION_VELOCITY = 0.5f; - const float STATIC_FRICTION_STRENGTH = _scale * 20.f; - applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_VELOCITY, STATIC_FRICTION_STRENGTH); - - const float LINEAR_DAMPING_STRENGTH = 1.0f; - const float SPEED_BRAKE_POWER = _scale * 10.0f; - const float SQUARED_DAMPING_STRENGTH = 0.2f; - if (_speedBrakes) { - applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH * SPEED_BRAKE_POWER, SQUARED_DAMPING_STRENGTH * SPEED_BRAKE_POWER); - } else { - applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH, SQUARED_DAMPING_STRENGTH); - } - - //pitch and roll the body as a function of forward speed and turning delta - const float BODY_PITCH_WHILE_WALKING = -20.0; - const float BODY_ROLL_WHILE_TURNING = 0.2; - float forwardComponentOfVelocity = glm::dot(getBodyFrontDirection(), _velocity); - orientation = orientation * glm::quat(glm::radians(glm::vec3( - BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity, 0.0f, - BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta))); - - // these forces keep the body upright... - const float BODY_UPRIGHT_FORCE = _scale * 10.0; - float tiltDecay = BODY_UPRIGHT_FORCE * deltaTime; - if (tiltDecay > 1.0f) {tiltDecay = 1.0f;} - - // update the euler angles - setOrientation(orientation); - - //the following will be used to make the avatar upright no matter what gravity is - setOrientation(computeRotationFromBodyToWorldUp(tiltDecay) * orientation); - - // Compute instantaneous acceleration - float forwardAcceleration = glm::length(glm::dot(getBodyFrontDirection(), getVelocity() - oldVelocity)) / deltaTime; - const float ACCELERATION_PITCH_DECAY = 0.4f; - const float ACCELERATION_YAW_DECAY = 0.4f; - const float ACCELERATION_PULL_THRESHOLD = 0.2f; - const float OCULUS_ACCELERATION_PULL_THRESHOLD = 1.0f; - const int OCULUS_YAW_OFFSET_THRESHOLD = 10; - - // Decay HeadPitch as a function of acceleration, so that you look straight ahead when - // you start moving, but don't do this with an HMD like the Oculus. - if (!OculusManager::isConnected()) { - if (forwardAcceleration > ACCELERATION_PULL_THRESHOLD) { - _head.setPitch(_head.getPitch() * (1.f - forwardAcceleration * ACCELERATION_PITCH_DECAY * deltaTime)); - _head.setYaw(_head.getYaw() * (1.f - forwardAcceleration * ACCELERATION_YAW_DECAY * deltaTime)); - } - } else if (fabsf(forwardAcceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD - && fabs(_head.getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) { - // if we're wearing the oculus - // and this acceleration is above the pull threshold - // and the head yaw if off the body by more than OCULUS_YAW_OFFSET_THRESHOLD - - // match the body yaw to the oculus yaw - _bodyYaw = getAbsoluteHeadYaw(); - - // set the head yaw to zero for this draw - _head.setYaw(0); - - // correct the oculus yaw offset - OculusManager::updateYawOffset(); - } - } - //apply the head lean values to the ball positions... if (USING_HEAD_LEAN) { if (fabs(_head.getLeanSideways() + _head.getLeanForward()) > 0.0f) { @@ -795,11 +403,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCamer _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); _head.setScale(_scale); _head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2])); - _head.simulate(deltaTime, isMyAvatar(), gyroCameraSensitivity); - _hand.simulate(deltaTime, isMyAvatar()); - - - + _head.simulate(deltaTime, false, gyroCameraSensitivity); + _hand.simulate(deltaTime, false); // use speed and angular velocity to determine walking vs. standing if (_speed + fabs(_bodyYawDelta) > 0.2) { @@ -816,35 +421,11 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter, float gyroCamer } -void Avatar::checkForMouseRayTouching() { - - for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - - glm::vec3 directionToBodySphere = glm::normalize(_bodyBall[b].position - _mouseRayOrigin); - float dot = glm::dot(directionToBodySphere, _mouseRayDirection); - - float range = _bodyBall[b].radius * MOUSE_RAY_TOUCH_RANGE; - - if (dot > (1.0f - range)) { - _bodyBall[b].touchForce = (dot - (1.0f - range)) / range; - } else { - _bodyBall[b].touchForce = 0.0; - } - } -} - void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction ) { _mouseRayOrigin = origin; _mouseRayDirection = direction; } -void Avatar::setOrientation(const glm::quat& orientation) { - glm::vec3 eulerAngles = safeEulerAngles(orientation); - _bodyPitch = eulerAngles.x; - _bodyYaw = eulerAngles.y; - _bodyRoll = eulerAngles.z; -} - void Avatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovement) { glm::quat orientation = getOrientation(); @@ -863,127 +444,11 @@ void Avatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovem _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement; } - if (isMyAvatar()) { - _avatarTouch.setMyBodyPosition(_position); - _avatarTouch.setMyOrientation(orientation); - - float closestDistance = std::numeric_limits::max(); - - _interactingOther = NULL; - - //loop through all the other avatars for potential interactions... - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - Avatar *otherAvatar = (Avatar *)node->getLinkedData(); - - // test whether shoulders are close enough to allow for reaching to touch hands - glm::vec3 v(_position - otherAvatar->_position); - float distance = glm::length(v); - if (distance < closestDistance) { - closestDistance = distance; - - if (distance < _scale * PERIPERSONAL_RADIUS) { - _interactingOther = otherAvatar; - } - } - } - } - - if (_interactingOther) { - - _avatarTouch.setHasInteractingOther(true); - _avatarTouch.setYourBodyPosition(_interactingOther->_position); - _avatarTouch.setYourHandPosition(_interactingOther->_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].position); - _avatarTouch.setYourOrientation (_interactingOther->getOrientation()); - _avatarTouch.setYourHandState (_interactingOther->_handState); - - //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); - } - } - } - - glm::vec3 vectorFromMyHandToYourHand - ( - _interactingOther->_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - ); - - float distanceBetweenOurHands = glm::length(vectorFromMyHandToYourHand); - - /* - // if my arm can no longer reach the other hand, turn off hand-holding - if (!_avatarTouch.getAbleToReachOtherAvatar()) { - _avatarTouch.setHoldingHands(false); - } - if (distanceBetweenOurHands > _maxArmLength) { - _avatarTouch.setHoldingHands(false); - } - */ - - // if neither of us are grasping, turn off hand-holding - if ((_handState != HAND_STATE_GRASPING ) && (_interactingOther->_handState != HAND_STATE_GRASPING)) { - _avatarTouch.setHoldingHands(false); - } - - //if holding hands, apply the appropriate forces - if (_avatarTouch.getHoldingHands()) { - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += - ( - _interactingOther->_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - ) * 0.5f; - - if (distanceBetweenOurHands > 0.3) { - float force = 10.0f * deltaTime; - if (force > 1.0f) {force = 1.0f;} - _velocity += vectorFromMyHandToYourHand * force; - } - } - } else { - _avatarTouch.setHasInteractingOther(false); - } - - // If there's a leap-interaction hand visible, use that as the endpoint - glm::vec3 rightMostHand; - bool anyHandsFound = false; - for (size_t i = 0; i < getHand().getPalms().size(); ++i) { - PalmData& palm = getHand().getPalms()[i]; - if (palm.isActive()) { - if (!anyHandsFound - || palm.getRawPosition().x > rightMostHand.x) { - _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = palm.getPosition(); - rightMostHand = palm.getRawPosition(); - } - anyHandsFound = true; - } - } - }//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 if (enableHandMovement) { updateArmIKAndConstraints(deltaTime); } - - //Set right hand position and state to be transmitted, and also tell AvatarTouch about it - if (isMyAvatar()) { - setHandPosition(_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); - - if (_mousePressed) { - _handState = HAND_STATE_GRASPING; - } else { - _handState = HAND_STATE_NULL; - } - - _avatarTouch.setMyHandState(_handState); - _avatarTouch.setMyHandPosition(_bodyBall[ BODY_BALL_RIGHT_FINGERTIPS ].position); - } } void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float deltaTime) { @@ -1012,195 +477,13 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d } } -void Avatar::updateCollisionWithEnvironment(float deltaTime) { - glm::vec3 up = getBodyUpDirection(); - float radius = _collisionRadius; - const float ENVIRONMENT_SURFACE_ELASTICITY = 1.0f; - const float ENVIRONMENT_SURFACE_DAMPING = 0.01; - const float ENVIRONMENT_COLLISION_FREQUENCY = 0.05f; - glm::vec3 penetration; - if (Application::getInstance()->getEnvironment()->findCapsulePenetration( - _position - up * (_pelvisFloatingHeight - radius), - _position + up * (_height - _pelvisFloatingHeight + radius), radius, penetration)) { - _lastCollisionPosition = _position; - updateCollisionSound(penetration, deltaTime, ENVIRONMENT_COLLISION_FREQUENCY); - applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING); - } -} - - -void Avatar::updateCollisionWithVoxels(float deltaTime) { - float radius = _collisionRadius; - const float VOXEL_ELASTICITY = 1.4f; - const float VOXEL_DAMPING = 0.0; - const float VOXEL_COLLISION_FREQUENCY = 0.5f; - glm::vec3 penetration; - if (Application::getInstance()->getVoxels()->findCapsulePenetration( - _position - glm::vec3(0.0f, _pelvisFloatingHeight - radius, 0.0f), - _position + glm::vec3(0.0f, _height - _pelvisFloatingHeight + radius, 0.0f), radius, penetration)) { - _lastCollisionPosition = _position; - updateCollisionSound(penetration, deltaTime, VOXEL_COLLISION_FREQUENCY); - applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); - } -} - -void Avatar::applyHardCollision(const glm::vec3& penetration, float elasticity, float damping) { - // - // Update the avatar in response to a hard collision. Position will be reset exactly - // to outside the colliding surface. Velocity will be modified according to elasticity. - // - // if elasticity = 1.0, collision is inelastic. - // if elasticity > 1.0, collision is elastic. - // - _position -= penetration; - static float HALTING_VELOCITY = 0.2f; - // cancel out the velocity component in the direction of penetration - float penetrationLength = glm::length(penetration); - if (penetrationLength > EPSILON) { - _elapsedTimeSinceCollision = 0.0f; - glm::vec3 direction = penetration / penetrationLength; - _velocity -= glm::dot(_velocity, direction) * direction * elasticity; - _velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f); - if ((glm::length(_velocity) < HALTING_VELOCITY) && (glm::length(_thrust) == 0.f)) { - // If moving really slowly after a collision, and not applying forces, stop altogether - _velocity *= 0.f; - } - } -} - -void Avatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) { - // consider whether to have the collision make a sound - const float AUDIBLE_COLLISION_THRESHOLD = 0.02f; - const float COLLISION_LOUDNESS = 1.f; - const float DURATION_SCALING = 0.004f; - const float NOISE_SCALING = 0.1f; - glm::vec3 velocity = _velocity; - glm::vec3 gravity = getGravity(); - - if (glm::length(gravity) > EPSILON) { - // If gravity is on, remove the effect of gravity on velocity for this - // frame, so that we are not constantly colliding with the surface - velocity -= _scale * glm::length(gravity) * GRAVITY_EARTH * deltaTime * glm::normalize(gravity); - } - float velocityTowardCollision = glm::dot(velocity, glm::normalize(penetration)); - float velocityTangentToCollision = glm::length(velocity) - velocityTowardCollision; - - if (velocityTowardCollision > AUDIBLE_COLLISION_THRESHOLD) { - // Volume is proportional to collision velocity - // Base frequency is modified upward by the angle of the collision - // Noise is a function of the angle of collision - // Duration of the sound is a function of both base frequency and velocity of impact - Application::getInstance()->getAudio()->startCollisionSound( - fmin(COLLISION_LOUDNESS * velocityTowardCollision, 1.f), - frequency * (1.f + velocityTangentToCollision / velocityTowardCollision), - fmin(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.f), - 1.f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision); - } -} - -void Avatar::updateAvatarCollisions(float deltaTime) { - - // Reset detector for nearest avatar - _distanceToNearestAvatar = std::numeric_limits::max(); - - // loop through all the other avatars for potential interactions... - NodeList* nodeList = NodeList::getInstance(); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { - Avatar *otherAvatar = (Avatar *)node->getLinkedData(); - - // check if the bounding spheres of the two avatars are colliding - glm::vec3 vectorBetweenBoundingSpheres(_position - otherAvatar->_position); - - if (glm::length(vectorBetweenBoundingSpheres) < _height * ONE_HALF + otherAvatar->_height * ONE_HALF) { - // apply forces from collision - applyCollisionWithOtherAvatar(otherAvatar, deltaTime); - } - // test other avatar hand position for proximity - glm::vec3 v(_skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position); - v -= otherAvatar->getPosition(); - - float distance = glm::length(v); - if (distance < _distanceToNearestAvatar) { - _distanceToNearestAvatar = distance; - } - } - } -} - -// 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 body balls of each avatar to check for every possible collision - for (int b = 1; b < NUM_AVATAR_BODY_BALLS; b++) { - if (_bodyBall[b].isCollidable) { - - for (int o = b+1; o < NUM_AVATAR_BODY_BALLS; o++) { - if (otherAvatar->_bodyBall[o].isCollidable) { - - glm::vec3 vectorBetweenBalls(_bodyBall[b].position - otherAvatar->_bodyBall[o].position); - float distanceBetweenBalls = glm::length(vectorBetweenBalls); - - if (distanceBetweenBalls > 0.0) { // to avoid divide by zero - float combinedRadius = _bodyBall[b].radius + otherAvatar->_bodyBall[o].radius; - - // check for collision - if (distanceBetweenBalls < combinedRadius * COLLISION_RADIUS_SCALAR) { - glm::vec3 directionVector = vectorBetweenBalls / distanceBetweenBalls; - - // push balls away from each other and apply friction - 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; - - _bodyBall[b].velocity += ballPushForce; - otherAvatar->_bodyBall[o].velocity -= ballPushForce; - - }// check for collision - } // to avoid divide by zero - } // o loop - } // collidable - } // b loop - } // collidable - - // apply force on the whole body - _velocity += bodyPushForce; -} - - static TextRenderer* textRenderer() { static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT); return renderer; } -void Avatar::setGravity(glm::vec3 gravity) { - _gravity = gravity; - _head.setGravity(_gravity); - - // use the gravity to determine the new world up direction, if possible - float gravityLength = glm::length(gravity); - if (gravityLength > EPSILON) { - _worldUpDirection = _gravity / -gravityLength; - } else { - _worldUpDirection = DEFAULT_UP_DIRECTION; - } -} - void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { - if (isMyAvatar() && usingBigSphereCollisionTest) { - // show TEST big sphere - glColor4f(0.5f, 0.6f, 0.8f, 0.7); - glPushMatrix(); - glTranslatef(_TEST_bigSpherePosition.x, _TEST_bigSpherePosition.y, _TEST_bigSpherePosition.z); - glScalef(_TEST_bigSphereRadius, _TEST_bigSphereRadius, _TEST_bigSphereRadius); - glutSolidSphere(1, 20, 20); - glPopMatrix(); - } - if (Application::getInstance()->getAvatar()->getHand().isRaveGloveActive()) { _hand.setRaveLights(RAVE_LIGHTS_AVATAR); } @@ -1212,25 +495,18 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { renderBody(lookingInMirror, renderAvatarBalls); // render sphere when far away - if (!isMyAvatar()) { - const float MAX_ANGLE = 10.f; - glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); - glm::vec3 delta = _height * (_head.getCameraOrientation() * IDENTITY_UP) / 2.f; - float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); + const float MAX_ANGLE = 10.f; + glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); + glm::vec3 delta = _height * (_head.getCameraOrientation() * IDENTITY_UP) / 2.f; + float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); - if (angle < MAX_ANGLE) { - glColor4f(0.5f, 0.8f, 0.8f, 1.f - angle / MAX_ANGLE); - glPushMatrix(); - glTranslatef(_position.x, _position.y, _position.z); - glScalef(_height / 2.f, _height / 2.f, _height / 2.f); - glutSolidSphere(1.2f + _head.getAverageLoudness() * .0005f, 20, 20); - glPopMatrix(); - } - } - - // if this is my avatar, then render my interactions with the other avatar - if (isMyAvatar()) { - _avatarTouch.render(Application::getInstance()->getCamera()->getPosition()); + if (angle < MAX_ANGLE) { + glColor4f(0.5f, 0.8f, 0.8f, 1.f - angle / MAX_ANGLE); + glPushMatrix(); + glTranslatef(_position.x, _position.y, _position.z); + glScalef(_height / 2.f, _height / 2.f, _height / 2.f); + glutSolidSphere(1.2f + _head.getAverageLoudness() * .0005f, 20, 20); + glPopMatrix(); } // Render the balls @@ -1283,21 +559,6 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { } } -void Avatar::renderScreenTint(ScreenTintLayer layer, Camera& whichCamera) { - - if (layer == SCREEN_TINT_BEFORE_AVATARS) { - if (_hand.isRaveGloveActive()) { - _hand.renderRaveGloveStage(); - } - } - else if (layer == SCREEN_TINT_BEFORE_AVATARS) { - if (_hand.isRaveGloveActive()) { - // Restore the world lighting - Application::getInstance()->setupWorldLight(whichCamera); - } - } -} - void Avatar::resetBodyBalls() { for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { @@ -1443,18 +704,12 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { } float Avatar::getBallRenderAlpha(int ball, bool lookingInMirror) const { - const float RENDER_OPAQUE_OUTSIDE = _scale * 0.25f; // render opaque if greater than this distance - const float DO_NOT_RENDER_INSIDE = _scale * 0.25f; // do not render if less than this distance - float distanceToCamera = glm::length(Application::getInstance()->getCamera()->getPosition() - _bodyBall[ball].position); - return (lookingInMirror || !isMyAvatar()) ? 1.0f : glm::clamp( - (distanceToCamera - DO_NOT_RENDER_INSIDE) / (RENDER_OPAQUE_OUTSIDE - DO_NOT_RENDER_INSIDE), 0.f, 1.f); + return 1.0f; } void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { - if (isMyAvatar() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON) { - // Dont display body - } else if (_head.getFace().isFullFrame()) { + if (_head.getFace().isFullFrame()) { // Render the full-frame video float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); if (alpha > 0.0f) { @@ -1479,18 +734,9 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { } } else if (alpha > 0.0f) { // Render the body ball sphere - if (!isMyAvatar() || 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); - } else { - glColor4f(SKIN_COLOR[0] + _bodyBall[b].touchForce * 0.3f, - SKIN_COLOR[1] - _bodyBall[b].touchForce * 0.2f, - SKIN_COLOR[2] - _bodyBall[b].touchForce * 0.1f, - alpha); - } + 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); if ((b != BODY_BALL_HEAD_TOP ) && (b != BODY_BALL_HEAD_BASE )) { @@ -1632,9 +878,9 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, glEnd(); } -void Avatar::setNewScale(const float scale) { - _newScale = scale; -} +// void Avatar::setNewScale(const float scale) { +// _newScale = scale; +// } void Avatar::setScale(const float scale) { _scale = scale; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 29a79047ed..80b25c52a9 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -58,6 +58,11 @@ const float BODY_BALL_RADIUS_RIGHT_KNEE = 0.025; const float BODY_BALL_RADIUS_RIGHT_HEEL = 0.025; const float BODY_BALL_RADIUS_RIGHT_TOES = 0.025; +extern const bool usingBigSphereCollisionTest; + +extern const float chatMessageScale; +extern const float chatMessageHeight; + enum AvatarBodyBallID { BODY_BALL_NULL = -1, @@ -121,85 +126,35 @@ enum ScreenTintLayer NUM_SCREEN_TINT_LAYERS }; +class MyAvatar; + class Avatar : public AvatarData { public: Avatar(Node* owningNode = NULL); ~Avatar(); void init(); - void reset(); void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity); - void updateThrust(float deltaTime, Transmitter * transmitter); void follow(Avatar* leadingAvatar); - void updateFromGyrosAndOrWebcam(bool gyroLook, - float pitchFromTouch); - void addBodyYaw(float bodyYaw) {_bodyYaw += bodyYaw;}; - void addBodyYawDelta(float bodyYawDelta) {_bodyYawDelta += bodyYawDelta;} void render(bool lookingInMirror, bool renderAvatarBalls); - void renderScreenTint(ScreenTintLayer layer, Camera& whichCamera); //setters - void setMousePressed (bool mousePressed ) { _mousePressed = mousePressed;} - void setNoise (float mag ) { _head.noise = mag;} - void setMovedHandOffset (glm::vec3 movedHandOffset ) { _movedHandOffset = movedHandOffset;} - void setThrust (glm::vec3 newThrust ) { _thrust = newThrust; }; void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors);} - void setVelocity (const glm::vec3 velocity ) { _velocity = velocity; }; - void setLeanScale (float scale ) { _leanScale = scale;} - void setGravity (glm::vec3 gravity); void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction); - void setOrientation (const glm::quat& orientation); - void setNewScale (const float scale); - void setWantCollisionsOn (bool wantCollisionsOn ) { _isCollisionsOn = wantCollisionsOn; } //getters bool isInitialized () const { return _initialized;} - bool isMyAvatar () const { return _owningNode == NULL; } const Skeleton& getSkeleton () const { return _skeleton;} 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() * IDENTITY_RIGHT; } - glm::vec3 getBodyUpDirection () const { return getOrientation() * IDENTITY_UP; } - glm::vec3 getBodyFrontDirection () const { return getOrientation() * IDENTITY_FRONT; } float getScale () const { return _scale;} - float getNewScale () const { return _newScale;} const glm::vec3& getVelocity () const { return _velocity;} - float getSpeed () const { return _speed;} - float getHeight () const { return _height;} - AvatarMode getMode () const { return _mode;} - float getLeanScale () const { return _leanScale;} - float getElapsedTimeStopped () const { return _elapsedTimeStopped;} - float getElapsedTimeMoving () const { return _elapsedTimeMoving;} - float getElapsedTimeSinceCollision() const { return _elapsedTimeSinceCollision;} - const glm::vec3& getLastCollisionPosition () const { return _lastCollisionPosition;} - float getAbsoluteHeadYaw () const; - float getAbsoluteHeadPitch () const; Head& getHead () {return _head; } Hand& getHand () {return _hand; } glm::quat getOrientation () const; glm::quat getWorldAlignedOrientation() const; - const glm::vec3& getMouseRayOrigin () const { return _mouseRayOrigin; } - const glm::vec3& getMouseRayDirection () const { return _mouseRayDirection; } - Avatar* getLeadingAvatar () const { return _leadingAvatar; } - glm::vec3 getGravity () const { return _gravity; } - - glm::vec3 getUprightHeadPosition() const; - glm::vec3 getUprightEyeLevelPosition() const; - glm::vec3 getEyePosition(); - - AvatarVoxelSystem* getVoxels() { return &_voxels; } - - // Set what driving keys are being pressed to control thrust levels - void setDriveKeys(int key, bool val) { _driveKeys[key] = val; }; - bool getDriveKeys(int key) { return _driveKeys[key]; }; - void jump() { _shouldJump = true; }; - // Set/Get update the thrust that will move the avatar around - void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; - glm::vec3 getThrust() { return _thrust; }; + AvatarVoxelSystem* getVoxels() { return &_voxels; } // get/set avatar data void saveData(QSettings* set); @@ -210,11 +165,9 @@ public: static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); -private: - // privatize copy constructor and assignment operator to avoid copying - Avatar(const Avatar&); - Avatar& operator= (const Avatar&); - + friend class MyAvatar; + +protected: struct AvatarBall { AvatarJointID parentJoint; // the skeletal joint that serves as a reference for determining the position @@ -230,77 +183,62 @@ private: float touchForce; // a scalar determining the amount that the cursor (or hand) is penetrating the ball }; - bool _initialized; Head _head; Hand _hand; Skeleton _skeleton; bool _ballSpringsInitialized; float _TEST_bigSphereRadius; glm::vec3 _TEST_bigSpherePosition; - bool _mousePressed; - float _bodyPitchDelta; float _bodyYawDelta; - float _bodyRollDelta; glm::vec3 _movedHandOffset; - AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; + AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; AvatarMode _mode; - glm::vec3 _handHoldingPosition; glm::vec3 _velocity; glm::vec3 _thrust; - bool _shouldJump; float _speed; - float _maxArmLength; float _leanScale; - int _driveKeys[MAX_DRIVE_KEYS]; - float _pelvisStandingHeight; float _pelvisFloatingHeight; float _pelvisToHeadLength; float _scale; float _height; Balls* _balls; AvatarTouch _avatarTouch; - float _distanceToNearestAvatar; // How close is the nearest avatar? - glm::vec3 _gravity; glm::vec3 _worldUpDirection; glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; - Avatar* _interactingOther; - bool _isMouseTurningRight; - float _elapsedTimeMoving; // Timers to drive camera transitions when moving - float _elapsedTimeStopped; - float _elapsedTimeSinceCollision; - glm::vec3 _lastCollisionPosition; - bool _speedBrakes; - bool _isThrustOn; bool _isCollisionsOn; - float _collisionRadius; - Avatar* _leadingAvatar; float _stringLength; AvatarVoxelSystem _voxels; + + // protected methods... + glm::vec3 getBodyRightDirection () const { return getOrientation() * IDENTITY_RIGHT; } + glm::vec3 getBodyUpDirection () const { return getOrientation() * IDENTITY_UP; } + glm::vec3 getBodyFrontDirection () const { return getOrientation() * IDENTITY_FRONT; } + glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const; + void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); + void updateBodyBalls( float deltaTime ); + void updateArmIKAndConstraints( float deltaTime ); + void setScale (const float scale); + +private: + // privatize copy constructor and assignment operator to avoid copying + Avatar(const Avatar&); + Avatar& operator= (const Avatar&); + + bool _initialized; + glm::vec3 _handHoldingPosition; + float _maxArmLength; + float _pelvisStandingHeight; // private methods... glm::vec3 calculateAverageEyePosition() { return _head.calculateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat) - glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const; float getBallRenderAlpha(int ball, bool lookingInMirror) const; void renderBody(bool lookingInMirror, bool renderAvatarBalls); void initializeBodyBalls(); void resetBodyBalls(); - void updateBodyBalls( float deltaTime ); - void calculateBoneLengths(); - void readSensors(); void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement); - void updateAvatarCollisions(float deltaTime); - void updateArmIKAndConstraints( float deltaTime ); - void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); - void updateCollisionWithEnvironment(float deltaTime); - void updateCollisionWithVoxels(float deltaTime); - void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping); - void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); - void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime ); - void checkForMouseRayTouching(); - void setScale (const float scale); }; #endif diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index fc6ca4224e..dda948d92f 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -36,7 +36,7 @@ Hand::Hand(Avatar* owningAvatar) : void Hand::init() { // Different colors for my hand and others' hands - if (_owningAvatar && _owningAvatar->isMyAvatar()) { + if (_owningAvatar && _owningAvatar->getOwningNode() == NULL) { _ballColor = glm::vec3(0.0, 0.4, 0.0); } else {