From eb15aa602ce35140951a8dcbe80f9c91888a529a Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 23 May 2013 12:17:24 -0700 Subject: [PATCH 1/3] Added amplification of gyro rates when applying to head, for more sensitivity, and to allow easily looking to one side and another --- interface/src/Avatar.cpp | 18 +++++++++--------- interface/src/Head.cpp | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 3f3715a89b..cb1f4d671f 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -128,19 +128,19 @@ void Avatar::reset() { // Update avatar head rotation with sensor data void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterface, glm::vec3* gravity) { - float measuredPitchRate = 0.0f; - float measuredRollRate = 0.0f; - float measuredYawRate = 0.0f; + const float AMPLIFY_PITCH = 2.f; + const float AMPLIFY_YAW = 2.f; + const float AMPLIFY_ROLL = 2.f; - measuredPitchRate = serialInterface->getLastPitchRate(); - measuredYawRate = serialInterface->getLastYawRate(); - measuredRollRate = serialInterface->getLastRollRate(); + float measuredPitchRate = serialInterface->getLastPitchRate(); + float measuredYawRate = serialInterface->getLastYawRate(); + float measuredRollRate = serialInterface->getLastRollRate(); // Update avatar head position based on measured gyro rates - _head.addPitch(measuredPitchRate * deltaTime); - _head.addYaw (measuredYawRate * deltaTime); - _head.addRoll (measuredRollRate * deltaTime); + _head.addPitch(measuredPitchRate * AMPLIFY_PITCH * deltaTime); + _head.addYaw (measuredYawRate * AMPLIFY_YAW * deltaTime); + _head.addRoll (measuredRollRate * AMPLIFY_ROLL * deltaTime); // Update head lean distance based on accelerometer data glm::vec3 headRotationRates(_head.getPitch(), _head.getYaw(), _head.getRoll()); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 33a5f792ee..cb42c6cc54 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -76,10 +76,10 @@ void Head::simulate(float deltaTime, bool isMine) { _roll *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * deltaTime); } - // For invensense gyro, decay only slightly when roughly centered + // For invensense gyro, decay only slightly when near center (until we add fusion) if (isMine) { const float RETURN_RANGE = 15.0; - const float RETURN_STRENGTH = 2.0; + const float RETURN_STRENGTH = 0.5; if (fabs(_pitch) < RETURN_RANGE) { _pitch *= (1.0f - RETURN_STRENGTH * deltaTime); } if (fabs(_yaw ) < RETURN_RANGE) { _yaw *= (1.0f - RETURN_STRENGTH * deltaTime); } if (fabs(_roll ) < RETURN_RANGE) { _roll *= (1.0f - RETURN_STRENGTH * deltaTime); } From 32d2418b7aec57793c5f81b4a5d9a1333fa0e9d4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 23 May 2013 12:33:26 -0700 Subject: [PATCH 2/3] Added display head mouse option (default off) and all camera modes follow head gyros the same way. --- interface/src/Application.cpp | 13 ++++++------- interface/src/Application.h | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3546ee1ecf..40f0456726 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -57,8 +57,6 @@ const glm::vec3 START_LOCATION(0.f, 0.f, 0.f); // Where one's own agent begin const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff // in the idle loop? (60 FPS is default) - -const bool DISPLAY_HEAD_MOUSE = true; // customized canvas that simply forwards requests/events to the singleton application class GLCanvas : public QGLWidget { @@ -319,12 +317,11 @@ void Application::paintGL() { } } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { _myCamera.setTargetPosition(_myAvatar.getHeadPosition()); - _myCamera.setTargetRotation(_myAvatar.getBodyYaw(), - 0.0f, - //-_myAvatar.getAbsoluteHeadPitch(), + _myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(), + _myAvatar.getAbsoluteHeadPitch(), 0.0f); } - + // important... _myCamera.update( 1.f/_fps ); @@ -1203,6 +1200,8 @@ void Application::initMenu() { _gyroLook->setChecked(true); (_mouseLook = optionsMenu->addAction("Mouse Look"))->setCheckable(true); _mouseLook->setChecked(false); + (_showHeadMouse = optionsMenu->addAction("Head Mouse"))->setCheckable(true); + _showHeadMouse->setChecked(false); (_transmitterDrives = optionsMenu->addAction("Transmitter Drive"))->setCheckable(true); _transmitterDrives->setChecked(true); @@ -1747,7 +1746,7 @@ void Application::displayOverlay() { //noiseTest(_glWidget->width(), _glWidget->height()); - if (DISPLAY_HEAD_MOUSE && !_lookingInMirror->isChecked() && USING_INVENSENSE_MPU9150) { + if (_showHeadMouse->isChecked() && !_lookingInMirror->isChecked() && USING_INVENSENSE_MPU9150) { // Display small target box at center or head mouse target that can also be used to measure LOD glColor3f(1.0, 1.0, 1.0); glDisable(GL_LINE_SMOOTH); diff --git a/interface/src/Application.h b/interface/src/Application.h index 98a41e89c2..8ef63b5022 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -138,6 +138,7 @@ private: QAction* _lookingInMirror; // Are we currently rendering one's own head as if in mirror? QAction* _gyroLook; // Whether to allow the gyro data from head to move your view QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view + QAction* _showHeadMouse; // Whether the have the mouse near edge of screen move your view QAction* _transmitterDrives; // Whether to have Transmitter data move/steer the Avatar QAction* _renderVoxels; // Whether to render voxels QAction* _renderVoxelTextures; // Whether to render noise textures on voxels From 37cb914891635f32480408efa6537489bb088b50 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 23 May 2013 15:02:32 -0700 Subject: [PATCH 3/3] You can reset start location with 'G' --- interface/src/Application.cpp | 24 ++++----- interface/src/Application.h | 1 + interface/src/Avatar.cpp | 89 +++++++++++++++++--------------- interface/src/Avatar.h | 5 +- interface/src/AvatarRenderer.cpp | 70 ------------------------- 5 files changed, 62 insertions(+), 127 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c072a6b9b8..b9b0948490 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -52,7 +52,7 @@ using namespace std; static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; static char STAR_CACHE_FILE[] = "cachedStars.txt"; -const glm::vec3 START_LOCATION(0.f, 0.f, 0.f); // Where one's own agent begins in the world +const glm::vec3 START_LOCATION(4.f, 0.f, 5.f); // Where one's own agent begins in the world // (will be overwritten if avatar data file is found) const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff @@ -295,7 +295,6 @@ void Application::paintGL() { 0.0f, 0.0f); } else if (OculusManager::isConnected()) { - _myAvatar.setDisplayingHead(false); _myCamera.setUpShift (0.0f); _myCamera.setDistance (0.0f); _myCamera.setTightness (100.0f); @@ -313,7 +312,6 @@ void Application::paintGL() { glm::vec3 distanceToHead(_myCamera.getPosition() - _myAvatar.getSpringyHeadPosition()); if (glm::length(distanceToHead) < HEAD_RENDER_DISTANCE) { - _myAvatar.setDisplayingHead(false); } } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { _myCamera.setTargetPosition(_myAvatar.getHeadPosition()); @@ -568,6 +566,10 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Space: resetSensors(); break; + + case Qt::Key_G: + goHome(); + break; case Qt::Key_A: _myAvatar.setDriveKeys(ROT_LEFT, 1); @@ -961,7 +963,6 @@ void Application::idle() { a.distance = 0.0f; a.tightness = 100.0f; _myCamera.setMode(CAMERA_MODE_FIRST_PERSON, a); - _myAvatar.setDisplayingHead(true); } } else { @@ -973,7 +974,6 @@ void Application::idle() { a.distance = 0.0f; a.tightness = 100.0f; _myCamera.setMode(CAMERA_MODE_FIRST_PERSON, a); - _myAvatar.setDisplayingHead(true); } } else { @@ -983,7 +983,6 @@ void Application::idle() { a.distance = 1.5f; a.tightness = 8.0f; _myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a); - _myAvatar.setDisplayingHead(true); } } } @@ -1027,15 +1026,13 @@ void Application::setHead(bool head) { 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) { @@ -1339,7 +1336,6 @@ void Application::init() { a.distance = 1.5f; a.tightness = 8.0f; _myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a); - _myAvatar.setDisplayingHead(true); _myAvatar.setDisplayingLookatVectors(false); QCursor::setPos(_headMouseX, _headMouseY); @@ -1711,13 +1707,13 @@ void Application::displaySide(Camera& whichCamera) { for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { Avatar *avatar = (Avatar *)agent->getLinkedData(); - avatar->render(0, _myCamera.getPosition()); + avatar->render(false); } } agentList->unlock(); // Render my own Avatar - _myAvatar.render(_lookingInMirror->isChecked(), _myCamera.getPosition()); + _myAvatar.render(_lookingInMirror->isChecked()); _myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked()); } @@ -2052,6 +2048,10 @@ void Application::deleteVoxelUnderCursor() { } } +void Application::goHome() { + _myAvatar.setPosition(START_LOCATION); +} + void Application::resetSensors() { _headMouseX = _mouseX = _glWidget->width() / 2; _headMouseY = _mouseY = _glWidget->height() / 2; diff --git a/interface/src/Application.h b/interface/src/Application.h index 8ef63b5022..bcdf04bfb6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -123,6 +123,7 @@ private: void maybeEditVoxelUnderCursor(); void deleteVoxelUnderCursor(); + void goHome(); void resetSensors(); void setMenuShortcutsEnabled(bool enabled); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index cb1f4d671f..bdfd7c8691 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -88,12 +88,10 @@ Avatar::Avatar(bool isMine) : _orientation(), _pelvisStandingHeight(0.0f), _pelvisFloatingHeight(0.0f), - _displayingHead(true), _distanceToNearestAvatar(std::numeric_limits::max()), _gravity(0.0f, -1.0f, 0.0f), _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), - _cameraPosition(0.0f, 0.0f, 0.0f), _interactingOther(NULL), _cumulativeMouseYaw(0.0f), _isMouseTurningRight(false) @@ -727,10 +725,8 @@ void Avatar::setGravity(glm::vec3 gravity) { _head.setGravity(_gravity); } -void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { - - _cameraPosition = cameraPosition; // store this for use in various parts of the code - +void Avatar::render(bool lookingInMirror) { + if (_isMine && usingBigSphereCollisionTest) { // show TEST big sphere glColor4f(0.5f, 0.6f, 0.8f, 0.7); @@ -749,7 +745,7 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { // if this is my avatar, then render my interactions with the other avatar if (_isMine) { - _avatarTouch.render(_cameraPosition); + _avatarTouch.render(getCameraPosition()); } // Render the balls @@ -1131,49 +1127,60 @@ void Avatar::updateArmIKAndConstraints(float deltaTime) { void Avatar::renderBody(bool lookingInMirror) { - // Render joint positions as spheres + const float RENDER_OPAQUE_BEYOND = 1.2f; // Meters beyond which body is shown opaque + const float RENDER_TRANSLUCENT_BEYOND = 0.5f; + + // Render the body as balls and cones for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - + float distanceToCamera = glm::length(getCameraPosition() - _joint[b].position); + // Always render other people, and render myself when beyond threshold distance if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case - if (_displayingHead) { + if (lookingInMirror || !_isMine || distanceToCamera > RENDER_OPAQUE_BEYOND) { _head.render(lookingInMirror); } - } else { - - glColor3f( - skinColor[0] + _joint[b].touchForce * 0.3f, - skinColor[1] - _joint[b].touchForce * 0.2f, - skinColor[2] - _joint[b].touchForce * 0.1f - ); - + } else if (!_isMine || distanceToCamera > RENDER_TRANSLUCENT_BEYOND) { + // Render the sphere at the joint + if (!_isMine) { + glColor3f(skinColor[0] + _joint[b].touchForce * 0.3f, + skinColor[1] - _joint[b].touchForce * 0.2f, + skinColor[2] - _joint[b].touchForce * 0.1f); + } else { + glColor4f(skinColor[0] + _joint[b].touchForce * 0.3f, + skinColor[1] - _joint[b].touchForce * 0.2f, + skinColor[2] - _joint[b].touchForce * 0.1f, + glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) + / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f)); + } glPushMatrix(); glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z); glutSolidSphere(_joint[b].radius, 20.0f, 20.0f); glPopMatrix(); + + // Render the cone connecting this joint to it's parent + + if (_joint[b].parent != AVATAR_JOINT_NULL) + if ((b != AVATAR_JOINT_HEAD_TOP ) + && (b != AVATAR_JOINT_HEAD_BASE ) + && (b != AVATAR_JOINT_PELVIS ) + && (b != AVATAR_JOINT_TORSO ) + && (b != AVATAR_JOINT_CHEST ) + && (b != AVATAR_JOINT_LEFT_COLLAR ) + && (b != AVATAR_JOINT_LEFT_SHOULDER ) + && (b != AVATAR_JOINT_RIGHT_COLLAR ) + && (b != AVATAR_JOINT_RIGHT_SHOULDER)) { + // Render cone sections connecting the joint positions + glColor3fv(darkSkinColor); + renderJointConnectingCone + ( + _joint[_joint[b].parent ].springyPosition, + _joint[b ].springyPosition, + _joint[_joint[b].parent ].radius * 0.8, + _joint[b ].radius * 0.8 + ); + } + } - } - - for (int j = 1; j < NUM_AVATAR_JOINTS; j++) { - if (_joint[j].parent != AVATAR_JOINT_NULL) - if ((j != AVATAR_JOINT_HEAD_TOP ) - && (j != AVATAR_JOINT_HEAD_BASE ) - && (j != AVATAR_JOINT_PELVIS ) - && (j != AVATAR_JOINT_TORSO ) - && (j != AVATAR_JOINT_CHEST ) - && (j != AVATAR_JOINT_LEFT_COLLAR ) - && (j != AVATAR_JOINT_LEFT_SHOULDER ) - && (j != AVATAR_JOINT_RIGHT_COLLAR ) - && (j != AVATAR_JOINT_RIGHT_SHOULDER)) { - // Render cone sections connecting the joint positions - glColor3fv(darkSkinColor); - renderJointConnectingCone - ( - _joint[_joint[j].parent ].springyPosition, - _joint[j ].springyPosition, - _joint[_joint[j].parent ].radius * 0.8, - _joint[j ].radius * 0.8 - ); - } + } } void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity, float deltaTime, float smoothingTime) { diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 20fd580328..f713a1a47f 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -108,12 +108,11 @@ public: Head& getHead() { return _head; } void setMousePressed(bool pressed); - void render(bool lookingInMirror, glm::vec3 cameraPosition); + void render(bool lookingInMirror); void renderBody(bool lookingInMirror); void simulate(float deltaTime, Transmitter* transmitter); void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset; } void updateArmIKAndConstraints( float deltaTime ); - void setDisplayingHead( bool displayingHead ) { _displayingHead = displayingHead; } void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); } // Set what driving keys are being pressed to control thrust levels @@ -177,12 +176,10 @@ private: float _height; Balls* _balls; AvatarTouch _avatarTouch; - 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; Avatar* _interactingOther; float _cumulativeMouseYaw; bool _isMouseTurningRight; diff --git a/interface/src/AvatarRenderer.cpp b/interface/src/AvatarRenderer.cpp index 45c10c4441..bfbfb7a5f3 100644 --- a/interface/src/AvatarRenderer.cpp +++ b/interface/src/AvatarRenderer.cpp @@ -10,74 +10,4 @@ #include "AvatarRenderer.h" #include "InterfaceConfig.h" -/* -AvatarRenderer::AvatarRenderer() { -} -// this method renders the avatar -void AvatarRenderer::render() { - - - // show avatar position - glColor4f(0.5f, 0.5f, 0.5f, 0.6); - glPushMatrix(); - glm::vec3 j( getJointPosition( AVATAR_JOINT_PELVIS ) ); - glTranslatef(j.x, j.y, j.z); - glScalef(0.08, 0.08, 0.08); - glutSolidSphere(1, 10, 10); - glPopMatrix(); - - renderDiskShadow(getJointPosition( AVATAR_JOINT_PELVIS ), glm::vec3(0.0f, 1.0f, 0.0f), 0.1f, 0.2f); - - //renderBody(lookingInMirror); -} - -void AvatarRenderer::renderBody() { - // 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 - if (_displayingHead) { - _head.render(lookingInMirror); - } - } else { - - //show direction vectors of the bone orientation - //renderOrientationDirections(_joint[b].springyPosition, _joint[b].orientation, _joint[b].radius * 2.0); - - glColor3fv(_avatar->skinColor); - glPushMatrix(); - glTranslatef(_avatar->[b].springyPosition.x, _avatar->_joint[b].springyPosition.y, _avatar->_joint[b].springyPosition.z); - glutSolidSphere(_avatar->_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); - - for (int b = 1; b < NUM_AVATAR_JOINTS; b++) { - if (_joint[b].parent != AVATAR_JOINT_NULL) - if (b != AVATAR_JOINT_HEAD_TOP) { - glBegin(GL_LINE_STRIP); - glVertex3fv(&_joint[ _joint[ b ].parent ].springyPosition.x); - glVertex3fv(&_joint[ b ].springyPosition.x); - glEnd(); - } - } -} -*/ -