What's So Bad About STL Files?

The explanation is simple, if you use enough words…


Table of Contents:


Introduction

(Top)

STL files are a mainstay of consumer 3D printing; the term is almost like “frigidare” in the household refrigerator domain. They are one way to export our futzing around in CAD programs to make a model, suitable for printers’ slicer programs to make the slice files the printer uses to do its thing. You may hear occasionally about how STL files aren’t good for this use, with no explanation as to why that is the case. Then, when you go alooking for such, you’ll find all manner of hand-waving about ‘incompleteness’, referencing omission of things like measurement dimensions and color. Well, the fundamental reason is a bit more ‘fundamental’ than that, and has to do with things rooted in the mathematics of representing three-dimensional things. I’m going to attempt an explanation of that, and some perspective to take away regarding using STL files with ’eyes-wide-open’.

Representing Three-Dimensional Objects

(Top)

First, I’m going to assume you are familiar with coordnate systems used in CAD and 3D printing. Suffice it to say that we’re talking about the X, Y, and Z numbers, along axes that converge on an origin, which is at 0,0,0 in XYZ coordinates. If you had any algerbra in your youth schooling, that would be an extension of the XY two-dimensional stuff you did in graph plotting; just add a Z axis shooting out at your face, perpendicular to the other two. If not, Wikipedia can tell you more than you ever wanted to know:

https://en.wikipedia.org/wiki/Cartesian_coordinate_system

Basic two-dimensional objects can be described as a collection of points in XY coordinates that form an outline. This is called a polygon, useful in its own right, but not equipped to describe something in three dimensions. That is the purpose of a mesh, which is a collection of polygons that share common edges. The “share common edges” part is important to why STL files are incomplete, so keep that in mind. Meshes describe the boundary of an object, or one aspect of its ‘surface’, with other attributes being color, reflectivity, texture, etc. Meshes are sometimes called “B-rep”, or “boundary-representation” things, one part of the description of an object. The boundary of an object is the essential thing for 3D printing, because it determines where material is to go, and conversely, not go.

Meshes can be defined with all manner of polygons, but the meshes that have the best modifiability are triangle meshes. There’s a lot of math out there to do useful stuff to triangle meshes; indeed, most mesh tools for programmers have a ’triangulate’ tool to make equivalent triangle structures of those messy polygons. You can easily see the triangles of an object in most CAD programs when you turn on the ‘wireframe’ view option. One thing to keep in mind as you make a model is, each triangle needs to be modified when you do things like move, scale, or rotate on the object. The more triangles the object has, the larger the burden on your computer to compute all the changes.

Basic Encoding of Triangle Meshes

(Top)

Okay, that section title might sound a bit wonky, but it’s at the heart of why STL files are problematic. What I’m going to describe here is the essential information needed to represent a mesh, which I’ll then use to point out the STL problems.

The goal of a mesh that represents an object boundary is to be “manifold”, that is, no gaps or holes. “Tight” is a more-informal adjective, “tight meshes” don’t have holes. This is important to 3D printing in that holes can create ambiguity about whether or not to put material at a given point in space. Really though, whether a given hole presents that problem depends on its size and how resolute is the 3D printing mechanism, which is why you can usually print a STL file that has holes. More on this in a bit.

So, a mesh consisting of a collection of triangles with common edges needs to identify both the points in space of the triangles, and how those points make common edges. Files that do this have two lists:

  1. The list of all the points of all the triangles, and,
  2. The list of all the triangles, where each triangle is defined by referencing its points in the point list.

That way, common edges can be readily identified where two triangles share two points.

The list of points looks something like this:

0.0,0.0,0.0
10.0,10.0,10.0
10.0.0,0,0.0
0.0,10.0,0.0
...

where each set of three numbers is a XYZ coordinate using floating point numbers.

The list of triangles looks similar:

1,3,2
4,1,3
...

but the numbers of the triangle list are not coordinates, they’re indexes to the points in the point list. The first two triangles of this example share the edge made by points 1 and 3, ta-da, a common edge, readily identifiable by the indexes.

One more important aspect of encoding this information is the order in which points are identified in the triangle list. In a mesh, a triangle essentially has two “sides”, one facing out and the other facing in. This is represented by the order of the point indexes, which should run counter-clockwise with respect to the side facing out. This is just a convention that all the software recognizes, “winding CCW”. But, this is more important to some aspects of manifold-ness needed to render an image of the object, less-so to printing. But, if you’re being told by some software that your mesh isn’t manifold and you can readily identifiy the points and the triangle indexes, it’s likely one or more of the triangles aren’t “wound CCW”.

Why STL Is Deficient

(Top)

Simply, STL files combine both lists. STL files define each triangle as a list of the three XYZ coordinates. So now, each point value can exist in multiple triangle definitions. If the coordinate numbers are exactly the same, shouldn’t be a problem, right? Indeed, STL files are usually imported with code that builds the triangle list with index numbers by using “de-duplication” logic to assert that two numbers are the same to make the point list, but that ability is compromised by using floating point numbers for coordinates. Without getting into all the reasons floating point numbers can diverge slightly as they are manipulated, just recognize that is possible, and modifying STL triangle data directly can introduce differences that make identifying common points, and edges, problematic.

Some STL file import code doesn’t even try to de-duplicate, it just makes separate points with the same XYZ values for the point list. That then exposes the disconnect to anything the software might do to the mesh, making each floating point operation complicit in destroying the manifold-ness of the mesh. Horrors…

The essential point is that STL files don’t capture enough information to unambiguously define the surface boundary of a physical object. If any of this information is missing, determining whether a particular point in space is inside or outside of the object becomes a guessing game for the software. Making slices for 3D printing may tolerate some of this guess-iness, but at some point it’ll fail, either keeping the slicing software from producing the slice file or worse, showing up in the finished print.

Almost Any Other Format Is Better Than STL

(Top)

If a mesh file format encodes the information like I described above, separate point coordinate and triangle index lists, enough information is presented to preserve the manifold-ness of the mesh. 3MF does this, so does OBJ. They’re “clunky” file formats for other reasons, but they respect the ’two-list’ mesh encoding convention. There’s a lot of posting on the internets about how much better is 3MF, and it indeed passes more information. But, it’s XML-encoded, which is a rather verbose way of schlepping data*. Thing is, it allows multiple meshes to be stored as ‘objects’, and allows all sorts of other information to accompany it, like color. These aspects will become more important as color printers take the stage. I’ve started encoding all my CAD output as 3MF, mainly to avoid the STL problem, but also to “future-proof” my work.

Now, if you don’t modify your STL files before printing, you reduce your exposure to non-manifold badness. After all, with today’s 3D printing mechanisms the important thing for making things work is, “is this point in or out of the thing?”, and extant holes may just not be big enough to vex that. But, you don’t eliminate the problem, so YMMV.

Anyway, hope this helps…


*Of note, 3MF files usually end up being smaller than their STL equivalents due to zip file encoding and the elimination of vertex duplication.