-
Notifications
You must be signed in to change notification settings - Fork 210
Adding 3D models
EmptyEpsilon can use Wavefront (.obj) models. To make new OBJ models available for use:
-
Place the OBJ files and any textures in the
EmptyEpsilon/resourcesdirectory. -
Add a
ModelData()entry toEmptyEpsilon/scripts/model_data.lua.Debris in
model_data.luais a minimal example:model = ModelData() model:setName("debris-cubesat") model:setMesh("mesh/various/debris-cubesat.obj") model:setTexture("mesh/various/cubesat.png") model:setScale(10) model:setRadius(100)
- adds a model named
debris-cubesatfrom OBJ file atresources/mesh/various/debris-cubesat.obj - uses
resources/mesh/various/cubesat.pngfor its texture - scales the model up 10x
- sets its in-game collision radius to 100 meters, independently of the model's scale
Given this example:
model = ModelData() model:setName("gentest") model:setMesh("gentest.obj") model:setTexture("gentest.png") model:setSpecular("gentest_specular.png") model:setIllumination("gentest_illumination.png") model:setNormalMap("gentest_normal.png") -- development builds only model:setScale(24) model:setRadius(120) model:addEngineEmitter(-13, -2.1500, 0.3, 0.2, 0.2, 1.0, 3.0) model:addEngineEmitter(-13, 2.1500, 0.3, 0.2, 0.2, 1.0, 3.0)
EmptyEpsilon:
- adds a model named
gentestfrom OBJ file atresources/gentest.obj - uses
resources/gentest.pngfor its texture - uses
resources/gentest_specular.pngfor its optional specular/reflective map - uses
resources/gentest_illumination.pngfor its optional illumination map - uses
resources/gentest_normal.pngfor its optional normal map (development builds only as of Dec. 2025) - scales the model up 24x
- sets its in-game collision radius to 120 meters, independently of the model's scale
- adds two engine effect emitters, located at Blender coordinates X -13 (13 units backward), Y -2.15 and 2.15 (left and right), and Z 0.3 (up), with percentile colors red 20% (0.2), green 20% (0.2), and blue 100% (1.0), and a radius of 3 units in Blender.
- adds a model named
-
If you copied the above code, adjust your ModelData properties appropriately.
-
Ensure that your models are UV unwrapped. Many, but not all, models available online in OBJ format or for game development purposes are already UV unwrapped, but models available in STL format or for 3D printing generally are not.
If your model is not UV unwrapped, unwrapping it yourself can be a complex subject with details that depend on the software you used to create or convert your 3D models. Some tools can automate at least some of the work; for example, here's a beginners' tutorial on UV unwrapping in Blender.
-
Ensure that your model's normals are all facing outward. EmptyEpsilon culls backfaces, which means if a polygon/vertex normal is facing inward, EmptyEpsilon won't render it, which can make parts of the model seem unexpectedly transparent.
Model with correct normals:
Model with inverted normals:
To invert normals in Blender, enter edit mode with Tab, press a to select all, press Shift-n to recalculate normals, and select "Inside" to invert them.
For a visual aid in identifying inverted normals, enable "Face Orientation" in the Geometry section of the Show Overlays menu. This colors all faces with inverted normals.
-
If you need to rotate a model, do so from a 3D modeling program. Some example programs include:
- Blender (Windows, macOS, Linux): Note that positive values are forward on the X axis are up on the Z axis by default in Blender, which differs from the exported OBJ.
- Misfit Model 3D (Windows; macOS and FreeBSD experimental)
-
EmptyEpsilon doesn't support OBJ materials (
.mtlfiles). Place separate images in theresourcesdirectory to use as textures, preferably as PNG images alongside your model's OBJ file.
Since model_data.lua is a Lua script file, you can use loops, functions, or other code to add many similar models.
EmptyEpsilon uses OpenGL's left-handed coordinate system, in which negative values on the Z axis face forward and Y faces up. 3D coordinates (vec3) in these functions translate to X, Y, Z values in Blender, which uses a right-handed, X-forward, Z-up coordinate system.
| Blender default | EmptyEpsilon | Relative direction from center |
|---|---|---|
| X | -Z | Forward of the center point |
| Y | X | Right of the center point |
| Z | Y | Up from the center point |
To view coordinates in Blender, press Tab to enter edit mode, then n to open the Transform panel.
For example, a point reported at X -24, Y 1, Z 20 in Blender is 24 meters forward, 1 meter to the right, and 20 meters above the center point. In EmptyEpsilon, this point is at Z 24, X 1, Y 20.
-
:setName(string name): The model's name, which is used to refer to the model in ship template scripts or entity model definitions. -
:setMesh(string mesh_name): The relative path to the mesh file within either theresourcesdirectory or a pack in thepacksdirectory. -
:setTexture(string texture_name): The relative path to a texture file... -
:setSpecular(string specular_texture_name): ... specular map ... -
:setIllumination(string illumination_texture_name): ... and illumination map. -
:setNormalMap(string normal_map_texture_name): ... and normal (simulated depth in detail) map, in development builds only. -
:setRenderOffset(vec3 mesh_offset): Offset the mesh's position by this amount on each axis. Useful to recenter the model if its center point in the mesh file is not at0, 0, 0. -
:setScale(float scale): Scale the mesh by this multiplier. -
:setRadius(float radius): Set the mesh's effective radius in in-game meters for collision purposes. Colliders are circular by default. -
:setCollisionBox(vec2 collision_box): Set the width and height, respectively, of a rectangular collider if preferable to a circular collider. -
:addBeamPosition(vec3 position): Add the origin point of a beam emitter at these coordinates on the unscaled model. -
:addTubePosition(vec3 position): Add the origin point of a weapons tube at these coordinates on the unscaled model. -
:addEngineEmitter(vec3 position, vec3 color, float radius): Add the origin point of an engine emitter at thepositioncoordinates on the model, with a normalized RGBcolor(i.e.1.0, 0.5, 0.1representing 100% red, 50% green, 10% blue), and aradiusfor the particles created for the emitter's trail.
Create your model facing in the negative direction of X (with points intended to be the front of the ship having negative X values) with Z as up (points intended to be the top of the ship having positive Z values).
Pictured model is Imperial from LowPoly Models by Quaternius, CC0
If you're exporting Wavefront OBJ files from Blender, make sure to UV unwrap your model first, and ensure that UVs and normals are exported, that modifiers are applied, and that forward is -Z and up is Y. For example, use the following export settings:
- Blender 2.8:
- Blender 4 and 5:
As of December 2025, EmptyEpsilon doesn't use materials or support model animations.
You can't use Blender's procedural materials natively in EmptyEpsilon, and you must bake them to texture images instead.
- Home
- ECS
- Stations
- Main Screen/Captain
- 5-6 Player Crews
- 3-4 Player Crews
- 1 Player Crew
- Game Master
- Additional Stations and Views
- Setting up a Game
- Lore
- Expanding the Game
- Additional Features
- Building from Source
