X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fupdate%2Fgestures%2Fscene-graph-pan-gesture.cpp;h=d8a119a8dde8938ffab5a5b7bb7e6233518b4fda;hb=6dec6c8c9b56b76394659c2c776ed6a2ba2ea4d2;hp=4ee7ddd84c7e1599aead01ba148bac0e25395818;hpb=9e362f9cd4e43e7cffb08b5538b80bfb4f2533c2;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/update/gestures/scene-graph-pan-gesture.cpp b/dali/internal/update/gestures/scene-graph-pan-gesture.cpp index 4ee7ddd..d8a119a 100644 --- a/dali/internal/update/gestures/scene-graph-pan-gesture.cpp +++ b/dali/internal/update/gestures/scene-graph-pan-gesture.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include // INTERNAL INCLUDES #include @@ -31,14 +32,23 @@ namespace Internal namespace SceneGraph { + namespace { -const int MAX_GESTURE_AGE = 50; ///< maximum age of a gesture before disallowing its use in algorithm -const unsigned int DEFAULT_PREDICTION_INTERPOLATION = 0; ///< how much to interpolate pan position and displacement from last vsync time +const int MAX_GESTURE_AGE = 50; ///< maximum age of a gesture before disallowing its use in algorithm TODO: Possibly make this configurable. +const float ACCELERATION_THRESHOLD = 0.1f; ///< minimum pan velocity change to trigger dynamic change of prediction amount +const unsigned int DEFAULT_PREDICTION_INTERPOLATION = 5; ///< how much to interpolate pan position and displacement from last vsync time (in milliseconds) +const unsigned int DEFAULT_MAX_PREDICTION_INTERPOLATION = 32; ///< the upper bound of the range to clamp the prediction interpolation +const unsigned int DEFAULT_MIN_PREDICTION_INTERPOLATION = 0; ///< the lower bound of the range to clamp the prediction interpolation +const unsigned int DEFAULT_PREDICTION_INTERPOLATION_ADJUSTMENT = 2; ///< the amount of prediction interpolation to adjust (in milliseconds) each time when pan velocity changes +const float DEFAULT_SMOOTHING_AMOUNT = 0.25f; ///< how much to interpolate pan position and displacement from last vsync time } // unnamed namespace -const PanGesture::PredictionMode PanGesture::DEFAULT_PREDICTION_MODE = PanGesture::AVERAGE; -const int PanGesture::NUM_PREDICTION_MODES = PanGesture::PREDICTION_2 + 1; +const PanGesture::PredictionMode PanGesture::DEFAULT_PREDICTION_MODE = PanGesture::PREDICTION_NONE; +const int PanGesture::NUM_PREDICTION_MODES = PanGesture::PREDICTION_1 + 1; + +const PanGesture::SmoothingMode PanGesture::DEFAULT_SMOOTHING_MODE = PanGesture::SMOOTHING_LAST_VALUE; +const int PanGesture::NUM_SMOOTHING_MODES = PanGesture::SMOOTHING_LAST_VALUE + 1; PanGesture* PanGesture::New() { @@ -73,28 +83,12 @@ void PanGesture::RemoveOldHistory(PanInfoHistory& panHistory, unsigned int curre iter = panHistory.erase(iter); endIter = panHistory.end(); } -} -void PanGesture::SimpleAverageAlgorithm(bool justStarted, PanInfo& gestureOut, unsigned int lastVSyncTime) -{ - if( mInGesture ) + // dont want more than 5 previous predictions for smoothing + iter = mPredictionHistory.begin(); + while( mPredictionHistory.size() > 1 && iter != mPredictionHistory.end() ) { - if( !justStarted ) - { - gestureOut.screen.position += mLastEventGesture.screen.position; - gestureOut.local.position += mLastEventGesture.local.position; - gestureOut.screen.position *= 0.5f; - gestureOut.local.position *= 0.5f; - // make current displacement relative to previous update-frame now. - gestureOut.screen.displacement = gestureOut.screen.position - mLastEventGesture.screen.position; - gestureOut.local.displacement = gestureOut.local.position - mLastEventGesture.local.position; - // calculate velocity relative to previous update-frame - unsigned int timeDiff( lastVSyncTime - mLastEventGesture.time ); - gestureOut.screen.velocity = gestureOut.screen.displacement / timeDiff; - gestureOut.local.velocity = gestureOut.local.displacement / timeDiff; - } - - gestureOut.time = lastVSyncTime; + iter = mPredictionHistory.erase(iter); } } @@ -112,88 +106,25 @@ void PanGesture::PredictiveAlgorithm1(int eventsThisFrame, PanInfo& gestureOut, PanInfoHistoryIter iter = panHistory.begin(); Vector2 screenVelocity = gestureOut.screen.velocity; Vector2 localVelocity = gestureOut.local.velocity; + Vector2 screenDisplacement = gestureOut.screen.displacement; + Vector2 localDisplacement = gestureOut.local.displacement; bool havePreviousAcceleration = false; bool previousVelocity = false; float previousAccel = 0.0f; unsigned int lastTime(0); - while( iter != endIter ) + + unsigned int interpolationTime = lastVSyncTime + mCurrentPredictionAmount; + + if( interpolationTime > gestureOut.time ) // Guard against the rare case when gestureOut.time > (lastVSyncTime + mCurrentPredictionAmount) { - PanInfo currentGesture = *iter; - if( !previousVelocity ) - { - // not yet set a previous velocity - screenVelocity = currentGesture.screen.velocity; - previousVelocity = true; - lastTime = currentGesture.time; - ++iter; - continue; - } - float velMag = currentGesture.screen.velocity.Length(); - float velDiff = velMag - screenVelocity.Length(); - float acceleration = 0.0f; - float time = (float)(currentGesture.time - lastTime); - if( time > Math::MACHINE_EPSILON_1 ) - { - acceleration = velDiff / time; - } - float interpolationTime = (float)((int)lastVSyncTime - (int)currentGesture.time); - float newVelMag = 0.0f; - if( !havePreviousAcceleration ) - { - newVelMag = velMag + (acceleration * interpolationTime); - havePreviousAcceleration = true; - } - else - { - newVelMag = velMag + (((acceleration + previousAccel) * 0.5f) * interpolationTime); - } - float velMod = 1.0f; - if( velMag > Math::MACHINE_EPSILON_1 ) - { - velMod = newVelMag / velMag; - } - gestureOut.screen.velocity = currentGesture.screen.velocity * velMod; - gestureOut.local.velocity = currentGesture.local.velocity * velMod; - screenVelocity = currentGesture.screen.velocity; - localVelocity = currentGesture.local.velocity; - previousAccel = acceleration; - ++iter; + interpolationTime -= gestureOut.time; } - // gestureOut's position is currently equal to the last event's position and its displacement is equal to last frame's total displacement - // add interpolated distance and position to current - float interpolationTime = (float)((int)lastVSyncTime - (int)gestureOut.time); - // work out interpolated velocity - gestureOut.screen.displacement = (gestureOut.screen.velocity * interpolationTime); - gestureOut.local.displacement = (gestureOut.local.velocity * interpolationTime); - gestureOut.screen.position += gestureOut.screen.displacement; - gestureOut.local.position += gestureOut.local.displacement; - gestureOut.time += (lastVSyncTime - gestureOut.time); -} - -void PanGesture::PredictiveAlgorithm2(int eventsThisFrame, PanInfo& gestureOut, PanInfoHistory& panHistory, unsigned int lastVSyncTime, unsigned int nextVSyncTime) -{ - // TODO - adapt PredictiveAlgorithm1 with better smoothing, still under development - RemoveOldHistory(panHistory, lastVSyncTime, MAX_GESTURE_AGE, 0); - size_t panHistorySize = panHistory.size(); - if( panHistorySize == 0 ) + else { - // cant do any prediction without a history - return; + interpolationTime = 0u; } - PanInfoHistoryConstIter endIter = panHistory.end(); - PanInfoHistoryIter iter = panHistory.begin(); - Vector2 screenVelocity = gestureOut.screen.velocity; - Vector2 localVelocity = gestureOut.local.velocity; - Vector2 screenDisplacement = gestureOut.screen.displacement; - Vector2 localDisplacement = gestureOut.local.displacement; - - bool havePreviousAcceleration = false; - bool previousVelocity = false; - float previousAccel = 0.0f; - unsigned int lastTime(0); - unsigned int interpolationTime = (lastVSyncTime + mPredictionAmount) - gestureOut.time; while( iter != endIter ) { PanInfo currentGesture = *iter; @@ -210,21 +141,27 @@ void PanGesture::PredictiveAlgorithm2(int eventsThisFrame, PanInfo& gestureOut, float velMag = currentGesture.screen.velocity.Length(); float velDiff = velMag - screenVelocity.Length(); float acceleration = 0.0f; - float time = (float)(currentGesture.time - lastTime); + + float time(0.f); + if (currentGesture.time > lastTime) // Guard against invalid timestamps + { + time = static_cast( currentGesture.time - lastTime ); + } if( time > Math::MACHINE_EPSILON_1 ) { acceleration = velDiff / time; } + float newVelMag = 0.0f; - int currentInterpolation = (lastVSyncTime + mPredictionAmount) - currentGesture.time; + int currentInterpolation = interpolationTime; if( !havePreviousAcceleration ) { - newVelMag = velMag + (acceleration * currentInterpolation); + newVelMag = velMag; havePreviousAcceleration = true; } else { - newVelMag = velMag + (((acceleration * (1.0f - previousValueWeight)) + (previousAccel * previousValueWeight)) * interpolationTime); + newVelMag = velMag + (((acceleration * (1.0f - previousValueWeight)) + (previousAccel * previousValueWeight)) * currentInterpolation); } float velMod = 1.0f; if( velMag > Math::MACHINE_EPSILON_1 ) @@ -243,145 +180,372 @@ void PanGesture::PredictiveAlgorithm2(int eventsThisFrame, PanInfo& gestureOut, // gestureOut's position is currently equal to the last event's position and its displacement is equal to last frame's total displacement // add interpolated distance and position to current // work out interpolated velocity - gestureOut.screen.displacement = screenDisplacement; - gestureOut.local.displacement = localDisplacement; gestureOut.screen.position = (gestureOut.screen.position - gestureOut.screen.displacement) + screenDisplacement; gestureOut.local.position = (gestureOut.local.position - gestureOut.local.displacement) + localDisplacement; + gestureOut.screen.displacement = screenDisplacement; + gestureOut.local.displacement = localDisplacement; gestureOut.time += interpolationTime; } -bool PanGesture::UpdateProperties( unsigned int lastVSyncTime, unsigned int nextVSyncTime ) +void PanGesture::SmoothingAlgorithm1(bool justStarted, PanInfo& gestureOut, unsigned int lastVSyncTime) { - if( !mInGesture ) + if( justStarted ) { - // clear current pan history - mPanHistory.clear(); + gestureOut.screen.displacement = Vector2::ZERO; + gestureOut.screen.velocity = Vector2::ZERO; + gestureOut.local.displacement = Vector2::ZERO; + gestureOut.local.velocity = Vector2::ZERO; + } + else + { + gestureOut.screen.position -= (gestureOut.screen.position - mLastGesture.screen.position) * 0.5f * (1.0f - mSmoothingAmount); + gestureOut.local.position -= (gestureOut.local.position - mLastGesture.local.position) * 0.5f * (1.0f - mSmoothingAmount); + // make current displacement relative to previous update-frame now. + gestureOut.screen.displacement = gestureOut.screen.position - mLastGesture.screen.position; + gestureOut.local.displacement = gestureOut.local.position - mLastGesture.local.position; + // calculate velocity relative to previous update-frame + float timeDiff( gestureOut.time - mLastGesture.time ); + gestureOut.screen.velocity = gestureOut.screen.displacement / timeDiff; + gestureOut.local.velocity = gestureOut.local.displacement / timeDiff; } +} - // create an event for this frame - bool justStarted ( false ); - bool justFinished ( false ); - bool eventFound( false ); +void PanGesture::SmoothingAlgorithm2(bool justStarted, PanInfo& gestureOut, unsigned int lastVSyncTime) +{ + // push back result + mPredictionHistory.push_back(gestureOut); + + // now smooth current pan event + PanInfoHistoryConstIter endIter = mPredictionHistory.end() - 1; + PanInfoHistoryIter iter = mPredictionHistory.begin(); + + float distanceMod = 1.0f; + float weight = 0.8f; + while( iter != endIter ) + { + PanInfo currentGesture = *iter; + float newDistanceMod = currentGesture.screen.displacement.Length() / gestureOut.screen.displacement.Length(); + distanceMod = ((distanceMod * weight) + (newDistanceMod * (1.0f - weight))); + weight -= 0.15f; + ++iter; + } + gestureOut.screen.position -= gestureOut.screen.displacement; + gestureOut.local.position -= gestureOut.local.displacement; + gestureOut.screen.displacement *= distanceMod; + gestureOut.local.displacement *= distanceMod; + gestureOut.screen.position += gestureOut.screen.displacement; + gestureOut.local.position += gestureOut.local.displacement; +} - // Not going through array from the beginning, using it as a circular buffer and only using unread - // values. - int eventsThisFrame = 0; +bool PanGesture::ReadGestures( FrameGestureInfo& info, unsigned int currentTimestamp ) +{ + unsigned int previousReadPosition = 0; + bool eventFound = false; + info.frameGesture = mLastUnmodifiedGesture; - // create PanInfo to pass into prediction method - PanInfo nextGesture = mEventGesture; - // add new gestures and work out one full gesture for the frame - while(mReadPosition != mWritePosition) + while( mReadPosition != mWritePosition ) { // Copy the gesture first - PanInfo currentGesture(mGestures[mReadPosition]); + PanInfo currentGesture( mGestures[mReadPosition] ); if( mProfiling ) { - mProfiling->mRawData.push_back( PanGestureProfiling::Position( currentGesture.time, currentGesture.screen.position ) ); + mProfiling->mRawData.push_back( PanGestureProfiling::Position( currentGesture.time, currentGesture.screen.position, currentGesture.screen.displacement, currentGesture.screen.velocity, currentGesture.state ) ); } - nextGesture.local.position = currentGesture.local.position; - nextGesture.local.velocity = currentGesture.local.velocity; - nextGesture.screen.position = currentGesture.screen.position; - nextGesture.screen.velocity = currentGesture.screen.velocity; + info.frameGesture.local.position = currentGesture.local.position; + info.frameGesture.local.velocity = currentGesture.local.velocity; + info.frameGesture.screen.position = currentGesture.screen.position; + info.frameGesture.screen.velocity = currentGesture.screen.velocity; + + if( info.eventsThisFrame > 0 ) + { + info.acceleration = currentGesture.screen.velocity.Length() - mGestures[previousReadPosition].screen.velocity.Length(); + } + if( !eventFound ) { - nextGesture.local.displacement = currentGesture.local.displacement; - nextGesture.screen.displacement = currentGesture.screen.displacement; + info.frameGesture.local.displacement = currentGesture.local.displacement; + info.frameGesture.screen.displacement = currentGesture.screen.displacement; + eventFound = true; } else { - nextGesture.local.displacement += currentGesture.local.displacement; - nextGesture.screen.displacement += currentGesture.screen.displacement; + info.frameGesture.local.displacement += currentGesture.local.displacement; + info.frameGesture.screen.displacement += currentGesture.screen.displacement; } - eventFound = true; - nextGesture.time = currentGesture.time; + info.frameGesture.time = currentGesture.time; // add event to history - mPanHistory.push_back(currentGesture); - justStarted |= (currentGesture.state == Gesture::Started); + mPanHistory.push_back( currentGesture ); if( currentGesture.state == Gesture::Started ) { - justStarted = true; + info.justStarted = true; // clear just finished as we have started new pan - justFinished = false; + info.justFinished = false; } - justFinished |= (currentGesture.state == Gesture::Finished || currentGesture.state == Gesture::Cancelled); + info.justFinished |= ( currentGesture.state == Gesture::Finished || currentGesture.state == Gesture::Cancelled ); // Update our read position. - ++eventsThisFrame; + previousReadPosition = mReadPosition; + ++info.eventsThisFrame; ++mReadPosition; mReadPosition %= PAN_GESTURE_HISTORY; } - // set nextGesture to last gesture so it's position is correct and velocity is same as last frame - mEventGesture = nextGesture; + // This code does not determine if the data will be used. + return false; +} + +bool PanGesture::ReadAndResampleGestures( FrameGestureInfo& info, unsigned int currentTimestamp ) +{ + PanInfo lastReadGesture; + while( mReadPosition != mWritePosition ) + { + // Copy the gesture first + lastReadGesture = mGestures[mReadPosition]; + if( mProfiling ) + { + mProfiling->mRawData.push_back( PanGestureProfiling::Position( lastReadGesture.time, lastReadGesture.screen.position, + lastReadGesture.screen.displacement, lastReadGesture.screen.velocity, lastReadGesture.state ) ); + } + + info.frameGesture.screen.position += lastReadGesture.screen.position; + info.frameGesture.local.position += lastReadGesture.local.position; + info.frameGesture.screen.velocity += lastReadGesture.screen.velocity; + info.frameGesture.local.velocity += lastReadGesture.local.velocity; + + if( lastReadGesture.state == Gesture::Started ) + { + // Clear just finished as we have started new pan. + info.justFinished = false; + info.justStarted = true; + } + else + { + info.justFinished |= ( lastReadGesture.state == Gesture::Finished || lastReadGesture.state == Gesture::Cancelled ); + } + + // Add event to history + mPanHistory.push_back( lastReadGesture ); + + // Update our read position. + ++info.eventsThisFrame; + ++mReadPosition; + mReadPosition %= PAN_GESTURE_HISTORY; + } + + bool updateProperties = false; + if( info.eventsThisFrame > 0 ) + { + // Some events were read this frame. + mTargetGesture = lastReadGesture; + + if( info.eventsThisFrame > 1 ) + { + info.frameGesture.screen.position /= info.eventsThisFrame; + info.frameGesture.local.position /= info.eventsThisFrame; + info.frameGesture.screen.velocity /= info.eventsThisFrame; + info.frameGesture.local.velocity /= info.eventsThisFrame; + + info.frameGesture.screen.displacement = info.frameGesture.screen.position - mLastGesture.screen.position; + info.frameGesture.local.displacement = info.frameGesture.local.position - mLastGesture.local.position; + + mNotAtTarget = true; + } + else + { + info.frameGesture.screen.displacement = lastReadGesture.screen.displacement; + info.frameGesture.local.displacement = lastReadGesture.local.displacement; + } + + info.frameGesture.time = currentTimestamp; + + updateProperties = true; + } + else + { + // 0 Events this frame. + if( mNotAtTarget ) + { + mNotAtTarget = false; + info.frameGesture = mTargetGesture; + updateProperties = true; + } + else + { + info.frameGesture = mLastGesture; + } + } + + return updateProperties; +} - mInGesture |= justStarted; +bool PanGesture::UpdateProperties( unsigned int lastVSyncTime, unsigned int nextVSyncTime ) +{ + if( !mInGesture ) + { + // clear current pan history + mPanHistory.clear(); + mPredictionHistory.clear(); + } + FrameGestureInfo frameInfo; bool updateProperties = false; - if ( mInGesture ) + // Read input data. + // If we are using a form of prediction, read all the input as-is. + if( mPredictionMode != PREDICTION_NONE ) + { + // Read input required for prediction algorithms. + updateProperties = ReadGestures( frameInfo, lastVSyncTime ); + } + else + { + // Read and resample input. + updateProperties = ReadAndResampleGestures( frameInfo, lastVSyncTime ); + } + + PanInfo frameGesture = frameInfo.frameGesture; + mLastUnmodifiedGesture = frameGesture; + + // Process input data. + mInGesture |= frameInfo.justStarted; + if( mInGesture ) { + // Profiling. if( mProfiling ) { - mProfiling->mLatestData.push_back( PanGestureProfiling::Position( lastVSyncTime, mEventGesture.screen.position ) ); + mProfiling->mLatestData.push_back( PanGestureProfiling::Position( lastVSyncTime, frameGesture.screen.position, + frameGesture.screen.displacement, frameGesture.screen.velocity, frameGesture.state ) ); } + // Perform prediction. switch( mPredictionMode ) { - case NONE: + case PREDICTION_NONE: { - updateProperties = eventFound; break; } - case AVERAGE: + case PREDICTION_1: { - SimpleAverageAlgorithm(justStarted, nextGesture, lastVSyncTime); - // make latest gesture equal to current gesture after averaging + // Dynamically change the prediction amount according to the pan velocity acceleration. + if( !frameInfo.justStarted ) + { + if( frameInfo.eventsThisFrame <= 1 ) + { + frameInfo.acceleration = frameGesture.screen.velocity.Length() - mLastUnmodifiedGesture.screen.velocity.Length(); + } + + // Ignore tiny velocity fluctuation to avoid unnecessary prediction amount change + if( fabsf( frameInfo.acceleration ) > ACCELERATION_THRESHOLD ) + { + mCurrentPredictionAmount += mPredictionAmountAdjustment * ( frameInfo.acceleration > Math::MACHINE_EPSILON_0 ? 1.0f : -1.0f ); + if( mCurrentPredictionAmount > mMaxPredictionAmount + mPredictionAmountAdjustment ) // Guard against unsigned int overflow + { + mCurrentPredictionAmount = 0; + } + } + } + else + { + mCurrentPredictionAmount = mPredictionAmount; // Reset the prediction amount for each new gesture + } + + mCurrentPredictionAmount = std::max( mMinPredictionAmount, std::min( mCurrentPredictionAmount, mMaxPredictionAmount ) ); + + // Calculate the delta of positions before the prediction + Vector2 deltaPosition = frameGesture.screen.position - mLastUnmodifiedGesture.screen.position; + + // Make latest gesture equal to current gesture before interpolation + PredictiveAlgorithm1( frameInfo.eventsThisFrame, frameGesture, mPanHistory, lastVSyncTime, nextVSyncTime ); + + // Calculate the delta of positions after the prediction. + Vector2 deltaPredictedPosition = frameGesture.screen.position - mLastGesture.screen.position; + + // If the change in the prediction has a different sign than the change in the actual position, + // there is overshot (i.e. the current prediction is too large). Return the previous prediction + // to give the user's finger a chance to catch up with where we have panned to. + bool overshotXAxis = false; + bool overshotYAxis = false; + if( (deltaPosition.x > Math::MACHINE_EPSILON_0 && deltaPredictedPosition.x < Math::MACHINE_EPSILON_0 ) + || (deltaPosition.x < Math::MACHINE_EPSILON_0 && deltaPredictedPosition.x > Math::MACHINE_EPSILON_0 ) ) + { + overshotXAxis = true; + frameGesture.screen.position.x = mLastGesture.screen.position.x; + } + + if( (deltaPosition.y > Math::MACHINE_EPSILON_0 && deltaPredictedPosition.y < Math::MACHINE_EPSILON_0 ) + || (deltaPosition.y < Math::MACHINE_EPSILON_0 && deltaPredictedPosition.y > Math::MACHINE_EPSILON_0 ) ) + { + overshotYAxis = true; + frameGesture.screen.position.y = mLastGesture.screen.position.y; + } + + // If there is overshot in one axis, reduce the possible overshot in the other axis, + // and reduce the prediction amount so that it doesn't overshoot as easily next time. + if(overshotXAxis || overshotYAxis) + { + mCurrentPredictionAmount -= mPredictionAmountAdjustment; + if( mCurrentPredictionAmount > mMaxPredictionAmount + mPredictionAmountAdjustment ) // Guard against unsigned int overflow + { + mCurrentPredictionAmount = 0; + } + mCurrentPredictionAmount = std::max( mMinPredictionAmount, std::min( mCurrentPredictionAmount, mMaxPredictionAmount ) ); + + if( overshotXAxis && !overshotYAxis ) + { + frameGesture.screen.position.y = ( mLastGesture.screen.position.y + frameGesture.screen.position.y ) * 0.5f; + } + + if( overshotYAxis && !overshotXAxis ) + { + frameGesture.screen.position.x = ( mLastGesture.screen.position.x + frameGesture.screen.position.x ) * 0.5f; + } + } + updateProperties = true; break; } - case PREDICTION_1: + } + + // Perform smoothing. + switch( mSmoothingMode ) + { + case SMOOTHING_NONE: { - // make latest gesture equal to current gesture before interpolation - PredictiveAlgorithm1(eventsThisFrame, nextGesture, mPanHistory, lastVSyncTime, nextVSyncTime); - updateProperties = true; + // No smoothing break; } - case PREDICTION_2: + case SMOOTHING_LAST_VALUE: { - // make latest gesture equal to current gesture before interpolation - PredictiveAlgorithm2(eventsThisFrame, nextGesture, mPanHistory, lastVSyncTime, nextVSyncTime); - updateProperties = true; + SmoothingAlgorithm1( frameInfo.justStarted, frameGesture, lastVSyncTime ); break; } } - // always keep latest gesture up to date with event gesture - mLatestGesture = nextGesture; - if( updateProperties ) { // only update properties if event received // set latest gesture to raw pan info with unchanged time - mPanning.Set( mInGesture & !justFinished ); - mScreenPosition.Set( nextGesture.screen.position ); - mScreenDisplacement.Set( nextGesture.screen.displacement ); - mScreenVelocity.Set( nextGesture.screen.velocity ); - mLocalPosition.Set( nextGesture.local.position ); - mLocalDisplacement.Set( nextGesture.local.displacement ); - mLocalVelocity.Set( nextGesture.local.velocity ); + mPanning.Set( mInGesture & !frameInfo.justFinished ); + mScreenPosition.Set( frameGesture.screen.position ); + mScreenDisplacement.Set( frameGesture.screen.displacement ); + mScreenVelocity.Set( frameGesture.screen.velocity ); + mLocalPosition.Set( frameGesture.local.position ); + mLocalDisplacement.Set( frameGesture.local.displacement ); + mLocalVelocity.Set( frameGesture.local.velocity ); } if( mProfiling ) { - mProfiling->mAveragedData.push_back( PanGestureProfiling::Position( nextGesture.time, nextGesture.screen.position ) ); + mProfiling->mAveragedData.push_back( PanGestureProfiling::Position( frameGesture.time, frameGesture.screen.position, + frameGesture.screen.displacement, frameGesture.screen.velocity, frameGesture.state ) ); } } - mLastEventGesture = mEventGesture; - mInGesture &= ~justFinished; + mLastGesture = frameGesture; - if( mProfiling && justFinished ) + mInGesture &= ~frameInfo.justFinished; + if( mProfiling && frameInfo.justFinished ) { mProfiling->PrintData(); mProfiling->ClearData(); @@ -435,6 +599,31 @@ void PanGesture::SetPredictionAmount(unsigned int amount) mPredictionAmount = amount; } +void PanGesture::SetMaximumPredictionAmount(unsigned int amount) +{ + mMaxPredictionAmount = amount; +} + +void PanGesture::SetMinimumPredictionAmount(unsigned int amount) +{ + mMinPredictionAmount = amount; +} + +void PanGesture::SetPredictionAmountAdjustment(unsigned int amount) +{ + mPredictionAmountAdjustment = amount; +} + +void PanGesture::SetSmoothingMode(SmoothingMode mode) +{ + mSmoothingMode = mode; +} + +void PanGesture::SetSmoothingAmount(float amount) +{ + mSmoothingAmount = amount; +} + void PanGesture::EnableProfiling() { if( !mProfiling ) @@ -456,13 +645,21 @@ PanGesture::PanGesture() : mGestures(), mWritePosition( 0 ), mReadPosition( 0 ), + mNotAtTarget( false ), mInGesture( false ), - mPredictionMode(DEFAULT_PREDICTION_MODE), - mPredictionAmount(DEFAULT_PREDICTION_INTERPOLATION), + mPredictionMode( DEFAULT_PREDICTION_MODE ), + mPredictionAmount( DEFAULT_PREDICTION_INTERPOLATION ), + mCurrentPredictionAmount( DEFAULT_PREDICTION_INTERPOLATION ), + mMaxPredictionAmount( DEFAULT_MAX_PREDICTION_INTERPOLATION ), + mMinPredictionAmount( DEFAULT_MIN_PREDICTION_INTERPOLATION ), + mPredictionAmountAdjustment( DEFAULT_PREDICTION_INTERPOLATION_ADJUSTMENT ), + mSmoothingMode( DEFAULT_SMOOTHING_MODE ), + mSmoothingAmount( DEFAULT_SMOOTHING_AMOUNT ), mProfiling( NULL ) { } + } // namespace SceneGraph } // namespace Internal