Python Scripting for Procedural Animation
by Geno Ruffalo

As of version 1.67 Blender can be programmed with the Python scripting language. Objects, Materials,
Lamps, Cameras, and World IPO's can be accessed and changed dynamically via Python. If you're an
artist that only uses Blender for Stills then Python will not help you (Not Yet). This tutorial will show
you how get the location of one object and change the properties of another depending on the location
of the first one. We will create a coiled spring that bounces off of a plane. We will use Python to
determine if the spring made contact with the plane and if so, compress it. We can move the plane or
resize the spring and you don't have do anything, Python will dynamicall recalculate the situation and
make changes accordingly. So let's start off with a quick lesson on coil modeling. In front view add
an 18 vertex circle, scale it down, deselect all vertices and add a 2 point line to right off it that is taller than
the circle. Set the edit buttons up as in the image below (Steps 16 - Turns 4) and click 'Screw'.
Make sure to place the objects and 3D cursor as shown.




Deselct All vertices and select only the center tube by placing the mouse pointer over one of the vertices
and pressing the LKEY. Delete the tube with the XKEY.



Scale the new coiled spring as close as possible into a 2x2x2 grid cube and make a new Center (EditButtons
lower left button 'Center New'). When done leave edit mode and press CTRL+A. This is going to make all size
parameters '1.00' and rotations '0.00'. You can press the NKEY to verify this.



Center the 3D cursor at 0,0,0 - go into top view (NUMPAD7) and add a Plane to the scene. I named my plane
'mPlane' and this will matter when we start scripting in the steps to follow.



Now we are ready for some scripting. I made a new screen in my .B.blend default file just for Python
and you may want to do something similar. First put the mouse over a 3D screen that you will type in
your Python code and press SHIFT+F11. This changes it to a text input window. Click the button with
the 'dash' icon and select 'ADD NEW'. I named my text object 'Script'. In the Edit Buttons Header click the new
button added in 1.67 that looks like a sheet of paper. As long as the Spring is selected a button with
an object icon will be available on the Edit Buttons header, so click it. This will show a new section in
the left side of the Edit Buttons Window. Click the 'New' button and enter the name of the text object in the
blank button. I highlighted all the buttons I am referring to red. Follow the link to the full size image and
save it so you can read the script clearly when you enter the script exactly as it is shown.



While scripting it is a good idea to show all the axis of the objects in our script. This is done in the
Edit Buttons. Look for the 'Axis' button all the way to the left in the 'Draw Extra' section. The rest of our
tutorial is going to be a detailed explanation of the flow of our script. We can now test our script.
To test the script go into front view and 'GRAB-DRAG' the spring down to the plane. It should compress when
it makes contact with the plane. Also you should not be able to drag it below the plane. If this doesn't
happen make sure you typed in the script correctly.



When planning a script ask yourself 'What, Where, When, and How':

What do we want to do? We want to compress a spring.
Where do we want to do this in the scene? Where the spring and plane meet.
When do we want to do this in the scene? When the spring is at the bottom of it's 'LocZ' IPO
How are we going to do this? That's what the rest of this lesson will cover!

Remeber when I said we can move the plane up or down and we don't have to make any changes to the script?
Give it a go, Leave the spring squashed on the plane as in the last example and move the plane up. The
spring should also move up.



Lets start with lines of code and what they do. (I am using " <-- -->" to seperate the code from the instruction)

<-- import Blender --> required in all scripts to import the Blender API

<-- mSpring= Blender.link --> 'mSpring' is the name I gave the object linked to this script. 'Blender.link' will never change.

<-- mPlane= Blender.Object.Get("mPlane")--> 'mPlane' is the name I gave to our Plane. 'Blender.Object.Get( )' is a function
that returns the DataBlock of object in the ( ). Enter the exact name of the object. Activate the object and look at the top
info header for th% name.

<-- if mSpring.LocZ < (mPlane.LocZ + (mSpring.SizeY / 2)): mSpring.LocZ= (mPlane.LocZ + (mSpring.SizeY / 2)) -->


This stops the spring from going under the plane. We could have simplified this by "if mSpring.LocZ < 1.0: mSpring.LocZ= 1.0"
But if the plane moved or we upsized our spring it wouldn't work. That is why in Step 3 we scaled the spring into a default
size of a 2x2x2 grid. Just substitute numbers to variables to understand the code. "mPlane.LocZ" is '0.00' & "mSpring.SizeY / 2"
= 0.5. That will stop the Spring from going under a locZ of 0.5. I used SizeY because SizeY is not going to change. The code
will stop the spring from going under the plane's locZ plus 1/2 the size of the spring. Try it, rescale the spring to twice
it's size. It won't go under the plane no matter how big you make it or where the plane's location is on the Z axis.










The next line determins if the spring needs to be compressed:

if mSpring.LocZ < (mPlane.LocZ + mSpring.SizeY):


The first part "if mSpring.LocZ < (mPlane.LocZ + mSpring.SizeY):" just checks the location of the spring & plane to see
if any compression is needed. Replace variables with numbers to test. Take our default situation: mPlane at center 0,0,0
and mSpring at original sixe of '1'. Now we have "if mSpring.LocZ < (0.00 + 1.00)" or 'if the Spring is lower than 1'
compress it. Double the size of mSpring and move the plane up 2 units and we have "if mSpring.LocZ < (2.00 + 2.00) " or
'if the spring(center)is lower than 4' compress it. Remeber an objects location is determined by its center (the little pink
or yellow ball)




 

The next line of code does the compressing:

mSpring.SizeZ= (mSpring.LocZ - mPlane.LocZ)

This is probably the simplest to understand if you haven't done much programming, or just suck at math! It simply states
that the tallness or 'SizeZ' of the Spring is equal to the location of the Spring minus the location of the Plane. Where the
Plane first meets the Spring there is no compression. That would be the Plane at 0.00 and the Spring at 1.00. Put in the
numbers. "mSpring.SizeZ= (1.00 - 0.00)" or "mSpring.SizeZ= 1", no change. Now when the Spring drops the size drops.
Put the spring's Z location at 0.75 and the size changes to 0.75.

The Last line:

else: mSpring.SizeZ= mSpring.SizeY

Makes sure that spring is scaled back to the original size once it is out if the "Squash Zone"






 

We could just as well use Python scripting to animate the Spring's Up & Down bouncing movement, but for
our purposes here it is easier to do it via IPO's. There is no need to write a script that isn't going to make any
changes or decisions during this animation. Go to FRAME1 & place the Spring at it's highest location and insert
a location IPO (IKEY). In an IPO window (SHIFT+F6) add keys with CTRL+LM. To make it look realistic make
a shaprer curve when the spring begins it's upward movement and a lower slope as it gets more & more compressed.
This will look as if the kenetic energy is building up as the spring compresses and 'pops' or releases
all at once when the spring cant take any more compression.



I hope I haven't put a strain on your brain because mine sure as hell hurts now!
If you can't get the code to work you can get the .blend file for this tutorial RIGHT HERE
and the final render RIGHT HERE


If you have't done so read a Python HOWTO and definitely the Complete Pages at
www.blender.nl/complete/index.html
At least learn the proper syntax and how to create 'if' 'then' loops and program flow.
If you're using Python Scripting then you have a C-Key, so add a little Motion Blur to our little example.
As I understand Python a little more I will write another more advanced tutorial because this one is
uses the limits if what I have discovered so far. GOOD LUCK!!