Animating rotation using keyframes in python

Hi am a noob to scripting in python, I’m doing some research to see if blender is a viable option for my students to use next year. I have managed to piece together a code from various sources that first creates and then animates a cube to move along the x,y,z axis’s. This works great!!! & I have included the code, But its not quite enough for students to allow students to produce a soley coded scene to show off their coding ability.

What I’m hoping to figure out how to do is to add rotation to the animation of the cube. I want it to rotate in key frames using only python to do this (as I have done for the location keyframes). Any help would be much appreciated as I have been looking for some time for information to solve it myself but no luck.


import bpy

verts = [(-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1), (-1, -1, 1), (-1, 1, 1), (1, 1, 1), (1, -1, 1)]
faces = [(0,1,2,3), (0,1,5,4), (1,2,6,5), (2,3,7,6), (3,0,4,7), (4,5,6,7)]

me = bpy.data.meshes.new("cubey")
ob = bpy.data.objects.new("cubey", me)

ob.location = (5.0, 5.0, 5.0)
ob.keyframe_insert(data_path = "location", frame = 0.0, index= 0)
ob.keyframe_insert(data_path = "location", frame = 0.0, index= 1)
ob.keyframe_insert(data_path = "location", frame = 0.0, index= 2)

ob.location = (-5.0, 5.0, 5.0)
ob.keyframe_insert(data_path = "location", frame = 20.0, index= 0)
ob.keyframe_insert(data_path = "location", frame = 20.0, index= 1)
ob.keyframe_insert(data_path = "location", frame = 20.0, index= 2)

ob.location = (0.0, 0.0, 0.0)
ob.keyframe_insert(data_path = "location", frame = 40.0, index= 0)
ob.keyframe_insert(data_path = "location", frame = 40.0, index= 1)
ob.keyframe_insert(data_path = "location", frame = 40.0, index= 2)

bpy.context.scene.objects.link(ob)

me.from_pydata(verts, [], faces)
me.update(calc_edges=True)

me = bpy.context.object

Ok, first: you don’t need to keyframe every component individually

ob.keyframe_insert(data_path = “location”, frame = 0.0) # index=-1 -> all 3 components

For rotation, you use ob.rotation_euler, ob.rotation_quaternion or ob.axis_angle, depending on the ob.rotation_mode.

You can also set the rotation by applying a matrix to ob.matrix_world, but you still need to keyframe one of the above.

To set the rotation for matrix_world, you can use the mathutils.Matrix module:
mat = Matrix.Rotation(radians(45), 4, ‘Z’) # angle in radians, size of resulting matrix, axis (‘X’, ‘Y’, ‘Z’ or a custom one as Vector object)

import bpy
from mathutils import Matrix
from math import radians

ob = bpy.context.object
ob.keyframe_insert("rotation_euler", frame=1) # assuming rotation_mode being euler by default
ob.matrix_world = Matrix.Translation(ob.location) * Matrix.Rotation(radians(45), 4, 'Z')
ob.keyframe_insert("rotation_euler", frame=50)

Note that it’s not the only way to animate things:
http://www.blender.org/documentation/blender_python_api_2_69_1/info_quickstart.html#animation

Thanks allot for your help Codemax, awesome!! I’m still fumbling around trying to figure out all the examples that you have provided, I have managed to apply rotation to the cube and it seems to be working, using another variation on the example you provided. I’ll post my code below in the hopes that it will provide some clarification for others. I don’t seem to have the control I had hoped for, I want to master the various methods of rotation (i.e. rotation around an axis other than the centre of the object is a goal), so will keep at it. Any advice that any one can provide would be much appreciated!!

import bpy
from mathutils import Matrix
from math import radians
verts = [(-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1), (-1, -1, 1), (-1, 1, 1), (1, 1, 1), (1, -1, 1)]
faces = [(0,1,2,3), (0,1,5,4), (1,2,6,5), (2,3,7,6), (3,0,4,7), (4,5,6,7)]
me = bpy.data.meshes.new("cubey")
ob = bpy.data.objects.new("cubey", me)
ob.location = (5.0, 5.0, 0.0)
ob.keyframe_insert(data_path = "location", frame = 0.0, index= -1)
ob.keyframe_insert("rotation_euler", frame = 0.0)
ob.rotation_mode = "XYZ"
ob.rotation_euler.x = 0
ob.location = (-5.0, 5.0, 0.0)
ob.keyframe_insert(data_path = "location", frame = 20.0, index= -1)
ob.keyframe_insert("rotation_euler", frame = 20)
ob.rotation_mode = "XYZ"
ob.rotation_euler.x = 3.14
ob.rotation_euler.y = 3.14
ob.location = (-5.0, -5.0, 0.0)
ob.keyframe_insert(data_path = "location", frame = 40.0, index= -1)
ob.keyframe_insert("rotation_euler", frame = 40)
ob.rotation_mode = "XYZ"
ob.rotation_euler.x = 6.28
ob.rotation_euler.y = 6.28
ob.location = (5.0, -5.0, 0.0)
ob.keyframe_insert(data_path = "location", frame = 60.0, index= -1)
ob.keyframe_insert("rotation_euler", frame = 60)
ob.rotation_mode = "XYZ"
ob.rotation_euler.x = 9.41
ob.rotation_euler.y = 9.41
ob.location = (5.0, 5.0, 0.0)
ob.keyframe_insert(data_path = "location", frame = 80.0, index= -1)
ob.keyframe_insert("rotation_euler", frame = 80)
ob.rotation_mode = "XYZ"
ob.rotation_euler.x = 18.82
ob.rotation_euler.y = 18.82
bpy.context.scene.objects.link(ob)
me.from_pydata(verts, [], faces)
me.update(calc_edges=True)
me = bpy.context.object
ob = bpy.context.object

Can anyone tell me how the following code has to be adjusted to work with Quaternions (as source of rotation information)?

Like this?

import bpy
from mathutils import Matrix
from math import radians

ob = bpy.context.object
ob.keyframe_insert("rotation_quaternion", frame=1) # assuming rotation_mode being quaternion
ob.matrix_world = Matrix.Translation(ob.location) * Matrix.Rotation(radians(45), 4, 'Z')
ob.keyframe_insert("rotation_quaternion", frame=50)

Assigning a transform matrix to matrix_world works independently of the chosen rotation mode.

Or do you have a Quaternion rotation, want to rotate it further and assign?