GhostSCAD: Marrying OpenSCAD and Golang
OpenSCAD is awesome. Being a software engineer, the ability to code up my 3D models and keep them readably under version control pleases me immensely. I started learning OpenSCAD from this fantastic tutorial that quickly showed me the expressive power of the relatively few basic concepts provided by the system. It also made me realize some of the system's limitations.
For example, when doing the function grapher exercise, I was disappointed that I could not pass the function being plotted to the module doing the work. Instead, I had to generate an array of 3D points in a particular order so that the grapher could build the desired polyhedron out of them. It is cumbersome, and it could, in principle, be automated. It also makes the grapher module leak abstraction. You need to be aware of its internal workings to plot what you want.
The issue of leaking abstractions became more visible when I started using OpenSCAD to model the enclosure for my NAS project.
Firstly, I wanted part of the enclosure holding the disks to be parametrized by the number of disks it could contain and their size. I also wanted the part of the enclosure holding the optical drive and the ARM board to be parametrized by the size of these components. Everything worked fine until I had to figure out how to connect these parts. I could not determine the locations of bolts and screws without knowing the internals of each of the modules, and there was no obvious way for the modules to expose the necessary information to the outside world. I ended up defining a bunch of helper functions that would compute this information when supplied with the same parameters as the modules they described. It quickly became cumbersome, though, and started to look pretty ugly.
Secondly, I needed to design the components separately to 3D print them later. But I also wanted to visualize the model as a whole to see if things fit together. That ended up being impossible without knowing the dimensions of the parametrized components, the arrangement of attachments (which were a non-trivial function of the module's input parameters), and the frame of reference in which each part was designed.
The last two issues fundamentally stem from the fact that, in OpenSCAD, the abstract syntax tree of the program you're writing represents the geometry tree of the model you are designing. Significant improvements can be made if you divorce the two. For example, doing so would allow the module objects to have properties that you could use for integration without exposing how these properties were calculated internally. It would also allow for writing programs that analyze or manipulate the geometry tree in interesting ways before it is rendered. Solving the first issue is just a matter of making functions first-class citizens, which would probably be an easy change to the OpenSCAD language.
I finally managed to find enough time to make good on the threats I had made when I designed the chassis for my NAS and played with solving the issues mentioned above. I decided to use Go because it's a garbage-collected language with great tooling, and it compiles really fast. I designed a Java3D-like API that can be used to build the geometry tree of a model, which can then be compiled to OpenSCAD source and further processed by vanilla OpenSCAD. I used this system to design something of a non-trivial size that I needed - a small computer rack for all the electronic gadgets that accumulated under my TV table and evolved into a maze of wires, routers, and bare PCB boards.
I called the system GhostSCAD, and the TV table rack project is here. This article summarizes the results of this investigation.