Bake Constraints

As my first Python programming exercise, in conjunction with a paper I am writing, I wrote a script that creates a shadow object with a motion curve that mimics the computed location of the selected object.

So, if you have a cube that copies the location of one object, and the rotation of another object, you can now ‘bake’ that motion into an Ipo curve, with a fixed offset by some amount.

http://wiki.blender.org/index.php/Scripts/Manual/Animation/Bake_Constraints

My first step was to learn python and the bpy, so that is accomplished. I also re-awakened all my coding techniques to produce a good object-oriented program that is easy to understand. Now I want to expand the script to work with baking the bone movements of armatures, and add a UI to set the offset and frame duration and offset as well. But for now, if someone is interested, please download and it test/comment back to me. Thanks.!

Good idea. At the very least this could reduce render times.
I’ll check it out, thanks for posting.

hello

i have a camera tracked to empty object, when i select a camera and run the script i have this in console (OSX):

5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: ------------------------------------
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: Bake Constraints Script
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: Bake Constraints began at 1210683472
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: Baking Scene [Scene “Scene”]
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: Baking object [Object “Camera.002”]
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: Object to duplicate is Camera.002
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: =myob= was created as Camera.003
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] debug: Removing constraints from Camera.003
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] Traceback (most recent call last):
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] File “<string>”, line 420, in ?
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] File “<string>”, line 408, in benchmark
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] File “<string>”, line 389, in main
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] File “<string>”, line 372, in bake
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] File “<string>”, line 360, in bakeObject
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] File “<string>”, line 180, in removeConstraints
5/13/08 2:57:51 PM [0x0-0x36036].org.blenderfoundation.blender[374] TypeError

and animation of my camera isn’t the same as with constrain, what is wrong?

greets

peter

i dunno, i will look into it. i had not baked a camera before.

Well, after a couple all nighters and reading all the good links you guys gave me, including the magic invert() from poselib16, here is a script that bakes a constrained armature:

# prior to running script, make a duplicate of a reference (constrained) armature and remove constraints from the clone.
# simplistic example where ref and clone have to be identical with respect to bone names and order
# select the unconstrained armature clone, then shift-select the reference armature object.
# the actual motion of the reference armature's bones will be keyed in the clone's pose ipo

import Blender
import bpy
import BPyMessages

#Vector= Blender.Mathutils.Vector
#Euler= Blender.Mathutils.Euler
Matrix= Blender.Mathutils.Matrix #invert() function at least
#RotationMatrix = Blender.Mathutils.RotationMatrix
#TranslationMatrix= Blender.Mathutils.TranslationMatrix

# Make a dict for fast access without rebuilding a list all the time.
xformConstants = [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT]

CURFRAME='curframe'
scn = bpy.data.scenes.active

def bakeBone(frame,pbone,ref_pose): #frame to bake for, bone to bake, reference bones, armature pose for children to find their parents
    print ('Baking bone %s' % pbone)
    # ref bone must be properly positioned for the frame before entry

    rbones = ref_pose.bones.values()

    #magic happens here. Thank you Faulty
    for rbone in rbones: # find reference bone
        if rbone.name == pbone.name: break
    if pbone.parent == None:
        par_mat = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
    else:
        print ('       bone %s parent is %s' % (pbone,pbone.parent.name))
        parent_pbone = ref_pose.bones[rbone.parent.name] #get their parent's role model (uncle)
        par_mat = parent_pbone.poseMatrix
        
    par_mat.invert()
    pbone.localMatrix = rbone.poseMatrix * par_mat 
    print ('Baked %s frame %i matrix %s' % (pbone.name,frame,pbone.localMatrix[0]))
    pbone.insertKey(arm_ob, frame, xformConstants, True )

    return

def bakeBones(ref_ob,arm_ob): #copy pose from ref_ob to arm_ob

  context=scn.getRenderingContext() 
  staframe = context.startFrame()
  endframe = context.endFrame()
  curframe = Blender.Get(CURFRAME)
  frame = staframe

  ref_mat = ref_ob.matrixWorld
  ref_data = ref_ob.getData()
  ref_arm = Blender.Armature.Get(ref_data.name) #the armature used by the passed object
  
  arm_pose = arm_ob.getPose()
  ref_pose = ref_ob.getPose()

  pbones = arm_pose.bones.values()
  rbones = ref_pose.bones.values()

  act = Blender.Armature.NLA.NewAction()
  act.setActive(arm_ob)
  act.setName(arm_ob.getName())

  # Pose the reference object before starting, or you get a wierd glitch where the bones may not be copied correctly (od data in buffer somewhere)
  Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects
  for frame in range(staframe,endframe+1):
    print ('=================')
    print ('Baking frame %i' % frame)
    Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects
    Blender.Redraw()
    for pbone in pbones:
       bakeBone(frame,pbone,ref_pose) #bake this bone based on its role model (cousin and possibly uncle)

  # eye-candy - smoothly rewind the animation, showing now how the clone match moves
  for frame in range (endframe,staframe,-1): #rewind
    Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects
    Blender.Redraw()
  
  # user comprehension feature - change channel ipo name to match the bone names they drive
  print ('Renaming each ipo to match the bone they pose')
  idx=0
  arm_channels = act.getAllChannelIpos()
  for pbone in pbones:
    print pbone.name, arm_channels[pbone.name] 
    ipo=arm_channels[pbone.name]
    ipo.name = pbone.name

  return

ref_ob = Blender.Object.GetSelected()[0]
arm_ob = Blender.Object.GetSelected()[1]
bakeBones(ref_ob,arm_ob)
print 'done'

ok, piotrek, i must have fixed that somewhere in my journey to version 0.2. See http://wiki.blender.org/uploads/5/54/Bake_Constraints.zip or the wiki page for the latest version, which blends in the script in my above post into a more friendly and rigorous do-it-all script of 800 lines of love and joy. This version bakes the object motion, and then bone motion.

I do have an issue with the root bone during baking, which I will be looking into, I suspect it is something about the magic area of the code…

hello,

thanx for fast answer
now i don’t have a error messages in console but a final clone of camera is translated (not at the same position as source), ipos was created

what do you think about it?

still testing on animated camera “track to” empty object

greets

peter

yes, the translated offset is intentional (so you can see it!) it is defined by usrDelta - you can change that to all zeros, (it is specified in the Contstants section of the code, line 143. Do you know how to edit the python code?
usrDelta=[0,0,0,0,0,0]
It is a matrix that offsets the clone from the reference. loc xyz and rot xyz
just be sure to delete the right camera!

hello papa :slight_smile:

thanx :slight_smile: i will do it in text editor

:slight_smile:

Peter

nice work, although it’s a duplacate of a script i did like 3 or 4 years ago :). That’s how it ends if scripts dont make it into svn, they’ll get coded again and again instead of improved. So don’t hesistate and try to get it into the repository :wink:

pildanovak: ya got a link? an old copy somewhere on your hard drive? I’d love to look at it, not that it wasnt a great learning experience and all…I’ve started a wiki scripts page for that posterity feeling.

ah sorry just sent you a stupid pm :slight_smile: I didn’t remember this thread ;]

http://plant.ffa.vutbr.cz/~novak/dwnflz/consToIpos.py

this is the link you wanted. It should have also a gui. But I’m not sure if it will work correctly with current blender.

edit: no it probably hasn’t gui, I’ve mixed it all up. I’m so tired today! and still sitting here and working…

this one does this thing: records all selected objects movements to ipos, DISCONNECTS them from hierarchy. That’s because with ipos they would start having offsets and stuff like that.So it’s better to duplicate them manually before running the script. I used it to play back animations in blender game engine - see the anatomical sketchbook on my site:
http://plant.ffa.vutbr.cz/~novak/

Hi PapaSmurf,

I tried your script, and it works perfect as long as I only select one Object to bake.
For example, when I try to bake the animation of two objects at the same time. I get two copies for each object, of which one has been baked correctly. The other copies have also baked ipo-curves, but they are screwed up. Can you give me a hint what I did wrong?
My problem is, that I have to bake 25 Objects in an 3800frames animation, so doing each one alone takes very much time.

hi orion! I will modify it tonight to handle multiple selected objects. I will post it back when I have it updated.

Cool, thanks in advance :wink:

wiki updated. including “user manual”. It should be version 0_4 if I did it right.

many thanks for this script, it’s a must have for game engine animations and mocap !
it could be handy if the clone armature contains only the ‘deform enabled’ bones.

  • a insertkey step value.

here is a mod of papasmurf script :
http://www.mediafire.com/file/mlmmo5zmtzl/contraint bake mod.zip

Mod Version History ( littleneo )
	0.7mod:
		30/03/10
		based on 0.7. added a gui for most of the 0.7 options,
		. create a new armature, leave original one unmodified
		. IK strech/scale support
		. faster
		added new options :
		. 'first keyed frame' offset
		. start and end frame can be retrieved from action
		. bone selection by layers, selected, and/or deformed
		also modded BPyArmature : this script needs the BPyArmature_mod to work
		! only tested by me ! <b>need a community review</b>. but works fine afaik :)

unzip it in the script folder. nothing will be deleted ( I suppose :slight_smile: )
file names are :
animation_bake_constraints_mod.py
BPyArmature_mod.py (in bpymodules)

works fine in most of the cases, but it need some more code in special cases :
example since you can choose which bone to key, if a parent bone is animated and not keyed, one need to key the sons accordingly to reflect the animation, and to clearparent() in the new armature.

oh wow. so cool. Thanks little Neo! glad it helped u, and nice to see this stuff lives on. now i’m wondering if it should be converted to 2.6…I’ll put it on the list of to-do’s.

there’s this thread about open rigging setup, really interesting.
as the api is work in progress, it requires more spare time to maintain your script. for the moment ORS does not seem to work on alpha2.

I have some ideas related to bake constraint script, maybe we could share some work ?

it’s really useful for the mocap of course but also for the GE :
the less bone, the more frame/sec
the less constraints, the more frame/sec

main idea would be, starting from one armatureA controled by constraints (in or outside the arm) :
to generate an armatureB containing only the ‘flesh’ and muscles bones.

…maybe the option to generate an armatureC with controlers and ‘meca’ intermediates bones only. so one need to modify all of the constraints target on armatureB (I made this script already)

to bake only some of the bones (as the mod does) from A to B : bone list generated from the bone listed in an action, and also which of the curves are keyed in it. it’s useful to blend animations in the GE action actuator.

etc…

Hi guys,

Just been trying this script out for a workflow to get animated geometry from blender into Unity.

It’s for 2D characters made of simple quad planes. I have the planes constrained to an Armature. I need to bake the Armature animation into the planes. This will remove the need to export the Armature into Unity as well as the geometry.

The version I’m using is 0.7 from wiki.blender.org.

I’m selecting multiple objects when running the script. I get a correct result with a flat hierarchy, but this also generates a lot of unwanted animation data. With a parented hierarchy there is an additive transform result on child objects.

Would it be possible to modify the script to work with geometry based hierarchies as well as Armatures?

btw, I’m currently working with 2.49b