Adding Third-Party Libraries to Unreal Engine : NASA's SPICE Toolkit (Part 1)
Note: This is the first post of a 5 part series
Unreal Engine : What problem are we going to solve?
Sure, Unreal Engine is great. It has almost everything we need, right?
Well, maybe not everything. Most “middlewareish” things a game dev might be interested in have already been integrated or implemented as a plugin by somebody, somewhere. Everything from Appsflyer to Zen Dev and supercool things in-between like Cesium.
Often - especially when we’re on a leading edge - there’s a tech critical to our mission that hasn’t yet been pulled into UE. I found myself in such a position not long ago so I thought I’d write up our own solution real quick in case it’s helpful to others.
SPICE: Spacecraft Planet Instrument C-matrix Events
In my particular case, I wanted to leverage a very powerful toolkit available from NASA’s Navigation And Ancillary Information Facility (NAIF). NAIF is a part of the storied Jet Propulsion Laboratory (JPL). The toolkit’s name is SPICE.
SPICE is an acronym for “Spacecraft Planet Instrumentation C-matrix Events”.
C-matrix stands for “Camera Matrix”. “Camera Matrix” is a term often used in regards to spacecraft orientation. If you want to know what a spacecraft’s camera is pointing at, you’ll need to compute the C-matrix!
SPICE was originally developed in FORTRAN, which is commonly used for super scientific things… It’s for Rocket Science type stuff, done by (real) Rocket Scientists.
And the library is amaaaaaaaaaaaaaazing. When powered by the “right” data SPICE is accurate down to around 2 centimeters for things as far away as one of the Voyager probes - which are outside the solar system.
We can do things like compute positions of planets, moons, spacecraft. If we want, we can compute something’s apparent position (where it appears to be) that accounts for the finite speed of light. We can account for the relativistic effects of gravity on the speed of a spacecraft’s clock (on earth versus in outer space). In real life, it’s used for such things as determining exactly what direction to point an antenna to send a message that arrives exactly at a space probe’s position at exactly the right time. SPICE can even tell you the velocity between various “fixed” points on earth. “Velocity between ‘fixed’ points?”, you ask. Yup. Due to tectonic plate motion.
SPICE data comes in the form of Spice Data Kernels. These “Kernels” are data files, and with them SPICE can compute the positions and orientations of pretty much anything that’s flown or will fly through the heavens.
SPICE Data Kernels are also available to describe the surface geometry of many interesting locations (moons, planets, asteroids, comets). JPL and ESA (among others) have made much high quality data available for general usage.
Now, while it could be an interesting challenge integrating FORTRAN into Unreal Engine there’s a better way. NAIF supplies SPICE subroutine libraries in a C wrapper. The C library even comes with prebuilt lib binaries for many relevant platforms Windows, Mac, Linux, etc… But sadly, not Xbox or Playstation, … so we’ll need to build our own Spice libs for consoles (and, we will).
What we’re going to do:
This blog series is a 5 parter, broken down into:
- The goal, defined (that’s this post!)
- A range possible solutions (none are wrong)
- A solution (the right one)
- Implementation Details
- The results (code is here)
The goal, defined:
Integrate NAIF’s C-SPICE toolkit and UE5.
- C++ API exposed to UE5
- Native Unreal Engine Data Types for SPICE
- Blueprints API
Using only Blueprints I should be able to:
- Complete any of the SPICE toolkit tutorials
- Compute the position / orientation of spacecraft / planets / moons / etc for any ephemeris time
- Record Unreal Engine values in native SPICE kernel data files
Example: C++ API
/** Determine the state (position, velocity) of an orbiting body from a set of elliptic, hyperbolic, or parabolic orbital elements. See: https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/conics_c.html Google: cspice conics_c */ UFUNCTION( BlueprintCallable, Category = "Spice | Api | Conics", meta = ( ExpandEnumAsExecs = "ResultCode", ShortToolTip = "Determine state from conic elements", ToolTip = "Determine the state (position, velocity) of an orbiting body from a set of elliptic, hyperbolic, or parabolic orbital elements" )) static void conics( ES_ResultCode& ResultCode, FString& ErrorMessage, const FSConicElements& elts, const FSEphemerisTime& et, FSStateVector& state );
Example: Unreal Engine Data Types
Sooo buckle up, Spacekateers, we’re in for a pretty sweet ride!
In Part 2 of this series we’ll take a look at a few possible solutions.