before SaltShaker after


Download the SaltShaker script I wrote in Python for Blender
(usage)

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.

before


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


getting a mesh
In Blender setup a scene and split the view vertically.
Enter the following code.
import Blender
myObj = Blender.Object.Get("Cube")
print myObj.name
tut_001
(click image for .blend file)
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.
import Blender
myObj = Blender.Object.Get("Cube")
print myObj.name
myObj.RotX = myObj.RotX + 0.75
Blender.Redraw()
tut_002
(click image for .blend file)
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()   
tut_003
(click image for .blend file)
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
title result

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.
tut 004
(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.


Usage
So you have downloaded the script and want to shake things up a little ?

inside blender hit [SHIFT + F11] to switch to a text window (it is a good idea to split the screen first, so you can still see the 3D scene).
Hit [ALT + o] or select Open from the File menu and load the
saltshaker script (file with .py extension)
Now hit [ALT + p] and the GUI will appear in the text window (hiding the actual code).
gui

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


links
Dupliverts video tutorial
Windows only Blender Python GUI creator
SaltShaker project page at sourceForge.net
current SaltShaker script(kindly hosted by sourceForge.net
Blender python Docs
Blender.org
Blender3d
Blender python scripts
Blender wikibook

Blender has many other resources on the net, look closer!

email saltshaker at jumpstation.co.uk ]

root


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!


Thanks be to SourceForge.net
SourceForge.net Logo
Image linking to http://www.pay4foss.org