The simulation had a huge improvement when I changed the integrator. I was using the fifth order Gear's predictor and corrector integrator. Since most of the people in real-time applications says that the fourth order Runge Kutta integrator is the most effective, I implemented and saw what they where talking about: it's really fast! From a few minutes using Gear's algorithm with collision detection, it dropped to a few seconds with collision detection. A lot better. :)
In the first time I was calculating the collisions between particles. To another improvement, I followed the hint given by Bugsbane in a comment of the last post and decided to remove the particles collisions.Indeed, for our purposes, these collisions must happen only in two specific situations: (1) when the mouse does the spreading of sand already in the canvas and (2) when one particle tries to pass the canvas boundaries.
I had some numerical problems too, but that was my fault. In certain initial conditions, one of the particle properties was set to zero, without I even notice that. This propertie was the Young modulus, which gives us the elastic properties of a material. The value was set to zero, doing a unproper division in the equations and yielding numerical errors.
When most of the previous errors and drawbacks was removed, I ploted the particles in a QWidget and animated it to see what was really happening:
I took the particles properties from a initialization file (with it's positions, velocities, forces and other properties), instatiated them and draw each one with a drawEllipse method of a QPainter class. After that, for each time step, I applied the integrator and redraw the entire particle set on the canvas.
I didn't pushed this part to the repository yet, but as soon as I finish the code comments and refactoring, it will be available. For now, I'm listing my next steps :
- Forces evaluation : I will modify the normal force method to deal with a big "particle" of the size of the brush, so the particles can move properly in the canvas as the mouse emulates the artist finger. Another thing is that the code is working only with circular particles for now, so the tangencial force do not have any significant role for this simulation. Perhaps in the future when it starts to deal with non-circular elements it will be useful, but until there, it will remain unused.
- Grid Mouse interaction: I divided the numerical simulation space in a grid to improve the performance. Now I will do the same with the canvas to detect which particles the mouse are touching and apply forces in each of them based on the mouse movements. I believe I will not have much problem with that when I port this code to a Krita paintop, since the canvas is already divided in 64x64 grid cells.
- Canvas Boundaries: This will be more complicated since the behaviour of the sand in the boundaries depend of the box material. Most of the particles have a little bounce back after colliding with the bounds, so I'm thinking if I set invisible particles at the bounds or if I set a default bounce back force for each particle.