During a workshop at the Confetti Institute, I was in a situation where I had to explain to a group of students how technical art could allow an artist to create something very complex in a short amount of time using scripting techniques. I very quickly realised that a good way to demonstrate this was to show what the random function could do. Within minutes, I had written script that could create a relatively complicated piece of geometry in a very short amount of time. While this was something of a diversion from the main point of the workshop, it was something that some of the students wanted to explore further, so I am writing this tutorial to demonstrate the principles.
Using The Random Function To Create Object Variations
MAXScript’s random function can be used to create an instant and natural variation of an object. Any of the accessible properties of an object, such as it’s colour or it’s size can be randomized. This is powerful, as if we create an object such as a tree, we can create multiple variations from the same model.
fn RandomSize boxObject factor =
minFactor = (1.0 - factor)
maxFactor = (1.0 + factor)
xScale = random (boxObject.scale.x * minFactor) (boxObject.scale.x * maxFactor)
yScale = random (boxObject.scale.y * minFactor) (boxObject.scale.y * maxFactor)
zScale = random (boxObject.scale.z * minFactor) (boxObject.scale.z * maxFactor)
boxObject.scale = [xScale, yScale, zScale]
myBox1 = Box width:1 length:1 height:4 name:"myBox"
for i = 1 to 4 do
RandomSize myBox1 0.75
myBox1.position.x += 3
The script is based around the function, RandomSize. This function takes in two arguments. The first is a boxObject which is going to be processed. The second argument is a random factor.
The random function itself takes the form of:
It returns a value that sits in between the two minimum and maximum values.
So we are using these values to control the scale value of our box.
With the function set up, we create a box object (myBox1) and then we use a for loop to manipulate the object. In the for loop, we copy the box, randomize it’s size, and then move it along the x axis. So from one base object, we have created five variations.
We can extend this random behaviour to other kinds of transform as shown in this script.
myObj = Box name:"myObj" width:1 length:1 height:4
for i = 1 to 20 do
--duplicate the object
newObj = Geometry[Geometry.count]
--give it random rotation
newObj.rotation = (eulerAngles 0 0 (random 0 360))
--give it random position
newObj.position = [(random 0 20), (random 0 20), 0]
--give it random scale
newObj.scale = [(random 0.5 1.5), (random 0.5 1.5), (random 0.5 1.5)]
Here, we are adding random factors to the rotation and the position as well as the scale. When we copy an object, a great way to be able to pick it up so that we can manipulate it is by looking for newest object in the Geometry list. So we get access to the copied object’s parameters by accessing it through the line:
newObj = Geometry[Geometry.count]
Once we have picked it up, we can manipulate it with the random factors.
Death Star Geometry
The final stage of this tutorial is to create some geometry that is reminiscent of a spaceship surface, such as that of Star Wars’s Death Star.
fn CreateDeathStar size:20 complexity:800 =
for i = 1 to complexity do
local xdim = random 0.1 4
local ydim = random 0.1 4
local zdim = random 0.1 1
local randNum = random 75 100
local randColor = color randNum randNum randNum
local dstarMesh = Box width:xdim length:ydim height:zdim name:"dstar" wirecolor:randColor
dstarMesh.position = [(random 0 size), (random 0 size), 0]
This time, I placed all the relevant code inside the function, ‘CreateDeathStar’. Using colons in the function name arguments allows us to either stick with default values by calling the function using brackets:
Or, we can pass values to the function to set our own parameters:
CreateDeathStar size:50 complexity:1200
As well as randomizing the size of the boxes, I am also setting the geometry up with random wirecolor values.
There are many applications for the random function and it can be used very effectively to create procedural geometry.