-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Model loading helper lib with Assimp
- Loading branch information
1 parent
29bf06d
commit 97d5e82
Showing
2 changed files
with
330 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
#ifndef __MYLIB_MESH_HPP__ | ||
#define __MYLIB_MESH_HPP__ | ||
|
||
#ifdef _DEBUG | ||
#undef _NDEBUG | ||
#undef NDEBUG | ||
#else | ||
#define _NDEBUG | ||
#define NDEBUG | ||
#endif | ||
|
||
#include <iostream> | ||
#include <vector> | ||
#include <string> | ||
#include <sstream> | ||
|
||
#include <epoxy/gl.h> | ||
#ifdef _WIN32 | ||
#include <epoxy/wgl.h> | ||
#else | ||
#include <epoxy/glx.h> | ||
#endif | ||
|
||
#include <glm/glm.hpp> | ||
|
||
#include "mylib.hpp" | ||
|
||
namespace mylib | ||
{ | ||
|
||
struct Vertex | ||
{ | ||
glm::vec3 position; | ||
glm::vec3 normal; | ||
glm::vec2 texCoords; | ||
}; | ||
|
||
struct Texture | ||
{ | ||
GLuint id; | ||
std::string type; | ||
aiString path; | ||
}; | ||
|
||
class Mesh | ||
{ | ||
public: | ||
//! mesh data | ||
std::vector<Vertex> vertices; | ||
std::vector<GLuint> indices; | ||
std::vector<Texture> textures; | ||
|
||
Mesh( | ||
std::vector<Vertex> vertices, | ||
std::vector<GLuint> indices, | ||
std::vector<Texture> textures) : | ||
vertices(vertices), | ||
indices(indices), | ||
textures(textures) | ||
{ | ||
this->setupMesh(); | ||
} | ||
|
||
//! draw() renders the mesh onto app window | ||
/// | ||
/// assumes sampler2D naming conventions as follows: | ||
/// diffuse textures: texture_diffuseN | ||
/// speculat textures: texture_specularN | ||
/// where N: [0, MAX_TEXTURE_UNITS] | ||
/// | ||
void draw(mylib::Shader& shader) | ||
{ | ||
GLuint diffuseNr{ 1 }, specularNr{ 1 }; | ||
for (GLuint i = 0; i < textures.size(); ++i) { | ||
glActiveTexture(GL_TEXTURE0 + i); // activate *_textureN | ||
std::string number; // *_texture<"N"> | ||
std::string name = textures[i].type; // <"*_texture">N | ||
if (name == "texture_diffuse") { | ||
number = std::to_string(diffuseNr++); | ||
} | ||
else if (name == "texture_specular") { | ||
number = std::to_string(specularNr++); | ||
} | ||
|
||
glUniform1f( | ||
glGetUniformLocation( | ||
shader.program, | ||
// material.<"*_textureN"> | ||
("material." + name + number).c_str()), | ||
i); | ||
#ifdef _DEBUG | ||
//std::clog << "texture: " << ("material." + name + number).c_str() | ||
//<< std::endl; | ||
#endif // _DEBUG | ||
|
||
glBindTexture(GL_TEXTURE_2D, textures[i].id); | ||
} | ||
glActiveTexture(GL_TEXTURE0); | ||
|
||
// draw | ||
shader.use(); | ||
glBindVertexArray(VAO); | ||
glDrawElements(GL_TRIANGLES, | ||
indices.size(), GL_UNSIGNED_INT, 0); | ||
glBindVertexArray(0); | ||
} | ||
|
||
private: | ||
//! render data | ||
GLuint VAO{ 0 }, VBO{ 0 }, EBO{ 0 }; | ||
|
||
void setupMesh() | ||
{ | ||
glGenVertexArrays(1, &VAO); | ||
glGenBuffers(1, &VBO); | ||
glGenBuffers(1, &EBO); | ||
|
||
glBindVertexArray(VAO); | ||
|
||
glBindBuffer(GL_ARRAY_BUFFER, VBO); | ||
glBufferData(GL_ARRAY_BUFFER, | ||
vertices.size() * sizeof(*(vertices.data())), | ||
vertices.data(), | ||
GL_STATIC_DRAW); | ||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); | ||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, | ||
indices.size() * sizeof(*(indices.data())), | ||
indices.data(), | ||
GL_STATIC_DRAW); | ||
|
||
// Vertex positions | ||
glEnableVertexAttribArray(0); | ||
glVertexAttribPointer(0, 3, | ||
GL_FLOAT, GL_FALSE, sizeof(Vertex), ML_BUFFER_OFFSET(0)); | ||
// Vertex normals | ||
glEnableVertexAttribArray(1); | ||
glVertexAttribPointer(1, 3, | ||
GL_FLOAT, GL_FALSE, sizeof(Vertex), | ||
ML_BUFFER_OFFSET(offsetof(Vertex, normal))); | ||
// Vertex texture coordinates | ||
glEnableVertexAttribArray(2); | ||
glVertexAttribPointer(2, 2, | ||
GL_FLOAT, GL_FALSE, sizeof(Vertex), | ||
ML_BUFFER_OFFSET(offsetof(Vertex, texCoords))); | ||
glBindVertexArray(0); | ||
} | ||
}; | ||
|
||
}; // namespace mylib | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
#ifndef __MYLIB_MODEL_HPP__ | ||
#define __MYLIB_MODEL_HPP__ | ||
|
||
#include "c:\Users\samuel vishesh paul\documents\visual studio 2015\Projects\OpenGL Playground\OpenGL Playground\stdafx.h" | ||
|
||
namespace mylib | ||
{ | ||
static GLint TextureFromFile(const char* path, std::string directory) | ||
{ | ||
std::string filename = std::string(path); | ||
filename = directory + '/' + filename; | ||
GLuint textureID; | ||
glGenTextures(1, &textureID); | ||
int width, height; | ||
unsigned char* image = SOIL_load_image(filename.c_str(), | ||
&width, &height, 0, SOIL_LOAD_RGB); | ||
glBindTexture(GL_TEXTURE_2D, textureID); | ||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, | ||
GL_RGB, GL_UNSIGNED_BYTE, image); | ||
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); | ||
glBindTexture(GL_TEXTURE_2D, 0); | ||
SOIL_free_image_data(image); | ||
|
||
return textureID; | ||
} | ||
|
||
class Model | ||
{ | ||
public: | ||
|
||
Model() {} | ||
Model(const GLchar* path) | ||
{ | ||
loadModel(path); | ||
} | ||
|
||
void draw(Shader shader) | ||
{ | ||
for (GLuint i = 0; i < meshes.size(); ++i) { | ||
meshes[i].draw(shader); | ||
} | ||
} | ||
|
||
private: | ||
//! model data | ||
std::vector<Mesh> meshes; | ||
std::string directory; | ||
std::vector<Texture> textures_loaded; | ||
|
||
void loadModel(std::string path) | ||
{ | ||
Assimp::Importer import; | ||
const aiScene* scene = import.ReadFile(path, | ||
aiProcess_Triangulate | aiProcess_FlipUVs); | ||
|
||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { | ||
std::cerr << "ERROR: ASSIMP: " << __PRETTY_FUNCTION__ | ||
<< "\n" << import.GetErrorString() << std::endl; | ||
throw std::runtime_error( | ||
std::string("ERROR::ASSIMP::") + import.GetErrorString()); | ||
} | ||
directory = path.substr(0, path.find_last_of('/')); | ||
processNode(scene->mRootNode, scene); | ||
} | ||
|
||
void processNode(aiNode* node, const aiScene* scene) | ||
{ | ||
// for all the node's meshes (if any) | ||
for (GLuint j = 0; j < node->mNumMeshes; ++j) { | ||
aiMesh* mesh = scene->mMeshes[node->mMeshes[j]]; | ||
this->meshes.push_back(processMesh(mesh, scene)); | ||
} | ||
// for all it's children | ||
for (GLuint i = 0; i < node->mNumChildren; ++i) { | ||
processNode(node->mChildren[i], scene); | ||
} | ||
} | ||
|
||
Mesh processMesh(aiMesh* mesh, const aiScene* scene) | ||
{ | ||
std::vector<Vertex> vertices; | ||
std::vector<GLuint> indices; | ||
std::vector<Texture> textures; | ||
|
||
// process and extract Vertices, Normals and texture Coords | ||
for (GLuint i = 0; i < mesh->mNumVertices; i++) { | ||
Vertex vertex; | ||
|
||
glm::vec3 vector; | ||
vector.x = mesh->mVertices[i].x; | ||
vector.y = mesh->mVertices[i].y; | ||
vector.z = mesh->mVertices[i].z; | ||
vertex.position = vector; | ||
|
||
if (mesh->HasNormals()) { | ||
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]) { | ||
glm::vec2 coords; | ||
coords.x = mesh->mTextureCoords[0][i].x; | ||
coords.y = mesh->mTextureCoords[0][i].y; | ||
vertex.texCoords = coords; | ||
} | ||
else { | ||
vertex.texCoords = glm::vec2(0.0f, 0.0f); | ||
} | ||
|
||
vertices.push_back(vertex); | ||
} | ||
// process and extract indices | ||
for (GLuint i = 0; i < mesh->mNumFaces; i++) { | ||
aiFace face = mesh->mFaces[i]; | ||
for (GLuint j = 0; j < face.mNumIndices; j++) { | ||
indices.push_back(face.mIndices[j]); | ||
} | ||
} | ||
|
||
// process and extract materials | ||
if (mesh->mMaterialIndex >= 0) { | ||
// We assume a convention for sampler names in the shaders. Each diffuse texture should be named | ||
// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER. | ||
// Same applies to other texture as the following list summarizes: | ||
// Diffuse: texture_diffuseN | ||
// Specular: texture_specularN | ||
// Normal: texture_normalN | ||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; | ||
|
||
std::vector<Texture> diffuseMaps = this->loadMaterialTextures( | ||
material, aiTextureType_DIFFUSE, "texture_diffuse"); | ||
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); | ||
|
||
std::vector<Texture> specularMaps = this->loadMaterialTextures( | ||
material, aiTextureType_SPECULAR, "texture_specular"); | ||
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); | ||
} | ||
|
||
return Mesh(vertices, indices, textures); | ||
} | ||
|
||
std::vector<Texture> loadMaterialTextures(aiMaterial* mat, | ||
aiTextureType type, std::string typeName) | ||
{ | ||
std::vector<Texture> textures; | ||
for (GLuint i = 0; i < mat->GetTextureCount(type); ++i) { | ||
aiString str; | ||
mat->GetTexture(type, i, &str); | ||
bool skip = false; | ||
for (GLuint j = 0; j < textures_loaded.size(); ++j) { | ||
if (std::strcmp(textures_loaded[j].path.C_Str(), str.C_Str()) == 0) { | ||
textures.push_back(textures_loaded[j]); | ||
skip = true; | ||
break; | ||
} | ||
} | ||
if (!skip) { | ||
Texture texture; | ||
texture.id = TextureFromFile(str.C_Str(), this->directory); | ||
texture.type = typeName; | ||
texture.path = str; | ||
textures.push_back(texture); | ||
this->textures_loaded.push_back(texture); | ||
} | ||
} | ||
|
||
return textures; | ||
} | ||
}; | ||
|
||
} | ||
|
||
#endif |