You can try it yourself here.
This project uses WebGL to render a simulation of various celestial bodies. Interactions between bodies is dictated by Newton's Law of Gravitation and takes into account mass, radius and velocity. However collisions between objects are currently ignored.
Any two bodies attract each other in direct proportion to their masses and inversely to the square of the distance between them. This is illustrated in the formula below where:
- G is the gravitational constant
- G = 6.67 x 10-11
- M1 is the mass of one object
- M2 is the mass of the other object
- r2 is the radial distance between the centers of M1 and M2
Implementation details can be found here.
Once the simulation is up and running the difficult part is figuring out the initial position and velocities of celestial bodies in order to achieve a "stable" orbit.
Since we know that FC and FG are equal but opposite forces we can derive a formula to calculate the orbital velocity needed to sustain an orbit around a given object. This does make the assumption that the orbiting object M2 will have negligible mass in comparison to M1. Below is an illustration of how this is derived and more details can be found here and here.
A helper method found here can be used to aid in the calculation of these velocities.
Custom scenarios can be loaded into the simulator by defining a list of celestial bodies in a JSON file. The key attributes for the simulation are the object mass, radius, position and initial velocity. Below is an example of how this data should be defined.
[
{
"name": "Mars",
"mass": 1000000000000000,
"radius": 63.71,
"colour": 13369344,
"position": { "x": -5000, "y": 0, "z": -500 },
"initialVelocity": { "x": 0, "y": 0, "z": 0.75 }
},
{
"name": "Deimos",
"mass": 1000,
"radius": 17.37,
"colour": 13421772,
"position": { "x": -5384, "y": 0, "z": -500 },
"initialVelocity": { "x": 0, "y": 1, "z": 0.75 }
},
{
"name": "Phobos",
"mass": 1.0e3,
"radius": 17.37,
"colour": 13421772,
"position": { "x": -4616, "y": 0, "z": -500 },
"initialVelocity": { "x": 0, "y": 1, "z": 0.75 }
}
]
To reduce the number of draw calls required, objects which share the same geometry but with different scale, position or rotation are batched together and sent to the GPU in a single instance. This is very useful for objects like the trails which need to render a large number of the same geometry but in different positions.
For larger celestial bodies number Levels of Detail (LOD) are defined and swapped between based on distance from camera. This allows objects to appear rich in detail when close to the camera and swapped out for lower detail when further away.


