From a767c2fd0880b71d5bf88d23eb865f5cb8084cb2 Mon Sep 17 00:00:00 2001 From: GPayne Date: Tue, 8 May 2018 16:44:53 -0600 Subject: [PATCH] Fixed some touch behavior (especially zoom) and implemented lower-right corner double-tap for zooming out --- modules/touch/include/touchinteraction.h | 84 +++--- modules/touch/src/touchinteraction.cpp | 320 +++++++++-------------- 2 files changed, 166 insertions(+), 238 deletions(-) diff --git a/modules/touch/include/touchinteraction.h b/modules/touch/include/touchinteraction.h index 45d4bbbd6a..2bba20bc26 100644 --- a/modules/touch/include/touchinteraction.h +++ b/modules/touch/include/touchinteraction.h @@ -38,14 +38,30 @@ #include //#define TOUCH_DEBUG_PROPERTIES -#define CONST_TIME_DECAY -#define SPEED_BRAKE +#define ZOOM_CORNER_TAP namespace openspace { class Camera; class SceneGraphNode; +//Class used for keeping track of the recent average frame time +class FrameTimeAverage +{ +public: + //Update the circular buffer with the most recent frame time + void updateWithNewFrame(double sample); + //Get the value of the most recent average frame time (seconds) + double getAvgFrameTime(); + +private: + static const int totalSamples = 10; + int _nSamples = 0; + double _samples[totalSamples]; + double _runningTotal = 0.0; + int index = 0; +}; + class TouchInteraction : public properties::PropertyOwner { public: using Point = std::pair; @@ -53,7 +69,11 @@ public: TouchInteraction(); // for interpretInteraction() - enum Type { ROT = 0, PINCH, PAN, ROLL, PICK }; + enum Type { ROT = 0, PINCH, PAN, ROLL, PICK +#ifdef ZOOM_CORNER_TAP + , ZOOM_OUT +#endif + }; // Stores the velocity in all 6DOF struct VelocityStates { @@ -150,6 +170,17 @@ private: void computeVelocities(const std::vector& list, const std::vector& lastProcessed); + //Compute velocity based on double-tap for zooming + double computeTapZoomDistance(double zoomGain); + + //Compute coefficient for velocity decay to be applied in decceleration + double computeConstTimeDecayCoefficient(double velocity); + + //Compute coefficient of decay based on current frametime; if frametime has been + // longer than usual then multiple decay steps may be applied to keep the decay + // relative to user time + double computeDecayCoeffFromFrametime(double coeff, int times); + /* Decelerate the velocities. Function is called in step() but is dereferenced from * frame time to assure same behaviour on all systems */ @@ -174,7 +205,8 @@ private: properties::FloatProperty _rollAngleThreshold; properties::FloatProperty _orbitSpeedThreshold; properties::FloatProperty _spinSensitivity; - properties::FloatProperty _zoomSensitivity; + properties::FloatProperty _zoomSensitivityExponential; + properties::FloatProperty _zoomSensitivityProportionalDist; properties::FloatProperty _zoomSensitivityDistanceThreshold; properties::FloatProperty _zoomBoundarySphereMultiplier; properties::FloatProperty _inputStillThreshold; @@ -186,17 +218,7 @@ private: properties::Vec4Property _friction; properties::FloatProperty _pickingRadiusMinimum; properties::BoolProperty _ignoreGui; -#ifdef CONST_TIME_DECAY properties::FloatProperty _constTimeDecay_secs; -#endif - -#ifdef SPEED_BRAKE - properties::FloatProperty _speedLimitNearVelocityDivider; - properties::FloatProperty _speedLimitDistanceThresholdExp; -#else - properties::FloatProperty _speedLimitDistanceFraction; -#endif - properties::FloatProperty _zoomSpeedAsymmetryGain; #ifdef TOUCH_DEBUG_PROPERTIES struct DebugProperties : PropertyOwner { @@ -228,6 +250,9 @@ private: bool _directTouchMode; bool _tap; bool _doubleTap; +#ifdef ZOOM_CORNER_TAP + bool _zoomOutTap; +#endif bool _lmSuccess; bool _guiON; std::vector _selected; @@ -236,36 +261,6 @@ private: glm::dquat _toSlerp; glm::dvec3 _centroid; -#ifdef CONST_TIME_DECAY - class FrameTimeAverage - { - public: - void updateWithNewFrame (double sample) - { - if (sample > 0.0005) { - _samples[index++] = sample; - if (index >= totalSamples) - index = 0; - if (_nSamples < totalSamples) - _nSamples++; - } - } - - double getAvgFrameTime () { - if (_nSamples == 0) - return 1.0 / 60.0; - else - return std::accumulate(_samples, _samples + _nSamples, 0.0) - / (double)(_nSamples); - } - - private: - static const int totalSamples = 10; - int _nSamples = 0; - double _samples[totalSamples]; - double _runningTotal = 0.0; - int index = 0; - }; FrameTimeAverage _frameTimeAvg; struct ConstantTimeDecayCoefficients { @@ -275,7 +270,6 @@ private: double pan = 0.0; }; ConstantTimeDecayCoefficients _constTimeDecayCoeff; -#endif }; } // openspace namespace diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index 40f8421847..d620b3cdfd 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -140,12 +140,18 @@ namespace { "" // @TODO Missing documentation }; - static const openspace::properties::Property::PropertyInfo ZoomSensitivityInfo = { - "ZoomSensitivity", + static const openspace::properties::Property::PropertyInfo ZoomSensitivityExpInfo = { + "ZoomSensitivityExp", "Sensitivity of exponential zooming in relation to distance from focus node", "" // @TODO Missing documentation }; + static const openspace::properties::Property::PropertyInfo ZoomSensitivityPropInfo = { + "ZoomSensitivityProp", + "Sensitivity of zooming proportional to distance from focus node", + "" // @TODO Missing documentation + }; + static const openspace::properties::Property::PropertyInfo ZoomSensitivityDistanceThresholdInfo = { "ZoomSensitivityDistanceThreshold", "Threshold of distance to target node for whether or not to use exponential zooming", @@ -158,39 +164,11 @@ namespace { "" // @TODO Missing documentation }; -#ifdef CONST_TIME_DECAY static const openspace::properties::Property::PropertyInfo ConstantTimeDecaySecsInfo = { "ConstantTimeDecaySecs", "Time duration that a pitch/roll/zoom/pan should take to decay to zero (seconds)", "" }; -#endif - -#ifdef SPEED_BRAKE - static const openspace::properties::Property::PropertyInfo SpeedLimitNearVelocityDividerInfo = { - "SpeedLimitNearVelocityDivider", - "At close distance, velocity is limited by dividing distance-to-focus-node by this value", - "" - }; - - static const openspace::properties::Property::PropertyInfo SpeedLimitFarDistanceThresholdExpInfo = { - "SpeedLimitFarDistanceThreshold", - "Threshold for distance (exponent for 10^) from camera to focus node where near velocity divider blends to far divider", - "" - }; -#else - static const openspace::properties::Property::PropertyInfo SpeedLimitDistanceFractionInfo = { - "SpeedLimitDistanceFraction", - "Speed limiting factor as a fraction of distance to focus node", - "" - }; -#endif //#ifdef SPEED_BRAKE - - static const openspace::properties::Property::PropertyInfo ZoomSpeedAsymmetryGainInfo = { - "ZoomSpeedAsymmetryGain", - "At close distance to focus node, zooming-out velocity is this much faster (gain) than zooming-in velocity", - "" - }; static const openspace::properties::Property::PropertyInfo InputSensitivityInfo = { "InputSensitivity", @@ -259,7 +237,8 @@ TouchInteraction::TouchInteraction() , _rollAngleThreshold(RollThresholdInfo, 0.025f, 0.f, 0.05f) , _orbitSpeedThreshold(OrbitSpinningThreshold, 0.005f, 0.f, 0.01f) , _spinSensitivity(SpinningSensitivityInfo, 1.f, 0.f, 2.f) - , _zoomSensitivity(ZoomSensitivityInfo, 1.035f, 1.0f, 1.1f) + , _zoomSensitivityExponential(ZoomSensitivityExpInfo, 1.03f, 1.0f, 1.1f) + , _zoomSensitivityProportionalDist(ZoomSensitivityPropInfo, 11.f, 5.f, 50.f) , _zoomSensitivityDistanceThreshold(ZoomSensitivityDistanceThresholdInfo, 0.05, 0.01, 0.25) , _zoomBoundarySphereMultiplier(ZoomBoundarySphereMultiplierInfo, 1.001, 1.0, 1.01) , _inputStillThreshold(InputSensitivityInfo, 0.0005f, 0.f, 0.001f) @@ -267,7 +246,7 @@ TouchInteraction::TouchInteraction() , _centroidStillThreshold(StationaryCentroidInfo, 0.0018f, 0.f, 0.01f) , _panEnabled(PanModeInfo, false) , _interpretPan(PanDeltaDistanceInfo, 0.015f, 0.f, 0.1f) - , _slerpTime(SlerpTimeInfo, 3.f, 0.f, 5.f) + , _slerpTime(SlerpTimeInfo, 3.f, 0.1f, 5.f) , _guiButton( GuiButtonSizeInfo, glm::ivec2(32, 64), @@ -291,17 +270,8 @@ TouchInteraction::TouchInteraction() false ) , _vel{ glm::dvec2(0.0), 0.0, 0.0, glm::dvec2(0.0) } - , _sensitivity{ glm::dvec2(0.08, 0.045), 4.0, 2.75, glm::dvec2(0.08, 0.045) } -#ifdef SPEED_BRAKE - , _speedLimitNearVelocityDivider(SpeedLimitNearVelocityDividerInfo, 0.7f, 0.01f, 3.f) - , _speedLimitDistanceThresholdExp(SpeedLimitFarDistanceThresholdExpInfo, 8.6, 7.0, 10.0) -#else - , _speedLimitDistanceFraction(SpeedLimitDistanceFractionInfo, 7.f, 0.1f, 20.0f) -#endif -#ifdef CONST_TIME_DECAY + , _sensitivity{ glm::dvec2(0.08, 0.045), 12.0 /*4.0*/, 2.75, glm::dvec2(0.08, 0.045) } , _constTimeDecay_secs(ConstantTimeDecaySecsInfo, 1.75f, 0.1f, 4.0f) -#endif - , _zoomSpeedAsymmetryGain(ZoomSpeedAsymmetryGainInfo, 15.f, 1.f, 100.f) // calculated with two vectors with known diff in length, then // projDiffLength/diffLength. , _projectionScaleFactor(1.000004) @@ -312,6 +282,9 @@ TouchInteraction::TouchInteraction() , _directTouchMode(false) , _tap(false) , _doubleTap(false) +#ifdef ZOOM_CORNER_TAP + , _zoomOutTap(false) +#endif , _lmSuccess(true) , _guiON(false) #ifdef TOUCH_DEBUG_PROPERTIES @@ -330,19 +303,11 @@ TouchInteraction::TouchInteraction() addProperty(_rollAngleThreshold); addProperty(_orbitSpeedThreshold); addProperty(_spinSensitivity); - addProperty(_zoomSensitivity); + addProperty(_zoomSensitivityExponential); + addProperty(_zoomSensitivityProportionalDist); addProperty(_zoomSensitivityDistanceThreshold); addProperty(_zoomBoundarySphereMultiplier); -#ifdef SPEED_BRAKE - addProperty(_speedLimitNearVelocityDivider); - addProperty(_speedLimitDistanceThresholdExp); -#else - addProperty(_speedLimitDistanceFraction); -#endif -#ifdef CONST_TIME_DECAY addProperty(_constTimeDecay_secs); -#endif - addProperty(_zoomSpeedAsymmetryGain); addProperty(_inputStillThreshold); addProperty(_centroidStillThreshold); addProperty(_panEnabled); @@ -389,6 +354,27 @@ void TouchInteraction::updateStateFromInput(const std::vector& list, _time.initSession(); } +#ifdef ZOOM_CORNER_TAP + WindowWrapper& wrapper = OsEng.windowWrapper(); + glm::ivec2 res = wrapper.currentWindowSize(); + glm::dvec2 pos = glm::vec2( + list.at(0).getScreenX(res.x), + list.at(0).getScreenY(res.y) + ); + const float bottomCornerSizeForZoomTap_fraction = 0.08f; + int zoomTapThresholdX = (float)res.x * (1.0f - bottomCornerSizeForZoomTap_fraction); + int zoomTapThresholdY = (float)res.y * (1.0f - bottomCornerSizeForZoomTap_fraction); + + bool isTapInLowerCorner = ( std::abs(pos.x) > zoomTapThresholdX + && std::abs(pos.y) > zoomTapThresholdY ); + + if( _doubleTap && isTapInLowerCorner ) { + _zoomOutTap = true; + _tap = false; + _doubleTap = false; + } +#endif + if (!guiMode(list)) { if (_directTouchMode && _selected.size() > 0 && list.size() == _selected.size()) { #ifdef TOUCH_DEBUG_PROPERTIES @@ -444,6 +430,7 @@ bool TouchInteraction::guiMode(const std::vector& list) { else if (_guiON) { module.touchInput = { _guiON, pos, 1 }; // emulate touch input as a mouse } + return _guiON; } @@ -952,6 +939,11 @@ int TouchInteraction::interpretInteraction(const std::vector& list, _debugProperties.minDiff = minDiff; #endif +#ifdef ZOOM_CORNER_TAP + if (_zoomOutTap) + return ZOOM_OUT; + else +#endif if (_doubleTap) { return PICK; } @@ -988,10 +980,6 @@ void TouchInteraction::computeVelocities(const std::vector& list, { TuioCursor cursor = list.at(0); const int action = interpretInteraction(list, lastProcessed); -#ifdef CONST_TIME_DECAY - double stepsToDecay = _constTimeDecay_secs / _frameTimeAvg.getAvgFrameTime(); - const double postDecayVelocityTarget = 1e-6; -#endif #ifdef TOUCH_DEBUG_PROPERTIES const std::map interactionNames = { @@ -1005,7 +993,8 @@ void TouchInteraction::computeVelocities(const std::vector& list, if (pinchConsecCt > 0 && action != PINCH) { if( pinchConsecCt > 3 ) - LINFO("PINCH_gesture_ended_with " << pinchConsecZoomFactor << " drag_distance_and " << pinchConsecCt << " counts."); + LINFO("PINCH_gesture_ended_with " << pinchConsecZoomFactor + << " drag_distance_and " << pinchConsecCt << " counts."); pinchConsecCt = 0; pinchConsecZoomFactor = 0.0; } @@ -1016,15 +1005,9 @@ void TouchInteraction::computeVelocities(const std::vector& list, _vel.orbit += glm::dvec2(cursor.getXSpeed() * _sensitivity.orbit.x, cursor.getYSpeed() * _sensitivity.orbit.y); -#ifdef CONST_TIME_DECAY - /*double orbitVelocityAvg = (cursor.getXSpeed() * _sensitivity.orbit.x - + cursor.getYSpeed() * _sensitivity.orbit.y) / 2.0;*/ double orbitVelocityAvg = glm::distance(_vel.orbit.x, _vel.orbit.y); - if( stepsToDecay > 0.0 && std::abs(orbitVelocityAvg) > 0.0 ) - _constTimeDecayCoeff.orbit = std::pow((postDecayVelocityTarget / std::abs(orbitVelocityAvg)), (1.0 / stepsToDecay)); - else - _constTimeDecayCoeff.orbit = 1.0; -#endif + _constTimeDecayCoeff.orbit + = computeConstTimeDecayCoefficient(orbitVelocityAvg); break; } case PINCH: { @@ -1057,42 +1040,26 @@ void TouchInteraction::computeVelocities(const std::vector& list, glm::dvec3 centerPos = _focusNode->worldPosition(); glm::dvec3 currDistanceToFocusNode = camPos - centerPos; - double distanceFromFocusSurface = length(currDistanceToFocusNode) - _focusNode->boundingSphere(); + double distanceFromFocusSurface = length(currDistanceToFocusNode) + - _focusNode->boundingSphere(); double zoomFactor = (distance - lastDistance); #ifdef TOUCH_DEBUG_PROPERTIES pinchConsecCt++; pinchConsecZoomFactor += zoomFactor; #endif -#ifdef CONST_TIME_DECAY - if( stepsToDecay > 0.0 && std::abs(_vel.zoom) > 0.0 ) - //Use half the number of steps for zooming in order to decay faster - _constTimeDecayCoeff.zoom = std::pow((postDecayVelocityTarget / std::abs(_vel.zoom)), (1.0 / stepsToDecay / 2)); - else - _constTimeDecayCoeff.zoom = 1.0; -#endif - if ((length(currDistanceToFocusNode) / distanceFromFocusSurface) > _zoomSensitivityDistanceThreshold) { - zoomFactor *= pow(std::abs(distanceFromFocusSurface), (float)_zoomSensitivity); - } - - //Make zoom-out gestures faster near the focus node - if (zoomFactor < 0.0) { - double distanceThreshold = std::pow(10.0, (double)_speedLimitDistanceThresholdExp); - double zoomOutGain; - if (distanceFromFocusSurface < distanceThreshold) { - zoomOutGain = _zoomSpeedAsymmetryGain; - } else if (distanceFromFocusSurface < (distanceThreshold * 10)) { - double zoomOutGainBeyondUnity = _zoomSpeedAsymmetryGain - 1.0; - double ratioOfZoomOutGainToApplyBasedOnDistance = 1.0 - (distanceFromFocusSurface - distanceThreshold) - / (distanceThreshold * 10 - distanceThreshold); - zoomOutGain = 1.0 + zoomOutGainBeyondUnity*ratioOfZoomOutGainToApplyBasedOnDistance; - } else { - zoomOutGain = 1.0; + _constTimeDecayCoeff.zoom = computeConstTimeDecayCoefficient(_vel.zoom); + if (distanceFromFocusSurface > 0.1) { + double ratioOfDistanceToNodeVsSurface = length(currDistanceToFocusNode) + / distanceFromFocusSurface; + if (ratioOfDistanceToNodeVsSurface > _zoomSensitivityDistanceThreshold) { + zoomFactor *= pow(std::abs(distanceFromFocusSurface), + (float)_zoomSensitivityExponential); } - zoomFactor *= zoomOutGain; + } else { + zoomFactor = 1.0; } - - _vel.zoom += zoomFactor * _sensitivity.zoom * + _vel.zoom = zoomFactor * _zoomSensitivityProportionalDist * std::max(_touchScreenSize.value() * 0.1, 1.0); break; } @@ -1132,27 +1099,15 @@ void TouchInteraction::computeVelocities(const std::vector& list, ) / list.size(); _vel.roll += -rollFactor * _sensitivity.roll; -#ifdef CONST_TIME_DECAY - if( stepsToDecay > 0.0 && std::abs(_vel.roll) > 0.0 ) - _constTimeDecayCoeff.roll = std::pow((postDecayVelocityTarget / std::abs(_vel.roll)), (1.0 / stepsToDecay)); - else - _constTimeDecayCoeff.roll = 1.0; -#endif + _constTimeDecayCoeff.roll = computeConstTimeDecayCoefficient(_vel.roll); break; } case PAN: { // add local rotation velocity _vel.pan += glm::dvec2(cursor.getXSpeed() * _sensitivity.pan.x, cursor.getYSpeed() * _sensitivity.pan.y); -#ifdef CONST_TIME_DECAY - /*double panVelocityAvg = (cursor.getXSpeed() * _sensitivity.pan.x - + cursor.getYSpeed() * _sensitivity.pan.y) / 2.0;*/ double panVelocityAvg = glm::distance(_vel.pan.x, _vel.pan.y); - if( stepsToDecay > 0.0 && std::abs(panVelocityAvg) > 0.0 ) - _constTimeDecayCoeff.pan = std::pow((postDecayVelocityTarget / std::abs(panVelocityAvg)), (1.0 / stepsToDecay)); - else - _constTimeDecayCoeff.pan = 1.0; -#endif + _constTimeDecayCoeff.pan = computeConstTimeDecayCoefficient(panVelocityAvg); break; } case PICK: { @@ -1178,19 +1133,42 @@ void TouchInteraction::computeVelocities(const std::vector& list, else { // zooms in to current if PICK interpret happened but only space was // selected - double dist = glm::distance( - _camera->positionVec3(), _camera->focusPositionVec3() - ) - _focusNode->boundingSphere(); - _vel.zoom = _sensitivity.zoom * - std::max(_touchScreenSize.value() * 0.1, 1.0) * - _tapZoomFactor * dist; - + _vel.zoom = computeTapZoomDistance(0.3); + _constTimeDecayCoeff.zoom = computeConstTimeDecayCoefficient(_vel.zoom); } break; } +#ifdef ZOOM_CORNER_TAP + case ZOOM_OUT: { + // zooms out from current if triple tap occurred + _vel.zoom = computeTapZoomDistance(-1.0); + _constTimeDecayCoeff.zoom = computeConstTimeDecayCoefficient(_vel.zoom); + } +#endif } } +double TouchInteraction::computeConstTimeDecayCoefficient(double velocity) { + const double postDecayVelocityTarget = 1e-6; + double stepsToDecay = _constTimeDecay_secs / _frameTimeAvg.getAvgFrameTime(); + + if (stepsToDecay > 0.0 && std::abs(velocity) > postDecayVelocityTarget) + return std::pow((postDecayVelocityTarget / std::abs(velocity)), (1.0 / stepsToDecay)); + else + return 1.0; +} + +double TouchInteraction::computeTapZoomDistance(double zoomGain) { + double dist = glm::distance(_camera->positionVec3(), _camera->focusPositionVec3()); + dist -= _focusNode->boundingSphere(); + + double newVelocity = dist * _tapZoomFactor; + newVelocity *= std::max(_touchScreenSize.value() * 0.1, 1.0); + newVelocity *= _zoomSensitivityProportionalDist * zoomGain; + + return newVelocity; +} + // Main update call, calculates the new orientation and position for the camera depending // on _vel and dt. Called every frame void TouchInteraction::step(double dt) { @@ -1270,27 +1248,7 @@ void TouchInteraction::step(double dt) { double planetBoundaryRadius = length(centerToBoundingSphere); planetBoundaryRadius *= _zoomBoundarySphereMultiplier; double distToSurface = length(centerToCamera - planetBoundaryRadius); - //Speed Limit on zoom velocity -#ifdef SPEED_BRAKE - double nearSpeedLimit = distToSurface / _speedLimitNearVelocityDivider; - double farSpeedLimit = _vel.zoom; - double distanceThreshold = std::pow(10.0, (double)_speedLimitDistanceThresholdExp); - double speedLimit; - if (distToSurface < distanceThreshold) { - double velocityFraction = distToSurface / distanceThreshold; - speedLimit = farSpeedLimit * velocityFraction + nearSpeedLimit * (1.0 - velocityFraction); - } - else { - speedLimit = farSpeedLimit; - } -#else - double speedLimit = _speedLimitDistanceFraction * distanceFromFocusSurface; -#endif - if (std::abs(_vel.zoom) > 1e-7) - _vel.zoom = (std::min(std::abs(speedLimit), std::abs(_vel.zoom))) * (_vel.zoom > 0.0 ? 1.0 : -1.0); - else - _vel.zoom = 0.0; //Apply the velocity to update camera position if (length(_vel.zoom*dt) < distToSurface && length(centerToCamera + directionToCenter*_vel.zoom*dt) @@ -1321,6 +1279,9 @@ void TouchInteraction::step(double dt) { _tap = false; _doubleTap = false; +#ifdef ZOOM_CORNER_TAP + _zoomOutTap = false; +#endif if (_reset) { resetToDefault(); } @@ -1372,9 +1333,7 @@ void TouchInteraction::unitTest() { // Assume: frequency = 0.01, dt = 0.05 (200 fps), _timeSlack = 0.0001 // times = floor((0.05 + 0.0001) / 0.01) = 5 // _timeSlack = 0.0501 % 0.01 = 0.01 - void TouchInteraction::decelerate(double dt) { -#ifdef CONST_TIME_DECAY _frameTimeAvg.updateWithNewFrame(dt); double expectedFrameTime = _frameTimeAvg.getAvgFrameTime(); @@ -1384,68 +1343,24 @@ void TouchInteraction::decelerate(double dt) { // Save the new time slack for the next frame _timeSlack = fmod((dt + _timeSlack), expectedFrameTime) * expectedFrameTime; - if (times > 0) { - if (_constTimeDecayCoeff.orbit > 0.0001) - _vel.orbit *= std::pow(_constTimeDecayCoeff.orbit, times); - else - _vel.orbit = { 0.0, 0.0 }; + //Ensure the number of times to apply the decay coefficient is valid + times = std::min(times, 1); - if (_constTimeDecayCoeff.roll > 0.0001) - _vel.roll *= std::pow(_constTimeDecayCoeff.roll, times); - else - _vel.roll = 0.0; - - if (_constTimeDecayCoeff.pan > 0.0001) - _vel.pan *= std::pow(_constTimeDecayCoeff.pan, times); - else - _vel.pan = { 0.0, 0.0 }; - - if( _constTimeDecayCoeff.zoom > 0.0001) { - // Decelerate zoom velocity quicker if we're close enough to use direct-manipulation - if (!_directTouchMode && _currentRadius > _nodeRadiusThreshold && - _vel.zoom > _focusNode->boundingSphere()) - { - _vel.zoom *= std::pow(2 * _constTimeDecayCoeff.zoom, times); - } - else { - _vel.zoom *= std::pow(_constTimeDecayCoeff.zoom, times); - } - } - else { - _vel.zoom = 0.0; - } - } -#else - double frequency = 1.0 / _deceleratesPerSecond; - // Number of times velocities should decelerate, depending on chosen frequency and - // time slack over from last frame - int times = static_cast((dt + _timeSlack) / frequency); - // Save the new time slack for the next frame - _timeSlack = fmod((dt + _timeSlack), frequency) * frequency; - - // Decelerate zoom velocity quicker if we're close enough to use direct-manipulation - if (!_directTouchMode && _currentRadius > _nodeRadiusThreshold && - _vel.zoom > _focusNode->boundingSphere()) - { - _vel.zoom *= std::pow(1 - 2 * _friction.value().y, times); - } - _vel.orbit *= std::pow(1 - _friction.value().x, times); - _vel.roll *= std::pow(1 - _friction.value().z, times); - _vel.pan *= std::pow(1 - _friction.value().w, times); -#endif //#ifdef CONST_TIME_DECAY - -#ifndef CONST_TIME_DECAY - float frictionDecayValue = _friction.value().y; -#endif //#ifndef CONST_TIME_DECAY + _vel.orbit *= computeDecayCoeffFromFrametime(_constTimeDecayCoeff.orbit, times); + _vel.roll *= computeDecayCoeffFromFrametime(_constTimeDecayCoeff.roll, times); + _vel.pan *= computeDecayCoeffFromFrametime(_constTimeDecayCoeff.pan, times); + _vel.zoom *= computeDecayCoeffFromFrametime(_constTimeDecayCoeff.zoom, times); glm::dvec3 camPos = _camera->positionVec3(); glm::dvec3 centerPos = _focusNode->worldPosition(); glm::dvec3 centerToCamera = camPos - centerPos; +} -#ifndef CONST_TIME_DECAY - _vel.zoom *= std::pow((1 - frictionDecayValue), times); -#endif //#ifndef CONST_TIME_DECAY - +double TouchInteraction::computeDecayCoeffFromFrametime(double coeff, int times) { + if( coeff > 0.00001 ) + return std::pow(coeff, times); + else + return 0.0; } // Called if all fingers are off the screen @@ -1501,7 +1416,7 @@ void TouchInteraction::resetToDefault() { _rollAngleThreshold.set(0.025f); _orbitSpeedThreshold.set(0.005f); _spinSensitivity.set(1.0f); - _zoomSensitivity.set(1.01f); + _zoomSensitivityExponential.set(1.025f); _inputStillThreshold.set(0.0005f); _centroidStillThreshold.set(0.0018f); _interpretPan.set(0.015f); @@ -1533,6 +1448,25 @@ void TouchInteraction::setFocusNode(SceneGraphNode* focusNode) { _focusNode = focusNode; } +void FrameTimeAverage::updateWithNewFrame(double sample) { + if (sample > 0.0005) { + _samples[index++] = sample; + if (index >= totalSamples) + index = 0; + if (_nSamples < totalSamples) + _nSamples++; + } +} + +double FrameTimeAverage::getAvgFrameTime() { + double ft; + if (_nSamples == 0) + ft = 1.0 / 60.0; //Just guess at 60fps if no data is available yet + else + ft = std::accumulate(_samples, _samples + _nSamples, 0.0) / (double)(_nSamples); + return ft; +} + #ifdef TOUCH_DEBUG_PROPERTIES TouchInteraction::DebugProperties::DebugProperties() : properties::PropertyOwner({ "TouchDebugProperties" })