146 lines
4.2 KiB
C++
146 lines
4.2 KiB
C++
#include <opengl-playground/model.hpp>
|
|
#include <opengl-playground/material.hpp>
|
|
#include <iostream>
|
|
|
|
Model::Model(const std::string &path, const glm::vec4 &static_color, std::shared_ptr<OpenGlShaderProgram> shader)
|
|
: OpenGlGraphics(shader)
|
|
{
|
|
this->model_path = path;
|
|
this->static_color = static_color;
|
|
}
|
|
|
|
void Model::render()
|
|
{
|
|
for (unsigned int i = 0; i < meshes.size(); i++) {
|
|
meshes[i].render(this->model_matrix, this->normal_matrix);
|
|
}
|
|
}
|
|
|
|
void Model::realize()
|
|
{
|
|
Assimp::Importer importer;
|
|
|
|
const aiScene *scene = importer.ReadFile(this->model_path, aiProcess_Triangulate | aiProcess_FlipUVs);
|
|
|
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
|
std::cout << "Error: Assimp: " << importer.GetErrorString() << std::endl;
|
|
return;
|
|
}
|
|
|
|
this->directory = this->model_path.substr(0, this->model_path.find_last_of('/'));
|
|
this->processNode(scene->mRootNode, scene);
|
|
|
|
importer.FreeScene();
|
|
}
|
|
|
|
void Model::processNode(aiNode *node, const aiScene *scene)
|
|
{
|
|
for(unsigned int i = 0; i < node->mNumMeshes; i++)
|
|
{
|
|
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
|
|
this->meshes.push_back(this->processMesh(mesh, scene));
|
|
}
|
|
|
|
for(unsigned int i = 0; i < node->mNumChildren; i++)
|
|
{
|
|
this->processNode(node->mChildren[i], scene);
|
|
}
|
|
}
|
|
|
|
|
|
std::vector<std::shared_ptr<OpenGlTexture>> Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type)
|
|
{
|
|
std::vector<std::shared_ptr<OpenGlTexture>> tex_vector;
|
|
|
|
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) {
|
|
aiString str;
|
|
mat->GetTexture(type, i, &str);
|
|
bool already_loaded = false;
|
|
for (unsigned int j = 0; j < this->allocated_textures.size(); j++) {
|
|
if (std::strcmp(this->allocated_textures[j]->getPath().c_str(), str.C_Str()) == 0) {
|
|
/* texture already loaded */
|
|
tex_vector.push_back(this->allocated_textures[j]);
|
|
already_loaded = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!already_loaded) {
|
|
auto new_texture = std::make_shared<OpenGlTexture>(str.C_Str());
|
|
new_texture->loadFromImagePath(this->directory);
|
|
tex_vector.push_back(new_texture);
|
|
this->allocated_textures.push_back(new_texture);
|
|
}
|
|
}
|
|
|
|
return tex_vector;
|
|
}
|
|
|
|
Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene)
|
|
{
|
|
std::vector<Vertex> vertices;
|
|
std::vector<unsigned int> indices;
|
|
Material mesh_material;
|
|
|
|
for(unsigned int 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;
|
|
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 vec;
|
|
vec.x = mesh->mTextureCoords[0][i].x;
|
|
vec.y = mesh->mTextureCoords[0][i].y;
|
|
vertex.TextureCoords = vec;
|
|
} else {
|
|
vertex.TextureCoords = 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]);
|
|
}
|
|
|
|
if(mesh->mMaterialIndex >= 0)
|
|
{
|
|
aiColor3D col;
|
|
|
|
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
|
|
auto diffuseTextures = loadMaterialTextures(material, aiTextureType_DIFFUSE);
|
|
auto specularTextures = loadMaterialTextures(material, aiTextureType_SPECULAR);
|
|
auto ambientTextures = loadMaterialTextures(material, aiTextureType_AMBIENT);
|
|
|
|
mesh_material.pushDiffuseTexture(diffuseTextures);
|
|
mesh_material.pushSpecularTexture(specularTextures);
|
|
mesh_material.pushAmbientTexture(ambientTextures);
|
|
|
|
if (!material->Get(AI_MATKEY_COLOR_AMBIENT, col))
|
|
mesh_material.setAmbientColor(glm::vec3(col.r, col.g, col.b));
|
|
if (!material->Get(AI_MATKEY_COLOR_SPECULAR, col))
|
|
mesh_material.setSpecularColor(glm::vec3(col.r, col.g, col.b));
|
|
if (!material->Get(AI_MATKEY_COLOR_DIFFUSE, col))
|
|
mesh_material.setDiffuseColor(glm::vec3(col.r, col.g, col.b));
|
|
|
|
material->Get(AI_MATKEY_SHININESS, mesh_material.shininess);
|
|
material->Get(AI_MATKEY_SHININESS_STRENGTH, mesh_material.shininess_strength);
|
|
std::cout << "Material: " << mesh_material << std::endl;
|
|
}
|
|
|
|
|
|
Mesh my_mesh = Mesh(vertices, indices, mesh_material, this->shaderprog);
|
|
my_mesh.realize();
|
|
return my_mesh;
|
|
}
|