The n-body simulation code essentially uses Euler's method for stepwise integration of the gravity equations. At each cycle, the force vector between each of the bodies is calculated and summed to find the net force vector acting on each body. According to Newton's 2nd law of motion, F = ma, the force on each body, when divided by its mass, determines its acceleration. The accelaration over the time interval dt of the cycle determines the change in velocity for that cycle, and then the new velocity applied over the same interval determines the new position of the body.
This is a first-order Euler simulation, which tends to result in
fairly high errors.
A slight improvement would average the force at time t and t + dt2, which would result in a second-order solution.
The goals for this system, however, are less concerned with the accuracy of the simulation than with making interesting-looking movement that results in interesting music.
Some quirks of the algorithm:
- Discrete algorithms are known not to conserve momentum. The system tends to gain energy over time.
- Because of this, there is "friction." The velocities decrease by a world-dependent factor each cycle.
- This isn't straight Newtonian gravity: I've implemented attraction at the inverse square law, and repulsion at the inverse cube law. That's why the bodies appear to bounce off each other.
- The bodies (and rocks) with rings inside them are mutators. Every time they hit something, they randomly change its mass.
- Unless a world has mutators to add randomness, it is a strict simulation, and will "play" the same motions and music every time.
- The boundary of the universe is a semi-permeable membrane. Bodies can get caught outside until friction slows them down and they sneak back in.
When bodies collide, they light up for a bit. If they also play a note, they light up even more.
Each body (or rock) can have a note, melody, or sequence attached to it, as well as specify the instrument or midi channel on which to play the note. When a body is involved with a collision, it plays its note, or the next note in its melody or sequence. Those notes are specified as note name and octave, Eg. C3, Ab4, or D#1, with C4 corresponding to middle C (midi note 60). Notes can also be rests.
The midi velocity of each note that is played is determined by the world-velocity of the body that the note is attached to. A world-specific formula derives the midi velocty (0-127) from the world-velocity. The default is a one-to-one mapping with a specified floor and ceiling (e.g. from 35 to 102).
The system currently has no notion of determining note duration from the physical properties of the ball. (That will happen when the use of a midi sequencer is implemented). Each instrument has a queue of currently playing notes. When a ball assigned to that instrument plays a note, it looks to see if the queue is full, and if so, stops playing the earliest-started note that is still playing (i.e. send a midi NOTE-OFF message on that channel). The default is 3 notes playing at a time for each instrument, though that can be changed in the world file on a per-instrument basis.