Skip to content

Archive

Category: Blender Scripting

Not quite. For now just a few links that you may find helpful.

Know the tricks

There are several essential tricks for Blender 2.6.1 (much of this works in 2.5x/2.49 or can inspire you). Presented as a list of tips, honestly it’s more of a survival kit if you’re serious about scripting Blender – read it or learn the hard, frustrating way.

And if you’re still an OS-X newbie (I am), learn how to run programs from the terminal.

What if I wanted to use a Python IDE with Blender?

The main problem I see here is that bpy and Blender may not be recognized by Python IDEs (I tried PyCharm). I think there might be a workaround but it looks heavy handed.

  • There is/was/used to be Stani’s Python editor. I think there is an old version on sourceforge. Maybe you can access his blog in which case you might get a later version (untested).
  • It may be possible to setup Eclipse in a useful way (see ‘Programming add-ons for 2.5′ below) (untested).
  • Wing IDE provides a solution that is somehow compatible with Blender (untested).

I want to set breakpoints

There is a community add-on for that (2.5x, untested)

Programming add-ons for 2.5…

Getting started with writing add ons is a little harder than with 2.49b. I wrote a little about this (search?). More notably, there is a free e-book in PDF format by Witold Jaworksi (haven’t read it yet, looks useful)

I just did a test using blender 2.49’s radiosity feature. I wanted to bake self illumination to vertex color.

However, this opens more questions than it solves.

Radiosity in 2.49 doesn’t support double sided faces. This seems to cause artifacts when baking clothes and hair (clothes don’t have thickness, and I doubt I would go this far – the model is heavy enough as it is).

Additionally, the rendering is not very clean with the original, mid poly model (~5k faces). I can increase the definition to render lighting (using radio buttons), but then I need to transfer the result back to the original model.

So the plan (assuming I persist) would be to modify the model, add thickness to clothes, bake illumination, then write a script that can transfer color data back to the original model.

I think it’s a bit over the top but radio bakes play an important part in our pipeline already, and I feel vertex paint, however old fashioned, offers distinctive possibilities. For example I already have a script that can extract dark areas from the radio bake, which gives access to ’shadow geometry’ – so we can take this into account when programming gameplay.

I’m also working on a method to simplify geometry while losing as little color information as possible – ultimately this should help me improve rendering quality without losing much performance.

This is applicable to Blender 2.49. It’s hardly worth a post but I keep forgetting about it.

  • In your blender folder, select the blender application icon, right click and do ’show package contents’
  • browse to content/MacOS/.blender
  • The nag is that this .blender file is hidden by default, you can use this tip or download a free utility to hide/show hidden files and folders.

A good idea is to make an alias after you found your scripts folder…

This post won’t give you all the information you need if you’re simply new to Blender Scripting. Many of us, however, continued scripting Blender 2.49 because 2.5 scripting wasn’t stable at the beginning. I’m quite sure this post can help you to migrate your scripts from 2.49 although it’s very hands on and I haven’t really tried to organize these useful bits.

  • Export script template (source code). This shows how to arrange metadata, invoke the file selector and write simple output to a file (to make sure something’s actually happening). Includes summary instructions to install the script.

I updated my exporter, Ox3ich, although not with all the features of the current 2.49 version. After trying it out a little I will make it available. In the meantime I list just a few of the many differences between the 2.49 / 2.59 APIs.

Writing I/O scripts for Blender 2.5 isn’t exactly what I’d like to do at the moment. I just have to. Scripting integration looks interesting, with a little more flexibility than in 2.4. Useful links…

As usual, looking at existing scripts will help. The documentation isn’t awesome.

Script Registration

  • The registration process has changed. The easy part is updating your metadata (just look at any of the scripts bundled with 2.5).
  • Scripts now require register/unregister methods. This allows tighter integration as far as I can see, notably it makes it easy/possible for a script to call another script.

Your script/add-on won’t automatically show in the designated menu, but it should appear under [file > user preferences > add-ons] where you can enable it. Then save user prefs (save as default option in the bottom left) to keep the script enabled next time. This page gives a little information about registering add-ons.

2.49 => 2.59 scripting : Miscellaneous changes

  • access current scene - bpy.context.scene
  • get object data (e.g mesh) – object.data
  • Blender.sys.join => os.path.join
  • Writing strings to output stream, see stack overflow answer (python 3.0)
  • mesh.verts => mesh.vertices
  • faces.verts => face.vertices - additionally, face.vertices is now an array of ints representing vertex indexing.
  • face.mat => face.material_index
  • mesh.getFromObject => object.to_mesh(bpy.context.scene,True,”PREVIEW”)
  • vertex.no => vertex.normal (but still uses vertex.co for ‘coord/coordinate’)
  • to change the current frame, use scene.frame_set(). Do not directly assign the frame number. Note that frame numbers start at 0, not 1.

There are changes from Python 2.x to Python 3.x in the way global variables are handled; this combines with a change in the way scripts are invoked, adding up to annoyances when trying a quick and dirty way to output debug info to a file…

Vertex colors

Vertex color data is now separate from face data, stored in Mesh.vertex_colors; additionally this now supports multiple layers, and colors are now in rgb float format (think it used to be rgba, byte format)

  • Iterate layers with something like for layer in mesh.vertex_colors
  • layer.active to find if a layer is active.
  • get layer data: layer.data
  • get vertex color for a face: layer.data[i], will contain corner colors for face at index i.
  • example 1: mesh.vertex_colors[0].data[1].color4[0]
    Red component for corner 4 in face 1, vcol layer 0 of mesh
  • example 2: mesh.vertex_colors[0].data[0].color1.r
  • Red component for corner 1, face 0, vcol layer 0 of mesh

Random links

These days I’m working on urban environments in Blender. Urban environments can be easily broken down into modules and series – cloning the same objects over and over to create roads, floor tilings, buildings and so forth…

Duplicating modules by hand is tedious even if you don’t care about millimeter accuracy. So I thought I’d write a little script to do simple tilings.

The script duplicates the active object several times and merges the result into a single object. The original module or ’tile’ is preserved. This script will run with Blender 2.49 and can be easily modified (for example, if you want to add padding between copies or don’t want to merge the result)

What we need to know

To retrieve the active object:

scene=Scene.GetCurrent()
active=scene.objects.active

Initially I thought about duplicating vertex data directly as I want the tiles to be part of the same object. But duplicating the object first may be safer and offers more flexibility.

We can use the following command to duplicate active objects:

Object.Duplicate() # duplicate, link mesh data
Object.Duplicate(mesh=1) # duplicate, clone mesh data

To tile clones edge to edge, we’ll need to know the extent of the object:

dimX=obj.getBoundBox()[6][0]-obj.getBoundBox()[0][0]
dimY=obj.getBoundBox()[6][1]-obj.getBoundBox()[0][1]
dimZ=obj.getBoundBox()[6][2]-obj.getBoundBox()[0][2]

Once we have duplicated and moved our objects we can merge them together using join(). This function is a member of the object class and will join the target with all objects in a given array:

arr=[]
arr.append(anObject)
obj.join(arr)

join() doesn’t delete merged objects; usually we want to delete all clones after merging. To remove an object from the scene, we can use the following command:

scene.unlink(anObj)

Reminder… to iterate in python:

for x in range(N) # e.g range 10 iterates from zero to 9

If you’re in a hurry, a modal UI provides the quick and dirty way to input data from the user:

numX = Blender.Draw.PupMenu(”X dupli%t|1|2″)

This gets the user to input either ‘1′ or ‘2′.

Complete Source Code

#!BPY

“”" Registration info for Blender menus:

Name: ‘Tile v0.0′

Blender: 249

Group: ‘Object’

Tip: ‘Tile an object along x,y,z axis and merge’

“”"

import Blender

import bpy

from Blender import *

# TILE V0.0 – A SIMPLE SCRIPT FOR TILING AND MERGING THE RESULT

# LICENSE: LGPL

def copy_and_merge(nx,ny,nz):

scene=Blender.Scene.GetCurrent()

target=scene.objects.active

dimX=target.getBoundBox()[6][0]-target.getBoundBox()[0][0]

dimY=target.getBoundBox()[6][1]-target.getBoundBox()[0][1]

dimZ=target.getBoundBox()[6][2]-target.getBoundBox()[0][2]

clones=[]

for x in range(nx):

for y in range(ny):

for z in range(nz):

Object.Duplicate(mesh=1)

clone=scene.objects.active

clone.LocX+=dimX*x

clone.LocY+=dimY*y

clone.LocZ+=dimZ*z

clones.append(clone)

clone.select(0)

target.select(1)

first=clones.pop()

first.join(clones)

for k in clones: scene.unlink(k)

# ————————————–
# Get the number of copies from the user and run the script

numX = Blender.Draw.PupMenu(“X dupli%t|1|2|3|4|5|5|6|7|8|9|10″)

numY = Blender.Draw.PupMenu(“Y dupli%t|1|2|3|4|5|5|6|7|8|9|10″)

numZ = Blender.Draw.PupMenu(“Z dupli%t|1|2|3|4|5|5|6|7|8|9|10″)

copy_and_merge(numX,numY,numZ)

# END ————————————

This is it. Modifying the script just a little can help you make staircases, fences and all kind of stuff, so I think it’s a nice introduction to how scripting can help generating scenes quickly and easily.

Exporting cloth animations required only a few changes to the ox3ich exporter.

=> Ox3ich exports blender meshes and animations (source, LGPL).

Since both qwagga (scene export) and ox3ich (mesh/animations export) are now available for download, I guess I’ll want to consolidate this soon with an online project manager. In the meantime… you can have a look at the notes below, outlining how ox3ich handles cloth animations.

Finding Cloth objects

myObject=bpy.data.objects["Dress"] // get the object to be exported

myObject.type == Modifier.Types.CLOTH // confirm this object has ‘cloth’ enabled

We could have an isCloth method, looking like this:

def isCloth(object):

for x in object.modifiers:

if x.type==Modifier.Types.ARMATURE:

return 1

return 0

Using Cloth Objects as equipment

A simple way to generate animations for equipment (see this article) consists in reusing the parent object’s Armature (with extra bones for equipment) and export the actual keyframes (the shape of the mesh as deformed by the armature). Mesh data is memory intensive. One advantage, however, is we don’t need to rewrite / adapt modifiers code.

Now, for equipment, we grab all actions and apply them to the actor’s armature. We’ll do the same for cloth objects. However, there is a difference

In the case of equipment the actor’s armature is on the object’s modifier stack and is really used to animate the object, not the actor.
In the case of cloth, we may not want to animate the cloth with the armature directly. Instead, we apply the armature (and the action) to the actor, which indirectly influences cloth dynamics.

So we need to retrieve the actor used to influence cloth dynamics. I’ll use the same naming convention I used for other equipment items, e.g. dress@player. Then we have:

def getArmatureForCloth(cloth):

influencingActor=bpy.data.objects[cloth.name.split('@')[-1]]

return getArmature(influencingActor)

This uses the naming convention to retrieve the actor. For basic animation export, ox3ich doesn’t need anything else (in code sample ‘object’ is the object using cloth modifier):

exportItemFile(object,path)                      # export basic mesh and material data

actions=getActions(object)                      # return actions for owner (uses naming convention)

armature=getArmatureForCloth(object)            # return the owner’s armature

exportActionFiles(actions,armature,object,path) # export all actions in the usual way.

Restricting key frames for export

By default, the exporter will export mesh data for all action frames, so I’ll extend the actor naming convention to allow us to define a frame range; for example

“player.walk@30-50″ # walk cycle includes only frames 30 to 50 for export

The following function parses the frame range according to this convention

def getFrameRange(action)

range=[1,30000]

parts=action.name.split(’@')

if len(parts)==2:

rngString=parts.split(’-')

range[0]=int(rngString[0])

range[1]=int(rngString[1])

return range

Notes

This is enough to get started with exporting cloth animations. There are several shortcomings:

  • The exporter does not bake cloth animations, this is done manually (so probably the cloth animation part only works if each file contains only one animation).
  • The exporter doesn’t explicitly handle cyclic animations. With my sample walk cycle, it doesn’t look all that bad, but there has to be a discontinuity between the first and last frame. Minimally the last frame should be replaced by the first frame. For smoother results, two consecutive cycles should be blended together, and I’d like the exporter to do this as well.

A quick solution for equipment

The story so far

A few months back I wrote a simple export plugin for Blender. Unlike most export scripts, the plugin interprets blender files as asset libraries. The plugin supports basic material properties and animation.

When I wrote the export script, I didn’t want to spend time writing a bone animation module for the engine. Instead I decided to bake animation frames – bone deformations are applied from within blender, resulting in ‘mesh frames’.

While mesh frames are pretty heavy, there are advantages too:

  • Interpolating between frames is much faster than applying bone deformations.
  • Since the exporter generates frames by collapsing an object’s modifier stack, it is possible to export all kind of animations, not just bone animations.

Equipment

At that point, my setup didn’t provide a solution for equipment. So if I wanted an actor to hold an axe, or a sword, I had to clone the model and bake a separate animation. Needless to say such a system is hardly usable.

Equipping items consists in making them visible as part of a PC or NPC visual presentation, so an actor could hold a sword, a shield, or change dress (this requires more care).

The new setup is fairly simple:

  1. Bones are added to the actor’s armature – so we can add a bone to represent a sword, a gun, a hat… anything.
  2. The item we want to equip is placed at the correct location – so if it’s a sword, we just place it in the character’s hand.
  3. The item is renamed accordingly, e.g. sword@elven, indicates that the sword should animate along with an actor named ‘elven’.
  4. Parent the item to the armature (in the item’s modifier tab, I check ‘make real’ for the armature modifier, to ensure that this gets applied when the exporter collapses the modifier stack)

The notation item@actor is an arbitrary convention. Since actions are not bound to any particular actor, if we have…

  • an action named elven.strike
  • a piece of equipment named sword@elven

…then the exporter knows that elven.strike should be applied to sword@elven.

Animations are exported separately for various pieces of equipment. It’s a huge step forward compared to the previous system I used. When we want an actor to equip an item, all we have to do is load the matching ‘animated version’ of this item and synchronize animation playback.

This solution is still wasteful – but it wouldn’t be too hard to extend it to define equipment slots (so instead of exporting all animations over again for each item, we’d just have ‘dummies’ used to define transform matrices)

One Animation per File, really?

When I investigated Blender animation to create my exporter, I found about Blender actions. Blender actions provide a simple, easy way to define ’several animations per actor’. More specifically, an action is a named sequence of key frames associated with an object (typically an armature, but also works with other object types). So at the moment I have ‘run’,'walk’,'hit’ actions etc… While actions are normally used in NLA (non linear animation – aka mixing part animations together, e.g. smile + run), they originally seemed well suited to building ‘animation libraries’ - All the exporter has to do is retrieve each action, bind it to the armature and export it.

Unfortunately, this approach breaks down when we combine several animated objects. For example, suppose you want to apply a floor constraint (e.g., as part of a walk animation), then…

  1. Consider the armature for the actor we’re animating.
  2. Define a ‘floor’ object
  3. Define 2 empties (used to move the actor’s feet)
  4. Apply the floor constraint to the empties using the ‘floor’ object as target
  5. Add IK solver constraints to the feet of the actor’s armature, so the feet now follow the empties.
  6. To animate, we move the empties, not just the bones.

How many objects are being animated here? Well, 3 really. We have the armature and the empties. To setup this animation correctly, then, we need to bind the following actions (assuming we associated the empties animations to actions) …

  • The armature action (e.g. elven.walk)
  • LeftFootEmpty action (elven.walk.leftFoot?)
  • RightFootEmpty action (elven.walk.rightFoot?)

At this point, I drop the towel altogether. Although there are disadvantages to keeping one file per animation, we have to choose: unless an animation is simple (1 action <=> 1 animation <=> 1 object), it should be kept in a separate file.

I guess if it was to do all over again, I’d simply try to avoid complex rigs. In the meantime I changed my export script (never mind some of my engine code) so that animations are always kept in separate files. I now have, for each object:

  • A model file. All models, whether animated or not, use the same format
  • For each model, zero, one or several animation files.

Wow. Kind of blended into the new year without noticing. But then 2009 hasn’t been a bad year. Let’s keep it up :)

In my series of articles about Blender Export scripts, I explored how we can use Blender scenes as game asset libraries. In this article, I cover basic facilities needed to export a scene to several files representing
game assets.

Interactive Session

Try this:

Blender.sys.makename(ext='.foo')

Then this:

Blender.sys.makename()

Using the above, you can avoid accidentally overriding the .blend file, making sure, the default export file name uses the correct extension.

Now let's try this:

data='foo'
fname=Blender.sys.makename(ext='.exnfo')
fname # prints 'PATH_TO_BLEND_FILE/BLEND_FILE_NAME.exnfo'
file=open(fname,'w')
file.write(data)
file.close()
Blender.sys.exists(fname) # prints '1' for true
input=open(fname,'r')
target=input.read()
target # prints foo!
input.close()

Use something like this to retain the path to export to across Blender sessions, saving
frustrating moments browsing to the same path over and over.

The Blender file chooser isn't terribly helpful to export to folders as it doesn't allow selecting a directory so easily. Worse, I haven't really found a way that a new directory can be created using a Blender script (being Noob-y?). Having said that, with a little assistance, we can still get a user to enter a directory path, and with the above, we make it easy to just reuse the same path.

To generate file names under a given path, use something like:

x=Blender.sys.makename()
parent=Blender.sys.dirname(x)
child=Blender.sys.basename(x)
dirname=Blender.sys.join(parent,child)
fname=Blender.sys.join(parent,'dummy.txt')
fname # just print the result to be sure...

Note that x and dirname are... exactly the same thing. This is just to illustrate defining a default export folder (if we want to export a scene to several files) and creating a path to export to.

Finally, code to pop a file chooser and bind it to a callback will look like:

# the callback
def exportTo(fname)
# do something useful...

#pop the file chooser
Blender.Window.FileSelector(exportTo, 'Meshes in Exile','dummy.myExtension')

(not sure if this works in interactive mode, but that's what we need)

Putting it all together, we can create a script that:
- Retrieves a path to export to, from a well known location (as in, the same folder as the blender file). The export path is (sensibly) specific to each Blender scene.
- Suggests such previous export path, if available.
- Otherwise suggests a reasonable path for an export folder
- Generates filenames to export within such export folder.

Checkout previous articles for 'actually how to export the real data'.

In Blender, Actions contain information about ‘reusable animations’ that can be combined to generate complex animated scenes. Actions can also be used to create catalogues of animations associated with game assets.

I might have suggested before that a 3D artist may prefer to keep several avatar models in the same blender file. Keeping models in separate files makes it (not impossible yet) more difficult to share geometry and materials between models. For the designer, ’sharing’ may not be a very high level concept, more something like ‘copy, paste and modify’. Nice, fast and simple.

Blender actions are created while posing armatures. Unfortunately, there is not a clear way to retain the connection between an action and the armature first used to generate this action. Here’s a little experiment that illustrates this:

1. Create an armature A with a bone named ‘Bone’. Create an action X for this armature.
2. Create an armature B with a bone named ‘Bone’ (same name). Make action X current in B.
2. Observe the result.

Essentially, Blender Actions are lists of keyframes ‘per channel’; a channel is just a name; the name binds bone names. Any armature can use any action, and this will be ‘effective’ as long as the names match.
That may be powerful. Not great when we want to export per character keyframes for each action.

At this point, we may consider loading a config file listing actions for each actor, or design a little script letting us retain the original armature <> action binding when creating new actions (I think that can be done and integrated nicely with Blender). But I won’t illustrate any of the above this time. I just fallback to a naming convention for my actions, something like:

myActor.jump
myActor.nod

Since all actions are dumped in the same list, this also allows quickly locating per character actions in the Blender interface.

Let’s not learn all about Python Strings

Instead, try this:

z='funbot.jump'
p=z.split('.')
p[0] # prints 'funbot'
p[1] # prints 'jump'

Now we can match each action to a character ‘owning’ this action. You can learn more about actions and *stuff* in previous articles on this blog.

My current export script for character animation requires a naming convention for binding a character to it’s armature.  Also, the script only exports the currently selected mesh.

In this article, I illustrate how to examine a Blender scene to discover assets; I also show how to find the armature modifier associated with an animated character.

In outline, this is how to structure a script to export an asset library:

  • Iterate all objects in the scene
  • Retain only Mesh objects.
  • For each mesh object, check whether this object uses an armature; if so, assume the object is a kind of actor or character.
  • Export mesh objects as appropriate (You can learn how to do this from previous articles on this blog)

Interactive session

Let’s try the following:

s=Blender.Scene.GetCurrent()
s.objects
for x in s.objects:
	x.type

(After typing ‘x.type’ in the interactive console, press enter twice to effect the loop)

This will print the type of each object in the order they are stored in the scene. We only want to export Mesh objects. Pick any Mesh object using an armature. (in my case, index 1 in the object list).

object=s.objects[1]
for x in object.modifiers:
	if(x.type==Modifier.Types.ARMATURE):
		x

This will print something like:

[Modifier "Armature", Type "Armature"]

That’s all we need to identify actors and props in a Blender Scene.