https://github.com/fogleman/sdf
One big plus to doing it this way is that it's "just" Python and you can use arbitrary logic to help construct your model.
You can even load an existing 3D mesh and operate on it as an SDF. Great for hollowing, chopping, eroding/dilating, etc. existing models.
I should probably do more with this project. I think there's a lot of interest in this space.
I would really recommend using the git master than the latest release though. The last release was 2021 but they are still actively working on it and it's much faster now.
I also have to recommend the BOSL2 library which means you don't have to implement all of those one million features from typical CAD software yourself. Its definitely got a bit of a learning curve but the fact that you can always default back to vanilla OpenSCAD and that you can actually see how stuff is implemented makes it much more satisfying to me to learn than learning what all the traditional CAD GUI buttons do.
Pro tip: Use the latest nightly build and switch to the Manifold backend in preferences. Render times drop from minutes to seconds for complex models. The official 2021 release is painfully outdated.
Also, the BOSL2 library is essential - it adds proper filleting, rounding, and attachment operations that vanilla OpenSCAD lacks. Makes the difference between toy projects and actually useful designs.
The Git-friendliness is underrated too. Diffing .scad files is trivial compared to trying to understand what changed in a binary Fusion 360 file.
The awful thing about OpenSCAD is that what one can model in 3D is limited by one's ability to mathematically stretch, rotate, and/or arrange spheres, cylinders, and cubes in 3D.
For folks who want "real" (read mutable in normal terms of scope) variables there is a Python-enabled fork (which should become part of the main release presently:
Instead it's basically like graphics programming, with a couple of basic primitives, some linear transformations and a bit of set theory. When I do a model a month and get back to previous work, I read a few lines of code and know exactly how I achieved the result.
but it has real problems - the language is weird and unfortunate. not anything super fatal, just the obvious product of evolution that would be more cohesive if it were architected wholesale
epsilons are really unfortunate. you have to expect that after getting what you want in the whole, you're going to have to scan over the whole thing and look for cracks or collision where there shouldn't be
performance is quite sad. here you are happy going back and forth between the view and text windows, but as you go on, it starts taking .. minutes.. to update the view once you have a reasonably complicated geometry
high-level operators would also be nice. I made the mistake of using a thread library once, not only did that make my model unrenderable, there was so much noise in the model and the manufacturing process I had to make 3 expensive test prints in sintered nylon to get the fit right. (I'm thinking an annotation on a cylinder that says 'standard 1mm thread')The same model in freecad is like 6 megs of zipped xml and realistically not nearly as usefully parametric.
That couple-k of plain text is such a huge deal that it makes all the other difficulty worth it for mechanical/functional stuff.
Currently I'm playing with a gear library which is part of BOSL2 (https://github.com/BelfrySCAD/BOSL2/wiki/gears.scad), to make something to rotate a polariser in my microscope.
The power of parametric cad is such that I wouldn't be a 10th as productive using an interactive cad system. And because it is effectively software you are writing (even if it compiles into physical objects) you can use all of the goodies that you can use to manage software. Diff files, git, kompare, branching, merging. It is nothing short of amazing, it is like I have a design team and a prototype injection molding facility in one. And the turnaround time is something you'd have killed for in the 90's.
https://cubehero.com/2013/11/19/know-only-10-things-to-be-da...
I recently started messing around with OpenSCAD too. I found these boxes that are great for storing the tiles for various 18xx railroad boardgames: https://www.printables.com/model/287297-parametric-18xx-tile...
Cool thing is that you can easily print them in whichever size you like, and the sizes in the supplied files are rather large, so I tried some smaller sizes, and discovered some details weren't actually centered properly, so I dove into the code, tweaking some bits here and there until I got it centered properly.
Then my dad asked me to print boxes for a game that had slightly larger tiles, so I needed to tweak the sizes, the thickness, and made everything just a bit more configurable.
I've got another idea I haven't tried yet: print the shape of the track on the tile on the spot its meant for. That's a whole new feature and not merely tweaking an existing one, so maybe it's time to finally learn how this format actually works.
Although I did see in the code that you create shapes through intersections and substractions with other shapes. And that's where I got stuck. Maybe it's time to pick it up again. It's a fun way of building shapes.
That's because you wrote a for-loop without braces, so it can only contain a single statement, and that single statement is your let().
Here is an equivalent way to write that section of code (and I did test it):
for (r = [ 1 : numRows ]) {
startColumn = ((c * thicknessWall) + ((c - 1) * batteryType));
startRow = ((r * thicknessWall) + ((r - 1) * batteryType));
translate([startColumn, startRow, thicknessWall])
cube([batteryType, batteryType, heightCompartment + 1]);
}
Side note, related to declaring variables but not an issue that you encountered: OpenSCAD does not allow setting the value of a variable more than once. So this code is illegal: x = 1;
echo(x);
x = 2;
echo(x);
Second note is that whenever you introduce a construct such as {union(), difference(), if(), for()}, variables declared within the braces are scoped, so they don't exist between iterations or after the scope ends. if (true) { y = -1; }
echo(y); // Illegal
However, just introducing braces without a construct does not restrict the variable to the scope: { z = 5; }
echo(z); // LegalI went from OpenSCAD -> cadquery/build123d -> Zoo/KCL
It still is early days, and it needs some more helper functions but it's really nice having two-way capabilities (not just code -> model, but also the reverse).
Of course having Text-to-model as a first class citizen is also nice.
As many correctly pointed out, STL & DXF are not considered professional file-formats anymore by some people. Some fabricators will not respond to quote requests, as without a Step file they are literately self-confessed useless clowns without Onshape/Fusion true solids handling the ugly math.
It is partially a unofficial standards issue, but customers without Step files may have to look around for fabricators. YMMV =3
I'm aware of Onshape having a git-like workflow as well, wonder how the two compare! A fully cloud-based suite would probably not work well for an open source project.
I personally do better with CAD software such as fusion or freecad since my mind doesn't work in the code realm since I have more of a hardware mindset. Translating the picture in my head to code is more difficult than drawing it using the standard CAD set of tools.
My opinion on OpenSCAD is that it is a very useful piece of software which many have used to make some very interesting things. If you have a background in code I recommend giving it a go. I largely view it as "the coder's CAD".
Also with OpenSCAD, you can feed the documentation to your favorite LLM and ask it for a starter design of whatever you are building. (Or you can skip the documentation; it is in the trading data after all.) Maybe in the future that SVG Pelican on a bike test will be a 3D model in OpenSCAD.
$fn = $preview ? 32 : 64;https://github.com/rahulgarg123/openscad-mcp
It’s still strictly worse than what these models are capable of for general-purpose coding, but for simple tasks where precision isn't the bottleneck, it's surprisingly decent.The "aha" moment for me was an image-to-object workflow: found a geometric design on the web --> generated OpenSCAD to match the image --> 3D printed it. Going from seeing a JPEG to holding the physical object in a few hours.
I tried using Build123d, a Python library that lets you use all of the features of Python. And it's supposed to allow specifically things like box1.width, but it's always 0. Lots of other issues/bugs too, and severely lacking in ddocumentation.Maybe it'll get there some day.
And when something gets too trick, ChatGPT is amazing at writing in it. Often it nails the whole design in the first try, like https://bsky.app/profile/bradfitz.com/post/3maelwomyw22n to mask off certain Raspberry Pi pins to make reassembly of projects easier later.
The chatbots kept recommending I try using OpenSCAD but I resisted without even giving it a look. The results I had with just the Python script are quite adequate for the tasks I had. You can just ask the LLM to add a fillet to a vertical pin on a plane or to chamfer some edge and it is pretty good at doing it.
https://wiki.roshangeorge.dev/w/Blog/2025-12-01/Grounding_Yo... if you want to roughly see the workflow.
I'm going to try using OpenSCAD for things in the future. Does anyone else use exclusively an LLM with OpenSCAD (I used Claude Code and Codex) and if you do what did you do to make it more effective? The Python script wouldn't always generate printable meshes so I had to give it a check script to operate on.
Years later, I never actually got the hang of CadQuery, and I'm wondering if it was a mistake to write off OpenSCAD.
I am pretty new to CAD, so I don't actually know when I would run into OpenSCAD's limitations.
I don't really see why that code is better, more logical, more readable or more robust than the equivalent quite trivial parametrics in more or less any GUI CAD program, and I think the geek discourse is really harmed by people who don't understand the value of the things that OpenSCAD can't ever offer.
My favorite thing I’ve printed is a little downsize coupler for the cool shirt system I built for my spec miata. It’s realllly silly & small thing, but it saved me!
I wrote more about it here, although I only mentioned OpenSCAD briefly https://hackaday.io/project/202488-manhattan-subway-map/deta...
While it was very handy for my programmer brain to create a few 3D printed things, when I wanted to create a drawing for something I'd make myself, adding dimensions seemed very unwieldly. I used a different CAD program for those projects (maybe Autodesk Inventor?).
It's neat that I can tell the computer what I want in words and then have that object come out of the 3D printer
Ok if you want to generate a couple of cubes, but if you want anything advanced the kernel quickly falls apart
The big distinction is that those work implicitly, while OpenSCAD requires you to be implicit.
OpenSCAD can automatically re-render a preview as soon as the external editor saves to disk
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_an_...
total lack of interactivity.
https://youtu.be/eG5lhLYvihQ?si=ehet5COZhiNrcK9bAnd even if it’s not perfect it saves a lot of time looking up the documentation and generally gets the relationships between objects right.
However, there are a number of limitations that are truly and deeply frustrating.
1. The language is downright weird. Don't get me wrong, it's a very nice little exercise in implementing a functional-tasting scripting language. Someone obviously wanted to scratch a functional DSL design itch and he did, but the result is unfortunately extremely limiting. Creating a function that does not return geometry is barely possible (only bloody lambdas IIRC). He should have picked python instead (and yes, I know about SolidPython2)
2. From my POV: the main headache with OpenSCAD is there is no way to partially evaluate an object and use the result of that partial evaluation in the rest of the construction. For example, if you try to take two complex assemblies and place them tangent to one another ... very good luck to you sir, I pray and hope the 3D math is really strong with you.
Whereas: if you had a simple rayIntersect(csg_tree, line_in_3d_spce) that would return the first intersection and two normals ... something you can reuse in subsequent transforms and construction, man would life be simpler.
These days, with LLMs you can sort of build a scaffolding to work around this by asking the agent to break down the assembly in multiple stages and use external libraries to do the partial eval for you, but ... ugh ... what a mess.
3. Speed. The moment your CSG assembly gets complex (e.g. uses a ton of morpho ... hull, minkowski, etc...), OpenSCAD crawls to a halt.
4. NO FILLETS. The age-old, standard methodology of building things CSG style with cubes, spheres, cylinders, etc ... and then once the object is finished adding the rounding ... simply not possible with OpenSCAD. Adding fillets after the fact once you've built a complex CSG tree ... nightmare with OpenSCAD.
So, YMMV, but caveat emptor, if you get serious with the toole, you're bound to hit some very hard walls.
And then, you discover that those darn LLMs have absolutely no spatial intuition. None.
It is seriously frustrating: one the one hand you can just feel the raw potential of vibe coding complex geometries, and on the other, when you do, you keep seeing the agent making mistakes a 5 year old playing lego would never make.
Absolutely infuriating.