Attempt at Silverlight animation
Here is the toy:
This has been a fun little project, especially since I haven’t done any programming for fun in a while.
I learned (and borrowed) a lot from Rick Barraza’s blog:
How it works.
Animation. The model is rendered to a WritableBitmap and the CompositionTarget_Rendering event is used for animation. This method gives really good performance, but I found two drawbacks with it. First, it’s very CPU-hungry, because of the high default FPS. I found that instead of lowering the FPS you can simply skip every other frame. This is what I do in my implementation. Also potentially you may choose to render different parts of the model in different frames, making it less CPU-demanding, but still smooth. (Haven’t tried that though). The second drawback is that when you recalculate your model in CompositionTarget_Rendering, the frame rate becomes your model’s "physical clock". So you can’t control the model’s "time rate" unless you, again, skip frames. You may want to use a separate Threading.Timer as the model’s clock, and still do rendering in CompositionTarget_Rendering. But that helps only if you want to slow it down. If you want the fastest rate then CompositionTarget_Rendering is the best shot.
The "reflection" at the bottom is a separate Image element using the same WritableBitmap as a source, with a Transform and a BlurEffect.
What can significantly slow down the rendering: 1. Alpha transparency. I tried to do the neat Fade effect using a semi-transparent rectangle, as described by Rick, but found it too slow. 2. Blur effect – it’s really slow, and the greater the radius the slower it gets. 3. Don’t use Canvas.Left/Top for positioning. Use Transforms instead.
The Model. The "water" is the very basic discrete wave equation. It is unstable, i.e. it diverges (acts crazy) if you don’t choose precise parameter values. So "physical properties" of my "water" are pretty much fixed. I’m currently digesting this paper http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/GDC03.pdf (thanks again to Rick Barraza for the link) and will hopefully rewrite my model so that it’s stable. The water is rendered simply as a bunch of pixels.
Modeling the Ship took some creativity since I’d never done anything like this before. But it is surprisingly simple. The ship’s lateral acceleration is proportional to the sine of the wave’s slope (it simply slides down the "inclined plane"). And there is the drag decceleration proportional to the square of the ship’s velocity. That’s it. There’s also slight random "wind" just for fun.
The ship is a png bitmap loaded from resource. It’s rendered using a TransformGroup to combine rotation and positioning. I could use a single MatrixTransform, but the TransformGroup creates the matrix for me. The Transform classes could use more refined interfaces, but they are neat anyway. I appreciate the word "Group" in the class name. Even though it’s not (always) a group, it multiplies plane transforms, so it has a lot to do with groups 🙂
There is some inconsistency in the water and the ship models. The ship is driven by "gravity". And the water doesn’t experience any forces except for its own tension, and drag when the "damp" checkbox is on.
Mouse interaction. At first, I wanted to allow drawing arbitrary shapes with the mouse. But rough shapes become really ugly when they are fed into the wave equation. So I do average smoothing with a large radius. I’m not very satisfied with the result, but anyway.