From 2e854b5ed7b7afbe9ba0fc033604756595f58cf8 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 10 Jul 2013 12:20:26 -0700 Subject: [PATCH] Tune and smooth 'Touch Look' and always turned on, old mouseLook code removed. Add vec3 speed test. Smooth simulation by passing exact deltaTime to update() --- interface/src/Application.cpp | 64 ++++++++++++++++++--------------- interface/src/Application.h | 9 +++-- interface/src/Avatar.cpp | 27 -------------- interface/src/Avatar.h | 2 -- interface/src/Util.cpp | 14 ++++++++ libraries/shared/src/StdDev.cpp | 13 ++++++- 6 files changed, 67 insertions(+), 62 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fcf06cd293..2c058cf620 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -338,6 +338,7 @@ void Application::initializeGL() { QTimer* idleTimer = new QTimer(this); connect(idleTimer, SIGNAL(timeout()), SLOT(idle())); idleTimer->start(0); + _idleLoopStdev.reset(); if (_justStarted) { float startupTime = (usecTimestampNow() - usecTimestamp(&_applicationStartupTime)) / 1000000.0; @@ -866,6 +867,8 @@ void Application::touchUpdateEvent(QTouchEvent* event) { void Application::touchBeginEvent(QTouchEvent* event) { touchUpdateEvent(event); + _lastTouchAvgX = _touchAvgX; + _lastTouchAvgY = _touchAvgY; } void Application::touchEndEvent(QTouchEvent* event) { @@ -949,28 +952,36 @@ static glm::vec3 getFaceVector(BoxFace face) { } void Application::idle() { + timeval check; gettimeofday(&check, NULL); // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran - - if (diffclock(&_lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) { + + double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check); + if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) { // If we're using multi-touch look, immediately process any // touch events, and no other events. // This is necessary because id the idle() call takes longer than the // interval between idle() calls, the event loop never gets to run, // and touch events get delayed. - if (_touchLook->isChecked()) { - sendPostedEvents(NULL, QEvent::TouchBegin); - sendPostedEvents(NULL, QEvent::TouchUpdate); - sendPostedEvents(NULL, QEvent::TouchEnd); - } - - update(1.0f / _fps); - + sendPostedEvents(NULL, QEvent::TouchBegin); + sendPostedEvents(NULL, QEvent::TouchUpdate); + sendPostedEvents(NULL, QEvent::TouchEnd); + + const float BIGGEST_DELTA_TIME_SECS = 0.25f; + update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS)); _glWidget->updateGL(); - _lastTimeIdle = check; + _lastTimeUpdated = check; + _idleLoopStdev.addValue(timeSinceLastUpdate); + + // Record standard deviation and reset counter if needed + const int STDEV_SAMPLES = 500; + if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { + _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); + _idleLoopStdev.reset(); + } } } void Application::terminate() { @@ -1476,10 +1487,6 @@ void Application::initMenu() { optionsMenu->addAction("Noise", this, SLOT(setNoise(bool)), Qt::Key_N)->setCheckable(true); (_gyroLook = optionsMenu->addAction("Smooth Gyro Look"))->setCheckable(true); _gyroLook->setChecked(true); - (_mouseLook = optionsMenu->addAction("Mouse Look"))->setCheckable(true); - _mouseLook->setChecked(true); - (_touchLook = optionsMenu->addAction("Touch Look"))->setCheckable(true); - _touchLook->setChecked(false); (_showHeadMouse = optionsMenu->addAction("Head Mouse"))->setCheckable(true); _showHeadMouse->setChecked(false); (_transmitterDrives = optionsMenu->addAction("Transmitter Drive"))->setCheckable(true); @@ -1677,7 +1684,7 @@ void Application::init() { LeapManager::initialize(); gettimeofday(&_timerStart, NULL); - gettimeofday(&_lastTimeIdle, NULL); + gettimeofday(&_lastTimeUpdated, NULL); loadSettings(); if (!shouldDynamicallySetJitterBuffer()) { @@ -1816,20 +1823,19 @@ void Application::update(float deltaTime) { if (_myAvatar.getMode() == AVATAR_MODE_WALKING) { _handControl.stop(); } - - // Update from Mouse - if (_mouseLook->isChecked()) { - QPoint mouse = QCursor::pos(); - _myAvatar.updateFromMouse(_glWidget->mapFromGlobal(mouse).x(), - _glWidget->mapFromGlobal(mouse).y(), - _glWidget->width(), - _glWidget->height()); - } - + // Update from Touch - if (_isTouchPressed && _touchLook->isChecked()) { - _myAvatar.updateFromTouch(_touchAvgX - _touchDragStartedAvgX, - _touchAvgY - _touchDragStartedAvgY); + if (_isTouchPressed) { + float TOUCH_YAW_SCALE = -50.0f; + float TOUCH_PITCH_SCALE = -50.0f; + _myAvatar.getHead().addYaw((_touchAvgX - _lastTouchAvgX) + * TOUCH_YAW_SCALE + * deltaTime); + _myAvatar.getHead().addPitch((_touchAvgY - _lastTouchAvgY) + * TOUCH_PITCH_SCALE + * deltaTime); + _lastTouchAvgX = _touchAvgX; + _lastTouchAvgY = _touchAvgY; } // Leap finger-sensing device diff --git a/interface/src/Application.h b/interface/src/Application.h index 565df61785..7fba44249f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -212,8 +212,6 @@ private: QAction* _shouldLowPassFilter; // Use test lowpass filter QAction* _gyroLook; // Whether to allow the gyro data from head to move your view QAction* _renderAvatarBalls; // Switch between voxels and joints/balls for avatar render - QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view - QAction* _touchLook; // Whether a 2-finger touch may be used to control look direction QAction* _showHeadMouse; // Whether the have the mouse near edge of screen move your view QAction* _transmitterDrives; // Whether to have Transmitter data move/steer the Avatar QAction* _gravityUse; // Whether gravity is on or not @@ -261,7 +259,7 @@ private: float _fps; timeval _applicationStartupTime; timeval _timerStart, _timerEnd; - timeval _lastTimeIdle; + timeval _lastTimeUpdated; bool _justStarted; Stars _stars; @@ -313,6 +311,8 @@ private: float _touchAvgX; float _touchAvgY; + float _lastTouchAvgX; + float _lastTouchAvgY; float _touchDragStartedAvgX; float _touchDragStartedAvgY; bool _isTouchPressed; // true if multitouch has been pressed (clear when finished) @@ -361,6 +361,9 @@ private: int _packetsPerSecond; int _bytesPerSecond; int _bytesCount; + + StDev _idleLoopStdev; + float _idleLoopMeasuredJitter; }; diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index c2c850c923..00bf65fd7d 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -350,34 +350,7 @@ 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_ROTATE_SPEED = 0.01f; - const float MOUSE_PITCH_SPEED = 0.02f; - const int TITLE_BAR_HEIGHT = 46; - - 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 - // - - 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); - } - } -} -void Avatar::updateFromTouch(float touchAvgDistX, float touchAvgDistY) { - const float TOUCH_ROTATE_SPEED = 0.01f; - const float TOUCH_PITCH_SPEED = 0.02f; - - _head.addYaw(-touchAvgDistX * TOUCH_ROTATE_SPEED); - _head.addPitch(-touchAvgDistY * TOUCH_PITCH_SPEED); -} void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { // diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 855d49e51c..c38e5e4e84 100755 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -88,8 +88,6 @@ public: void simulate(float deltaTime, Transmitter* transmitter); void updateThrust(float deltaTime, Transmitter * transmitter); void updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngles); - void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight); - void updateFromTouch(float touchAvgDistX, float touchAvgDistY); void addBodyYaw(float y) {_bodyYaw += y;}; void render(bool lookingInMirror, bool renderAvatarBalls); diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 4bfdb1f587..f5efd1b13a 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -500,6 +500,20 @@ void runTimingTests() { elapsedMsecs = diffclock(&startTime, &endTime); printLog("powf(f, 0.5) usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests); + // Vec3 test + glm::vec3 vecA(randVector()), vecB(randVector()); + float result; + + gettimeofday(&startTime, NULL); + for (int i = 1; i < numTests; i++) { + glm::vec3 temp = vecA-vecB; + result = glm::dot(temp,temp); + } + gettimeofday(&endTime, NULL); + elapsedMsecs = diffclock(&startTime, &endTime); + printLog("vec3 assign and dot() usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests); + + } float loadSetting(QSettings* settings, const char* name, float defaultValue) { diff --git a/libraries/shared/src/StdDev.cpp b/libraries/shared/src/StdDev.cpp index 2c29a4254b..17bf60e8be 100644 --- a/libraries/shared/src/StdDev.cpp +++ b/libraries/shared/src/StdDev.cpp @@ -6,8 +6,9 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include "StdDev.h" +#include #include +#include "StdDev.h" const int MAX_STDEV_SAMPLES = 1000; @@ -34,6 +35,16 @@ float StDev::getAverage() { return average/(float)sampleCount; else return 0; } +/* +float StDev::getMax() { + float average = -FLT_MAX; + for (int i = 0; i < sampleCount; i++) { + average += data[i]; + } + if (sampleCount > 0) + return average/(float)sampleCount; + else return 0; +}*/ float StDev::getStDev() { float average = getAverage();