Python: How to Randomize Rotation in Blender

The Confetti Function

A couple weeks back, I posted a confetti function that was wildly fun to play with, but frustrating because all the confetti was oriented in the same direction.

In the end, I started selecting the individual planes at random to rotate the manually, but well, let’s face it. There were over 200 planes. That was just stupid. Two new lines of Python. That’s all it took. I actually wasn’t even the Python that threw me in the first place—it was the rotation operator.

How Does Transform.Rotate Work?

Here’s the thing about the rotation transform operation—the first parameter (unhelpfully referred to as “value” on the Blender API page) is the amount you wish to rotate your object. In radians.

Remembering that there are approximately 6.2 of those in a circle, we can adjust the rotation value to be a random number between 1 and 6.2.

The next parameter is axis. It takes three values—all of which should be numbers between 0 and 1—for which axis you wish to rotate around. X, Y, or Z.

So, for instance, if you wanted 10 planes randomly rotated around the y-axis, that could be accomplished by plugging in a loop like this:

y axis

Cool, right? I’m sure I’ll use that later at some point when I start modelling space ships, but back to the point.

An Updated Confetti Function

So, I added two lines to the existing function. First, the line assigning a random number to the variable R. Just as a reminder, if you want to randomize a floating point number (with decimal places), use random.uniform.

r=random.uniform(0,6.2)

Second, the final line, rotating the plane by the value inside R. And presto. Randomly rotated confetti.

bpy.ops.transform.rotate(value=r, axis=(1,1,1))

Enjoy.

Rotate with Python in Blender

The Full Script

Remember, this one only works with Blender Cycles. And if you want white, you have to jack all the values (Red, Green, Blue) up to 1.

import bpy
import random

def confetti(MatCol,r,g,b):
bpy.ops.mesh.primitive_plane_add()
bpy.ops.transform.resize(value=(.25,.25,.25))
#Resize to fit the scene
bpy.data.objects['Plane'].name = MatCol
#Rename the planes as the 1st paramater above
mat_name = MatCol
mat = bpy.data.materials.new(mat_name)
bpy.data.materials[mat_name].use_nodes = True
bpy.data.materials[mat_name].node_tree.nodes.new(type='ShaderNodeEmission')
inp = bpy.data.materials[mat_name].node_tree.nodes['Material Output'].inputs['Surface']
outp = bpy.data.materials[mat_name].node_tree.nodes['Emission'].outputs['Emission']
bpy.data.materials[mat_name].node_tree.links.new(inp,outp)
bpy.data.materials[mat_name].node_tree.nodes['Emission'].inputs[0].default_value = (r,g,b,.5)
bpy.data.objects[MatCol].active_material = bpy.data.materials[mat_name]
#Run a loop 100 times
for index in range(200):
bpy.ops.object.select_all(action='DESELECT')
#If you don't deslect the other objects, the results are real weird
bpy.data.objects[MatCol].select = True
x=random.uniform(-10,10)
y=random.uniform(-10,10)
z=random.uniform(-10,10)
r=random.uniform(0,6.2)
#Randomize some variables
bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False,"mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(x,y,z)})
bpy.ops.transform.rotate(value=r, axis=(1,1,1))

confetti("WhiteMat", 1, 1, 1)

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: