Chris Cavanagh’s Blog

WPF Physics Source

October 30, 2006 · 34 Comments

You can download the source code for my WPF / Physics demo here.  Here’s a very brief overview…

Most of the action takes place in World.xaml and its codebehind file.  It uses an ItemsControl bound to an ObservableCollection, with a DataTemplate for each body class.  Here’s the ItemsControl:

<ItemsControl ItemsSource="{Binding}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

The ItemsControl has its ItemsSource bound to the current DataContext.  The default item container is replaced with a Canvas to allow drawing objects to be positioned anywhere.  Here are a couple of the DataTemplates I’ve got:

<DataTemplate DataType="{x:Type local:RectangleBody}">
    <Rectangle Width="{Binding Width}" Height="{Binding Height}" Fill="#80FF0000" Stroke="#80000000" StrokeThickness="0.01" RenderTransformOrigin="0.5, 0.5">
        <Rectangle.RenderTransform>
            <MatrixTransform Matrix="{Binding DisplayMatrix}"/>
        </Rectangle.RenderTransform>
    </Rectangle>
</DataTemplate>

<DataTemplate DataType="{x:Type local:PolygonBody}">
    <Polygon Points="{Binding Points}" Fill="#80808000" Stroke="#80000000" StrokeThickness="0.01">
        <Polygon.RenderTransform>
            <MatrixTransform Matrix="{Binding DisplayMatrix}"/>
        </Polygon.RenderTransform>
    </Polygon>
</DataTemplate>

RectangleBody and PolygonBody are a couple of custom classes wrapping Newton primitives.  DisplayMatrix is a property that returns a 2D transformation matrix based on the 3D matrix calculated by the Newton engine.  Whenever Newton adjusts the matrix it raises an event.  I catch this and call my PropertyChanged delegate (see the INotifyPropertyChanged interface for details).

Why the ridiculously thin (0.01) StrokeThickness I hear you ask?  I’ve got a fairly good explanation for that (scaling from physical world coordinates to display coordinates), but I’ll wait until someone asks before I try to explain myself…

Anyway, take a look at the source and fire some questions at me.  I’m still amazed how little WPF code & markup it needed to get this going.

Thanks again to Flylio for writing a great C# Newton Dynamics wrapper, which is now even better since I ironed out some bugs and replaced its XNA dependency with a WPF one!

Categories: .NET

34 responses so far ↓

  • Marcus Tucker // October 31, 2006 at 5:57 am | Reply

    Cool!

    But why the ridiculously thin (0.01) StrokeThickness?! :p

  • Chris Cavanagh // October 31, 2006 at 7:36 am | Reply

    Ok, so about that ridiculously thin (0.01) StrokeThickness… It’s because I’m defining the shapes with the same units I’m representing the bodies in the ‘physical’ world (meters), and scaling the whole scene up to display units with a RenderTransform. This scales the StrokeThickness up by the same amount… Is that a lame excuse? :o )

  • Robby // November 1, 2006 at 11:28 am | Reply

    This is unbelievably cool–probably the most fun I’ve had with WPF in months! Thanks for putting this together.

  • slyi // November 3, 2006 at 7:39 am | Reply

    That was loads of fun but there seems to a performance limit when you add a huge number of sprites.

    Does the video use Microsoft Physics Illustrator? If that app had an export to xaml function that could be pretty cool for creating basic technical animations in xaml.

  • Chris Cavanagh // November 3, 2006 at 8:27 am | Reply

    The performance does suffer but that’s to be expected (I’ve not looked yet if it’s the physics engine choking or WPF). I’m sure there are optimizations that could be made :o )

    Physics Illustrator doesn’t have an XAML export (that I’m aware of); could be interesting if it did. The source is freely available though, so I’m thinking about adapting some of its design / stroke-handling ideas.

    Before that I was probably going to make the bodies draggable during the animation (just as an excuse to play more with WPF).

  • Roberto Sonnino // November 4, 2006 at 6:10 am | Reply

    Looks nice, but I couldn’t run here. Can we have your version of the NewtonWrapper?

    Thanks!

  • Chris Cavanagh // November 4, 2006 at 8:30 am | Reply

    Sorry! You can get it at http://www.cubpack99.com/Pack99/NewtonDynamics.zip

  • Sam M // December 16, 2006 at 3:24 pm | Reply

    Hi, I’m really curious and I found this page through a google search. Did you manage to get Newton Dynamics working in XNA Game Studio Express? And if so do you think you could let me know how to use the wrapper in a GSE project? If you could e-mail me back that would be great, thanks.

  • Mike Walters // June 14, 2007 at 9:46 pm | Reply

    Hi Chris,

    Awesome blog and super cool demos. In fact, you’ve inspired me to work on a 2D game I’ve been thinking about for a while. To that end, I would like to use some of your code (it’s excellent and would save me a lot of time), but in the likely event that I:
    a) Finish the game and
    b) Miraculously find a way to make money from it,
    I don’t want to be in a sticky licensing situtation.
    So, my natural question to you is, what is the licensing agreement for your source code? I see Newton has a pretty liberal license, any chance your code uses the same license? Or MIT license or ZLib license (same as bullet engine)? Any of those would be great. GNU and some of the others are pretty prohibitive so I’m hoping (pretty please!) that you won’t choose one of those.

    I see someone else had the same question. Please let us know.
    Thanks for the great blog,
    Mike.

  • Chris Cavanagh // June 14, 2007 at 10:35 pm | Reply

    Sam – I’m sure it’d be possible to get Newton working in GSE, but it’d only work on a PC. It should be possible to test it easily enough (create a new project in GSE and drag the files in?). I’m prepared to be wrong though!

  • Chris Cavanagh // June 14, 2007 at 10:41 pm | Reply

    Mike – You can assume my code uses the same license as Newton (or Flylio’s wrapper which my demo also depends on). To be honest the real work is done in Flylio’s code (NewtonWrapper); he did the hard work of figuring out the interop to Newton’s DLLs. Other than a few bugs I fixed, it’s pretty much unchanged from his site (except to remove the XNA dependency and replace it with a WPF one).

    Don’t forget there’s also the fully managed BulletX library my later demos use. If you want to deploy on Silverlight or Xbox you’ll need all the managed code you can get :)

    Let me know if you have any problems with my code; I’ll help any way I can.

  • Mike Walters // June 15, 2007 at 12:28 pm | Reply

    Awesome, thanks Chris! I really appreciate it.

    Have you tried (had any luck with) using Newton CollisionTrees? I can’t seem to get them to work using the wrapper.

  • Chris Cavanagh // June 15, 2007 at 12:47 pm | Reply

    Mike – I’ve not tried using them (I don’t even know what they do :) ). It’s quite possible there’s a bug in the NewtonWrapper somewhere; it’s worth taking a look at the Newton header files and comparing the datatypes to what the wrapper is expecting. Pay particular attention if the wrapper uses sizeof() or passes an array in any form (the bugs I already found/fixed were like that).

  • Chris Cavanagh // June 15, 2007 at 12:49 pm | Reply

    Mike – When debugging, just keep this chant in your head: “Newton is solid and works for everyone else” :) That only leaves the wrapper and my code to wade through. It possible there’s a bug in Newton itself, but I bet it’s highly unlikely at this stage.

  • Mike Walters // June 15, 2007 at 12:55 pm | Reply

    Okay, that’s good advice. I have found some minor tweaks I’ve had to make to the wrapper myself (regarding the same issues you mentioned). So the problem is probably along the same lines. I shall forge on and presevere.

    P.S. Your code has been rock-solid… no problems.

  • Chris Cavanagh // June 15, 2007 at 1:06 pm | Reply

    Mike – Can you let me know what bugs you find/fix in the wrapper? Would be good to keep my code up to date.

    Maybe it’s time I added the source to CodePlex again :)

  • Mike Walters // June 18, 2007 at 8:46 am | Reply

    Sure, here goes:
    1. Fixed InvokeContactBegin return value handling in CMaterialPhysics (was hardcoded to 1… you need to be able to return 0 if you want to ignore material contacts).
    2. There are a number of properties imported in BodyManipulation.cs that refer to ref float[] (examples: NewtonBodyGetVelocity, NewtonBodyGetTorque, etc). These needed to be changed to just float[] (get rid of the ref) in order to work. Also made the corresponding change in CBody.cs.
    3. CJointBallSocket.cs -> NewtonConstraintCreateBall passes m_Handle in the call to Newton.NewtonConstraintCreateBall. It needs to pass m_World.Handle.

    I think that covers it for actual “bugs”. I made some other tweaks to expose/cleanup properties I needed but I don’t think they qualify as mandatory.

  • Mike Walters // June 18, 2007 at 10:25 pm | Reply

    Man, I cannot for the life of me get Collision trees to work. Picture the car in your demo rolling down a concave ramp. I’m trying to use collision trees to create the ramp (Newton doesn’t like concave surfaces so you have to simulate them by chaining together a bunch of convex collisions). Anyway, I think I have to throw in the towel on this one. I have the ramp mostly working using CCollisionComplexPrimitives.CreateCompound but there is an undesirable side effect of random “bumpiness” along the ramp’s surface. I was told (on the Newton forums) that collision trees should fix this, but alas, it appears as though I’m not smart enough for to make them work. Anyway, if you find yourself bored (and are itching for some frustration) I’d be thrilled to learn you actually got collision trees to work (I noticed Flyio’s original wrapper samples use them but the download I found is just .cs files… no project or solution included so I wasn’t able to actually run it).

    Cheers,
    Mike.

  • Chris Cavanagh // June 18, 2007 at 11:33 pm | Reply

    Mike – Sorry to hear of problems :( Do the bumps correspond to the vertices along the surface? (as if they’re connected with flat lines).

    I’ll take a look at it, but not sure when yet (my time is stretched pretty thin right now). I’ll let you know if/when I figure it out :) Let me know if you make any more progress on it.

    Thanks!
    Chris.

  • Mike Walters // June 19, 2007 at 11:13 am | Reply

    Hey Chris,

    The vertices are connected with flat lines (very short line segments). I’ve created the ramp’s compound collision by drawing 2 parrallel arcs (half circles) and then connecting 2 points from the inner arc to 2 points from the outer arc (so each sub-collision is a small trapezoid… note: I also tried tessellating with triangles instead of trapezoids and got the same behavior). As I said, this seems to work pretty well except for the occassional, random bounce upward (it’s as though there are some unseen potholes in my ramp… it does not behave like you would expect if it were just transitioning from one flat line to another… it behaves like it hit something sticking up… in fact increasing the number of points per arc (thus shortening the length of each flat line) actually makes the side-effect worse). Shrug.

    How has your experience with the Managed Bullet Library been? Do you find it easier to use than Newton? Have you done anything with compound or concave surfaces with it? I wonder if it would be worth it trying to switch engines. It would be a lot of work and I think I can live with the behavior I have now, but if you strongly endorse the Bullet library I’ll strongly consider taking the plunge.

    Mike.

  • Chris Cavanagh // June 19, 2007 at 11:55 am | Reply

    Mike – Unfortunately I don’t know enough about the innards of the engine to offer much help :( It might be worth contacting the NewtonDynamics guys to see if it’s likely to be an engine glitch (although their site hasn’t been updated recently).

    I’d definitely recommend Bullet; it seems more capable than Newton (with apparent support for non-convex collisions). Unfortunately I’ve not had time to kick it around as much as I’d like. It might be worth grabbing one of my other demos (the Silverlight 1.1 Physics one clamps to 2D) and see how easy/difficult it is to get more complex stuff in there. It includes a ‘Vehicle’ class like Newton too, so porting might not be too difficult.

    Here’s how to get BulletX working with WPF or Silverlight:
    1) Download the source for my ‘3D XBAP Physics’ or ‘Silverlight 1.1 Physics’ demos, you’ll find a wrapper assembly called CJC.XnaToWpf (or similar).
    2) Get the latest BulletX source from http://www.codeplex.com/xnadevru/Release/ProjectReleases.aspx?ReleaseId=1278 and add a project reference to XnaToWpf; you should be able to remove the XNA reference completely (XnaToWpf just mimics the main math classes from XNA).

    Also, the Xnadev.ru guys have some other projects you might find useful: http://www.codeplex.com/xnadevru

    Hope this helps! Let me know what you decide.

    Chris

  • Mike Walters // August 28, 2007 at 8:46 am | Reply

    Hey Chris!

    I have a beta version of the game I’ve been working on (which leverages some of your code) now available. I’d love for you to check it out, but I don’t want to post the url anywhere until I’ve had a chance to work out the kinks. Can I send you an email? Or can you email me and I’ll respond with the link?

    Thanks for the great blog and awesome samples,
    Mike.

  • Alex Cedeno // October 3, 2007 at 11:10 am | Reply

    Hi Chris!! Thanks for this excellent demo. Have you tried something similar but with draggable objects? How easy do you think it could be?. I’ve seen some newton dragging samples but I’m not too sure if they could be translated to the .net wrapper completely, mainly b/c I don’t understand clearly how to translate screen coords to world coords. That newton samples also use worldraycast to figure out (i think) if the mouse is over an object. In wpf I think this is not necessary since we have the onmouse events.

    Thanks a lot and keep the excellent work!!!

  • Futile » Blog Archive » links for 2008-01-10 // January 9, 2008 at 10:28 pm | Reply

    [...] WPF Physics Source « Chris Cavanagh’s Blog (tags: wpf xaml programming) [...]

  • Fabrice Kauffmann // April 24, 2008 at 2:20 am | Reply

    Great demo, thanks Chris! I really appreciate it too.

    I tried to put an InkCanvas with its EditMode property set to “Select” around the ItemControls element, but it failed to select any shape. Only a small canvas element seems to be selected at the center of the form each time I click an object. Any idea / suggestion ?

  • Chris Cavanagh // June 7, 2008 at 6:58 pm | Reply

    Fabrice – Sorry for my delayed reply… Were you able to resolve this?

  • Flylio // March 12, 2009 at 3:44 pm | Reply

    Hello,

    I’m surprised and very happy to see that someone used my wrapper!

    I’ll hope it was usefull !!

    @PLUS2009!

    Flylio.

  • Chris Cavanagh // March 12, 2009 at 5:35 pm | Reply

    Hey Flylio! – Your wrapper was very useful and saved me a lot of time – thanks!

  • Alex // March 23, 2009 at 3:27 pm | Reply

    Chris,
    How can I move those objecs ‘bodies’ with the mouse? I tried to play with the Matrix of the objects, but nothing.

  • Chris Cavanagh // March 23, 2009 at 11:44 pm | Reply

    Alex – I’d need to look at the code to be sure (it’s been a while) but I’m pretty sure you need to apply a force to the body you want to move. You could also take a look at the “move platforms” code; pretty sure that just jiggles the matrices a bit… Let me know how it goes :)

  • Alex // March 24, 2009 at 7:57 am | Reply

    Chris,
    “You could also take a look at the “move platforms” code” – where is that?

  • Alex // March 24, 2009 at 8:29 am | Reply

    And one else, when the objects complete their movement, they are frozen…I cannot manipulate…Do I need to set something?

  • Chris Cavanagh // March 24, 2009 at 9:12 am | Reply

    Alex – Take a look at the SetPlatforms method in Bodies.cs (although looking at it now, it’s probably not much use). Instead try calling the AddForce method on the body you want to move, giving it a Vector3D of the direction you want it to move (imaginary force pushing it from the opposite side). Let me know if it works!

  • Chris Cavanagh // March 24, 2009 at 9:14 am | Reply

    Alex – The Newton engine has an optimization where it stops calculating body movement when it thinks they’re stationary (they can still be moved by other collisions of course). You might need to dig around in the code a little to find how to override that (again, just applying a force to the body may be sufficient).

Leave a Comment