Skeletal animation

Nobody nobody at nowhere.com
Wed Oct 7 00:13:25 EDT 2009


On Mon, 05 Oct 2009 15:25:17 -0700, Carl Banks wrote:

> There are two ways to do what you want.  The first way is to represent
> bones as OpenGL transformations.  Basically a joint deformation you'd
> represent as a translation + rotation.  To rotate a bone you'd simply
> update the rotation of that joint.  Then, when the proper
> transformation is in place, just draw the mesh attached to the bone.
> This can be done with simply with Python an OpenGL.  It's conceptually
> simple but the details can be nasty.  Also it doesn't look very good.

The main problem here is you have to have a separate mesh for each bone.
You can't make a bone affect part of a mesh; or rather, you can't make a
bone affect part of a polygon, i.e. you can't have one vertex attached to
one bone and another vertex of the same polygon attached to a different
bone. This limits it to rigid bodies (machines, robots, etc); you can't
use it for anything with a flexible skin.

> The second way is skinning.  You have a big mesh and each vertex on
> the mesh in influenced by any nearby bones.  This is more difficult
> because a calculation is required for each vertex, and you can't take
> advantage of OpenGL calcualtions(**), but it looks much better.  Also,
> there is no way to do skinning calculations fast enough in Python.
> You might be able to manage it with numpy.

A numpy solution for one-bone-per-vertex (i.e. no blending) is quite
straightforward:

	bone_xforms = np.empty((n_bones,3,3), dtype=float)
	base_vertices = np.empty((n_verts,3), dtype=float)
	vertex_bones = np.empty((n_verts,), dtype=int)
	...
	xform_vertices = add.reduce(bone_xforms[vertex_bones] * b[:,newaxis,:],	axis=2)

[This can be extended to blending a fixed number of bones per vertex,
but is inefficient if the number of bones varies.]

This will be much quicker than doing the arithmetic in Python, but may
still be noticeably slower than a typical C/C++ solution due to copying
the matrices (i.e. bone_xforms[vertex_bones] will duplicate each 3*3 array
to create a n_verts*3*3 array in memory).

OTOH, there might be ways to improve upon this; you could try asking
on the numpy mailing list.




More information about the Python-list mailing list