ShapeScript
ShapeScript copied to clipboard
Support for variables, scripting support
I'm an OpenSCAD user and make use of its command line interface to export automated variations of my models. I use:
$tto change the camera (32 rotations)- other variables to adjust wheel turning, tilt body, etc (9 combinations)
My issues with OpenSCAD are:
- performance (single-threaded)
- user interface (not native)
- fixed lighting
So, I was wondering if there are plans to add support for variables and scripting (CLI, AppleScript, internal, etc)
Cheers! matt from Cornwall
--
Example final output from my Makefile (render, resize, stitch, convert to 1-bit):

And the OpenSCAD model used:
// use only in editor, not in CLI batch
$vpr = [45,0,180-$t*360];
$vpt = [0,0,100];
$vpd = 9000;
s = 30;
h = s/2;
d = s*2;
w = h*4.5;
body = "#333";
trim = "#FFF";
black = "#000";
white = "#FFF";
glass = "#FFF";
rr = 1;
rl = 0;
rside = 2;
rf = 0;
rb = 0;
rfwd = 2;
shad = -1;
if (shad == 0 || shad == -1) {
rotate([0,0,180])
translate([-h,-d,0])
car();
}
if (shad == 1 || shad == -1) {
rotate([0,0,180])
translate([-h,-d,0])
realshadow();
}
module car() {
// rear wheels
translate([s*0.84, s*1.75, h])
wheel();
translate([-s*0.84, s*1.75, h])
wheel();
// front wheels
if (rr == 1) {
translate([s*0.84, s*3.5, h])
translate([4,-7,0])
rotate([0,0,30])
wheel();
}
if (rl == 1) {
translate([s*0.84, s*3.5, h])
translate([4,9,0])
rotate([0,0,-35])
wheel();
}
if (!rr && !rl) {
translate([s*0.84, s*3.5, h])
wheel();
}
if (rr == 1) {
translate([-s*0.84, s*3.5, h])
translate([0,-8,0])
rotate([0,0,35])
wheel();
}
if (rl == 1) {
translate([-s*0.84, s*3.5, h])
translate([0,7,0])
rotate([0,0,-30])
wheel();
}
if (!rr && !rl) {
translate([-s*0.84, s*3.5, h])
wheel();
}
rotate([-rfwd*rf+rfwd*rb,-rside*rl+rside*rr,0])
translate([0,0,-rfwd*rb+rfwd*rf])
union() {
// gas can
color(white)
translate([-h/2,d*1.85,d*0.88])
rotate([0,90,0])
cylinder(s*1.5,8,8);
// rear grille
*color(white)
translate([-9,d*1.975,s*.75])
cube([d*0.8,10,15]);
// exhausts
color(white)
hull() {
color(white)
translate([0, 128, 30])
rotate([90,0,0])
cylinder(5,8,8);
color(white)
translate([30, 128, 30])
rotate([90,0,0])
cylinder(5,8,8);
}
difference() {
body();
// wheel arches
union() {
translate([s*0.75, s*1.75, h])
arch();
translate([-s*0.75, s*1.75, h])
arch();
translate([s*0.75, s*3.5, h])
arch();
translate([-s*0.75, s*3.5, h])
arch();
}
}
}
}
module body() {
color(body)
union() {
difference() {
body_main();
// fork
translate([15,-5,55])
cube([d+1,d+1,d*1.2], center = true);
// fork gap
translate([15,-5,20])
cube([s*1.3,d+1,s], center = true);
// fork gap v r
translate([-15,16,53])
cube([s,s,d*1.2], center = true);
// fork gap v m
translate([15,16,53])
cube([h,s,d*1.2], center = true);
// fork gap v l
translate([45,16,53])
cube([s,s,d*1.2], center = true);
// fork cut
translate([15,35,66])
cube([d+1,s/3,d], center = true);
// roof cut
translate([15,70,83])
cube([d+1,d+1,h], center = true);
// rear cut
translate([15,136,75])
cube([d+1,d+1,d], center = true);
// front cut
color(glass)
translate([46,105-s,40])
rotate([90,0,-90])
linear_extrude(0,0,62)
polygon(points=[[40,50],[20,50],[35,-4]]);
// rear cut
color(glass)
translate([46,140,40])
rotate([90,0,-90])
linear_extrude(0,0,62)
polygon(points=[[55,50],[30,50],[30,5],[45,5]]);
// front and back windows
color(white)
translate([-11,35,44])
rotate([1,0,0])
cube([52,d*1.2,28]);
// side windows
color(white)
translate([46,105-s,35])
rotate([90,0,-90])
linear_extrude(0,0,62)
polygon(points=[[-10,37],[-16,10],[30,2],[21,37]]);
}
}
// interior
color("white")
translate([15,70,41])
rotate([10,0,0])
cube([d*0.9,d*0.65,1], center = true);
}
module body_main() {
difference() {
// body box
color(body)
translate([-h, -h, h])
cube([s*2,s*4.75,s*2.4]);
}
}
module wheel() {
difference() {
// tyre
translate([s/3,0,0])
color(black)
rotate([0,90,0])
cylinder(s/3,h*1,h*1);
// tyre hole
color(white)
translate([h/2,0,0])
rotate([0,90,0])
cylinder(h,s/3,s/3);
}
// hub cap
color(white)
translate([h*0.75,0,0])
rotate([0,90,0])
cylinder(h/2,s/3,s/3);
}
module arch() {
// hole
translate([4.5,0,0])
color(white)
rotate([0,90,0])
cylinder(s*0.7,s*0.6,s*0.6);
}
module mark() {
translate([h/4,0,0])
color(black)
square([s/2,s/2],0);
}
module realshadow() {
N = [[ 1 , 0 , 0 , 0 ],
[ 0 , 1 , 0 , 0 ],
[ 0 , 0 , 0.01 , 0 ],
[ 0 , 0 , 0 , 1 ] ];
color([0,0,0, 1])
translate([0,0,-4])
multmatrix(N)
car();
}
@gingerbeardman yes, this is definitely something I'd like to support, and thanks so much for the example code - it will be very helpful in deciding what the feature set ought to be.
@gingerbeardman can you explain a bit more about $t and how that works? I don't see a reference to it in your example.
Oops, I had deleted some commented out lines. I have reinstated them at the top of the model description.
$t is a value that varies as animation is happening, you can use it as a variable in your model to change things as the animation progresses. https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#$t
Only when in the OpenSCAD editor I uncomment those lines and the model will react when I am running animation (it will rotate, actually the camera will rotate around it) because I use $t as a variable in the $vpr (view port rotation) directive.
When I am done, I comment out those top few lines and instead control the camera using a command line parameter, where I am in charge of the variable that sets the rotation amount, I pass it as an argument with each call.
Recently OpenSCAD had the feature for animation on command line added. However after trying it I saw that the performance is limited by OpenSCAD's limitation of using only a single CPU core. So, instead, I run a bunch of instances at once from the command line (using & to run them in the background and wait to do them in batches) see here which uses pretty much all my CPU cores and is therefore much more performant.
Rendering all my cars takes ~16 minutes right now, but my Makefile is clever enough to only build things that have changed so turnaround is very quick (~25 seconds)
For completeness, here's a snippet of a script I call from my Makefile
I pass on the CLI variables to rock the body of the car:
- $RF (forwards)
- $RB (backwards)
- $RL (left)
- $RR (right)
and whether or not to render shadow (I render car and shadow separately):
- $SHAD (boolean)
and others including:
- $CAR (name of car model)
TOTAL=$(( 9*32 ))
for i in {0..31};
do
ANGLE=$(( 180-11.25*(i) ))
NUM=$(( ${TOTAL}-(($p-1)*32+$i+1) ))
printf -v NUMBER "%03d" $NUM
openscad \
-q \
-D rl=$RL \
-D rr=$RR \
-D rf=$RF \
-D rb=$RB \
-D shad=$SHAD \
--autocenter \
--camera 0,2,28,45,0,$ANGLE,500 \
--imgsize 320,320 \
-o $NUMBER-$CAR.png \
_$CAR.scad 2> /dev/null &
done
wait