What 2,172 triangles tells you about a text-to-STL export
A text field that produces an STL file looks deceptively simple. Type a word, pick a size and a depth, download a mesh. But the exported numbers are rarely the numbers you typed, and a letter that renders cleanly on scre
A text field that produces an STL file looks deceptively simple. Type a word, pick a size and a depth, download a mesh. But the exported numbers are rarely the numbers you typed, and a letter that renders cleanly on screen can disappear in a slicer at a 0.4 mm nozzle.
This note comes from a browser-based text-to-mesh tool in the Voxel3D project. It is about the step after geometry exists, not about image generation. For the earlier image preparation and generation workflow, see the 3d model from image guide. Here the input is a line of text and the output is a binary STL.
1. Extruding outlines is not the same as rendering a font
A screen font paints pixels. A printable letter is a closed solid with a top face, a bottom face and side walls. The generator constructs outlines from a bundled sans-serif font, extrudes them along Z, and writes triangle geometry. A space remains a gap, and separate letters remain separate solids.
Two consequences follow. First, the download is usually several disconnected parts, not one nameplate. There is no rectangular sign, no mounting holes and no backing plate unless you add them in an editor. Second, character coverage matters: this tool supports Latin letters, digits and common punctuation, and rejects unsupported characters rather than silently substituting a missing-glyph box into your geometry.
2. Verify the file instead of trusting the UI
A binary STL has an 80-byte header, a 32-bit triangle count and then exactly 50 bytes per triangle. That makes the exported numbers cheap to check independently:
# inspect_text_stl.py
import json
import struct
import sys
from pathlib import Path
def read_binary_stl(path):
data = Path(path).read_bytes()
if len(data) < 84:
raise SystemExit("Not a binary STL")
count = struct.unpack_from("<I", data, 80)[0]
if len(data) != 84 + count * 50:
raise SystemExit(
f"Header says {count} triangles; file holds {(len(data) - 84) // 50}"
)
xs, ys, zs = [], [], []
for i in range(count):
# 12 floats = normal (3) + three vertices (9), then a 2-byte attribute count
v = struct.unpack_from("<12f", data, 84 + i * 50)
xs.extend(v[3::3])
ys.extend(v[4::3])
zs.extend(v[5::3])
lo = [min(xs), min(ys), min(zs)]
hi = [max(xs), max(ys), max(zs)]
return {
"triangles": count,
"min_mm": [round(x, 2) for x in lo],
"max_mm": [round(x, 2) for x in hi],
"extents_mm": [round(hi[i] - lo[i], 2) for i in range(3)],
}
if __name__ == "__main__":
print(json.dumps(read_binary_stl(sys.argv[1]), indent=2))
python inspect_text_stl.py nameplate.stl
In our browser test, the default string at a 20 mm type size and 3 mm depth produced 2,172 triangles, with reported bounding dimensions of approximately 104.74 × 20.78 × 3 mm. Those are measurements of the exported mesh, not a ruler measurement of a physical print. The script above is how you reproduce the geometry part of that check from your own download.
An STL carries no dependable unit declaration. The millimetre interpretation here comes from the tool's documented scale, not from the file format.
3. The size field is not the finished dimension
The 20 mm type size did not yield a 20 mm tall mesh: the bounding height was about 20.78 mm, and the full string was about 104.74 mm wide. Uppercase letters, lowercase letters and descenders have different extents, so a single size parameter cannot predict the outside bounding box of an arbitrary string.
This matters when lettering has to fit a recess or a fixed plate. Compare the complete string width and height against the available space, then resize and regenerate deliberately. Depth is a separate axis: increasing it from 1 mm to 3 mm makes a thicker standing letter, but it does not widen the narrowest stroke in the XY plane, so it cannot rescue an outline that is too thin to print.
4. Stroke width decides more than triangle count
For FDM, the useful starting check is the narrowest stroke in the actual generated outline. Prusa documents an example 0.4 mm nozzle profile with roughly 0.45 mm extrusion width, where one perimeter is about 0.45 mm and two are about 0.9 mm. Those are profile-dependent reference values, not a promise that any 0.45 mm feature will print cleanly; inspect the line widths in your own slicer profile.
A thin stroke can vanish during slicing while the shaded mesh still shows it. Check the counters inside A, B, e and R as well as the outer strokes: a closed counter makes a label unreadable. A sans-serif typeface avoids some fragile decorative details, but the font choice alone does not establish a minimum printable size. If a stroke is too narrow, increase the letter size or choose a more robust outline in an editor.
5. Relief depth is a layer-height decision
Relief height is easier to reason about in layers than in abstract millimetres. At a nominal 0.2 mm layer height, a 0.8 mm raised feature is four layers and 1.2 mm is six. That arithmetic helps you plan an experiment; it is not a tested print profile. First-layer adhesion, nozzle width, material and slicer settings still dominate the outcome. Start with a small sample containing the most difficult characters before committing to a full sign.
Printing the flat backs of the letters against the build plate is usually the simplest orientation to inspect. If you add a backing plate, do the union as an explicit modeling step and examine the sliced layers through the join — visually overlapping a plate and the letters is not evidence of a clean solid.
6. What this measurement does not establish
Triangle count, bounding extents and a successful file parse say nothing about whether the object is watertight, whether the letters are joined, or whether a printed part will survive handling. We have not physically printed the example projects described here; they are preparation decisions, not print results.
Before distributing your own file, open it in a slicer, confirm every intended letter and counter is present, review the first layer for adhesion and the later layers for missing strokes, and check the supports at your chosen scale. When you change the string or size, save the output under a distinct filename so an older test does not end up on the printer.
The useful deliverable is a mesh whose dimensions and limits you have measured, not just a file with an .stl extension.
References and disclosure
This post was drafted with AI assistance from the project's tool documentation and its recorded browser measurement. The inspection script is a standalone reader for binary STL files. All model illustrations in this project are digital renders, not photographs of a physical print.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.