1 Developer Documentation For The Python API: 1.1 Modeling and Animation
1 Developer Documentation For The Python API: 1.1 Modeling and Animation
Blender uses a scripting language called Python for different purposes. At the
moment you can use Python in two ways:
If you use Blender as a modeling and animation tool1 you can use Python
to model a scene by programming how the scene should build itself or you
can write import and export scripts to handle other file formats describing
cameras, lights, etc.
In the game engine2 you can use Python to control the game flow by exe-
cuting scripts whenever a specified situation happens to occur.
There are other purposes but for the moment it’s enough to know that the
execution of a Python script is handled differently and that the known modules
are different for the two parts.
1
import Blender: If you write import Blender in one of the first lines
of your script you have to write Blender. in front of all global functions
or classes you use from this module. Even if you think this is a lot of typing
you will never forget where a function or class is located and I would prefer
this method to import the module.
All examples of this documentation assume that you use the first method. Af-
ter importing the module you can see the name space of the Blender module by
typing print dir(Blender). You will see a list of names in the name space
of the module. This names will be explained in one of the following chapters and
you will learn if a name stands for a function or if it is the name of a class you can
use. A class has it’s own name space of member functions and member variables.
You will learn how to use them as well.
if __name__ == "__main__":
printModuleInfo("Blender", "getCurrentScene")
Note that I did not write import Blender in one of the first lines. This
was done because I wanted to have a reusable script for printing module info.
Have a look at the last two lines. The last line is only executed if your scripts runs
standalone. This means that you didn’t import this script within another script. It
is always a good idea to have lines like this to test a module. If you import this
2
module only the function printModuleInfo will be in the name space of the
module. You could reuse this function by calling it with appropriate parameters.
In Blender the display settings are visible in the Display buttons (F10). If you
look at figure 1 you can see values for the following display settings:
3
currentFrame: At the top left corner of figure 1 you see the pressed button
for the Display buttons (F10). To the right you see a selection mechanism
for the current scene and the name of it. The next button to the right is the
current frame.
startFrame: The start frame can be seen in the bottom line: Sta: 1
endFrame: The end frame can be seen in the bottom line: End: 250
xResolution: The image width in pixels can be seen on the right side of
figure 1: SizeX: 320
yResolution: The image height in pixels can be seen on the right side of
figure 1: SizeY: 256
If you want to export an animation you will have to step through all the
frames and write the current scene for the current frame. The API gives you
the freedom to save all frames in one file3 or to use one file for each frame.
To inform Blender which frame you currently want to export use the function
Blender.setCurrentFrame(frame).
For most of the external renderers you have to write the camera settings be-
fore you write the scene. You can access the current camera in your current
scene by calling camobj = scene.getCurrentCamera(). Notice: This
call gives you access to an camera object. The settings which are individual
and unique to cameras are linked to the object and can be accessed by call-
ing camera = Blender.getCamera(camobj.data). Unfortunately it
is not possible to see this link in the OOPS (Object Oriented Programming System)
window. But for most of the other linked data you can see a gray rectangle for the
object itself and e.g. a brown rectangle for the linked mesh. See figure 2 for some
examples.
You can’t see which attributes an object has at one place in Blender. But there
are several places where you can find out about associated attributes of an instance
of the class Object: Object
matrix: Only the location, rotation, and size settings of a matrix are visible
in Blender4 if you press the NKEY in one of the 3D windows. A shear
matrix for example can not be created in Blender. But the Python API will
allow to do this in the future by manipulating the matrix directly.
3
Which can be done e.g. for RenderMan.
4
and can be manipulated there
4
Figure 2: The Object Oriented Programming System window
data: The data variable tells you the name of the linked data. So you can
decide about the type of an object by either checking it’s type variable or by
using one of the
5
You can have more than one material for one object.
5
– Blender.isCamera(name),
– Blender.isLamp(name), or
– Blender.isMesh(name)
functions.
ClSta: The clipping start determines where the camera clipping begins.
ClEnd: The clipping end determines where the camera clipping ends.
After exporting the camera settings most of the external renderers demand that
the lights are exported next. For some renderers the sequence does not matter but
for some renderers only the lights defined before the geometry will illuminate
it. Some renderers allow you to decide which geometry should be illuminated
by which lights. Nevertheless you need access to the light settings. This can
be achieved by checking for a light with Blender.isLamp(name) and using
a similar sequence as you used for a camera to get access to the object and the
associated data:
lampobj = Blender.getObject(name)
lamp = Blender.getLamp(lampobj.data)
At the moment the following light settings for an instance of the class Lamp Lamp
are available.
type: The type of a lamp can be: ”Lamp”, ”Spot”, ”Sun”, or ”Hemi”
mode: The mode indicates with a string of length 8 if a setting in the lamp
buttons (F4) is on (”1”) or off (”0”). The order is exactly the same as in
the lamp buttons (from top downwards): Quad, Sphere, Shadows, Halo,
Layer, Negative, OnlyShadow, and Square.
6
G: Green part of the lamp color.
SpoBl: Spotlight setting: Spot blend (falloff from full light intensity to
darkness).
For now you can only export mesh data. Which means in fact triangles and
quads. The triangles and quads are collected in instances of the class Mesh. The
sequence to get access to the mesh data is:
meshobj = Blender.getObject(name)
mesh = Blender.getMesh(meshobj.data)
It is not that easy to see what attributes are there for an instance of the class
Mesh. You can type print dir(mesh) but this will give you a list of member Mesh
variables as well as member functions. You will learn about this functions later.
In this section we are only interested in the member variables:
vertices: This holds a list of vertices for usage within Python. A face uses
the indices of this vertices. This allows to store the vertices efficient and to
share the same vertex between different triangles or quads.
normals: This holds a list of vertex normals which can be used for smooth
rendering. The number of elements in this list should be exactly the same
as in the list for the vertices.
colors: This holds a list of vertex colors. The list might be empty if no
colors are used. But if they are used the list should be exactly of the same
size as the list of vertices.
7
faces: This holds a list of faces. At the moment a face is a list with 6 entries
(integers). This might change in the future. The first 4 entries are indices to
describe the vertices for a triangle or a quad. The decision if a quad is used
or not is made by the fourth entry. If this is 0 then only the first 3 entries
are used for an triangle. The fifth entry tells if the triangle (or quad) should
be rendered as smooth (using vertex normals) or not. The last entry is the
index of the material used for this face.
texcoords: This holds a list of texture coordinates. The list might be empty
but if used the list should have exactly the same size as the list of faces.
The texture coordinates are stored for each face as a list of 4 sublists (for
triangles just ignore the fourth sublist). Each of this sublists has 2 entries
(u- and v- direction).
texture: This holds the name (with path) of the used texture (if any).
The last class for now is the class Material. You can access the material Material
settings with Blender.getMaterial(name). At the moment only a small
subset of the Blender material settings can be reached from within Python:
8
using a file selector can be seen if you press F1 or F2 to load or save a file in
Blender. If you look at figure 3 you see that it looks pretty much the same if you
call a file selector from within Python9 .
After importing the module with import GUI you can create an instance
of the class FileSelector with fs = GUI.FileSelector(). Nothing hap-
pens until you call fs.activate(callback, fs). When the file selector
is activated the control goes back to Blender. You can stop the file selection by
pressing ESC or continue browsing the file hierarchy as you would do to load a
Blender file. After selecting a file with the middle mouse button10 the file selector
is closed. But how can I get back into my Python code?
If you look at the call of the function activate(...) you will see that you
have to specify a callback function and optional you can give an argument to
this callback function when it is called. This means that you don’t have to specify
the second argument of the call fs.activate(callback, fs). I used this
argument to give the callback function access to the filename of the instance of
the class FileSelector:
def callback(fs):
filename = fs.filename
# whatever you want to do with the filename ...
9
Except the message: SELECT A FILE
10
Or by first selecting it with the left mouse button and then pressing ENTER.
9
The next thing you might want to do is to parse the file and read in the data.
It is wise to parse and read the complete file before you pass any data to Blender.
This part of your Python code can be reused by other scripts to read in the data.
You could write a conversion from one file format to another without using any
interaction with Blender.
At the moment only meshes are supported. For other data it should work very
similar but I will explain the technique only for meshes. The first thing you should
do is getting access to the current scene.
scene = Blender.getCurrentScene()
# this can be done for several meshes ...
mesh = Blender.Mesh("NAME")
object = Blender.Object("NAME")
mesh.enterEditMode()
# triangle
i1 = mesh.addVertex(x1, y1, z1, 0, 0, 0)
i2 = mesh.addVertex(x2, y2, z2, 0, 0, 0)
i3 = mesh.addVertex(x3, y3, z3, 0, 0, 0)
mesh.addFace(i1, i2, i3, 0, 0, 0)
# quad
i1 = mesh.addVertex(x1, y1, z1, 0, 0, 0)
i2 = mesh.addVertex(x2, y2, z2, 0, 0, 0)
i3 = mesh.addVertex(x3, y3, z3, 0, 0, 0)
i4 = mesh.addVertex(x4, y4, z4, 0, 0, 0)
mesh.addFace(i1, i2, i3, i4, 0, 0)
Blender.connect(object, mesh)
Blender.connect(scene, object)
mesh.leaveEditMode()
You can add all the data to one mesh or you might have criteria why you want
to store the data in several meshes. Anyway you will have to create an instance
of the class Object and the class Mesh. A Blender object or mesh has allways
a unique name. The name you give as an argument for the constructor is only a
proposal for the real name. Blender will check if this name is already used and
rename the object if necessary. This is why you can use the same name in the
constructor again and again. Then you add vertices and faces to the mesh. It does
not matter if you first add all vertices and after that create all faces or if you mix
the calls to mesh.addVertex(...) and mesh.addFace(...). Please re-
member to use the indices you get back from mesh.addVertex(...) for the
call of mesh.addFace(...).
The function mesh.addVertex(...) takes at least 6 arguments, followed
by three optional arguments. The first 3 values are used for the vertex coordinates,
10
the next 3 values for the vertex normal, and the last 3 (if used) for the vertex color.
The color information has not to be specified. The default values mean: Don’t
store any color information.
The function mesh.addFace(...) takes exactly 6 arguments. The first 4
entries are indices to describe the vertices for a triangle or a quad. The decision
if a quad is used or not is made by the 4th entry. If this is 0 then only the first 3
entries are used for an triangle. The 5th entry tells if the triangle (or quad) should
be rendered as ”smooth” (using vertex normals) or not. The last entry is the index
of the material used for this face.
Don’t forget to connect the object to the mesh and the scene to the object. The
call Blender.connect(...) can be used for both. Before you can add any
data to the mesh you have to call mesh.enterEditMode() and after inserting
all the data for this mesh you have to call mesh.leaveEditMode(). There
are only two functions left to explain:
11
By using only the first two indices and settings the other two to Zero.
12
E.g. a DXF file.
11