1
+ #include < GL\glew.h>
2
+ #include < GL\GL.h>
3
+
4
+ #include < assimp\Importer.hpp>
5
+ #include < assimp\scene.h>
6
+ #include < assimp\postprocess.h>
7
+
8
+ #include < glm\glm.hpp>
9
+ #include < glm\gtc\type_ptr.hpp>
10
+
11
+ #include < string>
12
+ #include < vector>
13
+ #include < map>
14
+ #include < memory>
15
+ #include < iostream>
16
+
17
+ using namespace std ;
18
+
19
+ class Model {
20
+
21
+ class Mesh {
22
+
23
+ private:
24
+ Model* model;
25
+
26
+ public:
27
+ Mesh (const aiMesh* mesh, Model* model) :
28
+ buffer{ 0 }, vao{ 0 } {
29
+ this ->model = model;
30
+ load (mesh);
31
+ create ();
32
+ }
33
+
34
+ ~Mesh () {
35
+ glDeleteBuffers (4 , buffer);
36
+ glDeleteVertexArrays (1 , &vao);
37
+ }
38
+
39
+ // dibujar el mesh
40
+ void draw () {
41
+ glBindVertexArray (vao);
42
+ glDrawElements (GL_TRIANGLES, indices.size (), GL_UNSIGNED_INT, NULL );
43
+ glBindVertexArray (0 );
44
+ };
45
+
46
+ void draw (GLuint program) {
47
+ glUniform3fv (glGetUniformLocation (program, " material.ambient" ), 1 , color_ambient);
48
+ glUniform3fv (glGetUniformLocation (program, " material.diffuse" ), 1 , color_diffuse);
49
+ glUniform3fv (glGetUniformLocation (program, " material.specular" ), 1 , color_specular);
50
+ glUniform3fv (glGetUniformLocation (program, " material.emissive" ), 1 , color_emissive);
51
+ glUniform1f (glGetUniformLocation (program, " material.shininess" ), shininess);
52
+ glUniform1f (glGetUniformLocation (program, " material.shininess_strength" ), shininess_strength);
53
+
54
+ glBindVertexArray (vao);
55
+ glDrawElements (GL_TRIANGLES, indices.size (), GL_UNSIGNED_INT, NULL );
56
+ glBindVertexArray (0 );
57
+ };
58
+
59
+ // inicializar el mesh
60
+ void init (const aiMesh* mesh) {
61
+ load (mesh);
62
+ create ();
63
+ };
64
+
65
+ private:
66
+ vector<glm::vec3> vertex;
67
+ vector<glm::vec3> normal ;
68
+ vector<glm::vec2> uv;
69
+ vector<unsigned int > indices;
70
+
71
+ GLuint buffer[4 ];
72
+ GLuint vao;
73
+
74
+ float shininess, shininess_strength;
75
+ float color_ambient[4 ] = { 1 , 1 , 1 , 1 };
76
+ float color_diffuse[4 ] = { 1 , 1 , 1 , 1 };
77
+ float color_specular[4 ] = { 0.0 };
78
+ float color_emissive[4 ] = { 0.0 };
79
+
80
+ // obtener los datos de cada mesh
81
+ void load (const aiMesh* mesh) {
82
+
83
+ vertex.reserve (mesh->mNumVertices );
84
+ uv.reserve (mesh->mNumVertices );
85
+ normal .reserve (mesh->mNumVertices );
86
+ indices.reserve (3 * mesh->mNumFaces );
87
+
88
+ for (unsigned int i = 0 ; i < mesh->mNumVertices ; i++) {
89
+
90
+ // Obtener la posicion de cada vertice
91
+ const aiVector3D* pos = &(mesh->mVertices [i]);
92
+ vertex.push_back (glm::vec3 (pos->x , pos->y , pos->z ));
93
+
94
+ // Obtener las coordenadas de textura
95
+ if (mesh->HasTextureCoords (0 )) {
96
+ const aiVector3D* UVW = &(mesh->mTextureCoords [0 ][i]);
97
+ uv.push_back (glm::vec2 (UVW->x , UVW->y ));
98
+ }
99
+ else uv.push_back (glm::vec2 (0 , 0 ));
100
+
101
+ // Obtener los vectores normales
102
+ if (mesh->HasNormals ()) {
103
+ const aiVector3D* n = &(mesh->mNormals [i]);
104
+ normal .push_back (glm::vec3 (n->x , n->y , n->z ));
105
+ }
106
+ }
107
+
108
+ // Obtener los indices
109
+ for (unsigned int i = 0 ; i < mesh->mNumFaces ; i++) {
110
+ indices.push_back (mesh->mFaces [i].mIndices [0 ]);
111
+ indices.push_back (mesh->mFaces [i].mIndices [1 ]);
112
+ indices.push_back (mesh->mFaces [i].mIndices [2 ]);
113
+ }
114
+
115
+ if (mesh->mMaterialIndex >= 0 ) {
116
+ // obtener el material correspondiente a este Mesh
117
+ const aiMaterial* material = model->scene ->mMaterials [mesh->mMaterialIndex ];
118
+
119
+ if (material->Get (AI_MATKEY_SHININESS, shininess) != AI_SUCCESS) shininess = 128.0 ;
120
+ if (material->Get (AI_MATKEY_SHININESS_STRENGTH, shininess_strength) != AI_SUCCESS) shininess_strength = 1.0 ;
121
+
122
+ aiColor4D diffuse, ambient, specular, emisive;
123
+
124
+ if (aiGetMaterialColor (material, AI_MATKEY_COLOR_DIFFUSE, &diffuse) == AI_SUCCESS) {
125
+ aiColorToFloat (diffuse, color_diffuse);
126
+ }
127
+
128
+ if (aiGetMaterialColor (material, AI_MATKEY_COLOR_SPECULAR, &specular) == AI_SUCCESS) {
129
+ aiColorToFloat (specular, color_specular);
130
+ }
131
+
132
+ if (aiGetMaterialColor (material, AI_MATKEY_COLOR_AMBIENT, &ambient) == AI_SUCCESS) {
133
+ aiColorToFloat (ambient, color_ambient);
134
+ }
135
+
136
+ if (aiGetMaterialColor (material, AI_MATKEY_COLOR_EMISSIVE, &emisive) == AI_SUCCESS) {
137
+ aiColorToFloat (emisive, color_emissive);
138
+ }
139
+ }
140
+ }
141
+
142
+ inline void aiColorToFloat (aiColor4D& src, float dst[4 ]) {
143
+ dst[0 ] = src.r ;
144
+ dst[1 ] = src.g ;
145
+ dst[2 ] = src.b ;
146
+ dst[3 ] = src.a ;
147
+ }
148
+
149
+ void create () {
150
+ // generar y activar el VAO
151
+ glGenVertexArrays (1 , &vao);
152
+ glBindVertexArray (vao);
153
+
154
+ // generar dos ids para los buffer
155
+ glGenBuffers (4 , buffer);
156
+
157
+ // buffer de vertices
158
+ glBindBuffer (GL_ARRAY_BUFFER, buffer[0 ]);
159
+ glBufferData (GL_ARRAY_BUFFER, vertex.size () * sizeof (glm::vec3), &vertex[0 ], GL_STATIC_DRAW);
160
+ glVertexAttribPointer (0 , 3 , GL_FLOAT, GL_FALSE, 0 , NULL );
161
+ glEnableVertexAttribArray (0 );
162
+
163
+ // buffer de textura
164
+ if (!uv.empty ()) {
165
+ glBindBuffer (GL_ARRAY_BUFFER, buffer[1 ]);
166
+ glBufferData (GL_ARRAY_BUFFER, uv.size () * sizeof (glm::vec2), &uv[0 ], GL_STATIC_DRAW);
167
+ glVertexAttribPointer (1 , 2 , GL_FLOAT, GL_FALSE, 0 , NULL );
168
+ glEnableVertexAttribArray (1 );
169
+ }
170
+
171
+ // buffer de normales
172
+ if (!normal .empty ()) {
173
+ glBindBuffer (GL_ARRAY_BUFFER, buffer[2 ]);
174
+ glBufferData (GL_ARRAY_BUFFER, normal .size () * sizeof (glm::vec3), &normal [0 ], GL_STATIC_DRAW);
175
+ glVertexAttribPointer (2 , 3 , GL_FLOAT, GL_FALSE, 0 , NULL );
176
+ glEnableVertexAttribArray (2 );
177
+ }
178
+
179
+ // buffer de indices
180
+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffer[3 ]);
181
+ glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size () * sizeof (unsigned int ), &indices[0 ], GL_STATIC_DRAW);
182
+
183
+ // desactivar el VAO
184
+ glBindVertexArray (0 );
185
+ }
186
+ };
187
+
188
+ public:
189
+ string directory;
190
+ const aiScene* scene;
191
+ map<string, GLuint> textures;
192
+
193
+ private:
194
+ vector<shared_ptr<Mesh>> meshes;
195
+
196
+ // procesar recusivamente cada nodo de la escena
197
+ void processNode (const aiNode* node, const aiScene* scene)
198
+ {
199
+ // obtener los mesh de esta escena
200
+ for (unsigned int i = 0 ; i < node->mNumMeshes ; i++) {
201
+ shared_ptr<Mesh> mesh (new Mesh (scene->mMeshes [node->mMeshes [i]], this ));
202
+ meshes.push_back (mesh);
203
+ }
204
+
205
+ // procesar los hijos del nodo
206
+ for (unsigned int i = 0 ; i < node->mNumChildren ; i++)
207
+ this ->processNode (node->mChildren [i], scene);
208
+ }
209
+
210
+ public:
211
+ // cargar el archivo deseado
212
+ void init (const std::string& file_name) {
213
+
214
+ size_t index = file_name.find_last_of (" \\ /" );
215
+ directory = index == string::npos ? " " : file_name.substr (0 , index );
216
+
217
+ Assimp::Importer importer;
218
+ scene = importer.ReadFile (file_name, aiProcess_Triangulate | aiProcess_FlipUVs);
219
+
220
+ if (scene && scene->mRootNode )
221
+ processNode (scene->mRootNode , scene);
222
+ else cout << importer.GetErrorString () << endl;
223
+ }
224
+
225
+ // dibujar la escena completa
226
+ void draw () {
227
+ for (auto & m : meshes) m->draw ();
228
+ }
229
+
230
+ void draw (GLuint program) {
231
+ for (auto & m : meshes) m->draw (program);
232
+ }
233
+ };
0 commit comments