alistair
3 years ago
8 changed files with 579 additions and 79 deletions
@ -0,0 +1,233 @@
@@ -0,0 +1,233 @@
|
||||
#include "mesh.h" |
||||
#include "stb_image.h" |
||||
|
||||
#include <assimp/Importer.hpp> |
||||
#include <assimp/material.h> |
||||
|
||||
Mesh::Mesh(std::vector<struct vertex> vertices, std::vector<unsigned int> indices,
|
||||
std::vector<struct texture> textures)
|
||||
{ |
||||
this->vertices = vertices; |
||||
this->indices = indices; |
||||
this->textures = textures; |
||||
} |
||||
|
||||
|
||||
void Mesh::setupMesh()
|
||||
{ |
||||
glGenVertexArrays(1, &VAO); |
||||
glGenBuffers(1, &VBO); |
||||
glGenBuffers(1, &EBO); |
||||
|
||||
glBindVertexArray(VAO); |
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO); |
||||
glBufferData( GL_ARRAY_BUFFER, vertices.size() * sizeof(vertex), &vertices[0], GL_STATIC_DRAW); |
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); |
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); |
||||
|
||||
glEnableVertexAttribArray(0); |
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)0); |
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)offsetof(vertex, normal)); |
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)offsetof(vertex, texture_coords)); |
||||
|
||||
glBindVertexArray(0); |
||||
|
||||
} |
||||
|
||||
void Mesh::draw(Shader &shader) { |
||||
unsigned int specularNr = 1; |
||||
unsigned int diffuseNr = 1; |
||||
/*
|
||||
for(unsigned int i = 0; i < textures.size(); i++) |
||||
{ |
||||
glActiveTexture(GL_TEXTURE0 + i); // activate proper texture unit before binding
|
||||
// retrieve texture number (the N in diffuse_textureN)
|
||||
std::string number; |
||||
std::string name = textures[i].type; |
||||
if(name == "texture_diffuse") |
||||
number = std::to_string(diffuseNr++); |
||||
else if(name == "texture_specular") |
||||
number = std::to_string(specularNr++); |
||||
|
||||
shader.setFloat(("material." + name + number).c_str(), i); |
||||
glBindTexture(GL_TEXTURE_2D, textures[i].id); |
||||
} |
||||
glActiveTexture(GL_TEXTURE0); |
||||
*/ |
||||
|
||||
// draw mesh
|
||||
glBindVertexArray(VAO); |
||||
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); |
||||
glBindVertexArray(0); |
||||
} |
||||
|
||||
|
||||
|
||||
/** Model */ |
||||
|
||||
void Model::draw(Shader &shader) |
||||
{ |
||||
for(auto mesh : meshes) { |
||||
mesh.draw(shader); |
||||
} |
||||
} |
||||
|
||||
void Model::load_model(std::string path) { |
||||
Assimp::Importer importer; |
||||
const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); |
||||
|
||||
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||
{ |
||||
std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl; |
||||
throw std::exception(); |
||||
return; |
||||
} |
||||
|
||||
directory = path.substr(0, path.find_last_of('/')); |
||||
|
||||
process_node(scene->mRootNode, scene); |
||||
} |
||||
|
||||
void Model::process_node(aiNode *node, const aiScene *scene)
|
||||
{ |
||||
for (unsigned int i = 0; i < node->mNumMeshes; i++) { |
||||
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; |
||||
meshes.push_back(process_mesh(mesh, scene)); |
||||
} |
||||
|
||||
// recurse
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++) { |
||||
process_node(node->mChildren[i], scene); |
||||
} |
||||
} |
||||
|
||||
Mesh Model::process_mesh(aiMesh *mesh, const aiScene *scene)
|
||||
{ |
||||
std::vector<vertex> vertices; |
||||
std::vector<unsigned int> indices; |
||||
std::vector<texture> textures; |
||||
|
||||
for (unsigned int i = 0 ; i < mesh->mNumVertices; i++) { |
||||
glm::vec3 pos = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); |
||||
glm::vec3 norm = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z); |
||||
|
||||
vertex v; |
||||
v.position = pos; |
||||
v.normal = norm; |
||||
|
||||
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; |
||||
v.texture_coords = vec; |
||||
} else { |
||||
v.texture_coords = glm::vec2(0.0f); |
||||
} |
||||
|
||||
|
||||
vertices.push_back(v); |
||||
|
||||
} |
||||
|
||||
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]); |
||||
} |
||||
|
||||
if (mesh->mMaterialIndex >= 0) { |
||||
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; |
||||
|
||||
std::vector<texture> diffuseMaps = load_material_textures(material, aiTextureType_DIFFUSE, "texture_diffuse"); |
||||
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); |
||||
|
||||
std::vector<texture> specularMaps = load_material_textures(material, aiTextureType_SPECULAR, "texture_specular"); |
||||
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); |
||||
|
||||
} |
||||
|
||||
return Mesh(vertices, indices, textures); |
||||
|
||||
} |
||||
|
||||
|
||||
unsigned int Model::texture_from_file(const char *fname, std::string directory) { |
||||
std::string filename = std::string(fname); |
||||
filename = directory + '/' + filename; |
||||
|
||||
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 |
||||
{ |
||||
stbi_image_free(data); |
||||
} |
||||
|
||||
return textureID; |
||||
} |
||||
|
||||
|
||||
std::vector<texture> Model::load_material_textures(aiMaterial *mat, aiTextureType type, std::string typeName) { |
||||
std::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 < textures_loaded.size(); j++) { |
||||
if (std::strcmp(textures_loaded[j].path.data(), str.C_Str()) == 0) { |
||||
textures.push_back(textures_loaded[j]); |
||||
skip = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (!skip) { |
||||
texture texture; |
||||
texture.id = texture_from_file(str.C_Str(), directory); |
||||
texture.type = typeName; |
||||
texture.path = str.C_Str(); |
||||
textures.push_back(texture); |
||||
textures_loaded.push_back(texture); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
return textures; |
||||
} |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,60 @@
@@ -0,0 +1,60 @@
|
||||
|
||||
#ifndef MESH_H |
||||
#define MESH_H |
||||
|
||||
#include <vector> |
||||
#include <string> |
||||
#include "shaders.h" |
||||
#include <glm/glm.hpp> |
||||
|
||||
#include <assimp/scene.h> |
||||
#include <assimp/postprocess.h> |
||||
|
||||
|
||||
struct vertex { |
||||
glm::vec3 position; |
||||
glm::vec3 normal; |
||||
glm::vec2 texture_coords; |
||||
}; |
||||
|
||||
struct texture { |
||||
unsigned int id; |
||||
std::string type; |
||||
std::string path; |
||||
}; |
||||
|
||||
class Mesh { |
||||
public: |
||||
std::vector<struct vertex> vertices; |
||||
std::vector<unsigned int> indices; |
||||
std::vector<struct texture> textures; |
||||
|
||||
Mesh(std::vector<struct vertex> vertices,
|
||||
std::vector<unsigned int> indices,
|
||||
std::vector<struct texture> textures); |
||||
void draw(Shader &shader); |
||||
private: |
||||
unsigned int VAO, VBO, EBO; |
||||
void setupMesh(); |
||||
}; |
||||
|
||||
|
||||
class Model { |
||||
public: |
||||
Model(std::string path) { |
||||
load_model(path); |
||||
} |
||||
void draw(Shader &shader); |
||||
private: |
||||
std::vector<Mesh> meshes; |
||||
std::string directory; |
||||
std::vector<texture> textures_loaded; |
||||
|
||||
unsigned int texture_from_file(const char *fname, std::string directory);
|
||||
void load_model(std::string path); |
||||
void process_node(aiNode *node, const aiScene *scene); |
||||
Mesh process_mesh(aiMesh *mesh, const aiScene *scene); |
||||
std::vector<texture> load_material_textures(aiMaterial *mat, aiTextureType type, std::string type_name); |
||||
}; |
||||
|
||||
#endif |
Loading…
Reference in new issue