-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathModel.cpp
241 lines (203 loc) · 7.3 KB
/
Model.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#include "Model.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
uint TextureFromFile(const char *path, const string &directory, bool gamma = false);
Model::Model(string path) {
loadModel(path);
}
void Model::draw(Shader &shader) {
for (uint i = 0; i < meshes.size(); i++)
{
meshes[i].draw(shader);
}
}
void Model::loadModel(string path) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
cout << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
directory = path.substr(0, path.find_last_of('\\'));
#else
directory = path.substr(0, path.find_last_of('/'));
#endif
#ifdef WINDOWS
directory = path.substr(0, path.find_last_of('\\'));
#else
directory = path.substr(0, path.find_last_of('/'));
#endif
processNode(scene->mRootNode, scene);
}
void Model::processNode(aiNode *node, const aiScene *scene) {
// process all the node's meshes (if any)
for(unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
// then do the same for each of its children
for(unsigned int i = 0; i < node->mNumChildren; i++)
{
processNode(node->mChildren[i], scene);
}
}
Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene) {
string name;
vector<Vertex> vertices;
vector<uint> indices;
vector<Texture> textures;
name = mesh->mName.C_Str();
glm::vec3 min(mesh->mVertices[0].x, mesh->mVertices[0].y, mesh->mVertices[0].z);
glm::vec3 max(mesh->mVertices[0].x, mesh->mVertices[0].y, mesh->mVertices[0].z);
for(unsigned int i = 0; i < mesh->mNumVertices; i++)
{
// process vertex positions, normals and texture coordinates
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
if (vector.x < min.x) min.x = vector.x;
if (vector.x > max.x) max.x = vector.x;
if (vector.y < min.y) min.y = vector.y;
if (vector.y > max.y) max.y = vector.y;
if (vector.z < min.z) min.z = vector.z;
if (vector.z > max.z) max.z = vector.z;
Vertex vertex;
vertex.Position = vector;
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
if(mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
{
glm::vec2 vec;
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoords = vec;
}
else
vertex.TexCoords = glm::vec2(0.0f, 0.0f);
vertices.push_back(vertex);
}
// process indices
for(unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
// process material
if(mesh->mMaterialIndex >= 0)
{
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
vector<Texture> diffuseMaps = loadMaterialTextures(material,
aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
vector<Texture> specularMaps = loadMaterialTextures(material,
aiTextureType_SPECULAR, "texture_specular");
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
}
return Mesh(name, vertices, indices, textures, min, max);
}
vector<Texture> Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type, string typeName)
{
vector<Texture> textures;
for(unsigned int i = 0; i < mat->GetTextureCount(type); i++)
{
aiString str;
mat->GetTexture(type, i, &str);
bool skip = false;
for(unsigned int j = 0; j < loadedTextures.size(); j++)
{
if(std::strcmp(loadedTextures[j].path.data(), str.C_Str()) == 0)
{
textures.push_back(loadedTextures[j]);
skip = true;
break;
}
}
if(!skip)
{ // if texture hasn't been loaded already, load it
Texture texture;
texture.id = TextureFromFile(str.C_Str(), directory);
texture.type = typeName;
texture.path = str.C_Str();
textures.push_back(texture);
loadedTextures.push_back(texture); // add to loaded textures
}
}
return textures;
}
glm::vec3 Model::getMinVec(string meshName) {
for (Mesh mesh : meshes) {
if (mesh.name == meshName) return mesh.getMinVec();
}
}
glm::vec3 Model::getMaxVec(string meshName) {
for (Mesh mesh : meshes) {
if (mesh.name == meshName) return mesh.getMaxVec();
}
}
glm::vec3 Model::getOrigin(string name) {
for (Mesh mesh : meshes) {
if (mesh.name == name) return mesh.getOrigin();
}
}
glm::vec3 Model::getMinVec() {
glm::vec3 minVec = glm::vec3(0,0,0);
for (Mesh mesh : meshes) {
glm::vec3 tmp = mesh.getMinVec();
if (glm::length(tmp) > glm::length(minVec))
minVec = mesh.getMinVec();
}
return minVec;
}
glm::vec3 Model::getMaxVec() {
glm::vec3 maxVec = glm::vec3(0,0,0);
for (Mesh mesh : meshes) {
glm::vec3 tmp = mesh.getMaxVec();
if (glm::length(tmp) > glm::length(maxVec))
maxVec = mesh.getMaxVec();
}
return maxVec;
}
uint TextureFromFile(const char *path, const string &directory, bool gamma)
{
string filename = string(path);
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
filename = directory + '\\' + filename;
#else
filename = directory + '/' + filename;
#endif
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
if (data)
{
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(data);
}
else
{
std::cout << "Texture failed to load at path: " << path << std::endl;
stbi_image_free(data);
}
return textureID;
}