Designing with Weighted Random Parameters in OpenSCAD

Designing with Weighted Random Parameters in OpenSCAD

Designing with Weighted Random Parameters in OpenSCAD 1000 756 mathgrrl

Minecraft worlds are procedurally generated from one random number seed, which then determines the placement of the trees, landscapes, strongholds, and everything else on the map. This video from PBS Game/Show describes how Minecraft starts with this small piece of information and uses Perlin noise and “controlled randomness” to create an entire gameworld:

In this post we’ll talk about how to do a much simpler version of the same thing in OpenSCAD, using a single random seed and some “style weights” to produce complex and variable 3D-printable designs.

The Snowflake Machine

A few years ago we created code for the Snowflake Machine, which uses sequences of random numbers based on a single random seed to create 3D-printable snowflake designs. The random sequences helped us recreate how some snowflakes grow in real life, simulating environmental conditions that control whether and how quickly a snowflake develops branches or plates.

The snowflakes produced by this code aren’t completely random, since we want to make sure we produce beautiful and realistic looking snowflake designs. The code puts controls on the randomness in two ways. First, the numerical sequences that determine the formation of each flake are restricted to ranges and values that make sense and are more likely to produce good looking results. Second, the code contains a set of “style parameters” that can be set manually to tip the scales in favor of different types of snowflakes, such as branchy flakes, sparse flakes, or organic-looking irregular flakes.

Check out our previous post The Snowflake Machine for tips about using the random sequence weights in the code to design different styles of random snowflakes.

Sunburst Clocks

Using a very similar strategy, we recently wrote some code to produce randomly generated Sunburst Clock designs. Starting from a random number seed, this code creates sequences of style-weighted random numbers to control the shape, style, size, and placements of the design spokes around the clock face. This gif shows twelve of our favorites:

You can read more about the Sunburst Clock code at our previous post Just in Time: Clocks. After writing this code we realized it might be useful to have a core piece of code to use as a starting point for future 3D designs that use random style parameters, which leads us to…

A simple randomizer with two types of weights

The design shown below creates a sequence of random-height “skyscrapers” based on a random seed and two style parameters. One style parameter makes it more or less likely for the skyscrapers to be tall, and the other style parameter makes it more or less likely for the skyscrapers to exist. The random seed is used to generate sequences of random numbers that control the height and existence of the skyscrapers, weighted by the chosen style parameters.

You can use this code as the base for any OpenSCAD project with a random element:

The code above also has built-in functionality for Thingiverse Customizer menus that allow the user to modify the size, style, and random seed parameters. Click the “Open in Customizer” button to see how the menus work in action. To use this code in OpenSCAD you will have to comment out the Customizer random seed line of code and un-comment the OpenSCAD random seed line of code.

Creating your own random-parameter OpenSCAD designs

If you want to play with the code yourself, download the .scad file from Thingiverse or copy the OpenSCAD-only version from below. After opening the code in OpenSCAD, press “F5” to compile the code and see the results. Make any changes you like and then press “F5” again to see what happened.

Here’s what each section of this code does; first, the “size parameters” set the overall length and width of the base of the design:

///////////////////////////////////////////////////////////////////
// SIZE PARAMETERS

// Some overall dimension
A = 100;

// Another overall dimension
B = 30;

Next, the “style parameters” set two weights, one to make it more or less likely that the skyscrapers will be tall, and one to make it more or less likely that the skyscrapers exist:

///////////////////////////////////////////////////////////////////
// STYLE PARAMETERS

// controls scaling of elements in random subsequence1
// number from 0 (min allowable) to 10 (max allowable)
style1 = 7;

// controls likelihood of true/false in random subsequence2
// number from 0 (always false) to 10 (always true)
style2 = 8;

In the “random seed” section, a number is selected either randomly or manually, and is then displayed on the render screen and in the log:

///////////////////////////////////////////////////////////////////
// RANDOM SEED

// OpenSCAD chooses a random seed
random_seed = floor(rands(1,9999999,1)[0]);

// OR TYPE IN A SEED MANUALLY
// Overrides the slider seed unless set to 0
custom_seed = 0;

// set the random snowflake seed
seed = (custom_seed==0) ? random_seed : custom_seed;

// Show random seed? (it won't print even if you say yes)
show_seed = "yes"; 

// Create a string to output the random seed
// thank you laird for showing me how to do this with your code
// from http://www.thingiverse.com/thing:188481
labelString=str(floor(seed/1000000)%10, floor(seed/100000)%10, 
                floor(seed/10000)%10, floor(seed/1000)%10, 
                floor(seed/100)%10, floor(seed/10)%10, floor(seed/1)%10);

// Display the random seed in the render
if(show_seed=="yes"){
    translate([0,-30,0]) 
        color("gray")
        %linear_extrude(height=1)
            text(labelString,size=4,halign="center");
}

// Output the random seed in the log
echo(labelString);

The “random sequences” section uses the random seed to create a long sequence of random numbers, and then pulls out two subsequences from that list and weights them according to the style parameters. The first subsequence is a list of ten numbers that will define the heights of the skyscrapers, and the second subsequence is a list of ten true/false binary choices that will determine if we draw a skyscraper in each of the ten locations on the base:

///////////////////////////////////////////////////////////////////
// RANDOM SEQUENCES

// construct the main random sequence
// a list of random real numbers in [0,10] based on the chosen seed
maxSteps=30*1;
random = rands(0,10,maxSteps,seed);
echo(random);

// subsequence of 10 items from the main sequence
// weighted by style1
subrandom1 = [for(i=[0:10-1]) random[i]*style1];
echo(subrandom1);

// subsequence of another 10 items from the main sequence
// output as true/false verdicts by comparison to style2
subrandom2 = [for(i=[10:10+10-1]) random[i]<=style2]; 
echo(subrandom2);

Finally, the “renders” section draws a sequence of up to ten skyscrapers according to the defined parameter sequences. This is the part you would change if you wanted to use the random style parameters to define other types of shapes or models:

///////////////////////////////////////////////////////////////////
// RENDERS

// example: flat base based on overall size parameters
cube([A,B,10],center=true);

// example: cubes 
// heights based on subrandom1, visibility based on subrandom2
color("white")
for (i=[0:10-1]){
    if (subrandom2[i]==true){
        translate([(i-5)*(A/12)+A/24,0,5+subrandom1[i]/2]) 
        cube([5,5,subrandom1[i]],center=true);
    }
}

You can use this simple randomizer code as a starting point for adding some controlled randomness to just about any OpenSCAD design. If you make something, let me know! I’d love to see what you and randomness create together :)

 

——————

As an Amazon Associate we earn from qualifying purchases, so if you’ve got something you need to pick up anyway, going to Amazon through this link will help us keep Hacktastic running. Thanks! :)


Leave a Reply