feat: engine class
This commit is contained in:
197
src/engine.cpp
Normal file
197
src/engine.cpp
Normal 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);
|
||||
}
|
||||
50
src/engine.h
Normal file
50
src/engine.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef ENGINE_H_
|
||||
#define ENGINE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "../lib/glfw/glfw3.h"
|
||||
|
||||
class World;
|
||||
class Camera;
|
||||
class Model;
|
||||
class Mesh;
|
||||
|
||||
class Engine {
|
||||
public:
|
||||
Engine();
|
||||
~Engine();
|
||||
|
||||
void initialize();
|
||||
void run();
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
// Lifecycle methods
|
||||
void setup();
|
||||
void start();
|
||||
void process_input();
|
||||
void update(const double delta_time);
|
||||
void render();
|
||||
|
||||
[[nodiscard]] bool is_running() const;
|
||||
|
||||
// Window and OpenGL
|
||||
GLFWwindow* window_;
|
||||
int screen_width_;
|
||||
int screen_height_;
|
||||
|
||||
// Game objects
|
||||
std::unique_ptr<World> world_;
|
||||
std::shared_ptr<Camera> camera_;
|
||||
std::vector<std::shared_ptr<Model>> models_;
|
||||
std::shared_ptr<Mesh> mesh_;
|
||||
|
||||
// Game loop timing
|
||||
double last_update_time_;
|
||||
double last_frame_time_;
|
||||
double angle_;
|
||||
};
|
||||
|
||||
#endif // ENGINE_H_
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
|
||||
void move(const glm::vec3& vec);
|
||||
|
||||
virtual void update(float delta_time)
|
||||
virtual void update(const float delta_time)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
139
src/main.cpp
139
src/main.cpp
@@ -2,144 +2,15 @@
|
||||
#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
|
||||
#endif*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "../lib/glew/GL/glew.h"
|
||||
#include "../lib/glfw/glfw3.h"
|
||||
#include "../lib/glm/glm.hpp"
|
||||
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||
|
||||
#include "vertex.h"
|
||||
#include "shader.h"
|
||||
#include "buffer.h"
|
||||
#include "state.h"
|
||||
#include "mesh.h"
|
||||
#include "entity.h"
|
||||
#include "model.h"
|
||||
#include "camera.h"
|
||||
#include "world.h"
|
||||
|
||||
#define SCREEN_WIDTH 800
|
||||
#define SCREEN_HEIGHT 600
|
||||
#include "engine.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialize OpenGL
|
||||
if (!glfwInit()) {
|
||||
std::cerr << "Failed to initialize glfw\n";
|
||||
return 1;
|
||||
}
|
||||
Engine engine;
|
||||
|
||||
glfwWindowHint(GLFW_RESIZABLE, false);
|
||||
glfwWindowHint(GLFW_SAMPLES, 8);
|
||||
|
||||
// glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
// glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
GLFWwindow* win = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT,
|
||||
"Daniel Poveda", nullptr, nullptr);
|
||||
if (win == nullptr) {
|
||||
std::cerr << "Failed to create opengl window\n";
|
||||
glfwTerminate();
|
||||
return 1;
|
||||
}
|
||||
glfwMakeContextCurrent(win);
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
// 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";
|
||||
}
|
||||
|
||||
// Create world
|
||||
World world;
|
||||
|
||||
// Create camera
|
||||
auto 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) / 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);
|
||||
auto mesh = std::make_shared<Mesh>();
|
||||
mesh->add_buffer(buffer);
|
||||
|
||||
// Create 9 models in a 3x3 grid
|
||||
std::vector<std::shared_ptr<Model>> models;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Main loop
|
||||
double angle = 0.0;
|
||||
double lastTime = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(win)
|
||||
&& !glfwGetKey(win, GLFW_KEY_ESCAPE)) {
|
||||
// Delta time
|
||||
double currentTime = glfwGetTime();
|
||||
double deltaTime = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
|
||||
// Update angle
|
||||
angle += 32.0 * deltaTime;
|
||||
|
||||
// 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 and draw world
|
||||
world.update(static_cast<float>(deltaTime));
|
||||
world.draw();
|
||||
|
||||
// Refresh screen
|
||||
glfwSwapBuffers(win);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// Shutdown
|
||||
glfwTerminate();
|
||||
engine.initialize();
|
||||
engine.run();
|
||||
engine.destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@
|
||||
<ClInclude Include="lib\glfw\glfw3native.h" />
|
||||
<ClInclude Include="src\buffer.h" />
|
||||
<ClInclude Include="src\camera.h" />
|
||||
<ClInclude Include="src\engine.h" />
|
||||
<ClInclude Include="src\entity.h" />
|
||||
<ClInclude Include="src\mesh.h" />
|
||||
<ClInclude Include="src\model.h" />
|
||||
@@ -173,6 +174,7 @@
|
||||
<ClCompile Include="lib\glew\glew.c" />
|
||||
<ClCompile Include="src\buffer.cpp" />
|
||||
<ClCompile Include="src\camera.cpp" />
|
||||
<ClCompile Include="src\engine.cpp" />
|
||||
<ClCompile Include="src\entity.cpp" />
|
||||
<ClCompile Include="src\main.cpp" />
|
||||
<ClCompile Include="src\mesh.cpp" />
|
||||
|
||||
@@ -60,6 +60,9 @@
|
||||
<ClInclude Include="src\world.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\engine.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\main.cpp">
|
||||
@@ -95,6 +98,9 @@
|
||||
<ClCompile Include="src\world.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\engine.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="data\fragment.glsl">
|
||||
|
||||
Reference in New Issue
Block a user