JointTransform.java 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package eu.tankernn.gameEngine.animation;
  2. import org.lwjgl.util.vector.Matrix4f;
  3. import org.lwjgl.util.vector.Vector3f;
  4. /**
  5. *
  6. * Represents the local bone-space transform of a joint at a certain keyframe
  7. * during an animation. This includes the position and rotation of the joint,
  8. * relative to the parent joint (for the root joint it's relative to the model's
  9. * origin, seeing as the root joint has no parent). The transform is stored as a
  10. * position vector and a quaternion (rotation) so that these values can be
  11. * easily interpolated, a functionality that this class also provides.
  12. *
  13. * @author Karl
  14. *
  15. */
  16. public class JointTransform {
  17. // remember, this position and rotation are relative to the parent bone!
  18. private final Vector3f position;
  19. private final Quaternion rotation;
  20. /**
  21. *
  22. * @param position
  23. * - the position of the joint relative to the parent joint
  24. * (bone-space) at a certain keyframe. For example, if this joint
  25. * is at (5, 12, 0) in the model's coordinate system, and the
  26. * parent of this joint is at (2, 8, 0), then the position of
  27. * this joint relative to the parent is (3, 4, 0).
  28. * @param rotation
  29. * - the rotation of the joint relative to the parent joint
  30. * (bone-space) at a certain keyframe.
  31. */
  32. public JointTransform(Vector3f position, Quaternion rotation) {
  33. this.position = position;
  34. this.rotation = rotation;
  35. }
  36. /**
  37. * @param localTransform
  38. * - the joint's local-transform at a certain keyframe of an
  39. * animation.
  40. */
  41. public JointTransform(Matrix4f localTransform) {
  42. this.position = new Vector3f(localTransform.m30, localTransform.m31, localTransform.m32);
  43. this.rotation = new Quaternion(localTransform);
  44. }
  45. /**
  46. * In this method the bone-space transform matrix is constructed by
  47. * translating an identity matrix using the position variable and then
  48. * applying the rotation. The rotation is applied by first converting the
  49. * quaternion into a rotation matrix, which is then multiplied with the
  50. * transform matrix.
  51. *
  52. * @return This bone-space joint transform as a matrix. The exact same
  53. * transform as represented by the position and rotation in this
  54. * instance, just in matrix form.
  55. */
  56. protected Matrix4f getLocalTransform() {
  57. Matrix4f matrix = new Matrix4f();
  58. matrix.translate(position);
  59. Matrix4f.mul(matrix, rotation.toRotationMatrix(), matrix);
  60. return matrix;
  61. }
  62. /**
  63. * Interpolates between two transforms based on the progression value. The
  64. * result is a new transform which is part way between the two original
  65. * transforms. The translation can simply be linearly interpolated, but the
  66. * rotation interpolation is slightly more complex, using a method called
  67. * "SLERP" to spherically-linearly interpolate between 2 quaternions
  68. * (rotations). This gives a much much better result than trying to linearly
  69. * interpolate between Euler rotations.
  70. *
  71. * @param frameA
  72. * - the previous transform
  73. * @param frameB
  74. * - the next transform
  75. * @param progression
  76. * - a number between 0 and 1 indicating how far between the two
  77. * transforms to interpolate. A progression value of 0 would
  78. * return a transform equal to "frameA", a value of 1 would
  79. * return a transform equal to "frameB". Everything else gives a
  80. * transform somewhere in-between the two.
  81. * @return
  82. */
  83. protected static JointTransform interpolate(JointTransform frameA, JointTransform frameB, float progression) {
  84. Vector3f pos = interpolate(frameA.position, frameB.position, progression);
  85. Quaternion rot = Quaternion.nlerp(frameA.rotation, frameB.rotation, progression);
  86. return new JointTransform(pos, rot);
  87. }
  88. /**
  89. * Linearly interpolates between two translations based on a "progression"
  90. * value.
  91. *
  92. * @param start
  93. * - the start translation.
  94. * @param end
  95. * - the end translation.
  96. * @param progression
  97. * - a value between 0 and 1 indicating how far to interpolate
  98. * between the two translations.
  99. * @return
  100. */
  101. private static Vector3f interpolate(Vector3f start, Vector3f end, float progression) {
  102. float x = start.x + (end.x - start.x) * progression;
  103. float y = start.y + (end.y - start.y) * progression;
  104. float z = start.z + (end.z - start.z) * progression;
  105. return new Vector3f(x, y, z);
  106. }
  107. }