From 297a78188af622d3fae3dc5f8bb6dbf4746f7919 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 10 Jun 2013 08:10:51 -0700 Subject: [PATCH 01/46] removed const values per code review --- libraries/voxels/src/VoxelNode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 952ad15bb7..58776755fa 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -103,8 +103,8 @@ public: void setColor(const nodeColor& color); const nodeColor& getTrueColor() const { return _trueColor; }; const nodeColor& getColor() const { return _currentColor; }; - void setDensity(const float density) { _density = density; }; - const float getDensity() const { return _density; }; + void setDensity(float density) { _density = density; }; + float getDensity() const { return _density; }; #else void setFalseColor(colorPart red, colorPart green, colorPart blue) { /* no op */ }; void setFalseColored(bool isFalseColored) { /* no op */ }; From 5820c3c7c33de16ed8e8d81c7257dc1f924e2df6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 10 Jun 2013 14:49:39 -0700 Subject: [PATCH 02/46] Remove average measurements, compute estimated acceleration (without rotated gravity). --- interface/src/SerialInterface.cpp | 23 ++++++++--------------- interface/src/SerialInterface.h | 12 +++++------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 28ae7eceb4..aca91bb34b 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -155,11 +155,11 @@ void SerialInterface::renderLevels(int width, int height) { // Acceleration rates glColor4f(1, 1, 1, 1); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 42); - glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)((_lastAcceleration.x - _gravity.x) *ACCEL_VIEW_SCALING), LEVEL_CORNER_Y + 42); + glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)(_estimatedAcceleration.x * ACCEL_VIEW_SCALING), LEVEL_CORNER_Y + 42); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 57); - glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)((_lastAcceleration.y - _gravity.y) *ACCEL_VIEW_SCALING), LEVEL_CORNER_Y + 57); + glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)(_estimatedAcceleration.y * ACCEL_VIEW_SCALING), LEVEL_CORNER_Y + 57); glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER, LEVEL_CORNER_Y + 72); - glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)((_lastAcceleration.z - _gravity.z) * ACCEL_VIEW_SCALING), LEVEL_CORNER_Y + 72); + glVertex2f(LEVEL_CORNER_X + LEVEL_CENTER + (int)(_estimatedAcceleration.z * ACCEL_VIEW_SCALING), LEVEL_CORNER_Y + 72); // Estimated Position glColor4f(0, 1, 1, 1); @@ -231,29 +231,24 @@ void SerialInterface::readData(float deltaTime) { // Update raw rotation estimates glm::quat estimatedRotation = glm::quat(glm::radians(_estimatedRotation)) * - glm::quat(glm::radians(deltaTime * (_lastRotationRates - _averageRotationRates))); + glm::quat(glm::radians(deltaTime * _lastRotationRates)); + + // Update acceleration estimate + _estimatedAcceleration = _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; // Update estimated position and velocity float const DECAY_VELOCITY = 0.95f; float const DECAY_POSITION = 0.95f; - _estimatedVelocity += deltaTime * (_lastAcceleration - _averageAcceleration); + _estimatedVelocity += deltaTime * _estimatedAcceleration; _estimatedPosition += deltaTime * _estimatedVelocity; _estimatedVelocity *= DECAY_VELOCITY; _estimatedPosition *= DECAY_POSITION; // Accumulate a set of initial baseline readings for setting gravity if (totalSamples == 0) { - _averageRotationRates = _lastRotationRates; - _averageAcceleration = _lastAcceleration; _gravity = _lastAcceleration; } else { - // Cumulate long term average to (hopefully) take DC bias out of rotation rates - _averageRotationRates = (1.f - 1.f / (float)LONG_TERM_RATE_SAMPLES) * _averageRotationRates - + 1.f / (float)LONG_TERM_RATE_SAMPLES * _lastRotationRates; - _averageAcceleration = (1.f - 1.f / (float)LONG_TERM_RATE_SAMPLES) * _averageAcceleration - + 1.f / (float)LONG_TERM_RATE_SAMPLES * _lastAcceleration; - if (totalSamples < GRAVITY_SAMPLES) { _gravity = (1.f - 1.f/(float)GRAVITY_SAMPLES) * _gravity + 1.f/(float)GRAVITY_SAMPLES * _lastAcceleration; @@ -293,8 +288,6 @@ void SerialInterface::readData(float deltaTime) { void SerialInterface::resetAverages() { totalSamples = 0; _gravity = glm::vec3(0, 0, 0); - _averageRotationRates = glm::vec3(0, 0, 0); - _averageAcceleration = glm::vec3(0, 0, 0); _lastRotationRates = glm::vec3(0, 0, 0); _estimatedRotation = glm::vec3(0, 0, 0); _estimatedPosition = glm::vec3(0, 0, 0); diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index 3fc9ea920a..a49c09c599 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -26,8 +26,6 @@ class SerialInterface { public: SerialInterface() : active(false), _gravity(0, 0, 0), - _averageRotationRates(0, 0, 0), - _averageAcceleration(0, 0, 0), _estimatedRotation(0, 0, 0), _estimatedPosition(0, 0, 0), _estimatedVelocity(0, 0, 0), @@ -37,13 +35,14 @@ public: void pair(); void readData(float deltaTime); - const float getLastPitchRate() const { return _lastRotationRates[0] - _averageRotationRates[0]; } - const float getLastYawRate() const { return _lastRotationRates[1] - _averageRotationRates[1]; } - const float getLastRollRate() const { return _lastRotationRates[2] - _averageRotationRates[2]; } + const float getLastPitchRate() const { return _lastRotationRates[0]; } + const float getLastYawRate() const { return _lastRotationRates[1]; } + const float getLastRollRate() const { return _lastRotationRates[2]; } const glm::vec3& getLastRotationRates() const { return _lastRotationRates; }; const glm::vec3& getEstimatedRotation() const { return _estimatedRotation; }; const glm::vec3& getEstimatedPosition() const { return _estimatedPosition; }; const glm::vec3& getEstimatedVelocity() const { return _estimatedVelocity; }; + const glm::vec3& getEstimatedAcceleration() const { return _estimatedAcceleration; }; const glm::vec3& getLastAcceleration() const { return _lastAcceleration; }; const glm::vec3& getGravity() const { return _gravity; }; @@ -59,11 +58,10 @@ private: int totalSamples; timeval lastGoodRead; glm::vec3 _gravity; - glm::vec3 _averageRotationRates; - glm::vec3 _averageAcceleration; glm::vec3 _estimatedRotation; glm::vec3 _estimatedPosition; glm::vec3 _estimatedVelocity; + glm::vec3 _estimatedAcceleration; glm::vec3 _lastAcceleration; glm::vec3 _lastRotationRates; }; From 1b8683cbc5371b6603758c32bd9c667eba7e19a4 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 10 Jun 2013 15:22:53 -0700 Subject: [PATCH 03/46] Let's see if we can get an estimate of the distance to the sensor based on the ratios between linear and angular velocity. --- interface/src/SerialInterface.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index aca91bb34b..26c7f5f581 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -225,9 +225,14 @@ void SerialInterface::readData(float deltaTime) { // Convert the integer rates to floats const float LSB_TO_DEGREES_PER_SECOND = 1.f / 16.4f; // From MPU-9150 register map, 2000 deg/sec. - _lastRotationRates[0] = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND; - _lastRotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; - _lastRotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND; + glm::vec3 rotationRates; + rotationRates[0] = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND; + rotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; + rotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND; + + // compute the angular acceleration + glm::vec3 angularAcceleration = (deltaTime < EPSILON) ? glm::vec3() : (rotationRates - _lastRotationRates) / deltaTime; + _lastRotationRates = rotationRates; // Update raw rotation estimates glm::quat estimatedRotation = glm::quat(glm::radians(_estimatedRotation)) * @@ -236,6 +241,16 @@ void SerialInterface::readData(float deltaTime) { // Update acceleration estimate _estimatedAcceleration = _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; + static float ratioEstimate = 0.0f; + float angularAccelerationLength = glm::length(angularAcceleration); + float linearAccelerationLength = glm::length(estimatedAcceleration); + if (angularAccelerationLength > EPSILON && linearAccelerationLength > EPSILON) { + float ratio = linearAccelerationLength / angularAccelerationLength; + static float ratioEstimate = ratio; + ratioEstimate = ratioEstimate * 0.999 + ratio * 0.001; + printLog("%g %g\n", ratio, ratioEstimate); + } + // Update estimated position and velocity float const DECAY_VELOCITY = 0.95f; float const DECAY_POSITION = 0.95f; From 90ef6a7cc0b3fe20d58b266d835ccdb27d08c713 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 10 Jun 2013 18:40:07 -0700 Subject: [PATCH 04/46] Attempting to perform the transform between angular and linear acceleration. --- interface/src/SerialInterface.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 26c7f5f581..407f06f736 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -238,18 +238,19 @@ void SerialInterface::readData(float deltaTime) { glm::quat estimatedRotation = glm::quat(glm::radians(_estimatedRotation)) * glm::quat(glm::radians(deltaTime * _lastRotationRates)); + // The acceleration matrix transforms angular to linear accelerations + const glm::vec3 PIVOT_OFFSET(0.0f, -0.02f, -0.01f); + const glm::vec3 PIVOT_VECTOR_NORMALIZED = glm::normalize(PIVOT_OFFSET); + const glm::vec3 PIVOT_SINES = glm::max(glm::vec3(EPSILON, EPSILON, EPSILON), + glm::sqrt(glm::vec3(1.0f, 1.0f, 1.0f) - PIVOT_OFFSET * PIVOT_OFFSET)); + const glm::mat3 ACCELERATION_MATRIX( + 0.0f, PIVOT_OFFSET.z / PIVOT_SINES.x, -PIVOT_OFFSET.y / PIVOT_SINES.x, + -PIVOT_OFFSET.z / PIVOT_SINES.y, 0.0f, PIVOT_OFFSET.x / PIVOT_SINES.y, + PIVOT_OFFSET.y / PIVOT_SINES.z, -PIVOT_OFFSET.x / PIVOT_SINES.z, 0.0f); + // Update acceleration estimate - _estimatedAcceleration = _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; - - static float ratioEstimate = 0.0f; - float angularAccelerationLength = glm::length(angularAcceleration); - float linearAccelerationLength = glm::length(estimatedAcceleration); - if (angularAccelerationLength > EPSILON && linearAccelerationLength > EPSILON) { - float ratio = linearAccelerationLength / angularAccelerationLength; - static float ratioEstimate = ratio; - ratioEstimate = ratioEstimate * 0.999 + ratio * 0.001; - printLog("%g %g\n", ratio, ratioEstimate); - } + _estimatedAcceleration = _lastAcceleration - glm::inverse(estimatedRotation) * _gravity - + ACCELERATION_MATRIX * angularAcceleration; // Update estimated position and velocity float const DECAY_VELOCITY = 0.95f; From a34f9a0ef3142091f5d053eccdc41052111cc91a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 10 Jun 2013 18:41:49 -0700 Subject: [PATCH 05/46] Need to include SharedUtil. --- interface/src/SerialInterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 407f06f736..2e5124c1b3 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -6,6 +6,7 @@ // #include "SerialInterface.h" +#include "SharedUtil.h" #include "Util.h" #include #include From 988c4f97b04e13804eba41c03e3e6a8c3c6640e9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 10 Jun 2013 18:43:11 -0700 Subject: [PATCH 06/46] This should be the normalized offset. --- interface/src/SerialInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 2e5124c1b3..7c4d1ac86f 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -241,9 +241,9 @@ void SerialInterface::readData(float deltaTime) { // The acceleration matrix transforms angular to linear accelerations const glm::vec3 PIVOT_OFFSET(0.0f, -0.02f, -0.01f); - const glm::vec3 PIVOT_VECTOR_NORMALIZED = glm::normalize(PIVOT_OFFSET); + const glm::vec3 PIVOT_OFFSET_NORMALIZED = glm::normalize(PIVOT_OFFSET); const glm::vec3 PIVOT_SINES = glm::max(glm::vec3(EPSILON, EPSILON, EPSILON), - glm::sqrt(glm::vec3(1.0f, 1.0f, 1.0f) - PIVOT_OFFSET * PIVOT_OFFSET)); + glm::sqrt(glm::vec3(1.0f, 1.0f, 1.0f) - PIVOT_OFFSET_NORMALIZED * PIVOT_OFFSET_NORMALIZED)); const glm::mat3 ACCELERATION_MATRIX( 0.0f, PIVOT_OFFSET.z / PIVOT_SINES.x, -PIVOT_OFFSET.y / PIVOT_SINES.x, -PIVOT_OFFSET.z / PIVOT_SINES.y, 0.0f, PIVOT_OFFSET.x / PIVOT_SINES.y, From 73ceea7795dbe8db4f58d4fb0af058e9d43927a8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 10:55:28 -0700 Subject: [PATCH 07/46] Working on "learning" the acceleration matrices. --- interface/src/SerialInterface.cpp | 55 ++++++++++++++++++++++++------- interface/src/SerialInterface.h | 7 +++- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 7c4d1ac86f..cbd03f801b 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -239,19 +239,50 @@ void SerialInterface::readData(float deltaTime) { glm::quat estimatedRotation = glm::quat(glm::radians(_estimatedRotation)) * glm::quat(glm::radians(deltaTime * _lastRotationRates)); - // The acceleration matrix transforms angular to linear accelerations - const glm::vec3 PIVOT_OFFSET(0.0f, -0.02f, -0.01f); - const glm::vec3 PIVOT_OFFSET_NORMALIZED = glm::normalize(PIVOT_OFFSET); - const glm::vec3 PIVOT_SINES = glm::max(glm::vec3(EPSILON, EPSILON, EPSILON), - glm::sqrt(glm::vec3(1.0f, 1.0f, 1.0f) - PIVOT_OFFSET_NORMALIZED * PIVOT_OFFSET_NORMALIZED)); - const glm::mat3 ACCELERATION_MATRIX( - 0.0f, PIVOT_OFFSET.z / PIVOT_SINES.x, -PIVOT_OFFSET.y / PIVOT_SINES.x, - -PIVOT_OFFSET.z / PIVOT_SINES.y, 0.0f, PIVOT_OFFSET.x / PIVOT_SINES.y, - PIVOT_OFFSET.y / PIVOT_SINES.z, -PIVOT_OFFSET.x / PIVOT_SINES.z, 0.0f); + // Update acceleration estimate: first, subtract gravity as rotated into current frame + _estimatedAcceleration = _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; + + // Consider updating our angular velocity/acceleration to linear acceleration mapping + if (glm::length(_lastRotationRates) > EPSILON || glm::length(angularAcceleration) > EPSILON) { + // compute predicted linear acceleration, find error between actual and predicted + glm::vec3 predictedAcceleration = _angularVelocityToLinearAccel * _lastRotationRates + + _angularAccelToLinearAccel * angularAcceleration; + glm::vec3 error = _estimatedAcceleration - predictedAcceleration; - // Update acceleration estimate - _estimatedAcceleration = _lastAcceleration - glm::inverse(estimatedRotation) * _gravity - - ACCELERATION_MATRIX * angularAcceleration; + // adjust according to error in each dimension, in proportion to input magnitudes + for (int i = 0; i < 3; i++) { + if (fabsf(error[i]) < EPSILON) { + continue; + } + const float LEARNING_RATE = 0.1f; + float rateSum = fabsf(_lastRotationRates.x) + fabsf(_lastRotationRates.y) + fabsf(_lastRotationRates.z); + if (rateSum > EPSILON) { + for (int j = 0; j < 3; j++) { + float proportion = LEARNING_RATE * fabsf(_lastRotationRates[j]) / rateSum; + if (proportion > EPSILON) { + _angularVelocityToLinearAccel[j][i] += error[i] * proportion / _lastRotationRates[j]; + } + } + } + float accelSum = fabsf(angularAcceleration.x) + fabsf(angularAcceleration.y) + fabsf(angularAcceleration.z); + if (accelSum > EPSILON) { + for (int j = 0; j < 3; j++) { + float proportion = LEARNING_RATE * fabsf(angularAcceleration[j]) / accelSum; + if (proportion > EPSILON) { + _angularAccelToLinearAccel[j][i] += error[i] * proportion / angularAcceleration[j]; + } + } + } + } + } + + printLog("%g %g %g\n", _angularVelocityToLinearAccel[0][0], _angularVelocityToLinearAccel[1][0], _angularVelocityToLinearAccel[2][0]); + printLog("%g %g %g\n", _angularVelocityToLinearAccel[0][1], _angularVelocityToLinearAccel[1][1], _angularVelocityToLinearAccel[2][1]); + printLog("%g %g %g\n\n", _angularVelocityToLinearAccel[0][2], _angularVelocityToLinearAccel[1][2], _angularVelocityToLinearAccel[2][2]); + + printLog("%g %g %g\n", _angularAccelToLinearAccel[0][0], _angularAccelToLinearAccel[1][0], _angularAccelToLinearAccel[2][0]); + printLog("%g %g %g\n", _angularAccelToLinearAccel[0][1], _angularAccelToLinearAccel[1][1], _angularAccelToLinearAccel[2][1]); + printLog("%g %g %g\n\n", _angularAccelToLinearAccel[0][2], _angularAccelToLinearAccel[1][2], _angularAccelToLinearAccel[2][2]); // Update estimated position and velocity float const DECAY_VELOCITY = 0.95f; diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index a49c09c599..b7ead8c9d7 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -30,7 +30,9 @@ public: _estimatedPosition(0, 0, 0), _estimatedVelocity(0, 0, 0), _lastAcceleration(0, 0, 0), - _lastRotationRates(0, 0, 0) + _lastRotationRates(0, 0, 0), + _angularVelocityToLinearAccel(0), + _angularAccelToLinearAccel(0) {} void pair(); @@ -64,6 +66,9 @@ private: glm::vec3 _estimatedAcceleration; glm::vec3 _lastAcceleration; glm::vec3 _lastRotationRates; + + glm::mat3 _angularVelocityToLinearAccel; + glm::mat3 _angularAccelToLinearAccel; }; #endif From b1e3a0984b85d897b61b1a00b67c0413ead3777f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 11 Jun 2013 11:10:09 -0700 Subject: [PATCH 08/46] Improved mouse look behavior to be smoother, removed transmitter debug. --- interface/src/Application.cpp | 2 +- interface/src/Avatar.cpp | 23 ++++++++--------------- interface/src/Transmitter.cpp | 4 +--- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eb03e1f592..0d73702a86 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1206,7 +1206,7 @@ void Application::initMenu() { (_gyroLook = optionsMenu->addAction("Gyro Look"))->setCheckable(true); _gyroLook->setChecked(false); (_mouseLook = optionsMenu->addAction("Mouse Look"))->setCheckable(true); - _mouseLook->setChecked(false); + _mouseLook->setChecked(true); (_showHeadMouse = optionsMenu->addAction("Head Mouse"))->setCheckable(true); _showHeadMouse->setChecked(false); (_transmitterDrives = optionsMenu->addAction("Transmitter Drive"))->setCheckable(true); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index e5c5a76a70..771d2cd891 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -317,30 +317,23 @@ glm::quat Avatar::getWorldAlignedOrientation () const { void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) { // Update head yaw and pitch based on mouse input - const float MOUSE_MOVE_RADIUS = 0.3f; - const float MOUSE_ROTATE_SPEED = 4.0f; - const float MOUSE_PITCH_SPEED = 2.0f; + const float MOUSE_ROTATE_SPEED = 0.01f; + const float MOUSE_PITCH_SPEED = 0.02f; const int TITLE_BAR_HEIGHT = 46; - float mouseLocationX = (float)mouseX / (float)screenWidth - 0.5f; - float mouseLocationY = (float)mouseY / (float)screenHeight - 0.5f; if ((mouseX > 1) && (mouseX < screenWidth) && (mouseY > TITLE_BAR_HEIGHT) && (mouseY < screenHeight)) { // // Mouse must be inside screen (not at edge) and not on title bar for movement to happen // - if (mouseLocationX > MOUSE_MOVE_RADIUS) { - _head.addYaw(-(mouseLocationX - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_ROTATE_SPEED); - } else if (mouseLocationX < -MOUSE_MOVE_RADIUS) { - _head.addYaw(-(mouseLocationX + MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_ROTATE_SPEED); - } - if (mouseLocationY > MOUSE_MOVE_RADIUS) { - _head.addPitch(-(mouseLocationY - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED); - } else if (mouseLocationY < -MOUSE_MOVE_RADIUS) { - _head.addPitch(-(mouseLocationY + MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED); + int pixelMoveThreshold = screenWidth / 6; + glm::vec2 mouseVector(mouseX - (screenWidth / 2), mouseY - (screenHeight / 2)); + if (glm::length(mouseVector) > pixelMoveThreshold) { + mouseVector -= glm::normalize(mouseVector) * (float) pixelMoveThreshold; + _head.addYaw(-mouseVector.x * MOUSE_ROTATE_SPEED); + _head.addPitch(-mouseVector.y * MOUSE_PITCH_SPEED); } } - return; } void Avatar::simulate(float deltaTime, Transmitter* transmitter) { diff --git a/interface/src/Transmitter.cpp b/interface/src/Transmitter.cpp index a02e864087..8cbb4a5c29 100644 --- a/interface/src/Transmitter.cpp +++ b/interface/src/Transmitter.cpp @@ -70,9 +70,7 @@ void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) { // Update estimated absolute position from rotation rates _estimatedRotation += _lastRotationRate * DELTA_TIME; - - printf("The accel %f, %f, %f\n", _lastAcceleration.x, _lastAcceleration.y, _lastAcceleration.z); - + // Sensor Fusion! Slowly adjust estimated rotation to be relative to gravity (average acceleration) const float GRAVITY_FOLLOW_RATE = 1.f; float rollAngle = angleBetween(glm::vec3(_lastAcceleration.x, _lastAcceleration.y, 0.f), glm::vec3(0,-1,0)) * From bf389de774a14b658850d3cf3940b83af787dd67 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 11:22:43 -0700 Subject: [PATCH 09/46] Testing a different coordinate conversion. --- interface/src/SerialInterface.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index cbd03f801b..03a03b87aa 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -216,8 +216,9 @@ void SerialInterface::readData(float deltaTime) { // From MPU-9150 register map, with setting on // highest resolution = +/- 2G - _lastAcceleration = glm::vec3(-accelXRate, -accelYRate, -accelZRate) * LSB_TO_METERS_PER_SECOND2; - + //_lastAcceleration = glm::vec3(-accelXRate, -accelYRate, -accelZRate) * LSB_TO_METERS_PER_SECOND2; + _lastAcceleration = glm::vec3(-accelYRate, accelXRate, accelZRate) * LSB_TO_METERS_PER_SECOND2; + int rollRate, yawRate, pitchRate; convertHexToInt(sensorBuffer + 22, rollRate); @@ -227,8 +228,12 @@ void SerialInterface::readData(float deltaTime) { // Convert the integer rates to floats const float LSB_TO_DEGREES_PER_SECOND = 1.f / 16.4f; // From MPU-9150 register map, 2000 deg/sec. glm::vec3 rotationRates; - rotationRates[0] = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND; - rotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; + //rotationRates[0] = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND; + //rotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; + //rotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND; + + rotationRates[0] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; + rotationRates[1] = ((float) pitchRate) * LSB_TO_DEGREES_PER_SECOND; rotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND; // compute the angular acceleration From ff9e6f831c17bc0285f660681a8f296441a60853 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 11:31:01 -0700 Subject: [PATCH 10/46] Revert to previous coordinates. --- interface/src/SerialInterface.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 03a03b87aa..cbd03f801b 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -216,9 +216,8 @@ void SerialInterface::readData(float deltaTime) { // From MPU-9150 register map, with setting on // highest resolution = +/- 2G - //_lastAcceleration = glm::vec3(-accelXRate, -accelYRate, -accelZRate) * LSB_TO_METERS_PER_SECOND2; - _lastAcceleration = glm::vec3(-accelYRate, accelXRate, accelZRate) * LSB_TO_METERS_PER_SECOND2; - + _lastAcceleration = glm::vec3(-accelXRate, -accelYRate, -accelZRate) * LSB_TO_METERS_PER_SECOND2; + int rollRate, yawRate, pitchRate; convertHexToInt(sensorBuffer + 22, rollRate); @@ -228,12 +227,8 @@ void SerialInterface::readData(float deltaTime) { // Convert the integer rates to floats const float LSB_TO_DEGREES_PER_SECOND = 1.f / 16.4f; // From MPU-9150 register map, 2000 deg/sec. glm::vec3 rotationRates; - //rotationRates[0] = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND; - //rotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; - //rotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND; - - rotationRates[0] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; - rotationRates[1] = ((float) pitchRate) * LSB_TO_DEGREES_PER_SECOND; + rotationRates[0] = ((float) -pitchRate) * LSB_TO_DEGREES_PER_SECOND; + rotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; rotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND; // compute the angular acceleration From 517bbe80a7d8a3efe86d2fe126efca0884cf1997 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 13:02:20 -0700 Subject: [PATCH 11/46] Initial values, report error. --- interface/src/SerialInterface.cpp | 2 ++ interface/src/SerialInterface.h | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index cbd03f801b..f4af4437d8 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -249,6 +249,8 @@ void SerialInterface::readData(float deltaTime) { _angularAccelToLinearAccel * angularAcceleration; glm::vec3 error = _estimatedAcceleration - predictedAcceleration; + printLog("error %g\n", glm::length(error)); + // adjust according to error in each dimension, in proportion to input magnitudes for (int i = 0; i < 3; i++) { if (fabsf(error[i]) < EPSILON) { diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index b7ead8c9d7..2bb7e541ac 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -31,8 +31,14 @@ public: _estimatedVelocity(0, 0, 0), _lastAcceleration(0, 0, 0), _lastRotationRates(0, 0, 0), - _angularVelocityToLinearAccel(0), - _angularAccelToLinearAccel(0) + _angularVelocityToLinearAccel( // experimentally derived initial values + 0.001f, -0.008f, 0.020f, + 0.003f, -0.003f, 0.025f, + 0.017f, 0.007f, 0.029f), + _angularAccelToLinearAccel( // experimentally derived initial values + 0.0f, 0.0f, 0.002f, + 0.0f, 0.0f, 0.002f, + -0.002f, -0.002f, 0.0f) {} void pair(); From 5ba1d3a28cbd980d813e0159e6f88d5485cdaf6b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 13:18:13 -0700 Subject: [PATCH 12/46] It ain't perfect, but I'm going with what I've got for now. --- interface/src/SerialInterface.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index f4af4437d8..af9c35196b 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -249,14 +249,15 @@ void SerialInterface::readData(float deltaTime) { _angularAccelToLinearAccel * angularAcceleration; glm::vec3 error = _estimatedAcceleration - predictedAcceleration; - printLog("error %g\n", glm::length(error)); + // the "error" is actually what we want: the linear acceleration minus rotational influences + _estimatedAcceleration = error; // adjust according to error in each dimension, in proportion to input magnitudes for (int i = 0; i < 3; i++) { if (fabsf(error[i]) < EPSILON) { continue; } - const float LEARNING_RATE = 0.1f; + const float LEARNING_RATE = 0.01f; float rateSum = fabsf(_lastRotationRates.x) + fabsf(_lastRotationRates.y) + fabsf(_lastRotationRates.z); if (rateSum > EPSILON) { for (int j = 0; j < 3; j++) { @@ -278,13 +279,8 @@ void SerialInterface::readData(float deltaTime) { } } - printLog("%g %g %g\n", _angularVelocityToLinearAccel[0][0], _angularVelocityToLinearAccel[1][0], _angularVelocityToLinearAccel[2][0]); - printLog("%g %g %g\n", _angularVelocityToLinearAccel[0][1], _angularVelocityToLinearAccel[1][1], _angularVelocityToLinearAccel[2][1]); - printLog("%g %g %g\n\n", _angularVelocityToLinearAccel[0][2], _angularVelocityToLinearAccel[1][2], _angularVelocityToLinearAccel[2][2]); - - printLog("%g %g %g\n", _angularAccelToLinearAccel[0][0], _angularAccelToLinearAccel[1][0], _angularAccelToLinearAccel[2][0]); - printLog("%g %g %g\n", _angularAccelToLinearAccel[0][1], _angularAccelToLinearAccel[1][1], _angularAccelToLinearAccel[2][1]); - printLog("%g %g %g\n\n", _angularAccelToLinearAccel[0][2], _angularAccelToLinearAccel[1][2], _angularAccelToLinearAccel[2][2]); + // rotate estimated acceleration into global rotation frame + _estimatedAcceleration = estimatedRotation * _estimatedAcceleration; // Update estimated position and velocity float const DECAY_VELOCITY = 0.95f; From b88380db6f01841aceded1cdaaf20758a6063fe1 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 13:43:29 -0700 Subject: [PATCH 13/46] New values, slower learning. --- interface/src/SerialInterface.cpp | 2 +- interface/src/SerialInterface.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index af9c35196b..be1e6328da 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -257,7 +257,7 @@ void SerialInterface::readData(float deltaTime) { if (fabsf(error[i]) < EPSILON) { continue; } - const float LEARNING_RATE = 0.01f; + const float LEARNING_RATE = 0.001f; float rateSum = fabsf(_lastRotationRates.x) + fabsf(_lastRotationRates.y) + fabsf(_lastRotationRates.z); if (rateSum > EPSILON) { for (int j = 0; j < 3; j++) { diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index 2bb7e541ac..b10fba84ce 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -32,12 +32,12 @@ public: _lastAcceleration(0, 0, 0), _lastRotationRates(0, 0, 0), _angularVelocityToLinearAccel( // experimentally derived initial values - 0.001f, -0.008f, 0.020f, - 0.003f, -0.003f, 0.025f, - 0.017f, 0.007f, 0.029f), + 0.003f, -0.001f, -0.006f, + -0.005f, -0.001f, -0.006f, + 0.010f, 0.004f, 0.007f), _angularAccelToLinearAccel( // experimentally derived initial values 0.0f, 0.0f, 0.002f, - 0.0f, 0.0f, 0.002f, + 0.0f, 0.0f, 0.001f, -0.002f, -0.002f, 0.0f) {} From 47bd3bcdd7cc7bb971441a24e353b08c3b30adb7 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 14:03:49 -0700 Subject: [PATCH 14/46] Don't estimate acceleration before we know the gravity and don't update our matrices without acceleration. --- interface/src/SerialInterface.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index be1e6328da..2132f5a2de 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -240,10 +240,12 @@ void SerialInterface::readData(float deltaTime) { glm::quat(glm::radians(deltaTime * _lastRotationRates)); // Update acceleration estimate: first, subtract gravity as rotated into current frame - _estimatedAcceleration = _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; + _estimatedAcceleration = (totalSamples < GRAVITY_SAMPLES) ? glm::vec3() : + _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; // Consider updating our angular velocity/acceleration to linear acceleration mapping - if (glm::length(_lastRotationRates) > EPSILON || glm::length(angularAcceleration) > EPSILON) { + if (glm::length(_estimatedAcceleration) > EPSILON && + glm::length(_lastRotationRates) > EPSILON || glm::length(angularAcceleration) > EPSILON) { // compute predicted linear acceleration, find error between actual and predicted glm::vec3 predictedAcceleration = _angularVelocityToLinearAccel * _lastRotationRates + _angularAccelToLinearAccel * angularAcceleration; @@ -338,6 +340,7 @@ void SerialInterface::resetAverages() { _estimatedRotation = glm::vec3(0, 0, 0); _estimatedPosition = glm::vec3(0, 0, 0); _estimatedVelocity = glm::vec3(0, 0, 0); + _estimatedAcceleration = glm::vec3(0, 0, 0); } void SerialInterface::resetSerial() { From 4b890e2ccc677ce05c695ba3ad6c976012d37892 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 14:23:47 -0700 Subject: [PATCH 15/46] Let's see what the long-term average acceleration is. --- interface/src/SerialInterface.cpp | 7 ++++++- interface/src/SerialInterface.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 2132f5a2de..8e3cddf9bb 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -218,6 +218,11 @@ void SerialInterface::readData(float deltaTime) { _lastAcceleration = glm::vec3(-accelXRate, -accelYRate, -accelZRate) * LSB_TO_METERS_PER_SECOND2; + _averageAcceleration = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageAcceleration + + 1.f/(float)LONG_TERM_RATE_SAMPLES * _lastAcceleration; + + printLog("%g %g %g\n", _averageAcceleration.x, _averageAcceleration.y, _averageAcceleration.z); + int rollRate, yawRate, pitchRate; convertHexToInt(sensorBuffer + 22, rollRate); @@ -245,7 +250,7 @@ void SerialInterface::readData(float deltaTime) { // Consider updating our angular velocity/acceleration to linear acceleration mapping if (glm::length(_estimatedAcceleration) > EPSILON && - glm::length(_lastRotationRates) > EPSILON || glm::length(angularAcceleration) > EPSILON) { + (glm::length(_lastRotationRates) > EPSILON || glm::length(angularAcceleration) > EPSILON)) { // compute predicted linear acceleration, find error between actual and predicted glm::vec3 predictedAcceleration = _angularVelocityToLinearAccel * _lastRotationRates + _angularAccelToLinearAccel * angularAcceleration; diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index b10fba84ce..73f67fc618 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -73,6 +73,8 @@ private: glm::vec3 _lastAcceleration; glm::vec3 _lastRotationRates; + glm::vec3 _averageAcceleration; + glm::mat3 _angularVelocityToLinearAccel; glm::mat3 _angularAccelToLinearAccel; }; From d913f8dec03e419694108416add1f3902f6666de Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 14:25:05 -0700 Subject: [PATCH 16/46] Actually, we want it sans gravity. --- interface/src/SerialInterface.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 8e3cddf9bb..9933ba1129 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -218,10 +218,6 @@ void SerialInterface::readData(float deltaTime) { _lastAcceleration = glm::vec3(-accelXRate, -accelYRate, -accelZRate) * LSB_TO_METERS_PER_SECOND2; - _averageAcceleration = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageAcceleration + - 1.f/(float)LONG_TERM_RATE_SAMPLES * _lastAcceleration; - - printLog("%g %g %g\n", _averageAcceleration.x, _averageAcceleration.y, _averageAcceleration.z); int rollRate, yawRate, pitchRate; @@ -248,6 +244,11 @@ void SerialInterface::readData(float deltaTime) { _estimatedAcceleration = (totalSamples < GRAVITY_SAMPLES) ? glm::vec3() : _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; + _averageAcceleration = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageAcceleration + + 1.f/(float)LONG_TERM_RATE_SAMPLES * _estimatedAcceleration; + + printLog("%g %g %g\n", _averageAcceleration.x, _averageAcceleration.y, _averageAcceleration.z); + // Consider updating our angular velocity/acceleration to linear acceleration mapping if (glm::length(_estimatedAcceleration) > EPSILON && (glm::length(_lastRotationRates) > EPSILON || glm::length(angularAcceleration) > EPSILON)) { From e77aee39676d2ffce770e402ed0356be1a5f6896 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 15:47:05 -0700 Subject: [PATCH 17/46] Show the average rotation rates, too. --- interface/src/SerialInterface.cpp | 7 ++++++- interface/src/SerialInterface.h | 1 + libraries/shared/src/SharedUtil.cpp | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 9933ba1129..02c672ba8f 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -236,6 +236,11 @@ void SerialInterface::readData(float deltaTime) { glm::vec3 angularAcceleration = (deltaTime < EPSILON) ? glm::vec3() : (rotationRates - _lastRotationRates) / deltaTime; _lastRotationRates = rotationRates; + _averageRotationRates = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageRotationRates + + 1.f/(float)LONG_TERM_RATE_SAMPLES * _lastRotationRates; + + printLog("r: %g %g %g\n", _averageRotationRates.x, _averageRotationRates.y, _averageRotationRates.z); + // Update raw rotation estimates glm::quat estimatedRotation = glm::quat(glm::radians(_estimatedRotation)) * glm::quat(glm::radians(deltaTime * _lastRotationRates)); @@ -247,7 +252,7 @@ void SerialInterface::readData(float deltaTime) { _averageAcceleration = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageAcceleration + 1.f/(float)LONG_TERM_RATE_SAMPLES * _estimatedAcceleration; - printLog("%g %g %g\n", _averageAcceleration.x, _averageAcceleration.y, _averageAcceleration.z); + printLog("a: %g %g %g\n", _averageAcceleration.x, _averageAcceleration.y, _averageAcceleration.z); // Consider updating our angular velocity/acceleration to linear acceleration mapping if (glm::length(_estimatedAcceleration) > EPSILON && diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index 73f67fc618..88af60ccbe 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -74,6 +74,7 @@ private: glm::vec3 _lastRotationRates; glm::vec3 _averageAcceleration; + glm::vec3 _averageRotationRates; glm::mat3 _angularVelocityToLinearAccel; glm::mat3 _angularAccelToLinearAccel; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 30aa75b461..697719b36d 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -102,12 +102,12 @@ void setAtBit(unsigned char& byte, int bitIndex) { } int getSemiNibbleAt(unsigned char& byte, int bitIndex) { - return (byte >> (7 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 + return (byte >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 } void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) { //assert(value <= 3 && value >= 0); - byte += ((value & 3) << (7 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 + byte += ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 } From 090df81afebb29d8c95a2141cab728f9476f3d22 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 15:58:50 -0700 Subject: [PATCH 18/46] Fixes to align better with previous code. --- interface/src/SerialInterface.cpp | 16 +++++++++------- interface/src/SerialInterface.h | 7 ++++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 02c672ba8f..86755e28b5 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -232,15 +232,15 @@ void SerialInterface::readData(float deltaTime) { rotationRates[1] = ((float) -yawRate) * LSB_TO_DEGREES_PER_SECOND; rotationRates[2] = ((float) -rollRate) * LSB_TO_DEGREES_PER_SECOND; + // update and subtract the long term average + _averageRotationRates = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageRotationRates + + 1.f/(float)LONG_TERM_RATE_SAMPLES * rotationRates; + rotationRates -= _averageRotationRates; + // compute the angular acceleration glm::vec3 angularAcceleration = (deltaTime < EPSILON) ? glm::vec3() : (rotationRates - _lastRotationRates) / deltaTime; _lastRotationRates = rotationRates; - - _averageRotationRates = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageRotationRates + - 1.f/(float)LONG_TERM_RATE_SAMPLES * _lastRotationRates; - printLog("r: %g %g %g\n", _averageRotationRates.x, _averageRotationRates.y, _averageRotationRates.z); - // Update raw rotation estimates glm::quat estimatedRotation = glm::quat(glm::radians(_estimatedRotation)) * glm::quat(glm::radians(deltaTime * _lastRotationRates)); @@ -249,10 +249,10 @@ void SerialInterface::readData(float deltaTime) { _estimatedAcceleration = (totalSamples < GRAVITY_SAMPLES) ? glm::vec3() : _lastAcceleration - glm::inverse(estimatedRotation) * _gravity; + // update and subtract the long term average _averageAcceleration = (1.f - 1.f/(float)LONG_TERM_RATE_SAMPLES) * _averageAcceleration + 1.f/(float)LONG_TERM_RATE_SAMPLES * _estimatedAcceleration; - - printLog("a: %g %g %g\n", _averageAcceleration.x, _averageAcceleration.y, _averageAcceleration.z); + _estimatedAcceleration -= _averageAcceleration; // Consider updating our angular velocity/acceleration to linear acceleration mapping if (glm::length(_estimatedAcceleration) > EPSILON && @@ -347,6 +347,8 @@ void SerialInterface::readData(float deltaTime) { void SerialInterface::resetAverages() { totalSamples = 0; _gravity = glm::vec3(0, 0, 0); + _averageRotationRates = glm::vec3(0, 0, 0); + _averageAcceleration = glm::vec3(0, 0, 0); _lastRotationRates = glm::vec3(0, 0, 0); _estimatedRotation = glm::vec3(0, 0, 0); _estimatedPosition = glm::vec3(0, 0, 0); diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index 88af60ccbe..8c918e65ff 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -26,6 +26,8 @@ class SerialInterface { public: SerialInterface() : active(false), _gravity(0, 0, 0), + _averageRotationRates(0, 0, 0), + _averageAcceleration(0, 0, 0), _estimatedRotation(0, 0, 0), _estimatedPosition(0, 0, 0), _estimatedVelocity(0, 0, 0), @@ -66,6 +68,8 @@ private: int totalSamples; timeval lastGoodRead; glm::vec3 _gravity; + glm::vec3 _averageRotationRates; + glm::vec3 _averageAcceleration; glm::vec3 _estimatedRotation; glm::vec3 _estimatedPosition; glm::vec3 _estimatedVelocity; @@ -73,9 +77,6 @@ private: glm::vec3 _lastAcceleration; glm::vec3 _lastRotationRates; - glm::vec3 _averageAcceleration; - glm::vec3 _averageRotationRates; - glm::mat3 _angularVelocityToLinearAccel; glm::mat3 _angularAccelToLinearAccel; }; From ee526265a1c3b8fd40895651785968319dc9f1d3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 16:00:14 -0700 Subject: [PATCH 19/46] Fix for nibble packing. --- libraries/shared/src/SharedUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 30aa75b461..697719b36d 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -102,12 +102,12 @@ void setAtBit(unsigned char& byte, int bitIndex) { } int getSemiNibbleAt(unsigned char& byte, int bitIndex) { - return (byte >> (7 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 + return (byte >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11 } void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) { //assert(value <= 3 && value >= 0); - byte += ((value & 3) << (7 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 + byte += ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11 } From 35e18abcbd7e6d1d04547001657d2bf33c85d8c6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 16:27:39 -0700 Subject: [PATCH 20/46] Let's try using estimated velocity to control "lean." --- interface/src/Avatar.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 32b35aebac..9a59e2b804 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -285,18 +285,8 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa _head.setRoll(estimatedRotation.z * AMPLIFY_ROLL); // Update head lean distance based on accelerometer data - glm::vec3 headRotationRates(_head.getPitch(), _head.getYaw(), _head.getRoll()); - - glm::vec3 leaning = (serialInterface->getLastAcceleration() - serialInterface->getGravity()) - * LEAN_SENSITIVITY - * (1.f - fminf(glm::length(headRotationRates), HEAD_RATE_MAX) / HEAD_RATE_MAX); - leaning.y = 0.f; - if (glm::length(leaning) < LEAN_MAX) { - _head.setLeanForward(_head.getLeanForward() * (1.f - LEAN_AVERAGING * deltaTime) + - (LEAN_AVERAGING * deltaTime) * leaning.z * LEAN_SENSITIVITY); - _head.setLeanSideways(_head.getLeanSideways() * (1.f - LEAN_AVERAGING * deltaTime) + - (LEAN_AVERAGING * deltaTime) * leaning.x * LEAN_SENSITIVITY); - } + _bodyPitchDelta = serialInterface->getEstimatedVelocity().z * LEAN_SENSITIVITY; + _bodyRollDelta = -serialInterface->getEstimatedVelocity().x * LEAN_SENSITIVITY; } float Avatar::getAbsoluteHeadYaw() const { From c1c2439d2ca9f91d83e69556e71c21ed8f6d7d51 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 16:44:21 -0700 Subject: [PATCH 21/46] Let's try changing the torso rotation based on the gyros! --- interface/src/Avatar.cpp | 10 +++++----- interface/src/Skeleton.cpp | 6 +++--- interface/src/Skeleton.h | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 9a59e2b804..43056244ff 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -280,13 +280,13 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa const float AMPLIFY_ROLL = 2.f; glm::vec3 estimatedRotation = serialInterface->getEstimatedRotation(); - _head.setPitch(estimatedRotation.x * AMPLIFY_PITCH); - _head.setYaw(estimatedRotation.y * AMPLIFY_YAW); - _head.setRoll(estimatedRotation.z * AMPLIFY_ROLL); + //_head.setPitch(estimatedRotation.x * AMPLIFY_PITCH); + //_head.setYaw(estimatedRotation.y * AMPLIFY_YAW); + //_head.setRoll(estimatedRotation.z * AMPLIFY_ROLL); // Update head lean distance based on accelerometer data - _bodyPitchDelta = serialInterface->getEstimatedVelocity().z * LEAN_SENSITIVITY; - _bodyRollDelta = -serialInterface->getEstimatedVelocity().x * LEAN_SENSITIVITY; + glm::vec3 estimatedPosition = serialInterface->getEstimatedPosition(); + _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(estimatedRotation)); } float Avatar::getAbsoluteHeadYaw() const { diff --git a/interface/src/Skeleton.cpp b/interface/src/Skeleton.cpp index 2fa43c9010..fcec90b542 100644 --- a/interface/src/Skeleton.cpp +++ b/interface/src/Skeleton.cpp @@ -132,15 +132,15 @@ void Skeleton::update(float deltaTime, const glm::quat& orientation, glm::vec3 p for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { if (joint[b].parent == AVATAR_JOINT_NULL) { - joint[b].rotation = orientation; + joint[b].absoluteRotation = orientation * joint[b].rotation; joint[b].position = position; } else { - joint[b].rotation = joint[ joint[b].parent ].rotation; + joint[b].absoluteRotation = joint[ joint[b].parent ].absoluteRotation * joint[b].rotation; joint[b].position = joint[ joint[b].parent ].position; } - glm::vec3 rotatedJointVector = joint[b].rotation * joint[b].defaultPosePosition; + glm::vec3 rotatedJointVector = joint[b].absoluteRotation * joint[b].defaultPosePosition; joint[b].position += rotatedJointVector; } } diff --git a/interface/src/Skeleton.h b/interface/src/Skeleton.h index e98c2e7b12..ec40f18cb3 100644 --- a/interface/src/Skeleton.h +++ b/interface/src/Skeleton.h @@ -68,6 +68,7 @@ public: glm::quat absoluteBindPoseRotation; // the absolute rotation when the avatar is in the "T-pose" float bindRadius; // the radius of the bone capsule that envelops the vertices to bind glm::quat rotation; // the parent-relative rotation (orientation) of the joint as a quaternion + glm::quat absoluteRotation; // the absolute rotation of the joint as a quaternion float length; // the length of vector connecting the joint and its parent }; From 70c5a941d7d9118aab8b86e5450aaeaf6d133d39 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 17:01:06 -0700 Subject: [PATCH 22/46] Now let's try using the estimated position to calculate lean. --- interface/src/Avatar.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 43056244ff..5547fe5e43 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -280,13 +280,18 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa const float AMPLIFY_ROLL = 2.f; glm::vec3 estimatedRotation = serialInterface->getEstimatedRotation(); - //_head.setPitch(estimatedRotation.x * AMPLIFY_PITCH); - //_head.setYaw(estimatedRotation.y * AMPLIFY_YAW); - //_head.setRoll(estimatedRotation.z * AMPLIFY_ROLL); + _head.setPitch(estimatedRotation.x * AMPLIFY_PITCH); + _head.setYaw(estimatedRotation.y * AMPLIFY_YAW); + _head.setRoll(estimatedRotation.z * AMPLIFY_ROLL); - // Update head lean distance based on accelerometer data + // Update torso lean distance based on accelerometer data glm::vec3 estimatedPosition = serialInterface->getEstimatedPosition(); - _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(estimatedRotation)); + const float TORSO_LENGTH = 0.5f; + const float MAX_LEAN_RADIANS = PIf / 4; + _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::vec3( + glm::clamp(atanf(estimatedPosition.z / TORSO_LENGTH), -MAX_LEAN_RADIANS, MAX_LEAN_RADIANS), + 0.0f, + glm::clamp(atanf(-estimatedPosition.x / TORSO_LENGTH), -MAX_LEAN_RADIANS, MAX_LEAN_RADIANS))); } float Avatar::getAbsoluteHeadYaw() const { From 648aacb53d8f6ce0075b44c64b45aa2a5bedbdcf Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 17:26:41 -0700 Subject: [PATCH 23/46] Let's use a fixed vector for the camera position so that the target doesn't move with lean. --- interface/src/Application.cpp | 6 +++--- interface/src/Avatar.cpp | 6 ++++++ interface/src/Avatar.h | 3 +++ interface/src/SerialInterface.cpp | 4 ++-- interface/src/Skeleton.cpp | 7 +++++++ interface/src/Skeleton.h | 1 + 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 51c6e65cb9..489150c8a1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -308,7 +308,7 @@ void Application::paintGL() { if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setTightness (100.0f); - _myCamera.setTargetPosition(_myAvatar.getBallPosition(AVATAR_JOINT_HEAD_BASE)); + _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); _myCamera.setTargetRotation(_myAvatar.getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); } else if (OculusManager::isConnected()) { @@ -320,11 +320,11 @@ void Application::paintGL() { } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { _myCamera.setTightness(0.0f); // In first person, camera follows head exactly without delay - _myCamera.setTargetPosition(_myAvatar.getBallPosition(AVATAR_JOINT_HEAD_BASE)); + _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(_headCameraPitchYawScale)); } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { - _myCamera.setTargetPosition(_myAvatar.getHeadJointPosition()); + _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(_headCameraPitchYawScale)); } diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 5547fe5e43..7d6e0aad37 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -103,9 +103,11 @@ Avatar::Avatar(Agent* owningAgent) : initializeBodyBalls(); _height = _skeleton.getHeight() + _bodyBall[ BODY_BALL_LEFT_HEEL ].radius + _bodyBall[ BODY_BALL_HEAD_BASE ].radius; + _maxArmLength = _skeleton.getArmLength(); _pelvisStandingHeight = _skeleton.getPelvisStandingHeight() + _bodyBall[ BODY_BALL_LEFT_HEEL ].radius; _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight() + _bodyBall[ BODY_BALL_LEFT_HEEL ].radius; + _pelvisToHeadLength = _skeleton.getPelvisToHeadLength(); _avatarTouch.setReachableRadius(PERIPERSONAL_RADIUS); @@ -310,6 +312,10 @@ glm::quat Avatar::getWorldAlignedOrientation () const { return computeRotationFromBodyToWorldUp() * getOrientation(); } +glm::vec3 Avatar::getUprightHeadPosition() const { + return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, _pelvisToHeadLength, 0.0f); +} + void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) { // Update head yaw and pitch based on mouse input const float MOUSE_MOVE_RADIUS = 0.3f; diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 0fc5b31286..82d98a3a02 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -121,6 +121,8 @@ public: glm::quat getOrientation () const; glm::quat getWorldAlignedOrientation() const; + glm::vec3 getUprightHeadPosition() const; + AvatarVoxelSystem* getVoxels() { return &_voxels; } // Set what driving keys are being pressed to control thrust levels @@ -185,6 +187,7 @@ private: int _driveKeys[MAX_DRIVE_KEYS]; float _pelvisStandingHeight; float _pelvisFloatingHeight; + float _pelvisToHeadLength; float _height; Balls* _balls; AvatarTouch _avatarTouch; diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 86755e28b5..76487bb668 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -296,8 +296,8 @@ void SerialInterface::readData(float deltaTime) { _estimatedAcceleration = estimatedRotation * _estimatedAcceleration; // Update estimated position and velocity - float const DECAY_VELOCITY = 0.95f; - float const DECAY_POSITION = 0.95f; + float const DECAY_VELOCITY = 0.975f; + float const DECAY_POSITION = 0.975f; _estimatedVelocity += deltaTime * _estimatedAcceleration; _estimatedPosition += deltaTime * _estimatedVelocity; _estimatedVelocity *= DECAY_VELOCITY; diff --git a/interface/src/Skeleton.cpp b/interface/src/Skeleton.cpp index fcec90b542..1167194534 100644 --- a/interface/src/Skeleton.cpp +++ b/interface/src/Skeleton.cpp @@ -174,6 +174,13 @@ float Skeleton::getPelvisFloatingHeight() { FLOATING_HEIGHT; } +float Skeleton::getPelvisToHeadLength() { + return + joint[ AVATAR_JOINT_TORSO ].length + + joint[ AVATAR_JOINT_CHEST ].length + + joint[ AVATAR_JOINT_NECK_BASE ].length + + joint[ AVATAR_JOINT_HEAD_BASE ].length; +} diff --git a/interface/src/Skeleton.h b/interface/src/Skeleton.h index ec40f18cb3..bb953fe947 100644 --- a/interface/src/Skeleton.h +++ b/interface/src/Skeleton.h @@ -56,6 +56,7 @@ public: float getHeight(); float getPelvisStandingHeight(); float getPelvisFloatingHeight(); + float getPelvisToHeadLength(); //glm::vec3 getJointVectorFromParent(AvatarJointID jointID) {return joint[jointID].position - joint[joint[jointID].parent].position; } struct AvatarJoint From 82f03ffd8eba4d7413da0490d880cf93e412b63d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 17:53:49 -0700 Subject: [PATCH 24/46] Don't render the voxels when we're too close (i.e., in first person mode). --- interface/src/Avatar.cpp | 32 ++++++++++++++++---------------- interface/src/Avatar.h | 1 + 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 7d6e0aad37..1b219e440e 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -1131,32 +1131,29 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { - +float Avatar::getBallRenderAlpha(int ball, bool lookingInMirror) const { const float RENDER_OPAQUE_BEYOND = 1.0f; // Meters beyond which body is shown opaque const float RENDER_TRANSLUCENT_BEYOND = 0.5f; + float distanceToCamera = glm::length(_cameraPosition - _bodyBall[ball].position); + return (lookingInMirror || _owningAgent) ? 1.0f : glm::clamp( + (distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f); +} + +void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { + + // Render the body as balls and cones if (renderAvatarBalls || !_voxels.getVoxelURL().isValid()) { for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { - float distanceToCamera = glm::length(_cameraPosition - _bodyBall[b].position); - - float alpha = lookingInMirror ? 1.0f : glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / - (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f); - - if (lookingInMirror || _owningAgent) { - alpha = 1.0f; - } + float alpha = getBallRenderAlpha(b, lookingInMirror); // Always render other people, and render myself when beyond threshold distance if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special - if (lookingInMirror || _owningAgent || distanceToCamera > RENDER_OPAQUE_BEYOND * 0.5) { + if (alpha > 0.0f) { _head.render(lookingInMirror, _cameraPosition, alpha); } - } else if (_owningAgent || distanceToCamera > RENDER_TRANSLUCENT_BEYOND - || b == BODY_BALL_RIGHT_ELBOW - || b == BODY_BALL_RIGHT_WRIST - || b == BODY_BALL_RIGHT_FINGERTIPS ) { + } else if (alpha > 0.0f) { // Render the body ball sphere if (_owningAgent || b == BODY_BALL_RIGHT_ELBOW || b == BODY_BALL_RIGHT_WRIST @@ -1208,7 +1205,10 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { } } else { // Render the body's voxels - _voxels.render(false); + float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); + if (alpha > 0.0f) { + _voxels.render(false); + } } } diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 82d98a3a02..de76092328 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -204,6 +204,7 @@ private: // private methods... glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // 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(); From 7ef2a2c5d98af51de1f001b396fb57b29c4680d9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 18:06:05 -0700 Subject: [PATCH 25/46] Set/get lean to/from network data. --- interface/src/Avatar.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 1b219e440e..e33624467e 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -289,11 +289,9 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa // Update torso lean distance based on accelerometer data glm::vec3 estimatedPosition = serialInterface->getEstimatedPosition(); const float TORSO_LENGTH = 0.5f; - const float MAX_LEAN_RADIANS = PIf / 4; - _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::vec3( - glm::clamp(atanf(estimatedPosition.z / TORSO_LENGTH), -MAX_LEAN_RADIANS, MAX_LEAN_RADIANS), - 0.0f, - glm::clamp(atanf(-estimatedPosition.x / TORSO_LENGTH), -MAX_LEAN_RADIANS, MAX_LEAN_RADIANS))); + const float MAX_LEAN = 45.0f; + _head.setLeanSideways(glm::clamp(glm::degrees(atanf(-estimatedPosition.x / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); + _head.setLeanForward(glm::clamp(glm::degrees(atanf(estimatedPosition.z / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); } float Avatar::getAbsoluteHeadYaw() const { @@ -355,6 +353,10 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // update balls if (_balls) { _balls->simulate(deltaTime); } + // update torso rotation based on head lean + _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(glm::vec3( + _head.getLeanForward(), 0.0f, _head.getLeanSideways()))); + // update avatar skeleton _skeleton.update(deltaTime, getOrientation(), _position); From c58eb0d5841ebf0f0b7548b29ef3f51cfdc3d717 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 11 Jun 2013 18:11:42 -0700 Subject: [PATCH 26/46] Bump the maximum voxels up to 10000. --- interface/src/AvatarVoxelSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/AvatarVoxelSystem.cpp b/interface/src/AvatarVoxelSystem.cpp index 8a7708587f..dc3b937da9 100644 --- a/interface/src/AvatarVoxelSystem.cpp +++ b/interface/src/AvatarVoxelSystem.cpp @@ -17,7 +17,7 @@ #include "renderer/ProgramObject.h" const float AVATAR_TREE_SCALE = 1.0f; -const int MAX_VOXELS_PER_AVATAR = 2000; +const int MAX_VOXELS_PER_AVATAR = 10000; const int BONE_ELEMENTS_PER_VOXEL = BONE_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXEL; AvatarVoxelSystem::AvatarVoxelSystem(Avatar* avatar) : From ad58d0aa23963ed83fea4eb1d8960b1175b40eff Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 11 Jun 2013 21:19:58 -0700 Subject: [PATCH 27/46] Adding voxel thrust on grabbing/dragging to move avatar --- interface/src/Application.cpp | 59 +++++++++++++++++++++++++++++++++++ interface/src/Application.h | 10 ++++++ interface/src/Avatar.cpp | 7 +++-- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 67dd0f7a15..71769b6be2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -721,6 +721,9 @@ void Application::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { _mouseX = event->x(); _mouseY = event->y(); + _mouseDragStartedX = _mouseX; + _mouseDragStartedY = _mouseY; + _mouseVoxelDragging = _mouseVoxel; _mousePressed = true; maybeEditVoxelUnderCursor(); @@ -1003,6 +1006,12 @@ static void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) { } } +const glm::vec3 Application::getMouseVoxelWorldCoordinates(VoxelDetail _mouseVoxel) { + return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE, + (_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE, + (_mouseVoxel.z + _mouseVoxel.s / 2.f) * TREE_SCALE); +} + void Application::decreaseVoxelSize() { _mouseVoxelScale /= 2; } @@ -1432,6 +1441,26 @@ void Application::update(float deltaTime) { // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); + // If we are dragging on a voxel, add thrust according to the amount the mouse is dragging + const float VOXEL_GRAB_THRUST = 10.0f; + if (_mousePressed && (_mouseVoxel.s != 0)) { + glm::vec2 mouseDrag(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY); + glm::quat orientation = _myAvatar.getOrientation(); + //glm::vec3 front = orientation * IDENTITY_FRONT; + //glm::vec3 right = orientation * IDENTITY_RIGHT; + glm::vec3 up = orientation * IDENTITY_UP; + glm::vec3 towardVoxel = getMouseVoxelWorldCoordinates(_mouseVoxelDragging) + - _myAvatar.getCameraPosition(); + glm::vec3 lateralToVoxel = glm::cross(up, glm::normalize(towardVoxel)) * glm::length(towardVoxel); + _voxelThrust = glm::vec3(0, 0, 0); + _voxelThrust += towardVoxel * VOXEL_GRAB_THRUST * deltaTime * mouseDrag.y; + _voxelThrust += lateralToVoxel * VOXEL_GRAB_THRUST * deltaTime * mouseDrag.x; + + // Add thrust from voxel grabbing to the avatar + _myAvatar.addThrust(_voxelThrust); + + } + _mouseVoxel.s = 0.0f; if (checkedVoxelModeAction() != 0 && (fabs(_myAvatar.getVelocity().x) + @@ -1951,6 +1980,10 @@ void Application::displaySide(Camera& whichCamera) { glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); + // Enable to show line from me to the voxel I am touching + //renderLineToTouchedVoxel(); + renderThrustAtVoxel(_voxelThrust); + // draw a red sphere float sphereRadius = 0.25f; glColor3f(1,0,0); @@ -2167,6 +2200,32 @@ void Application::displayStats() { } } +void Application::renderThrustAtVoxel(glm::vec3 thrust) { + if (_mousePressed) { + glColor3f(1, 0, 0); + glLineWidth(2.0f); + glBegin(GL_LINES); + glm::vec3 voxelTouched = getMouseVoxelWorldCoordinates(_mouseVoxelDragging); + glVertex3f(voxelTouched.x, voxelTouched.y, voxelTouched.z); + glVertex3f(voxelTouched.x + thrust.x, voxelTouched.y + thrust.y, voxelTouched.z + thrust.z); + glEnd(); + } + +} +void Application::renderLineToTouchedVoxel() { + // Draw a teal line to the voxel I am currently dragging on + if (_mousePressed) { + glColor3f(0, 1, 1); + glLineWidth(2.0f); + glBegin(GL_LINES); + glm::vec3 voxelTouched = getMouseVoxelWorldCoordinates(_mouseVoxelDragging); + glVertex3f(voxelTouched.x, voxelTouched.y, voxelTouched.z); + glm::vec3 headPosition = _myAvatar.getHeadJointPosition(); + glVertex3fv(&headPosition.x); + glEnd(); + } +} + ///////////////////////////////////////////////////////////////////////////////////// // renderViewFrustum() // diff --git a/interface/src/Application.h b/interface/src/Application.h index 4f33f8fb1e..7660b8651f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -67,6 +67,8 @@ public: void wheelEvent(QWheelEvent* event); + const glm::vec3 getMouseVoxelWorldCoordinates(VoxelDetail _mouseVoxel); + Avatar* getAvatar() { return &_myAvatar; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } @@ -142,6 +144,9 @@ private: void renderViewFrustum(ViewFrustum& viewFrustum); + void renderLineToTouchedVoxel(); + void renderThrustAtVoxel(glm::vec3 thrust); + void setupPaintingVoxel(); void shiftPaintingColor(); void maybeEditVoxelUnderCursor(); @@ -256,7 +261,12 @@ private: int _mouseX; int _mouseY; + int _mouseDragStartedX; + int _mouseDragStartedY; + VoxelDetail _mouseVoxelDragging; + glm::vec3 _voxelThrust; bool _mousePressed; // true if mouse has been pressed (clear when finished) + VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor float _mouseVoxelScale; // the scale for adding/removing voxels diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index a9c8a368f8..f336da2d8c 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -412,9 +412,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { const float THRUST_MAG = 600.0f; if (!_owningAgent) { - - _thrust = glm::vec3(0.0f, 0.0f, 0.0f); - + // Add Thrusts from keyboard if (_driveKeys[FWD ]) {_thrust += THRUST_MAG * deltaTime * front;} if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG * deltaTime * front;} @@ -468,6 +466,9 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // add thrust to velocity _velocity += _thrust * deltaTime; + // Zero thrust out now that we've added it to velocity in this frame + _thrust = glm::vec3(0, 0, 0); + // calculate speed _speed = glm::length(_velocity); From 59c8d9d26aa9d5591f552d418128f7e2cddf5edc Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 10:25:28 -0700 Subject: [PATCH 28/46] Function cleanup, fixed misspelling, tweaked transparency distances to accomodate lean. --- interface/src/Avatar.cpp | 21 ++++++++------------- interface/src/Avatar.h | 3 +-- interface/src/Head.cpp | 11 ++++++----- interface/src/Head.h | 6 +++--- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index e33624467e..168fa80016 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -74,7 +74,6 @@ Avatar::Avatar(Agent* owningAgent) : _bodyRollDelta(0.0f), _movedHandOffset(0.0f, 0.0f, 0.0f), _mode(AVATAR_MODE_STANDING), - _cameraPosition(0.0f, 0.0f, 0.0f), _handHoldingPosition(0.0f, 0.0f, 0.0f), _velocity(0.0f, 0.0f, 0.0f), _thrust(0.0f, 0.0f, 0.0f), @@ -584,7 +583,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // set head lookat position if (!_owningAgent) { if (_interactingOther) { - _head.setLookAtPosition(_interactingOther->caclulateAverageEyePosition()); + _head.setLookAtPosition(_interactingOther->calculateAverageEyePosition()); } else { _head.setLookAtPosition(glm::vec3(0.0f, 0.0f, 0.0f)); // 0,0,0 represents NOT looking at anything } @@ -914,9 +913,7 @@ void Avatar::setGravity(glm::vec3 gravity) { } void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { - - _cameraPosition = Application::getInstance()->getCamera()->getPosition(); - + if (!_owningAgent && usingBigSphereCollisionTest) { // show TEST big sphere glColor4f(0.5f, 0.6f, 0.8f, 0.7); @@ -935,7 +932,7 @@ void Avatar::render(bool lookingInMirror, bool renderAvatarBalls) { // if this is my avatar, then render my interactions with the other avatar if (!_owningAgent) { - _avatarTouch.render(getCameraPosition()); + _avatarTouch.render(Application::getInstance()->getCamera()->getPosition()); } // Render the balls @@ -1134,17 +1131,15 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { } float Avatar::getBallRenderAlpha(int ball, bool lookingInMirror) const { - const float RENDER_OPAQUE_BEYOND = 1.0f; // Meters beyond which body is shown opaque - const float RENDER_TRANSLUCENT_BEYOND = 0.5f; - float distanceToCamera = glm::length(_cameraPosition - _bodyBall[ball].position); + const float RENDER_OPAQUE_OUTSIDE = 1.25f; // render opaque if greater than this distance + const float DO_NOT_RENDER_INSIDE = 0.75f; // do not render if less than this distance + float distanceToCamera = glm::length(Application::getInstance()->getCamera()->getPosition() - _bodyBall[ball].position); return (lookingInMirror || _owningAgent) ? 1.0f : glm::clamp( - (distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f); + (distanceToCamera - DO_NOT_RENDER_INSIDE) / (RENDER_OPAQUE_OUTSIDE - DO_NOT_RENDER_INSIDE), 0.f, 1.f); } void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { - - // Render the body as balls and cones if (renderAvatarBalls || !_voxels.getVoxelURL().isValid()) { for (int b = 0; b < NUM_AVATAR_BODY_BALLS; b++) { @@ -1153,7 +1148,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { // Always render other people, and render myself when beyond threshold distance if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special if (alpha > 0.0f) { - _head.render(lookingInMirror, _cameraPosition, alpha); + _head.render(lookingInMirror, alpha); } } else if (alpha > 0.0f) { // Render the body ball sphere diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index de76092328..8391c81e96 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -177,7 +177,6 @@ private: glm::vec3 _movedHandOffset; AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; AvatarMode _mode; - glm::vec3 _cameraPosition; glm::vec3 _handHoldingPosition; glm::vec3 _velocity; glm::vec3 _thrust; @@ -202,7 +201,7 @@ private: AvatarVoxelSystem _voxels; // private methods... - glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat) + 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); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index d58c29f84d..c7fac99d8b 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -5,6 +5,7 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. #include +#include "Application.h" #include "Avatar.h" #include "Head.h" #include "Util.h" @@ -161,7 +162,7 @@ void Head::determineIfLookingAtSomething() { if ( fabs(_lookAtPosition.x + _lookAtPosition.y + _lookAtPosition.z) == 0.0 ) { // a lookatPosition of 0,0,0 signifies NOT looking _lookingAtSomething = false; } else { - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - caclulateAverageEyePosition()); + glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - calculateAverageEyePosition()); float dot = glm::dot(targetLookatAxis, getFrontDirection()); if (dot < MINIMUM_EYE_ROTATION_DOT) { // too far off from center for the eyes to rotate _lookingAtSomething = false; @@ -202,7 +203,7 @@ void Head::calculateGeometry() { } -void Head::render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha) { +void Head::render(bool lookingInMirror, float alpha) { _renderAlpha = alpha; _lookingInMirror = lookingInMirror; @@ -212,7 +213,7 @@ void Head::render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha) { glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); - renderMohawk(cameraPosition); + renderMohawk(); renderHeadSphere(); renderEyeBalls(); renderEars(); @@ -256,7 +257,7 @@ void Head::createMohawk() { } } -void Head::renderMohawk(glm::vec3 cameraPosition) { +void Head::renderMohawk() { if (!_mohawkTriangleFan) { createMohawk(); @@ -267,7 +268,7 @@ void Head::renderMohawk(glm::vec3 cameraPosition) { glm::vec3 baseAxis = _hairTuft[t].midPosition - _hairTuft[t].basePosition; glm::vec3 midAxis = _hairTuft[t].endPosition - _hairTuft[t].midPosition; - glm::vec3 viewVector = _hairTuft[t].basePosition - cameraPosition; + glm::vec3 viewVector = _hairTuft[t].basePosition - Application::getInstance()->getCamera()->getPosition(); glm::vec3 basePerpendicular = glm::normalize(glm::cross(baseAxis, viewVector)); glm::vec3 midPerpendicular = glm::normalize(glm::cross(midAxis, viewVector)); diff --git a/interface/src/Head.h b/interface/src/Head.h index 4150cbbc50..d331b98efc 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -33,8 +33,8 @@ public: void reset(); void simulate(float deltaTime, bool isMine); - void render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha); - void renderMohawk(glm::vec3 cameraPosition); + void render(bool lookingInMirror, float alpha); + void renderMohawk(); void setScale (float scale ) { _scale = scale; } void setPosition (glm::vec3 position ) { _position = position; } @@ -55,7 +55,7 @@ public: const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected) float getAverageLoudness() {return _averageLoudness;}; - glm::vec3 caclulateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; } + glm::vec3 calculateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; } float yawRate; float noise; From 3546bcc10167fc87fa39ed6e5a11e0aa65b723f5 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 12 Jun 2013 11:36:28 -0700 Subject: [PATCH 29/46] Avatar can set velocity, velocity set to zero on reset --- interface/src/Application.cpp | 2 ++ interface/src/Avatar.h | 1 + 2 files changed, 3 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4c37be98c3..2de3b8295f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2502,6 +2502,8 @@ void Application::resetSensors() { QCursor::setPos(_headMouseX, _headMouseY); _myAvatar.reset(); _myTransmitter.resetLevels(); + _myAvatar.setVelocity(glm::vec3(0,0,0)); + _myAvatar.setThrust(glm::vec3(0,0,0)); } static void setShortcutsEnabled(QWidget* widget, bool enabled) { diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index de76092328..4018764ffc 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -96,6 +96,7 @@ public: 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 setGravity (glm::vec3 gravity); void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction); void setOrientation (const glm::quat& orientation); From 26ca1a9a1d4225b8295927cb6985d48936554eda Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 12 Jun 2013 12:58:45 -0700 Subject: [PATCH 30/46] Remove shortcut on ground plane 'G', was conflicting with turning gravity on/off --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2de3b8295f..445702aed3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1245,7 +1245,6 @@ void Application::initMenu() { _renderAtmosphereOn->setShortcut(Qt::SHIFT | Qt::Key_A); (_renderGroundPlaneOn = renderMenu->addAction("Ground Plane"))->setCheckable(true); _renderGroundPlaneOn->setChecked(true); - _renderGroundPlaneOn->setShortcut(Qt::SHIFT | Qt::Key_G); (_renderAvatarsOn = renderMenu->addAction("Avatars"))->setCheckable(true); _renderAvatarsOn->setChecked(true); (_renderAvatarBalls = renderMenu->addAction("Avatar as Balls"))->setCheckable(true); @@ -1446,11 +1445,12 @@ void Application::update(float deltaTime) { if (_mousePressed && (_mouseVoxel.s != 0)) { glm::vec2 mouseDrag(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY); glm::quat orientation = _myAvatar.getOrientation(); - //glm::vec3 front = orientation * IDENTITY_FRONT; - //glm::vec3 right = orientation * IDENTITY_RIGHT; + glm::vec3 front = orientation * IDENTITY_FRONT; + glm::vec3 right = orientation * IDENTITY_RIGHT; glm::vec3 up = orientation * IDENTITY_UP; glm::vec3 towardVoxel = getMouseVoxelWorldCoordinates(_mouseVoxelDragging) - _myAvatar.getCameraPosition(); + towardVoxel = front * glm::length(towardVoxel); glm::vec3 lateralToVoxel = glm::cross(up, glm::normalize(towardVoxel)) * glm::length(towardVoxel); _voxelThrust = glm::vec3(0, 0, 0); _voxelThrust += towardVoxel * VOXEL_GRAB_THRUST * deltaTime * mouseDrag.y; From 52c616b688dbef39886dec3745365b3969fedb63 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 13:06:28 -0700 Subject: [PATCH 31/46] Added configurable lean scale, fixed loadSetting. --- interface/src/Application.cpp | 5 +++++ interface/src/Avatar.cpp | 7 ++++++- interface/src/Avatar.h | 4 +++- interface/src/Util.cpp | 4 ++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 489150c8a1..e3c7ca0bdf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -880,6 +880,10 @@ void Application::editPreferences() { headCameraPitchYawScale->setValue(_headCameraPitchYawScale); form->addRow("Head Camera Pitch/Yaw Scale:", headCameraPitchYawScale); + QDoubleSpinBox* leanScale = new QDoubleSpinBox(); + leanScale->setValue(_myAvatar.getLeanScale()); + form->addRow("Lean Scale:", leanScale); + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject())); @@ -893,6 +897,7 @@ void Application::editPreferences() { sendAvatarVoxelURLMessage(url); _headCameraPitchYawScale = headCameraPitchYawScale->value(); + _myAvatar.setLeanScale(leanScale->value()); } void Application::pair() { diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 168fa80016..771ce8e7e5 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -79,6 +79,7 @@ Avatar::Avatar(Agent* owningAgent) : _thrust(0.0f, 0.0f, 0.0f), _speed(0.0f), _maxArmLength(0.0f), + _leanScale(0.5f), _pelvisStandingHeight(0.0f), _pelvisFloatingHeight(0.0f), _distanceToNearestAvatar(std::numeric_limits::max()), @@ -286,7 +287,7 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa _head.setRoll(estimatedRotation.z * AMPLIFY_ROLL); // Update torso lean distance based on accelerometer data - glm::vec3 estimatedPosition = serialInterface->getEstimatedPosition(); + glm::vec3 estimatedPosition = serialInterface->getEstimatedPosition() * _leanScale; const float TORSO_LENGTH = 0.5f; const float MAX_LEAN = 45.0f; _head.setLeanSideways(glm::clamp(glm::degrees(atanf(-estimatedPosition.x / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); @@ -1223,6 +1224,8 @@ void Avatar::loadData(QSettings* settings) { _voxels.setVoxelURL(settings->value("voxelURL").toUrl()); + _leanScale = loadSetting(settings, "leanScale", 0.5f); + settings->endGroup(); } @@ -1244,6 +1247,8 @@ void Avatar::saveData(QSettings* set) { set->setValue("voxelURL", _voxels.getVoxelURL()); + set->setValue("leanScale", _leanScale); + set->endGroup(); } diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 8391c81e96..34483b6d93 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -96,6 +96,7 @@ public: void setMovedHandOffset (glm::vec3 movedHandOffset ) { _movedHandOffset = movedHandOffset;} void setThrust (glm::vec3 newThrust ) { _thrust = newThrust; }; void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors);} + 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); @@ -115,6 +116,7 @@ public: float getSpeed () const { return _speed;} float getHeight () const { return _height;} AvatarMode getMode () const { return _mode;} + float getLeanScale () const { return _leanScale;} float getAbsoluteHeadYaw () const; float getAbsoluteHeadPitch () const; Head& getHead () {return _head; } @@ -182,7 +184,7 @@ private: glm::vec3 _thrust; float _speed; float _maxArmLength; - glm::quat _righting; + float _leanScale; int _driveKeys[MAX_DRIVE_KEYS]; float _pelvisStandingHeight; float _pelvisFloatingHeight; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 74fe5abd1c..cc566dd6fb 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -498,9 +498,9 @@ void runTimingTests() { } float loadSetting(QSettings* settings, const char* name, float defaultValue) { - float value = settings->value(name, 0.0f).toFloat(); + float value = settings->value(name, defaultValue).toFloat(); if (isnan(value)) { value = defaultValue; } return value; -} \ No newline at end of file +} From 178996bb8bf2789c6d9069932c81ced3fb9e7c9e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 13:30:41 -0700 Subject: [PATCH 32/46] Make sure first person mode and mirror mode are mutually exclusive. --- interface/src/Application.cpp | 13 ++++++++----- interface/src/Application.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e3c7ca0bdf..f76d413db9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -144,7 +144,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _viewFrustumOffsetDistance(25.0), _viewFrustumOffsetUp(0.0), _audioScope(256, 200, true), - _manualFirstPerson(false), _mouseX(0), _mouseY(0), _mousePressed(false), @@ -908,6 +907,8 @@ void Application::setHead(bool head) { if (head) { _myCamera.setMode(CAMERA_MODE_MIRROR); _myCamera.setModeShiftRate(100.0f); + _manualFirstPerson->setChecked(false); + } else { _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); _myCamera.setModeShiftRate(1.0f); @@ -925,7 +926,9 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setRenderFirstPerson(bool firstPerson) { - _manualFirstPerson = firstPerson; + if (firstPerson) { + _lookingInMirror->setChecked(false); + } } void Application::setFrustumOffset(bool frustumOffset) { @@ -1250,8 +1253,8 @@ void Application::initMenu() { _renderFrameTimerOn->setChecked(false); (_renderLookatOn = renderMenu->addAction("Lookat Vectors"))->setCheckable(true); _renderLookatOn->setChecked(false); - - renderMenu->addAction("First Person", this, SLOT(setRenderFirstPerson(bool)), Qt::Key_P)->setCheckable(true); + (_manualFirstPerson = renderMenu->addAction( + "First Person", this, SLOT(setRenderFirstPerson(bool)), Qt::Key_P))->setCheckable(true); QMenu* toolsMenu = menuBar->addMenu("Tools"); (_renderStatsOn = toolsMenu->addAction("Stats"))->setCheckable(true); @@ -1572,7 +1575,7 @@ void Application::update(float deltaTime) { } } else { if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) { - if (_manualFirstPerson) { + if (_manualFirstPerson->isChecked()) { if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) { _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); _myCamera.setModeShiftRate(1.0f); diff --git a/interface/src/Application.h b/interface/src/Application.h index 4f33f8fb1e..062954a4b7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -186,6 +186,7 @@ private: QAction* _renderStatsOn; // Whether to show onscreen text overlay with stats QAction* _renderFrameTimerOn; // Whether to show onscreen text overlay with stats QAction* _renderLookatOn; // Whether to show lookat vectors from avatar eyes if looking at something + QAction* _manualFirstPerson; // Whether to force first-person mode QAction* _logOn; // Whether to show on-screen log QActionGroup* _voxelModeActions; // The group of voxel edit mode actions QAction* _addVoxelMode; // Whether add voxel mode is enabled @@ -249,7 +250,6 @@ private: Environment _environment; int _headMouseX, _headMouseY; - bool _manualFirstPerson; float _headCameraPitchYawScale; HandControl _handControl; From b28df1720701cf8643c91b56a020694671eb7580 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 13:51:16 -0700 Subject: [PATCH 33/46] Slight tweak: we need to call trigger in order to get the full toggle behavior. --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f76d413db9..3121ed36e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -926,8 +926,8 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setRenderFirstPerson(bool firstPerson) { - if (firstPerson) { - _lookingInMirror->setChecked(false); + if (firstPerson && _lookingInMirror->isChecked()) { + _lookingInMirror->trigger(); } } From f197b4cd6243eff01569768d394abdcf6c361af6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 14:20:28 -0700 Subject: [PATCH 34/46] Some debugging to use on the other machine. --- interface/src/Application.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3121ed36e0..4079e920b1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -826,6 +826,9 @@ void Application::terminate() { static void sendAvatarVoxelURLMessage(const QUrl& url) { uint16_t ownerID = AgentList::getInstance()->getOwnerID(); + + qDebug() << "me" << ownerID << url; + if (ownerID == UNKNOWN_AGENT_ID) { return; // we don't yet know who we are } @@ -847,6 +850,8 @@ static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataB packetData += sizeof(agentID); dataBytes -= sizeof(agentID); + qDebug() << "them" << agentID << QUrl::fromEncoded(QByteArray((char*)packetData, dataBytes)); + // make sure the agent exists Agent* agent = AgentList::getInstance()->agentWithID(agentID); if (!agent || !agent->getLinkedData()) { From e4ed9162b981d206adc148499cd78b681a47ba24 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 15:52:29 -0700 Subject: [PATCH 35/46] This should help, as well as fix another annoyance: bind to an ephemeral port, rather than a fixed one. --- interface/src/Application.cpp | 6 +----- libraries/shared/src/AgentList.cpp | 3 +-- libraries/shared/src/AgentList.h | 2 +- libraries/shared/src/UDPSocket.cpp | 9 ++++++++- libraries/shared/src/UDPSocket.h | 4 +++- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4079e920b1..d864fb86dd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -169,7 +169,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _window->setWindowTitle("Interface"); printLog("Interface Startup:\n"); - unsigned int listenPort = AGENT_SOCKET_LISTEN_PORT; + unsigned int listenPort = 0; // bind to an ephemeral port by default const char** constArgv = const_cast(argv); const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); if (portStr) { @@ -827,8 +827,6 @@ void Application::terminate() { static void sendAvatarVoxelURLMessage(const QUrl& url) { uint16_t ownerID = AgentList::getInstance()->getOwnerID(); - qDebug() << "me" << ownerID << url; - if (ownerID == UNKNOWN_AGENT_ID) { return; // we don't yet know who we are } @@ -850,8 +848,6 @@ static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataB packetData += sizeof(agentID); dataBytes -= sizeof(agentID); - qDebug() << "them" << agentID << QUrl::fromEncoded(QByteArray((char*)packetData, dataBytes)); - // make sure the agent exists Agent* agent = AgentList::getInstance()->agentWithID(agentID); if (!agent || !agent->getLinkedData()) { diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 9c309bb23f..56641bd2a0 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -62,7 +62,6 @@ AgentList::AgentList(char newOwnerType, unsigned int newSocketListenPort) : _agentSocket(newSocketListenPort), _ownerType(newOwnerType), _agentTypesOfInterest(NULL), - _socketListenPort(newSocketListenPort), _ownerID(UNKNOWN_AGENT_ID), _lastAgentID(0) { pthread_mutex_init(&mutex, 0); @@ -224,7 +223,7 @@ void AgentList::sendDomainServerCheckIn() { packetPosition += packSocket(checkInPacket + sizeof(PACKET_HEADER) + sizeof(AGENT_TYPE), getLocalAddress(), - htons(_socketListenPort)); + htons(_agentSocket.getListeningPort())); // add the number of bytes for agent types of interest *(packetPosition++) = numBytesAgentsOfInterest; diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index 3007dbc8e3..1b51913928 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -58,7 +58,7 @@ public: UDPSocket* getAgentSocket() { return &_agentSocket; } - unsigned int getSocketListenPort() const { return _socketListenPort; }; + unsigned int getSocketListenPort() const { return _agentSocket.getListeningPort(); }; void(*linkedDataCreateCallback)(Agent *); diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index b7c2275635..8cd58a20bc 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -117,7 +117,7 @@ unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket) { } } -UDPSocket::UDPSocket(int listeningPort) : blocking(true) { +UDPSocket::UDPSocket(int listeningPort) : blocking(true), listeningPort(listeningPort) { init(); // create the socket handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -140,6 +140,13 @@ UDPSocket::UDPSocket(int listeningPort) : blocking(true) { return; } + // if we requested an ephemeral port, get the actual port + if (listeningPort == 0) { + socklen_t addressLength = sizeof(sockaddr_in); + getsockname(handle, (sockaddr*) &bind_address, &addressLength); + listeningPort = ntohs(bind_address.sin_port); + } + // set timeout on socket recieve to 0.5 seconds struct timeval tv; tv.tv_sec = 0; diff --git a/libraries/shared/src/UDPSocket.h b/libraries/shared/src/UDPSocket.h index b56a1cc0cf..8539ff93c2 100644 --- a/libraries/shared/src/UDPSocket.h +++ b/libraries/shared/src/UDPSocket.h @@ -23,14 +23,16 @@ public: UDPSocket(int listening_port); ~UDPSocket(); bool init(); + int getListeningPort() const { return listeningPort; } void setBlocking(bool blocking); - bool isBlocking() { return blocking; } + bool isBlocking() const { return blocking; } int send(sockaddr* destAddress, const void* data, size_t byteLength) const; int send(char* destAddress, int destPort, const void* data, size_t byteLength) const; bool receive(void* receivedData, ssize_t* receivedBytes) const; bool receive(sockaddr* recvAddress, void* receivedData, ssize_t* receivedBytes) const; private: int handle; + int listeningPort; bool blocking; }; From 6dae9db01de45a04e6487f20076a30c27232c88d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 15:54:13 -0700 Subject: [PATCH 36/46] Initialize members in the right order. --- libraries/shared/src/UDPSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/UDPSocket.cpp b/libraries/shared/src/UDPSocket.cpp index 8cd58a20bc..69cf0cfebe 100644 --- a/libraries/shared/src/UDPSocket.cpp +++ b/libraries/shared/src/UDPSocket.cpp @@ -117,7 +117,7 @@ unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket) { } } -UDPSocket::UDPSocket(int listeningPort) : blocking(true), listeningPort(listeningPort) { +UDPSocket::UDPSocket(int listeningPort) : listeningPort(listeningPort), blocking(true) { init(); // create the socket handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); From 19180ad9006667f7b0ea1b8ee2ea905f4b029d82 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 15:56:28 -0700 Subject: [PATCH 37/46] Put the debugging back in. --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d864fb86dd..b02afe2b0e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -827,6 +827,8 @@ void Application::terminate() { static void sendAvatarVoxelURLMessage(const QUrl& url) { uint16_t ownerID = AgentList::getInstance()->getOwnerID(); + qDebug() << "me" << ownerID << url; + if (ownerID == UNKNOWN_AGENT_ID) { return; // we don't yet know who we are } @@ -848,6 +850,8 @@ static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataB packetData += sizeof(agentID); dataBytes -= sizeof(agentID); + qDebug() << "them" << agentID << QUrl::fromEncoded(QByteArray((char*)packetData, dataBytes)); + // make sure the agent exists Agent* agent = AgentList::getInstance()->agentWithID(agentID); if (!agent || !agent->getLinkedData()) { From ccd61ee5a2d4aaac9623382baaf9e0568885947f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 16:13:44 -0700 Subject: [PATCH 38/46] Found the problem we were having: the domain server was reporting back all kinds of things as our ID. --- domain-server/src/main.cpp | 35 ++++++++++++++++++----------------- interface/src/Application.cpp | 4 ---- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index b1e2117db3..b8f66b0641 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -135,25 +135,26 @@ int main(int argc, const char * argv[]) if (numInterestTypes > 0) { // if the agent has sent no types of interest, assume they want nothing but their own ID back for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - if (!agent->matches((sockaddr*) &agentPublicAddress, (sockaddr*) &agentLocalAddress, agentType) - && memchr(agentTypesOfInterest, agent->getType(), numInterestTypes)) { - // this is not the agent themselves - // and this is an agent of a type in the passed agent types of interest - // or the agent did not pass us any specific types they are interested in + if (!agent->matches((sockaddr*) &agentPublicAddress, (sockaddr*) &agentLocalAddress, agentType)) { + if (memchr(agentTypesOfInterest, agent->getType(), numInterestTypes)) { + // this is not the agent themselves + // and this is an agent of a type in the passed agent types of interest + // or the agent did not pass us any specific types they are interested in - if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) { - // this is an agent of which there can be multiple, just add them to the packet - // don't send avatar agents to other avatars, that will come from avatar mixer - if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) { - currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); - } + if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) { + // this is an agent of which there can be multiple, just add them to the packet + // don't send avatar agents to other avatars, that will come from avatar mixer + if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) { + currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); + } - } else { - // solo agent, we need to only send newest - if (newestSoloAgents[agent->getType()] == NULL || - newestSoloAgents[agent->getType()]->getWakeMicrostamp() < agent->getWakeMicrostamp()) { - // we have to set the newer solo agent to add it to the broadcast later - newestSoloAgents[agent->getType()] = &(*agent); + } else { + // solo agent, we need to only send newest + if (newestSoloAgents[agent->getType()] == NULL || + newestSoloAgents[agent->getType()]->getWakeMicrostamp() < agent->getWakeMicrostamp()) { + // we have to set the newer solo agent to add it to the broadcast later + newestSoloAgents[agent->getType()] = &(*agent); + } } } } else { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b02afe2b0e..d864fb86dd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -827,8 +827,6 @@ void Application::terminate() { static void sendAvatarVoxelURLMessage(const QUrl& url) { uint16_t ownerID = AgentList::getInstance()->getOwnerID(); - qDebug() << "me" << ownerID << url; - if (ownerID == UNKNOWN_AGENT_ID) { return; // we don't yet know who we are } @@ -850,8 +848,6 @@ static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataB packetData += sizeof(agentID); dataBytes -= sizeof(agentID); - qDebug() << "them" << agentID << QUrl::fromEncoded(QByteArray((char*)packetData, dataBytes)); - // make sure the agent exists Agent* agent = AgentList::getInstance()->agentWithID(agentID); if (!agent || !agent->getLinkedData()) { From 7570329867220b5c07d218359f11c8ced8a9907a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Jun 2013 16:28:37 -0700 Subject: [PATCH 39/46] This appears still to be broken, but you know what? We already have the agent pointer; why not just get the ID from that? --- domain-server/src/main.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index b8f66b0641..d84dd64a1b 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -94,8 +94,6 @@ int main(int argc, const char * argv[]) agentList->startSilentAgentRemovalThread(); - uint16_t packetAgentID = 0; - while (true) { if (agentList->getAgentSocket()->receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes) && (packetData[0] == PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_HEADER_DOMAIN_LIST_REQUEST)) { @@ -163,9 +161,6 @@ int main(int argc, const char * argv[]) // this is the agent, just update last receive to now agent->setLastHeardMicrostamp(timeNow); - // grab the ID for this agent so we can send it back with the packet - packetAgentID = agent->getAgentID(); - if (packetData[0] == PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY && memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES))) { agent->setWakeMicrostamp(timeNow); @@ -182,7 +177,7 @@ int main(int argc, const char * argv[]) } // add the agent ID to the end of the pointer - currentBufferPos += packAgentId(currentBufferPos, packetAgentID); + currentBufferPos += packAgentId(currentBufferPos, newAgent->getAgentID()); // send the constructed list back to this agent agentList->getAgentSocket()->send((sockaddr*) &agentPublicAddress, From a5a0df09cb85a4278fca92eda24a037b35a0017d Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 12 Jun 2013 16:36:55 -0700 Subject: [PATCH 40/46] removed grab voxel rendering --- animation-server/src/main.cpp | 1 - interface/src/Application.cpp | 2 +- interface/src/Application.h | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp index c02e8e8383..37dd301d1c 100644 --- a/animation-server/src/main.cpp +++ b/animation-server/src/main.cpp @@ -244,7 +244,6 @@ static void renderMovingBug() { } - float intensity = 0.5f; float intensityIncrement = 0.1f; const float MAX_INTENSITY = 1.0f; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8f78c2f770..925d629933 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1991,7 +1991,7 @@ void Application::displaySide(Camera& whichCamera) { // Enable to show line from me to the voxel I am touching //renderLineToTouchedVoxel(); - renderThrustAtVoxel(_voxelThrust); + //renderThrustAtVoxel(_voxelThrust); // draw a red sphere float sphereRadius = 0.25f; diff --git a/interface/src/Application.h b/interface/src/Application.h index ac45415d43..655268024b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -95,6 +95,9 @@ private slots: void setRenderFirstPerson(bool firstPerson); + void renderThrustAtVoxel(glm::vec3 thrust); + void renderLineToTouchedVoxel(); + void setFrustumOffset(bool frustumOffset); void cycleFrustumRenderMode(); @@ -143,10 +146,7 @@ private: void displayStats(); void renderViewFrustum(ViewFrustum& viewFrustum); - - void renderLineToTouchedVoxel(); - void renderThrustAtVoxel(glm::vec3 thrust); - + void setupPaintingVoxel(); void shiftPaintingColor(); void maybeEditVoxelUnderCursor(); From c0ba2aeebea21e5997b16d6342ce2e2763994c56 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 12 Jun 2013 23:45:59 -0700 Subject: [PATCH 41/46] Added jumping, tuned friction model, tuned thrust --- interface/src/Application.cpp | 6 ++- interface/src/Avatar.cpp | 92 ++++++++++++++++++++--------------- interface/src/Avatar.h | 2 + 3 files changed, 60 insertions(+), 40 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 925d629933..230e523d34 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -510,6 +510,9 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_E: + if (!_myAvatar.getDriveKeys(UP)) { + _myAvatar.jump(); + } _myAvatar.setDriveKeys(UP, 1); break; @@ -1450,12 +1453,11 @@ void Application::update(float deltaTime) { _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); // If we are dragging on a voxel, add thrust according to the amount the mouse is dragging - const float VOXEL_GRAB_THRUST = 10.0f; + const float VOXEL_GRAB_THRUST = 5.0f; if (_mousePressed && (_mouseVoxel.s != 0)) { glm::vec2 mouseDrag(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY); glm::quat orientation = _myAvatar.getOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; - glm::vec3 right = orientation * IDENTITY_RIGHT; glm::vec3 up = orientation * IDENTITY_UP; glm::vec3 towardVoxel = getMouseVoxelWorldCoordinates(_mouseVoxelDragging) - _myAvatar.getCameraPosition(); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 9c45d5a1c8..adbe3358da 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -77,6 +77,7 @@ Avatar::Avatar(Agent* owningAgent) : _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), @@ -412,28 +413,38 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { glm::vec3 up = orientation * IDENTITY_UP; // driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely) - const float THRUST_MAG = 600.0f; + const float THRUST_MAG_UP = 800.0f; + const float THRUST_MAG_DOWN = 200.f; + const float THRUST_MAG_FWD = 300.f; + const float THRUST_MAG_BACK = 150.f; + const float THRUST_MAG_LATERAL = 200.f; + const float THRUST_JUMP = 100.f; if (!_owningAgent) { // Add Thrusts from keyboard - if (_driveKeys[FWD ]) {_thrust += THRUST_MAG * deltaTime * front;} - if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG * deltaTime * front;} - if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG * deltaTime * right;} - if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG * deltaTime * right;} - if (_driveKeys[UP ]) {_thrust += THRUST_MAG * deltaTime * up;} - if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG * deltaTime * up;} + if (_driveKeys[FWD ]) {_thrust += THRUST_MAG_FWD * deltaTime * front;} + if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG_BACK * deltaTime * front;} + if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG_LATERAL * deltaTime * right;} + if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG_LATERAL * deltaTime * right;} + if (_driveKeys[UP ]) {_thrust += THRUST_MAG_UP * deltaTime * up;} + if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG_DOWN * deltaTime * up;} if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;} if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;} + if (_shouldJump) { + _thrust += THRUST_JUMP * up; + _shouldJump = false; + } // 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 = 25.f; - const float TRANSMITTER_FWD_FORCE_SCALE = 100.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; @@ -447,7 +458,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _bodyYawDelta += rotation.y * TRANSMITTER_YAW_SCALE * deltaTime; } if (transmitter->getTouchState()->state == 'D') { - _thrust += THRUST_MAG * + _thrust += TRANSMITTER_UP_FORCE_SCALE * (float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF * TRANSMITTER_LIFT_SCALE * deltaTime * @@ -469,9 +480,31 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // add thrust to velocity _velocity += _thrust * deltaTime; - // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0, 0, 0); + // Decay velocity. If velocity is really low, increase decay to simulate static friction + const float VELOCITY_DECAY_UNDER_THRUST = 0.0; + const float VELOCITY_FAST_DECAY = 0.8; + const float VELOCITY_SLOW_DECAY = 8.0; + const float VELOCITY_HALT_DECAY = 100.0; + const float VELOCITY_FAST_THRESHOLD = 2.0f; + const float VELOCITY_HALT_THRESHOLD = 0.15f; + float decayConstant, decay; + if (glm::length(_thrust) > 0.f) { + decayConstant = VELOCITY_DECAY_UNDER_THRUST; + } else if (glm::length(_velocity) > VELOCITY_FAST_THRESHOLD) { + decayConstant = VELOCITY_FAST_DECAY; + } else if (glm::length(_velocity) > VELOCITY_HALT_THRESHOLD) { + decayConstant = VELOCITY_SLOW_DECAY; + } else { + decayConstant = VELOCITY_HALT_DECAY; + } + + decay = glm::clamp(1.0f - decayConstant * deltaTime, 0.0f, 1.0f); + _velocity *= decay; + + // update position by velocity + _position += _velocity * deltaTime; + // calculate speed _speed = glm::length(_velocity); @@ -494,27 +527,11 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { //the following will be used to make the avatar upright no matter what gravity is setOrientation(computeRotationFromBodyToWorldUp(tiltDecay) * orientation); - // update position by velocity - _position += _velocity * deltaTime; - - // decay velocity - const float VELOCITY_DECAY = 0.9; - float decay = 1.0 - VELOCITY_DECAY * deltaTime; - if ( decay < 0.0 ) { - _velocity = glm::vec3( 0.0f, 0.0f, 0.0f ); - } else { - _velocity *= decay; - } - // If another avatar is near, dampen velocity as a function of closeness if (_distanceToNearestAvatar < PERIPERSONAL_RADIUS) { float closeness = 1.0f - (_distanceToNearestAvatar / PERIPERSONAL_RADIUS); - float drag = 1.0f - closeness * AVATAR_BRAKING_STRENGTH * deltaTime; - if ( drag > 0.0f ) { - _velocity *= drag; - } else { - _velocity = glm::vec3( 0.0f, 0.0f, 0.0f ); - } + float avatarDrag = glm::clamp(1.0f - closeness * AVATAR_BRAKING_STRENGTH * deltaTime, 0.0f, 1.0f); + _velocity *= avatarDrag; } // Compute instantaneous acceleration @@ -577,6 +594,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // set head lookat position if (!_owningAgent) { + //if (_camera) if (_interactingOther) { _head.setLookAtPosition(_interactingOther->calculateAverageEyePosition()); } else { @@ -596,6 +614,10 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { } else { _mode = AVATAR_MODE_INTERACTING; } + + // Zero thrust out now that we've added it to velocity in this frame + _thrust = glm::vec3(0, 0, 0); + } void Avatar::checkForMouseRayTouching() { @@ -798,20 +820,14 @@ void Avatar::updateCollisionWithVoxels() { void Avatar::applyCollisionWithScene(const glm::vec3& penetration) { _position -= penetration; - static float STATIC_FRICTION_VELOCITY = 0.15f; - static float STATIC_FRICTION_DAMPING = 0.0f; static float KINETIC_FRICTION_DAMPING = 0.95f; - + static float ELASTIC_COLLISION_FACTOR = 1.4f; // 1.0 = inelastic, > 2.0 = pinball bumper! // cancel out the velocity component in the direction of penetration float penetrationLength = glm::length(penetration); if (penetrationLength > EPSILON) { glm::vec3 direction = penetration / penetrationLength; - _velocity -= glm::dot(_velocity, direction) * direction; + _velocity -= glm::dot(_velocity, direction) * direction * ELASTIC_COLLISION_FACTOR; _velocity *= KINETIC_FRICTION_DAMPING; - // If velocity is quite low, apply static friction that takes away energy - if (glm::length(_velocity) < STATIC_FRICTION_VELOCITY) { - _velocity *= STATIC_FRICTION_DAMPING; - } } } diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index ef42ee4c73..5be04b06c3 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -131,6 +131,7 @@ public: // 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; }; @@ -183,6 +184,7 @@ private: glm::vec3 _handHoldingPosition; glm::vec3 _velocity; glm::vec3 _thrust; + bool _shouldJump; float _speed; float _maxArmLength; float _leanScale; From db729a04aa953668d993dd9e93e02402e397e760 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 13 Jun 2013 11:11:59 -0700 Subject: [PATCH 42/46] Converted double timestamps to long long (64 bit integers), fixed bug with updating agent timestamps. --- animation-server/src/main.cpp | 6 +- audio-mixer/src/main.cpp | 2 +- domain-server/src/main.cpp | 56 +++++++++--------- eve/src/main.cpp | 4 +- injector/src/main.cpp | 2 +- interface/src/Application.cpp | 5 +- interface/src/VoxelSystem.cpp | 14 ++--- libraries/audio/src/AudioInjector.cpp | 2 +- libraries/shared/src/Agent.cpp | 2 + libraries/shared/src/Agent.h | 12 ++-- libraries/shared/src/AgentList.cpp | 6 +- libraries/shared/src/PerfStat.cpp | 2 +- libraries/shared/src/PerfStat.h | 2 +- libraries/shared/src/SharedUtil.cpp | 8 +-- libraries/shared/src/SharedUtil.h | 4 +- libraries/shared/src/SimpleMovingAverage.h | 2 +- libraries/voxels/src/VoxelNode.h | 4 +- voxel-server/src/main.cpp | 66 +++++++++++----------- 18 files changed, 99 insertions(+), 100 deletions(-) diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp index c02e8e8383..bceb276a8a 100644 --- a/animation-server/src/main.cpp +++ b/animation-server/src/main.cpp @@ -644,14 +644,14 @@ void* animateVoxels(void* args) { sendDanceFloor(); } - double end = usecTimestampNow(); - double elapsedSeconds = (end - ::start) / 1000000.0; + long long end = usecTimestampNow(); + long long elapsedSeconds = (end - ::start) / 1000000; if (::shouldShowPacketsPerSecond) { printf("packetsSent=%ld, bytesSent=%ld pps=%f bps=%f\n",packetsSent,bytesSent, (float)(packetsSent/elapsedSeconds),(float)(bytesSent/elapsedSeconds)); } // dynamically sleep until we need to fire off the next set of voxels - double usecToSleep = ANIMATE_VOXELS_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime)); + long long usecToSleep = ANIMATE_VOXELS_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime)); if (usecToSleep > 0) { usleep(usecToSleep); diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index c9ea474354..fbcba0979f 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -318,7 +318,7 @@ int main(int argc, const char* argv[]) { } } - double usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); + long long usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); if (usecToSleep > 0) { usleep(usecToSleep); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index d84dd64a1b..67c1123205 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -133,37 +133,26 @@ int main(int argc, const char * argv[]) if (numInterestTypes > 0) { // if the agent has sent no types of interest, assume they want nothing but their own ID back for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - if (!agent->matches((sockaddr*) &agentPublicAddress, (sockaddr*) &agentLocalAddress, agentType)) { - if (memchr(agentTypesOfInterest, agent->getType(), numInterestTypes)) { - // this is not the agent themselves - // and this is an agent of a type in the passed agent types of interest - // or the agent did not pass us any specific types they are interested in - - if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) { - // this is an agent of which there can be multiple, just add them to the packet - // don't send avatar agents to other avatars, that will come from avatar mixer - if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) { - currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); - } - - } else { - // solo agent, we need to only send newest - if (newestSoloAgents[agent->getType()] == NULL || - newestSoloAgents[agent->getType()]->getWakeMicrostamp() < agent->getWakeMicrostamp()) { - // we have to set the newer solo agent to add it to the broadcast later - newestSoloAgents[agent->getType()] = &(*agent); - } + if (!agent->matches((sockaddr*) &agentPublicAddress, (sockaddr*) &agentLocalAddress, agentType) && + memchr(agentTypesOfInterest, agent->getType(), numInterestTypes)) { + // this is not the agent themselves + // and this is an agent of a type in the passed agent types of interest + // or the agent did not pass us any specific types they are interested in + + if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) { + // this is an agent of which there can be multiple, just add them to the packet + // don't send avatar agents to other avatars, that will come from avatar mixer + if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) { + currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, &(*agent)); } - } - } else { - double timeNow = usecTimestampNow(); - // this is the agent, just update last receive to now - agent->setLastHeardMicrostamp(timeNow); - - if (packetData[0] == PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY - && memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES))) { - agent->setWakeMicrostamp(timeNow); + } else { + // solo agent, we need to only send newest + if (newestSoloAgents[agent->getType()] == NULL || + newestSoloAgents[agent->getType()]->getWakeMicrostamp() < agent->getWakeMicrostamp()) { + // we have to set the newer solo agent to add it to the broadcast later + newestSoloAgents[agent->getType()] = &(*agent); + } } } } @@ -175,6 +164,15 @@ int main(int argc, const char * argv[]) currentBufferPos = addAgentToBroadcastPacket(currentBufferPos, soloAgent->second); } } + + // update last receive to now + long long timeNow = usecTimestampNow(); + newAgent->setLastHeardMicrostamp(timeNow); + + if (packetData[0] == PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY + && memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES))) { + newAgent->setWakeMicrostamp(timeNow); + } // add the agent ID to the end of the pointer currentBufferPos += packAgentId(currentBufferPos, newAgent->getAgentID()); diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 387c72633b..9310e2b316 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -128,7 +128,7 @@ int main(int argc, const char* argv[]) { broadcastPacket[0] = PACKET_HEADER_HEAD_DATA; timeval thisSend; - double numMicrosecondsSleep = 0; + long long numMicrosecondsSleep = 0; int handStateTimer = 0; @@ -212,4 +212,4 @@ int main(int argc, const char* argv[]) { // stop the agent list's threads agentList->stopPingUnknownAgentsThread(); agentList->stopSilentAgentRemovalThread(); -} \ No newline at end of file +} diff --git a/injector/src/main.cpp b/injector/src/main.cpp index f2e87990d1..a0c07179f7 100644 --- a/injector/src/main.cpp +++ b/injector/src/main.cpp @@ -187,7 +187,7 @@ int main(int argc, char* argv[]) { unsigned char broadcastPacket = PACKET_HEADER_INJECT_AUDIO; timeval thisSend; - double numMicrosecondsSleep = 0; + long long numMicrosecondsSleep = 0; timeval lastDomainServerCheckIn = {}; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d864fb86dd..e69e40f527 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2078,9 +2078,8 @@ void Application::displayOverlay() { // Show on-screen msec timer if (_renderFrameTimerOn->isChecked()) { char frameTimer[10]; - double mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5); - mSecsNow = mSecsNow - floor(mSecsNow / 1000.0) * 1000.0; - sprintf(frameTimer, "%3.0f\n", mSecsNow); + long long mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5); + sprintf(frameTimer, "%d\n", (int)(mSecsNow % 1000)); drawtext(_glWidget->width() - 100, _glWidget->height() - 20, 0.30, 0, 1.0, 0, frameTimer, 0, 0, 0); drawtext(_glWidget->width() - 102, _glWidget->height() - 22, 0.30, 0, 1.0, 0, frameTimer, 1, 1, 1); } diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 9cde8906be..716fe708a3 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -165,15 +165,15 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { void VoxelSystem::setupNewVoxelsForDrawing() { PerformanceWarning warn(_renderWarningsOn, "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated - double start = usecTimestampNow(); - double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000.0; + long long start = usecTimestampNow(); + long long sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging if (!iAmDebugging && sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) { return; // bail early, it hasn't been long enough since the last time we ran } - double sinceLastViewCulling = (start - _lastViewCulling) / 1000.0; + long long sinceLastViewCulling = (start - _lastViewCulling) / 1000; // If the view frustum is no longer changing, but has changed, since last time, then remove nodes that are out of view if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) && !isViewChanging() && hasViewChanged()) { @@ -189,8 +189,8 @@ void VoxelSystem::setupNewVoxelsForDrawing() { // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary. cleanupRemovedVoxels(); - double endViewCulling = usecTimestampNow(); - _lastViewCullingElapsed = (endViewCulling - start) / 1000.0; + long long endViewCulling = usecTimestampNow(); + _lastViewCullingElapsed = (endViewCulling - start) / 1000; } bool didWriteFullVBO = _writeRenderFullVBO; @@ -226,8 +226,8 @@ void VoxelSystem::setupNewVoxelsForDrawing() { pthread_mutex_unlock(&_bufferWriteLock); - double end = usecTimestampNow(); - double elapsedmsec = (end - start) / 1000.0; + long long end = usecTimestampNow(); + long long elapsedmsec = (end - start) / 1000; _setupNewVoxelsForDrawingLastFinished = end; _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; } diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index f9f1bcc094..24e0a369d5 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -115,7 +115,7 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket)); - double usecToSleep = usecTimestamp(&startTime) + (++nextFrame * INJECT_INTERVAL_USECS) - usecTimestampNow(); + long long usecToSleep = usecTimestamp(&startTime) + (++nextFrame * INJECT_INTERVAL_USECS) - usecTimestampNow(); if (usecToSleep > 0) { usleep(usecToSleep); } diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index 4556f670d6..88d0f901f2 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -6,6 +6,8 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // +#include "stdio.h" + #include #include "Agent.h" #include "AgentTypes.h" diff --git a/libraries/shared/src/Agent.h b/libraries/shared/src/Agent.h index 5201fd9048..18d42fdf3d 100644 --- a/libraries/shared/src/Agent.h +++ b/libraries/shared/src/Agent.h @@ -37,11 +37,11 @@ public: uint16_t getAgentID() const { return _agentID; } void setAgentID(uint16_t agentID) { _agentID = agentID;} - double getWakeMicrostamp() const { return _wakeMicrostamp; } - void setWakeMicrostamp(double wakeMicrostamp) { _wakeMicrostamp = wakeMicrostamp; } + long long getWakeMicrostamp() const { return _wakeMicrostamp; } + void setWakeMicrostamp(long long wakeMicrostamp) { _wakeMicrostamp = wakeMicrostamp; } - double getLastHeardMicrostamp() const { return _lastHeardMicrostamp; } - void setLastHeardMicrostamp(double lastHeardMicrostamp) { _lastHeardMicrostamp = lastHeardMicrostamp; } + long long getLastHeardMicrostamp() const { return _lastHeardMicrostamp; } + void setLastHeardMicrostamp(long long lastHeardMicrostamp) { _lastHeardMicrostamp = lastHeardMicrostamp; } sockaddr* getPublicSocket() const { return _publicSocket; } void setPublicSocket(sockaddr* publicSocket) { _publicSocket = publicSocket; } @@ -71,8 +71,8 @@ private: char _type; uint16_t _agentID; - double _wakeMicrostamp; - double _lastHeardMicrostamp; + long long _wakeMicrostamp; + long long _lastHeardMicrostamp; sockaddr* _publicSocket; sockaddr* _localSocket; sockaddr* _activeSocket; diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index 56641bd2a0..e1b4bd9d63 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -392,7 +392,7 @@ void *pingUnknownAgents(void *args) { } } - double usecToSleep = PING_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSend)); + long long usecToSleep = PING_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSend)); if (usecToSleep > 0) { usleep(usecToSleep); @@ -413,7 +413,7 @@ void AgentList::stopPingUnknownAgentsThread() { void *removeSilentAgents(void *args) { AgentList* agentList = (AgentList*) args; - double checkTimeUSecs, sleepTime; + long long checkTimeUSecs, sleepTime; while (!silentAgentThreadStopFlag) { checkTimeUSecs = usecTimestampNow(); @@ -422,7 +422,7 @@ void *removeSilentAgents(void *args) { if ((checkTimeUSecs - agent->getLastHeardMicrostamp()) > AGENT_SILENCE_THRESHOLD_USECS && agent->getType() != AGENT_TYPE_VOXEL_SERVER) { - + printLog("Killed "); Agent::printLog(*agent); diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 3c30c62993..2de5aa2816 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -104,7 +104,7 @@ int PerfStat::DumpStats(char** array) { // Destructor handles recording all of our stats PerformanceWarning::~PerformanceWarning() { - double end = usecTimestampNow(); + long long end = usecTimestampNow(); double elapsedmsec = (end - _start) / 1000.0; if ((_alwaysDisplay || _renderWarningsOn) && elapsedmsec > 1) { if (elapsedmsec > 1000) { diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 8898899960..f57d49aa46 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -84,7 +84,7 @@ typedef std::map >::iterator class PerformanceWarning { private: - double _start; + long long _start; const char* _message; bool _renderWarningsOn; bool _alwaysDisplay; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 697719b36d..0ec2c6e302 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -22,14 +22,14 @@ #include #endif -double usecTimestamp(timeval *time) { - return (time->tv_sec * 1000000.0 + time->tv_usec); +long long usecTimestamp(timeval *time) { + return (time->tv_sec * 1000000 + time->tv_usec); } -double usecTimestampNow() { +long long usecTimestampNow() { timeval now; gettimeofday(&now, NULL); - return (now.tv_sec * 1000000.0 + now.tv_usec); + return (now.tv_sec * 1000000 + now.tv_usec); } float randFloat () { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 28c4adb296..e227137470 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -36,8 +36,8 @@ static const float DECIMETER = 0.1f; static const float CENTIMETER = 0.01f; static const float MILLIIMETER = 0.001f; -double usecTimestamp(timeval *time); -double usecTimestampNow(); +long long usecTimestamp(timeval *time); +long long usecTimestampNow(); float randFloat(); int randIntInRange (int min, int max); diff --git a/libraries/shared/src/SimpleMovingAverage.h b/libraries/shared/src/SimpleMovingAverage.h index e24b639133..b1d0709342 100644 --- a/libraries/shared/src/SimpleMovingAverage.h +++ b/libraries/shared/src/SimpleMovingAverage.h @@ -25,7 +25,7 @@ public: float getAverageSampleValuePerSecond(); private: int _numSamples; - double _lastEventTimestamp; + long long _lastEventTimestamp; float _average; float _eventDeltaAverage; diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 952ad15bb7..8f71ef64f1 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -29,7 +29,7 @@ private: #endif glBufferIndex _glBufferIndex; bool _isDirty; - double _lastChanged; + long long _lastChanged; bool _shouldRender; bool _isStagedForDeletion; AABox _box; @@ -80,7 +80,7 @@ public: void printDebugDetails(const char* label) const; bool isDirty() const { return _isDirty; }; void clearDirtyBit() { _isDirty = false; }; - bool hasChangedSince(double time) const { return (_lastChanged > time); }; + bool hasChangedSince(long long time) const { return (_lastChanged > time); }; void markWithChangedTime() { _lastChanged = usecTimestampNow(); }; void handleSubtreeChanged(VoxelTree* myTree); diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 1f6a386eda..aae631bb16 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -32,7 +32,7 @@ const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo"; -const double VOXEL_PERSIST_INTERVAL = 1000.0 * 30; // every 30 seconds +const long long VOXEL_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds const int VOXEL_LISTEN_PORT = 40106; @@ -118,7 +118,7 @@ void resInVoxelDistributor(AgentList* agentList, bool searchReset = false; int searchLoops = 0; int searchLevelWas = agentData->getMaxSearchLevel(); - double start = usecTimestampNow(); + long long start = usecTimestampNow(); while (!searchReset && agentData->nodeBag.isEmpty()) { searchLoops++; @@ -137,19 +137,19 @@ void resInVoxelDistributor(AgentList* agentList, } } } - double end = usecTimestampNow(); - double elapsedmsec = (end - start)/1000.0; + long long end = usecTimestampNow(); + int elapsedmsec = (end - start)/1000; if (elapsedmsec > 100) { if (elapsedmsec > 1000) { - double elapsedsec = (end - start)/1000000.0; - printf("WARNING! searchForColoredNodes() took %lf seconds to identify %d nodes at level %d in %d loops\n", + int elapsedsec = (end - start)/1000000; + printf("WARNING! searchForColoredNodes() took %d seconds to identify %d nodes at level %d in %d loops\n", elapsedsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); } else { - printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", + printf("WARNING! searchForColoredNodes() took %d milliseconds to identify %d nodes at level %d in %d loops\n", elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); } } else if (::debugVoxelSending) { - printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", + printf("searchForColoredNodes() took %d milliseconds to identify %d nodes at level %d in %d loops\n", elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); } @@ -161,7 +161,7 @@ void resInVoxelDistributor(AgentList* agentList, int packetsSentThisInterval = 0; int truePacketsSent = 0; int trueBytesSent = 0; - double start = usecTimestampNow(); + long long start = usecTimestampNow(); bool shouldSendEnvironments = shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) { @@ -206,19 +206,19 @@ void resInVoxelDistributor(AgentList* agentList, trueBytesSent += envPacketLength; truePacketsSent++; } - double end = usecTimestampNow(); - double elapsedmsec = (end - start)/1000.0; + long long end = usecTimestampNow(); + int elapsedmsec = (end - start)/1000; if (elapsedmsec > 100) { if (elapsedmsec > 1000) { - double elapsedsec = (end - start)/1000000.0; - printf("WARNING! packetLoop() took %lf seconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + int elapsedsec = (end - start)/1000000; + printf("WARNING! packetLoop() took %d seconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", elapsedsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); } else { - printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + printf("WARNING! packetLoop() took %d milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); } } else if (::debugVoxelSending) { - printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + printf("packetLoop() took %d milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); } @@ -245,7 +245,7 @@ void deepestLevelVoxelDistributor(AgentList* agentList, pthread_mutex_lock(&::treeLock); int maxLevelReached = 0; - double start = usecTimestampNow(); + long long start = usecTimestampNow(); // FOR NOW... agent tells us if it wants to receive only view frustum deltas bool wantDelta = agentData->getWantDelta(); @@ -281,19 +281,19 @@ void deepestLevelVoxelDistributor(AgentList* agentList, } } - double end = usecTimestampNow(); - double elapsedmsec = (end - start)/1000.0; + long long end = usecTimestampNow(); + int elapsedmsec = (end - start)/1000; if (elapsedmsec > 100) { if (elapsedmsec > 1000) { - double elapsedsec = (end - start)/1000000.0; - printf("WARNING! searchForColoredNodes() took %lf seconds to identify %d nodes at level %d\n", + int elapsedsec = (end - start)/1000000; + printf("WARNING! searchForColoredNodes() took %d seconds to identify %d nodes at level %d\n", elapsedsec, agentData->nodeBag.count(), maxLevelReached); } else { - printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d\n", + printf("WARNING! searchForColoredNodes() took %d milliseconds to identify %d nodes at level %d\n", elapsedmsec, agentData->nodeBag.count(), maxLevelReached); } } else if (::debugVoxelSending) { - printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d\n", + printf("searchForColoredNodes() took %d milliseconds to identify %d nodes at level %d\n", elapsedmsec, agentData->nodeBag.count(), maxLevelReached); } @@ -304,7 +304,7 @@ void deepestLevelVoxelDistributor(AgentList* agentList, int packetsSentThisInterval = 0; int truePacketsSent = 0; int trueBytesSent = 0; - double start = usecTimestampNow(); + long long start = usecTimestampNow(); bool shouldSendEnvironments = shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) { @@ -351,19 +351,19 @@ void deepestLevelVoxelDistributor(AgentList* agentList, truePacketsSent++; } - double end = usecTimestampNow(); - double elapsedmsec = (end - start)/1000.0; + long long end = usecTimestampNow(); + int elapsedmsec = (end - start)/1000; if (elapsedmsec > 100) { if (elapsedmsec > 1000) { - double elapsedsec = (end - start)/1000000.0; - printf("WARNING! packetLoop() took %lf seconds to generate %d bytes in %d packets %d nodes still to send\n", + int elapsedsec = (end - start)/1000000; + printf("WARNING! packetLoop() took %d seconds to generate %d bytes in %d packets %d nodes still to send\n", elapsedsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count()); } else { - printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets, %d nodes still to send\n", + printf("WARNING! packetLoop() took %d milliseconds to generate %d bytes in %d packets, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count()); } } else if (::debugVoxelSending) { - printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets, %d nodes still to send\n", + printf("packetLoop() took %d milliseconds to generate %d bytes in %d packets, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count()); } @@ -380,10 +380,10 @@ void deepestLevelVoxelDistributor(AgentList* agentList, pthread_mutex_unlock(&::treeLock); } -double lastPersistVoxels = 0; +long long lastPersistVoxels = 0; void persistVoxelsWhenDirty() { - double now = usecTimestampNow(); - double sinceLastTime = (now - ::lastPersistVoxels) / 1000.0; + long long now = usecTimestampNow(); + long long sinceLastTime = (now - ::lastPersistVoxels) / 1000; // check the dirty bit and persist here... if (::wantVoxelPersist && ::serverTree.isDirty() && sinceLastTime > VOXEL_PERSIST_INTERVAL) { @@ -428,7 +428,7 @@ void *distributeVoxelsToListeners(void *args) { } // dynamically sleep until we need to fire off the next set of voxels - double usecToSleep = VOXEL_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime)); + long long usecToSleep = VOXEL_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime)); if (usecToSleep > 0) { usleep(usecToSleep); From 61b1a2f995d1e9cf5908479d87763098a53272a3 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 11:31:41 -0700 Subject: [PATCH 43/46] First person to third person transition driven by velocity, changes to make moving and flying physics more fun. --- interface/src/Application.cpp | 33 ++--- interface/src/Avatar.cpp | 233 ++++++++++++++++++++-------------- interface/src/Avatar.h | 11 +- 3 files changed, 159 insertions(+), 118 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 230e523d34..c5d913c65e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -62,8 +62,6 @@ using namespace std; -const bool TESTING_AVATAR_TOUCH = false; - // Starfield information static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; static char STAR_CACHE_FILE[] = "cachedStars.txt"; @@ -1600,30 +1598,27 @@ void Application::update(float deltaTime) { _myAvatar.simulate(deltaTime, NULL); } - if (TESTING_AVATAR_TOUCH) { - if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { - _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); - _myCamera.setModeShiftRate(1.0f); - } - } else { if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) { if (_manualFirstPerson->isChecked()) { if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) { _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); _myCamera.setModeShiftRate(1.0f); } - } else { - if (_myAvatar.getIsNearInteractingOther()) { - if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) { - _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); - _myCamera.setModeShiftRate(1.0f); - } - } else { - if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { - _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); - _myCamera.setModeShiftRate(1.0f); - } + } else { + const float THIRD_PERSON_SHIFT_VELOCITY = 2.0f; + const float TIME_BEFORE_SHIFT_INTO_FIRST_PERSON = 0.75f; + const float TIME_BEFORE_SHIFT_INTO_THIRD_PERSON = 0.1f; + + if ((_myAvatar.getElapsedTimeStopped() > TIME_BEFORE_SHIFT_INTO_FIRST_PERSON) + && (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON)) { + _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); + _myCamera.setModeShiftRate(1.0f); } + if ((_myAvatar.getSpeed() > THIRD_PERSON_SHIFT_VELOCITY) + && (_myAvatar.getElapsedTimeMoving() > TIME_BEFORE_SHIFT_INTO_THIRD_PERSON) + && (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON)) { + _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); + _myCamera.setModeShiftRate(1000.0f); } } } diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index adbe3358da..c55f082be5 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -90,6 +90,9 @@ Avatar::Avatar(Agent* owningAgent) : _mouseRayDirection(0.0f, 0.0f, 0.0f), _interactingOther(NULL), _isMouseTurningRight(false), + _elapsedTimeMoving(0.0f), + _elapsedTimeStopped(0.0f), + _elapsedTimeSinceCollision(0.0f), _voxels(this) { // give the pointer to our head to inherited _headData variable from AvatarData @@ -336,14 +339,109 @@ void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int scree } } +void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { + // + // Gather thrust information from keyboard and sensors to apply to avatar motion + // + glm::quat orientation = getOrientation(); + 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 = 200.f; + const float THRUST_MAG_FWD = 300.f; + const float THRUST_MAG_BACK = 150.f; + const float THRUST_MAG_LATERAL = 200.f; + const float THRUST_JUMP = 65.f; + + // Add Thrusts from keyboard + if (_driveKeys[FWD ]) {_thrust += THRUST_MAG_FWD * deltaTime * front;} + if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG_BACK * deltaTime * front;} + if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG_LATERAL * deltaTime * right;} + if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG_LATERAL * deltaTime * right;} + if (_driveKeys[UP ]) {_thrust += THRUST_MAG_UP * deltaTime * up;} + if (_driveKeys[DOWN ]) {_thrust -= 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 += THRUST_JUMP * up; + _shouldJump = false; + } + + // 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; + } + } +} + void Avatar::simulate(float deltaTime, Transmitter* transmitter) { - //figure out if the mouse cursor is over any body spheres... - checkForMouseRayTouching(); + glm::quat orientation = getOrientation(); + glm::vec3 front = orientation * IDENTITY_FRONT; + glm::vec3 right = orientation * IDENTITY_RIGHT; + + // Update movement timers + if (!_owningAgent) { + _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; + } + } + + // Collect thrust forces from keyboard and devices + if (!_owningAgent) { + updateThrust(deltaTime, transmitter); + } // copy velocity so we can use it later for acceleration glm::vec3 oldVelocity = getVelocity(); + if (!_owningAgent) { + // update position by velocity + _position += _velocity * deltaTime; + + // calculate speed + _speed = glm::length(_velocity); + } + + //figure out if the mouse cursor is over any body spheres... + if (!_owningAgent) { + checkForMouseRayTouching(); + } + // update balls if (_balls) { _balls->simulate(deltaTime); } @@ -385,12 +483,13 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { //update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime); - _avatarTouch.simulate(deltaTime); // apply gravity and collision with the ground/floor if (!_owningAgent && USING_AVATAR_GRAVITY) { _velocity += _gravity * (GRAVITY_EARTH * deltaTime); + } + if (!_owningAgent) { updateCollisionWithEnvironment(); } @@ -407,65 +506,11 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { updateCollisionWithVoxels(); } - glm::quat orientation = getOrientation(); - glm::vec3 front = orientation * IDENTITY_FRONT; - glm::vec3 right = orientation * IDENTITY_RIGHT; - glm::vec3 up = orientation * IDENTITY_UP; - - // driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely) - const float THRUST_MAG_UP = 800.0f; - const float THRUST_MAG_DOWN = 200.f; - const float THRUST_MAG_FWD = 300.f; - const float THRUST_MAG_BACK = 150.f; - const float THRUST_MAG_LATERAL = 200.f; - const float THRUST_JUMP = 100.f; - if (!_owningAgent) { - - // Add Thrusts from keyboard - if (_driveKeys[FWD ]) {_thrust += THRUST_MAG_FWD * deltaTime * front;} - if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG_BACK * deltaTime * front;} - if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG_LATERAL * deltaTime * right;} - if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG_LATERAL * deltaTime * right;} - if (_driveKeys[UP ]) {_thrust += THRUST_MAG_UP * deltaTime * up;} - if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG_DOWN * deltaTime * up;} - if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;} - if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;} - - if (_shouldJump) { - _thrust += THRUST_JUMP * up; - _shouldJump = false; - } - // 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; - } - } - + + // 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)); @@ -477,37 +522,22 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _bodyYawDelta *= bodySpinMomentum; _bodyRollDelta *= bodySpinMomentum; - // add thrust to velocity - _velocity += _thrust * deltaTime; - // Decay velocity. If velocity is really low, increase decay to simulate static friction - const float VELOCITY_DECAY_UNDER_THRUST = 0.0; - const float VELOCITY_FAST_DECAY = 0.8; - const float VELOCITY_SLOW_DECAY = 8.0; - const float VELOCITY_HALT_DECAY = 100.0; + const float VELOCITY_DECAY_UNDER_THRUST = 0.2; + const float VELOCITY_FAST_DECAY = 0.6; + const float VELOCITY_SLOW_DECAY = 3.0; const float VELOCITY_FAST_THRESHOLD = 2.0f; - const float VELOCITY_HALT_THRESHOLD = 0.15f; float decayConstant, decay; if (glm::length(_thrust) > 0.f) { decayConstant = VELOCITY_DECAY_UNDER_THRUST; } else if (glm::length(_velocity) > VELOCITY_FAST_THRESHOLD) { decayConstant = VELOCITY_FAST_DECAY; - } else if (glm::length(_velocity) > VELOCITY_HALT_THRESHOLD) { - decayConstant = VELOCITY_SLOW_DECAY; } else { - decayConstant = VELOCITY_HALT_DECAY; - } - + decayConstant = VELOCITY_SLOW_DECAY; + } decay = glm::clamp(1.0f - decayConstant * deltaTime, 0.0f, 1.0f); _velocity *= decay; - - - // update position by velocity - _position += _velocity * deltaTime; - - // calculate speed - _speed = glm::length(_velocity); - + //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; @@ -527,13 +557,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { //the following will be used to make the avatar upright no matter what gravity is setOrientation(computeRotationFromBodyToWorldUp(tiltDecay) * orientation); - // If another avatar is near, dampen velocity as a function of closeness - if (_distanceToNearestAvatar < PERIPERSONAL_RADIUS) { - float closeness = 1.0f - (_distanceToNearestAvatar / PERIPERSONAL_RADIUS); - float avatarDrag = glm::clamp(1.0f - closeness * AVATAR_BRAKING_STRENGTH * deltaTime, 0.0f, 1.0f); - _velocity *= avatarDrag; - } - // Compute instantaneous acceleration float forwardAcceleration = glm::length(glm::dot(getBodyFrontDirection(), getVelocity() - oldVelocity)) / deltaTime; const float ACCELERATION_PITCH_DECAY = 0.4f; @@ -798,36 +821,53 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d } void Avatar::updateCollisionWithEnvironment() { + glm::vec3 up = getBodyUpDirection(); float radius = _height * 0.125f; + const float ENVIRONMENT_SURFACE_ELASTICITY = 1.0f; + const float ENVIRONMENT_SURFACE_DAMPING = 0.01; glm::vec3 penetration; if (Application::getInstance()->getEnvironment()->findCapsulePenetration( _position - up * (_pelvisFloatingHeight - radius), _position + up * (_height - _pelvisFloatingHeight - radius), radius, penetration)) { - applyCollisionWithScene(penetration); + applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING); } } + void Avatar::updateCollisionWithVoxels() { float radius = _height * 0.125f; + const float VOXEL_ELASTICITY = 1.4f; + const float VOXEL_DAMPING = 0.0; 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)) { - applyCollisionWithScene(penetration); + applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); } } -void Avatar::applyCollisionWithScene(const glm::vec3& penetration) { +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 KINETIC_FRICTION_DAMPING = 0.95f; - static float ELASTIC_COLLISION_FACTOR = 1.4f; // 1.0 = inelastic, > 2.0 = pinball bumper! + 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 * ELASTIC_COLLISION_FACTOR; - _velocity *= KINETIC_FRICTION_DAMPING; + _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; + } } } @@ -849,7 +889,6 @@ void Avatar::updateAvatarCollisions(float deltaTime) { // 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(); diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 5be04b06c3..db4f4dd7a6 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -85,6 +85,7 @@ public: void init(); void reset(); void simulate(float deltaTime, Transmitter* transmitter); + void updateThrust(float deltaTime, Transmitter * transmitter); void updateHeadFromGyros(float frametime, SerialInterface * serialInterface); void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight); void addBodyYaw(float y) {_bodyYaw += y;}; @@ -118,6 +119,9 @@ public: 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;} float getAbsoluteHeadYaw () const; float getAbsoluteHeadPitch () const; Head& getHead () {return _head; } @@ -195,13 +199,16 @@ private: float _height; Balls* _balls; AvatarTouch _avatarTouch; - float _distanceToNearestAvatar; // How close is the nearest avatar? + 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; AvatarVoxelSystem _voxels; @@ -221,7 +228,7 @@ private: void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); void updateCollisionWithEnvironment(); void updateCollisionWithVoxels(); - void applyCollisionWithScene(const glm::vec3& penetration); + void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping); void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime ); void checkForMouseRayTouching(); void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); From d517487d1bc23a51ed16e17c4faeebc09047fd80 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 11:35:36 -0700 Subject: [PATCH 44/46] OK I wanted us to jump just a bit higher. --- interface/src/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index c55f082be5..c89a078f23 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -353,7 +353,7 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { const float THRUST_MAG_FWD = 300.f; const float THRUST_MAG_BACK = 150.f; const float THRUST_MAG_LATERAL = 200.f; - const float THRUST_JUMP = 65.f; + const float THRUST_JUMP = 120.f; // Add Thrusts from keyboard if (_driveKeys[FWD ]) {_thrust += THRUST_MAG_FWD * deltaTime * front;} From b85f91a7d46a5dd0803ae2ed5b52622aa1b98e15 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 12:05:06 -0700 Subject: [PATCH 45/46] fixes per code review --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 4 ++-- interface/src/Avatar.cpp | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c5d913c65e..40f7de7e85 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1016,7 +1016,7 @@ static void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) { } } -const glm::vec3 Application::getMouseVoxelWorldCoordinates(VoxelDetail _mouseVoxel) { +const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) { return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE, (_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE, (_mouseVoxel.z + _mouseVoxel.s / 2.f) * TREE_SCALE); @@ -2206,7 +2206,7 @@ void Application::displayStats() { } } -void Application::renderThrustAtVoxel(glm::vec3 thrust) { +void Application::renderThrustAtVoxel(const glm::vec3& thrust) { if (_mousePressed) { glColor3f(1, 0, 0); glLineWidth(2.0f); diff --git a/interface/src/Application.h b/interface/src/Application.h index 655268024b..1d50b5065f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -67,7 +67,7 @@ public: void wheelEvent(QWheelEvent* event); - const glm::vec3 getMouseVoxelWorldCoordinates(VoxelDetail _mouseVoxel); + const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel); Avatar* getAvatar() { return &_myAvatar; } Camera* getCamera() { return &_myCamera; } @@ -95,7 +95,7 @@ private slots: void setRenderFirstPerson(bool firstPerson); - void renderThrustAtVoxel(glm::vec3 thrust); + void renderThrustAtVoxel(const glm::vec3& thrust); void renderLineToTouchedVoxel(); void setFrustumOffset(bool frustumOffset); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index c89a078f23..a2ff33ca52 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -617,7 +617,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // set head lookat position if (!_owningAgent) { - //if (_camera) if (_interactingOther) { _head.setLookAtPosition(_interactingOther->calculateAverageEyePosition()); } else { From b57a78c414f76d6c877e362b66645a2696bedceb Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 13 Jun 2013 13:15:08 -0700 Subject: [PATCH 46/46] Another fix: using strlen to determine the length of the packet is... unwise. Remember the length when we create it. This should fix the voxel server's not appearing. --- libraries/shared/src/AgentList.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index e1b4bd9d63..7a4803586e 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -205,6 +205,7 @@ void AgentList::sendDomainServerCheckIn() { // construct the DS check in packet if we need to static unsigned char* checkInPacket = NULL; + static int checkInPacketSize; if (!checkInPacket) { int numBytesAgentsOfInterest = _agentTypesOfInterest ? strlen((char*) _agentTypesOfInterest) : 0; @@ -236,10 +237,10 @@ void AgentList::sendDomainServerCheckIn() { packetPosition += numBytesAgentsOfInterest; } - *packetPosition = '\0'; + checkInPacketSize = packetPosition - checkInPacket; } - _agentSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, checkInPacket, strlen((char*) checkInPacket)); + _agentSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, checkInPacket, checkInPacketSize); } int AgentList::processDomainServerList(unsigned char *packetData, size_t dataBytes) {