AnimationLoader.java 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package eu.tankernn.gameEngine.loader.colladaLoader;
  2. import java.nio.FloatBuffer;
  3. import java.util.List;
  4. import org.lwjgl.BufferUtils;
  5. import org.lwjgl.util.vector.Matrix4f;
  6. import org.lwjgl.util.vector.Vector3f;
  7. import eu.tankernn.gameEngine.loader.xmlLoader.XmlNode;
  8. public class AnimationLoader {
  9. private static final Matrix4f CORRECTION = new Matrix4f().rotate((float) Math.toRadians(-90), new Vector3f(1, 0, 0));
  10. private XmlNode animationData;
  11. private XmlNode jointHierarchy;
  12. public AnimationLoader(XmlNode animationData, XmlNode jointHierarchy){
  13. this.animationData = animationData;
  14. this.jointHierarchy = jointHierarchy;
  15. }
  16. public AnimationData extractAnimation(){
  17. String rootNode = findRootJointName();
  18. float[] times = getKeyTimes();
  19. float duration = times[times.length-1];
  20. KeyFrameData[] keyFrames = initKeyFrames(times);
  21. List<XmlNode> animationNodes = animationData.getChildren("animation");
  22. for(XmlNode jointNode : animationNodes){
  23. loadJointTransforms(keyFrames, jointNode, rootNode);
  24. }
  25. return new AnimationData(duration, keyFrames);
  26. }
  27. private float[] getKeyTimes(){
  28. XmlNode timeData = animationData.getChild("animation").getChild("source").getChild("float_array");
  29. String[] rawTimes = timeData.getData().split(" ");
  30. float[] times = new float[rawTimes.length];
  31. for(int i=0;i<times.length;i++){
  32. times[i] = Float.parseFloat(rawTimes[i]);
  33. }
  34. return times;
  35. }
  36. private KeyFrameData[] initKeyFrames(float[] times){
  37. KeyFrameData[] frames = new KeyFrameData[times.length];
  38. for(int i=0;i<frames.length;i++){
  39. frames[i] = new KeyFrameData(times[i]);
  40. }
  41. return frames;
  42. }
  43. private void loadJointTransforms(KeyFrameData[] frames, XmlNode jointData, String rootNodeId){
  44. String jointNameId = getJointName(jointData);
  45. String dataId = getDataId(jointData);
  46. XmlNode transformData = jointData.getChildWithAttribute("source", "id", dataId);
  47. String[] rawData = transformData.getChild("float_array").getData().split(" ");
  48. processTransforms(jointNameId, rawData, frames, jointNameId.equals(rootNodeId));
  49. }
  50. private String getDataId(XmlNode jointData){
  51. XmlNode node = jointData.getChild("sampler").getChildWithAttribute("input", "semantic", "OUTPUT");
  52. return node.getAttribute("source").substring(1);
  53. }
  54. private String getJointName(XmlNode jointData){
  55. XmlNode channelNode = jointData.getChild("channel");
  56. String data = channelNode.getAttribute("target");
  57. return data.split("/")[0];
  58. }
  59. private void processTransforms(String jointName, String[] rawData, KeyFrameData[] keyFrames, boolean root){
  60. FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
  61. float[] matrixData = new float[16];
  62. for(int i=0;i<keyFrames.length;i++){
  63. for(int j=0;j<16;j++){
  64. matrixData[j] = Float.parseFloat(rawData[i*16 + j]);
  65. }
  66. buffer.clear();
  67. buffer.put(matrixData);
  68. buffer.flip();
  69. Matrix4f transform = new Matrix4f();
  70. transform.load(buffer);
  71. transform.transpose();
  72. if(root){
  73. //because up axis in Blender is different to up axis in game
  74. Matrix4f.mul(CORRECTION, transform, transform);
  75. }
  76. keyFrames[i].addJointTransform(new JointTransformData(jointName, transform));
  77. }
  78. }
  79. private String findRootJointName(){
  80. XmlNode skeleton = jointHierarchy.getChild("visual_scene").getChildWithAttribute("node", "id", "Armature");
  81. return skeleton.getChild("node").getAttribute("id");
  82. }
  83. }