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.
Performance comparison
Time to first frame | RAM usage | Application size | |
fstl
| |||
meshview
| |||
Erizo | 0.308 sec | 60.3 MB | 889 KB |
These numbers are generated from this 1.95M triangle model:
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:
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:
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:
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
.