*/\r
package com.badlogic.gdx.graphics.keyframed;\r
\r
+import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.graphics.animation.Animator;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Animation;\r
+import com.badlogic.gdx.graphics.loaders.md5.MD5Quaternion;\r
+import com.badlogic.gdx.math.Quaternion;\r
+import com.badlogic.gdx.math.Vector3;\r
\r
/**\r
* An animation controller for keyframed animations.\r
R.Indices[idx] = new short[numIndices];\r
}\r
\r
+ /**\r
+ * Set the number of tagged joints for allocation\r
+ * @param num\r
+ */\r
+ public void setNumTaggedJoints(int num)\r
+ {\r
+ // allocate space for joint data in the result keyframe\r
+ R.TaggedJointPos = new Vector3[num];\r
+ for(int i=0; i<num; i++)\r
+ R.TaggedJointPos[i] = new Vector3();\r
+ R.TaggedJoint = new Quaternion[num];\r
+ for(int i=0; i<num; i++)\r
+ R.TaggedJoint[i] = new Quaternion(0,0,0,0);\r
+ }\r
+ \r
@Override\r
protected void setInterpolationFrames() {\r
A = ((KeyframeAnimation)mCurrentAnim).mKeyframes[mCurrentFrameIdx];\r
B = ((KeyframeAnimation)mCurrentAnim).mKeyframes[mNextFrameIdx];\r
}\r
\r
+\r
+ static MD5Quaternion jointAOrient = new MD5Quaternion();\r
+ static MD5Quaternion jointBOrient = new MD5Quaternion();\r
+\r
//TODO: Optimise further if possible - this is the CPU bottleneck for animation\r
@Override\r
protected void interpolate()\r
}\r
}\r
R.IndicesSet = true;\r
+ \r
+ //interpolate any tagged joints\r
+ for(int tj = 0; tj<A.TaggedJoint.length; tj++)\r
+ {\r
+ //position\r
+ float PAX = A.TaggedJointPos[tj].x;\r
+ float PAY = A.TaggedJointPos[tj].y;\r
+ float PAZ = A.TaggedJointPos[tj].z;\r
+ float PBX = B.TaggedJointPos[tj].x;\r
+ float PBY = B.TaggedJointPos[tj].y;\r
+ float PBZ = B.TaggedJointPos[tj].z;\r
+\r
+ R.TaggedJointPos[tj].x = PAX + (PBX - PAX)*t;\r
+ R.TaggedJointPos[tj].y = PAY + (PBY - PAY)*t;\r
+ R.TaggedJointPos[tj].z = PAZ + (PBZ - PAZ)*t;\r
+ \r
+ //orientation\r
+ jointAOrient.x = A.TaggedJoint[tj].x;\r
+ jointAOrient.y = A.TaggedJoint[tj].y;\r
+ jointAOrient.z = A.TaggedJoint[tj].z;\r
+ jointAOrient.w = A.TaggedJoint[tj].w;\r
+ jointBOrient.x = B.TaggedJoint[tj].x;\r
+ jointBOrient.y = B.TaggedJoint[tj].y;\r
+ jointBOrient.z = B.TaggedJoint[tj].z;\r
+ jointBOrient.w = B.TaggedJoint[tj].w;\r
+ jointAOrient.slerp(jointBOrient, t);\r
+ R.TaggedJoint[tj].x = jointAOrient.x;\r
+ R.TaggedJoint[tj].y = jointAOrient.y;\r
+ R.TaggedJoint[tj].z = jointAOrient.z;\r
+ R.TaggedJoint[tj].w = jointAOrient.w;\r
+ }\r
}\r
\r
/**\r
\r
import java.io.DataInputStream;\r
import java.io.DataOutputStream;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
\r
import com.badlogic.gdx.graphics.GL10;\r
import com.badlogic.gdx.graphics.Material;\r
import com.badlogic.gdx.graphics.animation.Animator;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Animation;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Animator;\r
+import com.badlogic.gdx.graphics.loaders.md5.MD5Joints;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Model;\r
import com.badlogic.gdx.graphics.loaders.md5.MD5Renderer;\r
+import com.badlogic.gdx.math.Quaternion;\r
+import com.badlogic.gdx.math.Vector3;\r
import com.badlogic.gdx.utils.GdxRuntimeException;\r
import com.badlogic.gdx.utils.ObjectMap;\r
\r
private KeyframeAnimator mAnimator = null;\r
private Mesh[] mTarget = null;\r
private int mNumMeshes = 0;\r
+ private ArrayList<String> mTaggedJointNames = new ArrayList<String>();\r
\r
/**\r
* Gets the {@link KeyframeAnimator} for this model.\r
mMaterials[i] = mats[i];\r
}\r
}\r
+ \r
+ /**\r
+ * Sets the tagged joints for this model's animations. Tagged joints have their data preserved post-sampling.\r
+ * @param joints\r
+ * An array of joint names.\r
+ */\r
+ public void setTaggedJoints(ArrayList<String> joints)\r
+ {\r
+ mTaggedJointNames = joints;\r
+ }\r
\r
//TODO: Split this out to an MD5toKeyframe loader in com.badlogic.gdx.graphics.loaders\r
/**\r
Keyframe k = new Keyframe();\r
k.Vertices = new float[mNumMeshes][];\r
k.Indices = new short[mNumMeshes][];\r
+ if(mTaggedJointNames.size() > 0)\r
+ {\r
+ k.TaggedJointPos = new Vector3[mTaggedJointNames.size()];\r
+ k.TaggedJoint = new Quaternion[mTaggedJointNames.size()];\r
+ }\r
\r
for(int m=0; m<mNumMeshes; m++)\r
{\r
if(mTarget[m] == null)\r
{\r
mAnimator.setKeyframeDimensions(m, numVertices, numIndices);\r
+ mAnimator.setNumTaggedJoints(mTaggedJointNames.size());\r
\r
VertexAttributes attribs = renderer.getMesh().getVertexAttributes();\r
mTarget[m] = new Mesh(false, numVertices, numIndices, attribs);\r
}\r
}\r
\r
+ //store tagged joints.\r
+ MD5Joints skel = animator.getSkeleton();\r
+ for(int tj=0; tj<mTaggedJointNames.size(); tj++)\r
+ {\r
+ String name = mTaggedJointNames.get(tj);\r
+ for(int j=0; j<skel.numJoints; j++)\r
+ {\r
+ if(name.equals(skel.names[j]))\r
+ {\r
+ int idx = j*8;\r
+ float p = skel.joints[idx];\r
+ float x = skel.joints[idx+1];\r
+ float y = skel.joints[idx+2];\r
+ float z = skel.joints[idx+3];\r
+ k.TaggedJointPos[tj] = new Vector3(x, y, z);\r
+ float qx = skel.joints[idx+4];\r
+ float qy = skel.joints[idx+5];\r
+ float qz = skel.joints[idx+6];\r
+ float qw = skel.joints[idx+7];\r
+ k.TaggedJoint[tj] = new Quaternion(qx, qy, qz, qw);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
a.mKeyframes[i] = k;\r
\r
animator.update(sampleRate);\r
mAnimations.put(animKey, a);\r
}\r
\r
+ public void getJointData(int tagIndex, Vector3 pos, Quaternion orient)\r
+ {\r
+ Keyframe kf = mAnimator.getInterpolatedKeyframe();\r
+ pos.set(kf.TaggedJointPos[tagIndex]);\r
+ orient.x = kf.TaggedJoint[tagIndex].x;\r
+ orient.y = kf.TaggedJoint[tagIndex].y;\r
+ orient.z = kf.TaggedJoint[tagIndex].z;\r
+ orient.w = kf.TaggedJoint[tagIndex].w;\r
+ }\r
+ \r
/**\r
* Set the current playing animation.\r
* @param animKey\r