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 {