General Usage of OpenSpace

This is a general usage guide for the current version of OpenSpace. It is aimed at a technically literate person not shying away from unprofessional GUI design, the necessity to edit text files, or the ability to perform Lua scripting.


All main configuration starts at the openspace.cfg in the main folder of OpenSpace. This file is read first upon startup and references two other configuration files.

The SGCTConfig (SGCT = Simple Graphics Cluster Toolkit) key defines the window setup of the application. This determines, among other things, whether the rendering is stereoscopic, rendering on a a single computer vs a dome environment, or outputting a fish eye rendering. Per default it loads the ${SGCT}/single.xml file which resolves to config/sgct/single.xml which creates a single window of size 1280×720. If you want to create high resolution screen shots, you can look at the single_4k.xml file for inspiration, which defines a Res tag with which you can set the window size and rendering resolution independently.

The Scene key defines the OpenSpace scene description that is to be loaded on application startup. Per default it loads the ${SCENE}/default.scene file which resolves to data/scene/default.scene. The next section will explain the markup of the *.scene file and the folders and files referenced therein. Changing the Scene value and restarting OpenSpace is the easiest and most reliable way to load a new scene.

Scene files

Underlying OpenSpace is a scene graph, whose structure is defined through the *.scene files. A *.scene file consists of three important parts:

The preInitialization() function is a Lua function that gets executed after the scene has been loaded, but before any initialization has occurred. This is the perfect time to load globally required SPICE kernels and setting the in-game time. Other tasks (like key bindings) can also be done here.

The postInitialization() function is a Lua function that is executed after all scene graph nodes have been initialized. This is the perfect time to override default values for Properties (see below), or doing final automatic changes through Lua before control is handed over to the user.

The return value of the script returns a table that defines the Camera properties, and, most importantly, a list of Modules that are to be loaded for this scene. The names of the modules are directories relative to the ScenePath value. If the directory contains a *.mod file of the same name, it is loaded, otherwise the directory is included recursively. For example in the default.scene:

The sun module is specified, so OpenSpace will look for the file sun/sun.mod and include it if it exists; if it does not exist, OpenSpace will recursively look through all subdirectories of sun and try to find all *.mod files in there.

For the jupiter module, OpenSpace does not find the file jupiter/jupiter.mod, but only the subdirectories jupiter/callisto, jupiter/europa, jupiter/ganymede, jupiter/io, and jupiter/jupiter. So each subdirectory is recursively checked (meaning it will check for jupiter/callisto/callisto.mod, jupiter/europa/europa.mod, etc). If one of the subdirectories does not contain a *.mod file, the recursion continues.

Good examples are:
| File | Reason |
| default.scene | The default |
| juno.scene | Defining delta times in the preInitialization function |
| rosetta.scene | Defining subdirectories in the Modules table |

Mod files

Each *.mod file must return a list of tables that define items in the scene graph. Each table must have a Name and a Parent entry. The Name must be globally unique among all *.mod files whereas the Parent entry must name another scene graph node’s Name. Based on these two information, the scene graph is constructed. An example is the jupiter/jupiter/jupiter.mod in which the JupiterBarycenter is a child of the SolarSystemBarycenter, which in turn is defined in sun/sun.mod. These parent-child relationships can be, for example, very useful when defining a model that consists of sub models (see rosetta/rosetta/rosetta.mod).

Important optional elements in a scene graph node are:

  1. Transform:
    A transformation that applies to the current node and all children (see jupiter/jupiter/jupiter.mod for an example). A Transform can have up to three entries:

    1. A Translation describes a translation that can either be of Type StaticEphemeris, such that a fixed offset Position relative to the parent is used, or a SpiceEphemeris, which uses a SPICE kernel to compute the dynamic offset relative to the parent. If a SpiceEphemeris is chosen, it table also needs a Body describing the NAIF body that is used, an Observer relative to which the position is calculated (this should almost always be the NAIF name of the parent), a Reference frame (almost always ECLIPJ2000), and a list of Kernels that should be loaded.

    2. A Rotation describes a rotation and can currently only be a SpiceRotation, that takes a SourceFrame and a DestinationFrame. With this information, a rotation matrix is generated by Spice to match the described coordinate systems.

    3. A Scale describes a static scaling of the scene. The only currently supported Type is StaticScale, which takes a floating point value of Scale by which the scene graph node and it’s children are scaled.

  2. Renderable
    A Renderable the main class for something that will show up on screen one way or the other. If a scene graph node does not have a Renderable key, it will produce no visual result, but is only used as an intermediate scene graph node (for example in combination with a Translation key). They type of the rendering is determined by the Type value contained inside. The possible values for the Types are too numerous to name, but the most important ones are:

    1. RenderablePlanet for planets (see earth/earth.mod)

    2. RenderableTrailNew for a trail behind objects (see earth/earth.mod)

    3. RenderableModel for an object defined by a model (see newhorizons/newhorizons/newhorizons.mod)

    4. RenderablePlanetProjection is a planet which can be projected on (see newhorizons/pluto/pluto.mod)

    5. RenderableModelProjection is a model which can be projected on (see rosetta/67P/67P.mod)

    6. RenderablePlaneProjection is a free-floating plane which can be projected on (see ImagePlaneRosetta in rosetta/rosetta/rosetta.mod)

    7. RenderableFov is the rendering of a field-of-view of a specific instrument (see NAVCAM FOV in rosetta/rosetta/rosetta.mod)


Similar to the preInitialization and postInitialization functions mentioned above, many things in OpenSpace can be changed while the application is running through the use of Lua scripts. Per default, the ` character opens a console in OpenSpace which can receive arbitrary Lua commands (see the red $ and green ^ sign on the left side of the window). The list of predefined OpenSpace Lua functions alongside short descriptions are written to the LuaScripting.txt on startup. The same descriptions hold true for the preInitialization and postInitialization functions.


OpenSpace has a built-in on-screen GUI that is using ImGui, which can be opened with the F1 key (or by executing the openspace.gui.toggle() script). The main interesting factors in this GUI are the Origin, which defines the camera pivot point, the Delta time, which determines how fast in-game time progresses relative to the wall clock, and lastly the different properties (either global properties or scene graph node properties). Every property is accessible through the openspace.setPropertyValue(...) or openspace.getPropertyValue(...) functions; the first argument of these functions is the URI for the property, which is displayed in a hover text above the specific property. Both functions accept wild cards (*) which are matched against all URIs. For example: openspace.setPropertyValue("*Trails.renderable.enabled", false) will disable all scene graph nodes that end in Trails.

Image projections in OpenSpace

A big part of the build-a-thon is dealing with image projections onto Saturn and Mercury. The best way to learn how to use the image projection capabilities is to look and understand the existing modules, which already exist in OpenSpace (newhorizons, rosetta, and osirisrex). New Horizons is probably the most similar as it also projected onto a planet (RenderablePlanetProjection renderable). This is way we are taking New Horizons / Pluto as an example.

The RenderablePlanetProjection has three important keys, which determine the image projections:

  1. Projection: Defining the main projection characteristics

    1. Sequence: A folder in which the projected images are kept. This is the only part where New Horizons is not 100% applicable to Cassini and Messenger, as New Horizons is using a hybrid approach to images, so for this part alone, we would refer to rosetta/67P/67P.mod instead. The SequenceType should be image-sequence so that the Sequence folder is scanned and all files in there are used for projections (see LabelParser section below).

    2. Observer: The NAIF name of the observer of this RenderablePlanetProjection

    3. Target: The NAIF name of the target

  2. DataInputTranslation: Defining a dictionary of mappings and possible translations

    1. Instrument: A list of the different instruments that are used to map onto the planet

    2. Target: Definitions regarding the image projection target; READ defines the values of the label files (see LabelParser section below) that are read. Convert allows multiple definitions to be translated into a single value. In the Rosetta example, some label files refer to 67P Churyumuv-Gerasimenko as CHURYUMOV, CHURYUMOVGERASIMENKO11969R1, CHURYUMOVGERASIMENKO, or CHURYUMOV-GERASIMENKO1(1969R1), but we only want to use CHURYUMOV-GERASIMENKO

  3. Instrument: The definition of the main instrument

LabelParser and Label Files

For successful image projections, we not only need the images (currently in *.jpg format), but also information about the instrument, acquisition and exposure time, and which object was targeted. This information comes in a so-called Label file. These label files must be located in the same directories as the images (see the Sequence key from above) and must be named the same except the extension. For example the newhorizons/pluto/pluto/images folder contains pairs of files such as lor_0299122189_0x630_sci_3.jpg and lor_0299122189_0x630_sci_3.lbl. The label files are text files that contain the necessary meta information. Each line can define a value in the form KEY = VALUE and the file must be terminated with an END. The bare minimum that a label file must specify are the TARGET_NAME, START_TIME, STOP_TIME, and INSTRUMENT_ID. In some cases (like Rosetta), the label files for the released images are publicly available, in other cases they have to be scraped from the internet and semi-manually be generated (see the modules/newhorizons/scripts folder for an example of these scrapings).