## Multitouch Game Loop Inertia Processing

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.

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.

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

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

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

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

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

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".

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?

In this formula:

Time PrevTime;

void ManipulationStarted()

{

PrevTime = Now();

}

void ManipulationDelta()

{

double elapsed_time = MillisecondsBetween(Now(), PrevTime);

velocity = (position - previous_position) / elapsed_time;

}

Is elapsed_time here is the time in milliseconds since the manipulation started like the above code or is it like the code below:

Time PrevTime;

void ManipulationStarted()

{

PrevTime = Now();

}

void ManipulationDelta()

{

Time currentTime = Now();

double elapsed_time = MillisecondsBetween(currentTime , PrevTime);

velocity = (position - previous_position) / elapsed_time;

PrevTime = currentTime;

}

Also, in the Inertia process in timer did you mean the elapsed_time to be since manipulation ended or in every frame for the timer process:

Since Manipulation ended Code:

Time InertiaPrevTime;

void ManipulationEnded()

{

InertiaPrevTime= Now();

}

void InertiaProcess()

{

double elapsed_time = MillisecondsBetween(Now(), InertiaPrevTime);

position += velocity * elapsed_time;

velocity *= constant * elapsed_time;

}

Or calc elapsed_time is the time between frames like this:

Time InertiaPrevTime;

void ManipulationEnded()

{

InertiaPrevTime = Now();

}

void InertiaProcess()

{

Time currentTime = Now();

double elapsed_time = MillisecondsBetween(currentTime , InertiaPrevTime);

position += velocity * elapsed_time;

velocity *= constant * elapsed_time;

InertiaPrevTime= currentTime;

}

I really need your help on this.

Thanks in advance

Best Regards,

DarkNight

## Add Comment