Lua scripting
SpaceSim allows you to create custom objects or simulation systems using the Lua language.
Scripted objects
Example:
You can try adding a scripted object by copying the script below, or by downloading it.
require("math")
-- Name of this object. This will be the label of the button added to 'Custom objects'.
objectName = "Color cloud";
-- Table of object parameters that will be shown in the UI.
parameters = {}
parameters.radius = Constants.R_Earth;
parameters.density = 10000;
parameters.spinRate = 0.0004;
parameters.particleScale = 0.01;
-- Returns the total volume of the object. This function is used to determine
-- how many particles are assigned to the object.
function getVolume()
return 0.02 * math.pi * math.pow(parameters.radius, 3);
end
-- Returns the total mass of the object.
function getTotalMass()
return getVolume() * parameters.density;
end
math.randomseed(os.time())
-- Main entry point of the script. The function will create a table containing
-- all particle data of the object.
function generate(n)
state = {}
state.position = {};
state.velocity = {};
state.mass = {};
state.density = {};
state.radius = {};
state.color = {};
phi = 2 * math.pi / n;
for i=1,n
do
r = math.pow(math.random(), 0.66) * parameters.radius;
v = r * parameters.spinRate;
state.position[i] = { r * math.cos(phi * i),
r * math.sin(phi * i),
0.01 * parameters.radius * (math.random(-1, 1)) };
state.velocity[i] = { v * math.sin(phi * i),
-v * math.cos(phi * i),
0 };
state.radius[i] = parameters.particleScale * Constants.R_Earth;
state.density[i] = parameters.density;
state.mass[i] = parameters.density * 4.0/3.0 * math.pi * math.pow(state.radius[i], 3);
state.color[i] = { state.position[i][1] / r,
0.5,
state.position[i][2] / r };
end
return state;
end
Script functions
The script must define the following mandatory functions.
| generate(N) | Function creating particles. Takes the number of particles as an input parameter. |
| getTotalMass | Returns the total mass of the object. |
| getVolume | Return the total volume of the object. |
Quantities
Script function generate has to return a table containing the particle quantities. All quantities are assumed to be in SI units
(meters, kilograms, Joules, etc.). The following quantities are mandatory and have to be returned by the function for the object
to work:
| position | Positions of all particles |
| velocity | Velocities of all particles |
| mass | Particle masses |
| radius | Particle radii |
Optionally, the script can also return additional quantities, namely:
| density | Particle densities |
| color | Diffuse color of particles |
| temperature | Temperatures, used to calculate the glow color |
| energy | Initial specific internal energy, used by the SPH solver |
| normal | Initial surface normal of particles |
| uv | Texturing coordinates, a table containing two values in the interval [0, 1]. |
If the density specified, the object enables the hydrodynamic solver and handles particle collisions, otherwise a pure gravity solver solver
is used for the simulation.
Variables
Optionally, the script can define a global table named parameters, containing key-value pairs.
If used, the values will appear in the object panel and can be modified along other object properties, such as position or rotation.
Currently, only number parameters are supported. Values of different types are ignored.
The script can also define the following variables:
| objectName | Name of the object in the "Add object" panel |
Constants
The script can use a few useful constants, defined in the global table Constants.
| R_Earth | Earth radius |
| R_Sun | Solar radius |
| au | Astronomical unit |
| M_Earth | Earth mass |
| M_Sun | Solar mass |
Object repository
List of Lua objects you can use as a starting point for your own experiments:
Scripted simulation systems
Example:
You can try adding a scripted system by copying the script below, or by downloading it.
require("math")
-- Simple system that explodes the largest object in the simulation.
-- Initialize all quantities used by the script.
-- These quantities will be updated by the simulation every time the script is run.
-- All quantities are in SI units (meters, kilograms, Kelvins, ...).
-- For the list of available quantities, see https://pavelsevecek.github.io/lua.html
-- This is a mandatory field.
particles = {};
particles.mass = {}
particles.position = {}
particles.velocity = {}
particles.island_index = {}
particles.temperature = {}
-- Names of all quantities changed by the script.
-- These quantities are copied back to the simulation after the script returns.
-- This is a mandatory field.
update_quantities = {"velocity", "temperature" };
-- Optional parameters of the system.
-- The parameters can be changed in the simulation settings after compiling the script.
parameters = {}
parameters.explosion_velocity = 0.005;
parameters.heating = 2000;
-- Main entry point of the script.
-- Called with period set in the simulation settings. If the period is 0,
-- the function is called every time step.
-- Parameters:
-- t - Current simulation time (in seconds)
-- dt - Current time step (in seconds);
function onTimeStep(t, dt)
local island_counts = {};
for i = 1, #particles.island_index
do
local island = particles.island_index[i];
if island_counts[island] == nil then
island_counts[island] = 1;
else
island_counts[island] = island_counts[island] + 1;
end
end
local largest_island = 0;
local max_count = 0;
for island, count in pairs(island_counts) do
if count > max_count then
largest_island = island;
max_count = count;
end
end
local x_com = 0;
local y_com = 0;
local z_com = 0;
local mass = 0;
for i = 1, #particles.island_index
do
if particles.island_index[i] == largest_island then
local m = particles.mass[i];
local r = particles.position[i];
x_com = x_com + m * r[1];
y_com = y_com + m * r[2];
z_com = z_com + m * r[3];
mass = mass + m;
end
end
x_com = x_com / mass;
y_com = y_com / mass;
z_com = z_com / mass;
local v = parameters.explosion_velocity;
for i = 1, #particles.island_index
do
if particles.island_index[i] == largest_island then
local r = particles.position[i];
particles.velocity[i] =
{
(r[1] - x_com) * v,
(r[2] - y_com) * v,
(r[3] - z_com) * v
};
particles.temperature[i] = particles.temperature[i] + parameters.heating;
end
end
end
Script functions
The script must define the following mandatory function.
| onTimeStep(t, dt) | Function called with the period set in the script settings. |
Particles
Particle quantities can be read from (and written into) the global table particles. The script can read and modify any of the following quantities:
| position | Positions of all particles |
| velocity | Velocities of all particles |
| acceleration | Accelerations of all particles |
| mass | Particle masses |
| radius | Particle radii |
| density | Particle densities |
| pressure | Pressure at the particle position |
| color | Diffuse color of particles |
| temperature | Temperatures, used to calculate the glow color |
| energy | Initial specific internal energy, used by the SPH solver |
| phase | Current particle phase, 0 for solid and 1 for gas. |
| normal | Initial surface normal of particles |
| uv | Texturing coordinates, a table containing two values in the interval [0, 1]. |
| body_index | Index of the original object. |
| island_index | Index of the current object. |
| material_index | Material index. |
Rigid bodies
The script can also read and modify the state of rigid (non-deformable) objects by accessing the global table rigid. Each rigid object has the following quantities:
| position | Object position. |
| velocity | Object velocity. |
| rotation | Object rotation given by Euler angles (in degrees). |
| spin_rate | Current spin vector (in units deg/s). |
| temperature | Surface temperature. |