First pass at blendshapes
[opengl.git] / blendshapes.cpp
1 #include <assimp/Importer.hpp>
2 #include <assimp/postprocess.h>
3 #include "blendshapes.hpp"
4 #include "util.hpp"
5
6 void createBlendshapes(std::vector<std::string> blendshapes, std::string neutral, Program p, Blendshapes *res) {
7
8         Assimp::Importer importer;
9         unsigned int ppFlags = aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_GenNormals;
10         importer.ReadFile(neutral, ppFlags);
11         const aiScene *scene = importer.GetOrphanedScene();
12
13         res->model = new Model(scene, p);
14         
15         assert(scene->mNumMeshes == 1);
16
17         const aiMesh *neutralMesh = scene->mMeshes[0];
18         res->neutral = std::vector<glm::vec3>(neutralMesh->mNumVertices);
19         res->deltas = std::vector<std::vector<glm::vec3>>(blendshapes.size());
20         for (int i = 0; i < neutralMesh->mNumVertices; i++)
21                 res->neutral[i] = aiVector3DToVec3(neutralMesh->mVertices[i]);
22
23         for (int i = 0; i < blendshapes.size(); i++) {
24                 auto fp = blendshapes[i];
25                 const aiScene *blendshape = importer.ReadFile(fp, ppFlags);
26                 if (blendshape->mNumMeshes != 1) {
27                         std::cerr << "Too many or too little meshes for the blendshape " << fp << std::endl;
28                         abort();
29                 }
30                 aiMesh *mesh = blendshape->mMeshes[0];
31                 std::vector<glm::vec3> meshDeltas(mesh->mNumVertices);
32                 assert(mesh->mNumVertices == neutralMesh->mNumVertices);
33                 for (int j = 0; j < mesh->mNumVertices; j++) {
34                         glm::vec3 d = aiVector3DToVec3(mesh->mVertices[j]) - aiVector3DToVec3(neutralMesh->mVertices[j]);
35                         meshDeltas[j] = d;
36                 }
37                 res->deltas[i] = meshDeltas;
38         }
39
40 }
41
42 void interpolateBlendshapes(Blendshapes *b, std::vector<float> weights) {
43         assert(weights.size() == b->deltas.size());
44         const Model::Mesh mesh = b->model->meshes[0];
45
46         for (int i = 0; i < mesh.ai.mNumVertices; i++) {
47                 glm::vec3 pos = b->neutral[i];
48                 for (int j = 0; j < b->deltas.size(); j++) {
49                         pos += b->deltas[j][i] * weights[j];
50                 }
51                 mesh.ai.mVertices[i] = vec3ToaiVector3D(pos);
52         }
53
54         mesh.updatePosBuffer();
55 }