msModel.cpp.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. ///////////////////////////////////////////////////////////////////////
  2. // title: MilkShape 3D Model Viewer Sample
  3. //
  4. // copyright: The programs and associated files contained in this
  5. // distribution were developed by Mete Ciragan. The
  6. // programs are not in the public domain, but they are
  7. // freely distributable without licensing fees. These
  8. // programs are provided without guarantee or warrantee
  9. // expressed or implied. Use at your own risk!
  10. //
  11. // email: [email protected]
  12. // web: http://www.milkshape3d.com
  13. ///////////////////////////////////////////////////////////////////////
  14. #include "msModel.h"
  15. #include "mathlib.h"
  16. msModel::msModel()
  17. {
  18. Clear();
  19. }
  20. msModel::~msModel()
  21. {
  22. Clear();
  23. }
  24. bool msModel::Load(C Str &filename)
  25. {
  26. #if WINDOWS
  27. FILE *fp = _wfopen(filename, L"rb");
  28. #else
  29. FILE *fp = fopen(UnixPathUTF8(filename), "r");
  30. #endif
  31. if (!fp)
  32. return false;
  33. Clear();
  34. fseek(fp, 0, SEEK_END);
  35. long fileSize = ftell(fp);
  36. fseek(fp, 0, SEEK_SET);
  37. char id[10];
  38. fread(id, sizeof(char), 10, fp);
  39. if (strncmp(id, "MS3D000000", 10) != 0)
  40. {
  41. fclose(fp);
  42. // "This is not a valid MS3D file format!"
  43. return false;
  44. }
  45. int version;
  46. fread(&version, sizeof(int), 1, fp);
  47. if (version != 4)
  48. {
  49. fclose(fp);
  50. // "This is not a valid MS3D file version!"
  51. return false;
  52. }
  53. int i, j;
  54. // vertices
  55. unsigned short numVertices;
  56. fread(&numVertices, sizeof(unsigned short), 1, fp);
  57. m_vertices.resize(numVertices);
  58. for (i = 0; i < numVertices; i++)
  59. {
  60. fread(&m_vertices[i].flags, sizeof(unsigned char), 1, fp);
  61. fread(&m_vertices[i].vertex, sizeof(float), 3, fp);
  62. fread(&m_vertices[i].boneId, sizeof(char), 1, fp);
  63. fread(&m_vertices[i].referenceCount, sizeof(unsigned char), 1, fp);
  64. }
  65. // triangles
  66. unsigned short numTriangles;
  67. fread(&numTriangles, sizeof(unsigned short), 1, fp);
  68. m_triangles.resize(numTriangles);
  69. for (i = 0; i < numTriangles; i++)
  70. {
  71. fread(&m_triangles[i].flags, sizeof(unsigned short), 1, fp);
  72. fread(m_triangles[i].vertexIndices, sizeof(unsigned short), 3, fp);
  73. fread(m_triangles[i].vertexNormals, sizeof(float), 3 * 3, fp);
  74. fread(m_triangles[i].s, sizeof(float), 3, fp);
  75. fread(m_triangles[i].t, sizeof(float), 3, fp);
  76. fread(&m_triangles[i].smoothingGroup, sizeof(unsigned char), 1, fp);
  77. fread(&m_triangles[i].groupIndex, sizeof(unsigned char), 1, fp);
  78. // TODO: calculate triangle normal
  79. }
  80. // groups
  81. unsigned short numGroups;
  82. fread(&numGroups, sizeof(unsigned short), 1, fp);
  83. m_groups.resize(numGroups);
  84. for (i = 0; i < numGroups; i++)
  85. {
  86. fread(&m_groups[i].flags, sizeof(unsigned char), 1, fp);
  87. fread(m_groups[i].name, sizeof(char), 32, fp);
  88. unsigned short numGroupTriangles;
  89. fread(&numGroupTriangles, sizeof(unsigned short), 1, fp);
  90. m_groups[i].triangleIndices.resize(numGroupTriangles);
  91. if (numGroupTriangles > 0)
  92. fread(&m_groups[i].triangleIndices[0], sizeof(unsigned short), numGroupTriangles, fp);
  93. fread(&m_groups[i].materialIndex, sizeof(char), 1, fp);
  94. }
  95. // materials
  96. unsigned short numMaterials;
  97. fread(&numMaterials, sizeof(unsigned short), 1, fp);
  98. m_materials.resize(numMaterials);
  99. for (i = 0; i < numMaterials; i++)
  100. {
  101. fread(m_materials[i].name, sizeof(char), 32, fp);
  102. fread(&m_materials[i].ambient, sizeof(float), 4, fp);
  103. fread(&m_materials[i].diffuse, sizeof(float), 4, fp);
  104. fread(&m_materials[i].specular, sizeof(float), 4, fp);
  105. fread(&m_materials[i].emissive, sizeof(float), 4, fp);
  106. fread(&m_materials[i].shininess, sizeof(float), 1, fp);
  107. fread(&m_materials[i].transparency, sizeof(float), 1, fp);
  108. fread(&m_materials[i].mode, sizeof(unsigned char), 1, fp);
  109. fread(m_materials[i].texture, sizeof(char), MAX_TEXTURE_FILENAME_SIZE, fp);
  110. fread(m_materials[i].alphamap, sizeof(char), MAX_TEXTURE_FILENAME_SIZE, fp);
  111. // set alpha
  112. m_materials[i].ambient[3] = m_materials[i].transparency;
  113. m_materials[i].diffuse[3] = m_materials[i].transparency;
  114. m_materials[i].specular[3] = m_materials[i].transparency;
  115. m_materials[i].emissive[3] = m_materials[i].transparency;
  116. }
  117. // animation
  118. fread(&m_animationFps, sizeof(float), 1, fp);
  119. if (m_animationFps < 1.0f)
  120. m_animationFps = 1.0f;
  121. fread(&m_currentTime, sizeof(float), 1, fp);
  122. fread(&m_totalFrames, sizeof(int), 1, fp);
  123. // joints
  124. unsigned short numJoints;
  125. fread(&numJoints, sizeof(unsigned short), 1, fp);
  126. m_joints.resize(numJoints);
  127. for (i = 0; i < numJoints; i++)
  128. {
  129. fread(&m_joints[i].flags, sizeof(unsigned char), 1, fp);
  130. fread(m_joints[i].name, sizeof(char), 32, fp);
  131. fread(m_joints[i].parentName, sizeof(char), 32, fp);
  132. fread(m_joints[i].rot, sizeof(float), 3, fp);
  133. fread(m_joints[i].pos, sizeof(float), 3, fp);
  134. unsigned short numKeyFramesRot;
  135. fread(&numKeyFramesRot, sizeof(unsigned short), 1, fp);
  136. m_joints[i].rotationKeys.resize(numKeyFramesRot);
  137. unsigned short numKeyFramesPos;
  138. fread(&numKeyFramesPos, sizeof(unsigned short), 1, fp);
  139. m_joints[i].positionKeys.resize(numKeyFramesPos);
  140. // the frame time is in seconds, so multiply it by the animation fps, to get the frames
  141. // rotation channel
  142. for (j = 0; j < numKeyFramesRot; j++)
  143. {
  144. fread(&m_joints[i].rotationKeys[j].time, sizeof(float), 1, fp);
  145. fread(&m_joints[i].rotationKeys[j].key, sizeof(float), 3, fp);
  146. m_joints[i].rotationKeys[j].time *= m_animationFps;
  147. }
  148. // translation channel
  149. for (j = 0; j < numKeyFramesPos; j++)
  150. {
  151. fread(&m_joints[i].positionKeys[j].time, sizeof(float), 1, fp);
  152. fread(&m_joints[i].positionKeys[j].key, sizeof(float), 3, fp);
  153. m_joints[i].positionKeys[j].time *= m_animationFps;
  154. }
  155. }
  156. // comments
  157. long filePos = ftell(fp);
  158. if (filePos < fileSize)
  159. {
  160. int subVersion = 0;
  161. fread(&subVersion, sizeof(int), 1, fp);
  162. if (subVersion == 1)
  163. {
  164. int numComments = 0;
  165. size_t commentSize = 0;
  166. // group comments
  167. fread(&numComments, sizeof(int), 1, fp);
  168. for (i = 0; i < numComments; i++)
  169. {
  170. int index;
  171. fread(&index, sizeof(int), 1, fp);
  172. std__vector<char> comment;
  173. fread(&commentSize, sizeof(size_t), 1, fp);
  174. comment.resize(commentSize);
  175. if (commentSize > 0)
  176. fread(&comment[0], sizeof(char), commentSize, fp);
  177. if (index >= 0 && index < (int) m_groups.size())
  178. m_groups[index].comment = comment;
  179. }
  180. // material comments
  181. fread(&numComments, sizeof(int), 1, fp);
  182. for (i = 0; i < numComments; i++)
  183. {
  184. int index;
  185. fread(&index, sizeof(int), 1, fp);
  186. std__vector<char> comment;
  187. fread(&commentSize, sizeof(size_t), 1, fp);
  188. comment.resize(commentSize);
  189. if (commentSize > 0)
  190. fread(&comment[0], sizeof(char), commentSize, fp);
  191. if (index >= 0 && index < (int) m_materials.size())
  192. m_materials[index].comment = comment;
  193. }
  194. // joint comments
  195. fread(&numComments, sizeof(int), 1, fp);
  196. for (i = 0; i < numComments; i++)
  197. {
  198. int index;
  199. fread(&index, sizeof(int), 1, fp);
  200. std__vector<char> comment;
  201. fread(&commentSize, sizeof(size_t), 1, fp);
  202. comment.resize(commentSize);
  203. if (commentSize > 0)
  204. fread(&comment[0], sizeof(char), commentSize, fp);
  205. if (index >= 0 && index < (int) m_joints.size())
  206. m_joints[index].comment = comment;
  207. }
  208. // model comments
  209. fread(&numComments, sizeof(int), 1, fp);
  210. if (numComments == 1)
  211. {
  212. std__vector<char> comment;
  213. fread(&commentSize, sizeof(size_t), 1, fp);
  214. comment.resize(commentSize);
  215. if (commentSize > 0)
  216. fread(&comment[0], sizeof(char), commentSize, fp);
  217. m_comment = comment;
  218. }
  219. }
  220. else
  221. {
  222. // "Unknown subversion for comments %d\n", subVersion);
  223. }
  224. }
  225. // vertex extra
  226. filePos = ftell(fp);
  227. if (filePos < fileSize)
  228. {
  229. int subVersion = 0;
  230. fread(&subVersion, sizeof(int), 1, fp);
  231. if (subVersion == 2)
  232. {
  233. for (int i = 0; i < numVertices; i++)
  234. {
  235. fread(&m_vertices[i].boneIds[0], sizeof(char), 3, fp);
  236. fread(&m_vertices[i].weights[0], sizeof(unsigned char), 3, fp);
  237. fread(&m_vertices[i].extra, sizeof(unsigned int), 1, fp);
  238. }
  239. }
  240. else if (subVersion == 1)
  241. {
  242. for (int i = 0; i < numVertices; i++)
  243. {
  244. fread(&m_vertices[i].boneIds[0], sizeof(char), 3, fp);
  245. fread(&m_vertices[i].weights[0], sizeof(unsigned char), 3, fp);
  246. }
  247. }
  248. else
  249. {
  250. // "Unknown subversion for vertex extra %d\n", subVersion);
  251. }
  252. }
  253. // joint extra
  254. filePos = ftell(fp);
  255. if (filePos < fileSize)
  256. {
  257. int subVersion = 0;
  258. fread(&subVersion, sizeof(int), 1, fp);
  259. if (subVersion == 1)
  260. {
  261. for (int i = 0; i < numJoints; i++)
  262. {
  263. fread(&m_joints[i].color, sizeof(float), 3, fp);
  264. }
  265. }
  266. else
  267. {
  268. // "Unknown subversion for joint extra %d\n", subVersion);
  269. }
  270. }
  271. // model extra
  272. filePos = ftell(fp);
  273. if (filePos < fileSize)
  274. {
  275. int subVersion = 0;
  276. fread(&subVersion, sizeof(int), 1, fp);
  277. if (subVersion == 1)
  278. {
  279. fread(&m_jointSize, sizeof(float), 1, fp);
  280. fread(&m_transparencyMode, sizeof(int), 1, fp);
  281. fread(&m_alphaRef, sizeof(float), 1, fp);
  282. }
  283. else
  284. {
  285. //"Unknown subversion for model extra %d\n", subVersion);
  286. }
  287. }
  288. fclose(fp);
  289. return true;
  290. }
  291. void msModel::Clear()
  292. {
  293. m_vertices.clear();
  294. m_triangles.clear();
  295. m_groups.clear();
  296. m_materials.clear();
  297. m_animationFps = 24.0f;
  298. m_currentTime = 1.0f;
  299. m_totalFrames = 30;
  300. m_joints.clear();
  301. m_comment.clear();
  302. m_jointSize = 1.0f;
  303. m_transparencyMode = TRANSPARENCY_MODE_SIMPLE;
  304. m_alphaRef = 0.5f;
  305. }
  306. int msModel::GetNumGroups() const
  307. {
  308. return (int) m_groups.size();
  309. }
  310. ms3d_group_t *msModel::GetGroup(int index)
  311. {
  312. return &m_groups[index];
  313. }
  314. int msModel::GetNumTriangles() const
  315. {
  316. return (int) m_triangles.size();
  317. }
  318. ms3d_triangle_t *msModel::GetTriangle(int index)
  319. {
  320. return &m_triangles[index];
  321. }
  322. int msModel::GetNumVertices() const
  323. {
  324. return (int) m_vertices.size();
  325. }
  326. ms3d_vertex_t *msModel::GetVertex(int index)
  327. {
  328. return &m_vertices[index];
  329. }
  330. int msModel::GetNumMaterials() const
  331. {
  332. return (int) m_materials.size();
  333. }
  334. ms3d_material_t *msModel::GetMaterial(int index)
  335. {
  336. return &m_materials[index];
  337. }
  338. int msModel::GetNumJoints() const
  339. {
  340. return (int) m_joints.size();
  341. }
  342. ms3d_joint_t *msModel::GetJoint(int index)
  343. {
  344. return &m_joints[index];
  345. }
  346. float msModel::GetJointSize() const
  347. {
  348. return m_jointSize;
  349. }
  350. int msModel::GetTransparencyMode() const
  351. {
  352. return m_transparencyMode;
  353. }
  354. float msModel::GetAlphaRef() const
  355. {
  356. return m_alphaRef;
  357. }
  358. int msModel::FindJointByName(const char *name)
  359. {
  360. for (size_t i = 0; i < m_joints.size(); i++)
  361. {
  362. if (strcmp(m_joints[i].name, name) == 0)
  363. return i;
  364. }
  365. return -1;
  366. }
  367. void msModel::SetupJoints(bool set_tangents)
  368. {
  369. for (size_t i = 0; i < m_joints.size(); i++)
  370. {
  371. ms3d_joint_t *joint = &m_joints[i];
  372. joint->parentIndex = FindJointByName(joint->parentName);
  373. }
  374. for (size_t i = 0; i < m_joints.size(); i++)
  375. {
  376. ms3d_joint_t *joint = &m_joints[i];
  377. AngleMatrix(joint->rot, joint->matLocalSkeleton);
  378. joint->matLocalSkeleton[0][3]= joint->pos[0];
  379. joint->matLocalSkeleton[1][3]= joint->pos[1];
  380. joint->matLocalSkeleton[2][3]= joint->pos[2];
  381. if (joint->parentIndex == -1)
  382. {
  383. memcpy(joint->matGlobalSkeleton, joint->matLocalSkeleton, sizeof(joint->matGlobalSkeleton));
  384. }
  385. else
  386. {
  387. ms3d_joint_t *parentJoint = &m_joints[joint->parentIndex];
  388. R_ConcatTransforms(parentJoint->matGlobalSkeleton, joint->matLocalSkeleton, joint->matGlobalSkeleton);
  389. }
  390. if(set_tangents)SetupTangents();
  391. }
  392. }
  393. void msModel::SetupTangents()
  394. {
  395. for (size_t j = 0; j < m_joints.size(); j++)
  396. {
  397. ms3d_joint_t *joint = &m_joints[j];
  398. int numPositionKeys = (int) joint->positionKeys.size();
  399. joint->tangents.resize(numPositionKeys);
  400. // clear all tangents (zero derivatives)
  401. for (int k = 0; k < numPositionKeys; k++)
  402. {
  403. joint->tangents[k].tangentIn[0] = 0.0f;
  404. joint->tangents[k].tangentIn[1] = 0.0f;
  405. joint->tangents[k].tangentIn[2] = 0.0f;
  406. joint->tangents[k].tangentOut[0] = 0.0f;
  407. joint->tangents[k].tangentOut[1] = 0.0f;
  408. joint->tangents[k].tangentOut[2] = 0.0f;
  409. }
  410. // if there are more than 2 keys, we can calculate tangents, otherwise we use zero derivatives
  411. if (numPositionKeys > 2)
  412. {
  413. for (int k = 0; k < numPositionKeys; k++)
  414. {
  415. // make the curve tangents looped
  416. int k0 = k - 1;
  417. if (k0 < 0)
  418. k0 = numPositionKeys - 1;
  419. int k1 = k;
  420. int k2 = k + 1;
  421. if (k2 >= numPositionKeys)
  422. k2 = 0;
  423. // calculate the tangent, which is the vector from key[k - 1] to key[k + 1]
  424. float tangent[3];
  425. tangent[0] = (joint->positionKeys[k2].key[0] - joint->positionKeys[k0].key[0]);
  426. tangent[1] = (joint->positionKeys[k2].key[1] - joint->positionKeys[k0].key[1]);
  427. tangent[2] = (joint->positionKeys[k2].key[2] - joint->positionKeys[k0].key[2]);
  428. // weight the incoming and outgoing tangent by their time to avoid changes in speed, if the keys are not within the same interval
  429. float dt1 = joint->positionKeys[k1].time - joint->positionKeys[k0].time;
  430. float dt2 = joint->positionKeys[k2].time - joint->positionKeys[k1].time;
  431. float dt = dt1 + dt2;
  432. joint->tangents[k1].tangentIn[0] = tangent[0] * dt1 / dt;
  433. joint->tangents[k1].tangentIn[1] = tangent[1] * dt1 / dt;
  434. joint->tangents[k1].tangentIn[2] = tangent[2] * dt1 / dt;
  435. joint->tangents[k1].tangentOut[0] = tangent[0] * dt2 / dt;
  436. joint->tangents[k1].tangentOut[1] = tangent[1] * dt2 / dt;
  437. joint->tangents[k1].tangentOut[2] = tangent[2] * dt2 / dt;
  438. }
  439. }
  440. }
  441. }
  442. void msModel::SetFrame(float frame)
  443. {
  444. if (frame < 0.0f)
  445. {
  446. for (size_t i = 0; i < m_joints.size(); i++)
  447. {
  448. ms3d_joint_t *joint = &m_joints[i];
  449. memcpy(joint->matLocal, joint->matLocalSkeleton, sizeof(joint->matLocal));
  450. memcpy(joint->matGlobal, joint->matGlobalSkeleton, sizeof(joint->matGlobal));
  451. }
  452. }
  453. else
  454. {
  455. for (size_t i = 0; i < m_joints.size(); i++)
  456. {
  457. EvaluateJoint(i, frame);
  458. }
  459. }
  460. m_currentTime = frame;
  461. }
  462. void msModel::EvaluateJoint(int index, float frame)
  463. {
  464. ms3d_joint_t *joint = &m_joints[index];
  465. //
  466. // calculate joint animation matrix, this matrix will animate matLocalSkeleton
  467. //
  468. vec3_t pos = { 0.0f, 0.0f, 0.0f };
  469. int numPositionKeys = (int) joint->positionKeys.size();
  470. if (numPositionKeys > 0)
  471. {
  472. int i1 = -1;
  473. int i2 = -1;
  474. // find the two keys, where "frame" is in between for the position channel
  475. for (int i = 0; i < (numPositionKeys - 1); i++)
  476. {
  477. if (frame >= joint->positionKeys[i].time && frame < joint->positionKeys[i + 1].time)
  478. {
  479. i1 = i;
  480. i2 = i + 1;
  481. break;
  482. }
  483. }
  484. // if there are no such keys
  485. if (i1 == -1 || i2 == -1)
  486. {
  487. // either take the first
  488. if (frame < joint->positionKeys[0].time)
  489. {
  490. pos[0] = joint->positionKeys[0].key[0];
  491. pos[1] = joint->positionKeys[0].key[1];
  492. pos[2] = joint->positionKeys[0].key[2];
  493. }
  494. // or the last key
  495. else if (frame >= joint->positionKeys[numPositionKeys - 1].time)
  496. {
  497. pos[0] = joint->positionKeys[numPositionKeys - 1].key[0];
  498. pos[1] = joint->positionKeys[numPositionKeys - 1].key[1];
  499. pos[2] = joint->positionKeys[numPositionKeys - 1].key[2];
  500. }
  501. }
  502. // there are such keys, so interpolate using hermite interpolation
  503. else
  504. {
  505. ms3d_keyframe_t *p0 = &joint->positionKeys[i1];
  506. ms3d_keyframe_t *p1 = &joint->positionKeys[i2];
  507. ms3d_tangent_t *m0 = &joint->tangents[i1];
  508. ms3d_tangent_t *m1 = &joint->tangents[i2];
  509. // normalize the time between the keys into [0..1]
  510. float t = (frame - joint->positionKeys[i1].time) / (joint->positionKeys[i2].time - joint->positionKeys[i1].time);
  511. float t2 = t * t;
  512. float t3 = t2 * t;
  513. // calculate hermite basis
  514. float h1 = 2.0f * t3 - 3.0f * t2 + 1.0f;
  515. float h2 = -2.0f * t3 + 3.0f * t2;
  516. float h3 = t3 - 2.0f * t2 + t;
  517. float h4 = t3 - t2;
  518. // do hermite interpolation
  519. pos[0] = h1 * p0->key[0] + h3 * m0->tangentOut[0] + h2 * p1->key[0] + h4 * m1->tangentIn[0];
  520. pos[1] = h1 * p0->key[1] + h3 * m0->tangentOut[1] + h2 * p1->key[1] + h4 * m1->tangentIn[1];
  521. pos[2] = h1 * p0->key[2] + h3 * m0->tangentOut[2] + h2 * p1->key[2] + h4 * m1->tangentIn[2];
  522. }
  523. }
  524. vec4_t quat = { 0.0f, 0.0f, 0.0f, 1.0f };
  525. int numRotationKeys = (int) joint->rotationKeys.size();
  526. if (numRotationKeys > 0)
  527. {
  528. int i1 = -1;
  529. int i2 = -1;
  530. // find the two keys, where "frame" is in between for the rotation channel
  531. for (int i = 0; i < (numRotationKeys - 1); i++)
  532. {
  533. if (frame >= joint->rotationKeys[i].time && frame < joint->rotationKeys[i + 1].time)
  534. {
  535. i1 = i;
  536. i2 = i + 1;
  537. break;
  538. }
  539. }
  540. // if there are no such keys
  541. if (i1 == -1 || i2 == -1)
  542. {
  543. // either take the first key
  544. if (frame < joint->rotationKeys[0].time)
  545. {
  546. AngleQuaternion(joint->rotationKeys[0].key, quat);
  547. }
  548. // or the last key
  549. else if (frame >= joint->rotationKeys[numRotationKeys - 1].time)
  550. {
  551. AngleQuaternion(joint->rotationKeys[numRotationKeys - 1].key, quat);
  552. }
  553. }
  554. // there are such keys, so do the quaternion slerp interpolation
  555. else
  556. {
  557. float t = (frame - joint->rotationKeys[i1].time) / (joint->rotationKeys[i2].time - joint->rotationKeys[i1].time);
  558. vec4_t q1;
  559. AngleQuaternion(joint->rotationKeys[i1].key, q1);
  560. vec4_t q2;
  561. AngleQuaternion(joint->rotationKeys[i2].key, q2);
  562. QuaternionSlerp(q1, q2, t, quat);
  563. }
  564. }
  565. // make a matrix from pos/quat
  566. float matAnimate[3][4];
  567. QuaternionMatrix(quat, matAnimate);
  568. matAnimate[0][3] = pos[0];
  569. matAnimate[1][3] = pos[1];
  570. matAnimate[2][3] = pos[2];
  571. // animate the local joint matrix using: matLocal = matLocalSkeleton * matAnimate
  572. R_ConcatTransforms(joint->matLocalSkeleton, matAnimate, joint->matLocal);
  573. // build up the hierarchy if joints
  574. // matGlobal = matGlobal(parent) * matLocal
  575. if (joint->parentIndex == -1)
  576. {
  577. memcpy(joint->matGlobal, joint->matLocal, sizeof(joint->matGlobal));
  578. }
  579. else
  580. {
  581. ms3d_joint_t *parentJoint = &m_joints[joint->parentIndex];
  582. R_ConcatTransforms(parentJoint->matGlobal, joint->matLocal, joint->matGlobal);
  583. }
  584. }
  585. float msModel::GetAnimationFps() const
  586. {
  587. return m_animationFps;
  588. }
  589. float msModel::GetCurrentFrame() const
  590. {
  591. return m_currentTime;
  592. }
  593. int msModel::GetTotalFrames() const
  594. {
  595. return m_totalFrames;
  596. }
  597. void msModel::TransformVertex(const ms3d_vertex_t *vertex, vec3_t out) const
  598. {
  599. int jointIndices[4], jointWeights[4];
  600. FillJointIndicesAndWeights(vertex, jointIndices, jointWeights);
  601. if (jointIndices[0] < 0 || jointIndices[0] >= (int) m_joints.size() || m_currentTime < 0.0f)
  602. {
  603. out[0] = vertex->vertex[0];
  604. out[1] = vertex->vertex[1];
  605. out[2] = vertex->vertex[2];
  606. }
  607. else
  608. {
  609. // count valid weights
  610. int numWeights = 0;
  611. for (int i = 0; i < 4; i++)
  612. {
  613. if (jointWeights[i] > 0 && jointIndices[i] >= 0 && jointIndices[i] < (int) m_joints.size())
  614. ++numWeights;
  615. else
  616. break;
  617. }
  618. // init
  619. out[0] = 0.0f;
  620. out[1] = 0.0f;
  621. out[2] = 0.0f;
  622. float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f };
  623. if (numWeights == 0)
  624. {
  625. numWeights = 1;
  626. weights[0] = 1.0f;
  627. }
  628. // add weighted vertices
  629. for (int i = 0; i < numWeights; i++)
  630. {
  631. const ms3d_joint_t *joint = &m_joints[jointIndices[i]];
  632. vec3_t tmp, vert;
  633. VectorITransform(vertex->vertex, joint->matGlobalSkeleton, tmp);
  634. VectorTransform(tmp, joint->matGlobal, vert);
  635. out[0] += vert[0] * weights[i];
  636. out[1] += vert[1] * weights[i];
  637. out[2] += vert[2] * weights[i];
  638. }
  639. }
  640. }
  641. void msModel::TransformNormal(const ms3d_vertex_t *vertex, const vec3_t normal, vec3_t out) const
  642. {
  643. int jointIndices[4], jointWeights[4];
  644. FillJointIndicesAndWeights(vertex, jointIndices, jointWeights);
  645. if (jointIndices[0] < 0 || jointIndices[0] >= (int) m_joints.size() || m_currentTime < 0.0f)
  646. {
  647. out[0] = normal[0];
  648. out[1] = normal[1];
  649. out[2] = normal[2];
  650. }
  651. else
  652. {
  653. // count valid weights
  654. int numWeights = 0;
  655. for (int i = 0; i < 4; i++)
  656. {
  657. if (jointWeights[i] > 0 && jointIndices[i] >= 0 && jointIndices[i] < (int) m_joints.size())
  658. ++numWeights;
  659. else
  660. break;
  661. }
  662. // init
  663. out[0] = 0.0f;
  664. out[1] = 0.0f;
  665. out[2] = 0.0f;
  666. float weights[4] = { (float) jointWeights[0] / 100.0f, (float) jointWeights[1] / 100.0f, (float) jointWeights[2] / 100.0f, (float) jointWeights[3] / 100.0f };
  667. if (numWeights == 0)
  668. {
  669. numWeights = 1;
  670. weights[0] = 1.0f;
  671. }
  672. // add weighted vertices
  673. for (int i = 0; i < numWeights; i++)
  674. {
  675. const ms3d_joint_t *joint = &m_joints[jointIndices[i]];
  676. vec3_t tmp, norm;
  677. VectorIRotate(normal, joint->matGlobalSkeleton, tmp);
  678. VectorRotate(tmp, joint->matGlobal, norm);
  679. out[0] += norm[0] * weights[i];
  680. out[1] += norm[1] * weights[i];
  681. out[2] += norm[2] * weights[i];
  682. }
  683. }
  684. }
  685. void msModel::FillJointIndicesAndWeights(const ms3d_vertex_t *vertex, int jointIndices[4], int jointWeights[4]) const
  686. {
  687. jointIndices[0] = vertex->boneId;
  688. jointIndices[1] = vertex->boneIds[0];
  689. jointIndices[2] = vertex->boneIds[1];
  690. jointIndices[3] = vertex->boneIds[2];
  691. jointWeights[0] = 100;
  692. jointWeights[1] = 0;
  693. jointWeights[2] = 0;
  694. jointWeights[3] = 0;
  695. if (vertex->weights[0] != 0 || vertex->weights[1] != 0 || vertex->weights[2] != 0)
  696. {
  697. jointWeights[0] = vertex->weights[0];
  698. jointWeights[1] = vertex->weights[1];
  699. jointWeights[2] = vertex->weights[2];
  700. jointWeights[3] = 100 - (vertex->weights[0] + vertex->weights[1] + vertex->weights[2]);
  701. }
  702. }