Recently a customer requested a particle simulation with the intention to investigate correlations and the effect of multiple ‘attractors’. The real, underlying issue in this demand is the fact that certain situations and systems are governed by laws (differential equations) which cannot be solved exactly and require a dynamic system to search for critical coefficients. These coefficients result in (semi) stable configurations or highlight boundary conditions inside which things make sense.
The problem with these kind of systems is the scalability which has two aspects;
the visualization which doesn't scale well with the retained graphics pipeline of WPF/SL/WP7 on the one hand and the O(N*N)
calculation of interactions between particles.
Regarding the visuals there is really a lot to consider:
- if you inherit from a baseclass like FrameworkElement or Control or even UserControl you carry around with each and every particle a whole lot of stuff; data binding, styling, event and other infrastructure. While all these things are really great in an LOB, one doesn’t usually need all this when dealing with (lots of) particles
- typically the underlying surface needs to be a Canvas but this element also brings along many gears; the retained rendering system, the measure/layout mechanics, styling and more. Maybe the bonus you miss when bypassing the Canvas is the ability to easily integrate zoom and pan in an application.
- how much user-interaction is required, are mouse-events necessary or is it a ‘let it run’ system? Here as well, you need to consider carefully the implications (especially related to the scalability of the app).
With respect to the simulation or calculation part things are more straightforward but you also need to think about
- the possibility to use F# for the more mathematically oriented parts. The disadvantage is however the need to constraint your model to make sure things talk to C#, or you have to go the full nine yards in F# (talking to XAML is still a disaster in this case).
- how to optimize the calculations and to make sure that inside loops you break early and branch as much as possible
- dropping unnecessary properties of the particles and make the particle system as lightweight as possible
Within the Silverlight/WP context my experience is that if you use the Canvas/UIElement combination you easily hit a wall around
500 particles due to the way the rendering engine is functioning and the fact that the UIElement (or FrameworkElement) are too ‘heavy’. The inter-particle calculation will still run OK with 500 particles but the end-result is that it’s not a good solution altogether.
One can keep the Canvas as underlying surface and render particles as inherited Shape items but this doesn’t push the boundary much.
A step further is to replace the Canvas with a bitmap and use direct pixel printing. This is easily done with the
WriteableBitmapEx project you can find on CodePlex. This boosts your rendering to
5000 particles if you drop interactions. However, if you switch on inter-particle forces you hit a calculational wall around
1500 particles which is still way better than the retained rendering solution but still somewhat underwhelming.
So, as a next step it would be great to use parallel processing for the algorithmic part but unfortunately there is no task parallel processing library (TPL) for Silverlight (though somewhat made an unofficial port). Another possibility would be to use MailboxProcessor of F# but it would entail threading issues and an altogether more difficult system.
Various samples and libraries are available for XNA and Windows Phone which allow one to create particle effects but
- the often use sprites or similar techniques to minimize the particle count. The results are usually very good but the aim in the context of games is usually to create a certain effect rather than to give a physically correct simulation.
- they often do not exhibit inter-particle forces. If they do the particle count is low.
- they focus on effects and not physics
See also the Flint-sharp library which is a port of the Flash/Flex library.
The conclusion is that one can perform simulations and develop particle system in Silverlight if the need is not above, say, a thousand particles. Above this threshold things become more difficult and Silverlight as a medium becomes less suitable for this type of task. Obviously there are high-tech solutions on the basis of C++ and GPU instructions but this was outside my client’s scope (and my technical know-how as well).
Note: on different level you need to note in the attached simulation sample that
- the average speed varies a lot while the amount of interacting particles stays the same
- the ergodic phenomenon if easily shown; that the average velocity over the sample equals the average of one item in time
- it's quite difficult to create stable configurations; which mimics well how the real world is also constantly influenced by quantum fluctuations
References