About

Erizo is a sequel to fstl, a fast viewer for STL files.

A few months after developing fstl, my friend Fogleman wrote meshview, which is slightly faster.

Erizo is my response to this blatant affront; it also includes a few new features, and explores a particular programming aesthetic.

Terrace bridge
Model by Jennifer Keeter, showing wireframe rendering

Performance comparison

Time to first frame RAM usage Application size
fstl 1.34 sec 63.2 MB 9.5 MB
meshview 0.413 sec 248.3 MB 9.2 MB
Erizo 0.308 sec 60.3 MB 889 KB

These numbers are generated from this 1.95M triangle model:

Porsche

(Model courtesy of Porsche)

The rest of this document explores what makes Erizo so fast, in comparison to its predecessors.

Native UI

My previous project, fstl, uses Qt for its UI. This means it has native UI dialogs and menus, but adds overhead to startup.

meshview uses GLFW, which is extremely low-overhead, but simply provides an OpenGL context. Files are specified on the command line, and there aren't any native UI elements.

Erizo aims for the best of both worlds: It uses GLFW for speed, but supplements it with platform-specific code for native file dialogs and menus. The only downside is needing to write per-platform code, but that comes out to a few hundred lines per OS.

(Also, I edited GLFW to skip a slow startup step)

Fast mesh indexing

The critical path for rendering a first frame looks something like this:

critical path

Shortening any step of this path will improve the time to the first frame. Indexed rendering is a strategy for reducing the amount of data sent to the GPU.

Consider the following four-triangle mesh:

Indexed mesh with four triangles and five vertices

A naive representation uses one list, containing every triangle:

  triangle 0: [[x0, y0, z0], [x1, y1, z1], [x2, y2, z2]]
  triangle 1: [[x0, y0, z0], [x2, y2, z2], [x3, y3, z3]]
  triangle 2: [[x0, y0, z0], [x3, y3, z3], [x4, y4, z4]]
  triangle 3: [[x0, y0, z0], [x4, y4, z4], [x1, y1, z1]]

However, this duplicates data, because vertices are shared between more than one triangle. Indexed rendering uses two lists: one list of vertex positions, and a separate list of triangles:

  vertex 0:   [x0, y0, z0]
  vertex 1:   [x1, y1, z1]
  vertex 2:   [x2, y2, z2]
  vertex 3:   [x3, y3, z3]
  vertex 4:   [x4, y4, z4]

  triangle 0: [v0, v1, v2]
  triangle 1: [v0, v2, v3]
  triangle 2: [v0, v3, v4]
  triangle 3: [v0, v4, v1]

This reduces the amount of data sent and stored on the GPU, at the cost of extra computation to build the indexed representation.

There's an intesting tradeoff here. We can do the mesh indexing step in parallel, but if it takes too long, then the critical path changes:

critical path with slow indexing

fstl, which uses indexed rendering, falls into this trap: its implementation of mesh indexing is slow enough that it eliminates the benefits of sending less data to the GPU (for large models).

meshview does not use indexed rendering, so it's slightly faster for large models.

Erizo does use indexed rendering, but the mesh indexing step is blindingly fast, so it completes while waiting for the window + OpenGL context to become available.

Ascetic programming

Inspired by Our Machinery / flooh / the Handmade Manifesto / Eskil Steenberg, Erizo is implemented in relatively austere C.

This was a delibrate aesthetic choice, and I don't regret it for a project of this scale – everything builds quickly, runs quickly, and it's a fun style of code to write.

All of the dependencies are included in the repository and statically linked, so I can distribute a single binary; cross-compiling for Windows works out of the box using x86_64-w64-mingw32-gcc.

Code

Erizo is on Github