Having built the simplest possible 3D model generator I soon discovered surprising complexity.
Following on from:
I had an idea to quickly producing something interesting.
I would print two objects: a shape with a random surface, and another shape with the opposite surface, so that it should be possible to slot the two together.
In this way there should be two surprisingly complicated shapes that combine to form one surprisingly simple shape; a naturally fun setup, I thought.
It was easy enough to code. My first attempt failed because I moved the top piece to the print bed in the model by flipping vertically instead of by rotating 180 degrees; so that print looked fine but did not work at all.
The second print looks like this:
I can’t show you the two separate pieces because they don’t separate any more. Pushing them together was hard, and they are now thoroughly stuck.
And so I learned, by doing: if two 3D printed pieces are supposed to fit together then be separable, there needs to be finely sculpted tolerance spaces everywhere.
This immediately broke my beautifully simple “voxels” model. The shapes can’t be built of equal-sized cubes; they need “trimming” depending on position to introduce tolerances.
The algorithm needed is not too bad: for each voxel, check for each face is “external”, meaning there is no adjoining voxel. If so, trim that face: move it slightly inwards.
Another algorithm goes with this one: if a face is not “external”, remove it altogether; I did this in a simpler way, the code just removes any faces that are exactly duplicated.
Having figured out the tolerances, so the pieces would slot together and slide apart comfortably, I had some fun with this setup.
I worked out how to nest and join the pieces in different ways, for example for this “double cube”:
And a mildly entertaining cube “puzzle”:
I had fun producing and playing with these models but in the end they were not quite satisfying.
The problem is that when you join two pieces together, you want them to stay together until you tell them otherwise. It is not a good experience to pick it up and have it fall apart.
This lead into a much more difficult problem: how to make two pieces that clip together, but can be pulled apart.
And so I started iterating.
First I tried simply tweaking the tolerances involved. This did not work; the pieces were either too loose or too tight.
So it looked like my model needed to move even further away from ideal same-sized cubes. Figuring this out with randomly generated pieces looked intimidating, so I settled instead on a simple interlocking shape to work with—more like a construction kit than a puzzle.
In removing the randomness I decided that the pieces should fit together through any rotation, which constrained the design considerably:
Having simplified as much as possible I now needed some kind of clip.
I decided to add a ring inside the socket piece, turning this:
# # # # # # # # #######
into this:
# # # # ## ## # # #######
And a corresponding indent in the plug piece, turning this:
##### ##### ##### ##### #####
Into this:
##### ##### ##### ### #####
And so the two pieces would “click” together and stay there until actively pulled apart; at least, that was the idea.
My idea did not work. It nearly worked. It came really, really close to working.
I tweaked endlessly the vertical and horizontal sizing of the ring and indent, printing and testing.
There’s no point in showing you printed models because the details are too small to see. It was a weird experience to iterate on invisible implementation details—that happens sometimes with code, too, but I’m used to setups with sufficient logging and monitoring. I had to take care to keep track of which print was which, and didn’t do a particularly good job; I should have followed some precise system for labeling and evaluating each iteration. Part of the challenge was that iterations were slow—even cutting the pieces down to the absolute minimum for testing, a print was still ten or twenty minutes.
More fun: I noticed that because of the process of slicing the idealized 3D model into actions for the printer, changing the context a piece is in necessarily changes how it prints. For example, if you take two identical 3D models and place them adjacent to each other, so they’re connected, that is not the same as printing the model twice; they both have to change to make the connection happen. At the scale of detail needed to make these clips work, that change could make or break the model.
Eventually I reached a design that in most prints would clip and unclick satisfactorily; sometimes it would stick.
But after a small number of repetitions of clipping and unclipping, the piece would physically degrade and the clipping action would be gone. My design was not compatible with the endurance properties of the plastic.
What was needed was a way to make a shape that would deform instead of degrade—to add some “springiness”.
I tried more variants; what eventually worked looks obvious in retrospect—I suppose that’s always the way.
The solution was to split the plug piece down the middle, exactly adding “springiness”:
##### ## ## ## ## # # ## ##
And giving these two minimal pieces that exactly clip and unclip as desired:
So much work for such a little thing!
Next time, I’ll post about what I did with it.
Once again I’ll end by sharing someone else’s work so that my underwhelming prints do not put you off the whole idea of 3D printing.
I really like this one; I kept it on my desk for a while because it’s so fun just to pick up and look at from different angles. I don’t quite remember but I suspect this model is part of why I settled on generating 3D models with code, in the hope of eventually producing something similarly amazing.
So far today, 2024-11-28, feedback has been received 4 times. Of these, 0 were likely from bots, and 4 might have been from real people. Thank you, maybe-real people!
——— / \ i a | C a \ D n | irc \ / ———