The great thing about OpenSCAD is that it makes it easy to 3D model things which may be described using spheres, cylinders, and cubes which are stretch, and/or rotated, and arranged in 3D space.
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:
Not just that but it also positions everything in absolute coordinates and does not have the ability to reason about solids, just surfaces. Basically if you want to model something like a bolt you need to create a cylinder for the shaft, a separate head of the bolt, and then a thread profile you can rotate around the cylinder. You must ensure there is enough overlap between these three separate parts so the resultant object is a single surface and not three separate ones.
You can use modules to create a semblance of relative measurements but you still cannot do things like “attach this surface of object A to that surface of object B)”. In practice this means that if you want to create something like a spacer or a bracket you can do that easily enough. But if you want to make a part that matches some real world design you are stuck doing a lot of caliper measurements and math to try to create a part that lines up correctly. The you 3D print it and find that you positioned some hole based on its edge and not center and so nothing quite fits.
OpenSCAD is easy to start but difficult to scale because of these limitations and because once you hard-code any measurement you are stuck with it. The “proper” way to do this is to give everything a variable but honestly that makes reasoning about how to line things up even more difficult. “Does base_width include the width of the vertical walls? What about the margin to make the parts fit together?”
I have never been able to understand how things like FreeCAD lay out their UI. TinkerCAD is relatively simple but clearly a lot less powerful. I did try cadquery which solved a lot of OpenSCAD’s issues by having all offsets be relative by default but also introduces a few issues of its own.
One tip I will give about OS: grab a copy of the latest beta/dev release. The renderer is several orders of magnitude faster.
> You must ensure there is enough overlap between these three separate parts so the resultant object is a single surface and not three separate ones.
(Post author here.)
This was a very weird thing to me I ran into and have thus far just sort of... accepted.
In Fusion, and other CAD software, if I have two faces end at the same point, unless I've specifically said to create them as separate bodies, they are joined, because they share a plane.
In OpenSCAD, in the tutorial, it has you extend an object 0.001 to ensure they overlap. To quote:
> In the example above, the second cube sits exactly on top of the first cube. This is something that should be avoided, as it’s not clear to OpenSCAD whether the two cubes form one object together. This issue can be easily solved by always maintaining a small overlap of about 0.001 - 0.002 between the corresponding objects. One way to do so is by decreasing the amount of translation along the Z axis from 10 unit to 9.999 units.
This struck me when making the example in my post. In line 47 I specifically add 1 to heightCompartment to ensure the opening extends past the top of the main body. If I didn't do that, this happens during preview: https://imgur.com/a/Amc1dK6 (That's an exported image from the latest nightly of OpenSCAD.)
But it doesn't happen during the actual render?
Still, that just feels... like there's something going on with a floating point value or something which, programatically, is probably correct... But from the perspective of someone trying to design something feels Very Wrong. Because I have a 20mm high box, I subtract a 19mm high box from it, starting 1mm up from the base. Why shouldn't the top be open? Why is it acceptable for it to be maybe kinda open but broken by design?
Floating point numbers are not closed under addition. They are not real numbers and not rational numbers. FP is on a grid whose size changes the farther you get from 0,0. For example 0.1 doesnt exist in fp nor does any number not representable by binary fractions. Also its a quirk of opengl and most 3d renderer to get issues when one surface coincides with another so the preview renderers like the little bumps. Also the underlying CGAL rendering kernel can be problematic when planes are almost nearly coincident but not one hundred percent. Finally OpenSCAD has an internal grid it tries to snap things to which can also cause issues. Not sure if the new Manifold renderer has these issues but in general the loss of info from ascii decimal to FP is the source of most of the problem. Those professional cad programs have enormous resources behind the scenes to make that stuff appear easy when its actually very complex and basically an illusion. Rotating anything using sine and cosine instantly loses information so planes with more than three points become non planar ever so slightly. So this assembly you made with “two surfaces touching” is not touching after rotation due to sin eing transcendental function simulated on a computer with finite time and memory. For example. These fancy CAD systems all have ways to deal with this.
Thanks for explaining that; that makes sense.
I still don't /like/ it because it seems I'll need to add in some sort of 0.001mm overlap into the code if I want to ensure this doesn't become a problem. And this feels like a messy way to go about it.
> but you still cannot do things like “attach this surface of object A to that surface of object B)”
Sure you can, but openscad is an imperative language so you need to do it in an imperative manner.
It would be nice to have more declarative constraints. The solvespace file format is plain text and it almost feels like you could write it by hand, but that would be a lot of manual record keeping. and you would loose all that imperative goodness. Perhaps you could have an imperative layer(say python or lisp or forth) that outputs the declarative layer(solvespace) and then solvespace renders(picture or stl) the declarative layer.I think a text input option for Solvespace which was optimize for readability and usability would be _very_ interesting approach, esp. if Solvespace was able to write back out to the same format, and it allowed math/variables/parameters and supported the same in the UI.
BOSL2 allows attaching when you define attachment points or something with attachment points defined for you (most everything in BOSL2).
Manifold backend also eliminates the need to avoid coincident faces.
Can you explain this a bit more? Might be the after effects of the COVID/flu vaccine I got yesterday but I am not picking up what you mean.
Consider making a standoff: a hollow cylinder. You take a cylinder primitive and subtract a cylinder primitive with a smaller radius. If they have the same height, the top and bottom faces of the cylinders are exactly the same plane, which the Preview gives odd effects. The old recommendation is to name your subtracting cylinder taller and shift it down a little, so those faces don't share a plane. Manifold doesn't care.
Oh, maybe you mean attaching.
https://github.com/BelfrySCAD/BOSL2/wiki/attachments.scad
Let me introduce to the awesomness of the BOSL2 screw module:
https://github.com/BelfrySCAD/BOSL2/wiki/screws.scad
This is amazing but the first time I needed to make a screw I needed to make one that used the NPT standard which this module still does not cover :)
> I have never been able to understand how things like FreeCAD lay out their UI.
I'm 100% with you there. One of the most utterly confusing UI I've had to deal with.
And I suspect the answer is : the FreeCAD devs don't either.
> The great thing about OpenSCAD is that it makes it easy to 3D model things which may be described using spheres, cylinders, and cubes which are stretch, and/or rotated, and arranged in 3D space.
It also has hulls and minkowski sums, which are powerful once you understand them.
Aren't hulls just a direct connection of the edges of two shapes (which could be simulated by a series of duplications) while Minkowski is "just" a matter of putting spheres along the edges of an object to round the straight edges?
So, spheres and cylinders and cubes placed, rotated, stretched and placed mathematically.
A hull requires at minimum one shape and returns a convex shape.
A minkowski sum, as far as I understand it, requires a surface and a volume and returns a volume.
Example 1: apply hull() to a star shape
Example 2: You want to fold a picture (SVG) around a cylinder and make its edges FDM printable by 45 degree overhang, apply a cone to the image
There's also OpenJSCAD. Which, being JavaScript ofc, can run in the browser
https://openjscad.xyz/
https://github.com/jscad/OpenJSCAD.org
From my testing, the CSG operations, with post-processing, don’t produce watertight meshes. And being focused on printing, it doesn’t support different colors for the CSG operands. My use case is animation/games, so I’m reimplementing the CSG with a watertight b-rep.
Re: JS based CAD, there's also replicad, which I've used previously and found to be really good.
https://replicad.xyz/
Don't people think this is one tool that would greatly benefit from using the very fastest languages available? Where's the C++, Rust, maybe even FORTRAN version?
This is only the language for describing the volumes. That's not heavy, rather the importance is that you can express the ideas you want. The heavy lifting of rendering and computing how volumes interact etc is already implemented in native code.
My understanding is that the core of OpenSCAD is done using C++.
If you wish to use Rust for 3D modeling directly there is:
https://fornjot.app/
(the developer of which is actually working on a BREP kernel)
You can also make more complex shapes if you're willing to define points, even on a 2D plane that you can then extrude. Downside is that it's basically a MENSA test to define all of the points in the correct order. I've done it a few times, but it's never fun.
Solid of revolutions and Bezier curves. That and some elementary Calculus will help everyone a lot.
Also you can use the new backend by writing C++: https://github.com/elalish/manifold
Which avoids using the OpenSCAD language, but also means you can't use BOSL2. Might as well use FreeCAD.
It has many language bindings, including python and js. Though the js backend is not parallel because it uses wasm, and we had problem with mimalloc memory usage with pthread enabled.
That's true, if you use i.e. Python you can use numpy for custom matrix math, but using C++ you can just do anything and it'll be pretty fast.
I think people should also give Bowler Studio a shot. It has a pretty decent Java-based CAD thing, and it even has built in Clojure support, with physics simulation support and everything. I really like it.
Another interesting option is FreeCAD, which is scriptable in Python but its primary interface is a GUI. So you can use a script to create things programmatically, edit graphically, or both.
FreeCAD sounds great but in practice it’s sooo slow.
If you are coming from SolidWorks, Fusion360, Inventor, or OnShape, it won’t take long before you start finding that there are a lot of things missing from it.
I'm coming from Fusion, advanced hobbyist, I can't find anything missing. </anecdata>
There is a problem though - sometimes what you want requires deep understanding. It's less user friendly, polished, and documented. That's also relevant to the performance - it's easy to cause performance issues. But I remember the same was also applicable to Fusion.
Of course FreeCAD is less user friendly, polished, and documented. It's open source. Open source people do not get GUIs. They think command line. It's taken decades for artists and graphic designers to nag the GIMP and Blender people into usable interfaces, and they're still inferior to Photoshop and Maya.
Isn't the Python scripting in FreeCAD just a direct representation of the internal object model?
It's _not_ something which was designed for ease of use, or rational semantics, or to facilitate expression.
I've had really good luck with https://github.com/SolidCode/SolidPython
I ended up adding the https://github.com/BelfrySCAD/BOSL2 library to OpenSCAD and it had some reasonable options for some gear and rack-and-pinion modeling that I needed to do.
(3D printing a sacrificial gear for a seat position adjustment mechanism)
Or perhaps take a look at cadquery? It’s also pretty neat - http://cadquery.readthedocs.io/
> https://pythonscad.org/
Thanks for this, didn't know about it.
How does that compare to solid python 2?
https://github.com/jeff-dh/SolidPython
It's native and more direct.
Rather then adding an additional compile cycle:
- run Python code to generate OpenSCAD code
- render OpenSCAD code to see output
OpenPythonSCAD creates a .py code window in the OpenSCAD interface which one interacts with in the same way as a .scad code window (there's even basic support for the Customizer).
I suspect it would be really easy to port SolidPython to work w/in OpenPythonSCAD (if it hasn't already been done)
> 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.
Not at all. You can build any polyhedron you want using the polyhedron command.
Which would be an enormous pain to write out by hand every time, but I wrote a function once upon a time to generate a polyhedron from a stack of layers, each of which is a list of points, and haven't had to mess with old cubes and spheres since.
One annoying thing is that the default way of writing programs in OpenSCAD uses 'modules', which are a bit limited compared to functions (you can't store them as values to to functions or other modules). I worked around that by writing a module that interprets arrays (think S-expressions) that representing the shape, and then just build up that S-expression-like thing with functions and whatever.
Once you've built your own programming language inside OpenSCAD it's perfectly usable. :-)
This might sound like sarcasm but I actually do prefer this to dealing with Python's mutable state jungle / package management nightmare.
Fair point.
This sounds _fascinating_ have you posted your code or written this up in a math journal? Link?
I don't touch polyhedrons in OpenSCAD because the logic of point placement mystifies me --- a tool such as you describe would make life a lot easier for a lot of folks, esp. if there was a way to use it to import a series of SVG files which could be used to define the points interactively.
I sometimes wonder if the key to future computer usage would be a series of Domain Specific Languages each intended for a given task:
- 3D == OpenSCAD
- 2D == METAPOST
- SQL == databases
- TeX == text/page composition
- sed == text
(and yes, I know this is the Unix ideal)
but such languages seem to be most successful and most approachable to typical users when they are paired with a front-end which affords editing, previewing, and, direct interaction.
I'm actually nuking my Python install right now, because I got it into a state where I couldn't get Fullcontrol G-code to run, so I agree that the state of Python package population is pitiful, hence of course, the XKCD:
https://xkcd.com/1987/
An example of an OpenSCAD design written this way: https://github.com/TOGoS/OpenSCADDesigns/blob/master/2023/ex...
I wrote about the approach a little bit in this Reddit post: https://www.reddit.com/r/openscad/comments/186b54r/interpret...
The interpreter itself is just a single module: https://github.com/TOGoS/OpenSCADDesigns/blob/master/2023/li...