brief what is blender/python Blender is a Free and Open source 3D design and rendering package that is close to, if not, as powerful as commercial alternatives.
One of the elements allowing Blender such power and flexibility is its inbuilt Python scripting language. Python
is an interesting language pooling the object orientated functionality
from Java and C++ but retaining a simple to write Perl / JavaScript
formality.
In fact if you have programmed in a few languages before, the key thing to remember with Python is that instead of using curly brackets { } to encapsulate statement blocks it uses the whitespace indenting the code.
Confusing at first (and when you mix tabs with spaces) this soon becomes second nature ie.
def randomiseit(perc):
pr = (Blender.Noise.random()*perc)
# 50% of the time make it negative
if (Blender.Noise.random()<=0.5):
pr = pr-(pr*2)
if (perc == 0):
pr=0
return(pr)
Where to start
This script is ideally used with the Dupliverts option in blender (video tutorial)
A good reference is the Blender book
Basically dupliverts take an existing object and at each vertex places another object.
A good examples is a plane sub divided many times making a grid, take
this and a tree object and dupliverts will neatly place a tree at each
intersection on the grid instantly giving you a forest.
what I wanted
Problem with your new forest is every tree is aligned and spaced exactly the same as its neighbor.
I had a grid of mirrors reflecting the 'sky' and wanted a bit of
randomness (without manually changing the rotation of each mirror).
So I wrote the SaltShaker script to do it for me.
getting a mesh
In Blender setup a scene and split the view vertically.
To run the code press [ALT]+P, the result of the print command is sent to the console window.
That was exciting wasn't it ?
No, well now we have the code to capture the "Cube" object we can do something with it.
Much more interesting, makes you wonder about the possibilities huh ?
The Blender.Redraw()
line at the end simply updates your blender window to show the change,
otherwise it happens but you do not see the results until you or
something else updates the screen.
In my original file I had manually copied the mirrors and they
had been given sequential names (same thing happens when using
dupliverts)
I thought the easiest way to process each mesh/mirror was to loop through the names.
import Blender
for i in range(1,3+1) :
s = str(i)
myObj = Blender.Object.Get("Cube." + s.zfill(3))
print myObj.name
myObj.RotX = myObj.RotX + 0.75
Blender.Redraw()
So what have we added; a loop for i in range(1,3+1) :, which is defined by the indenting and gives us i=1,i=2,i=3. s = str(i) which sets the variable s to a string version of the number held in i, will become clearer in a moment. .Get("Cube." + s.zfill(3)) which takes the string value of s and pads it with zeros to make it three characters long.
1 becomes 001, 2 becomes 002, 3 becomes 003 etc. giving us Cube.001, Cube.002, Cube.003 which is the names Blender gave the cube meshes.
This will rotate each cube (minus the first one which is named just "Cube")
I had this exact code setup for 80 objects (for i in range(1,80+1) : )!!
Before I get onto a better way of doing this, I needed a random element
import Blender
from Blender.Noise import *
for i in range(1,3+1) :
s = str(i)
myObj = Blender.Object.Get("Cube." + s.zfill(3))
#print myObj.name
pr = (Blender.Noise.random()/100)
myObj.RotX = myObj.RotX + pr
pr = (Blender.Noise.random()/100)
myObj.RotX = myObj.RotX - pr
Blender.Redraw()
When you run this with [ALT]+P what happens ? Nothing ? not quite try holding down [ALT]+P (three of the cubes should rotate slightly).
What is new this time; the hash in front of print myObj.name has made the line into a comment so we will NOT see the name of the object being rotated. from Blender.Noise import * at the top means we can use the built in random function to get random numbers. pr = (Blender.Noise.random()/100) assigns a random number
between 0 and 1 divided by 100 to the pr variable. (trying changing it
to /10 or /1 to get much more dramatic results)
And I duplicated the myObj.RotX = myObj.RotX + pr line to allow the rotation to be random in a negative direction.
So that gave me the subtle result I wanted
I quickly realised that I could use a more generic version of this code on lots of other scenes that required random objects.
If only I could make a nice front end so anyone could use it.
getting any currently selected mesh
I knew I could not ask users of the script to rename all their meshes to Cube.001, Cube.002 etc, so the first thing to change was the selection phase.
for i in range(1,3+1) :
s = str(i)
myObj = Blender.Object.Get("Cube." + s.zfill(3))
became
objList = Blender.Object.GetSelected()
for obj in objList :
myObj = obj.getData()
and to make sure we were not perverting any cameras or other randomly selected objects (lights etc).
if myObj.getType() == 'Mesh':
GUI
I started looking at some random python scripts on the internet, but none of them had pull down menus.
Then I came across http://www.elektrolite.com/btk_gui/ but it is way out of date and although easy to use and runs inside blender, the code it produced was unsuitable.
I had heard of a windows only Blender python interface GUI creator http://oregonstate.edu/~dennisa/Blender/BPG/.
I heated up the old windows laptop I had lying around and gave it a whirl, easy to use and produced the results I wanted.
So that was the end of that then ? Not quite, I found the code produced
did not allow easy alterations so I changed all(some) of the hard coded
values to be dynamic.
This way I could move things about easily, check the code to see what I mean. (click image for .blend file)
Future
If I want saltshaker to become part of the Blender shipped scripts then I need to follow the blender python script conventions.
I also might change the values used to be clearer i.e. 100% equals one
full rotation and one complete offset instead of my easy to use options.
Either use the pull down menu to pre-set the sliders or manually move them yourself. "Tilt X%" has a value 0 - 100 where 0 is no rotation on the X axis and 100% is a quarter turn.
(likewise for "Tilt Y%" and "Tilt Z%")
"Move X%" has a value 0 - 100 where 0 is no movement in the X axis and 100% is a half step on the X axis (based on the size of the object).
(likewise for "Move Y%" and "Move Z%")
Now with all the relevant objects selected in the scene (selection can be made at anytime) hit the "Shake" button and they will be shook!
The "Exit" button ends the SaltShaker python script.
I would have liked to have the "Undo"
button 'undo' the last change made (i.e. the 'shake') but it I have not
yet found a way to get at the Undo history to implement this.
The button does nothing, to perform a manual undo use [ALT + u].
Disclaimer:
This page is by me for me, if you are not me then please be aware of the following
I am not responsible for anything that works or does not work including files and pages made available at www.jumpstation.co.uk
I am also not responsible for any information(or what you or others do with it) available at www.jumpstation.co.uk
In fact I'm not responsible for anything ever, so there!