Advertisement
Guest User

Milkshape3D Animation cpp

a guest
May 19th, 2013
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.94 KB | None | 0 0
  1. #include <cstdio>
  2. #include <fstream>
  3. #include <assert.h>
  4. #include <iostream>
  5. #include <OpenGL/gl.h>
  6. #include <GLUT/glut.h>
  7. #include "Milkshape.h"
  8. #include "Quaternion.h"
  9. #include "LodePng.h"
  10. #include "Interpolator.h"
  11.  
  12. // http://web.archive.org/web/20050305044436/http://rsn.gamedev.net/tutorials/ms3danim.asp
  13.  
  14. using std::ifstream;
  15. using std::cout;
  16.  
  17. #define READ1(x)   input.read((char*)&(x), 1)
  18. #define READ2(x)   input.read((char*)&(x), 2)
  19. #define READ4(x)   input.read((char*)&(x), 4)
  20. #define READ6(x)   input.read((char*)&(x), 6)
  21. #define READ10(x)  input.read((char*)&(x), 10)
  22. #define READ12(x)  input.read((char*)&(x), 12)
  23. #define READ16(x)  input.read((char*)&(x), 16)
  24. #define READ32(x)  input.read((char*)&(x), 32)
  25. #define READ36(x)  input.read((char*)&(x), 36)
  26. #define READ128(x) input.read((char*)&(x), 128)
  27.  
  28. MS3D::~MS3D() {
  29.     glBindTexture(GL_TEXTURE_2D, 0);
  30.     for (int i = 0; i < int(m_nNumMaterials); ++i) {
  31.         if (m_vMaterials[0].textureId != -1)
  32.             glDeleteTextures(1, (unsigned int*)&m_vMaterials[0].textureId);
  33.         if (m_vMaterials[0].alphaMapId != -1)
  34.             glDeleteTextures(1, (unsigned int*)&m_vMaterials[0].alphaMapId);
  35.     }
  36. }
  37.  
  38. MS3D::MS3D(const char* filePath) {
  39.     memset(&m_tHeader, 0, sizeof(MS3DHeader));
  40.     ifstream input; input.open(filePath, std::ios::in | std::ios::binary);
  41.    
  42.     READ10(m_tHeader.identification[0]);
  43.     READ4(m_tHeader.version);
  44.     READ2(m_nNumVerts);
  45.     m_vVerts.reserve(m_nNumVerts);
  46.     MS3DVertex dummyVertex;
  47.     for (int i = 0; i < int(m_nNumVerts); ++i) {
  48.         m_vVerts.push_back(dummyVertex);
  49.         MS3DVertex& vertex = m_vVerts[i];
  50.        
  51.         READ1(vertex.flags);
  52.         READ12(vertex.position[0]);
  53.         READ1(vertex.boneId);
  54.         READ1(vertex.referenceCount);
  55.     }
  56.    
  57.     READ2(m_nNumTriangles);
  58.     m_vTriangles.reserve(m_nNumTriangles);
  59.     MS3DFace dummyTriangle;
  60.     for (int i = 0; i < int(m_nNumTriangles); ++i) {
  61.         m_vTriangles.push_back(dummyTriangle);
  62.         MS3DFace& triangle = m_vTriangles[i];
  63.        
  64.         READ2(triangle.flags);
  65.         READ6(triangle.vertexIndices[0]);
  66.         READ12(triangle.vertexNormals[0][0]);
  67.         READ12(triangle.vertexNormals[1][0]);
  68.         READ12(triangle.vertexNormals[2][0]);
  69.         READ12(triangle.s[0]);
  70.         READ12(triangle.t[0]);
  71.         READ1(triangle.smoothingGroup);
  72.         READ1(triangle.groupIndex);
  73.     }
  74.  
  75.     READ2(m_nNumGroups);
  76.     m_vSubmeshes.reserve(m_nNumGroups);
  77.     MS3DGroup dummyGroup;
  78.     for (int i = 0; i < int(m_nNumGroups); ++i) {
  79.         m_vSubmeshes.push_back(dummyGroup);
  80.         MS3DGroup& group = m_vSubmeshes[i];
  81.        
  82.         READ1(group.flags);
  83.         memset(group.name, 0, 32);
  84.         READ32(group.name[0]);
  85.         READ2(group.numTriangles);
  86.        
  87.         group.triangleIndices.reserve(group.numTriangles);
  88.         for (int j = 0; j < int(group.numTriangles); ++j) {
  89.             group.triangleIndices.push_back(0);
  90.             READ2(group.triangleIndices[j]);
  91.         }
  92.        
  93.         READ1(group.materialId);
  94.     }
  95.    
  96.     READ2(m_nNumMaterials);
  97.     m_vMaterials.reserve(m_nNumMaterials);
  98.     MS3DMaterial dummyMaterial;
  99.     for (int i = 0; i < int(m_nNumMaterials); ++i) {
  100.         m_vMaterials.push_back(dummyMaterial);
  101.         MS3DMaterial& material = m_vMaterials[i];
  102.        
  103.         memset(material.name, 0, 32);
  104.         READ32(material.name[0]);
  105.         READ16(material.ambient[0]);
  106.         READ16(material.diffuse[0]);
  107.         READ16(material.specular[0]);
  108.         READ16(material.emissive[0]);
  109.         READ4(material.shininess);
  110.         READ4(material.transparency);
  111.         READ1(material.mode);
  112.         memset(material.texture, 0, 128);
  113.         READ128(material.texture[0]);
  114.         memset(material.alphaMap, 0, 128);
  115.         READ128(material.alphaMap[0]);
  116.        
  117.         material.textureId = -1;
  118.         if (material.texture[0] != 0)
  119.             material.textureId = LoadTexture(material.texture);
  120.        
  121.         material.alphaMapId = -1;
  122.         if (material.alphaMap[0] != 0)
  123.             material.alphaMapId = LoadTexture(material.alphaMap);
  124.     }
  125.  
  126.     READ4(m_nFPS);
  127.     m_nFPSReciprocal = 1.0f / m_nFPS;
  128.     READ4(m_nCurTime);
  129.     READ4(m_nNumFrames);
  130.     READ2(m_nNumJoints);
  131.    
  132.     m_vJoints.reserve(m_nNumJoints);
  133.     MS3DJoint dummyJoint;
  134.     MS3DFrame dummyFrame;
  135.     MS3DRotationFrame dummyRotation;
  136.     MS3DTranslationFrame dummyTranslation;
  137.     for (int i = 0; i < int(m_nNumJoints); ++i) {
  138.         m_vJoints.push_back(dummyJoint);
  139.         MS3DJoint& joint = m_vJoints[i];
  140.        
  141.         READ1(joint.flags);
  142.         memset(joint.name, 0, 32);
  143.         READ32(joint.name[0]);
  144.         memset(joint.parentName, 0, 32);
  145.         READ32(joint.parentName[0]);
  146.         READ12(joint.rotation[0]);
  147.         READ12(joint.translation[0]);
  148.         READ2(joint.numRotationFrames);
  149.         READ2(joint.numTranslationFrames);
  150.         joint.rawRotationFrames.reserve(joint.numRotationFrames);
  151.         joint.rawTranslationFrames.reserve(joint.numTranslationFrames);
  152.         for (int j = 0; j < joint.numRotationFrames; ++j) {
  153.             joint.rawRotationFrames.push_back(dummyFrame);
  154.             READ4(joint.rawRotationFrames[j].time);
  155.             READ12(joint.rawRotationFrames[j].data[0]);            
  156.         }
  157.         for (int j = 0; j < joint.numTranslationFrames; ++j) {
  158.             joint.rawTranslationFrames.push_back(dummyFrame);
  159.             READ4(joint.rawTranslationFrames[j].time);
  160.             READ12(joint.rawTranslationFrames[j].data[0]);
  161.         }
  162.     }
  163.    
  164.     PrepareBones();
  165.    
  166.     input.close();
  167.    
  168.     m_nCurTime = 0.0f;
  169. }
  170.  
  171. void MS3D::PrepareBones() {
  172.     // Assign each bone a parent
  173.     for (int i = 0; i < int(m_nNumJoints); ++i) {
  174.         MS3DJoint& joint = m_vJoints[i];
  175.         joint.parentId = -1;
  176.        
  177.         char buffer[33]; memset(buffer, 0, 33);
  178.         memcpy(buffer, joint.name, 32);
  179.         if (buffer[0] != '\0') {
  180.             memcpy(buffer, joint.parentName, 32);
  181.             string parent = buffer; string thisJoint;
  182.             for (int j = 0; j < int(m_nNumJoints); ++j) {
  183.                 memset(buffer, 0, 33);
  184.                 memcpy(buffer, m_vJoints[j].name, 32);
  185.                 thisJoint = buffer;
  186.                 if (thisJoint == parent) {
  187.                     joint.parentId = j;
  188.                     break;
  189.                 }
  190.             }
  191.         }
  192.        
  193.         if (joint.parentId == -1) {
  194.             log << "Found \"root\" joint\n";
  195.         }
  196.     }
  197.    
  198.     // Find the absolute (world position) for each bone
  199.     for (int i = 0; i < int(m_nNumJoints); ++i) {
  200.         MS3DJoint& joint = m_vJoints[i];
  201.         Matrix localTransform = BuildMatrix(ToRotation(joint.rotation), ToTranslation(joint.translation));
  202.        
  203.         if (joint.parentId == -1) {
  204.             joint.finalTransform = localTransform;
  205.         } else {
  206.             joint.finalTransform =  m_vJoints[joint.parentId].finalTransform * localTransform;
  207.         }
  208.     }
  209.    
  210.     // Multiply every vertex (position) by the inverse of the world position of the bones
  211.     for (int i = 0; i < int(m_nNumVerts); ++i) {
  212.         MS3DVertex& vertex = m_vVerts[i];
  213.        
  214.         Vector vertexPosition(vertex.position[0], vertex.position[1], vertex.position[2]);
  215.         vertexPosition.w = 1.0f;
  216.        
  217.         if (vertex.boneId != -1) {
  218.             Matrix invFinalTransform = m_vJoints[vertex.boneId].finalTransform.Inverse();
  219.            
  220.             vertexPosition = invFinalTransform * vertexPosition;
  221.         }
  222.        
  223.         vertex.position[0] = vertexPosition.x;
  224.         vertex.position[1] = vertexPosition.y;
  225.         vertex.position[2] = vertexPosition.z;
  226.     }
  227.    
  228.     // Multiply every vertex (normal) by the inverse of the world position of the bones
  229.     for (int i = 0; i < int(m_nNumTriangles); ++i) {
  230.         MS3DFace& triangle = m_vTriangles[i];
  231.        
  232.         for (int j = 0; j < 3; ++j) {
  233.             Vector vertexNormal(triangle.vertexNormals[j][0], triangle.vertexNormals[j][1], triangle.vertexNormals[j][2]);
  234.             vertexNormal.w = 0.0f;
  235.            
  236.             if (m_vVerts[triangle.vertexIndices[j]].boneId != -1) {
  237.                 Matrix invFinalTransform = m_vJoints[m_vVerts[triangle.vertexIndices[j]].boneId].finalTransform.Inverse();
  238.                
  239.                 vertexNormal = invFinalTransform * vertexNormal;
  240.             }
  241.            
  242.             triangle.vertexNormals[j][0] = vertexNormal.x;
  243.             triangle.vertexNormals[j][1] = vertexNormal.y;
  244.             triangle.vertexNormals[j][2] = vertexNormal.z;
  245.         }
  246.     }
  247. }
  248.  
  249. void MS3D::RenderAnimated() {
  250.     glColor3f(1.0f, 1.0f, 1.0f);
  251.    
  252.     for (int i = 0; i < int(m_nNumGroups); ++i) {
  253.         MS3DGroup& submesh = m_vSubmeshes[i];
  254.         MS3DMaterial& material = m_vMaterials[submesh.materialId];
  255.         glBindTexture(GL_TEXTURE_2D, material.textureId);
  256.        
  257.         glBegin(GL_TRIANGLES);
  258.         for (int j = 0; j < submesh.numTriangles; ++j) {
  259.             MS3DFace& triangle = m_vTriangles[submesh.triangleIndices[j]];
  260.            
  261.             for (int k = 0; k < 3; ++k) {
  262.                 glTexCoord2f(triangle.s[k], triangle.t[k]);
  263.                 Vector vertexNormal(triangle.vertexNormals[k][0], triangle.vertexNormals[k][1], triangle.vertexNormals[k][2]);
  264.                 Vector vertexPosition(m_vVerts[triangle.vertexIndices[k]].position[0], m_vVerts[triangle.vertexIndices[k]].position[1], m_vVerts[triangle.vertexIndices[k]].position[2]);
  265.                
  266.                 if (m_vVerts[triangle.vertexIndices[k]].boneId != -1) {
  267.                     Matrix finalTransform = m_vJoints[m_vVerts[triangle.vertexIndices[k]].boneId].finalTransform;
  268.                     vertexPosition.w = 1.0f; vertexNormal.w = 0.0f;
  269.                    
  270.                     vertexPosition = finalTransform * vertexPosition;
  271.                     vertexNormal = finalTransform * vertexNormal;
  272.                    
  273.                     vertexNormal.Normalize();
  274.                 }
  275.                 glNormal3f(vertexNormal.x, vertexNormal.y, vertexNormal.z);
  276.                 glVertex3f(vertexPosition.x, vertexPosition.y, vertexPosition.z);
  277.             }
  278.         }
  279.         glEnd();
  280.     }
  281. }
  282.  
  283. void MS3D::UpdateAnimation(float deltaTime) {
  284.     // Update animation time
  285.     if (m_nCurTime > m_nNumFrames * m_nFPSReciprocal) m_nCurTime = 0.0f;
  286.     else m_nCurTime += deltaTime * 0.5f;
  287.    
  288.     // Loop trough each joint to set the animation data
  289.     for (int i = 0; i < int(m_nNumJoints); ++i) {
  290.         MS3DJoint& joint = m_vJoints[i];
  291.         Matrix localTransform = BuildMatrix(ToRotation(joint.rotation), ToTranslation(joint.translation));
  292.        
  293.         // Will be using this to build the final matrix
  294.         Vector animatedTranslation; Quaternion animatedRotation;
  295.        
  296.         // If there are no frames to animate, just stop
  297.         if (joint.numRotationFrames == 0 && joint.numTranslationFrames == 0 )
  298.             continue;
  299.        
  300.         // Find the translation frame number
  301.         int frame = 0;
  302.         while (frame < joint.numTranslationFrames &&
  303.                joint.rawTranslationFrames[frame].time < m_nCurTime) ++frame;
  304.         if (frame > joint.numTranslationFrames) frame = joint.numTranslationFrames;
  305.        
  306.         // Interpolate translation
  307.         if (frame == 0) { // No prev frame
  308.             animatedTranslation = ToTranslation(joint.rawTranslationFrames[0].data);
  309.         } else if (frame == joint.numTranslationFrames) { // No "this" frame
  310.             animatedTranslation = ToTranslation(joint.rawTranslationFrames[frame - 1].data);
  311.         } else  { // Do the actual interpolation
  312.             MS3DFrame& curFrame = joint.rawTranslationFrames[frame];
  313.             MS3DFrame& prevFrame = joint.rawTranslationFrames[frame - 1];
  314.            
  315.             float timeDelta = curFrame.time - prevFrame.time;
  316.             float interpValue = (float)((m_nCurTime - prevFrame.time) / timeDelta);
  317.            
  318.             animatedTranslation = Lerp(ToTranslation(prevFrame.data), ToTranslation(curFrame.data), interpValue);
  319.         }
  320.        
  321.         // Find the rotation frame
  322.         frame = 0;
  323.         while (frame < joint.numRotationFrames &&
  324.                joint.rawRotationFrames[frame].time < m_nCurTime) ++frame;
  325.         if (frame > joint.numRotationFrames) frame = joint.numRotationFrames;
  326.        
  327.         // Interpolate rotation
  328.         if (frame == 0) { // No prev frame
  329.             animatedRotation = ToRotation(joint.rawRotationFrames[0].data);
  330.         } else  if (frame == joint.numRotationFrames) { // No "this" frame
  331.             animatedRotation = ToRotation(joint.rawRotationFrames[frame - 1].data);
  332.         } else { // Do actual interpolation
  333.             MS3DFrame& curFrame = joint.rawRotationFrames[frame];
  334.             MS3DFrame& prevFrame = joint.rawRotationFrames[frame - 1];
  335.            
  336.             float timeDelta = curFrame.time - prevFrame.time;
  337.             float interpValue = (float)((m_nCurTime - prevFrame.time) / timeDelta);
  338.            
  339.             animatedRotation = Slerp(ToRotation(prevFrame.data), ToRotation(curFrame.data), interpValue);
  340.         }
  341.        
  342.         // Animate the bone in local space
  343.         Matrix animationTransform = BuildMatrix(animatedRotation, animatedTranslation);
  344.         localTransform = localTransform * animationTransform;
  345.        
  346.         if (joint.parentId == -1) {
  347.             joint.finalTransform = localTransform;
  348.         } else {
  349.             joint.finalTransform = m_vJoints[joint.parentId].finalTransform * localTransform;
  350.         }
  351.     }
  352. }
  353.  
  354. Matrix BuildMatrix(const Quaternion& rot, const Vector& trans) {
  355.     Quaternion q = rot;
  356.     Matrix m = Matrix::Translation(trans.x, trans.y, trans.z);
  357.     m.SetRotation(q.ToMatrix());
  358.     return m;
  359. }
  360.  
  361. Vector ToTranslation(float* f) {
  362.     Vector v(f[0], f[1], f[2]);
  363.     v.w = 1.0f;
  364.     return v;
  365. }
  366.  
  367. Quaternion ToRotation(float* f) {
  368.     Quaternion q;
  369.     q.Euler(f[0], f[1], f[2]);
  370.     q.Normalize();
  371.     return q;
  372. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement