Start working on scene based rendering

The renderer will render a scene object which has entities and "stray" models to render
This commit is contained in:
SeanOMik 2022-08-19 00:20:53 -04:00
parent 3a49373d75
commit 61ff63bef0
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
19 changed files with 176 additions and 2296 deletions

View File

@ -1,22 +1,24 @@
#include "simpleengine/camera.h"
#include "simpleengine/gfx/light.h"
#include "simpleengine/gfx/material.h"
#include "simpleengine/gfx/model.h"
#include "simpleengine/gfx/renderer.h"
#include "simpleengine/gfx/texture.h"
#include "simpleengine/objects/3d/terrain.h"
#include "simpleengine/vector.h"
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/fwd.hpp>
#include <memory>
#include <simpleengine/gfx/shader.h>
#include <simpleengine/renderable.h>
#include <simpleengine/event/event.h>
#include <simpleengine/shader_program.h>
#include <simpleengine/game.h>
#include <simpleengine/vertex.h>
#include <simpleengine/objects/3d/mesh.h>
#include <simpleengine/gfx/shaders/core_3d_shader.h>
#include <simpleengine/scene.h>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/fwd.hpp>
#include <memory>
#include <chrono>
#include <iostream>
#include <sstream>
@ -33,22 +35,6 @@ CMRC_DECLARE(resource_shaders);
namespace se = simpleengine;
class RendererEvent : public se::Event {
public:
RendererEvent(se::gfx::Renderer renderer) : se::Event(), renderer(renderer) {}
~RendererEvent() = default;
se::gfx::Renderer renderer;
virtual void update(const float& delta_time) override {
}
virtual void render(GLFWwindow* target) override {
this->renderer.render(nullptr);
}
};
std::string read_resource_shader(const std::string& path) {
auto fs = cmrc::resource_shaders::get_filesystem();
cmrc::file vertex_file = fs.open(path);
@ -153,14 +139,17 @@ int main(int argc, char *argv[]) {
5, 6, 12, 12, 6, 13
};
auto cube = std::make_shared<se::gfx::Model>(game.get_window(), core_shader, cube_vertices, cube_indicies);
se::gfx::Material material(white_texture, 1.f, 0.f, 0.f, 0.f, 0.f);
auto cube = std::make_shared<se::gfx::Model>(cube_vertices, cube_indicies,
std::optional<se::gfx::Material>(material));
cube->calculate_normals();
cube->translate(3.5f, 0.f, 0.f);
//game.add_event(cube);
auto renderer = std::make_shared<se::gfx::Renderer>(game.get_window(), core_shader);
/* auto renderer = std::make_shared<se::gfx::Renderer>(game.get_window(), core_shader);
renderer->add_model(white_texture, cube);
game.add_event(renderer);
game.add_event(renderer); */
/* auto r_event = std::make_shared<RendererEvent>(renderer);
game.add_event(r_event); */

View File

@ -12,7 +12,7 @@
namespace simpleengine {
class Camera : public simpleengine::Event {
private:
//glm::vec3 camera_forward;
GLFWwindow* window;
public:
glm::vec3 position;
glm::vec3 rotation;
@ -20,9 +20,6 @@ namespace simpleengine {
glm::mat4 projection_matrix;
glm::mat4 view_matrix;
//glm::vec3 camera_rotation;
/* glm::vec3 world_up = glm::vec3(0.f, 1.f, 0.f);
glm::vec3 cam_front = glm::vec3(0.f, 0.f, -1.f); */
glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);
@ -40,6 +37,5 @@ namespace simpleengine {
glm::vec3 cam_front = glm::vec3(0.f, 0.f, -1.f));
virtual void update(const float& delta_time) override;
virtual void render(GLFWwindow* target) override;
};
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "gfx/model.h"
#include "event/event.h"
#include <iostream>
#include <vector>
namespace simpleengine {
/**
* @brief A Model is a object that will be shown on the screen by a renderer.
*
*/
class Component : public simpleengine::Event {
public:
Component() = default;
virtual void update(const float& delta_time) override {
std::cout << "Component update" << std::endl;
}
virtual std::vector<std::shared_ptr<gfx::Model>> get_renderable_models() {
std::cout << "Got renderables" << std::endl;
return {};
}
};
}

View File

@ -0,0 +1,46 @@
#pragma once
#include "component.h"
#include "transformable.h"
#include <iterator>
#include <vector>
#include <iostream>
namespace simpleengine {
/**
* @brief A Model is a object that will be shown on the screen by a renderer.
*
*/
class Entity : public simpleengine::Event, public simpleengine::Transformable {
public:
std::vector<Component> components;
Entity(std::vector<Component> components = {}) : components(components) {
}
virtual void update(const float& delta_time) override {
std::cout << "Update entity" << std::endl;
for (auto& component : components) {
component.update(delta_time);
}
}
virtual std::vector<std::shared_ptr<gfx::Model>> get_renderable_models() {
std::cout << "Got renderables from entity" << std::endl;
std::vector<std::shared_ptr<gfx::Model>> models;
for (auto& component : components) {
std::vector<std::shared_ptr<gfx::Model>> comp_models = component.get_renderable_models();
// Move comp_models into models
models.insert(models.end(), std::make_move_iterator(comp_models.begin()),
std::make_move_iterator(comp_models.end()));
}
return models;
}
};
}

View File

@ -9,12 +9,9 @@
namespace simpleengine {
class Event : public simpleengine::Destructable {
public:
explicit Event(GLFWwindow* window = nullptr) : window(window) {}
Event() = default;
virtual ~Event() = default;
virtual void update(const float& delta_time) = 0;
virtual void render(GLFWwindow* target) = 0;
protected:
GLFWwindow* window;
};
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "texture.h"
#include <GLFW/glfw3.h>
namespace simpleengine::gfx {
class Material {
public:
Texture texture;
float ambient_scalar;
float diffuse_scalar;
float specular_scalar;
float shine;
float reflectivity;
Material(Texture texture, float shine, float reflectivity, float specular_scalar, float ambient_scalar, float diffuse_scalar) :
texture(texture), ambient_scalar(ambient_scalar), diffuse_scalar(diffuse_scalar), specular_scalar(specular_scalar),
shine(shine), reflectivity(reflectivity) {
}
};
}

View File

@ -1,38 +1,34 @@
#pragma once
#include "shader.h"
#include "../event/event.h"
#include "vao.h"
#include "vbo.h"
#include "../vertex.h"
#include "../renderable.h"
#include "../transformable.h"
#include "material.h"
#include <optional>
#include <vector>
namespace simpleengine::gfx {
class Model : public simpleengine::Renderable, public simpleengine::Transformable {
/**
* @brief A Model is a object that will be shown on the screen by a renderer.
*
*/
class Model : public simpleengine::Event, public simpleengine::Transformable {
public:
std::optional<Material> material;
std::vector<LitVertex> vertices;
std::vector<GLuint> indicies;
gfx::VBO ebo;
gfx::VBO vbo;
gfx::VAO vao;
gfx::Shader shader;
Model(std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>(), std::optional<Material> material = std::nullopt);
Model(GLFWwindow* window, gfx::Shader shader, std::vector<LitVertex> vertices, std::vector<GLuint> indicies = std::vector<GLuint>());
Model(GLFWwindow* window, GLuint shader_program, std::vector<LitVertex> vertices,
std::vector<GLuint> indicies = std::vector<GLuint>());
protected:
virtual void setup_vertices();
public:
virtual void update(const float& delta_time) override;
virtual void render(GLFWwindow* target) override;
private:
glm::vec3 compute_face_normal(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3);
public:
/**
* @brief Calculate the normals of the model.
*

View File

@ -1,37 +0,0 @@
#pragma once
/* #include "shader.h"
#include "vao.h"
#include "vbo.h"
#include "../vertex.h"
#include "../renderable.h"
#include "../transformable.h" */
#include "ssbo.h"
#include "shader.h"
#include "model.h"
#include "texture.h"
#include <GLFW/glfw3.h>
#include <vector>
namespace simpleengine::gfx {
class TexturedModel : public simpleengine::gfx::Model {
public:
std::vector<gfx::Texture> textures;
TexturedModel(GLFWwindow* window, gfx::Shader shader, gfx::Texture texture, std::vector<LitVertex> vertices,
std::vector<GLuint> indicies = std::vector<GLuint>());
TexturedModel(GLFWwindow* window, GLuint shader_program, gfx::Texture texture, std::vector<LitVertex> vertices,
std::vector<GLuint> indicies = std::vector<GLuint>());
TexturedModel(GLFWwindow* window, gfx::Shader shader, std::vector<gfx::Texture> textures, std::vector<LitVertex> vertices,
std::vector<GLuint> indicies = std::vector<GLuint>());
TexturedModel(GLFWwindow* window, GLuint shader_program, std::vector<gfx::Texture> textures, std::vector<LitVertex> vertices,
std::vector<GLuint> indicies = std::vector<GLuint>());
virtual void update(const float& delta_time) override;
virtual void render(GLFWwindow* target) override;
};
}

View File

@ -50,9 +50,10 @@ namespace simpleengine::gfx {
void bind() const {
glBindVertexArray(handle);
// TODO: Handle opengl errors EVERYWHERE
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
//fprintf(stderr, "Ran into opengl error: 0x%x\n", err);
fprintf(stderr, "Ran into opengl error: 0x%x\n", err);
//std::cerr << "Ran into enum error: "
}
}

View File

@ -1,57 +0,0 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include "../../optional.h"
#include "../../vector.h"
#include "../../vertex.h"
#include "../../renderable.h"
#include "../../transformable.h"
#include "../../gfx/vao.h"
#include "../../gfx/vbo.h"
#include "../../gfx/shader.h"
#include "../../gfx/texture.h"
#include "../../gfx/textured_model.h"
namespace simpleengine::objects_3d {
class Mesh : public simpleengine::gfx::TexturedModel {
private:
/**
* @brief Split a string multiple times (if possible) with a character delimiter.
*
* @param str The string to split.
* @param delim The character to split by.
* @return std::vector<std::string> The tokens that were split out of str.
*/
std::vector<std::string> split_string(std::string str, const char delim);
/**
* @brief Process a vertex from tokens read from the .obj file.
*
* @param vertex_data The vertex string tokens to process the vertex from.
* @param in_textures The texture coords that are unsorted, just read from the .obj file.
* @param in_normals The normals that are unsorted, just read from the .obj file.
* @param out_indicies (out) The vector to insert the indicies that were extracted from `vertex_data` into.
* @param out_textures (out) The vector to insert the texture coords that were extracted from `vertex_data` into.
* @param out_normals (out) The vector to insert the normals that were extracted from `vertex_data` into.
*/
static void process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies, std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals);
private:
/**
* @brief This is replaced with `lit_vertices`!!!!
*
*/
using simpleengine::gfx::Model::vertices;
public:
std::vector<LitVertex> lit_vertices;
Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::string filename);
Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::ifstream file_stream);
virtual void update(const float& delta_time) override;
};
}

View File

@ -1,104 +0,0 @@
#pragma once
#include "../../gfx/model.h"
#include "../../gfx/texture.h"
#include "../../gfx/textured_model.h"
#include "../../renderable.h"
#include "../../vertex.h"
#include <vector>
namespace simpleengine::objects_3d {
class Terrain : public simpleengine::gfx::TexturedModel {
private:
/**
* @brief DO NOT USE!!! Replaced with lit_vertices
*
*/
using gfx::Model::vertices;
public:
std::vector<LitVertex> lit_vertices;
const float size;
const int vertex_count;
float x;
float y;
gfx::Texture texture;
Terrain(GLFWwindow* window, gfx::Shader shader, gfx::Texture texture, int grid_x, int grid_y, float size = 800.f, int vertex_count = 128) :
simpleengine::gfx::TexturedModel(window, shader, { texture }, std::vector<LitVertex>()), x(grid_x * size), y(grid_y * size),
texture(texture), size(size), vertex_count(vertex_count) {
generate_terrain();
}
protected:
virtual void setup_vertices() override {
vao.bind();
vbo.buffer(lit_vertices.data(), 0, sizeof(LitVertex) * lit_vertices.size());
ebo.buffer(indicies.data(), 0, indicies.size() * sizeof(GLuint));
// Enable VAO attributes
vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, position));
//vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color));
vao.enable_attrib(vbo, 1, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord));
vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public:
void generate_terrain() {
lit_vertices.clear();
indicies.clear();
// Reserve space for vertices and indicies before hand.
int count = pow(vertex_count, 2);
lit_vertices.reserve(count);
indicies.reserve(6 * pow(vertex_count - 1, 2));
int vertex_index = 0;
for (int i = 0; i < vertex_count; i++) {
for (int j = 0; j < vertex_count; j++) {
Vectorf pos( (float) j / ((float) vertex_count - 1) * size, 0, (float) i / ((float) vertex_count - 1) * size);
glm::vec2 tex( (float) j / (float) vertex_count - 1, (float) i / (float) vertex_count - 1);
glm::vec3 normals(0, 1, 0);
lit_vertices.emplace_back(pos, tex, normals);
vertex_index++;
}
}
int indicies_index = 0;
for (int i = 0; i < vertex_count; i++) {
for (int j = 0; j < vertex_count; j++) {
int top_left = (i * vertex_count) + j;
int top_right = top_left + 1;
int bottom_left = ((i + 1) * vertex_count) + j;
int bottom_right = bottom_left + 1;
indicies.push_back(top_left);
indicies.push_back(bottom_left);
indicies.push_back(top_right);
indicies.push_back(top_right);
indicies.push_back(bottom_left);
indicies.push_back(bottom_right);
}
}
std::cout << "========= New terrain generated =========" << std::endl;
std::cout << " Lit vertices count: " << lit_vertices.size() << std::endl;
std::cout << " Indicies count: " << indicies.size() << std::endl;
setup_vertices();
}
virtual void update(const float& delta_time) override {
}
/* virtual void render(GLFWwindow* target) override {
} */
};
}

File diff suppressed because it is too large Load Diff

View File

@ -9,9 +9,11 @@
namespace simpleengine {
class Renderable : public simpleengine::Event {
private:
using super = simpleengine::Event;
using Super = simpleengine::Event;
public:
explicit Renderable(GLFWwindow* window = nullptr) : super(window) {}
Renderable() = default;
virtual ~Renderable() = default;
virtual void render(GLFWwindow* target) = 0;
};
}

View File

@ -0,0 +1,44 @@
#pragma once
#include "gfx/model.h"
#include "entity.h"
#include "event/event.h"
#include "renderable.h"
#include <memory>
#include <GLFW/glfw3.h>
#include <vector>
namespace simpleengine {
class Scene : public simpleengine::Event {
public:
/**
* @brief A list of entities in this scene.
*
*/
std::vector<std::shared_ptr<Entity>> entities;
/**
* @brief Models that don't belong to an entity.
*
*/
std::vector<std::shared_ptr<gfx::Model>> stray_models;
Scene() = default;
void add_entity(std::shared_ptr<Entity> entity) {
entities.push_back(entity);
}
void add_stray_model(std::shared_ptr<gfx::Model> stray) {
stray_models.push_back(stray);
}
virtual void update(const float& delta_time) override {
for (auto& entity : entities) {
entity->update(delta_time);
}
}
};
}

View File

@ -5,7 +5,7 @@
namespace simpleengine {
Camera::Camera(GLFWwindow* window, gfx::Shader shader, float fov, glm::vec3 position, glm::vec3 rotation,
float near_plane, float far_plane, glm::vec3 world_up, glm::vec3 cam_front) : simpleengine::Event(window), shader(shader),
float near_plane, float far_plane, glm::vec3 world_up, glm::vec3 cam_front) : window(window), shader(shader),
projection_matrix(1.f), view_matrix(1.f), fov(fov), position(position), rotation(rotation), near_plane(near_plane), far_plane(far_plane) {
// TODO: Update width and height on window resize.
@ -100,8 +100,4 @@ namespace simpleengine {
shader.set_uniform_matrix_4f("projection_matrix", projection_matrix, false);
shader.unuse();
}
void Camera::render(GLFWwindow* target) {
}
}

View File

@ -94,7 +94,7 @@ void simpleengine::Game::render_window(const float& delta_time) {
void simpleengine::Game::render_items(const float& delta_time) {
for (const std::shared_ptr<Event>& event : events) {
event->render(window);
//event->render(window);
}
}

View File

@ -1,60 +1,15 @@
#include "gfx/model.h"
namespace simpleengine::gfx {
Model::Model(GLFWwindow* window, gfx::Shader shader, std::vector<LitVertex> vertices, std::vector<GLuint> indicies) :
simpleengine::Renderable(window), shader(shader), vertices(vertices), indicies(indicies), vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)),
ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)), vao(gfx::VAO::init()) {
Model::Model(std::vector<LitVertex> vertices, std::vector<GLuint> indicies, std::optional<Material> material) :
material(material), vertices(vertices), indicies(indicies) {
//setup_vertices();
}
Model::Model(GLFWwindow* window, GLuint shader_program, std::vector<LitVertex> vertices, std::vector<GLuint> indicies) :
Model(window, gfx::Shader(shader_program), vertices, indicies) {
}
void Model::setup_vertices() {
vao.bind();
vbo.buffer(vertices.data(), 0, sizeof(LitVertex) * vertices.size());
if (!indicies.empty()) {
ebo.buffer(indicies.data(), 0, indicies.size() * sizeof(GLuint));
}
// Enable VAO attributes
vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, position));
vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color));
vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal));
// Attribute 2 is used for normals
vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord));
vao.enable_attrib(vbo, 4, 1, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, texture_id));
/* vao.disable_attrib(vbo, 2);
vao.disable_attrib(vbo, 4);
vao.set_attrib_value(vbo, 4, -1.f); */
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Model::update(const float& delta_time) {
this->rotate_y(1.f);
}
void Model::render(GLFWwindow* target) {
shader.use();
shader.set_uniform_matrix_4f("transform_matrix", transform_matrix, false);
// When binding to the texture, also tell the shader if the texture is set or not.
//shader.set_uniform_int("texture_is_set", (GLint) false, false);
vao.bind();
if (indicies.empty()) {
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
} else {
glDrawElements(GL_TRIANGLES, indicies.size(), GL_UNSIGNED_INT, 0);
}
}
glm::vec3 Model::compute_face_normal(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& p3) {
// Uses p2 as a new origin for p1,p3
auto a = p3 - p2;

View File

@ -1,62 +0,0 @@
#include "gfx/textured_model.h"
#include "gfx/ssbo.h"
namespace simpleengine::gfx {
TexturedModel::TexturedModel(GLFWwindow* window, gfx::Shader shader, gfx::Texture texture, std::vector<LitVertex> vertices,
std::vector<GLuint> indicies) : simpleengine::gfx::Model(window, shader, vertices, indicies),
textures(std::vector<gfx::Texture>{texture}) {
}
TexturedModel::TexturedModel(GLFWwindow* window, GLuint shader_program, gfx::Texture texture,
std::vector<LitVertex> vertices, std::vector<GLuint> indicies) : TexturedModel(window, gfx::Shader(shader_program),
std::vector<gfx::Texture>{texture}, vertices, indicies) {
}
TexturedModel::TexturedModel(GLFWwindow* window, gfx::Shader shader, std::vector<gfx::Texture> textures, std::vector<LitVertex> vertices,
std::vector<GLuint> indicies) : simpleengine::gfx::Model(window, shader, vertices, indicies),
textures(textures) {
}
TexturedModel::TexturedModel(GLFWwindow* window, GLuint shader_program, std::vector<gfx::Texture> textures,
std::vector<LitVertex> vertices, std::vector<GLuint> indicies) : TexturedModel(window, gfx::Shader(shader_program),
textures, vertices, indicies) {
}
void TexturedModel::update(const float& delta_time) {
}
void TexturedModel::render(GLFWwindow* target) {
shader.use();
shader.set_uniform_matrix_4f("transform_matrix", transform_matrix, false);
const int tex_id = 0;
// On a batch renderer, you would set an array.
shader.set_uniform_int("u_textures", tex_id, false);
shader.set_uniform_float("u_texture_shine", 1.f, false);
shader.set_uniform_float("u_texture_reflectivity", 0.f, false);
/* int samples[2] = { 0, 1 };
float shine[2] = { 1.f, 1.f};
float reflectivity[2] = { 0.f, 0.f};
shader.set_uniform_int_array("u_textures", 2, samples, false);
shader.set_uniform_float_array("u_texture_shine", 2, shine, false);
shader.set_uniform_float_array("u_texture_reflectivity", 2, reflectivity, false); */
glActiveTexture(GL_TEXTURE0 + tex_id);
glBindTextureUnit(tex_id, textures.front().get_texture_id());
const auto& texture = textures.front();
texture.bind();
vao.bind();
if (indicies.empty()) {
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
} else {
glDrawElements(GL_TRIANGLES, indicies.size(), GL_UNSIGNED_INT, 0);
}
}
}

View File

@ -1,126 +0,0 @@
#include "objects/3d/mesh.h"
namespace simpleengine::objects_3d {
std::vector<std::string> Mesh::split_string(std::string str, const char delim) {
std::istringstream ss(str);
std::vector<std::string> tokens;
size_t pos = 0;
std::string token;
while ((pos = str.find(delim)) != std::string::npos) {
token = str.substr(0, pos);
tokens.push_back(token);
str.erase(0, pos + 1);
}
tokens.push_back(str);
return tokens;
}
void Mesh::process_vertex(const std::vector<std::string>& vertex_data, const std::vector<glm::vec2>& in_textures,
const std::vector<glm::vec3>& in_normals, std::vector<GLuint>& out_indicies,
std::vector<glm::vec2>& out_textures, std::vector<glm::vec3>& out_normals) {
// Get the index the current vertex and put it in indicies
int currentVertexIndex = stoi(vertex_data[0]) - 1;
out_indicies.push_back(currentVertexIndex);
// Read texture coords
glm::vec2 current_tex = in_textures.at(stoi(vertex_data[1]) - 1);
current_tex.y = 1 - current_tex.y;
out_textures.at(currentVertexIndex) = current_tex;
// Read normals
glm::vec3 current_norm = in_normals.at(stoi(vertex_data[2]) - 1);
out_normals.at(currentVertexIndex) = current_norm;
}
Mesh::Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::string filename) :
Mesh(window, shader, texture, std::ifstream(filename, std::ios::in | std::ios::binary)) {
}
Mesh::Mesh(GLFWwindow *window, gfx::Shader shader, gfx::Texture texture, std::ifstream file_stream) :
simpleengine::gfx::TexturedModel(window, shader, std::vector<gfx::Texture>{texture}, std::vector<LitVertex>()) {
if (!file_stream.is_open()) {
std::cerr << "File stream that was given to ObjModel::ObjModel is not open!" << std::endl;
throw std::runtime_error("Failed to open ObjModel model file");
}
// The vertices, texture coords, and normals that were read from the obj file
// these are not in a particular order.
std::vector<glm::vec3> obj_vertices;
std::vector<glm::vec2> obj_textures;
std::vector<glm::vec3> obj_normals;
// The texture coords and normals that have been sorted.
std::vector<glm::vec2> textures;
std::vector<glm::vec3> normals;
// Read the vertices, texture coords, and normals. Break when run into indices
std::string line;
while (std::getline(file_stream, line)) {
std::vector<std::string> line_tokens = split_string(line, ' ');
if (line_tokens.front() == "v") {
//glm::vec3 vertex(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
obj_vertices.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
} else if (line_tokens.front() == "vt") {
obj_textures.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]));
} else if (line_tokens.front() == "vn") {
obj_normals.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3]));
} else if (line_tokens.front() == "f") {
auto size = obj_vertices.size();
textures.resize(size);
normals.resize(size);
break;
}
}
// Process the indicies. This will sort everything for storing inside of the Vertex list.
do {
if (!line.starts_with("f")) {
continue;
}
std::vector<std::string> line_tokens = split_string(line, ' ');
std::vector<std::string> vertex1 = split_string(line_tokens[1], '/');
std::vector<std::string> vertex2 = split_string(line_tokens[2], '/');
std::vector<std::string> vertex3 = split_string(line_tokens[3], '/');
process_vertex(vertex1, obj_textures, obj_normals, indicies, textures, normals);
process_vertex(vertex2, obj_textures, obj_normals, indicies, textures, normals);
process_vertex(vertex3, obj_textures, obj_normals, indicies, textures, normals);
} while (std::getline(file_stream, line));
file_stream.close();
const int texture_id = 0;
std::cout << "Texture ID: " << texture_id << std::endl;
// Insert everything into lit_vertices.
for (int i = 0; i < obj_vertices.size(); i++) {
lit_vertices.emplace_back(simpleengine::Vectorf(obj_vertices.at(i)), glm::vec3(1.f), textures.at(i), normals.at(i), texture_id);
}
// Create VAO and EBO and assign buffers
vao.bind();
vbo.buffer(lit_vertices.data(), 0, sizeof(LitVertex) * lit_vertices.size());
ebo.buffer(indicies.data(), 0, indicies.size() * sizeof(GLuint));
// Enable VAO attributes
vao.enable_attrib(vbo, 0, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, position));
vao.enable_attrib(vbo, 1, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, color));
vao.enable_attrib(vbo, 2, 3, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, normal));
vao.enable_attrib(vbo, 3, 2, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, tex_coord));
vao.enable_attrib(vbo, 4, 1, GL_FLOAT, sizeof(LitVertex), offsetof(LitVertex, texture_id));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::update(const float& delta_time) {
this->rotate_y(0.0005f); // Slowly rotate (for debugging)
}
}