SuperimposeMesh
All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
Model.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-2019 Istituto Italiano di Tecnologia (IIT)
3  *
4  * This software may be modified and distributed under the terms of the
5  * BSD 3-Clause license. See the accompanying LICENSE file for details.
6  */
7 
9 
10 #include <iostream>
11 
12 #include <assimp/Importer.hpp>
13 #include <assimp/postprocess.h>
14 
15 #include <glm/glm.hpp>
16 
17 #include <opencv2/core/core.hpp>
18 #include <opencv2/highgui/highgui.hpp>
19 
20 
21 Model::Model(const GLchar* path)
22 {
23  loadModel(path);
24 }
25 
26 
27 void Model::Draw(Shader shader)
28 {
29  for(GLuint i = 0; i < meshes_.size(); i++)
30  {
31  meshes_[i].Draw(shader);
32  }
33 }
34 
35 
37 {
38  return (textures_loaded_.size() > 0 ? true : false);
39 }
40 
41 
42 void Model::loadModel(std::string path)
43 {
44  Assimp::Importer import;
45  const aiScene* scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
46 
47  if(!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
48  {
49  std::cerr << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl;
50  return;
51  }
52 
53  size_t foundpos = path.find_last_of('/');
54  if (foundpos == std::string::npos)
55  {
56  directory_ = ".";
57  }
58  else
59  {
60  directory_ = path.substr(0, foundpos);
61  }
62 
63  processNode(scene->mRootNode, scene);
64 }
65 
66 
67 void Model::processNode(aiNode* node, const aiScene* scene)
68 {
69  /* Process all the node's meshes (if any). */
70  for (GLuint i = 0; i < node->mNumMeshes; ++i)
71  {
72  aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
73  meshes_.push_back(processMesh(mesh, scene));
74  }
75 
76  /* Then do the same for each of its children. */
77  for (GLuint i = 0; i < node->mNumChildren; ++i)
78  {
79  processNode(node->mChildren[i], scene);
80  }
81 }
82 
83 
84 Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)
85 {
86  std::vector<Mesh::Vertex> vertices;
87  std::vector<GLuint> indices;
88  std::vector<Mesh::Texture> textures;
89 
90  /* Process vertices. */
91  for (GLuint i = 0; i < mesh->mNumVertices; ++i)
92  {
93  Mesh::Vertex vertex;
94 
95  /* Process vertex positions, normals and texture coordinates. */
96  vertex.Position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
97  vertex.Normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
98 
99  /* Does the mesh contain texture coordinates? */
100  if (mesh->mTextureCoords[0])
101  {
102  vertex.TexCoords = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
103  }
104  else
105  {
106  vertex.TexCoords = glm::vec2(0.0f, 0.0f);
107  }
108 
109  vertices.push_back(vertex);
110  }
111 
112  /* Process indices. */
113  for (GLuint i = 0; i < mesh->mNumFaces; ++i)
114  {
115  aiFace face = mesh->mFaces[i];
116  for (GLuint j = 0; j < face.mNumIndices; ++j)
117  {
118  indices.push_back(face.mIndices[j]);
119  }
120  }
121 
122  /* Process textures. */
123  /* The texture code is taken as-is. The tutorial on texture was skipped. */
124  if (mesh->mMaterialIndex > 0)
125  {
126  aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
127 
128  std::vector<Mesh::Texture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
129  textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
130 
131  std::vector<Mesh::Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
132  textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
133  }
134 
135  return Mesh(vertices, indices, textures);
136 }
137 
138 
139 std::vector<Mesh::Texture> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName)
140 {
141  std::vector<Mesh::Texture> textures;
142  for (GLuint i = 0; i < mat->GetTextureCount(type); ++i)
143  {
144  aiString str;
145  mat->GetTexture(type, i, &str);
146  GLboolean skip = false;
147  for (GLuint j = 0; j < textures_loaded_.size(); ++j)
148  {
149  if (textures_loaded_[j].path == str)
150  {
151  textures.push_back(textures_loaded_[j]);
152  skip = true;
153  break;
154  }
155  }
156 
157  /* If texture hasn't been loaded already, load it. */
158  if (!skip)
159  {
160  Mesh::Texture texture;
161 
162  texture.id = TextureFromFile(str.C_Str(), directory_);
163  texture.type = typeName;
164  texture.path = str;
165  textures.push_back(texture);
166 
167  /* Add to loaded textures. */
168  textures_loaded_.push_back(texture);
169  }
170  }
171 
172  return textures;
173 }
174 
175 
176 GLint Model::TextureFromFile(const char* path, std::string directory)
177 {
178  std::string filename = directory + "/" + std::string(path);
179  cv::Mat image = cv::imread(filename, cv::IMREAD_ANYCOLOR);
180 
181  /* Generate texture ID and load texture data. */
182  GLuint textureID;
183  glGenTextures(1, &textureID);
184 
185  /* Assign texture to ID. */
186  glBindTexture(GL_TEXTURE_2D, textureID);
187  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, image.ptr());
188  glGenerateMipmap(GL_TEXTURE_2D);
189 
190  /* Parameters. */
191  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
192  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
193  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
194  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
195  glBindTexture(GL_TEXTURE_2D, 0);
196 
197  return textureID;
198 }
GLuint id
Definition: Mesh.h:34
void Draw(Shader shader)
Definition: Model.cpp:27
Definition: Shader.h:17
Definition: Mesh.h:23
Mesh processMesh(aiMesh *mesh, const aiScene *scene)
Definition: Model.cpp:84
std::vector< Mesh::Texture > textures_loaded_
Definition: Model.h:47
glm::vec3 Position
Definition: Mesh.h:27
void loadModel(std::string path)
Definition: Model.cpp:42
Model(const GLchar *path)
Definition: Model.cpp:21
glm::vec3 Normal
Definition: Mesh.h:28
std::string directory_
Definition: Model.h:45
std::string type
Definition: Mesh.h:35
bool has_texture()
Definition: Model.cpp:36
void processNode(aiNode *node, const aiScene *scene)
Definition: Model.cpp:67
GLint TextureFromFile(const char *path, std::string directory)
Definition: Model.cpp:176
aiString path
Definition: Mesh.h:36
std::vector< Mesh::Texture > loadMaterialTextures(aiMaterial *mat, aiTextureType type, std::string typeName)
Definition: Model.cpp:139
glm::vec2 TexCoords
Definition: Mesh.h:29
std::vector< Mesh > meshes_
Definition: Model.h:43