First pass at blendshapes
[opengl.git] / blendshapes.cpp
diff --git a/blendshapes.cpp b/blendshapes.cpp
new file mode 100644 (file)
index 0000000..8611f62
--- /dev/null
@@ -0,0 +1,55 @@
+#include <assimp/Importer.hpp>
+#include <assimp/postprocess.h>
+#include "blendshapes.hpp"
+#include "util.hpp"
+
+void createBlendshapes(std::vector<std::string> blendshapes, std::string neutral, Program p, Blendshapes *res) {
+
+       Assimp::Importer importer;
+       unsigned int ppFlags = aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_GenNormals;
+       importer.ReadFile(neutral, ppFlags);
+       const aiScene *scene = importer.GetOrphanedScene();
+
+       res->model = new Model(scene, p);
+       
+       assert(scene->mNumMeshes == 1);
+
+       const aiMesh *neutralMesh = scene->mMeshes[0];
+       res->neutral = std::vector<glm::vec3>(neutralMesh->mNumVertices);
+       res->deltas = std::vector<std::vector<glm::vec3>>(blendshapes.size());
+       for (int i = 0; i < neutralMesh->mNumVertices; i++)
+               res->neutral[i] = aiVector3DToVec3(neutralMesh->mVertices[i]);
+
+       for (int i = 0; i < blendshapes.size(); i++) {
+               auto fp = blendshapes[i];
+               const aiScene *blendshape = importer.ReadFile(fp, ppFlags);
+               if (blendshape->mNumMeshes != 1) {
+                       std::cerr << "Too many or too little meshes for the blendshape " << fp << std::endl;
+                       abort();
+               }
+               aiMesh *mesh = blendshape->mMeshes[0];
+               std::vector<glm::vec3> meshDeltas(mesh->mNumVertices);
+               assert(mesh->mNumVertices == neutralMesh->mNumVertices);
+               for (int j = 0; j < mesh->mNumVertices; j++) {
+                       glm::vec3 d = aiVector3DToVec3(mesh->mVertices[j]) - aiVector3DToVec3(neutralMesh->mVertices[j]);
+                       meshDeltas[j] = d;
+               }
+               res->deltas[i] = meshDeltas;
+       }
+
+}
+
+void interpolateBlendshapes(Blendshapes *b, std::vector<float> weights) {
+       assert(weights.size() == b->deltas.size());
+       const Model::Mesh mesh = b->model->meshes[0];
+
+       for (int i = 0; i < mesh.ai.mNumVertices; i++) {
+               glm::vec3 pos = b->neutral[i];
+               for (int j = 0; j < b->deltas.size(); j++) {
+                       pos += b->deltas[j][i] * weights[j];
+               }
+               mesh.ai.mVertices[i] = vec3ToaiVector3D(pos);
+       }
+
+       mesh.updatePosBuffer();
+}