18
Using Python Scripting in Blender Michael Malmrose, Ott Planetarium, Weber State University Welcome to the great Python documentation caper. I will try to coherently write down what I learned about Python in general, and some blender specific stuff. If nothing else, it will provide a decent jumping off point and some scripts that can in principle be easily modified to do something useful. Enjoy! 1. Introduction to Python First and most important, the Python tutorial that I used is located here: http://docs.python.org/tut/ . This may also prove to be helpful http://docs.python.org/mac/mac.html . It should be noted that the Python language is not named after serpents, but after the hilarious British comedy troupe “Monty Python”. When writing tutorials it is standard form to exploit this fact for comic effect, and I will continue the tradition. Let’s get started. To open python from the terminal, simply type “python”. To exit type ‘quit()’. Before you begin also note that python is a case sensitive language. If you define: >>> mad = ‘scientist’ and then ask python to do something with the variable Mad, you will get an error message. Variables: Python is an Implicit All language. Unlike FORTRAN, Python encourages enraging your programming instructors by hiding variable declarations deep within your code. Python variables can be integers, strings, real, or complex as in the following: >>> x = 'spam' >>> y = .141592653 >>> y = y+3 >>> z = 0 >>> imagine = complex(3, 14) >>> print imagine (3+14j) >>> print x spam >>> print y 3.141592653 >>> print z 0 You can also recreate parts of classic comedy bits with python. >>> x = 'spam ' >>> y = 'egg ' >>> print x*3 + y + 'and ' + x spam spam spam egg and spam

diana

Embed Size (px)

DESCRIPTION

diana diana diana

Citation preview

Using Python Scripting in Blender Michael Malmrose, Ott Planetarium, Weber State University Welcome to the great Python documentation caper. I will try to coherently write down what I learned about Python in general, and some blender specific stuff. If nothing else, it will provide a decent jumping off point and some scripts that can in principle be easily modified to do something useful. Enjoy!

1. Introduction to Python

First and most important, the Python tutorial that I used is located here: http://docs.python.org/tut/. This may also prove to be helpful http://docs.python.org/mac/mac.html. It should be noted that the Python language is not named after serpents, but after the hilarious British comedy troupe “Monty Python”. When writing tutorials it is standard form to exploit this fact for comic effect, and I will continue the tradition. Let’s get started. To open python from the terminal, simply type “python”. To exit type ‘quit()’. Before you begin also note that python is a case sensitive language. If you define: >>> mad = ‘scientist’ and then ask python to do something with the variable Mad, you will get an error message.

Variables: Python is an Implicit All language. Unlike FORTRAN, Python encourages enraging your programming instructors by hiding variable declarations deep within your code. Python variables can be integers, strings, real, or complex as in the following:

>>> x = 'spam' >>> y = .141592653 >>> y = y+3 >>> z = 0 >>> imagine = complex(3, 14) >>> print imagine (3+14j) >>> print x spam >>> print y 3.141592653 >>> print z 0

You can also recreate parts of classic comedy bits with python. >>> x = 'spam '

>>> y = 'egg ' >>> print x*3 + y + 'and ' + x spam spam spam egg and spam

Notice how if a variable is a string, the multiplication sign tells python to write it that many times.

>>> meatlikesubstance = x*3 >>> print meatlikesubstance + ‘wonderful ‘+ x spam spam spam wonderful spam

If you want to write a combination of strings and numbers you’ll need to convert the numbers to strings first.

>>> x = pi >>> y = x**2 >>> z = 1./2. >>> meat = 'sausage' >>> print meat +" "+ str(z) +" "+ str(y) sausage 0.5 9.86960440109

Arithmetic in python is done the usual way. If you want to do some useful calculations you may want to import the math module though. You may also be interested in a list of python’s math functions, http://docs.python.org/lib/module-math.html. >>> import math

>>> from math import * These two lines tell the interpreter to go grab the math module and bring along everything that lives in that module.

>>> x = pi >>> y = x**2 >>> print x, y 3.14159265359 9.86960440109 >>> z = complex(3,4) >>> zstar = complex(3,-4) >>> z * zstar (25+0j)

Unfortunately, the calculator is not perfect and you will have to deal with round off errors. Here are a couple annoying examples. >>> cos(pi/2)

6.1230317691118863e-17 >>> sin(pi) 1.2246063538223773e-16

Another useful thing is that variables can be lists. The following shows how to exploit that. >>> super_cool = [pi, cos(pi), 'lumberjack', 'Galahad the chaste', 3*4]

>>> print super_cool[3] Galahad the chaste >>> print super_cool[0] 3.14159265359

You can also add to lists after they have been declared >>> super_cool.append(42)

>>> print super_cool [3.1415926535897931, -1.0, 'lumberjack', 'Galahad the chaste', 12, 42]

Incidentally, a string is just a list. You can play around with that if you’d like. It could be useful if you are trying to read in data, but only want to use part of what you read in.

>>>mmmPi = ‘3.141592653’ >>>Piless3 = float(mmmPi[1:10])

Now I think that it is time for a ‘hello world’ program.

2. Programs Hello world

Here is a ‘hello world’ program written in python: #!/usr/bin/python # This is a comment ## This is another comment print “hello world” The first line will tell the interpreter that this is a python document; the rest should be self explanatory. Type the program into a text editor and save it with extension the extension .py , I named it hello.py. In the terminal type the following lines:

chmod +x hello.py ./hello.py

Congratulations! You have successfully written and executed your first python program. If-Then-Else statements The syntax for if statements (and loops) is very simple. The following code:

>>> x = 0 >>> if x < 10: ... print 'x is less than 10' ...

has the output: x is less than 10.

The syntax for an if statement is a colon at the end of the line containing the statement, and a single tab on every line that is to be executed if the condition is met. Else-if statements use the word elif, and else statements use else. This code: >>> x = 20

>>> if x < 10: ... print 'x is less than 10' ... elif x < 100: ... print 'x is less than 100' ... else: ... print' x is greater than 100' output is guess what?

Here is how you can print a table of numbers and their squares from 0 to 9.

>>> for naughtius_maximus in range(10): ... print str(naughtius_maximus) + " " + str(naughtius_maximus**2)

Here is another way it can be done >>> naughtius_maximus = 0 >>> while naughtius_maximus < 10:

... print str(naughtius_maximus) + " " + str(naughtius_maximus**2)

... naughtius_maximus = naughtius_maximus + 1 If you only want the even ones >>> for naughtius_maximus in range(2,10,2): ... print str(naughtius_maximus) + " " + str(naughtius_maximus**2) You can even print it backwards >>> for naughtius_maximus in range(10,2,-2): ... print str(naughtius_maximus) + " " + str(naughtius_maximus**2) Getting Data You can get data directly from the user in the terminal, read it from a file, or if so inclined you can build a graphical interface (in blender the last two options are the only ones that works as far as I can tell). I will explain the first two and come back to the third one when I write about scripting in Blender. a) There are a couple ways to prompt the user for info. Here are some examples:

Theta = input(“What is the launch angle in degrees?”)

or, print “What is the launch angle?”, # remember the comma theta = float(raw_input())

If you are expecting the input to be a string, use the second option. print “What is your name?”, name = str(raw_input()) print “What is your quest?”, quest = str(raw_input())

print “What is your favorite color?”, colorfav = str(raw_input())

b) Reading data from a file can be a little tricky, but it is possible. The first thing you

need to do is tell python which file you want to open and open it. Fileout = ‘shrubbery.txt’ Thisfile = open(Fileout, ‘r’)

The second line tells python to open the file for the purpose of reading it, if you want to write to the file simply replace ‘r’ with ‘w’. If you wish to read and write put ‘r+’. if you want to add data to the end of the file, use ‘a’. Now that we have the file open, it’s going to get fun. If you want to read x amount of data, type Thisfile.read(x). This will read x number of characters, if x is omitted the entire file will be read. If you want to read an entire line in, type Thisfile.readline(). To read all the lines of a file into a list type Thisfile.readlines() the “\n” at the end of the line is an instruction to the interpreter to begin a new line. Here is a simple way to print the entire contents of a file: for line in Thisfile: print line I have found that the most convenient way to read data is to read the file in line by line, and then use a command called split() to break it into it’s individual words. xvals, yvals, zvals = [], [], [] for line in file.readlines(): words = line.split() ##What this does is create a list called words on the present line. Now you can get ##whatever data you need before you head to the next line x, y, z = float(words[0]), float(words[1]), float(words[2]) xvals.append(x) yvals.append(y) zvals.append(z) If there is a header to skip, you’ll want to use the pass command. if words[0].startswith(‘!’) or words[0].startswith(‘S’): pass else: do some stuff… When you are done, it is always good form to close the file you were working with. This is accomplished with ‘Thisfile.close()’. c) Writing to files is easier than reading from them. Here’s an example that will write a

table of cubes to a file:

import math from math import * print"And where do you want this bad boy saved? ", output = str(raw_input()) outty = open(output, ‘w’) for x in range(10): outty.write(str(x) + “ “ + str(x**3) + “\n”)

Before being written, everything must be converted to a string. At this point the programs projmo.py and monT.py should be accessible. Make sure you also have the files ‘graisong’, ‘lifesong’, and ‘briansong’. Functions Python allows you to separate your code into separate functions. The syntax is def Name(variable_to_pass, another_variable_to_pass): Your code here… Functions can be useful if you plan on writing a lot of programs that use similar algorithms. Here is a very simple program containing a function, it can also be found in the file ‘function.py’. #!/usr/bin/python # Sample python program to show how to write a fucntion # This will get some input from the user and then save the output to a file. ######################################################################## import math from math import * the_gimp = [0,1,2,3,4,5,6,7,8,9] ## The variable passed to Bring_Out will be renamed 'The_Gimp' def Bring_Out(The_Gimp): file = open('LookyHere.txt','w') i = 0 while i < 10: file.write(str(The_Gimp[i]) + " " + str(The_Gimp[i]**2) + "\n") i = i + 1 file.write("The Gimp's sleeping \n") ## Pass the_gimp to the function Bring_out Bring_Out(the_gimp) If you want to use the results of a function somewhere else in your code, use the return command. This will return the result of a function back to the main code. Example:

#!/usr/bin/python

import math from math import *

def devo(x):

return x*2 x = 3 y = devo(x) # y is now 6 elephant = y**2 print elephant

Line Continuations

In python there are two ways to make multi line statements. If you are defining a list, you only need to add a comma after the last entry on the first line, and then indent the next. Funny_Movies = [‘The Big Lebowski’, ‘Airplane’, ‘Fargo’, ‘Maverick’, ‘Dr. Strangelove’, ‘Meaning of Life’] This is known as implicit line continuations in Python speak. If you are not working with a list, you will need to explicitly continue the line. The symbol for that is \. PositionY = (Initial_Velocity * sin(Theta*pi/180) * time) \

- (0.5 * g * time**2) Formatting Output Formatting output in Python is pretty sweet once you get the hang of it. A quick and dirty way of formatting a number is to use the round function. >>> x = pi >>> print round(x,4) 3.1416 One drawback of the round function is that if the number doesn’t have as many decimal places as you specify, it will not add trailing zeros. This can be very frustrating if you are trying to align your output. If you know that your output is going to have fewer spaces than you want to fill, you can use the zfill() function to pad the number. It inserts zeros until the number takes up the number of specified places, zfill() will not truncate numbers however. >>> x= 42 >>> print str(x).zfill(5) 00042 >>> ‘-3.14’.zfill(7) ‘-003.14’ >>> ‘3.14159265’.zfill(4)

‘3.14159265’ Note that the output needs to be a numeric string for zfill to work. If you want to specify where a number will end (and it’s not too long) you can use rjust(). You just put the number of tabs you want inside the parenthesis. Remember that rjust() also requires the output to be a string. Here is a way to print a table of the values of Exp(x). def expon():

print 'x'.rjust(2), 'e^x'.rjust(18) print '-------------------------------------------------' for x in range(50):

l = x/10.0 print str(l).rjust(3), str(round(exp(l),4)).rjust(20)

expon() In addition to rjust(), there are also ljust() and center() functions that work similarly. Currently I prefer to use the % function to format output. It allows you to specify how much space a number will take up and how many decimal places it will contain.

Radius = 3.14 print “ The radius is %6.4f “ %Radius + “\n”

The result of the print statement is ‘ The radius is 3.1400’. For more on formatting go to http://docs.python.org/tut/node9.html

3. Blender Before you do anything check out http://www.blender.org/download/python-scripts/. This is a repository of Blender scripts that have been released to the public. They claim that they are well maintained, but I have found a few that don’t work with the current version of Blender. You can open a terminal like console from Blender. To do this switch to the scripts window and click on: Scripts >> System >> Interactive Console. You can now input python commands just like you would from the command line. If you type in help(Blender) and dir(Blender), it will give you an idea of what can be controlled via a python script. To write scripts in blender, you need to change a window to the text editor. There are two modules that you need in order to access the inner workings of Blender. They are bpy, and Blender. The blender module is the older of the two and will eventually be replaced by bpy. Right now they both work and I usually import them both to be safe. You can also make your life easier by pushing the buttons at the bottom of the window that will display line numbers, and allow syntax highlighting. These tutorials will teach you some of the very basics of scriptwriting in blender: http://jmsoler.free.fr/didacticiel/blender/tutor/python_script00_en.htm http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/Advanced_Tutorials/Python_Scripting/Export_scripts

http://www.blender.org/documentation/243PythonDoc/ Unfortunately only part of the first one is in English (if you understand French you’re in business for the rest though). The second one woefully incomplete, but it does have some useful stuff in it like how to read files. There are also a couple sample scripts to help you get a feel for what you’re doing. The third one is a list of all the keywords that live in the blender module. I don’t find it very useful because it doesn’t really show any examples on how to use them. If you already know how to use them, it’s good for reference though. To run a script, press ‘option+p’. Be careful with your programming, because blender doesn’t seem to want to tell you where everything went to hell. The first useful thing you can do is create a mesh out of thin air, and link it to an object. I know it is easy to do this by pressing the spacebar, but this way is much more fun : ). The file spheregui.py does this by means of a user interface; I’ll go through it line by line to comment what it’s doing. For now skip all of the GUI stuff and begin on line 91. def sphereme(Radius): sphere = NMesh.GetRaw() This defines a function called sphereme that will be passed the variable Radius. The second line defines a list of the Blender type NMesh. ## get the number of vertices maximumpoint = 32.0*32.0 n=sqrt(maximumpoint) for i in range (0,n): for j in range(0,n): x = sin(j*pi*2/(n-1))*cos(-pi/2+i*pi/(n-1))*Radius y = cos(j*pi*2/(n-1))*cos(-pi/2+i*pi/(n-1))*Radius z = sin(-pi/2+i*pi/(n-1))*Radius v = NMesh.Vert(x,y,z) sphere.verts.append(v) ##The vertices are now assigned but without faces we don't have ## a sphere do we? This particular sphere is going to have 1024 vertices. They will be created in a couple of nested loops that range from 0 to 31 and each time i or j increases, the position of the vertex to be created will move by a 1/32 of a circle. The last two lines define v as a vertex and adds v to the mesh we named sphere.

n0 = len(range(0,n)) ## this works similarly to the first do loop. for i in range(0,n-1): for j in range(0,n-1): f = NMesh.Face() f.v.append(sphere.verts[i*n0+j]) f.v.append(sphere.verts[i*n0+j+1]) f.v.append(sphere.verts[(i+1)*n0+j+1]) f.v.append(sphere.verts[(i+1)*n0+j]) sphere.faces.append(f) ball = Blender.Object.New(‘Mesh’) ball.link(sphere) Now = Scene.GetCurrent() Now.link(ball) ball.setLocation(0,0,0) Blender.Redraw() n0 = len(range(0,n)) creates an integer out of the range(0,n) this is needed because the vertices live in an indexed list. Asking for vertex n-1 would result in an error. Other than that, it is almost the same as creating the vertices. The final two lines put the mesh in the scene, name it ‘ball’, and then draw it. Now we’re ready for the GUI.

# Implicit Some ##Default the parameters of the GUI T_Radius = Create(1.0) #Events EVENT_NOEVENT = 1 EVENT_DRAW = 2 EVENT_EXIT = 3

Apparently some of the variables in python need to be explicitly defined, so far the only ones I have run into are variables that will be controlled by a user interface. The last three lines are there to be used in subsequent if statements. def draw(): global T_Radius global EVENT_NOEVENT,EVENT_DRAW,EVENT_EXIT These lines tell the function that it wants to use previously declared variables ## I used the following tutorial to learn how to build this.

##(http://wiki.blender.org/index.php/Manual/Python_Scripting) glClear(GL_COLOR_BUFFER_BIT) glRasterPos2d(8,103)

Text("This script creates a sphere") ############### GUI buttons # The comments in the file blenderprojmo6.py explain the syntax of # the GUI buttons glRasterPos2d(8,103) Text("Parameters:") T_Radius=Slider("Radius:",EVENT_NOEVENT,10,55,210,18, T_Radius.val,0.001,20.0,1,"Radius of the sphere"); This tells it to make the radius controllable via a slider. The range can be from 0.001 to 20.0 units and the slider increases the radius by 0.1 when it is clicked. The first line controls the placement and the size of the button. 55 means 55 pixels from the bottom of the window and 10 is the thickness. The first line also tells it to keep the interface open as you move the slider ################ Draw and Exit Buttons Button("Draw",EVENT_DRAW,10,10,80,18) Button("Exit",EVENT_EXIT,140,10,80,18) Draw your two action buttons and assign what it is they are going to do. The interface still isn’t drawn at this point, but we are very close. def event(evt,val): if(evt==QKEY and not val): Exit() #For some reason, let people quit by pressing Q, but don’t tell them about it def bevent(evt): global T_Radius global EVENT_NOEVENT,EVENT_DRAW,EVENT_EXIT ## The possible inputs are now decided, so let's tell the computer how ## to handle them. if(evt==EVENT_EXIT): Exit() elif(evt==EVENT_DRAW): sphereme(T_Radius.val) Blender.Redraw() # Now blender knows what to do when you press one of the two buttons. # It also knows what you did last summer.

Register(draw,event,bevent) This is the line that will make it work. It kind of forces those three functions to play nicely together. After playing with this GUI code for a while, I was able to modify the projmo.py program to run in Blender. It is much more convenient in enter your inputs this way and the program now goes by the name Blenderprojmo8.py. If you don’t want your sphere created at the origin, you need to add a few lines. You will need to create an object and place it at a point in the scene before you draw the mesh. This is actually a good idea, even if you do want the object at the origin. Lameo = bpy.dada.objects[‘Mesh’] Lameo.LocX, Lameo.LocY, Lameo.LocZ = x, y, z …. …. (Now draw the sphere). If you are do not want to use the bpy module, you can still do the same thing. Just follow this procedure:

Mymesh = NMesh.GetRaw() … (create the vertices and faces of the mesh) lameo = Blender.Object.New(‘Mesh’) NMesh.PutRaw(Mymesh, “name”, 1) lameo.link(Mymesh) Now = Scene.GetCurrent() Now.link(lameo) ## Set the Location lameo.setLocation(x,y,z)

Writing If you are running a physical simulation of some sort and want to save the output to a file (why would you want to do that silly?), the procedure is a little bit different in Blender. Fortunately all of the formatting stuff is the same. Output must be saved to a file via a function, also it seems that any calculations must be performed inside the same function. Here is a sample along with what it is doing: def WaferThinMint(look_it_up): global Fat_Man global French_Waiter global F_Word gross = Fat_Man.val unforgivable = French_Waiter.val cuss = F_Word.val memorable_scene = gross + unforgivable + cuss # This line is the main difference between working in blender and

# working with a regular Python program. out = file(look_it_up, ‘w’) out.write(“!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \n”) out.write(“ !Man that scene was gross. \n”) # write the calculated value to the file, but only keep four decimal places out.write(str(round(memorable_scene, 4)+ “\n”) out.close() ## Showtime. This prompts the user for the file to save the output to. ## It asks for the function to call, and what you want the confirm button to say.

Blender.Window.Fileselector(WaferThinMint, “No going back now.”) The function begins like any other function with a name and a variable that it will be passed. I have only been able to get functions that write to files to work if I pass them 1 variable. I get around that by importing global parameters. I then define new variables as the value of parameters so that I can perform arithmetic operations on them and finally get to the interesting part. I write a two ine header for the file and then put in the interesting part rounded to 4 decimal places in this case, and then type in the command that executes the function. Material After you’ve created a mesh, you can assign a material to it straight from the script. This can be useful if you are creating many similar objects and you want to distinguish them somehow, but if you want to do some heavy duty editing, you should just use the buttons window. Anyway here is a way to assign a material to an object. Mymesh = NMesh.GetRaw() … make the vertices and faces… therock = Blender.Object.New(‘Mesh’) ballmat = Material.New(‘Material’) Mymesh.materials.append(ballmat) ballmat.rgbCol = [1.0,0,0] # makes it red ballmat.setAlpha(x) ballmat.setRef(y) ballmat.setSpec(z) ballmat.setHardness(xx) … ## Any other aspect of the material you wish to set here. ## Place it in the scene. therock.link(Mymesh) Animation It is possible to use python scripting to create an animation in Blender. The dirty, but not so quick way is to use a script to control the location of the object you are

animating, and then to insert a key frame manually at whatever interval you wish. This will take a lot of time, but it will work. To do this you will need two scripts. One to generate an output file, and one that will read that file and move the object accordingly. I assume that you already know how generate a file of coordinates so I’ll just explain the script that places the object. ## Begin the script with the standard opening lines. def import_baseball(path): #Let the user know that the computer is doing something Blender.Window.WaitCursor(1) file = open(path,'r') Those lines just define the function, and turn the mouse pointer into that cute wristwatch thingy. It also opens the file that is going to be read ## Create some empty arrays that will be filled with the data from the file. posx = [] posy = [] posz = [] ## Read the file line by line if posx == []: for line in file.readlines(): words = line.split() ## Skip any header in the file if words[0].startswith('#') or words[0].startswith('!') \

or words[0].startswith(‘$’): pass else: #Convert from a string to a float x,y,z = float(words[0]),float(words[1]),float(words[2]) # Scale the coordinates down to fit in the blender window posx.append(x) posy.append(y) posz.append(z) At this point, all of the relevant data is read and store in the appropriate arrays. Now it’s just a matter of sleuthing through it to find the element we want. The program will get the current frame from blender, and get the object named ‘Mesh’. Then it will place the object at the location corresponding to the current frame.

now = Blender.Get('curframe') ## The name in the next line will need to be changed to whatever you named the ## object. ball = Blender.Object.Get('Mesh')

## Change the orientation of the axis. ball.setLocation(posx[now-1],posz[now-1],posy[now-1])

Blender.Window.Redraw() Blender.Window.WaitCursor(0) #Execute the above Blender.Window.FileSelector(import_baseball, 'Import') To run the script, load it in the text editor window and hit ‘control-p’. You can now insert key frames to your heart’s content. Make sure that if you have any header in your file, the line begins with ‘$’, ‘#’, or ‘!’. This method isn’t very elegant, but it will work on shorter animations. Longer animations are going to require controlling Ipo objects directly from the script. The documentation on this totally sucks, but it turns out to be really simple to do. Like totally simple you won’t believe that it took so damn long to figure out. Suppose you have an object at position x and you want it to move to position y in 50 frames. Here is how to do it Holy_grail = Blender.Object.New(‘Mesh’) Holy_grail.link(name of mesh goes here) Now = Scene.getCurrent() Now.link(Holy_grail) TheTimeIs = Blender.Get(‘curframe’) Holy_grail.setLocation(x1,x2,x3) ## Ready for the magic? Seriously it’s one freaking line! Holy_grail.insertIpoKey(3) TheTimeIs = TheTimeIs + 50 Blender.Set(‘curframe’, TheTimeIs) Holy_grail.setLocation(y1,y2,y3) Holy_grail.insertIpoKey(3) Blender.Window.Redraw() The command insertIpoKey(3) inserts a key frame for the current location and rotation of the object. If you put a 1 in the parenthesis you insert a rotation key. If you put a 2, you get a scale key frame. What each index inserts a key frame for corresponds to the order they are listed when you insert a key frame manually. If you add a few lines to the beginning of the script, you will be able to run it from the scripts window. Here’s the syntax for that. #!BPY

“”” Name: ‘Name of script goes here’ Blender: 244 Group: ‘Name of the group you want this script to live with’ Tooltip: ‘I usually write something witty here’ “”” Now from the scripts window click Scripts > Update Menus and you should be able to find it More Animation If you’re not just content with adding key frames at certain intervals from a script, don’t fret because Blender allows you to control the entire Ipo object. You can set interpolation and extrapolation values, position, time, and well pretty much anything you can control from the Ipo window straight from the script. This gives you a lot power, but it can be difficult to learn how to use. Here are a couple places that I found useful in learning how to do this: http://ash.webpark.sk/recIpo_eng.htm, http://www.blender.org/documentation/243PythonDoc/Ipo-module.html. A simple example I can think of is a magic teleporting ball. A sphere will move along for some short distance than disappear from the universe and reappear somewhere else. I don’t think that this animation would be possible from keyframing alone. Make sure you have a sphere in the scene and that it is the only object selected. Then type the following into the interactive console: CheshireBall = Blender.Object.GetSelected() ChesihreBall = CheshireBall[0] # Create a new ipo object. It’s going to be an Object type ipo and will be named #animation. ipo = Ipo.New(‘Object’, ‘Animation’) ## Tell Blender who this new Ipo lives with. CheshireBall.setIpo(ipo) # Add the position curves to the Ipo x = ipo.addCurve(‘LocX’) y = ipo.addCurve(‘LocY’) z = ipo.addCurve(‘LocZ’) xx, yy, zz = 0, 0, 0 ChesireBall.setLocation(xx,yy,zz) ## Add a Bezier point at a frame number and location. ## For some reason double parentheses are required. x.addBezier((1,xx)) y.addBezier((1,yy))

z.addBezier((1,zz)) # Set the interpolation values. x.setInterpolation(‘Constant’) y.setInterpolation(‘Bezier’) z.setInterpolation(‘Bezier’) x.update() y.update() z.update() ## Move it to the final location. xx, yy, zz = 4, 5, 6 x.addBezier((25, xx)) y.addBezier((25, yy)) z.addBezier((25, zz)) x.update() y.update() z.update() The Game Engine One situation where I see that having such control over ipo’s is useful is if you is using Blender’s game engine to do a physical simulation. If you want to use Blender’s game engine as a physics simulator and save the results with an Ipo script, definitely see the link at the top of the last page. The file ‘projectile_motion.blend’ is already set up to animate the results of the game engine. If you add any objects, they will also be animated as long as you remember to activate the actor button in the buttons window. You will then need to click ‘add property’, change it to a ‘bool’ type, name it ‘ipo’, and click on ‘True’. Here is how to set it up. 1) Add an empty object to the scene 2) In the buttons window, click on the icon that looks like a blue Pac-man 3) Click “Add Property” and choose “Timer” from the list. 4) Add a couple of sensors to the empty. Choose always from the list, and unclick

the ‘’’ button on the first sensor. This will make it so that the script you are about to link to this sensor only runs once. Now on the second sensor, put 2 in the f field. This will make the second script run every second frame.

5) Add two controllers; select Python from the list and in the script field type ‘recIpo.py’ and ‘recFrame.py’ respectively. Now link the sensors to the controllers you just created. You also need to name the sensors sinit and sframe respectively. This is because the script actually looks for sensors by those names. If you name them something else, be sure to make the appropriate changes to the script.

6) Add the objects that you want to animate. Click Add Property, choose Bool, name it ipo, and click true.

7) Click Actor, and then Dynamic to make your object subject to physics 8) Place the mouse pointer in the 3d view window, make sure you are in object mode

and hit p. This will put you in game mode, and your objects should move around.

Hit esc to get out of game mode. There should now be an Ipo saved to the objects you saved.

Now that we can save the output of the game engine, we can do cool things like a domino rally. Or we could make a ball jump over a shark, and then crash into a bunch of blocks. One interesting thing you can do is making an object follow an Ipo curve before letting the physics engine take over. I’ve found that if I start with anything other than the file I downloaded (recIpo.blend), Blender acts a little bit buggy. It likes to move objects around to places they have no business being. The rather inelegant way I’ve been fixing that is to just open the recIpo.blend file and erase everything but the empty before I start adding objects. Just for fun, here is a tutorial for the game engine: http://wiki.blender.org/index.php/BSoD/Introduction_to_the_Game_Engine. To get a feel for what you can manipulate in the game engine go to http://www.blender.org/documentation/pydoc_gameengine/PyDoc-Gameengine-2.34/index.html. Extra credit goes to whoever recreates Super Mario Brothers.