Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for variables, scripting support #2

Open
gingerbeardman opened this issue May 10, 2021 · 4 comments
Open

Support for variables, scripting support #2

gingerbeardman opened this issue May 10, 2021 · 4 comments

Comments

@gingerbeardman
Copy link

gingerbeardman commented May 10, 2021

I'm an OpenSCAD user and make use of its command line interface to export automated variations of my models. I use:

  • $t to 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):

forklift-table-38-38

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();
}
@nicklockwood
Copy link
Owner

@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.

@nicklockwood
Copy link
Owner

@gingerbeardman can you explain a bit more about $t and how that works? I don't see a reference to it in your example.

@gingerbeardman
Copy link
Author

gingerbeardman commented May 10, 2021

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)

@gingerbeardman
Copy link
Author

gingerbeardman commented May 10, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants