Skip to content

First steps with Blender’s python API

January 19, 2013

I’ve been programming for quite a few years, but until today I never tried to write a python script for Blender.

Over ten years ago I used Visual Basic, then about three years ago I went over to use Perl and discovered scripting in modern open source languages and fell in love. Since python is in many ways similar to Perl, I knew it shouldn’t prove too difficult to convert to using python full time and implementing it in graphics and 3D software (as it’s the most popular language used in such software).

But instead of just jumping right in, I tried getting to know the language better from the bottom up. The Codeacademy website has been a tremendous help in accomplishing this, but I didn’t really complete all the courses there and after a very enthusiastic start and 6 courses completed, my motivation died off.

I’ve been trying to revive it ever since, and recently made a promise to myself that I would resume learning python and write my first blender script within a month (!).

But as it turns out (yet again), the best motivator for me to learn something new is a practical challenge.

Growing an Ivy Garden

Ivy Illustration

I’ve had an idea for an animation where plants will grow in a convincing manner, but I found no easy straightforward way to accomplish that.

There are three methods I tried, and each had it’s own limitations:

1. Array + Curve modifier – animating the array’s count value to “grow” branches and using a curve modifier to set the direction works nicely but forces you to use a very basic building block, which limits texturing realism and creates a lot of repetition. It’s also easy to get a very high poly count.

2. Using the Build modifier – this one is also nice and useful, enabling the gradual construction of an object, especially if used in combination with the “sort mesh elements” command which sets the order and direction by which the Build modifier works. But you have no control over the timing of the animation (except the start frame and length), and this could leads to serious variations in how the animation progresses (some areas can build too quickly, while others build too slowly).

3. Using an animated blend texture to control transparency – This is nice in theory, but as I understand, makes the transparency change in a straight line which corresponds to the texture’s rotation. So if you have a complex mesh that goes in various directions, this won’t work that well.

So, what I actually need is a Build modifier but with more control. I thought maybe if I could bake the animation it creates, that would allow me to get more control, but I found no way to do that. So I went on to try something else.

Make the ivy slither with some Python

When you generate an Ivy with the IvyGen add on, it creates a separate shell for each branch (similar to the sapling tree add on).
Now that’s useful, because if you add a Build modifier to the whole Ivy (after you’ve converted it from a curve to a mesh, so that you can sort the faces and make sure the construction is animated correctly), and then split up the branches by “loose parts” (select all faces in edit mode, then press P to separate, then choose “by loose parts”), all the shells get the modifiers which were applied to the parent mesh. In our case, all branches now get their own Build modifier with its own start frame and length.

That gives a whole lot more control over the growth animation, but would require manual adjustment of hundreds of objects.
Or… to use a script which would automatically give an appropriate start frame and length for each branch’s modifier.

So, how to do that?

Conveniently, the IvyGen and the splitting process creates and names the branch objects in the order by which they should be animated. So the order of the names in itself can be used to set each branch’s start frame.

And the length of each build animation can correspond to the number of faces.

So, having figured this out,  I started reading a bit about the API and immediately felt rather foolish for my hesitation to start playing with it until now, since it’s so straightforward and simple to implement!

After a day of fiddling with it and trying a few different approaches, this is what I came up with:

import bpy
import re

modifier_type = "Build"
base_name     = 'IVY_Curve'

frame_per_face        = 1 / 4   # how to allocate a total build animation length according to the number of faces on a branch
build_interval        = 15      # how many frames to wait until starting to build 2nd branch
wait_between_branches = 4       # how many frames to wait between branches
build_start_frame     = 1       # Build animation start frame for the first ivy branch

ivy_objects = []

for current_obj in bpy.data.objects:  # browse all objects and filter out ivy branches
    if re.search(base_name, current_obj.name):          # if the object name contains the base_name
        current_obj.data.update(calc_tessface=True)     # calculate face data so that...
        face_count = len(current_obj.data.tessfaces)    # we can obtain the total number of faces

        ivy_objects.append( { "name" : current_obj.name, "facecount" : face_count } ) # add ivy object to list, include name and face count

biggest_obj = ""
most_faces  = 0

# Find the biggest object (highest face count)
for obj in ivy_objects:
    if obj["facecount"] > most_faces:   # if this object's facecount is larger than the previous highscore,
        most_faces  = obj["facecount"]  # then make this facecount one the new max
        biggest_obj = obj["name"]       # and update the biggest object's name

# set base build animation length according to the biggest object's size
base_build_length = int( most_faces * frame_per_face )

count = 0

# set animation length and start frames to all objects in list
for obj in ivy_objects:
    name = obj["name"]
    current_object = bpy.data.objects[name]

    # set the start frame of each object's build anim. by the order of names (which corresponds to order of creation)
    if count != 0: # Set build start for all the branches after the first one:
        bpy.data.objects[name].modifiers[modifier_type].frame_start = int( build_start_frame + build_interval + count * wait_between_branches )
    else:   # Set when the first branch starts to build
        bpy.data.objects[name].modifiers[modifier_type].frame_start = int( build_start_frame )

    # Set build length in proportion to face count
    ratio = obj["facecount"] / most_faces
    bpy.data.objects[name].modifiers[modifier_type].frame_duration = int( ratio * base_build_length )

    count += 1

So this piece of code essentially goes over all objects named “IVY_curve” (which were separated from the single mesh the IvyGen add on creates, after I previously converted it to a mesh, sorted its faces and added a Build modifier to).

It uses the largest of all branches to calculate the maximum build time, according to an arbitrary 4 faces per frame ratio, and gives each branch a start time according to its order in the name stack.

And that’s that – here’s the result:

I’ll be using this for some more sophisticated animations in the near future, stay tuned. And of course, feel free to try it out!

Advertisements
2 Comments
  1. Rashmi permalink

    Hello,if i run this script i am not able to get anything.Can you please explain me how to get this.I did not understand all objects named “IVY_Curve”.

    • Hi Rashimi,

      Sorry, I didn’t really understand. Did you try to install the Ivy Growth Animator script?
      Or did you simply try to run some code?

      Please clarify

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: