Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

In an android game I want to draw a running leg. To output the thigh I do something like:

// legCX,legCY is the location on screen about which the leg rotates.
Matrix m = new Matrix();
m.postTranslate(-legCX,-legCY);
m.postRotate(legRot);
m.postTranslate(legCX,legCY);

So, the above translates the 0,0 point over to the point of rotation about which I want to rotate the leg, then it rotates by the amount I want the leg rotated, then it translates 0,0 back to the original origin.

I then use that matrix to draw the thigh. It ends up rotated as expected. So far so good.

How do I draw the second part of the leg below the knee? It rotates differently than the part of the leg above it and has a center point which moves with the leg above it. I tried the following, but it turns out that the end result is rotation around some single point which doesn't follow the thigh.

Matrix m = new Matrix();
m.postTranslate(-legCX,-legCY);
m.postRotate(legRot);
m.postTranslate(0,-thighLength);
m.postRotate(shinRot);
m.postTranslate(0,thighLength);
m.postTranslate(legCX,legCY);

I suspect that it's probably necessary to do the two rotations in two different Matrix objects and then combine them somehow, but I can't figure out how exactly to do that.

I've tried reading the various wikipedia articles on matrix operations, but I'm having trouble finding the sort of operation that I'm trying to perform.

EDIT: This type of matrix seems to be called a "transformation matrix". Combining multiple operations is called composition of transformations. However, none of the pages on this topic mention how to do a series of translations and rotations.

Surely, if you can use a matrix to do rotation about one point, it must be possible to do multiple matrix operations somehow to allow rotation about one point and then an additional rotation around a different point.

I've tried looking at pages on skeletal animation, but I can't make head nor tail of what they're talking about. My game won't involve many characters, so I don't need to use a physics engine to do super complex stuff. I just want to do the calculations to draw a character that runs.

EDIT: Hooray! Thanks dkantowitz! Your answer wasn't quite right, but you got me really close. I've edited your answer to be correct now. The second matrix needed to translate from the origin, not relative to the leg's center of rotation. And, the combined matrix needs to preConcat the shin matrix first and then the thigh's matrix. Thanks!

share|improve this question
    
Did you used the the keyword in java, the float, double, or Math if you're running on Java programming? For all I know, you're using the some some sort of a way to rotate an object. Also, what kind of rotation did you attempt? In 360 degree spin or not? –  David Dimalanta Feb 28 '13 at 10:27
    
Also, another thing, what kind of 3D software did you used for that skeleton-animation? Are you planning making a human figure moving? –  David Dimalanta Feb 28 '13 at 10:29
    
It's a 2D android game. The values are floats, but I am not trying to do 360 degree spins. I just want to animate a human figure running. I'm not using any extra libraries to do this. I'm just using the posted Matrix manipulations and trying to find the rotation point of the shin given the rotation of the thigh. –  HappyEngineer Feb 28 '13 at 17:46
add comment

2 Answers

up vote 2 down vote accepted

I don't have an Android dev environment setup, but this looks like basic linear algebra.

Try this:

Matrix moveLeg = new Matrix();
moveLeg.postTranslate(-legCX,-legCY);
moveLeg.postRotate(legRot);
moveLeg.postTranslate(legCX,legCY);

.. and another:

int shinCX = legCX;
int shinCY = legCY + thighLength;
Matrix moveShin = new Matrix()
m.postTranslate(-shinCX,-shinCY);
m.postRotate(shinRot);
m.postTranslate(shinCX,shinCY);

Now a combination of the two:

Matrix moveBoth = new Matrix();
moveBoth.postConcat(moveShin);
moveBoth.postConcat(moveLeg);

Obviously you need to apply the series of transforms that make sense to depending on how your figure is drawn.

You can think of a matrix as 'storing' all the transformations performed on it and becoming a new matrix operation. That matrix can the be applied to another matrix to 'repeat' those transformations.

For example:

Matrix spin245 = new Matrix();
spin245.postRotate(245);

You now have a new matrix 'operation': spin245. You can apply this any time you want:

Matrix foo = new Matrix();
foo.postConcat(spin245);

Matrix bar = new Matrix();
foo.postConcat(spin245);
share|improve this answer
add comment

This code should get you started on the necessary linear algebra. I built this class in all-int for an A-star algorithm.:

    /// <summary>Initializes a new fully-specificed non-normed <code>IntMatrix2D</code>.</summary>
/// <param name="m11">X-scale component.</param>
/// <param name="m12">Y-shear component</param>
/// <param name="m21">X-shear component</param>
/// <param name="m22">Y-scale component</param>
/// <param name="dx">X-translate component</param>
/// <param name="dy">Y-translate component</param>
/// <param name="norm">Normalization component</param>
public IntMatrix2D(int m11, int m12, int m21, int m22, int dx, int dy, int norm) : this() {
  Matrix = new int[3,3];
  Matrix[0,0] = m11;  Matrix[0,1] = m12;  Matrix[2,0] = 0;
  Matrix[1,0] = m21;  Matrix[1,1] = m22;  Matrix[2,1] = 0;
  Matrix[2,0] = dx;   Matrix[2,1] = dy;   Matrix[2,2] = norm;
}
#endregion

#region operators
/// <summary>(Contravariant) Vector application.</summary>
/// <param name="v">IntVector2D to be transformed.</param>
/// <param name="m">IntMatrix2D to be applied.</param>
/// <returns>New IntVector2D resulting from application of this matrix to vector v.</returns>
public static IntVector2D operator * (IntVector2D v, IntMatrix2D m) {
  return new IntVector2D (
    v.X * m.M11 + v.Y * m.M21 + m.M31,   v.X * m.M12 + v.Y * m.M22 + m.M32,  v.Z * m.M33
  ).Normalize();
}
/// <summary>Matrix multiplication.</summary>
/// <param name="m1">Prepended transformation.</param>
/// <param name="m2">Appended transformation.</param>
/// <returns></returns>
public static IntMatrix2D operator * (IntMatrix2D m1, IntMatrix2D m2) {
  return new IntMatrix2D (
    m1.M11*m2.M11 + m1.M12*m2.M21,           m1.M11*m2.M12 + m1.M12*m2.M22,
    m1.M21*m2.M11 + m1.M22*m2.M21,           m1.M21*m2.M12 + m1.M22*m2.M22,
    m1.M31*m2.M11 + m1.M32*m2.M21 + m2.M31,  m1.M31*m2.M12 + m1.M32*m2.M22 + m2.M32,  m1.M33 * m2.M33
  );
}
#endregion

As you build the three matrices, yo can cimply multiply them together to obtain a matrix for the resultant transformation, and apply it where needed.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.