Surface Physics Download

By
Dave
Project
Published
13 Feb 2010 12:15
Last Modified
13 Jan 2013 18:05

I've had a lot of requests to share my physics-enabled, WPF layout control for Microsoft Surface. This was demonstrated in the previous series of posts, Surface Physics Demo Part 1, Part 2, and Part 3.

So here it is! The following downloads are available:

  1. Physics Library (binary), .dll (zip'd), 19Kb. The physics library and layout control.
  2. Surface Physics Sample (install), .msi (zip'd), 1,046Kb. The sample application for demonstrating the physics library and layout control.
  3. Readme for Surface Physics Sample, .pdf, 1,626Kb. Readme for the sample application.
  4. Surface Physics Sample (source code), Visual Studio 2008 Project (zip'd), 907Kb. Source code for the the sample application.

Note that the Physics Library itself is currenly only available as a binary.

The Surface Physics Sample demonstrates many of the features supported by this library. However, to get you started with using the library in your own projects, I'll discuss how to enable basic physics for a simple ScatterView sample.

Migrating ScatterView to PhysicsView

This example demonstrates how to take a simple ScatterView sample and migrate it to make use of the physics-enabled layout control. You'll need the Microsft Surface SDK, available from the MSDN site here, and access to a Microsoft Surface or at least the Surface Simulator in the SDK. You'll also need the physics library.

First create a new Surface Application (WPF) project using the Visual Studio template inlcuded in the SDK. In SurfaceWindow1.xaml add a ScatterView to the default Grid control as follows:

<s:ScatterView Name="ScatterView1">
    <s:ScatterView.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="White" BorderThickness="2">
                <Image Source="{Binding}" Width="128" Height="96" />
            </Border>
        </DataTemplate>
    </s:ScatterView.ItemTemplate>
</s:ScatterView>

In SurfaceWindow1.xaml.cs add an event handler for the Loaded event and add some items to the layout control:

public SurfaceWindow1()
{
     InitializeComponent();

     // Add handlers for Application activation events
     AddActivationHandlers();

     this.Loaded += new RoutedEventHandler(SurfaceWindow1_Loaded);
}

void SurfaceWindow1_Loaded(object sender, RoutedEventArgs e)
{
    ScatterView1.ItemsSource = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures");
}

Run the project and if you're running the Surface Simulator you should see the following:

ScatterView

Figure 1. Simple ScatterView example. Note that the blank image is from a hidden file (desktop.ini) in the Sample Pictures folder.

We'll use this as a baseline to migrate from ScatterView to PhysicsView. First of all, copy the physics library (Physics.SurfaceControls.dll) into the project, and add a reference to it. Then add a namespace declaration at the top of SurfaceWindow1.xaml as follows:

xmlns:p="clr-namespace:Physics.SurfaceControls;assembly=Physics.SurfaceControls"

In SurfaceWindow1.xaml do a find and replace on s:ScatterView with p:PhysicsView and change the name from ScatterView1 to PhysicsView1. The rest of the markup remains unchanged, and the layout control should now look like this:

<p:PhysicsView Name="PhysicsView1">
    <p:PhysicsView.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="White" BorderThickness="2">
                <Image Source="{Binding}" Width="128" Height="96" />
            </Border>
        </DataTemplate>
    </p:PhysicsView.ItemTemplate>
</p:PhysicsView>

We can now set the ItemsSource on the new layout control. The next thing we need to do is inform the physics library of the physical properties of these items. Before we do this, however, we should set up some walls defining the bounding area. The library doesn't make any assumptions here since this area doesn't have to be rectangular nor aligned with the x,y axes. In this case we'll simply add four walls, inset from the extent of the screen by 16px (remembering that a Surface application runs at 1024 x 768px). Update SurfaceWindow1_Loaded to look like this:

void SurfaceWindow1_Loaded(object sender, RoutedEventArgs e)
{
    //ScatterView1.ItemsSource = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures");

    // add walls
    PhysicsView1.Bounds = GenerateWalls(0.5, new Rect(new Point(16, 16), new Point(1008,752)));

    // set data context
    PhysicsView1.ItemsSource = System.IO.Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures");

    // add behaviours
    AddBehaviours(this.PhysicsView1);
}

The methods for setting the bounds and item properties are as follows:

List<WallBody> GenerateWalls(double restitution, Rect rect)
{
    return new List<WallBody> {
        new WallBody { Normal = new Vector(1, 0), StartPoint = rect.TopLeft,
                EndPoint = rect.BottomLeft, Restitution = restitution }, // left
        new WallBody { Normal = new Vector(0, 1), StartPoint = rect.TopLeft, 
                EndPoint = rect.TopRight, Restitution = restitution }, // top
        new WallBody { Normal = new Vector(-1, 0), StartPoint = rect.TopRight,
                EndPoint = rect.BottomRight, Restitution = restitution },  // right
        new WallBody { Normal = new Vector(0, -1), StartPoint = rect.BottomLeft,
                EndPoint = rect.BottomRight, Restitution = restitution }}; // bottom
}

void AddBehaviours(PhysicsView physicsView)
{
    Random random = new Random();

    // ensure layout
    physicsView.UpdateLayout();

    for (int i = 0; i < physicsView.Items.Count; i++)
    {
        // get item
        PhysicsViewItem item = physicsView.ItemContainerGenerator.ContainerFromIndex(i) as PhysicsViewItem;

        // set properties
        Body body = new RectangularBody
        {
            Width = item.DesiredSize.Width,
            Height = item.DesiredSize.Height,
            Density = 0.01,
            InertiaConstant = 0.5,
            Restitution = 0.5,
            Orientation = random.NextDouble() * Math.PI * 2,
            Location = new Point(random.NextDouble() * physicsView.ActualWidth,
                random.NextDouble() * physicsView.ActualHeight),
        };

        // add item
        PhysicsCanvas.SetChildBody(item, body);
    }
}

That's it! The items will now collide with one another. Run the project and you should now see the following:

PhysicsView

Figure 2. PhysicsView Items now collide with one another and do not overlap.

Regrettably I've had no time to extend this work, so a lot of features remain un-implemented at this time. Examples inlcude multi-touch manipulations on the individual items themselves, a better dampening algorithm etc. However, I hope it may still prove useful in some cases.

The source code for this example can be downloaded here.

Comments

By
Rutledge
17 Feb 2010 19:11
Hi Dr Dave,
Could you psosibly send me the source you used for your physics engine? I've been playing around with it and would really like the ability to modify some things and understand what I'm dealing with a little better.

Thanks for your time,
Rutledge
By
Dave
23 Feb 2010 00:05
Hi Rutledge! Out of curiousity, what things are you considering modifying?
By
Tyler
5 Mar 2010 19:56
Thanks for releasing this! I find it after finishing a project using FarseerPhysics with WPF. My approach wasn't nearly as clean, in the end I determined I would have been better off with XNA.

I especially enjoyed seeing the source for the 3d spheres, it is much simpler than I had imagined.
By
Dave
6 Mar 2010 00:20
You're welcome, Tyler :)
As far as 3D spheres are concerned, Quaternions are marvellous!
By
dday
24 Mar 2010 14:38
Hi Dr Dave,
first thank you for your work because this help me a lot for my project.
However i have a lot of difficulties to create polygon in the physicsView. Indeed i try to change the body in polygonBody but i don't know why this don't work.
Could you help me please ?
Thank you in advance

ps: Sorry for my english, i'm french
By
cast urethane
29 Apr 2010 13:38
Indeed i try to change the body in polygonBody but i don't know why this don't work.
By
Simone
21 Jul 2010 16:00
You are awesome. This thing is awesome. THANK YOU.
By
Tao
22 Dec 2010 04:45
Hi Dave,

I just came across your Surface Physics project. It's cool. And more importantly, I also worked on integrating physics (using the Havok engine + XNA) with Surface back in 2008 when I was doing an internship in Microsoft! I was very enthusiastic and interested about that project, but my internship was only 3 months... I am very happy to see you are taking physics on Surface even further. I want to write an email to you but could not find your address, so I have to leave comments here... It would be great if you can tell me more info of the current status of this project and I am absolutely very happy to talk to you more about this, if you have time.

Thanks and happy holidays!

- Tao
By
Jon
26 Jul 2011 13:10
Hi Dave,

Will your library work with the new Surface 2.0 SDK?
By
Dave
26 Jul 2011 17:30
Hi Jon, unfortunately not, however I have ported the library to Surface 2.0 and will release the source code just as soon as I can. Best regards, Dave.
By
Koen Rotteveel
3 Nov 2011 09:08
Hi Dave,

I am having some trouble with adding the library. The sample runs very smoothly, but as soon as I am adding the DLL to my project and add the same code as above I get a 'Class not registered' error. Do you have any clue?

Thanks
-Koen
By
Dave
8 Nov 2011 13:39
Hi Koen, have you tried following the instructions above which start from an empty project, as that should work just fine?
By
Koen
14 Nov 2011 15:05
Hi Dave,

Thanks for your reply. Yeah I did start with a new project, which is a bit strange, because the download project works fine.
If I get my hands on another computer I will try again...

Koen
By
Dave
15 Nov 2011 11:50
Hi Koen - hope you have better luck. The only time I've seen the error you mentioned is when doing COM interop, and I'm certainly not doing that in this library...keep me posted!
By
Daniel Wang
8 Feb 2012 16:33
Hi Dave,
Thank you for your work.I compile the sample project and run,it works well when use Mouse,but when i use "Surface Input Simulator",something goes wrong.Like this:
Touch one PhysicsItem, TouchMove, TouchUp.Then Touch another PhysicsItem, the current one and the previous one will be moved together.Sorry for my english.

By
DANIEL WANG
9 Feb 2012 07:02
I found it.
In the TouchDown function,add "e.handle = true" to the end! It solved
By
Sahil
23 Mar 2012 16:43
Hi Dave,
Do you have a sample project targeting surface 2.0 ? I am trying to compile the project against surface 2.0, but I am getting all kinds of errors. I am actually looking for the dial implementation you did in the NUIVerse demo. I am trying to use Path to replicate it, but I am not sure if that's the right approach. I will really appreciate if you can provide me some pointers.
By
Dave
23 Mar 2012 17:35
Hi Sahil. Yes I do, but I've still got a few things to fix-up before I can release it (unfortunatley I've been too busy). There were quite a lot of changes from v1 to v2, so it's not a straightforward port.

This project doesn't have the dial used in NUIverse, which is a seperate codebase built on XNA. In WPF you'd probably be looking at a custom control, for which you could use Paths for the rendering and RenderTransforms for the rotation.
By
Roberto Valenti
9 Jun 2012 15:53
Hi Dave,
let me know, if i can help you to port your library on Surface 2.
I used your library in some prototype and i'd like to update these apps.

Regards,
Roberto

Add Comment

*
*
*
Captcha
*
*Required