Do boning and animation properly
[opengl.git] / model.hpp
1 #include <vector>
2 #include <map>
3 #include <set>
4 #ifdef __APPLE__
5 #include <GL/glew.h>
6 #else
7 #include <OpenGL/glew.h>
8 #endif
9 #include <glm/glm.hpp>
10 #include <assimp/scene.h>
11 #include "material.hpp"
12 #include "program.hpp"
13 #include "skybox.hpp"
14
15 inline glm::mat4 aiMatrixToMat4(aiMatrix4x4 from) {
16         glm::mat4 to;
17         for (int i = 0; i < 4; i++)
18                 for (int j = 0; j < 4; j++)
19                         to[i][j] = from[j][i];
20         return to;
21 }
22
23 class Model {
24
25         struct Animation {
26                 double duration;
27                 std::vector<const aiNodeAnim*> nodeAnims;
28         };
29
30         typedef std::map<std::string, std::pair<unsigned int, aiBone*>> BoneMap;
31         typedef std::map<std::string, std::vector<const Animation>> AnimMap;
32         typedef std::map<std::string, glm::mat4> BoneTransforms;
33
34         struct VertBones {
35                 unsigned int ids[4] = {0, 0, 0 ,0};
36                 float weights[4] = {1, 0, 0, 0};
37         };
38
39         struct Mesh {
40                 Mesh(const aiMesh *aiMesh, GLuint progId);
41                 GLuint progId, vao, numIndices;
42                 unsigned int materialIndex;
43                 BoneMap boneMap;
44         };
45         
46         public:
47                 Model(const aiScene *scene, Program p);
48                 void draw(Skybox skybox, const float tick) const;
49
50                 class Node {
51                         public:
52                                 Node(const aiNode &aiNode, GLuint progId, AnimMap *animMap);
53                                 void draw(const std::vector<Mesh> &meshes, const std::vector<Material> &materials, const Skybox s, const float tick, const BoneTransforms &boneTransforms, glm::mat4 parentModel) const;
54                                 const std::vector<Node*> &getChildren() const { return children; }
55                                 Node* findNode(const aiNode &aiNode);
56                                 const aiNode &ai;
57
58                                 // an extra transform
59                                 glm::mat4 transform = glm::mat4(1);
60                                 
61                                 glm::mat4 totalTrans(const glm::mat4 parentTrans, const float tick) const;
62
63                         private:
64                                 const GLuint progId;
65
66                                 const AnimMap *animMap;
67                                 std::vector<Node*> children;
68                                 std::vector<unsigned int> meshIndices;
69                 };
70                 
71                 Node* getRoot() { return root; }
72                 Node* find(const aiString name) const;
73                 Node* find(const std::string &name) const;
74         
75         private:
76                 const Program program;
77                 
78                 std::vector<Mesh> meshes;
79                 Node *root;
80
81                 std::vector<Material> materials;
82
83                 AnimMap animMap;
84
85                 BoneTransforms calcBoneTransforms(const Node &n, const float tick, const std::set<std::string> bones, const glm::mat4 parentTrans) const;
86                 void loadModel(const std::string &path);
87 };