This document summarizes my notes from our meetup discussion/exploration of STL files.
The Stereolithography (STL) format is a de-facto standard, meaning that the format was created by a company (3D Systems) for their own product and became an industry standard as other manufacturers copied the 3D Systems format. The best early reference is StereoLithography Interface Specification, 3D Systems, Inc., October 1989 but I could not find a copy of that paper online. Other online references such as Library of Congress and Wikipedia have become the de-facto standard.
STL has TWO file formats: ASCII and binary. The text format is sort-of human readable. The binary version is intended for machine use.
An ASCII STL file starts with the line:
solid name
where name is an optional string (although if name is omitted there MUST be a space after solid). The remainder of the line is ignored and may store extra data.
After the name the file contains a list of facets. A facet is a directed triangle. Directed triangle means that the triangle has an inside and an outside. The outside is defined in TWO WAYS. First, the definition of the facet includes a normal. The normal points from inside to outside. Second, the facet's vertices are listed in order using right hand rule with the thumb pointing toward the outside of the triangle. Each facet is defined by this text data structure:
facet normal ni nj nk outer loop vertex v1x v1y v1z vertex v2x v2y v2z vertex v3x v3y v3z endloop endfacet
where each n or v is a floating-point number in sign-mantissa-e-sign-exponent format, e.g., 2.648000e-002. The file concludes with:
endsolid name
The following is a direct cut and paste from the wikipedia page.
Because ASCII STL files can be large, a binary version of STL exists. A binary STL file has an 80-character header that is generally ignored, but should never begin with the ASCII representation of the string solid, as that may lead some software to confuse it with an ASCII STL file. Following the header is a 4-byte little-endian unsigned integer indicating the number of triangular facets in the file. Following that is data describing each triangle in turn. The file simply ends after the last triangle.
Each triangle is described by 12 32-bit floating-point numbers: 3 for the normal and then 3 for the X/Y/Z coordinate of each vertex – just as with the ASCII version of STL. After these follows a 2-byte ("short") unsigned integer that is the "attribute byte count" – in the standard format, this should be zero because most software does not understand anything else.[9]
Floating-point numbers are represented as IEEE floating-point numbers and are assumed to be little-endian, although this is not stated in documentation.
UINT8[80] – Header - 80 bytes
UINT32 – Number of triangles - 04 bytes
foreach triangle - 50 bytes
REAL32[3] – Normal vector - 12 bytes
REAL32[3] – Vertex 1 - 12 bytes
REAL32[3] – Vertex 2 - 12 bytes
REAL32[3] – Vertex 3 - 12 bytes
UINT16 – Attribute byte count - 02 bytes
end
STL file format is very simple. Any surface can be approximated by a mesh of triangles. It is possible to increase the accuracy of the approximation by increasing the number of triangles. Flat surfaces can sometimes be modeled perfectly.
The file format does not include any mechanism for metadata such as colour, notes, manufacturing equipment, etc.
It's easy to make a mistake on the direction of a triangle. Sometimes the normal doesn't match the order of the vertices.
Adjacent triangles share two vertices. The vertices must be EXACTLY the same in the two facet definitions. Even a small difference in the floating point numbers creates a hole. This can happen when software approximates a curved surface. Compare to the 3mf file format which first defines the vertices then applies the ennumerated vertices to the facets.
Microsoft 3d builder comes pre installed in many versions of Windows and automatically fixes some of these problems.
A cube has six square faces. Each square is two triangles. So a cube can be modeled perfected by twelve triangles. Here's an ASCII STL file for a unit cube with one corner at (0,0,0) and the opposite corner at (1,1,1) and an image courtesy of wikipedia (M6oh7z, CC BY-SA 4.0
solid Cube facet normal 0.0 0.0 -1.0 outer loop vertex 0.0 0.0 0.0 vertex 1.0 0.0 0.0 vertex 0.0 1.0 0.0 endloop endfacet facet normal 0.0 0.0 -1.0 outer loop vertex 1.0 0.0 0.0 vertex 1.0 1.0 0.0 vertex 0.0 1.0 0.0 endloop endfacet facet normal 0.0 0.0 1.0 outer loop vertex 0.0 0.0 1.0 vertex 0.0 1.0 1.0 vertex 1.0 0.0 1.0 endloop endfacet facet normal 0.0 0.0 1.0 outer loop vertex 1.0 0.0 1.0 vertex 0.0 1.0 1.0 vertex 1.0 1.0 1.0 endloop endfacet facet normal 0.0 -1.0 0.0 outer loop vertex 0.0 0.0 0.0 vertex 0.0 0.0 1.0 vertex 1.0 0.0 0.0 endloop endfacet facet normal 0.0 -1.0 0.0 outer loop vertex 1.0 0.0 0.0 vertex 0.0 0.0 1.0 vertex 1.0 0.0 1.0 endloop endfacet facet normal 0.0 1.0 0.0 outer loop vertex 0.0 1.0 0.0 vertex 1.0 1.0 0.0 vertex 0.0 1.0 1.0 endloop endfacet facet normal 0.0 1.0 0.0 outer loop vertex 1.0 1.0 0.0 vertex 1.0 1.0 1.0 vertex 0.0 1.0 1.0 endloop endfacet facet normal -1.0 0.0 0.0 outer loop vertex 0.0 0.0 0.0 vertex 0.0 1.0 0.0 vertex 0.0 0.0 1.0 endloop endfacet facet normal -1.0 0.0 0.0 outer loop vertex 0.0 1.0 0.0 vertex 0.0 1.0 1.0 vertex 0.0 0.0 1.0 endloop endfacet facet normal 1.0 0.0 0.0 outer loop vertex 1.0 0.0 0.0 vertex 1.0 0.0 1.0 vertex 1.0 1.0 0.0 endloop endfacet facet normal 1.0 0.0 0.0 outer loop vertex 1.0 1.0 0.0 vertex 1.0 0.0 1.0 vertex 1.0 1.0 1.0 endloop endfacet endsolid Cube