297 lines
8.2 KiB
C++
297 lines
8.2 KiB
C++
|
|
#define GLM_ENABLE_EXPERIMENTAL
|
|
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include "Mesh.h"
|
|
#include "../Global.h"
|
|
|
|
#include <glm/vec3.hpp>
|
|
#include <glm/gtx/string_cast.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
#include <assimp/Importer.hpp>
|
|
#include <assimp/scene.h>
|
|
#include <assimp/postprocess.h>
|
|
|
|
#include <SOIL/SOIL.h>
|
|
|
|
/**
|
|
* Constructor, loading the specified aiMesh
|
|
**/
|
|
|
|
|
|
|
|
|
|
Mesh::MeshEntry::MeshEntry(aiMesh *mesh, const aiScene* scene, Mesh * m)
|
|
{
|
|
parent = m;
|
|
|
|
vbo[VERTEX_BUFFER] = NULL;
|
|
vbo[TEXCOORD_BUFFER] = NULL;
|
|
vbo[NORMAL_BUFFER] = NULL;
|
|
vbo[INDEX_BUFFER] = NULL;
|
|
|
|
glGenVertexArrays(1, &vao);
|
|
glBindVertexArray(vao);
|
|
|
|
elementCount = mesh->mNumFaces * 3;
|
|
|
|
if (mesh->HasPositions()) {
|
|
float *vertices = new float[mesh->mNumVertices * 3];
|
|
for (int i = 0; i < mesh->mNumVertices; ++i) {
|
|
vertices[i * 3] = mesh->mVertices[i].x;
|
|
vertices[i * 3 + 1] = mesh->mVertices[i].y;
|
|
vertices[i * 3 + 2] = mesh->mVertices[i].z;
|
|
}
|
|
|
|
glGenBuffers(1, &vbo[VERTEX_BUFFER]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo[VERTEX_BUFFER]);
|
|
glBufferData(GL_ARRAY_BUFFER, 3 * mesh->mNumVertices * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
|
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
|
|
glEnableVertexAttribArray(0);
|
|
|
|
delete[] vertices;
|
|
}
|
|
|
|
|
|
if (mesh->HasTextureCoords(0)) {
|
|
float *texCoords = new float[mesh->mNumVertices * 2];
|
|
for (int i = 0; i < mesh->mNumVertices; ++i) {
|
|
texCoords[i * 2] = mesh->mTextureCoords[0][i].x;
|
|
texCoords[i * 2 + 1] = mesh->mTextureCoords[0][i].y;
|
|
}
|
|
|
|
glGenBuffers(1, &vbo[TEXCOORD_BUFFER]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER]);
|
|
glBufferData(GL_ARRAY_BUFFER, 2 * mesh->mNumVertices * sizeof(GLfloat), texCoords, GL_STATIC_DRAW);
|
|
|
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, NULL);
|
|
glEnableVertexAttribArray(2);
|
|
|
|
delete[] texCoords;
|
|
}
|
|
|
|
|
|
if (mesh->HasNormals()) {
|
|
float *normals = new float[mesh->mNumVertices * 3];
|
|
for (int i = 0; i < mesh->mNumVertices; ++i) {
|
|
normals[i * 3] = mesh->mNormals[i].x;
|
|
normals[i * 3 + 1] = mesh->mNormals[i].y;
|
|
normals[i * 3 + 2] = mesh->mNormals[i].z;
|
|
}
|
|
|
|
glGenBuffers(1, &vbo[NORMAL_BUFFER]);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER]);
|
|
glBufferData(GL_ARRAY_BUFFER, 3 * mesh->mNumVertices * sizeof(GLfloat), normals, GL_STATIC_DRAW);
|
|
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
|
|
glEnableVertexAttribArray(1);
|
|
|
|
delete[] normals;
|
|
}
|
|
|
|
|
|
if (mesh->HasFaces()) {
|
|
unsigned int *indices = new unsigned int[mesh->mNumFaces * 3];
|
|
for (int i = 0; i < mesh->mNumFaces; ++i) {
|
|
indices[i * 3] = mesh->mFaces[i].mIndices[0];
|
|
indices[i * 3 + 1] = mesh->mFaces[i].mIndices[1];
|
|
indices[i * 3 + 2] = mesh->mFaces[i].mIndices[2];
|
|
}
|
|
|
|
glGenBuffers(1, &vbo[INDEX_BUFFER]);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDEX_BUFFER]);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * mesh->mNumFaces * sizeof(GLuint), indices, GL_STATIC_DRAW);
|
|
|
|
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, NULL);
|
|
glEnableVertexAttribArray(3);
|
|
|
|
delete[] indices;
|
|
}
|
|
|
|
if (mesh->mMaterialIndex >= 0) {
|
|
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
|
|
|
material->Get(AI_MATKEY_SHININESS, shininessStrength);
|
|
material->Get(AI_MATKEY_COLOR_DIFFUSE, dcolor);
|
|
material->Get(AI_MATKEY_COLOR_AMBIENT, acolor);
|
|
material->Get(AI_MATKEY_COLOR_SPECULAR, scolor);
|
|
|
|
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Deletes the allocated OpenGL buffers
|
|
**/
|
|
Mesh::MeshEntry::~MeshEntry() {
|
|
if (vbo[VERTEX_BUFFER]) {
|
|
glDeleteBuffers(1, &vbo[VERTEX_BUFFER]);
|
|
}
|
|
|
|
if (vbo[TEXCOORD_BUFFER]) {
|
|
glDeleteBuffers(1, &vbo[TEXCOORD_BUFFER]);
|
|
}
|
|
|
|
if (vbo[NORMAL_BUFFER]) {
|
|
glDeleteBuffers(1, &vbo[NORMAL_BUFFER]);
|
|
}
|
|
|
|
if (vbo[INDEX_BUFFER]) {
|
|
glDeleteBuffers(1, &vbo[INDEX_BUFFER]);
|
|
}
|
|
|
|
glDeleteVertexArrays(1, &vao);
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Renders this MeshEntry
|
|
**/
|
|
void Mesh::MeshEntry::render() {
|
|
|
|
|
|
glBindVertexArray(vao);
|
|
int size;
|
|
glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
|
|
glDrawElements(GL_TRIANGLES, size/ sizeof(unsigned int), GL_UNSIGNED_INT, NULL);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
/**
|
|
* Mesh constructor, loads the specified filename if supported by Assimp
|
|
**/
|
|
Mesh::Mesh(const char *filename, ShaderProgram * sh)
|
|
{
|
|
shader = sh;
|
|
|
|
std::string fullname;
|
|
fullname = std::string("./Models/")+ std::string(filename);
|
|
|
|
Assimp::Importer importer; //aiProcessPreset_TargetRealtime_Fast
|
|
const aiScene* scene = importer.ReadFile(fullname.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenSmoothNormals | aiProcess_OptimizeMeshes);
|
|
|
|
// Check for errors
|
|
if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
|
|
{
|
|
std::cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << std::endl;
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < scene->mNumMeshes; ++i) {
|
|
meshEntries.push_back(new Mesh::MeshEntry(scene->mMeshes[i], scene, this));
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Clears all loaded MeshEntries
|
|
**/
|
|
Mesh::~Mesh(void)
|
|
{
|
|
for (int i = 0; i < meshEntries.size(); ++i) {
|
|
|
|
delete meshEntries.at(i);
|
|
}
|
|
meshEntries.clear();
|
|
}
|
|
|
|
/**
|
|
* Renders all loaded MeshEntries
|
|
**/
|
|
DrawableType Mesh::getType()
|
|
{
|
|
return DrawableType::LOADED_MESH;
|
|
}
|
|
|
|
void Mesh::draw(ShaderProgram *, glm::mat4x4 proj_matrix, glm::mat4x4 view_matrix) {
|
|
|
|
shader->use();
|
|
for (int i = 0; i < meshEntries.size(); ++i) {
|
|
|
|
MeshEntry * m = meshEntries[i];
|
|
|
|
|
|
float shiness = meshEntries.at(i)->shininessStrength;
|
|
|
|
|
|
_model.glPushMatrix();
|
|
effectTransformations();
|
|
shader->addUniform("mvp");
|
|
|
|
|
|
shader->addUniform("NormalMatrix"); //Refer next slide : mat3
|
|
shader->addUniform("ModelViewMatrix"); //View*Model : mat4
|
|
|
|
glm::vec4 light_center(0, 10, 0, 0);
|
|
float radius = 10.0f;
|
|
float angle = 0;
|
|
static bool first_draw = true;
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
std::string name = "Light[" + std::to_string(i) + "].Position";
|
|
shader->addUniform(name);
|
|
glm::vec4 position = glm::vec4(radius * cos(glm::radians(angle)), 10 ,radius * sin(glm::radians(angle)), 1);
|
|
glUniform4fv(shader->uniform(name), 1, glm::value_ptr(view_matrix * position));
|
|
angle += 360 / 5;
|
|
}
|
|
first_draw = false;
|
|
shader->addUniform("Light[0].Intensity");
|
|
glUniform3fv(shader->uniform("Light[0].Intensity"), 1, glm::value_ptr(glm::vec3(0.0f, 0.5f, 0.5f)));
|
|
shader->addUniform("Light[1].Intensity");
|
|
glUniform3fv(shader->uniform("Light[1].Intensity"), 1, glm::value_ptr(glm::vec3(0.0f, 0.0f, 0.5f)));
|
|
shader->addUniform("Light[2].Intensity");
|
|
glUniform3fv(shader->uniform("Light[2].Intensity"), 1, glm::value_ptr(glm::vec3(0.5f, 0.0f, 0.0f)));
|
|
shader->addUniform("Light[3].Intensity");
|
|
glUniform3fv(shader->uniform("Light[3].Intensity"), 1, glm::value_ptr(glm::vec3(0.0f, 0.5f, 0.0f)));
|
|
shader->addUniform("Light[4].Intensity");
|
|
glUniform3fv(shader->uniform("Light[4].Intensity"), 1, glm::value_ptr(glm::vec3(0.5f, 0.5f, 0.5f)));
|
|
|
|
glm::mat4 mvpMatrix = proj_matrix * view_matrix * _model.getMatrix();
|
|
glUniformMatrix4fv(shader->uniform("mvp"), 1, GL_FALSE, glm::value_ptr(mvpMatrix));
|
|
glm::mat4 modelview = view_matrix * _model.getMatrix();
|
|
glUniformMatrix4fv(shader->uniform("ModelViewMatrix"), 1, GL_FALSE, glm::value_ptr(modelview));
|
|
glm::mat4 inverseModelView = glm::inverse(modelview);
|
|
glm::mat3 normalMatrix = glm::mat3(glm::transpose(inverseModelView));
|
|
glUniformMatrix3fv(shader->uniform("NormalMatrix"), 1, GL_FALSE, glm::value_ptr(normalMatrix));
|
|
|
|
|
|
glm::vec3 diffuse = glm::vec3(meshEntries.at(i)->dcolor.r, meshEntries.at(i)->dcolor.g, meshEntries.at(i)->dcolor.b);
|
|
glm::vec3 specular = glm::vec3(meshEntries.at(i)->scolor.r, meshEntries.at(i)->scolor.g, meshEntries.at(i)->scolor.b);
|
|
glm::vec3 ambient = glm::vec3(meshEntries.at(i)->acolor.r, meshEntries.at(i)->acolor.g, meshEntries.at(i)->acolor.b);
|
|
|
|
if (glm::length(ambient) == 0) {
|
|
ambient = glm::vec3(0.1, 0.1, 0.1);
|
|
}
|
|
|
|
if (glm::length(diffuse) == 0) {
|
|
diffuse = glm::vec3(0.9, 0.9, 0.9);
|
|
}
|
|
|
|
if (glm::length(specular) == 0) {
|
|
specular = glm::vec3(0.4, 0.4, 0.4);
|
|
}
|
|
|
|
if (shiness == 0)
|
|
shiness = 150.0f;
|
|
|
|
glUniform3fv(shader->uniform("Ka"), 1, glm::value_ptr(ambient));
|
|
glUniform3fv(shader->uniform("Kd"), 1, glm::value_ptr(diffuse));
|
|
glUniform3fv(shader->uniform("Ks"), 1, glm::value_ptr(specular));
|
|
glUniform1f(shader->uniform("Shininess"), shiness);
|
|
|
|
meshEntries.at(i)->render();
|
|
_model.glPopMatrix();
|
|
}
|
|
|
|
shader->disable();
|
|
}
|