Our animation programmer, Aaron, sent the team this email yesterday and it was too good not to share! -Subutai
So I've been experimenting with ways to best determine which guard you're in. I started simple... I added a bounding box to our character's sword, and cached off the location of the center of the sword per pose and its angle relative to the player (like the face of a clock - 3 o'clock = left, 6 o'clock = down, etc.).
This forces you to somewhat arbitrarily chose a center point, and the closer you get to that point, the more sensitive things get. This also doesn't account well for poses like Breve and Longa which extend out in front of the player. A second angle in a plane perpendicular to the first (i.e. clock face centered on the arms) can be used to account for animations that extend out in front of the player, but the origin used still gives us problems for the same reasons. Another technique is to stamp out the bounding box for each of the poses, then calculate an error metric to measure the "distance" the player controlled sword is away from each of these.
This works pretty well, and I think I'll use it at least for making sure the sword is generally pointed the correct direction. We can also use this to grade the player on their form, or keep track of their favorite guards, variations or whatever. What I really wanted, however, is to divide the space up nicely for each of the poses. I already had some triangulation code that's being used as part of our parameterized animation calculations, and figured I should be able to put that to use. A Delaunay Triangulation takes a set of points, and tessellates the space nice and evenly avoiding skinny triangles. Here's an example in 2d:
You may remember from high school that you can calculate a circle given three points that lay on its circumference. One property of a Delaunay triangulation is that no other vertex can be inside the circumcircle of a given three vertices. That's how it generates nice triangles. Here's what the Delaunay triangulation of our guard poses looks like in 3d.
Note: in 3d the space is broken up into tetrahedron instead of triangles. A tetrahedron has just four points. More generally, these are called simplexes. A simplex is the simplest container you can create for a given set of dimensions. It always has one more vertex than the number of dimensions. So in 2d, this is a shape with 3 points (or a triangle). In 3d, we require 3+1 points to form a tetrahedron.
Anyway, so far this doesn't really help us much. However, there's something called a Voronoi diagram (or tessellation) which is the dual of a Delaunay triangulation. It's made by taking all the centers of our circumcircles...
These diagrams are useful for doing stuff like calculating the closest McDonalds!
For our purposes, we'll want this in 3d for finding the closest guard pose. Unfortunately, I sometimes go a little overboard. The Delaunay triangulation implementation I wrote for calculating parameterized animations is set up to handle any number of dimensions. The technique I used involves projecting the data onto a paraboloid one dimension higher and calculating its convex hull. I only mention this, because unlike other methods, we never explicitly calculate the circumcircles of the vertices. And because my code works in any dimension, instead of just circumcircles or circumspheres, I needed a method to calculate the hypersphere that circumscribes a given simplex for a given dimension. Phew! Turns out this isn't a big deal: you just load the legs of the simplex into a matrix (along with the half squared length), invert it, and the center falls right out! And here you thought you'd never use that simultaneous equation bullshit they taught in ninth grade. Back to the pretty pictures. Here's our Voronoi tessellation in 3d.
I've highlighted the faces that contain the currently selected pose. It's kinda hard to see what's going on without moving the camera around, but hopefully you get the idea. Here's with another pose selected and from a different angle. These are all using the center point of the sword. I'll probably try experiment using the hand position instead, or maybe the tip of the sword, and see what works best.
Anyway, I hope you enjoyed!
Thus endeth today's lesson.