Blender 3D: Noob to Pro/Advanced Tutorials/Print version
From Wikibooks, the open-content textbooks collection
[edit] Table of Contents
[edit] Advanced Tutorials
[edit] Python Scripting
- Introduction
- Export scripts
- Import scripts
- Procedural object creation
- Scripts for modifying meshes
- Creating a GUI for your script
[edit] Advanced Animation
- Introduction
- Guided tour:
- Working example: Bob
- Working example: Piston, Rod and Crank
[edit] Advanced Tutorials
Author: Anthony Gomez (Extensor) Date: March 5, 2005
Short Description: RVK tutorial
- Letters in brackets ie:(z) mean there is addition information at the bottom of the page.
[edit] Introduction:
This tutorial is meant to stop all the RVK (Relative Vertex Keys) questions.
[edit] Window Layout:
Set the left half of the screen as 3D View. The other half is divided in two. The top is Action and the bottom is IPO (set to vertex display).
[edit] Setting your Neutral Pose
Make sure you are on the first frame (a). With the cursor over the 3D View, select the mesh you want to animate. (mesh in object mode) and press the I key. Select Mesh from the pop up menu then Relative Keys from the next pop up menu. A line will appear in the IPO view. This line is your neutral pose.
[edit] Setting up your additional Pose Lines
Now, figure out how many key frames you will need. If you want to move both eyebrows up and down then you will need 4 additional IPO lines.
Left Brow Up Left Brow Down Right Brow Up Right Brow Down
Press the up arrow (cursor key) to move to forward 10 frames. Press the I key while over the 3D View and select Mesh. Repeat until you see a total of 5 lines in the IPO window.
[edit] Set your Poses
Right click on the Neutral pose line in the IPO window. This sets the mesh to the neutral pose. Now Right click on the next line up in the IPO window. Enter edit mode in the 3D View and move the vertices as desired (in this case you will be moving verts to get the left Brow up pose). Press Tab to exit edit mode. Now right click your Neutral pose line in the IPO window. You will see your object in its neutral state. Right click the next line up and you should see the changes you just made to your object. Set up all your mesh poses following the above instructions.
[edit] Name your Poses
RIght click on the Key names in the Action window. Change the name and click OK.
[edit] Time to Animate (b)
Click on the arrow next to the Sliders text. This will give you access to the pose sliders. Move to frame 20 to start your action. Move the pose slider but release the mouse when set to 0. Now move 10 frames forward and move the same slider to 1.00 (maximum). Use this method to set up all your actions(c). Remember to add a 0 value frame to end the pose.(d).
[edit] Adjust your Slow in & Out
In the IPO View select from the menu to find the IPO curves. You can get back to the Pose lines by selecting KeyIPO from the same menu. Right click the spline you want to edit and press TAB to enter edit mode. Move the handles to adjust slow in/out.(e)
(a) In this case moving to a frame has nothing to do with animation. It is done so that your pose lines are seperate from each other. (b) Select your key frame marker and use the usual commands to move <g> and duplicate <d> them. (c) Be subtle by not pushing the slider all the way to 1.00. (d) Try overlaping your poses. (e) When setting slider values they can sometimes go into the negative value. This will give you weird results. Although sometimes they can make your animation more interesting. To fix this edit the IPO, select the point where the line dips below zero and press the V key. Do the same at the othe end of the curve if needed.
Warning! Blender has a limit to the number of verts you can use.
Click here to read the advanced animation tutorial guided tour.
[edit] Python Scripting
One of Blender's powerful features is its Python API. This allows you to interface with Blender through the Python programming language. The Python interface allows you to control almost all aspects of Blender, for example you can write import or export scripts for meshes and materials of various formats or create procedurally generated textures. You can also create complete animations procedurally and write scripts to modify existing scenes in any way you can think of. On top of all, you can easily create a user interface for your script, transforming it into a generally usable tool.
The relevant section of the Blender User's Manual is here.
Download Python Scripts from the Blender site here.
This forum on blenderartists.org discusses Python scripting.
Introduction
For a general introduction to python programming, see: http://en.wikibooks.org/wiki/Programming:Python
[edit] Introduction
Python is used in blender to write plugins as well as automate tasks. It is one of the easiest programming languages to learn.
[edit] Your first python script
Make a text window. Then type this script:
import Blender #gets all blender's functions a = Blender.Object.Get("Cube") #change the name of the object you want to get a.LocX = 2 #move the object's location-x to 2.
[edit] Excersizes
- Change the script that puts the object's location-x to 6
- Change the script that puts the object's location-y to 1
Export scripts
[edit] Introduction
Blender is not just useful to create complete animations, but it's also a great modeller. You can build your complete 3D scene in Blender, and then export it to a useful format. In fact, you can use it for much more, for example I was using it as a level editor for a freeware 2D game someone else made. There was a short deadline for the game to be finished, and 2 weeks before that deadline, there still was no level editor for it. It had a custom ASCII level format, consisting of lists of materials, vertices, triangles and objects. So, remembering the Blender Python exporters, I volunteered to write an export script for Blender, so it could be used as level editor. And it worked out very well, Blender can be completely used as level editor for that game now.
In this tutorial we'll learn how to write a simple Python export script for Blender. Without requiring previous Python knowledge, it will explain how to query the objects in your scene, and how to write them to a file. It will also demonstrate the usefulness of export scripts, by showing how you can process the data while exporting, so you can achieve things that would not work by using any other existing format.
So, open Blender (2.44 or greater), make sure the default scene is loaded, and let's begin..
[edit] Finding out about things in a scene
Before we can export something, we must know what to export. One way to get this information is the Outliner window (SHIFT-F9). It will list all the things currently known to Blender. Now, we want the same information from a script. Open the scripts window (green snake symbol). Click on the menu titled Scripts, and go to Scripts → System → Interactive Python Console.
Now, you are ready for the big moment, you are about to execute the first Blender scripting command. Type this and hit RETURN (or you could type into the scripts window import Blender on the topmost line, then these lines below it, precede all the 'dir(x)' lines with print and choose file->Execute):
list(bpy.data.objects)
As a result, you should see this:
[[Object "Camera"], [Object "Cube"], [Object "Lamp"]]
Now, what just happened? The line "list(bpy.data.objects)" consists of three words, separated by two dots, The dots just separate different things. The first, "bpy", means to use a function from the bpy module. data is a sub-module of Blender. And finally objects is an iterator of bpy.data. The list() function is used to loop through all data in bpy.data.objects and return that as a list of all available objects. In our case, this is a Camera, a Cube, and a Lamp.
To get more information about an object, you can use the object name as a key in bpy.data.objects, and assign it to a variable, like this:
camera = bpy.data.objects["Camera"] cube = bpy.data.objects["Cube"] lamp = bpy.data.objects["Lamp"]
Be sure to import the bpy library first.
import bpy
We just assigned the three objects to three variables, camera, cube and lamp. To see the contents of a variable, type just its name:
cube [Object "Cube"]
camera [Object "Camera"]
lamp [Object "Lamp"]
Sometimes it's useful to use Python's dir() function to get more information about an object. For example
dir(cube)
will write the names of all functions and properties of the object. Quite a lot. But don't worry, soon you will know how to use all of them. You also may want to find out the type of something, which you can do like this:
type(cube)
In this case, just typing "cube" already displays the type, but from within an actual script, you would use type(). Something else which can be useful is viewing the documentation of Python objects. To do so, use the help() function on a variable or object.
help(bpy.data.objects)
This will print the documentation of the bpy.data.objects function we used. Of course, an easier way to view the documentation is the online HTML help. Click on Help->Python Scripting Reference. Hopefully now your browser opens and displays the online documentation of the Blender Python API. If not, you should find it also here:
http://www.blender.org/documentation/244PythonDoc/index.html
In the documentation, click on bpy, then on data and you can see more examples. Using the documentation will get absolutely vital whenever you need to do something in a script not covered in a tutorial. And you will need to do so, else you wouldn't want to learn scripting at all.
Another resource you will need, depending on how far you will go with scripting, is the Python reference:
For this tutorial, maybe read the "Tutorial" section in the python docs, but you will understand everything without doing so.
Now, let's try to find out more about our cube. Type:
cube.type
It will tell us that the cube really is a Mesh object in Blender. Look up "type" in the online docs. Since the variable cube holds an Object, and "type" is an attribute of that Object, click on Object. There you find its "type".
Now that we know that the cube is a mesh, let's find out more about the mesh.
mesh = cube.getData(mesh=1)
Every Blender object has data assigned to it, depending on the type. In the case of a mesh, the data are of type Mesh. In the documentation, go to the top again, and look for the Mesh module. It will contain documentation for the Mesh type. You can also try
dir(mesh)
to get an idea about the available functions and properties. Try these:
dir(mesh.verts) dir(mesh.faces)
The first line will list the 8 vertices of the cube's mesh. The second line will list its 6 faces.
To get a member out of a list, you specify the index in square brackets, starting with 0. So:
v = mesh.verts[0]
This will assign the first vertex of the cube to the variable v. By now, you already know how to use dir() to get a list of possibly interesting things in v, find out about its type with type(), and where to look for the API documentation. It is in the module Blender/Mesh, when you click one "MVert" under "Classes".
v.co
This will display the 3D coordinates of the first vertex. Now, what if we want to know the coordinates of all vertices? We could of course assign them all to a variable, but the real way to do this is using a looping constructs. There are numerous ways to do this, but one simple way looks like this:
for v in mesh.verts: print v.co
The for variable in list: construct assigns each element of the list to the variable in turn, and then executes the commands after the colon with the variable having the value of one particular list element. In a real script, you will have much more than a single command after the colon - so you would write them in the following lines.
By now, you should know enough to try yourself at a real script in the next section.
[edit] Creating a script
You can write scripts either in an external text editor, or in Blender's built in text editor. The built in text editor can be hard to use if it doesn't have the standard shortcuts of your preferred text editor. To copy text to and from your clipboard in blender, you have to use CTR+SHIFT-C and CTR+SHIFT+V, otherwise it uses an internal clipboard. Otherwise, it is quite usable. You reach it over the window selector, or by pressing SHIFT+F10 (SHIFT+F11 for Blender 2.41 and up). If you want, you can enable line numbers and syntax coloring with the buttons at the bottom. Create a new script with File → New, paste the code below into it, and save it. Or alternatively, paste the code below into a file, and open that file with File → Open in Blender. As name choose something with the extension .py, for example wikibooks.py. Put it into Blender's user scripts path.
For different operating systems this is:
- Linux: ~/.blender/scripts
- Windows XP: C:\Program Files\Blender Foundation\Blender\.blender\scripts
- Windows Vista: C:\Users\USERNAME\AppData\Roaming\Blender Foundation\Blender\.blender\scripts
- Mac OS X:
- Under Mac OSX the path is actually hidden in the blender.app so to know the path you would have to know that the script folder is actually hidden in the blender.app itself. Assuming that Blender is in the applications directory the path would be "/Applications/blender-2.37a-OSX-10.3-powerpc/blender.app/Contents/MacOS/.blender/scripts" If you try to open the .app contents from the finder you will notice that .blender section of the path is not visible, while blender will still be able to navigate to this folder. To see this folder from the OSX terminal use the ls -a command (lists all folders/files even hidden) in the MacOS folder of the listed path. It is probably a good idea to create an alias to the scripts folder in the "/Applications/blender-2.37a-OSX-10.3-powerpc" folder so that scripts can be easily manipulated through the finder. I know that its confusing that Blender should have its script folder buried inside the app but it is necessary to keep the app portable and not require an install.
- A safer approach than the one above consists in keeping your scripts somewhere in your home folder: with this scheme, there is no risk of deleting your scripts when you upgrade your blender application, as they are not contained within its folder. A method that follows this principle is as follows: create a folder that will contain your scripts (or some of them) inside your own home directory; then, instead of putting your files directly in the .../.blender/scripts/ folder discussed above, simply add a link to your script directory in the .../.blender/scripts/ folder (for instance with the "ln -s" Unix command, or by doing "open /Applications/blender-2.37a-OSX-10.3-powerpc/blender.app/Contents/MacOS/.blender/scripts/" [adapted to your version of blender] and then creating a link through the Finder, with File->Make Alias). Blender will now find all the scripts that you put in your home directory: it will follow the link you created in its .../.blender/scripts/ folder and go to the corresponding folder in your own directory, and find all the python scripts you put there.
#!BPY
"""
Name: 'Wikibooks'
Blender: 244
Group: 'Export'
Tooltip: 'Wikibooks sample exporter'
"""
import Blender
import bpy
def write(filename):
out = file(filename, "w")
sce= bpy.data.scenes.active
for ob in sce.objects:
out.write(ob.type + ": " + ob.name + "\n")
Blender.Window.FileSelector(write, "Export")
Now, go back into the scripts window, and in its menu, click Scripts → Update Menus. If you saved it into the right path, from now on there should be an entry "Wikibooks" in the File → Export menu. Try exporting any scene with it. It should open the file chooser dialog, and after you select a file and press the "Export" button, write a list of all objects in the scene into it. There will be one object per line, with the type, followed by a colon and the name.
How does it work? If you look at the script, you probably already know. But just in case, let's look at the script line by line. The first line contains this:
#!BPY
It tells Blender that this is a Blender script, and therefore it will consider it when scanning for scripts. Next simply follows a string, enclosed in triple quotation marks, so it can span multiple lines.
""" Name: 'Wikibooks' Blender: 244 Group: 'Export' Tooltip: 'Wikibooks sample exporter' """
It contains four items, which Blender uses to place the script into its menus. The name, group (menu location), and tooltip, all enclosed in single quotes. And the Blender version this is for.
import Blender import bpy
Remember how we said all functions from the bpy module start with "Blender."? In the interactive shell, we could simply use them, but in a python script, all used modules must be declared with an import statement (if you want to directly use functions from the Blender module in a script, you can simply replace the import statement above with "from Blender import *": no "Blender." prefix is necessary anymore; however, this slows down the loading of your script). So the above simply allows us to use the functions from the Blender module in our script.
the bpy module is new and will replace Blender for data access.
def write(filename):
This defines a function in Python. The syntax is def name(parameters):. In our case, the name is "write", and we have one parameter, called "filename".
out = file(filename, "w")
Here we open a file for writing (the "w"), with the name passed to the function (filename). The python function "file" will open the file, and return a reference to it, which we store in the variable "out".
sce= bpy.data.scenes.active
for ob in sce.objects:
out.write(ob.type + ": " + ob.name + "\n")
These three lines are our real export script. You already know what the first line does - first we get the current scene, then get a list of all objects in that scene, the for loop is assigning each one in turn to the variable "ob". The second line writes to the file - first the type of the object, then the string ": ", then the name of the object, and finally a newline.
Blender.Window.FileSelector(write, "Export")
This is where execution of the script starts. It is simply a call of a Blender function (look it up in the API docs), which opens the file selector. It will display an "Export" button, and when the user clicks it, our function "write" from above gets called and is passed the selected filename.
This script isn't really very useful yet, but it shows the basics. You should now be able to e.g. also list all the materials in the scene. (Hint: They are just like objects, try to find them in the API docs.)
In the next section, we will learn how to export additional information about objects to our text file.
[edit] Exporting a Mesh
Our export script lists the type and name of every object, but that's not very useful yet. If we want to load the exported data in another application, we need more. Let's try to export a mesh object in the OBJ format.
The example below is a cube in the OBJ file format.
v 1.000000 1.000000 -1.000000 v 1.000000 -1.000000 -1.000000 v -1.000000 -1.000000 -1.000000 v -1.000000 1.000000 -1.000000 v 1.000001 1.000000 1.000000 v 0.999999 -1.000000 1.000000 v -1.000000 -1.000000 1.000000 v -1.000000 1.000000 1.000000 f 1 2 3 4 f 5 8 7 6 f 1 5 6 2 f 2 6 7 3 f 3 7 8 4 f 5 1 4 8
Here is a simple obj export script that exports a selected mesh object, used to export the OBJ file above.
import Blender
import bpy
def write_obj(filepath):
out = file(filepath, 'w')
sce = bpy.data.scenes.active
ob = sce.objects.active
mesh = ob.getData(mesh=1)
for vert in mesh.verts:
out.write( 'v %f %f %f\n' % (vert.co.x, vert.co.y, vert.co.z) )
for face in mesh.faces:
out.write('f')
for vert in face.v:
out.write( ' %i' % (vert.index + 1) )
out.write('\n')
out.close()
Blender.Window.FileSelector(write_obj, "Export")
This script will export an OBJ file that can be read by many applications. Let's look at whats going on.
sce = bpy.data.scenes.active ob = sce.objects.active
Here we are getting the object you last selected in the current scene. This will raise an error if there are no selected objects, but its an easy way to test a new exporter.
mesh = ob.getData(mesh=1)
This gets the objects linked datablock. At the moment we dont know its a mesh, another case where error checking would need to be added.
for vert in mesh.verts: out.write( 'v %f %f %f\n' % (vert.co.x, vert.co.y, vert.co.z) )
Here we write a line for every vertex, using string formatting to replace the "%f" on the left, with the 3 values on the right.
for face in mesh.faces:
out.write('f')
for vert in face.v:
out.write( ' %i' % (vert.index + 1) )
out.write('\n')
In the OBJ format each face references a number of vertex indices. For every face we have a line starting with "f", then loop through the vertices in the face. Just as mesh.verts are a list of all the the vertices in a mesh, face.v is a list of verts in the face limited to 4 vertices maximum. (where mesh and face are arbitrary variable names assigned to Mesh and MFace objects) Every vertex writes its index on that same line with 1 added. This is because with the OBJ file format the first vertex is indexed at 1, whereas with Python and Blender the first item in a list is 0.
A new line is written so the next face will start on a new line. - in python '\n' represents a new line when written to a file.
Import scripts
[edit] Introduction
Importing objects into Blender is not that different from exporting. However, there are a few additional things to take care of. Firstly, all references to "export" in the header should be changed to "import". Secondly, instead of simply writing out data that Blender provides to us, we are responsible for giving data to Blender and ensuring that it is properly formatted. Although Blender is flexible, allowing us to ignore things like vertex indices, we do need to be careful that we do things in a sensible order.
Additionally, there is a bit of housekeeping to deal with. We should be in edit mode while modifying the mesh data. We also need to link up our newly created data to the scene, after it has been properly constructed, so that Blender can see it and maintain it. This makes it visible to the user, as well as ensuring that it gets saved along with the scene.
[edit] Importing a Mesh
Here is a simple script that can import an OBJ file created by the export script.
import Blender
def import_obj(path):
Blender.Window.WaitCursor(1)
name = path.split('\\')[-1].split('/')[-1]
mesh = Blender.NMesh.New( name ) # create a new mesh
# parse the file
file = open(path, 'r')
for line in file.readlines():
words = line.split()
if len(words) == 0 or words[0].startswith('#'):
pass
elif words[0] == 'v':
x, y, z = float(words[1]), float(words[2]), float(words[3])
mesh.verts.append(Blender.NMesh.Vert(x, y, z))
elif words[0] == 'f':
faceVertList = []
for faceIdx in words[1:]:
faceVert = mesh.verts[int(faceIdx)-1]
faceVertList.append(faceVert)
newFace = Blender.NMesh.Face(faceVertList)
mesh.addFace(newFace)
# link the mesh to a new object
ob = Blender.Object.New('Mesh', name) # Mesh must be spelled just this--it is a specific type
ob.link(mesh) # tell the object to use the mesh we just made
scn = Blender.Scene.GetCurrent()
for o in scn.getChildren():
o.sel = 0
scn.link(ob) # link the object to the current scene
ob.sel= 1
ob.Layers = scn.Layers
Blender.Window.WaitCursor(0)
Blender.Window.RedrawAll()
Blender.Window.FileSelector(import_obj, 'Import')
This will load an OBJ file into Blender, creating a new mesh object. Let's take a look at the more interesting portions.
Blender.Window.WaitCursor(1)
Turn on the wait cursor so the user knows the computer is importing.
name = path.split('\\')[-1].split('/')[-1]
mesh = Blender.NMesh.New( name ) # create a new mesh
Here, we create a new mesh datablock. The name is made from the path only with the filename.
ob = Blender.Object.New('Mesh', name)
ob.link(mesh)
Next, we create a new object and link it to the mesh. This instantiates the mesh.
scn = Blender.Scene.GetCurrent() scn.link(ob) # link the object to the current scene ob.sel= 1 ob.Layers = scn.Layers
Finally, we attach the new object to the current scene, making it accessible to the user and ensuring that it will be saved along with the scene. We also select the new object so that the user can easily modify it after import. Copying the scenes layers ensures that the object will occupy the scenes current view layers.
Blender.Window.WaitCursor(0) Blender.Window.RedrawAll()
Now the finishing touches. We turn off the wait cursor. We also redraw the 3D window to ensure that the new object is initially visible. If we didn't do this, the object might not appear until the user changes the viewpoint or forces a redraw in some other way.
Procedural object creation
[edit] Generating Elements with Python
A quick reference for commands to create elements through a Python script instead of manually. All of these scripts require the following code at the start:
import Blender from Blender import NMesh
We will also, for the tutorial, be working with an object, known as obj. To work with obj, after the import sequence, add the line
obj = NMesh.GetRaw()
If the name in quotes of an existing object is entered into the parentheses instead of left blank, it will use that object's mesh as a template.
[edit] Vertices
The basic structure of the vertex generation command is:
v=NMesh.Vert(x.x,y.y,z.z)
Where v is the name of the vertex and x.x, y.y, and z.z are the X, Y, and Z coordinates of v, which must end in a decimal place.
For example, here is how one might create the three vertices of a triangle and attach them to obj's mesh:
v=NMesh.Vert(1.0,0.0,0.0) obj.verts.append(v) v=NMesh.Vert(0.0,1.0,0.0) obj.verts.append(v) v=NMesh.Vert(0.0,0.0,1.0) obj.verts.append(v)
Or, for vertices not created under the same name (v), it can be written thusly:
a=NMesh.Vert(1.0,0.0,0.0) b=NMesh.Vert(0.0,1.0,0.0) c=NMesh.Vert(0.0,0.0,1.0) obj.verts.append(a) obj.verts.append(b) obj.verts.append(c)
[edit] Faces
The basic structure of the face generation command is:
f=NMesh.Face()
Where f is the name of a given face to be created.
To append vertices (maximum 4) to a face, use the line
f.v.append(obj.verts[x ])
Where x is the order of the vertex around the perimeter (beginning with 0).
Let us mix the previous vertex assigning conventions in with our example of a creation and appendage of a face to more efficiently demonstrate the degree of flexibility had by the command. This code adds a square to Obj.
v=NMesh.Vert(1.0,1.0,0.0) obj.verts.append(v) v=NMesh.Vert(1.0,-1.0,0.0) obj.verts.append(v) a=NMesh.Vert(-1.0,-1.0,0.0) b=NMesh.Vert(-1.0,1.0,0.0) obj.verts.append(a) obj.verts.append(b) f.v.append(obj.verts[0 ]) f.v.append(obj.verts[1 ]) f.v.append(obj.verts[2 ]) f.v.append(obj.verts[3 ]) obj.faces.append(f)
[edit] Objects
All of this code hasn't so much modified or created a mesh. It's more like a blueprint for the changes. To actually construct the new object, insert the following line of code at the end of the blueprint:
NMesh.PutRaw(obj, "Square", 1)
The first argument is the name of the mesh to be used to create "square", the second argument, which is the name of the object. This can be anything you like. The third argument is the renormalization boolean. When set to 1 (true), this forces Blender to recalculate the mesh's normals before generating the object in 3D space. Finally, use this piece of code after all of your object creation and other visual modification scripts to tell Blender to refresh the screen:
Blender.Redraw()
[edit] Iterative Loops
Possibly the most important advantage of procedural object creation is the work it saves you when creating something with any sort of replicable quality. Here we will give the basic format of a loop in Python, then show some example scripts you can build on. The basic loop is thus:
for i in range(a,b,c): Four (more) spaces indentation marking all code contained in the loop Same indententation level as "for i in range" line to exit loop
Where i is the iteration number, a is the start value of the iterations, b is the number of times the loop is run, and c is the increment. Entering in c is not necessary if the increment is 1. If a is 0, b is 100, and c is 1, it will run the iterative loop 100 times, starting with the 1st iteration, where i=0. If c is 2, it will run 100 times adding two to i each loop, so that for iteration 1 i=, iteration 2 i=2, and iteration 100 i=200. ɪ naturally equals 0, but it is always good to define i as 0 by placing the line "i=0" (no quotes) before the loop code. If you nest loops, you can perform such tasks as placing a row of ten vertices in with one of the coordinates set to i, so that when i makes another iteration the nested loop makes another row of ten vertices in the new position given by i.
A loop that produces a vertex at the origin, (1,1,1), and (2,2,2)
for i in range(0,3,1): v=NMesh.Vert(i,i,i) obj.verts.append(v)
A square-producing loop:
for i in range(0,2,1): for j in range(0,2,1): v=NMesh.Vert(j,0,i) obj.verts.append(v)
A two-square-producing loop:
for i in range(0,2,1): for j in range(0,2,1) for k in range(0,2,1) v=NMesh.Vert(j,k,i) obj.verts.append(v)
[edit] Links
- Blender tools:
- Python:
- Other:
- http://www.devx.com/Intel/Article/20333/2046 , "Procedural 3D Content Generation, Part 2"
- ModelingCloudsShape --antont, Sun, 20 Mar 2005 03:33:07 +0200 reply http://www-evasion.imag.fr/Publications/2004/BN04/
Scripts for modifying meshes
(to be written)
Also see saltshaker a basic but functional python script for blender, page includes details of how it was made.
http://jmsoler.free.fr/didacticiel/blender/tutor/python_script01_en.htm is a good one for learning about mesh creation.
Creating a GUI for your script
It is very easy to create a GUI for your script, and that way make it easy to change aspects of it for everyone.
The command to create a Graphical User Interface (GUI) is:
Blender.Draw.Register(draw,event,button)
This command registers the functions:
- draw - to draw the GUI
- event - to action mouse and key presses
- button - to action GUI button presses
However, this command will NOT work by itself !!!. You first need to define these 3 functions.
First we will import Blender's library of built in functions:
import Blender
Next, we will define the draw function.
def draw():
Inside this function we will draw the GUI. Here is an example of a drawing function we can use. It will clear the current window.
Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT)
And the next command will draw a button. Note that the first number in the command, '1' identifies the button as button 1. We will refer to this button later.
Blender.Draw.Toggle("Clear origin",1,10,20,100,20,0,"Tooltip")
Next, we will define the event function. The code of a key pressed on the keyboard is passed into the function as the variable evt.
def event(evt,val):
Now we will test to see if the escape key is pressed:
if evt == Blender.Draw.ESCKEY:
If it is pressed, exit the script, and return from the function:
Blender.Draw.Exit() return
Next, we will define the button function. This function will perform an action if the button is pressed.
def button(evt):
Now test the variable evt which holds the button number that we previously identified.
if evt == 1:
If it is pressed, we will move the selected object in the 3d window back to the centre and redraw the screen:
Blender.Scene.GetCurrent().getActiveObject().loc = (0,0,0) Blender.Window.Redraw()
Lastly, we can create the Graphical User Interface by typing the command:
Blender.Draw.Register(draw,event,button)
That's it !!! To enter the script yourself, type the following into the Text Editor window in Blender, and then press alt p to execute the script. Here's the entire script. Everything after the hash # is a comment and can be left out.
import Blender # This will import the library of blender functions we will use def draw(): # Define the draw function (which draws your GUI). Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT) # This clears the window # Add here drawing commands to draw your GUI, for example: Blender.Draw.Toggle("Clear origin",1,10,20,100,20,0,"Tooltip") # The line above will draw a toggle button. # Note the first number, '1' means this is button number 1 def event(evt,val): # Define mouse and keyboard press events if evt == Blender.Draw.ESCKEY: # Example if esc key pressed Blender.Draw.Exit() # then exit script return # return from the function def button(evt): # Define what to do if a button is pressed, for example: if evt == 1: # If button '1' is pressed, set active object to centre: Blender.Scene.GetCurrent().getActiveObject().loc = (0,0,0) Blender.Window.Redraw() # This will redraw the 3d window. # You can now run the Graphical User Interface by typing the command: Blender.Draw.Register(draw,event,button) # End of script
Noob Note: When I tried to run that script it came up with an error: Attribute Error: 'Scene' object has no attribute 'getActiveObject'. I changed "Blender.Scene.GetCurrent().getActiveObject().loc = (0,0,0)" to "Blender.Scene.GetCurrent().active.objects().loc = (0,0,0)" and it worked.
[edit] Advanced Animation
This section will show you the Animation system as it is in Blender 2.4. Most of the features will be explained and some tutorials will follow. I assume the user has a good understanding of Blender here.
This text is based on a presentation I did at the Montreal Blender Conference. I hope you'll find it useful and instructive.
Gabriel Beloin aka --Gabio 23:59, 31 October 2005 (UTC)
If you wish to discuss it further: Visit us at BlenderArtists.org: Animation Workshop 2
[edit] Index
- Advanced Animation
Introduction
Welcome to the wonderful yet complex world of computer animation! Through these pages I will try to show you everything old and new about the new animation system in Blender 2.4. But, before we get started, there are some basic notions about datablocks you should know. Animation in Blender is based on the fact that you have something moving in a Blender scene. For example, a ball bouncing on a floor plane:
-So you have a scene datablock, which holds some info about the scene itself, as you can see in the Render button window (F10KEY). -You populate this scene with various objects (which in this case refers to containers for data, not the actual mesh data that shapes the object itself). The only goal of an object is to hold the whereabouts of the data you want to see in your scene. It also holds the object instance's properties such as "does it have soft body or particle options, and do we draw its name?". Most of the info on an object can be seen in the Object Window (F7KEY).
An object links to all of the data you can see in a 3D view such as mesh, curves, nurbs, lattices, armatures, metadata, the empty property, text, camera and lamps.
So the ball you just added to the scene is in fact a mesh, linked to an object that is in turn linked to the current scene.
Now there are also data blocks you can't see in 3D view, such as material, texture, Ipo, action and image. Instead, you have a special window in which to edit them. This is the idea behind the Blender interface, wherein each data block has a window for you to edit the data.
So back to this bouncing ball: It's also moving across the plane! So an ""Ipo"" data block is linked to the object, telling it where in space the object will be at each frame of the animation. This Ipo is editable in the Ipo window when selecting the ball in 3D view. In Blender, the work you are performing is always on the currently active (selected) object and data.
Looking at the OOPS (object oriented programming system) view (or SHIFT-F9KEY), we can get a good idea of the internal data structure: 
Again, you are working in the scene "Scene", with an object "Sphere" linked to the mesh data block "Sphere" and the Ipo datablock "ObIpo". Why is that important? Because from there, you can start playing with the datablocks, linking them all around your projects to reuse old work. For example you can create more than one Ipo, and use the one you want, or tell more than one object to use the same Ipo, or to use the same object in more than one Scene.
Most of the linking job can be done in the Edit button window (F9KEY). Where you can tell an object to use another mesh's data block for Ipo, material, texture or image. There is always a little dropdown menu button for you to select an already-existing data block.
Now, when it comes to animation, you have to understand the way Blender handles data very well, because using Blender is always a matter of plugging data blocks together when working with Ipos, actions and NLA objects.
Guided tour:
Here I'll show you all the stuff you need to know about the interface when animating. Where is it? How does it work? Why use it?
We are going to talk about:
Armature Object
The Armature Object in itself is a tool for the animator to move an object or group of vertices in a reliable way. An armature is made of bones, which can be parented to each other, or connected to each other. It was built with the idea of a skeleton in mind.
You can add it using the SPACEKEY in 3Dview and selecting Armature. You'll then enter into editmode where you can add or move bones to build your default rig. An armature has 3 states. You can switch using the dropdown menu in the header of the 3Dview or use TABKEY to switch between Editmode <-> [Objectmode|Posemode] and CTRL-TABKEY to switch between Objectmode <-->Posemode:
- Object Mode: Your armature is like any other Object, you can move it around the scene, scale it, rotate it and edit options in the button window.
- Edit Mode: Your armature is in what we call rest position, you can modify the bones it contains.
- Pose Mode: Your armature is ready to be animated, each bone can be moved, scaled or rotated, constraints get applied, you can pose your character and animate the bones' behavior over time.
Take note that Pose mode is now a state of the armature you can switch on/off using CTRL-TABKEY. So when in Pose, you are still in object mode (you can select another object, contrary to the editmode)
Note: The following 3 pages of this tutorial contain screenshots and discuss techniques that are only available in Blender 2.40a and later. Refer to the Blender 2.40a release notes on Armature draw types and Armature envelopes.
Armature Object in Object Mode
[edit] The Armature Object
Armature Object is like any other object type:
- It has a center, a position, a rotation and a scale factor.
- It can be edited.
- It can be linked to other scenes, and the same armature data can be reused on multiple objects.
- All animation you do in object mode is only working on the object, not the armature's contents like bones.
Try it now: add an armature to your scene: SPACEKEY --> Add --> Armature. 
When you add a new armature, you'll enter editmode automatically. To switch between modes, use the TABKEY or the dropdown menu in the Header of the 3Dview window:

[edit] The Edit Panel When in Object Mode
This is how the edit panel looks after you have added a new armature and switched to object mode (TABKEY):

- Link and Materials panel:
- The AR: field let you rename your armature Datablock. The dropdown is a quick way to select which Armature datablock you want to connect to this armature. You can keep more than one version for the same character. Useful when you have a special move to achieve in a shot, you can turn on an armature for a special purpose.
- The F button is an option to assign a Fake user to the Armature. Again if you have more than one armature for your character, it's a good idea to turn the Fake on, because if your armature datablock is not used (linked) it's not going to be saved in your .blend files. You can always do batch Fake-assignment of armatures by opening the Datablock browser (SHIFT-F4KEY), go in Armature datablock, select all the armatures you want to keep, and Press the FKEY.
- The OB: field is just to Rename your armature Object to something more cool and useful than Armature... Armature.001...
- Armature panel:
- Editing Options:
- X-Axis Mirror Edit: Not really useful now, it's more of an editmode option. This feature tells Blender you want to replicate all of your bones on one part of the Armature to the other. It's a clean way to just do half the job ;). The axis of mirroring is X so left<-->right in frontview (NUMPAD_1KEY) and the center is the center of the armature object. We will see this feature in detail in the next page.
- X-Ray: This option will let you see the armature through anything in the scene, solid or not. It's useful to see where your bones are in your character so you can select them.
- Automatic IK is a Posemode option. It lets you pose a chain of bones as if the bone you were holding was an ik target. More info in Posemode page.
- Display Options: These options give you the chance to visualise your bones in various ways. Also note that there is some specific options and features regarding the display mode you're in.
- Octahedron: This is the default view. Nothing exciting except you have a good idea of the rolling of the bones.

- Stick: This display mode is really useful when you have a lot of bones in your view. It lets you "unclutter" the screen a bit. It draws the bones as tiny sticks.

- B-Bones: It's more a feature than a display mode. This is only useful to visualise the effect you get when you activate the B-bones (Bezier-Bones). Each bone acts like a curve handle and lets you get extremely curvy poses. This will be exposed in the following pages.

- Envelope: Again it's more a feature than a display mode. But in this case the visualisation will be useful to tweak your rig later. Envelope lets you easily tell which part of your character this bone will animate and it's visually possible to change the zone of influence exclusively in this display mode. The zone is only visible in Editmode or Posemode though.

- Draw Axes: To draw the axes on each bone of the armature when you are in Editmode or Posemode. Useful when you want to know where you are and which axis to use in a constraint for example. Mental note: Y is up, Z is depth and X is side, contrary to object for which Z is up, Y is depth and X is side.

- Draw names: This lets you see names of bones whatever the mode you are in. It's useful again to edit your armature, create parent dependencies or add constraints.

- Ghost: This option lets you see a ghost of the armature in frames behind and over the current time. This is only working when you have an action linked to the armature, as we will see later.
- Step (Armature_button_obj.jpg needs update): This option lets you choose the frames interval between ghost instances.
- Octahedron: This is the default view. Nothing exciting except you have a good idea of the rolling of the bones.
- Deform options:
- Vertex Groups & Envelope: These two toggles let you choose if you want the armature to deform your character using the Vertex Groups and/or the Envelopes. We will see that later.
- Rest position: This will bring the character back to factory default (item as Editmode), and no actions will be applied to the armature so you can easily edit it in the middle of an animation.
- Delay Deform: This was useful before as the old system was very slow. What it does is when you do a manipulation to the rig, it waits until you finish to update the view. Can still be useful though.
- Editing Options:
[edit] Extra Practice
This YouTube tutorial might also help: Link
Armature Object in Edit Mode
Now you've got your armature, but it's not much use until you add some more bones to it. Think about your body for a moment -- you've got this thing you call a 'skeleton', which for our purposes correspondings more or less to an armature object. Your skeleton consists of a number of bones (about 206, to be precise), but generally these are not independent from each other. If you move your femur (the bit of your leg between your pelvis and your knee) then conveniently the rest of your leg moves with it. In that example, the tibia/fibula would probably be counted as one bone, with the femur as their 'parent' bone. In this way, you build up a hierarchy of bones, making animation much simpler.
Editing an Armature Object gives you the chance to add, move or connect bones together. Whilst in edit mode, you will see all of the bones within the currently selected Armature.
When you create a new armature in Object mode a single bone will automatically be created for you, centered at the cursor position. Blender will then switch straight to Edit mode to allow you to add further bones. At this point we're just defining the default 'rest' position of the bones and specifying how they connect together -- you'll have to wait until the next chapter to find out how to create specific poses.
[edit] Now the basics about bones
Having created and selected an armature in Object mode, you can add and modify the bones in this armature by switching to Edit mode.
- You can add a new bone at cursor position by pressing SPACEKEY in the 3DView --> Add --> Bone.
- A bone has two ends: a root (the lower part) and a tip (the upper part). You can select and move the tip or the root independently with RMB, or you can select the entire bone by clicking on its body.
- You can extrude a new bone from the selection using EKEY. This will create a bone connected to the original one, meaning the Root of the new bone will follow the Tip of the original one. You can also CTRL-LMB to extrude a new bone. It will extrude to where you clicked.
- Alternatively, you can connect two existing bones by selecting them one after the other and pressing CTRL-PKEY. You can then choose either 'Connected' (the child bone - the one you selected first - will automatically be moved so that it touches the parent) or 'Keep offset'.
- You can use SHIFT-DKEY to duplicate a bone
- Using the WKEY menu, You can subdivide your bone or flip the name of the bone between Left-Right (See Naming convention below).
- You can delete the bone with XKEY
- You can select a chain of bones (connected together) using LKEY, when you hover your mouse over a bone.
[edit] The edit panel
- Armature Bones Panel
- BO: this field lets you rename your bone.
- "Child of" Dropdown: lets you choose which bone will be the parent of this bone. If a parent is selected, there will be a small button labelled "con", meaning connected. Setting the parent defines the relationship between your bones. When one bone has another as its parent, it will do everything the parent does, such as rotate, move and scale. A dotted line between the parent and child will appear. If you select Connected, the Root of the Children will go stick to the tip of the parent, giving you a chain of bones like the 2 bones in your arm.
- Segm: If you set this value to something greater than 1, it will cut your bone into several little segments and deform them on a bezier curve - referred to as a 'B-Bone'. You need to create a chain of bones to really show off this feature though. In the example below, the image on the right has 1 segment, and the one on the left has 3 segments each (these are shown in Object mode to show the effect more clearly):
- Dist: This is the area of influence of the bone. It can be visualised using the Envelope display mode. We generally don't touch this field as there is an easier and faster way to change this option. Turn Envelope on and select a bone. Then using ALT-S, you can scale the zone of influence. This has the advantage that you can do it on multiple bones simultaneously, and it works in both editmode and posemode:
- Weight: This specifies how strongly this bone will influence the geometry around it, relative to the other bones. If two bones crossing each other, both with envelope influence, have the same weight (like 1:1) they will influence the surrounding geometry equally. But if you set one to 0.5, the geometry will be affected more significantly by the other one, with weight 1. For example, in this image, 2 bones using envelope influence try to move the same geometry. The 2 on the left have the same weight, you can see the geometry didn't move. On the right, one of the bones has 0.5 so the bone with weight 1 is winning the tug-of-war!:
- Hinge: This tells the bone to remain motionless in a chain. It doesn't copy the rotation and scale of the parent. Useful for mechanical rig I would say, as you can animate the rotation of the hinge bone without having to correct it because the parent rotated:
- Deform: This lets you say if you want the bone to deform the geometry at all. Switching it off is like setting the weight to 0, except it's faster this way. Useful when using a bone as a target or a controller, i.e. a bone you just want to use to control other bones, but not the geometry itself.
- Mult: to deform geometry you can use vertex group and/or Envelope. The ability to mix both of these methods is handy for using one to tweak the other. For example, you might use envelope everywhere but tweak difficult places manually







