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);
|
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")
|
#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
|
||||||
#endif*/
|
#endif*/
|
||||||
|
|
||||||
#include <iostream>
|
#include "engine.h"
|
||||||
#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
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Initialize OpenGL
|
Engine engine;
|
||||||
if (!glfwInit()) {
|
|
||||||
std::cerr << "Failed to initialize glfw\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
glfwWindowHint(GLFW_RESIZABLE, false);
|
engine.initialize();
|
||||||
glfwWindowHint(GLFW_SAMPLES, 8);
|
engine.run();
|
||||||
|
engine.destroy();
|
||||||
// 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();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,6 +161,7 @@
|
|||||||
<ClInclude Include="lib\glfw\glfw3native.h" />
|
<ClInclude Include="lib\glfw\glfw3native.h" />
|
||||||
<ClInclude Include="src\buffer.h" />
|
<ClInclude Include="src\buffer.h" />
|
||||||
<ClInclude Include="src\camera.h" />
|
<ClInclude Include="src\camera.h" />
|
||||||
|
<ClInclude Include="src\engine.h" />
|
||||||
<ClInclude Include="src\entity.h" />
|
<ClInclude Include="src\entity.h" />
|
||||||
<ClInclude Include="src\mesh.h" />
|
<ClInclude Include="src\mesh.h" />
|
||||||
<ClInclude Include="src\model.h" />
|
<ClInclude Include="src\model.h" />
|
||||||
@@ -173,6 +174,7 @@
|
|||||||
<ClCompile Include="lib\glew\glew.c" />
|
<ClCompile Include="lib\glew\glew.c" />
|
||||||
<ClCompile Include="src\buffer.cpp" />
|
<ClCompile Include="src\buffer.cpp" />
|
||||||
<ClCompile Include="src\camera.cpp" />
|
<ClCompile Include="src\camera.cpp" />
|
||||||
|
<ClCompile Include="src\engine.cpp" />
|
||||||
<ClCompile Include="src\entity.cpp" />
|
<ClCompile Include="src\entity.cpp" />
|
||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
<ClCompile Include="src\mesh.cpp" />
|
<ClCompile Include="src\mesh.cpp" />
|
||||||
|
|||||||
@@ -60,6 +60,9 @@
|
|||||||
<ClInclude Include="src\world.h">
|
<ClInclude Include="src\world.h">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\engine.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\main.cpp">
|
<ClCompile Include="src\main.cpp">
|
||||||
@@ -95,6 +98,9 @@
|
|||||||
<ClCompile Include="src\world.cpp">
|
<ClCompile Include="src\world.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\engine.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="data\fragment.glsl">
|
<None Include="data\fragment.glsl">
|
||||||
|
|||||||
Reference in New Issue
Block a user