Faster 3D modelling with openscad
Update: python version here
Some time ago amidst a non-version controlled world of chaos I put away bespoke modelling with Blender and learned OpenSCAD. At least for my spider projects I did, sculpting and quick fixes to models I have acquired from the internet is still very much a Blender thing for me.
Why OpenSCAD
I did a quick intro here that explains the main reasons for doing it in a bit of detail but ultimately I needed a couple of things.
Version control — with 30 or 40 odd models each in un-equal states of completion and uneven rates of change I lost a lot of time creating folders and dreaming up new names for cross-phase versions…. I really needed git.
Parametric modelling — with a multitude of interlocking parts, joined by nuts and bolts and dovetail joints, making changes meant manually moving 100s of points around in an attempt to keep all of the 40 parts in sync went from a real headache to taking more time than making the models from scratch over and over again.
The main problem with OpenSCAD
Speed, OpenSCAD does a bunch of things extremely well but its all very mathematical and extremely declarative.
Using a myriad of patterns and algorithms behind the scenes to create objects in cascading levels of complexity becomes taxing on the CPU and there’s a lot of bad ways to do the same thing.
Solution 1: be a better developer
After a long period of increasing render times I spent a great deal of time reading the doc’s and finding the best ways of doing things, this saved me some time and led me to doing better models in general.
I tuned the basic OpenGL settings and other environmental limitations.
I used better practices, doing things like reducing overall rendering quality, reducing the amount of models being rendered while I was developing so I could iterate faster.
I even started prerendering all of the models I wasn’t working on in varying ways to get them into the cache.
Once I had mastered each of these steps I wrote a bunch of bash functions that automated the re-render process using bash scripting, this way I could edit everything in low detail and and let the computer render everything without my input while I slept.
Solution 2: make OpenSCAD faster
I spent a lot of time analysing the source code for OpenSCAD in the hopes of improving its cache, using interpolation of models during rendering and I even tried to port some of its math functions to Cuda libraries so my GTX1080 could help out.
This was a mammoth fail as the developers of OpenSCAD have already done a far better job than I could have. The way the code is rendered from top to bottom and the way the objects are arranged in the rendering process is very good.
Finally, moving to CUDA wasn’t going to help either as I’d have to rewrite the entire rendering system to do so.
Also… I’m building robots… not improving software.
Solution 3: more OpenSCADS!!! All the OpenSCADS!!
After spending a bunch of time on forums and doing a bit of testing I stumbled on something I’d used most days for the last decade.
Some school tricks with characters In a bash script you can chain commands together, you can have it run one and if the left one passed using &&
or you can wait till the left command finishes (postively or not) by using ;
between them. But whats really interesting *facepalm* you can use &
to run things at the same time.
How to run OpenSCAD multiple times in bash
We’re gona need some code.
2 files:
- something.sh — this triggers the openscad file
- something.scad — this is the openscad file
something.sh
I added some things in here to time how long things took and a bit of code tidying because it makes things… tidier…
The key here is the `which_model` part, this parameter will be used in the openscad file to decide what to do.
something.scad
Now we’ve ended up with a bunch of extra stuff we don’t need normally but it saves time so it can stay there.
A module in OpenSCAD is similar to any other function in an imperative language, its the direction you’re going in your code. With this in mind I need to make a way to pick which module I am going to call… and because i also need to work on these files without interrupting the scripting I have the if (which_model == "")
bit and all my manual coding goes there.
The downside being that any time I want to add another module to render, I need to replicate the thing in the base something.scad
and the something.sh
but thats not a lot of overhead considering the time I’m saving.
The outcome of using the & character
Stuff happens at the same time so all of my CPU threads are taken up with all that glorious rendering. Overall its probably cost the same amount of calculation time but this all happens when I am asleep or getting a cuppa tea so its not wasted.
Rendering used to take about 4 hours :
finished!! execution time: 249 min 23 sec
Rendering now takes about 50 minutes:
finished!! execution time: 51 min 57 sec
I hope this helps someone else.