Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vulkan/vulkan.h>
- #include <skeletalAnimation.h>
- #include <functional>
- skeletalAnimation::skeletalAnimation(std::string name)
- {
- asmpScene = importer.ReadFile(name,
- //aiProcess_CalcTangentSpace |
- aiProcess_Triangulate |
- aiProcess_JoinIdenticalVertices |
- aiProcess_SortByPType);
- if(asmpScene == nullptr) {
- throw std::runtime_error("Failed to read file " + std::string(importer.GetErrorString()));
- }
- printOgTree();
- convertScene();
- printTree();
- }
- skeletalAnimation::~skeletalAnimation()
- {
- }
- uint skeletalAnimation::FindPosition(float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
- {
- for (uint i = 0 ; i < pNodeAnim->mNumPositionKeys - 1 ; i++) {
- float t = (float)pNodeAnim->mPositionKeys[i + 1].mTime;
- if (AnimationTimeTicks < t) {
- return i;
- }
- }
- return 0;
- }
- void skeletalAnimation::loadAnimation(std::string path) {
- asmpScene = importer.ReadFile(path,
- //aiProcess_CalcTangentSpace |
- aiProcess_Triangulate |
- aiProcess_JoinIdenticalVertices |
- aiProcess_SortByPType);
- if(asmpScene == nullptr) {
- throw std::runtime_error("Failed to read file " + std::string(importer.GetErrorString()));
- }
- scene.bone_name_to_index_map.clear();
- scene.bones.resize(0, skeletalAnimation::Scene::BoneInfo(aiMatrix4x4()));
- //scene.globalTransforms.resize(0);
- scene.hierarchy.resize(0);
- scene.indices.resize(0);
- //scene.localTransforms.resize(0);
- scene.mesh_base_vertex.resize(0);
- scene.vertices.resize(0);
- convertScene();
- }
- void skeletalAnimation::CalcInterpolatedPosition(aiVector3D& Out, float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
- {
- // we need at least two values to interpolate...
- if (pNodeAnim->mNumPositionKeys == 1) {
- Out = pNodeAnim->mPositionKeys[0].mValue;
- return;
- }
- uint PositionIndex = FindPosition(AnimationTimeTicks, pNodeAnim);
- uint NextPositionIndex = PositionIndex + 1;
- assert(NextPositionIndex < pNodeAnim->mNumPositionKeys);
- float t1 = (float)pNodeAnim->mPositionKeys[PositionIndex].mTime;
- float t2 = (float)pNodeAnim->mPositionKeys[NextPositionIndex].mTime;
- float DeltaTime = t2 - t1;
- float Factor = (AnimationTimeTicks - t1) / DeltaTime;
- assert(Factor >= 0.0f && Factor <= 1.0f);
- const aiVector3D& Start = pNodeAnim->mPositionKeys[PositionIndex].mValue;
- const aiVector3D& End = pNodeAnim->mPositionKeys[NextPositionIndex].mValue;
- aiVector3D Delta = End - Start;
- Out = Start + Factor * Delta;
- }
- void skeletalAnimation::CalcInterpolatedRotation(aiQuaternion& Out, float AnimationTime, const aiNodeAnim* pNodeAnim)
- {
- // we need at least two values to interpolate...
- if (pNodeAnim->mNumRotationKeys == 1) {
- Out = pNodeAnim->mRotationKeys[0].mValue;
- return;
- }
- uint RotationIndex = FindRotation(AnimationTime, pNodeAnim);
- uint NextRotationIndex = (RotationIndex + 1);
- assert(NextRotationIndex < pNodeAnim->mNumRotationKeys);
- float DeltaTime = pNodeAnim->mRotationKeys[NextRotationIndex].mTime - pNodeAnim->mRotationKeys[RotationIndex].mTime;
- float Factor = (AnimationTime - (float)pNodeAnim->mRotationKeys[RotationIndex].mTime) / DeltaTime;
- assert(Factor >= 0.0f && Factor <= 1.0f);
- const aiQuaternion& StartRotationQ = pNodeAnim->mRotationKeys[RotationIndex].mValue;
- const aiQuaternion& EndRotationQ = pNodeAnim->mRotationKeys[NextRotationIndex].mValue;
- aiQuaternion::Interpolate(Out, StartRotationQ, EndRotationQ, Factor);
- Out = Out.Normalize();
- }
- uint skeletalAnimation::FindRotation(float AnimationTime, const aiNodeAnim* pNodeAnim)
- {
- assert(pNodeAnim->mNumRotationKeys > 0);
- for (uint i = 0 ; i < pNodeAnim->mNumRotationKeys - 1 ; i++) {
- if (AnimationTime < (float)pNodeAnim->mRotationKeys[i + 1].mTime) {
- return i;
- }
- }
- assert(0);
- }
- uint skeletalAnimation::FindScaling(float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
- {
- assert(pNodeAnim->mNumScalingKeys > 0);
- for (uint i = 0 ; i < pNodeAnim->mNumScalingKeys - 1 ; i++) {
- float t = (float)pNodeAnim->mScalingKeys[i + 1].mTime;
- if (AnimationTimeTicks < t) {
- return i;
- }
- }
- return 0;
- }
- void skeletalAnimation::CalcInterpolatedScaling(aiVector3D& Out, float AnimationTimeTicks, const aiNodeAnim* pNodeAnim)
- {
- // we need at least two values to interpolate...
- if (pNodeAnim->mNumScalingKeys == 1) {
- Out = pNodeAnim->mScalingKeys[0].mValue;
- return;
- }
- uint ScalingIndex = FindScaling(AnimationTimeTicks, pNodeAnim);
- uint NextScalingIndex = ScalingIndex + 1;
- assert(NextScalingIndex < pNodeAnim->mNumScalingKeys);
- float t1 = (float)pNodeAnim->mScalingKeys[ScalingIndex].mTime;
- float t2 = (float)pNodeAnim->mScalingKeys[NextScalingIndex].mTime;
- float DeltaTime = t2 - t1;
- float Factor = (AnimationTimeTicks - (float)t1) / DeltaTime;
- assert(Factor >= 0.0f && Factor <= 1.0f);
- const aiVector3D& Start = pNodeAnim->mScalingKeys[ScalingIndex].mValue;
- const aiVector3D& End = pNodeAnim->mScalingKeys[NextScalingIndex].mValue;
- aiVector3D Delta = End - Start;
- Out = Start + Factor * Delta;
- }
- void skeletalAnimation::loadBone(const aiBone* bone, uint meshI) {
- uint boneId = scene.getBoneId(bone);
- for(uint idWeightPairI = 0; idWeightPairI < bone->mNumWeights; idWeightPairI++) {
- aiVertexWeight idWeightPair = bone->mWeights[idWeightPairI];
- uint globalVertexId = scene.mesh_base_vertex[meshI] + idWeightPair.mVertexId;
- if(globalVertexId >= scene.vertices.size()) {
- throw std::runtime_error("global vertex id is greater than the number of vertices");
- }
- scene.vertices[globalVertexId].addBoneData(boneId, idWeightPair.mWeight);
- }
- }
- void skeletalAnimation::loadMeshes() {
- uint total_vertices = 0;
- scene.mesh_base_vertex.resize(asmpScene->mNumMeshes);
- for(uint meshI = 0; meshI < asmpScene->mNumMeshes; meshI++) {
- aiMesh* mesh = asmpScene->mMeshes[meshI];
- scene.mesh_base_vertex[meshI] = total_vertices;
- for(uint vertI = 0; vertI < mesh->mNumVertices; vertI++) {
- scene.vertices.push_back({});
- scene.vertices[scene.vertices.size()-1].pos = glm::vec3(mesh->mVertices[vertI].x, mesh->mVertices[vertI].y, mesh->mVertices[vertI].z);
- }
- for(uint faceI = 0; faceI < mesh->mNumFaces; faceI++) {
- scene.indices.push_back(mesh->mFaces[faceI].mIndices[0] + scene.mesh_base_vertex[meshI]);
- scene.indices.push_back(mesh->mFaces[faceI].mIndices[1] + scene.mesh_base_vertex[meshI]);
- scene.indices.push_back(mesh->mFaces[faceI].mIndices[2] + scene.mesh_base_vertex[meshI]);
- }
- for(uint boneI = 0; boneI < mesh->mNumBones; boneI++) {
- loadBone(mesh->mBones[boneI], meshI);
- }
- total_vertices += mesh->mNumVertices;
- }
- }
- aiNodeAnim* skeletalAnimation::findNodeAnim(const char* nodeName) {
- if(scene.animationIndex < 0) return nullptr;
- //std::cout << "Node name pointer: " << (void*)nodeName << std::endl;
- aiAnimation& anim = *(asmpScene->mAnimations[scene.animationIndex]);
- for(uint i = 0; i < anim.mNumChannels; i++) {
- //std::cout << std::string(nodeName) << ", " << std::string(anim.mChannels[i]->mNodeName.C_Str()) << std::endl;
- if(strcmp(anim.mChannels[i]->mNodeName.C_Str(), nodeName) == 0) {
- return anim.mChannels[i];
- }
- }
- return nullptr;
- }
- void skeletalAnimation::printOgTree() {
- std::stack<aiNode*> s;
- s.push(asmpScene->mRootNode);
- while(!s.empty()) {
- aiNode* top = s.top();
- s.pop();
- std::cout << top->mName.C_Str() << ", transformation=\n{a1: "
- << top->mTransformation.a1 << ", a2: " << top->mTransformation.a2 << ", a3: " << top->mTransformation.a3 << ", a4: " << top->mTransformation.a4 << std::endl
- << "b1: " << top->mTransformation.b1 << ", b2: " << top->mTransformation.b2 << ", b3: " << top->mTransformation.b3 << ", b4: " << top->mTransformation.b4 << std::endl
- << "c1: " << top->mTransformation.c1 << ", c2: " << top->mTransformation.c2 << ", c3: " << top->mTransformation.c3 << ", c4: " << top->mTransformation.c4 << std::endl
- << "d1: " << top->mTransformation.d1 << ", d2: " << top->mTransformation.d2 << ", d3: " << top->mTransformation.d3 << ", d4: " << top->mTransformation.d4 << "}";
- if(top->mNumChildren > 0)
- std::cout << " children:" << std::endl;
- for(uint i = 0; i < top->mNumChildren; i++) {
- s.push(top->mChildren[i]);
- std::cout << top->mChildren[i]->mName.C_Str() << "-";
- }
- std::cout << std::endl;
- }
- }
- void skeletalAnimation::printTree() {
- std::stack<uint> s;
- std::stack<std::function<void()>> printables;
- s.push(0);
- printables.push([&]() {
- std::cout << std::endl;
- });
- while(!s.empty()) {
- uint i = s.top();
- std::function<void()> print = printables.top();
- s.pop();
- printables.pop();
- print();
- std::cout << scene.hierarchy[i].name << ", transformation=\n{a1: "
- << 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
- << "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
- << "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
- << "d1: " << scene.hierarchy[i].transformation.d1 << ", d2: " << scene.hierarchy[i].transformation.d2 << ", d3: " << scene.hierarchy[i].transformation.d3 << ", d4: " << scene.hierarchy[i].transformation.d4 << "}";
- if(scene.hierarchy[i].firstChild > -1) {
- s.push(scene.hierarchy[i].firstChild);
- printables.push([=]() {
- std::cout << std::endl << std::endl;
- std::cout << scene.hierarchy[i].name << ": ";
- });
- }
- if(scene.hierarchy[i].nextSibling > -1) {
- s.push(scene.hierarchy[i].nextSibling);
- printables.push([]() {
- std::cout << "-";
- });
- }
- }
- }
- // (1) convert N-ary tree to left child right sibling
- // (2) move bone-vertex information into a linear array
- void skeletalAnimation::convertScene() {
- if(asmpScene->mNumAnimations > 0) {
- scene.animationIndex = 0;
- scene.animationDuration = asmpScene->mAnimations[scene.animationIndex]->mDuration;
- }
- scene.globalInverseTransform = asmpScene->mRootNode->mTransformation;
- scene.globalInverseTransform.Inverse();
- std::stack<aiNode*> s;
- s.push(asmpScene->mRootNode);
- struct Node root;
- root.name = std::string(asmpScene->mRootNode->mName.C_Str());
- root.firstChild = asmpScene->mRootNode->mNumChildren ? 1 : -1;
- root.nextSibling = -1;
- root.transformation = asmpScene->mRootNode->mTransformation;
- root.parent = -1;
- scene.hierarchy.push_back(root);
- std::stack<std::function<void(aiNode* st, struct Scene& sceneRef)>> runnables;
- runnables.push([](aiNode* st, struct Scene& sceneRef) {
- });
- while(!s.empty()) {
- aiNode* top = s.top();
- s.pop();
- std::function<void(aiNode* st, struct Scene& sceneRef)> run = runnables.top();
- runnables.pop();
- size_t currentIndex = scene.hierarchy.size();
- run(top, scene);
- for(uint i = 0; i < top->mNumChildren; i++) {
- s.push(top->mChildren[i]);
- struct Node someChild;
- someChild.name = std::string(top->mChildren[i]->mName.C_Str());
- someChild.parent = currentIndex-1;
- someChild.transformation = top->mChildren[i]->mTransformation;
- someChild.nextSibling = i < top->mNumChildren-1 ? currentIndex+i+1 : -1; // Checks if there is a next sibling
- someChild.firstChild = -1; // if someChild has no children this will stay at -1
- scene.hierarchy.push_back(someChild);
- runnables.push([=](aiNode* st, struct Scene& sceneRef) {
- sceneRef.hierarchy[i+currentIndex].firstChild = st->mNumChildren > 0 ? sceneRef.hierarchy.size() : -1;
- });
- }
- }
- /*scene.vertices = {
- {{-0.5f, -1.5f, 0.1f}},
- {{0.5f, -1.5f, 0.1f}},
- {{0.5f, 0.5f, 0.1f}},
- {{-0.5f, 0.5f, 0.1f}}
- };
- scene.indices = {
- 0, 1, 2, 2, 3, 0
- };*/
- loadMeshes();
- }
- void skeletalAnimation::traverse(float animationTime) {
- std::stack<uint> s;
- s.push(0); // index of the root node
- scene.hierarchy[0].localTransformation = scene.hierarchy[0].transformation;
- while (!s.empty())
- {
- uint top = s.top();
- s.pop();
- //std::cout << "Node name: " << top->name << std::endl;
- /*aiNodeAnim* nodeAnim = findNodeAnim(scene.hierarchy[top].name.c_str());
- if(nodeAnim) {
- std::cout << "Found a node animation" << std::endl;
- aiVector3D Scaling;
- CalcInterpolatedScaling(Scaling, animationTime, nodeAnim);
- aiMatrix4x4 ScalingM;
- ScalingM.Scaling(Scaling, ScalingM);
- // Interpolate rotation and generate rotation transformation matrix
- aiQuaternion RotationQ;
- CalcInterpolatedRotation(RotationQ, animationTime, nodeAnim);
- aiMatrix4x4 RotationM = aiMatrix4x4(RotationQ.GetMatrix());
- // Interpolate translation and generate translation transformation matrix
- aiVector3D Translation;
- CalcInterpolatedPosition(Translation, animationTime, nodeAnim);
- aiMatrix4x4 TranslationM;
- TranslationM.Translation(Translation, TranslationM);
- // Combine the above transformations
- scene.hierarchy[top].transformation = TranslationM * RotationM * ScalingM;
- }*/
- if(scene.hierarchy[top].parent > -1) {
- scene.hierarchy[top].localTransformation = scene.hierarchy[scene.hierarchy[top].parent].localTransformation * scene.hierarchy[top].transformation;
- }
- if(scene.bone_name_to_index_map.find(scene.hierarchy[top].name) != scene.bone_name_to_index_map.end()) {
- uint boneIndex = scene.bone_name_to_index_map[scene.hierarchy[top].name];
- scene.finalTransforms[boneIndex] = scene.globalInverseTransform * scene.hierarchy[top].localTransformation * scene.bones[boneIndex].OffsetMatrix;
- }
- if (scene.hierarchy[top].firstChild > -1) s.push(scene.hierarchy[top].firstChild);
- if (scene.hierarchy[top].nextSibling > -1) s.push(scene.hierarchy[top].nextSibling);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement