Should be able to load models now.

This commit is contained in:
Nicolás A. Ortega Froysa 2018-12-17 11:27:54 +01:00
parent e2d9fe9189
commit bae169977b
11 changed files with 440 additions and 115 deletions

View File

@ -42,8 +42,11 @@ include_directories(
SYSTEM ${SDL2_INCLUDE_DIRS}) SYSTEM ${SDL2_INCLUDE_DIRS})
set(SRCS set(SRCS
"src/AssetManager.cpp"
"src/Logger.cpp" "src/Logger.cpp"
"src/Main.cpp" "src/Main.cpp"
"src/Model.cpp"
"src/Shader.cpp"
"src/System.cpp") "src/System.cpp")
# Define C++ compiler flags # Define C++ compiler flags

View File

@ -0,0 +1,7 @@
#version 330 core
in vec3 frag_col;
out vec3 col;
void main() {
col = frag_col;
}

View File

@ -0,0 +1,9 @@
#version 330 core
layout(location = 0) in vec3 vert_pos;
uniform vec3 col;
/*uniform mat4 mvp;*/
out vec3 frag_col;
void main() {
gl_Position = /*mvp * */vec4(vert_pos, 1);
frag_col = col;
}

View File

@ -18,7 +18,132 @@
#include "AssetManager.hpp" #include "AssetManager.hpp"
void AssetManager::loadOBJ(const std::string &path, #include "System.hpp"
#include <vector>
#include <stdio.h>
//#define TINYOBJLOADER_IMPLEMENTATION
//#include <tiny_obj_loader.h>
#include <glm/glm.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
/*void AssetManager::loadOBJ(const std::string &path,
const std::string &name) const std::string &name)
{ {
std::vector<unsigned int> vertexIndices,
uvIndices, normalIndices;
std::vector<glm::vec3> temp_vertices;
std::vector<glm::vec2> temp_uvs;
std::vector<glm::vec3> temp_normals;
FILE *file = fopen(path.c_str(), "r");
if(not file)
{
System::logger->writeError("Failed to open file.");
return;
}
while(true)
{
char lineHeader[128];
int res = fscanf(file, "%s", lineHeader);
if(res == EOF)
break;
if(strcmp(lineHeader, "v") == 0)
{
glm::vec3 vertex;
fscanf(file, "%f %f %f\n",
&vertex.x, &vertex.y, &vertex.z);
temp_vertices.push_back(vertex);
}
else if(strcmp(lineHeader, "vt") == 0)
{
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
temp_uvs.push_back(uv);
}
else if(strcmp(lineHeader, "vn") == 0)
{
glm::vec3 normal;
fscanf(file, "%f %f %f\n",
&normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
}
else if(strcmp(lineHeader, "f") == 0)
{
std::string v1, v2, v3;
unsigned int vIndex[3], uvIndex[3], normIndex[3];
int matches = fscanf(file,
"%d/%d/%d %d/%d/%d %d/%d/%d\n",
&vIndex[0], &uvIndex[0], &normIndex[0],
&vIndex[1], &uvIndex[1], &normIndex[1],
&vIndex[2], &uvIndex[2], &normIndex[2]);
if(matches not_eq 9)
{
System::logger->writeError(
"OBJ file is too complicated.");
return;
}
for(auto &i : vIndex)
vertexIndices.push_back(i);
for(auto &i : uvIndex)
uvIndices.push_back(i);
for(auto &i : normIndex)
normalIndices.push_back(i);
}
}
}*/
void AssetManager::loadModel(const std::string &path,
const std::string &name)
{
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path,
aiProcess_Triangulate);
if(not scene)
{
System::logger->writeError(importer.GetErrorString());
return;
}
const aiMesh *mesh = scene->mMeshes[0];
std::vector<struct Vertex> vertices;
std::vector<unsigned int> indices;
vertices.reserve(mesh->mNumVertices);
for(unsigned int i = 0; i < mesh->mNumVertices; ++i)
{
aiVector3D pos = mesh->mVertices[i];
aiVector3D norm = mesh->mNormals[i];
vertices.push_back({
glm::vec3(pos.x, pos.y, pos.z),
glm::vec3(norm.x, norm.y, norm.z)});
}
indices.reserve(3 * mesh->mNumFaces);
for(unsigned int i = 0; i < mesh->mNumFaces; ++i)
{
for(unsigned int j = 0; j < 3; ++j)
indices.push_back(mesh->mFaces[i].mIndices[j]);
}
models.insert({ name,
std::make_shared<Model>(
vertices, indices)});
}
std::shared_ptr<Model> AssetManager::getModel(
const std::string &name)
{
return models.at(name);
}
void AssetManager::unloadModel(const std::string &name) {
models.erase(name);
} }

View File

@ -18,17 +18,22 @@
#pragma once #pragma once
#include "Model.hpp"
#include <map>
#include <memory>
#include <string> #include <string>
class AssetManager { class AssetManager {
public: public:
AssetManager(); AssetManager();
void loadOBJ(const std::string &path, /*void loadOBJ(const std::string &path,
const std::string &name);*/
void loadModel(const std::string &path,
const std::string &name); const std::string &name);
void loadSound(const std::string &path, std::shared_ptr<Model> getModel(const std::string &name);
const std::string &name); void unloadModel(const std::string &name);
void unloadOBJ(const std::string &name); //void unloadOBJ(const std::string &name);
void unloadSound(const std::string &name);
private: private:
std::map<std::string, std::shared_ptr<Model>> models;
}; };

60
src/Model.cpp Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Model.hpp"
#include <GL/glew.h>
#include <GL/gl.h>
Model::Model(const std::vector<struct Vertex> &vertices,
const std::vector<unsigned int> &indices) :
vertices(vertices), indices(indices)
{
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER,
vertices.size() * sizeof(struct 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);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
sizeof(struct Vertex), nullptr);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
sizeof(struct Vertex),
(void*)offsetof(struct Vertex, normal));
glBindVertexArray(0);
}
void Model::draw(const Shader &shader) {
glUniform3f(
glGetUniformLocation(shader.getId(), "col"),
color.r, color.g, color.b);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, indices.size(),
GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}

52
src/Model.hpp Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "Shader.hpp"
#include <vector>
#include <glm/glm.hpp>
struct Color {
float r;
float g;
float b;
};
struct Vertex {
glm::vec3 position;
glm::vec3 normal;
};
class Model {
public:
Model(const std::vector<struct Vertex> &vertices,
const std::vector<unsigned int> &indices);
void draw(const Shader &shader);
inline void setColor(float r, float g, float b) {
color = { r, g, b };
}
private:
struct Color color;
std::vector<struct Vertex> vertices;
std::vector<unsigned int> indices;
unsigned int vao, vbo, ebo;
};

110
src/Shader.cpp Normal file
View File

@ -0,0 +1,110 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Shader.hpp"
#include "System.hpp"
#include <fstream>
#include <sstream>
Shader::Shader(const std::string &vShaderPath,
const std::string &fShaderPath)
{
// Load the code from the files.
std::string vShaderCode, fShaderCode;
std::ifstream vShaderFile, fShaderFile;
vShaderFile.exceptions(std::ifstream::failbit bitor
std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit bitor
std::ifstream::badbit);
try
{
vShaderFile.open(vShaderPath);
fShaderFile.open(fShaderPath);
std::stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vShaderCode = vShaderStream.str();
fShaderCode = fShaderStream.str();
}
catch(const std::exception &e)
{
System::logger->writeError(
std::string("Failed to read from file: ") +
e.what());
}
// Compile the shaders
unsigned int vertexId, fragmentId;
int res;
char infoLog[512];
vertexId = glCreateShader(GL_VERTEX_SHADER);
{
const char *vShaderCodeChar = vShaderCode.c_str();
glShaderSource(vertexId, 1,
&vShaderCodeChar, nullptr);
}
glCompileShader(vertexId);
glGetShaderiv(vertexId, GL_COMPILE_STATUS, &res);
if(not res)
{
glGetShaderInfoLog(vertexId, 512, nullptr, infoLog);
System::logger->writeError(
std::string(
"Vertex shader compilation failed: ") +
infoLog);
}
fragmentId = glCreateShader(GL_FRAGMENT_SHADER);
{
const char *fShaderCodeChar = fShaderCode.c_str();
glShaderSource(fragmentId, 1,
&fShaderCodeChar, nullptr);
}
glCompileShader(fragmentId);
glGetShaderiv(fragmentId, GL_COMPILE_STATUS, &res);
if(not res)
{
glGetShaderInfoLog(fragmentId, 512, nullptr, infoLog);
System::logger->writeError(
std::string(
"Fragment shader compilation failed: ") +
infoLog);
}
// Link the program
id = glCreateProgram();
glAttachShader(id, vertexId);
glAttachShader(id, fragmentId);
glLinkProgram(id);
glGetProgramiv(id, GL_LINK_STATUS, &res);
if(not res)
{
glGetProgramInfoLog(id, 512, nullptr, infoLog);
System::logger->writeError(
std::string("Failed to link program: ") +
infoLog);
}
// Delete the shaders
glDeleteShader(vertexId);
glDeleteShader(fragmentId);
}

57
src/Shader.hpp Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <GL/glew.h>
#include <GL/gl.h>
class Shader {
public:
Shader(const std::string &vShaderPath,
const std::string &fShaderPath);
inline void use() {
glUseProgram(id);
}
inline void setBool(const std::string &name,
bool value) const
{
glUniform1i(glGetUniformLocation(id, name.c_str()),
static_cast<int>(value));
}
inline void setInt(const std::string &name,
bool value) const
{
glUniform1i(glGetUniformLocation(id, name.c_str()),
value);
}
inline void setFloat(const std::string &name,
bool value) const
{
glUniform1f(glGetUniformLocation(id, name.c_str()),
value);
}
inline unsigned int getId() const {
return id;
}
private:
unsigned int id;
};

View File

@ -48,8 +48,6 @@ System::System() : running(true) {
exit(1); exit(1);
} }
//SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
glcontext = SDL_GL_CreateContext(window); glcontext = SDL_GL_CreateContext(window);
SDL_GL_SetSwapInterval(0); SDL_GL_SetSwapInterval(0);
@ -61,104 +59,19 @@ System::System() : running(true) {
exit(1); exit(1);
} }
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
try { shader = std::make_unique<Shader>(
loadShaders(); "../assets/shaders/vertex_shader.glsl",
} catch(std::exception &e) { "../assets/shaders/fragment_shader.glsl");
logger->writeError(e.what());
exit(1);
}
matrixId = glGetUniformLocation(programId, "MVP");
}
void System::loadShaders() {
logger->writeDebug("Compiling shaders...");
GLuint vshader_id = glCreateShader(GL_VERTEX_SHADER);
GLuint fshader_id = glCreateShader(GL_FRAGMENT_SHADER);
GLint res;
int info_log_length = 0;
// Load/Compile vertex shader
glShaderSource(vshader_id, 1, &vertShader,
nullptr);
glCompileShader(vshader_id);
glGetShaderiv(vshader_id, GL_COMPILE_STATUS, &res);
glGetShaderiv(vshader_id, GL_INFO_LOG_LENGTH,
&info_log_length);
if(info_log_length > 0)
{
char *vshader_error = new char[info_log_length+1];
glGetShaderInfoLog(vshader_id, info_log_length,
nullptr, vshader_error);
std::string error =
"Vector shader compilation failed: ";
error.append(vshader_error);
delete vshader_error;
throw std::runtime_error(error);
}
// Load/Compile fragment shader
glShaderSource(fshader_id, 1, &fragShader, nullptr);
glCompileShader(fshader_id);
glGetShaderiv(fshader_id, GL_COMPILE_STATUS, &res);
glGetShaderiv(fshader_id, GL_INFO_LOG_LENGTH,
&info_log_length);
if(info_log_length > 0)
{
char *fshader_error = new char[info_log_length+1];
glGetShaderInfoLog(fshader_id, info_log_length,
nullptr, fshader_error);
std::string error =
"Fragment shader compilation failed: ";
error.append(fshader_error);
delete fshader_error;
throw std::runtime_error(error);
}
logger->writeDebug("Linking program...");
programId = glCreateProgram();
glAttachShader(programId, vshader_id);
glAttachShader(programId, fshader_id);
glLinkProgram(programId);
// check linkage
glGetProgramiv(programId, GL_LINK_STATUS, &res);
glGetProgramiv(programId, GL_INFO_LOG_LENGTH,
&info_log_length);
if(info_log_length > 0)
{
char *link_error = new char[info_log_length+1];
glGetProgramInfoLog(programId, info_log_length,
nullptr, link_error);
std::string error = "Program linking failed: ";
error.append(link_error);
delete link_error;
throw std::runtime_error(error);
}
// detach
glDetachShader(programId, vshader_id);
glDetachShader(programId, fshader_id);
glDeleteShader(vshader_id);
glDeleteShader(fshader_id);
} }
System::~System() { System::~System() {
logger->write("Shutting down systems."); logger->write("Shutting down systems.");
glDeleteProgram(programId);
SDL_GL_DeleteContext(glcontext); SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();
@ -171,7 +84,7 @@ void System::run() {
syncInputs(); syncInputs();
glClear(GL_COLOR_BUFFER_BIT bitor GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT bitor GL_DEPTH_BUFFER_BIT);
glUseProgram(programId); shader->use();
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);

View File

@ -19,6 +19,7 @@
#pragma once #pragma once
#include "Logger.hpp" #include "Logger.hpp"
#include "Shader.hpp"
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <memory> #include <memory>
@ -34,28 +35,11 @@ public:
static std::unique_ptr<Logger> logger; static std::unique_ptr<Logger> logger;
private: private:
void loadShaders();
void syncInputs(); void syncInputs();
const GLchar *vertShader =
"#version 330 core\n"
"layout(location = 0) in vec3 vert_pos;\n"
"layout(location = 1) in vec3 vert_col;\n"
"uniform mat4 MVP;\n"
"out vec3 frag_col;\n"
"void main() {\n"
"gl_Position = MVP * vec4(vert_pos, 1);\n"
"frag_col = vert_col;}\n";
const GLchar *fragShader =
"#version 330 core\n"
"in vec3 frag_col;\n"
"out vec3 color;\n"
"void main() { color = frag_col; }\n";
GLuint programId;
GLuint matrixId;
SDL_Window *window; SDL_Window *window;
SDL_GLContext glcontext; SDL_GLContext glcontext;
GLuint vao; std::unique_ptr<Shader> shader;
bool running; bool running;
}; };