Advertisement
Guest User

skeletalAnimation.cpp

a guest
Jan 14th, 2024
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.08 KB | Software | 0 0
  1. #include <vulkan/vulkan.h>
  2. #include <skeletalAnimation.h>
  3. #include <functional>
  4.  
  5. skeletalAnimation::skeletalAnimation(std::string name)
  6. {
  7.     asmpScene = importer.ReadFile(name,
  8.     //aiProcess_CalcTangentSpace       |
  9.     aiProcess_Triangulate            |
  10.     aiProcess_JoinIdenticalVertices  |
  11.     aiProcess_SortByPType);
  12.  
  13.     if(asmpScene == nullptr) {
  14.         throw std::runtime_error("Failed to read file " + std::string(importer.GetErrorString()));
  15.     }
  16.  
  17.     printOgTree();
  18.  
  19.     convertScene();
  20.  
  21.     printTree();
  22. }
  23.  
  24. skeletalAnimation::~skeletalAnimation()
  25. {
  26. }
  27.  
  28. uint skeletalAnimation::FindPosition(float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
  29. {
  30.     for (uint i = 0 ; i < pNodeAnim->mNumPositionKeys - 1 ; i++) {
  31.         float t = (float)pNodeAnim->mPositionKeys[i + 1].mTime;
  32.         if (AnimationTimeTicks < t) {
  33.             return i;
  34.         }
  35.     }
  36.  
  37.     return 0;
  38. }
  39.  
  40. void skeletalAnimation::loadAnimation(std::string path) {
  41.     asmpScene = importer.ReadFile(path,
  42.     //aiProcess_CalcTangentSpace       |
  43.     aiProcess_Triangulate            |
  44.     aiProcess_JoinIdenticalVertices  |
  45.     aiProcess_SortByPType);
  46.  
  47.     if(asmpScene == nullptr) {
  48.         throw std::runtime_error("Failed to read file " + std::string(importer.GetErrorString()));
  49.     }
  50.  
  51.     scene.bone_name_to_index_map.clear();
  52.     scene.bones.resize(0, skeletalAnimation::Scene::BoneInfo(aiMatrix4x4()));
  53.     //scene.globalTransforms.resize(0);
  54.     scene.hierarchy.resize(0);
  55.     scene.indices.resize(0);
  56.     //scene.localTransforms.resize(0);
  57.     scene.mesh_base_vertex.resize(0);
  58.     scene.vertices.resize(0);
  59.  
  60.     convertScene();
  61. }
  62.  
  63. void skeletalAnimation::CalcInterpolatedPosition(aiVector3D& Out, float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
  64. {
  65.     // we need at least two values to interpolate...
  66.     if (pNodeAnim->mNumPositionKeys == 1) {
  67.         Out = pNodeAnim->mPositionKeys[0].mValue;
  68.         return;
  69.     }
  70.  
  71.     uint PositionIndex = FindPosition(AnimationTimeTicks, pNodeAnim);
  72.     uint NextPositionIndex = PositionIndex + 1;
  73.     assert(NextPositionIndex < pNodeAnim->mNumPositionKeys);
  74.     float t1 = (float)pNodeAnim->mPositionKeys[PositionIndex].mTime;
  75.     float t2 = (float)pNodeAnim->mPositionKeys[NextPositionIndex].mTime;
  76.     float DeltaTime = t2 - t1;
  77.     float Factor = (AnimationTimeTicks - t1) / DeltaTime;
  78.     assert(Factor >= 0.0f && Factor <= 1.0f);
  79.     const aiVector3D& Start = pNodeAnim->mPositionKeys[PositionIndex].mValue;
  80.     const aiVector3D& End = pNodeAnim->mPositionKeys[NextPositionIndex].mValue;
  81.     aiVector3D Delta = End - Start;
  82.     Out = Start + Factor * Delta;
  83. }
  84.  
  85. void skeletalAnimation::CalcInterpolatedRotation(aiQuaternion& Out, float AnimationTime, const aiNodeAnim* pNodeAnim)
  86. {
  87.     // we need at least two values to interpolate...
  88.     if (pNodeAnim->mNumRotationKeys == 1) {
  89.         Out = pNodeAnim->mRotationKeys[0].mValue;
  90.         return;
  91.     }
  92.  
  93.     uint RotationIndex = FindRotation(AnimationTime, pNodeAnim);
  94.     uint NextRotationIndex = (RotationIndex + 1);
  95.     assert(NextRotationIndex < pNodeAnim->mNumRotationKeys);
  96.     float DeltaTime = pNodeAnim->mRotationKeys[NextRotationIndex].mTime - pNodeAnim->mRotationKeys[RotationIndex].mTime;
  97.     float Factor = (AnimationTime - (float)pNodeAnim->mRotationKeys[RotationIndex].mTime) / DeltaTime;
  98.     assert(Factor >= 0.0f && Factor <= 1.0f);
  99.     const aiQuaternion& StartRotationQ = pNodeAnim->mRotationKeys[RotationIndex].mValue;
  100.     const aiQuaternion& EndRotationQ = pNodeAnim->mRotationKeys[NextRotationIndex].mValue;
  101.     aiQuaternion::Interpolate(Out, StartRotationQ, EndRotationQ, Factor);
  102.     Out = Out.Normalize();
  103. }
  104.  
  105. uint skeletalAnimation::FindRotation(float AnimationTime, const aiNodeAnim* pNodeAnim)
  106. {
  107.     assert(pNodeAnim->mNumRotationKeys > 0);
  108.  
  109.     for (uint i = 0 ; i < pNodeAnim->mNumRotationKeys - 1 ; i++) {
  110.         if (AnimationTime < (float)pNodeAnim->mRotationKeys[i + 1].mTime) {
  111.             return i;
  112.         }
  113.     }
  114.  
  115.     assert(0);
  116. }
  117.  
  118. uint skeletalAnimation::FindScaling(float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
  119. {
  120.     assert(pNodeAnim->mNumScalingKeys > 0);
  121.  
  122.     for (uint i = 0 ; i < pNodeAnim->mNumScalingKeys - 1 ; i++) {
  123.         float t = (float)pNodeAnim->mScalingKeys[i + 1].mTime;
  124.         if (AnimationTimeTicks < t) {
  125.             return i;
  126.         }
  127.     }
  128.  
  129.     return 0;
  130. }
  131.  
  132.  
  133. void skeletalAnimation::CalcInterpolatedScaling(aiVector3D& Out, float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
  134. {
  135.     // we need at least two values to interpolate...
  136.     if (pNodeAnim->mNumScalingKeys == 1) {
  137.         Out = pNodeAnim->mScalingKeys[0].mValue;
  138.         return;
  139.     }
  140.  
  141.     uint ScalingIndex = FindScaling(AnimationTimeTicks, pNodeAnim);
  142.     uint NextScalingIndex = ScalingIndex + 1;
  143.     assert(NextScalingIndex < pNodeAnim->mNumScalingKeys);
  144.     float t1 = (float)pNodeAnim->mScalingKeys[ScalingIndex].mTime;
  145.     float t2 = (float)pNodeAnim->mScalingKeys[NextScalingIndex].mTime;
  146.     float DeltaTime = t2 - t1;
  147.     float Factor = (AnimationTimeTicks - (float)t1) / DeltaTime;
  148.     assert(Factor >= 0.0f && Factor <= 1.0f);
  149.     const aiVector3D& Start = pNodeAnim->mScalingKeys[ScalingIndex].mValue;
  150.     const aiVector3D& End   = pNodeAnim->mScalingKeys[NextScalingIndex].mValue;
  151.     aiVector3D Delta = End - Start;
  152.     Out = Start + Factor * Delta;
  153. }
  154.  
  155. void skeletalAnimation::loadBone(const aiBone* bone, uint meshI) {
  156.     uint boneId = scene.getBoneId(bone);
  157.     for(uint idWeightPairI = 0; idWeightPairI < bone->mNumWeights; idWeightPairI++) {
  158.         aiVertexWeight idWeightPair = bone->mWeights[idWeightPairI];
  159.         uint globalVertexId = scene.mesh_base_vertex[meshI] + idWeightPair.mVertexId;
  160.         if(globalVertexId >= scene.vertices.size()) {
  161.             throw std::runtime_error("global vertex id is greater than the number of vertices");
  162.         }
  163.         scene.vertices[globalVertexId].addBoneData(boneId, idWeightPair.mWeight);
  164.     }
  165. }
  166.  
  167. void skeletalAnimation::loadMeshes() {
  168.     uint total_vertices = 0;
  169.     scene.mesh_base_vertex.resize(asmpScene->mNumMeshes);
  170.     for(uint meshI = 0; meshI < asmpScene->mNumMeshes; meshI++) {
  171.         aiMesh* mesh = asmpScene->mMeshes[meshI];
  172.         scene.mesh_base_vertex[meshI] = total_vertices;
  173.         for(uint vertI = 0; vertI < mesh->mNumVertices; vertI++) {
  174.             scene.vertices.push_back({});
  175.             scene.vertices[scene.vertices.size()-1].pos = glm::vec3(mesh->mVertices[vertI].x, mesh->mVertices[vertI].y, mesh->mVertices[vertI].z);
  176.         }
  177.         for(uint faceI = 0; faceI < mesh->mNumFaces; faceI++) {
  178.             scene.indices.push_back(mesh->mFaces[faceI].mIndices[0] + scene.mesh_base_vertex[meshI]);
  179.             scene.indices.push_back(mesh->mFaces[faceI].mIndices[1] + scene.mesh_base_vertex[meshI]);
  180.             scene.indices.push_back(mesh->mFaces[faceI].mIndices[2] + scene.mesh_base_vertex[meshI]);
  181.         }
  182.         for(uint boneI = 0; boneI < mesh->mNumBones; boneI++) {
  183.             loadBone(mesh->mBones[boneI], meshI);
  184.         }
  185.         total_vertices += mesh->mNumVertices;
  186.     }
  187. }
  188.  
  189. aiNodeAnim* skeletalAnimation::findNodeAnim(const char* nodeName) {
  190.     if(scene.animationIndex < 0) return nullptr;
  191.     //std::cout << "Node name pointer: " << (void*)nodeName << std::endl;
  192.     aiAnimation& anim = *(asmpScene->mAnimations[scene.animationIndex]);
  193.     for(uint i = 0; i < anim.mNumChannels; i++) {
  194.         //std::cout << std::string(nodeName) << ", " << std::string(anim.mChannels[i]->mNodeName.C_Str()) << std::endl;
  195.         if(strcmp(anim.mChannels[i]->mNodeName.C_Str(), nodeName) == 0) {
  196.             return anim.mChannels[i];
  197.         }
  198.     }
  199.     return nullptr;
  200. }
  201.  
  202. void skeletalAnimation::printOgTree() {
  203.     std::stack<aiNode*> s;
  204.     s.push(asmpScene->mRootNode);
  205.     while(!s.empty()) {
  206.         aiNode* top = s.top();
  207.         s.pop();
  208.  
  209.         std::cout << top->mName.C_Str() << ", transformation=\n{a1: "
  210.         << top->mTransformation.a1 << ", a2: " << top->mTransformation.a2 << ", a3: " << top->mTransformation.a3 << ", a4: " << top->mTransformation.a4 << std::endl
  211.         << "b1: " << top->mTransformation.b1 << ", b2: " << top->mTransformation.b2 << ", b3: " << top->mTransformation.b3 << ", b4: " << top->mTransformation.b4 << std::endl
  212.         << "c1: " << top->mTransformation.c1 << ", c2: " << top->mTransformation.c2 << ", c3: " << top->mTransformation.c3 << ", c4: " << top->mTransformation.c4 << std::endl
  213.         << "d1: " << top->mTransformation.d1 << ", d2: " << top->mTransformation.d2 << ", d3: " << top->mTransformation.d3 << ", d4: " << top->mTransformation.d4 << "}";
  214.         if(top->mNumChildren > 0)
  215.         std::cout << " children:" << std::endl;
  216.  
  217.         for(uint i = 0; i < top->mNumChildren; i++) {
  218.             s.push(top->mChildren[i]);
  219.             std::cout << top->mChildren[i]->mName.C_Str() << "-";
  220.         }
  221.         std::cout << std::endl;
  222.     }
  223. }
  224.  
  225. void skeletalAnimation::printTree() {
  226.     std::stack<uint> s;
  227.     std::stack<std::function<void()>> printables;
  228.     s.push(0);
  229.     printables.push([&]() {
  230.         std::cout << std::endl;
  231.     });
  232.     while(!s.empty()) {
  233.         uint i = s.top();
  234.         std::function<void()> print = printables.top();
  235.         s.pop();
  236.         printables.pop();
  237.  
  238.         print();
  239.         std::cout << scene.hierarchy[i].name << ", transformation=\n{a1: "
  240.         << scene.hierarchy[i].transformation.a1 << ", a2: " << scene.hierarchy[i].transformation.a2 << ", a3: " << scene.hierarchy[i].transformation.a3 << ", a4: " << scene.hierarchy[i].transformation.a4 << std::endl
  241.         << "b1: " << scene.hierarchy[i].transformation.b1 << ", b2: " << scene.hierarchy[i].transformation.b2 << ", b3: " << scene.hierarchy[i].transformation.b3 << ", b4: " << scene.hierarchy[i].transformation.b4 << std::endl
  242.         << "c1: " << scene.hierarchy[i].transformation.c1 << ", c2: " << scene.hierarchy[i].transformation.c2 << ", c3: " << scene.hierarchy[i].transformation.c3 << ", c4: " << scene.hierarchy[i].transformation.c4 << std::endl
  243.         << "d1: " << scene.hierarchy[i].transformation.d1 << ", d2: " << scene.hierarchy[i].transformation.d2 << ", d3: " << scene.hierarchy[i].transformation.d3 << ", d4: " << scene.hierarchy[i].transformation.d4 << "}";
  244.         if(scene.hierarchy[i].firstChild > -1) {
  245.             s.push(scene.hierarchy[i].firstChild);
  246.             printables.push([=]() {
  247.                 std::cout << std::endl << std::endl;
  248.                 std::cout << scene.hierarchy[i].name << ": ";
  249.             });
  250.         }
  251.         if(scene.hierarchy[i].nextSibling > -1) {
  252.             s.push(scene.hierarchy[i].nextSibling);
  253.             printables.push([]() {
  254.                 std::cout << "-";
  255.             });
  256.         }
  257.     }
  258. }
  259.  
  260. // (1) convert N-ary tree to left child right sibling
  261. // (2) move bone-vertex information into a linear array
  262. void skeletalAnimation::convertScene() {
  263.     if(asmpScene->mNumAnimations > 0) {
  264.         scene.animationIndex = 0;
  265.         scene.animationDuration = asmpScene->mAnimations[scene.animationIndex]->mDuration;
  266.     }
  267.     scene.globalInverseTransform = asmpScene->mRootNode->mTransformation;
  268.     scene.globalInverseTransform.Inverse();
  269.     std::stack<aiNode*> s;
  270.     s.push(asmpScene->mRootNode);
  271.     struct Node root;
  272.     root.name = std::string(asmpScene->mRootNode->mName.C_Str());
  273.     root.firstChild = asmpScene->mRootNode->mNumChildren ? 1 : -1;
  274.     root.nextSibling = -1;
  275.     root.transformation = asmpScene->mRootNode->mTransformation;
  276.     root.parent = -1;
  277.     scene.hierarchy.push_back(root);
  278.     std::stack<std::function<void(aiNode* st, struct Scene& sceneRef)>> runnables;
  279.     runnables.push([](aiNode* st, struct Scene& sceneRef) {
  280.  
  281.     });
  282.     while(!s.empty()) {
  283.         aiNode* top = s.top();
  284.         s.pop();
  285.         std::function<void(aiNode* st, struct Scene& sceneRef)> run = runnables.top();
  286.         runnables.pop();
  287.         size_t currentIndex = scene.hierarchy.size();
  288.         run(top, scene);
  289.         for(uint i = 0; i < top->mNumChildren; i++) {
  290.             s.push(top->mChildren[i]);
  291.             struct Node someChild;
  292.             someChild.name = std::string(top->mChildren[i]->mName.C_Str());
  293.             someChild.parent = currentIndex-1;
  294.             someChild.transformation = top->mChildren[i]->mTransformation;
  295.             someChild.nextSibling = i < top->mNumChildren-1 ? currentIndex+i+1 : -1; // Checks if there is a next sibling
  296.             someChild.firstChild = -1; // if someChild has no children this will stay at -1
  297.             scene.hierarchy.push_back(someChild);
  298.             runnables.push([=](aiNode* st, struct Scene& sceneRef) {
  299.                 sceneRef.hierarchy[i+currentIndex].firstChild = st->mNumChildren > 0 ? sceneRef.hierarchy.size() : -1;
  300.             });
  301.         }
  302.     }
  303.    
  304.     /*scene.vertices = {
  305.         {{-0.5f, -1.5f, 0.1f}},
  306.         {{0.5f, -1.5f, 0.1f}},
  307.         {{0.5f, 0.5f, 0.1f}},
  308.         {{-0.5f, 0.5f, 0.1f}}
  309.     };
  310.  
  311.     scene.indices = {
  312.         0, 1, 2, 2, 3, 0
  313.     };*/
  314.     loadMeshes();
  315. }
  316.  
  317. void skeletalAnimation::traverse(float animationTime) {
  318.     std::stack<uint> s;
  319.     s.push(0); // index of the root node
  320.     scene.hierarchy[0].localTransformation = scene.hierarchy[0].transformation;
  321.     while (!s.empty())
  322.     {
  323.         uint top = s.top();
  324.         s.pop();
  325.         //std::cout << "Node name: " << top->name << std::endl;
  326.         /*aiNodeAnim* nodeAnim = findNodeAnim(scene.hierarchy[top].name.c_str());
  327.         if(nodeAnim) {
  328.             std::cout << "Found a node animation" << std::endl;
  329.             aiVector3D Scaling;
  330.             CalcInterpolatedScaling(Scaling, animationTime, nodeAnim);
  331.             aiMatrix4x4 ScalingM;
  332.             ScalingM.Scaling(Scaling, ScalingM);
  333.  
  334.             // Interpolate rotation and generate rotation transformation matrix
  335.             aiQuaternion RotationQ;
  336.             CalcInterpolatedRotation(RotationQ, animationTime, nodeAnim);
  337.             aiMatrix4x4 RotationM = aiMatrix4x4(RotationQ.GetMatrix());
  338.  
  339.             // Interpolate translation and generate translation transformation matrix
  340.             aiVector3D Translation;
  341.             CalcInterpolatedPosition(Translation, animationTime, nodeAnim);
  342.             aiMatrix4x4 TranslationM;
  343.             TranslationM.Translation(Translation, TranslationM);
  344.  
  345.             // Combine the above transformations
  346.             scene.hierarchy[top].transformation = TranslationM * RotationM * ScalingM;
  347.         }*/
  348.         if(scene.hierarchy[top].parent > -1) {
  349.             scene.hierarchy[top].localTransformation = scene.hierarchy[scene.hierarchy[top].parent].localTransformation * scene.hierarchy[top].transformation;
  350.         }
  351.         if(scene.bone_name_to_index_map.find(scene.hierarchy[top].name) != scene.bone_name_to_index_map.end()) {
  352.             uint boneIndex = scene.bone_name_to_index_map[scene.hierarchy[top].name];
  353.             scene.finalTransforms[boneIndex] = scene.globalInverseTransform * scene.hierarchy[top].localTransformation * scene.bones[boneIndex].OffsetMatrix;
  354.         }
  355.         if (scene.hierarchy[top].firstChild > -1) s.push(scene.hierarchy[top].firstChild);
  356.         if (scene.hierarchy[top].nextSibling > -1) s.push(scene.hierarchy[top].nextSibling);
  357.     }
  358. }
Tags: C++
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement