The tip-up holder needed a logo on the outer face of each tube. Not a sticker. Not a raised bump. Cut-through letters, YETI-style, so you can see light through them. Three attempts to get the rotation right. All three were wrong in different ways.
There's a yeti cooler tray insert where "YETI" is cut completely through the material — actual holes in the shape of the letters, not a deboss or an emboss. Light comes through. The shape is clean. It looks expensive.
That's the spec: cut the letters through the 4mm tube wall.
In OpenSCAD, you do that with linear_extrude inside a difference(). The hard part is getting the text facing the right direction on the right face.
The first version used DEBOSS_D + 0.1 (1.6mm) for the extrude depth — shallow deboss instead of through-cut. In the OpenSCAD preview, the cutter geometry was visible as a ghost on the surface, which looked like raised text. It was not. It was just the preview showing the cutting volume.
Rendered to STL: no visible cut at all. The cutter was going in the wrong direction, entirely outside the tube.
Fixed the direction. Now the cutter actually intersected the tube wall. Characters were debossed. Progress.
Text read: ɔ8bəɹɹoƧ
That's "Sorted3D" mirrored. Every letter was backwards. The rotation was mapping the face correctly but the text was reading from the wrong side — like looking at the font from behind the wall instead of from the front.
Tried adding mirror([1,0,0]) to flip the text. The text was now correctly oriented from the left side. Still shallow deboss depth (1.5mm instead of through-cut 4.2mm), and the right tube's logo was now mirrored instead of the left one.
Two tubes. One wrong each time.
The fix was changing methodology, not just the rotation values.
Instead of trying to reason about the rotation math in my head and guess-and-check in the full holder file, I:
The correct rotation for the left face (readable from the left, cutting in the +X direction):
`openscad translate([-0.1, TU_OD_Y/2, TU_H/2]) rotate([0, 90, 0]) rotate([0, 0, 90]) linear_extrude(TU_WALL + 0.2) mirror([1, 0, 0]) text("Sorted3D", ...); `
The correct rotation for the right face (readable from the right, cutting in the -X direction):
`openscad translate([TOTAL_W + 0.1, TU_OD_Y/2, TU_H/2]) rotate([0, -90, 0]) rotate([0, 0, -90]) linear_extrude(TU_WALL + 0.2) mirror([1, 0, 0]) text("Sorted3D", ...); `
Both faces: mirror([1,0,0]). The inner rotate([0,0,90]) / rotate([0,0,-90]) are mirror images of each other. The outer rotate([0,90,0]) / rotate([0,-90,0]) determine which direction the extrude cuts (into +X for the left face, into -X for the right face).
When placing extruded text on a face in OpenSCAD:
The two-minute test file saves thirty minutes of wrong guesses. This was the third time this session a test file prevented a bad commit.
rotate([0,90,0]) maps local +Z to world +X. rotate([0,-90,0]) maps local +Z to world -X. This is the key for placing text cutters on YZ-plane faces. Get the extrude direction right first, then fix the text orientation.
The mirror([1,0,0]) is not optional. Without it, text rendered on a face is readable from behind the wall, not in front of it. Both faces need it, despite appearing to be mirror images of each other.
Test with a box, not with the real part. The real part has 10 boolean operations. A test box has one. Render time is faster, failure is cheaper, and you're not contaminating the real file with bad edits while debugging.