feat: engine class

This commit is contained in:
2025-10-13 16:51:07 +02:00
parent f1a24f576b
commit 4e2c62aaf4
6 changed files with 261 additions and 135 deletions

197
src/engine.cpp Normal file
View File

@@ -0,0 +1,197 @@
#include "engine.h"
#include <iostream>
#include <vector>
#include "../lib/glew/GL/glew.h"
#include "../lib/glfw/glfw3.h"
#include "../lib/glm/glm.hpp"
#include "../lib/glm/gtc/matrix_transform.hpp"
#include "buffer.h"
#include "camera.h"
#include "mesh.h"
#include "model.h"
#include "shader.h"
#include "state.h"
#include "vertex.h"
#include "world.h"
constexpr int SCREEN_WIDTH = 800;
constexpr int SCREEN_HEIGHT = 600;
constexpr double FPS_LIMIT = 1.0 / 60.0;
Engine::Engine()
: window_(nullptr)
, screen_width_(SCREEN_WIDTH)
, screen_height_(SCREEN_HEIGHT)
, last_update_time_(0.0)
, last_frame_time_(0.0)
, angle_(0.0)
{
}
Engine::~Engine()
{
destroy();
}
void Engine::initialize()
{
// Initialize GLFW
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW\n";
return;
}
glfwWindowHint(GLFW_RESIZABLE, false);
glfwWindowHint(GLFW_SAMPLES, 8);
// Create window
window_ = glfwCreateWindow(screen_width_, screen_height_,
"Daniel Poveda", nullptr, nullptr);
if (window_ == nullptr) {
std::cerr << "Failed to create OpenGL window\n";
glfwTerminate();
return;
}
glfwMakeContextCurrent(window_);
// Enable OpenGL features
glEnable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
std::cout << "OpenGL initialized, version: " << glGetString(GL_VERSION)
<< "\n";
// Initialize GLEW
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (err != GLEW_OK) {
std::cerr << "Failed to initialize GLEW: "
<< glewGetErrorString(err) << "\n";
glfwTerminate();
return;
}
// Initialize default shader
State::default_shader_ =
std::make_shared<Shader>("data/vertex.glsl", "data/fragment.glsl");
if (std::strlen(State::default_shader_->error()) > 0) {
std::cerr << "Failed to initialize shaders: "
<< State::default_shader_->error() << "\n";
}
}
void Engine::run()
{
setup();
start();
last_update_time_ = glfwGetTime();
last_frame_time_ = glfwGetTime();
while (is_running()) {
const double now = glfwGetTime();
const double delta_time = now - last_update_time_;
process_input();
update(delta_time);
if (now - last_frame_time_ >= FPS_LIMIT) {
render();
last_frame_time_ = now;
}
last_update_time_ = now;
}
}
void Engine::destroy()
{
if (window_) {
glfwTerminate();
window_ = nullptr;
}
}
void Engine::setup()
{
// Create world
world_ = std::make_unique<World>();
// Create camera
camera_ = std::make_shared<Camera>();
camera_->set_position(glm::vec3(0.0f, 0.0f, 6.0f));
camera_->set_projection(
glm::perspective(glm::radians(45.0f),
static_cast<float>(screen_width_)
/ static_cast<float>(screen_height_),
0.1f, 100.0f));
camera_->set_viewport(glm::ivec4(0, 0, screen_width_, screen_height_));
camera_->set_clear_color(glm::vec3(0.1f, 0.1f, 0.1f));
world_->add_entity(camera_);
// Create triangle mesh
std::vector<Vertex> vertices = {
{{0.0f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}},
{{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}},
{{0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}}};
std::vector<uint16_t> indices = {0, 1, 2};
auto buffer = std::make_shared<Buffer>(vertices, indices);
mesh_ = std::make_shared<Mesh>();
mesh_->add_buffer(buffer);
// Create 9 models in a 3x3 grid
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 3; ++col) {
auto model = std::make_shared<Model>(mesh_);
model->set_position(
glm::vec3(-3.0f + static_cast<float>(col) * 3.0f,
0.0f, static_cast<float>(-row) * 3.0f));
models_.push_back(model);
world_->add_entity(model);
}
}
}
void Engine::start()
{
// Called once after setup, before the main loop
// Can be used for initialization that needs the scene to be ready
}
void Engine::process_input()
{
glfwPollEvents();
}
void Engine::update(const double delta_time)
{
// Update angle for rotation
angle_ += 32.0 * delta_time;
// Update rotation for all models
for (auto& model : models_) {
model->set_rotation(glm::vec3(
0.0f, glm::radians(static_cast<float>(angle_)), 0.0f));
}
// Update world
world_->update(static_cast<float>(delta_time));
}
void Engine::render()
{
// Draw world
world_->draw();
// Swap buffers
glfwSwapBuffers(window_);
}
bool Engine::is_running() const
{
return window_ && !glfwWindowShouldClose(window_)
&& !glfwGetKey(window_, GLFW_KEY_ESCAPE);
}