/SampleTOAPIA/MilkShapeViewer/MS3DModelAnimator.cs

https://github.com/Wiladams/NewTOAPIA · C# · 346 lines · 82 code · 45 blank · 219 comment · 8 complexity · 5d9f3001ea43f3ebc66623f03a32849d MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace MS3D
  5. {
  6. class MS3DModelAnimator
  7. {
  8. MS3DModel fModel;
  9. float m_currentTime;
  10. public MS3DModelAnimator(MS3DModel aModel)
  11. {
  12. fModel = aModel;
  13. }
  14. public float CurrentTime
  15. {
  16. get {return m_currentTime;}
  17. }
  18. public void SetFrame(float frame)
  19. {
  20. if (frame < 0.0f)
  21. {
  22. foreach (MS3DJoint joint in fModel.m_joints)
  23. {
  24. //memcpy(joint.matLocal, joint.matLocalSkeleton, sizeof(joint.matLocal));
  25. //memcpy(joint.matGlobal, joint.matGlobalSkeleton, sizeof(joint.matGlobal));
  26. joint.matLocalSkeleton = joint.matLocal;
  27. joint.matGlobalSkeleton = joint.matGlobal;
  28. }
  29. }
  30. else
  31. {
  32. foreach (MS3DJoint joint in fModel.m_joints)
  33. {
  34. EvaluateJoint(joint, frame);
  35. }
  36. }
  37. m_currentTime = frame;
  38. }
  39. public MS3DJoint FindJoint(string name)
  40. {
  41. foreach (MS3DJoint joint in fModel.m_joints)
  42. {
  43. if (string.Compare(joint.name, name) == 0)
  44. return joint;
  45. }
  46. return null;
  47. }
  48. public int FindJointIndex(string name)
  49. {
  50. for (int i = 0; i < fModel.m_joints.Count; i++ )
  51. {
  52. MS3DJoint joint = fModel.m_joints[i];
  53. if (string.Compare(joint.name, name) == 0)
  54. return i;
  55. }
  56. return -1;
  57. }
  58. public void SetupJoints()
  59. {
  60. foreach (MS3DJoint joint in fModel.m_joints)
  61. {
  62. joint.parentIndex = FindJointIndex(joint.parentName);
  63. }
  64. foreach (MS3DJoint joint in fModel.m_joints)
  65. {
  66. //MS3DMath.AngleMatrix(joint.fInitialRotation, ref joint.matLocalSkeleton);
  67. //joint.matLocalSkeleton[0][3] = joint.fInitialPosition[0];
  68. //joint.matLocalSkeleton[1][3] = joint.fInitialPosition[1];
  69. //joint.matLocalSkeleton[2][3] = joint.fInitialPosition[2];
  70. if (joint.parentIndex == -1)
  71. {
  72. //memcpy(joint.matGlobalSkeleton, joint.matLocalSkeleton, sizeof(joint.matGlobalSkeleton));
  73. joint.matLocalSkeleton = joint.matGlobalSkeleton;
  74. }
  75. else
  76. {
  77. MS3DJoint parentJoint = fModel.m_joints[joint.parentIndex];
  78. //MS3DMath.R_ConcatTransforms(parentJoint.matGlobalSkeleton, joint.matLocalSkeleton, joint.matGlobalSkeleton);
  79. }
  80. SetupTangents();
  81. }
  82. }
  83. void SetupTangents()
  84. {
  85. // for (int j = 0; j < m_joints.Count; j++)
  86. // {
  87. // MS3DJoint joint = m_joints[j];
  88. // int numPositionKeys = (int) joint.fPositionKeyframes.size();
  89. // joint.tangents.Capacity = numPositionKeys;
  90. // // clear all tangents (zero derivatives)
  91. // for (int k = 0; k < numPositionKeys; k++)
  92. // {
  93. // joint.tangents[k].tangentIn[0] = 0.0f;
  94. // joint.tangents[k].tangentIn[1] = 0.0f;
  95. // joint.tangents[k].tangentIn[2] = 0.0f;
  96. // joint.tangents[k].tangentOut[0] = 0.0f;
  97. // joint.tangents[k].tangentOut[1] = 0.0f;
  98. // joint.tangents[k].tangentOut[2] = 0.0f;
  99. // }
  100. // // if there are more than 2 keys, we can calculate tangents, otherwise we use zero derivatives
  101. // if (numPositionKeys > 2)
  102. // {
  103. // for (int k = 0; k < numPositionKeys; k++)
  104. // {
  105. // // make the curve tangents looped
  106. // int k0 = k - 1;
  107. // if (k0 < 0)
  108. // k0 = numPositionKeys - 1;
  109. // int k1 = k;
  110. // int k2 = k + 1;
  111. // if (k2 >= numPositionKeys)
  112. // k2 = 0;
  113. // // calculate the tangent, which is the vector from key[k - 1] to key[k + 1]
  114. // float3 tangent;
  115. // tangent[0] = (joint.fPositionKeyframes[k2].key[0] - joint.fPositionKeyframes[k0].key[0]);
  116. // tangent[1] = (joint.fPositionKeyframes[k2].key[1] - joint.fPositionKeyframes[k0].key[1]);
  117. // tangent[2] = (joint.fPositionKeyframes[k2].key[2] - joint.fPositionKeyframes[k0].key[2]);
  118. // // weight the incoming and outgoing tangent by their time to avoid changes in speed, if the keys are not within the same interval
  119. // float dt1 = joint.fPositionKeyframes[k1].time - joint.fPositionKeyframes[k0].time;
  120. // float dt2 = joint.fPositionKeyframes[k2].time - joint.fPositionKeyframes[k1].time;
  121. // float dt = dt1 + dt2;
  122. // joint.tangents[k1].tangentIn[0] = tangent[0] * dt1 / dt;
  123. // joint.tangents[k1].tangentIn[1] = tangent[1] * dt1 / dt;
  124. // joint.tangents[k1].tangentIn[2] = tangent[2] * dt1 / dt;
  125. // joint.tangents[k1].tangentOut[0] = tangent[0] * dt2 / dt;
  126. // joint.tangents[k1].tangentOut[1] = tangent[1] * dt2 / dt;
  127. // joint.tangents[k1].tangentOut[2] = tangent[2] * dt2 / dt;
  128. // }
  129. // }
  130. // }
  131. }
  132. void EvaluateJoint(MS3DJoint joint, float frame)
  133. {
  134. // MS3DJoint *joint = &m_joints[index];
  135. // //
  136. // // calculate joint animation matrix, this matrix will animate matLocalSkeleton
  137. // //
  138. // vec3_t fInitialPosition = { 0.0f, 0.0f, 0.0f };
  139. // int numPositionKeys = (int) joint.fPositionKeyframes.size();
  140. // if (numPositionKeys > 0)
  141. // {
  142. // int i1 = -1;
  143. // int i2 = -1;
  144. // // find the two keys, where "frame" is in between for the position channel
  145. // for (int i = 0; i < (numPositionKeys - 1); i++)
  146. // {
  147. // if (frame >= joint.fPositionKeyframes[i].time && frame < joint.fPositionKeyframes[i + 1].time)
  148. // {
  149. // i1 = i;
  150. // i2 = i + 1;
  151. // break;
  152. // }
  153. // }
  154. // // if there are no such keys
  155. // if (i1 == -1 || i2 == -1)
  156. // {
  157. // // either take the first
  158. // if (frame < joint.fPositionKeyframes[0].time)
  159. // {
  160. // fInitialPosition[0] = joint.fPositionKeyframes[0].key[0];
  161. // fInitialPosition[1] = joint.fPositionKeyframes[0].key[1];
  162. // fInitialPosition[2] = joint.fPositionKeyframes[0].key[2];
  163. // }
  164. // // or the last key
  165. // else if (frame >= joint.fPositionKeyframes[numPositionKeys - 1].time)
  166. // {
  167. // fInitialPosition[0] = joint.fPositionKeyframes[numPositionKeys - 1].key[0];
  168. // fInitialPosition[1] = joint.fPositionKeyframes[numPositionKeys - 1].key[1];
  169. // fInitialPosition[2] = joint.fPositionKeyframes[numPositionKeys - 1].key[2];
  170. // }
  171. // }
  172. // // there are such keys, so interpolate using hermite interpolation
  173. // else
  174. // {
  175. // M3DKeyframe *p0 = &joint.fPositionKeyframes[i1];
  176. // M3DKeyframe *p1 = &joint.fPositionKeyframes[i2];
  177. // M3DTangent *m0 = &joint.tangents[i1];
  178. // M3DTangent *m1 = &joint.tangents[i2];
  179. // // normalize the time between the keys into [0..1]
  180. // float t = (frame - joint.fPositionKeyframes[i1].time) / (joint.fPositionKeyframes[i2].time - joint.fPositionKeyframes[i1].time);
  181. // float t2 = t * t;
  182. // float t3 = t2 * t;
  183. // // calculate hermite basis
  184. // float h1 = 2.0f * t3 - 3.0f * t2 + 1.0f;
  185. // float h2 = -2.0f * t3 + 3.0f * t2;
  186. // float h3 = t3 - 2.0f * t2 + t;
  187. // float h4 = t3 - t2;
  188. // // do hermite interpolation
  189. // fInitialPosition[0] = h1 * p0.key[0] + h3 * m0.tangentOut[0] + h2 * p1.key[0] + h4 * m1.tangentIn[0];
  190. // fInitialPosition[1] = h1 * p0.key[1] + h3 * m0.tangentOut[1] + h2 * p1.key[1] + h4 * m1.tangentIn[1];
  191. // fInitialPosition[2] = h1 * p0.key[2] + h3 * m0.tangentOut[2] + h2 * p1.key[2] + h4 * m1.tangentIn[2];
  192. // }
  193. // }
  194. // vec4_t quat = { 0.0f, 0.0f, 0.0f, 1.0f };
  195. // int numRotationKeys = (int) joint.rotationKeys.size();
  196. // if (numRotationKeys > 0)
  197. // {
  198. // int i1 = -1;
  199. // int i2 = -1;
  200. // // find the two keys, where "frame" is in between for the rotation channel
  201. // for (int i = 0; i < (numRotationKeys - 1); i++)
  202. // {
  203. // if (frame >= joint.rotationKeys[i].time && frame < joint.rotationKeys[i + 1].time)
  204. // {
  205. // i1 = i;
  206. // i2 = i + 1;
  207. // break;
  208. // }
  209. // }
  210. // // if there are no such keys
  211. // if (i1 == -1 || i2 == -1)
  212. // {
  213. // // either take the first key
  214. // if (frame < joint.rotationKeys[0].time)
  215. // {
  216. // AngleQuaternion(joint.rotationKeys[0].key, quat);
  217. // }
  218. // // or the last key
  219. // else if (frame >= joint.rotationKeys[numRotationKeys - 1].time)
  220. // {
  221. // AngleQuaternion(joint.rotationKeys[numRotationKeys - 1].key, quat);
  222. // }
  223. // }
  224. // // there are such keys, so do the quaternion slerp interpolation
  225. // else
  226. // {
  227. // float t = (frame - joint.rotationKeys[i1].time) / (joint.rotationKeys[i2].time - joint.rotationKeys[i1].time);
  228. // vec4_t q1;
  229. // AngleQuaternion(joint.rotationKeys[i1].key, q1);
  230. // vec4_t q2;
  231. // AngleQuaternion(joint.rotationKeys[i2].key, q2);
  232. // QuaternionSlerp(q1, q2, t, quat);
  233. // }
  234. // }
  235. // // make a matrix from fInitialPosition/quat
  236. // float matAnimate[3][4];
  237. // QuaternionMatrix(quat, matAnimate);
  238. // matAnimate[0][3] = fInitialPosition[0];
  239. // matAnimate[1][3] = fInitialPosition[1];
  240. // matAnimate[2][3] = fInitialPosition[2];
  241. // // animate the local joint matrix using: matLocal = matLocalSkeleton * matAnimate
  242. // R_ConcatTransforms(joint.matLocalSkeleton, matAnimate, joint.matLocal);
  243. // // build up the hierarchy if joints
  244. // // matGlobal = matGlobal(parent) * matLocal
  245. // if (joint.parentIndex == -1)
  246. // {
  247. // memcpy(joint.matGlobal, joint.matLocal, sizeof(joint.matGlobal));
  248. // }
  249. // else
  250. // {
  251. // MS3DJoint *parentJoint = &m_joints[joint.parentIndex];
  252. // R_ConcatTransforms(parentJoint.matGlobal, joint.matLocal, joint.matGlobal);
  253. // }
  254. //}
  255. // void TransformVertex(MS3DVertex vertex, float3 vout)
  256. // {
  257. // int [] jointIndices = new int[4];
  258. // int [] jointWeights = new int[4];
  259. // FillJointIndicesAndWeights(vertex, jointIndices, jointWeights);
  260. // if (jointIndices[0] < 0 || jointIndices[0] >= (int) m_joints.size() || m_currentTime < 0.0f)
  261. // {
  262. // vout[0] = vertex.vertex[0];
  263. // vout[1] = vertex.vertex[1];
  264. // vout[2] = vertex.vertex[2];
  265. // }
  266. // else
  267. // {
  268. // // count valid weights
  269. // int numWeights = 0;
  270. // for (int i = 0; i < 4; i++)
  271. // {
  272. // if (jointWeights[i] > 0 && jointIndices[i] >= 0 && jointIndices[i] < (int) m_joints.size())
  273. // ++numWeights;
  274. // else
  275. // break;
  276. // }
  277. // // init
  278. // vout[0] = 0.0f;
  279. // vout[1] = 0.0f;
  280. // vout[2] = 0.0f;
  281. // float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f };
  282. // if (numWeights == 0)
  283. // {
  284. // numWeights = 1;
  285. // weights[0] = 1.0f;
  286. // }
  287. // // add weighted vertices
  288. // for (int i = 0; i < numWeights; i++)
  289. // {
  290. // const MS3DJoint *joint = &m_joints[jointIndices[i]];
  291. // vec3_t tmp, vert;
  292. // VectorITransform(vertex.vertex, joint.matGlobalSkeleton, tmp);
  293. // VectorTransform(tmp, joint.matGlobal, vert);
  294. // vout[0] += vert[0] * weights[i];
  295. // vout[1] += vert[1] * weights[i];
  296. // vout[2] += vert[2] * weights[i];
  297. // }
  298. // }
  299. }
  300. }
  301. }