2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
24 #include <dali/internal/update/gestures/pan-gesture-profiling.h>
36 const int MAX_GESTURE_AGE = 50; ///< maximum age of a gesture before disallowing its use in algorithm
37 const unsigned int DEFAULT_PREDICTION_INTERPOLATION = 0; ///< how much to interpolate pan position and displacement from last vsync time
38 const float DEFAULT_SMOOTHING_AMOUNT = 1.0f; ///< how much to interpolate pan position and displacement from last vsync time
39 } // unnamed namespace
41 const PanGesture::PredictionMode PanGesture::DEFAULT_PREDICTION_MODE = PanGesture::PREDICTION_NONE;
42 const int PanGesture::NUM_PREDICTION_MODES = PanGesture::PREDICTION_1 + 1;
44 const PanGesture::SmoothingMode PanGesture::DEFAULT_SMOOTHING_MODE = PanGesture::SMOOTHING_LAST_VALUE;
45 const int PanGesture::NUM_SMOOTHING_MODES = PanGesture::SMOOTHING_LAST_VALUE + 1;
47 PanGesture* PanGesture::New()
49 return new PanGesture();
52 PanGesture::~PanGesture()
57 void PanGesture::AddGesture( const Dali::PanGesture& gesture )
59 mGestures[ mWritePosition ] = gesture;
61 // Update our write position.
63 mWritePosition %= PAN_GESTURE_HISTORY;
66 void PanGesture::RemoveOldHistory(PanInfoHistory& panHistory, unsigned int currentTime, unsigned int maxAge, unsigned int minEvents)
68 PanInfoHistoryConstIter endIter = panHistory.end();
69 PanInfoHistoryIter iter = panHistory.begin();
70 while( iter != endIter && panHistory.size() > minEvents)
72 PanInfo currentGesture = *iter;
73 if( currentTime < currentGesture.time + maxAge )
77 iter = panHistory.erase(iter);
78 endIter = panHistory.end();
81 // dont want more than 5 previous predictions for smoothing
82 iter = mPredictionHistory.begin();
83 while( mPredictionHistory.size() > 1 && iter != mPredictionHistory.end() )
85 iter = mPredictionHistory.erase(iter);
89 void PanGesture::PredictiveAlgorithm1(int eventsThisFrame, PanInfo& gestureOut, PanInfoHistory& panHistory, unsigned int lastVSyncTime, unsigned int nextVSyncTime)
91 RemoveOldHistory(panHistory, lastVSyncTime, MAX_GESTURE_AGE, 0);
92 size_t panHistorySize = panHistory.size();
93 if( panHistorySize == 0 )
95 // cant do any prediction without a history
99 PanInfoHistoryConstIter endIter = panHistory.end();
100 PanInfoHistoryIter iter = panHistory.begin();
101 Vector2 screenVelocity = gestureOut.screen.velocity;
102 Vector2 localVelocity = gestureOut.local.velocity;
103 Vector2 screenDisplacement = gestureOut.screen.displacement;
104 Vector2 localDisplacement = gestureOut.local.displacement;
106 bool havePreviousAcceleration = false;
107 bool previousVelocity = false;
108 float previousAccel = 0.0f;
109 unsigned int lastTime(0);
110 unsigned int interpolationTime = (lastVSyncTime + mPredictionAmount) - gestureOut.time;
111 while( iter != endIter )
113 PanInfo currentGesture = *iter;
114 if( !previousVelocity )
116 // not yet set a previous velocity
117 screenVelocity = currentGesture.screen.velocity;
118 previousVelocity = true;
119 lastTime = currentGesture.time;
123 float previousValueWeight = (float)(MAX_GESTURE_AGE - (lastVSyncTime - lastTime)) / (float)MAX_GESTURE_AGE;
124 float velMag = currentGesture.screen.velocity.Length();
125 float velDiff = velMag - screenVelocity.Length();
126 float acceleration = 0.0f;
127 float time = (float)(currentGesture.time - lastTime);
128 if( time > Math::MACHINE_EPSILON_1 )
130 acceleration = velDiff / time;
132 float newVelMag = 0.0f;
133 int currentInterpolation = interpolationTime; //(lastVSyncTime + mPredictionAmount) - currentGesture.time;
134 if( !havePreviousAcceleration )
137 havePreviousAcceleration = true;
141 newVelMag = velMag + (((acceleration * (1.0f - previousValueWeight)) + (previousAccel * previousValueWeight)) * currentInterpolation);
144 if( velMag > Math::MACHINE_EPSILON_1 )
146 velMod = newVelMag / velMag;
148 gestureOut.screen.velocity = currentGesture.screen.velocity * velMod;
149 gestureOut.local.velocity = currentGesture.local.velocity * velMod;
150 screenDisplacement = gestureOut.screen.displacement + (gestureOut.screen.velocity * interpolationTime);
151 localDisplacement = gestureOut.local.displacement + (gestureOut.local.velocity * interpolationTime);
152 screenVelocity = currentGesture.screen.velocity;
153 localVelocity = currentGesture.local.velocity;
154 previousAccel = acceleration;
157 // gestureOut's position is currently equal to the last event's position and its displacement is equal to last frame's total displacement
158 // add interpolated distance and position to current
159 // work out interpolated velocity
160 gestureOut.screen.position = (gestureOut.screen.position - gestureOut.screen.displacement) + screenDisplacement;
161 gestureOut.local.position = (gestureOut.local.position - gestureOut.local.displacement) + localDisplacement;
162 gestureOut.screen.displacement = screenDisplacement;
163 gestureOut.local.displacement = localDisplacement;
164 gestureOut.time += interpolationTime;
167 void PanGesture::SmoothingAlgorithm1(bool justStarted, PanInfo& gestureOut, unsigned int lastVSyncTime)
171 gestureOut.screen.position -= (gestureOut.screen.position - mLastGesture.screen.position) * 0.5f * (1.0f - mSmoothingAmount);
172 gestureOut.local.position -= (gestureOut.local.position - mLastGesture.local.position) * 0.5f * (1.0f - mSmoothingAmount);
173 // make current displacement relative to previous update-frame now.
174 gestureOut.screen.displacement = gestureOut.screen.position - mLastGesture.screen.position;
175 gestureOut.local.displacement = gestureOut.local.position - mLastGesture.local.position;
176 // calculate velocity relative to previous update-frame
177 unsigned int timeDiff( gestureOut.time - mLastGesture.time );
178 gestureOut.screen.velocity = gestureOut.screen.displacement / timeDiff;
179 gestureOut.local.velocity = gestureOut.local.displacement / timeDiff;
183 void PanGesture::SmoothingAlgorithm2(bool justStarted, PanInfo& gestureOut, unsigned int lastVSyncTime)
186 mPredictionHistory.push_back(gestureOut);
188 // now smooth current pan event
189 PanInfoHistoryConstIter endIter = mPredictionHistory.end() - 1;
190 PanInfoHistoryIter iter = mPredictionHistory.begin();
192 float distanceMod = 1.0f;
194 while( iter != endIter )
196 PanInfo currentGesture = *iter;
197 float newDistanceMod = currentGesture.screen.displacement.Length() / gestureOut.screen.displacement.Length();
198 distanceMod = ((distanceMod * weight) + (newDistanceMod * (1.0f - weight)));
202 gestureOut.screen.position -= gestureOut.screen.displacement;
203 gestureOut.local.position -= gestureOut.local.displacement;
204 gestureOut.screen.displacement *= distanceMod;
205 gestureOut.local.displacement *= distanceMod;
206 gestureOut.screen.position += gestureOut.screen.displacement;
207 gestureOut.local.position += gestureOut.local.displacement;
210 bool PanGesture::UpdateProperties( unsigned int lastVSyncTime, unsigned int nextVSyncTime )
214 // clear current pan history
216 mPredictionHistory.clear();
219 // create an event for this frame
220 bool justStarted ( false );
221 bool justFinished ( false );
222 bool eventFound( false );
224 // Not going through array from the beginning, using it as a circular buffer and only using unread
226 int eventsThisFrame = 0;
228 // create PanInfo to pass into prediction method
229 mLastEventGesture = mEventGesture;
230 mLastGesture = mLatestGesture;
231 // add new gestures and work out one full gesture for the frame
232 while(mReadPosition != mWritePosition)
234 // Copy the gesture first
235 PanInfo currentGesture(mGestures[mReadPosition]);
239 mProfiling->mRawData.push_back( PanGestureProfiling::Position( currentGesture.time, currentGesture.screen.position ) );
241 mEventGesture.local.position = currentGesture.local.position;
242 mEventGesture.local.velocity = currentGesture.local.velocity;
243 mEventGesture.screen.position = currentGesture.screen.position;
244 mEventGesture.screen.velocity = currentGesture.screen.velocity;
247 mEventGesture.local.displacement = currentGesture.local.displacement;
248 mEventGesture.screen.displacement = currentGesture.screen.displacement;
252 mEventGesture.local.displacement += currentGesture.local.displacement;
253 mEventGesture.screen.displacement += currentGesture.screen.displacement;
256 mEventGesture.time = currentGesture.time;
258 // add event to history
259 mPanHistory.push_back(currentGesture);
260 if( currentGesture.state == Gesture::Started )
263 // clear just finished as we have started new pan
264 justFinished = false;
266 justFinished |= (currentGesture.state == Gesture::Finished || currentGesture.state == Gesture::Cancelled);
268 // Update our read position.
271 mReadPosition %= PAN_GESTURE_HISTORY;
273 mLatestGesture = mEventGesture;
275 mInGesture |= justStarted;
277 bool updateProperties = false;
283 mProfiling->mLatestData.push_back( PanGestureProfiling::Position( lastVSyncTime, mEventGesture.screen.position ) );
286 switch( mPredictionMode )
288 case PREDICTION_NONE:
290 updateProperties = eventFound;
291 // dont want event time
292 unsigned int time = mLastGesture.time;
293 mLastGesture = mLastEventGesture;
294 mLastGesture.time = time;
295 mLatestGesture.time = lastVSyncTime;
300 // make latest gesture equal to current gesture before interpolation
301 PredictiveAlgorithm1(eventsThisFrame, mLatestGesture, mPanHistory, lastVSyncTime, nextVSyncTime);
302 updateProperties = true;
307 switch( mSmoothingMode )
314 case SMOOTHING_LAST_VALUE:
316 SmoothingAlgorithm1(justStarted, mLatestGesture, lastVSyncTime);
321 if( updateProperties )
323 // only update properties if event received
324 // set latest gesture to raw pan info with unchanged time
325 mPanning.Set( mInGesture & !justFinished );
326 mScreenPosition.Set( mLatestGesture.screen.position );
327 mScreenDisplacement.Set( mLatestGesture.screen.displacement );
328 mScreenVelocity.Set( mLatestGesture.screen.velocity );
329 mLocalPosition.Set( mLatestGesture.local.position );
330 mLocalDisplacement.Set( mLatestGesture.local.displacement );
331 mLocalVelocity.Set( mLatestGesture.local.velocity );
336 mProfiling->mAveragedData.push_back( PanGestureProfiling::Position( mLatestGesture.time, mLatestGesture.screen.position ) );
340 mInGesture &= ~justFinished;
342 if( mProfiling && justFinished )
344 mProfiling->PrintData();
345 mProfiling->ClearData();
348 return updateProperties;
351 const GesturePropertyBool& PanGesture::GetPanningProperty() const
356 const GesturePropertyVector2& PanGesture::GetScreenPositionProperty() const
358 return mScreenPosition;
361 const GesturePropertyVector2& PanGesture::GetScreenVelocityProperty() const
363 return mScreenVelocity;
366 const GesturePropertyVector2& PanGesture::GetScreenDisplacementProperty() const
368 return mScreenDisplacement;
371 const GesturePropertyVector2& PanGesture::GetLocalPositionProperty() const
373 return mLocalPosition;
376 const GesturePropertyVector2& PanGesture::GetLocalDisplacementProperty() const
378 return mLocalDisplacement;
381 const GesturePropertyVector2& PanGesture::GetLocalVelocityProperty() const
383 return mLocalVelocity;
386 void PanGesture::SetPredictionMode(PredictionMode mode)
388 mPredictionMode = mode;
391 void PanGesture::SetPredictionAmount(unsigned int amount)
393 mPredictionAmount = amount;
396 void PanGesture::SetSmoothingMode(SmoothingMode mode)
398 mSmoothingMode = mode;
401 void PanGesture::SetSmoothingAmount(float amount)
403 mSmoothingAmount = amount;
406 void PanGesture::EnableProfiling()
410 mProfiling = new PanGestureProfiling();
414 void PanGesture::ResetDefaultProperties( BufferIndex updateBufferIndex )
416 mScreenPosition.Reset();
417 mScreenDisplacement.Reset();
418 mLocalPosition.Reset();
419 mLocalDisplacement.Reset();
423 PanGesture::PanGesture()
428 mPredictionMode(DEFAULT_PREDICTION_MODE),
429 mPredictionAmount(DEFAULT_PREDICTION_INTERPOLATION),
430 mSmoothingMode(DEFAULT_SMOOTHING_MODE),
431 mSmoothingAmount(DEFAULT_SMOOTHING_AMOUNT),
436 } // namespace SceneGraph
438 } // namespace Internal