Multitouch Game Loop Inertia Processing

By
Dave
Project
Published
21 Sep 2010 18:11
Last Modified
8 Dec 2012 16:21

In Part 1 I described a lightweight class to process general multitouch manipulations using a game-loop model in XNA.

A key aspect in bringing realism to a multitouch experience is the use of momentum and inertia. The Microsoft.Surface.Core.Manipulations.Affine2DInertiaProcessor provides this support in an event-driven model. In order to continue the approach of using a game-loop model, I needed to add linear and angular velocities, and expansion rates to my manipulation processor.

Changes in manipulator position occur relatively rarely in relation to the game loop frequency, hence calculating rates of change requires averaging these changes over time. The choice of duration and quantity of these time periods is somewhat subjective, and I settled on 5 samples averaged over a maximum of 200ms. Clearly this leads to a small latency between measured and actual velocities, however the smoothing effect is beneficial.

In order to visualise these rates, both for debbugging and to settle on suitable sampling settings, I added visual indicators of direction and magnitude, as shown below in Figure 1.

Multitouch manipulation

Figure 1. Visualising linear and angular velocities and expansion rates during multitouch manipulation.

With the addition of linear and angular velocities and expansion rates, I could now add a simple inertial processing component which uses these properties as input parameters. This inertial processor uses a simple deceleration algorithm, with configurable rates for translation, rotation, and expansion. The solution is demonstrated in the following video.

Video 1. Multitouch game loop inertia processing.

Note that for gestures such as a flick, where velcity increases rapidly, a time-weighted average may be more suitable for calculating the inertia processor's input parameters, and I'll investigate this at a later date.

Comments

By
Vidds
22 Oct 2010 13:51
Hi Dave,
Nice article. I have tried to use the Physiscs library but as mentioned it has limitations like scaling and Rotation of the items.Unlike the ScatterViewItems we are not able to scale or rotate the items. Is the Physics.SurfaceControls.dll updated to handle these if yes please let us know where we can find it. Thanks in advance.

Regards,
Vidds
By
Dave
29 Oct 2010 14:34
Hi Vidds,

Thanks for trying out the library! :) Supporting rotation and scaling in a physics-enabled manner is somewhat more complex than standard ScatterView behaviour, since it may not be possible to rotate or scale an item if it is colliding with another item which itself is fixed. That said, at least I now have the code for implementing the multitouch manipulation itself, which formed the basis of this article. It's not in there yet, but it's next on the list!

For posts relating to my physics-enabled ScatterView control for Surface, see http://drdave.co.uk/blog/archive/category/Surface-Physics.

Regards,
Dave
By
DarkNight
25 Nov 2013 12:29
Hi Dave

i managed to complete the manipulation part in a cross platform framework i am creating but i can't figure out how to do inertia. I mean how to calculate the initial velocity and how to affect it by deceleration and how Microsoft do it in the first place. I read the article inertia mechanism on MSDN but with no luck to understand it well. i don't want to create a very complex physics like yours just as simple as MS but cross platform with RAD Studio FireMonkey framework.

Best Regards,
DarkNight
By
Dave
27 Nov 2013 22:46
Hi DarkNight,

Sounds like you're almost there. For implementing inertia you need three things:

1. An initial velocity (i.e. speed and direction) at the point at which manipulation ended.
2. A deceleration function, which can be as simple as a constant.
3. A timer telling you the elapsed time since manipulation ended.

The calculation of initial velocity will vary depending on the implementation of your manipulation engine. Typically, one keeps track of the position of the manipulated object each frame, and calculates velocity = (position - previous_position) / elapsed_time. In subsequent frames, calculate position = position + velocity * elapsed_time, then decrease the velocity using your deceleration function, such as velocity = velocity * constant * elapsed_time, where constant is less than one.

If you want to add inertia to rotation, follow the same approach but use angle instead of position (which gives angular_velocity).

Regards,
Dave
By
DarkNight
12 Dec 2013 08:31
Thanks Dave for the reply

I just wanna make sure i got that right. let's assume we have a Rectangle control called "rect1" and please correct me in the following algorithm:

1- Manipulations Starts:

void ManipulationStarted()
{
float PrePosX = rect1->X;
float PrePosY = rect1->Y;
}

void ManipulationDelta()
{
velocityX = (rect1->X - PrePosX) / GetTickCounts();
velocityY = (rect1->Y - PrePosY) / GetTickCounts();
}

void ManipulationCompleted()
{
Inertia->InitialVelocityX = velocityX;
Inertia->InitialVelocityY = velocityY;
}

Is this correct or i am missing something


Also does that algorithm insure the correctness of velocity even if the object changed its direction of position or rotation. And for (velocity = (position - previous_position) / elapsed_time) formula. Is this the initial velocity? or do i have to add the velocity of the current frame to another variable say "TotalPosVelocity".
By
Dave
14 Dec 2013 18:23
Hi Darknight. I assume ManipulationDelta fires every frame, in which case you'll be calculating the average velocity since manipulation began, which is probably not what you want. Just update your PrePosX & Y variables in ManipulationDelta. Once you've done this, you will be tracking an "instantaneous" velocity. Depending on the accuracy of the input (such as mouse, touch etc.) and frame frequency you might find this can lead to unexpected inertial velocities (higher, lower, or in a different direction). While adding a layer of complexity, it's worth considering a timing loop which continuously averages the manipulation velocity over recurring, short time periods for smoothing purposes. But this should get you started.
By
DarkNight
15 Dec 2013 07:00
Hi Dave, if this technique might result in an unexpected velocities then how Microsoft is doing it. And isn't this part of the formula is actually the translation delta "(position - previous_position)".

Now if i managed in each ManipulationDelta function to add each frame current velocity and its time to a list since the Manipulation started then when the last finger is released i loop over each element in this list then compute the average by adding all velocities together and divide it by the total time like this:

float totalTime = 0;
float totalVel = 0;
for (int i = 0; i < velocities.Count; i++)
{
totalVel += velocities[i].Velocity;
totalTime += velocities[i].Time;
}

float initailVelocity = totalVel / totalTime;

Will that do the trick.

And for the time variable is it the deference in tick counts or normal time in milliseconds?

Add Comment

*
*
*
Captcha
*
*Required