diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2c60113d46..44321dfe26 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -47,9 +47,6 @@ using namespace std; -//const CameraMode DEFAULT_CAMERA_MODE = CAMERA_MODE_FIRST_PERSON; -const CameraMode DEFAULT_CAMERA_MODE = CAMERA_MODE_THIRD_PERSON; - // Starfield information static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; static char STAR_CACHE_FILE[] = "cachedStars.txt"; @@ -298,37 +295,29 @@ void Application::paintGL() { glLoadIdentity(); // camera settings - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - _myAvatar.setDisplayingHead(true); - _myCamera.setUpShift (0.0); - _myCamera.setDistance (0.2); - _myCamera.setTightness (100.0f); - _myCamera.setTargetPosition(_myAvatar.getHeadPosition()); - _myCamera.setTargetRotation(_myAvatar.getBodyYaw() - 180.0f, 0.0f, 0.0f); - - } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || OculusManager::isConnected()) { + if (OculusManager::isConnected()) { _myAvatar.setDisplayingHead(false); _myCamera.setUpShift (0.0f); _myCamera.setDistance (0.0f); _myCamera.setTightness (100.0f); _myCamera.setTargetPosition(_myAvatar.getHeadPosition()); + _myCamera.setTargetRotation(_myAvatar.getBodyYaw() + _myAvatar.getHeadYaw(), + -_myAvatar.getHeadPitch(), _myAvatar.getHeadRoll()); + + } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + _myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition()); + _myCamera.setTargetRotation(_myAvatar.getBodyYaw() - 180.0f, 0.0f, 0.0f); + + } else { + if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { + _myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition()); + _myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw() - _mouseViewShiftYaw, + _myAvatar.getRenderPitch() + _mouseViewShiftPitch, 0.0f); - if (OculusManager::isConnected()) { - _myCamera.setTargetRotation(_myAvatar.getBodyYaw() + _myAvatar.getHeadYaw(), - -_myAvatar.getHeadPitch(), - _myAvatar.getHeadRoll()); - } else { - _myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw()- _mouseViewShiftYaw, - _myAvatar.getAbsoluteHeadPitch() + - _myAvatar.getRenderPitch() + _mouseViewShiftPitch, 0.0f); - } - } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { - _myAvatar.setDisplayingHead(true); - _myCamera.setUpShift (-0.2f); - _myCamera.setDistance (1.5f); - _myCamera.setTightness (8.0f); - _myCamera.setTargetPosition(_myAvatar.getHeadPosition()); - _myCamera.setTargetRotation(_myAvatar.getBodyYaw() - _mouseViewShiftYaw, _mouseViewShiftPitch, 0.0f); + } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { + _myCamera.setTargetPosition(_myAvatar.getHeadPosition()); + _myCamera.setTargetRotation(_myAvatar.getBodyYaw() - _mouseViewShiftYaw, _mouseViewShiftPitch, 0.0f); + } } // important... @@ -819,14 +808,18 @@ void Application::idle() { _myAvatar.setMousePressed(_mousePressed); // check what's under the mouse and update the mouse voxel - glm::vec3 origin, direction; + glm::vec3 mouseRayOrigin, mouseRayDirection; _viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(), - _mouseY / (float)_glWidget->height(), origin, direction); + _mouseY / (float)_glWidget->height(), mouseRayOrigin, mouseRayDirection); + + // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position + _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); float distance; BoxFace face; _mouseVoxel.s = 0.0f; - if (_mouseMode != NO_EDIT_MODE && _voxels.findRayIntersection(origin, direction, _mouseVoxel, distance, face)) { + if (_mouseMode != NO_EDIT_MODE && _voxels.findRayIntersection( + mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) { // find the nearest voxel with the desired scale if (_mouseVoxelScale > _mouseVoxel.s) { // choose the larger voxel that encompasses the one selected @@ -839,7 +832,7 @@ void Application::idle() { glm::vec3 faceVector = getFaceVector(face); if (_mouseVoxelScale < _mouseVoxel.s) { // find the closest contained voxel - glm::vec3 pt = (origin + direction * distance) / (float)TREE_SCALE - + glm::vec3 pt = (mouseRayOrigin + mouseRayDirection * distance) / (float)TREE_SCALE - faceVector * (_mouseVoxelScale * 0.5f); _mouseVoxel.x = _mouseVoxelScale * floorf(pt.x / _mouseVoxelScale); _mouseVoxel.y = _mouseVoxelScale * floorf(pt.y / _mouseVoxelScale); @@ -893,6 +886,7 @@ void Application::idle() { if (agent->getLinkedData() != NULL) { Avatar *avatar = (Avatar *)agent->getLinkedData(); avatar->simulate(deltaTime); + avatar->setMouseRay(mouseRayOrigin, mouseRayDirection); } } agentList->unlock(); @@ -934,8 +928,23 @@ void Application::pair() { void Application::setHead(bool head) { #ifndef _WIN32 _audio.setMixerLoopbackFlag(head); - _myCamera.setMode(head ? CAMERA_MODE_MIRROR : DEFAULT_CAMERA_MODE); #endif + + if (head) { + Camera::CameraFollowingAttributes a; + a.upShift = 0.0f; + a.distance = 0.2f; + a.tightness = 100.0f; + _myCamera.setMode(CAMERA_MODE_MIRROR, a); + _myAvatar.setDisplayingHead(true); + } else { + Camera::CameraFollowingAttributes a; + a.upShift = -0.2f; + a.distance = 1.5f; + a.tightness = 8.0f; + _myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a); + _myAvatar.setDisplayingHead(true); + } } void Application::setNoise(bool noise) { @@ -948,7 +957,22 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setRenderFirstPerson(bool firstPerson) { - _myCamera.setMode(firstPerson ? CAMERA_MODE_FIRST_PERSON : CAMERA_MODE_THIRD_PERSON); + if (firstPerson) { + Camera::CameraFollowingAttributes a; + a.upShift = 0.0f; + a.distance = 0.0f; + a.tightness = 100.0f; + _myCamera.setMode(CAMERA_MODE_FIRST_PERSON, a); + _myAvatar.setDisplayingHead(false); + + } else { + Camera::CameraFollowingAttributes a; + a.upShift = -0.2f; + a.distance = 1.5f; + a.tightness = 8.0f; + _myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a); + _myAvatar.setDisplayingHead(true); + } } void Application::setOculus(bool oculus) { @@ -1118,7 +1142,12 @@ void Application::init() { _stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0); _myAvatar.setPosition(START_LOCATION); - _myCamera.setMode(DEFAULT_CAMERA_MODE); + Camera::CameraFollowingAttributes a; + a.upShift = -0.2f; + a.distance = 1.5f; + a.tightness = 8.0f; + _myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a); + _myAvatar.setDisplayingHead(true); OculusManager::connect(); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 74bd816bff..64b9310b78 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -49,36 +49,17 @@ const float HEAD_MAX_YAW = 85; const float HEAD_MIN_YAW = -85; const float AVATAR_BRAKING_RANGE = 1.6f; const float AVATAR_BRAKING_STRENGTH = 30.0f; +//const float MAX_JOINT_TOUCH_DOT = 0.995f; +const float JOINT_TOUCH_RANGE = 0.0005f; float skinColor [] = {1.0, 0.84, 0.66}; float lightBlue [] = {0.7, 0.8, 1.0}; -/* -float browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; -float mouthColor[] = {1, 0, 0}; - -float BrowRollAngle [5] = {0, 15, 30, -30, -15}; -float BrowPitchAngle[3] = {-70, -60, -50}; -float eyeColor [3] = {1,1,1}; - -float MouthWidthChoices[3] = {0.5, 0.77, 0.3}; - -float browWidth = 0.8; -float browThickness = 0.16; - - -//char iris_texture_file[] = "resources/images/green_eye.png"; -*/ bool usingBigSphereCollisionTest = true; float chatMessageScale = 0.0015; float chatMessageHeight = 0.45; -/* -vector iris_texture; -unsigned int iris_texture_width = 512; -unsigned int iris_texture_height = 256; -*/ Avatar::Avatar(bool isMine) { @@ -106,7 +87,10 @@ Avatar::Avatar(bool isMine) { _displayingHead = true; _TEST_bigSphereRadius = 0.4f; _TEST_bigSpherePosition = glm::vec3(5.0f, _TEST_bigSphereRadius, 5.0f); - + _mouseRayOrigin = glm::vec3(0.0f, 0.0f, 0.0f); + _mouseRayDirection = glm::vec3(0.0f, 0.0f, 0.0f); + _cameraPosition = glm::vec3(0.0f, 0.0f, 0.0f); + for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; _head.initialize(); @@ -122,17 +106,7 @@ Avatar::Avatar(bool isMine) { initializeSkeleton(); _avatarTouch.setReachableRadius(0.6); - - /* - if (iris_texture.size() == 0) { - switchToResourcesParentIfRequired(); - unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); - if (error != 0) { - printLog("error %u: %s\n", error, lodepng_error_text(error)); - } - } -*/ - + if (BALLS_ON) { _balls = new Balls(100); } else { _balls = NULL; } } @@ -318,6 +292,9 @@ bool Avatar::getIsNearInteractingOther() { } void Avatar::simulate(float deltaTime) { + + //figure out if the mouse cursor is over any body spheres... + checkForMouseRayTouching(); // update balls if (_balls) { _balls->simulate(deltaTime); } @@ -481,6 +458,30 @@ void Avatar::simulate(float deltaTime) { } } + + +void Avatar::checkForMouseRayTouching() { + + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { + + glm::vec3 directionToBodySphere = glm::normalize(_joint[b].springyPosition - _mouseRayOrigin); + float dot = glm::dot(directionToBodySphere, _mouseRayDirection); + + if (dot > (1.0f - JOINT_TOUCH_RANGE)) { + _joint[b].touchForce = (dot - (1.0f - JOINT_TOUCH_RANGE)) / JOINT_TOUCH_RANGE; + } else { + _joint[b].touchForce = 0.0; + } + } +} + + +void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction ) { + _mouseRayOrigin = origin; _mouseRayDirection = direction; +} + + + void Avatar::updateHandMovementAndTouching(float deltaTime) { // reset hand and arm positions according to hand movement @@ -491,8 +492,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement; - if (_isMine) - { + if (_isMine) { _avatarTouch.setMyBodyPosition(_position); Avatar * _interactingOther = NULL; @@ -853,6 +853,8 @@ void Avatar::setGravity(glm::vec3 gravity) { void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { + _cameraPosition = cameraPosition; // store this for use in various parts of the code + // render a simple round on the ground projected down from the avatar's position renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), 0.1f, 0.2f); @@ -877,16 +879,18 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { } //render body - renderBody(); + renderBody(lookingInMirror); + /* // render head if (_displayingHead) { _head.render(lookingInMirror, _bodyYaw); } + */ // if this is my avatar, then render my interactions with the other avatar if (_isMine) { - _avatarTouch.render(cameraPosition); + _avatarTouch.render(_cameraPosition); } // Render the balls @@ -941,180 +945,6 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { -void Avatar::renderHead(bool lookingInMirror) { -/* - int side = 0; - - glEnable(GL_DEPTH_TEST); - glEnable(GL_RESCALE_NORMAL); - - // show head orientation - //renderOrientationDirections(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition, _joint[ AVATAR_JOINT_HEAD_BASE ].orientation, 0.2f); - - glPushMatrix(); - - glTranslatef(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.x, - _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.y, - _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.z); - - glScalef - ( - _joint[ AVATAR_JOINT_HEAD_BASE ].radius, - _joint[ AVATAR_JOINT_HEAD_BASE ].radius, - _joint[ AVATAR_JOINT_HEAD_BASE ].radius - ); - - - if (lookingInMirror) { - glRotatef(_bodyYaw - _headYaw, 0, 1, 0); - //glRotatef(_bodyPitch + _headPitch, 1, 0, 0); - //glRotatef(_bodyRoll - _headRoll, 0, 0, 1); - // don't let body pitch and roll affect the head.. - glRotatef(_headPitch, 1, 0, 0); - glRotatef(-_headRoll, 0, 0, 1); - } else { - glRotatef(_bodyYaw + _headYaw, 0, 1, 0); - //glRotatef(_bodyPitch + _headPitch, 1, 0, 0); - //glRotatef(_bodyRoll + _headRoll, 0, 0, 1); - // don't let body pitch and roll affect the head.. - glRotatef(_headPitch, 1, 0, 0); - glRotatef(_headRoll, 0, 0, 1); - } - - //glScalef(2.0, 2.0, 2.0); - glColor3fv(skinColor); - - glutSolidSphere(1, 30, 30); - - // Ears - glPushMatrix(); - glTranslatef(1.0, 0, 0); - for(side = 0; side < 2; side++) { - glPushMatrix(); - glScalef(0.3, 0.65, .65); - glutSolidSphere(0.5, 30, 30); - glPopMatrix(); - glTranslatef(-2.0, 0, 0); - } - glPopMatrix(); - - - // Update audio attack data for facial animation (eyebrows and mouth) - _head.audioAttack = 0.9 * _head.audioAttack + 0.1 * fabs(_audioLoudness - _head.lastLoudness); - _head.lastLoudness = _audioLoudness; - - - const float BROW_LIFT_THRESHOLD = 100; - if (_head.audioAttack > BROW_LIFT_THRESHOLD) - _head.browAudioLift += sqrt(_head.audioAttack) / 1000.0; - - _head.browAudioLift *= .90; - - - // Render Eyebrows - glPushMatrix(); - glTranslatef(-_head.interBrowDistance / 2.0,0.4,0.45); - for(side = 0; side < 2; side++) { - glColor3fv(browColor); - glPushMatrix(); - glTranslatef(0, 0.35 + _head.browAudioLift, 0); - glRotatef(_head.eyebrowPitch[side]/2.0, 1, 0, 0); - glRotatef(_head.eyebrowRoll[side]/2.0, 0, 0, 1); - glScalef(browWidth, browThickness, 1); - glutSolidCube(0.5); - glPopMatrix(); - glTranslatef(_head.interBrowDistance, 0, 0); - } - glPopMatrix(); - - // Mouth - glPushMatrix(); - glTranslatef(0,-0.35,0.75); - glColor3f(0,0,0); - glRotatef(_head.mouthPitch, 1, 0, 0); - glRotatef(_head.mouthYaw, 0, 0, 1); - if (_head.averageLoudness > 1.f) { - glScalef(_head.mouthWidth * (.7f + sqrt(_head.averageLoudness) /60.f), - _head.mouthHeight * (1.f + sqrt(_head.averageLoudness) /30.f), 1); - } else { - glScalef(_head.mouthWidth, _head.mouthHeight, 1); - } - - glutSolidCube(0.5); - glPopMatrix(); - - glTranslatef(0, 1.0, 0); - - glTranslatef(-_head.interPupilDistance/2.0,-0.68,0.7); - // Right Eye - glRotatef(-10, 1, 0, 0); - glColor3fv(eyeColor); - glPushMatrix(); - { - glTranslatef(_head.interPupilDistance/10.0, 0, 0.05); - glRotatef(20, 0, 0, 1); - glScalef(_head.eyeballScaleX, _head.eyeballScaleY, _head.eyeballScaleZ); - glutSolidSphere(0.25, 30, 30); - } - glPopMatrix(); - - // Right Pupil - if (_sphere == NULL) { - _sphere = gluNewQuadric(); - gluQuadricTexture(_sphere, GL_TRUE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluQuadricOrientation(_sphere, GLU_OUTSIDE); -//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); - } - - glPushMatrix(); - { - glRotatef(_head.eyeballPitch[1], 1, 0, 0); - glRotatef(_head.eyeballYaw[1] + _headYaw + _head.pupilConverge, 0, 1, 0); - glTranslatef(0,0,.35); - glRotatef(-75,1,0,0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, _head.pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - - glPopMatrix(); - // Left Eye - glColor3fv(eyeColor); - glTranslatef(_head.interPupilDistance, 0, 0); - glPushMatrix(); - { - glTranslatef(-_head.interPupilDistance/10.0, 0, .05); - glRotatef(-20, 0, 0, 1); - glScalef(_head.eyeballScaleX, _head.eyeballScaleY, _head.eyeballScaleZ); - glutSolidSphere(0.25, 30, 30); - } - glPopMatrix(); - // Left Pupil - glPushMatrix(); - { - glRotatef(_head.eyeballPitch[0], 1, 0, 0); - glRotatef(_head.eyeballYaw[0] + _headYaw - _head.pupilConverge, 0, 1, 0); - glTranslatef(0, 0, .35); - glRotatef(-75, 1, 0, 0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, _head.pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - - glPopMatrix(); - - - glPopMatrix(); - */ - } - - void Avatar::setHandMovementValues(glm::vec3 handOffset) { _movedHandOffset = handOffset; } @@ -1138,6 +968,7 @@ void Avatar::initializeSkeleton() { _joint[b].roll = 0.0; _joint[b].length = 0.0; _joint[b].radius = 0.0; + _joint[b].touchForce = 0.0; _joint[b].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; _joint[b].orientation.setToIdentity(); } @@ -1373,10 +1204,11 @@ void Avatar::updateBodySprings(float deltaTime) { } } + // apply tightness force - (causing springy position to be close to rigid body position) _joint[b].springyVelocity += (_joint[b].position - _joint[b].springyPosition) * _joint[b].springBodyTightness * deltaTime; + // apply decay float decay = 1.0 - BODY_SPRING_DECAY * deltaTime; - if (decay > 0.0) { _joint[b].springyVelocity *= decay; } @@ -1384,20 +1216,25 @@ void Avatar::updateBodySprings(float deltaTime) { _joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f); } + //apply forces from touch... + if (_joint[b].touchForce > 0.0) { + _joint[b].springyVelocity += _mouseRayDirection * _joint[b].touchForce * 0.7f; + } + + //update position by velocity... _joint[b].springyPosition += _joint[b].springyVelocity * deltaTime; } } -const glm::vec3& Avatar::getHeadPosition() const { - - - //if (_usingBodySprings) { - // return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition; - //} - + +const glm::vec3& Avatar::getSpringyHeadPosition() const { return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition; } +const glm::vec3& Avatar::getHeadPosition() const { + return _joint[ AVATAR_JOINT_HEAD_BASE ].position; +} + void Avatar::updateArmIKAndConstraints(float deltaTime) { @@ -1438,12 +1275,16 @@ void Avatar::updateArmIKAndConstraints(float deltaTime) { } -void Avatar::renderBody() { +void Avatar::renderBody(bool lookingInMirror) { // Render joint positions as spheres for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - if (b != AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case in "renderHead" + if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case + if (_displayingHead) { + _head.render(lookingInMirror, _bodyYaw); + } + } else { //show direction vectors of the bone orientation //renderOrientationDirections(_joint[b].springyPosition, _joint[b].orientation, _joint[b].radius * 2.0); @@ -1454,8 +1295,20 @@ void Avatar::renderBody() { glutSolidSphere(_joint[b].radius, 20.0f, 20.0f); glPopMatrix(); } + + if (_joint[b].touchForce > 0.0f) { + + float alpha = _joint[b].touchForce * 0.2; + float r = _joint[b].radius * 1.1f + 0.005f; + glColor4f(0.5f, 0.2f, 0.2f, alpha); + glPushMatrix(); + glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z); + glScalef(r, r, r); + glutSolidSphere(1, 20, 20); + glPopMatrix(); + } } - + // Render lines connecting the joint positions glColor3f(0.4f, 0.5f, 0.6f); glLineWidth(3.0); diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 088e41fd1c..beca93b53e 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -91,7 +91,8 @@ public: float getBodyYaw() {return _bodyYaw;}; void addBodyYaw(float y) {_bodyYaw += y;}; void setGravity(glm::vec3 gravity); - + + void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction ); bool getIsNearInteractingOther(); float getAbsoluteHeadYaw() const; @@ -99,11 +100,9 @@ public: void setLeanForward(float dist); void setLeanSideways(float dist); void addLean(float x, float z); - const glm::vec3& getHeadPosition() const ; - - //const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].position; }; - const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].springyPosition; }; - + const glm::vec3& getHeadPosition() const ; // get the position of the avatar's rigid body head + const glm::vec3& getSpringyHeadPosition() const ; // get the springy position of the avatar's head + const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].springyPosition; }; const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); }; float getSpeed() const { return _speed; }; const glm::vec3& getVelocity() const { return _velocity; }; @@ -113,9 +112,8 @@ public: AvatarMode getMode(); void setMousePressed(bool pressed); - void render(bool lookingInMirrorm, glm::vec3 cameraPosition); - void renderBody(); - void renderHead(bool lookingInMirror); + void render(bool lookingInMirror, glm::vec3 cameraPosition); + void renderBody(bool lookingInMirror); void simulate(float); void setHandMovementValues( glm::vec3 movement ); void updateArmIKAndConstraints( float deltaTime ); @@ -155,6 +153,7 @@ private: float length; // the length of vector connecting the joint and its parent float radius; // used for detecting collisions for certain physical effects bool isCollidable; // when false, the joint position will not register a collision + float touchForce; // if being touched, what's the degree of influence? (0 to 1) }; Head _head; @@ -192,6 +191,12 @@ private: bool _displayingHead; // should be false if in first-person view float _distanceToNearestAvatar; // How close is the nearest avatar? glm::vec3 _gravity; + glm::vec3 _mouseRayOrigin; + glm::vec3 _mouseRayDirection; + glm::vec3 _cameraPosition; + + //AvatarJointID _jointTouched; + // private methods... void initializeSkeleton(); @@ -206,6 +211,7 @@ private: void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime ); void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime); + void checkForMouseRayTouching(); }; #endif diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 3045e732e6..4cd66521f0 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -12,6 +12,8 @@ #include "Camera.h" +const float MODE_SHIFT_RATE = 5.0f; + Camera::Camera() { _needsToInitialize = true; @@ -22,12 +24,10 @@ Camera::Camera() { _fieldOfView = 60.0; // default _nearClip = 0.08; // default _farClip = 50.0 * TREE_SCALE; // default - _modeShift = 0.0; _yaw = 0.0; _pitch = 0.0; _roll = 0.0; _upShift = 0.0; - _rightShift = 0.0; _distance = 0.0; _idealYaw = 0.0; _idealPitch = 0.0; @@ -36,28 +36,27 @@ Camera::Camera() { _position = glm::vec3(0.0, 0.0, 0.0); _idealPosition = glm::vec3(0.0, 0.0, 0.0); _orientation.setToIdentity(); + + for (int m = 0; m < NUM_CAMERA_MODES; m ++) { + _attributes[m].upShift = 0.0f; + _attributes[m].distance = 0.0f; + _attributes[m].tightness = 0.0f; + } } + void Camera::update(float deltaTime) { - if (_mode == CAMERA_MODE_NULL) { - _modeShift = 0.0; - } else { - // use iterative forces to push the camera towards the desired position and angle + if (_mode != CAMERA_MODE_NULL) { + // use iterative forces to push the camera towards the target position and angle updateFollowMode(deltaTime); - - if (_modeShift < 1.0f) { - _modeShift += MODE_SHIFT_RATE * deltaTime; - if (_modeShift > 1.0f) { - _modeShift = 1.0f; - } - } - } + } // do this AFTER making any changes to yaw pitch and roll.... generateOrientation(); } + // generate the ortho-normals for the orientation based on the three Euler angles void Camera::generateOrientation() { _orientation.setToIdentity(); @@ -74,7 +73,7 @@ void Camera::updateFollowMode(float deltaTime) { if (t > 1.0) { t = 1.0; } - + // update Euler angles (before position!) if (_needsToInitialize || OculusManager::isConnected()) { _yaw = _idealYaw; @@ -104,15 +103,27 @@ void Camera::updateFollowMode(float deltaTime) { _position = _idealPosition; _needsToInitialize = false; } else { - // pull position towards ideal position + // force position towards ideal position _position += (_idealPosition - _position) * t; } + + //transition to the attributes of the current mode + _upShift += (_attributes[_mode].upShift - _upShift ) * deltaTime * MODE_SHIFT_RATE; + _distance += (_attributes[_mode].distance - _distance ) * deltaTime * MODE_SHIFT_RATE; + _tightness += (_attributes[_mode].tightness - _tightness) * deltaTime * MODE_SHIFT_RATE; } +void Camera::setMode(CameraMode m, CameraFollowingAttributes a) { + + _attributes[m].upShift = a.upShift; + _attributes[m].distance = a.distance; + _attributes[m].tightness = a.tightness; + + setMode(m); +} void Camera::setMode(CameraMode m) { _mode = m; - _modeShift = 0.0f; _needsToInitialize = true; } diff --git a/interface/src/Camera.h b/interface/src/Camera.h index fa087ca453..52c577e88a 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -20,13 +20,18 @@ enum CameraMode NUM_CAMERA_MODES }; -const float MODE_SHIFT_RATE = 2.0f; - class Camera { public: Camera(); + struct CameraFollowingAttributes + { + float upShift; + float distance; + float tightness; + }; + void initialize(); // instantly put the camera at the ideal position and rotation. void update( float deltaTime ); @@ -35,7 +40,6 @@ public: void setPitch ( float p ) { _pitch = p; } void setRoll ( float r ) { _roll = r; } void setUpShift ( float u ) { _upShift = u; } - void setRightShift ( float r ) { _rightShift = r; } void setDistance ( float d ) { _distance = d; } void setTargetPosition( glm::vec3 t ) { _targetPosition = t; } void setTargetYaw ( float y ) { _idealYaw = y; } @@ -43,8 +47,8 @@ public: void setTightness ( float t ) { _tightness = t; } void setTargetRotation( float yaw, float pitch, float roll ); - void setMode ( CameraMode m ); + void setMode ( CameraMode m, CameraFollowingAttributes attributes ); void setFieldOfView ( float f ); void setAspectRatio ( float a ); void setNearClip ( float n ); @@ -56,7 +60,6 @@ public: glm::vec3 getPosition () { return _position; } Orientation getOrientation() { return _orientation; } CameraMode getMode () { return _mode; } - float getModeShift () { return _modeShift; } float getFieldOfView() { return _fieldOfView; } float getAspectRatio() { return _aspectRatio; } float getNearClip () { return _nearClip; } @@ -68,7 +71,6 @@ private: bool _needsToInitialize; CameraMode _mode; - float _modeShift; // 0.0 to 1.0 bool _frustumNeedsReshape; glm::vec3 _position; glm::vec3 _idealPosition; @@ -81,13 +83,14 @@ private: float _pitch; float _roll; float _upShift; - float _rightShift; float _idealYaw; float _idealPitch; float _idealRoll; float _distance; float _tightness; Orientation _orientation; + + CameraFollowingAttributes _attributes[NUM_CAMERA_MODES]; void generateOrientation(); void updateFollowMode( float deltaTime );