feat: add logger class

This commit is contained in:
2025-10-13 17:30:05 +02:00
parent 74a0bfca41
commit 41c9b68eb9
8 changed files with 185 additions and 22 deletions

View File

@@ -1,11 +1,11 @@
#include "buffer.h" #include "buffer.h"
#include <vector> #include <vector>
#include <iostream>
#include "../lib/glew/GL/glew.h" #include "../lib/glew/GL/glew.h"
#include "../lib/glfw/glfw3.h" #include "../lib/glfw/glfw3.h"
#include "logger.h"
#include "vertex.h" #include "vertex.h"
Buffer::Buffer(const std::vector<Vertex>& vertices, Buffer::Buffer(const std::vector<Vertex>& vertices,
@@ -30,6 +30,9 @@ Buffer::Buffer(const std::vector<Vertex>& vertices,
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
nullptr); nullptr);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
Logger::info(sstr("Buffer created with ", vertices.size(),
" vertices and ", indices.size(), " indices"));
} }
Buffer::~Buffer() Buffer::~Buffer()
@@ -37,6 +40,7 @@ Buffer::~Buffer()
glDeleteVertexArrays(1, &vao_); glDeleteVertexArrays(1, &vao_);
glDeleteBuffers(1, &vbo_); glDeleteBuffers(1, &vbo_);
glDeleteBuffers(1, &ebo_); glDeleteBuffers(1, &ebo_);
Logger::info("Buffer destroyed");
} }
void Buffer::draw(const Shader& shader) const void Buffer::draw(const Shader& shader) const

View File

@@ -1,6 +1,5 @@
#include "engine.h" #include "engine.h"
#include <iostream>
#include <vector> #include <vector>
#include "../lib/glew/GL/glew.h" #include "../lib/glew/GL/glew.h"
@@ -10,6 +9,7 @@
#include "buffer.h" #include "buffer.h"
#include "camera.h" #include "camera.h"
#include "logger.h"
#include "mesh.h" #include "mesh.h"
#include "model.h" #include "model.h"
#include "shader.h" #include "shader.h"
@@ -17,32 +17,37 @@
#include "vertex.h" #include "vertex.h"
#include "world.h" #include "world.h"
constexpr int SCREEN_WIDTH = 800; constexpr int screen_width = 800;
constexpr int SCREEN_HEIGHT = 600; constexpr int screen_height = 600;
constexpr double FPS_LIMIT = 1.0 / 60.0; constexpr double fps_limit = 1.0 / 60.0;
Engine::Engine() Engine::Engine()
: window_(nullptr) : window_(nullptr)
, screen_width_(SCREEN_WIDTH) , screen_width_(screen_width)
, screen_height_(SCREEN_HEIGHT) , screen_height_(screen_height)
, last_update_time_(0.0) , last_update_time_(0.0)
, last_frame_time_(0.0) , last_frame_time_(0.0)
, angle_(0.0) , angle_(0.0)
{ {
Logger::info("Engine created");
} }
Engine::~Engine() Engine::~Engine()
{ {
Logger::info("Engine destroyed");
destroy(); destroy();
} }
void Engine::initialize() void Engine::initialize()
{ {
Logger::info("Initializing engine...");
// Initialize GLFW // Initialize GLFW
if (!glfwInit()) { if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW\n"; Logger::error("Failed to initialize GLFW");
return; return;
} }
Logger::info("GLFW initialized successfully");
glfwWindowHint(GLFW_RESIZABLE, false); glfwWindowHint(GLFW_RESIZABLE, false);
glfwWindowHint(GLFW_SAMPLES, 8); glfwWindowHint(GLFW_SAMPLES, 8);
@@ -51,7 +56,7 @@ void Engine::initialize()
window_ = glfwCreateWindow(screen_width_, screen_height_, window_ = glfwCreateWindow(screen_width_, screen_height_,
"Daniel Poveda", nullptr, nullptr); "Daniel Poveda", nullptr, nullptr);
if (window_ == nullptr) { if (window_ == nullptr) {
std::cerr << "Failed to create OpenGL window\n"; Logger::error("Failed to create OpenGL window");
glfwTerminate(); glfwTerminate();
return; return;
} }
@@ -61,30 +66,39 @@ void Engine::initialize()
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
std::cout << "OpenGL initialized, version: " << glGetString(GL_VERSION) Logger::info(
<< "\n"; sstr("OpenGL initialized, version: ",
reinterpret_cast<const char*>(glGetString(GL_VERSION))));
// Initialize GLEW // Initialize GLEW
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
GLenum err = glewInit(); GLenum err = glewInit();
if (err != GLEW_OK) { if (err != GLEW_OK) {
std::cerr << "Failed to initialize GLEW: " Logger::error(sstr(
<< glewGetErrorString(err) << "\n"; "Failed to initialize GLEW: ",
reinterpret_cast<const char*>(glewGetErrorString(err))));
glfwTerminate(); glfwTerminate();
return; return;
} }
// Initialize default shader // Initialize default shader
Logger::info("Loading default shaders...");
state::default_shader = state::default_shader =
std::make_shared<Shader>("data/vertex.glsl", "data/fragment.glsl"); std::make_shared<Shader>("data/vertex.glsl", "data/fragment.glsl");
if (std::strlen(state::default_shader->error()) > 0) { if (std::strlen(state::default_shader->error()) > 0) {
std::cerr << "Failed to initialize shaders: " Logger::error(sstr("Failed to initialize shaders: ",
<< state::default_shader->error() << "\n"; state::default_shader->error()));
} else {
Logger::info("Default shaders loaded successfully");
} }
Logger::info("Engine initialization complete");
} }
void Engine::run() void Engine::run()
{ {
Logger::info("Starting game loop...");
setup(); setup();
start(); start();
@@ -98,26 +112,33 @@ void Engine::run()
process_input(); process_input();
update(delta_time); update(delta_time);
if (now - last_frame_time_ >= FPS_LIMIT) { if (now - last_frame_time_ >= fps_limit) {
render(); render();
last_frame_time_ = now; last_frame_time_ = now;
} }
last_update_time_ = now; last_update_time_ = now;
} }
Logger::info("Game loop ended");
} }
void Engine::destroy() void Engine::destroy()
{ {
if (window_) { if (window_) {
Logger::info("Shutting down engine...");
glfwTerminate(); glfwTerminate();
window_ = nullptr; window_ = nullptr;
Logger::info("Engine shutdown complete");
} }
} }
void Engine::setup() void Engine::setup()
{ {
Logger::info("Setting up scene...");
// Create world // Create world
world_ = std::make_unique<World>(); world_ = std::make_unique<World>();
Logger::info("World created");
// Create camera // Create camera
camera_ = std::make_shared<Camera>(); camera_ = std::make_shared<Camera>();
@@ -130,6 +151,7 @@ void Engine::setup()
camera_->set_viewport(glm::ivec4(0, 0, screen_width_, screen_height_)); camera_->set_viewport(glm::ivec4(0, 0, screen_width_, screen_height_));
camera_->set_clear_color(glm::vec3(0.1f, 0.1f, 0.1f)); camera_->set_clear_color(glm::vec3(0.1f, 0.1f, 0.1f));
world_->add_entity(camera_); world_->add_entity(camera_);
Logger::info("Camera created and added to world");
// Create triangle mesh // Create triangle mesh
std::vector<Vertex> vertices = { std::vector<Vertex> vertices = {
@@ -141,6 +163,8 @@ void Engine::setup()
auto buffer = std::make_shared<Buffer>(vertices, indices); auto buffer = std::make_shared<Buffer>(vertices, indices);
mesh_ = std::make_shared<Mesh>(); mesh_ = std::make_shared<Mesh>();
mesh_->add_buffer(buffer); mesh_->add_buffer(buffer);
Logger::info(sstr("Mesh created with ", vertices.size(),
" vertices and ", indices.size(), " indices"));
// Create 9 models in a 3x3 grid // Create 9 models in a 3x3 grid
for (int row = 0; row < 3; ++row) { for (int row = 0; row < 3; ++row) {
@@ -153,6 +177,8 @@ void Engine::setup()
world_->add_entity(model); world_->add_entity(model);
} }
} }
Logger::info(sstr("Created ", models_.size(), " models in scene"));
Logger::info("Scene setup complete");
} }
void Engine::start() void Engine::start()

57
src/logger.cpp Normal file
View File

@@ -0,0 +1,57 @@
#include "logger.h"
#include <chrono>
#include <iostream>
namespace {
std::string current_datetime_string()
{
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t(now);
struct tm now_tm {};
#ifdef _WIN32
localtime_s(&now_tm, &now_time_t);
#else
localtime_r(&now_time_t, &now_tm);
#endif
char buffer[30];
std::strftime(buffer, sizeof(buffer) / sizeof(char), "%Y-%m-%d %H:%M:%S",
&now_tm);
return std::string{buffer};
}
} // namespace
void Logger::info(const std::string& message)
{
LogEntry entry;
entry.type = LogType::info;
entry.message =
"[" + current_datetime_string() + "] [INFO]: " + message;
std::cout << "\x1B[32m" << entry.message << "\033[0m" << std::endl;
messages_.push_back(entry);
}
void Logger::warn(const std::string& message)
{
LogEntry entry;
entry.type = LogType::warn;
entry.message =
"[" + current_datetime_string() + "] [WARN]: " + message;
std::cout << "\x1B[93m" << entry.message << "\033[0m" << std::endl;
messages_.push_back(entry);
}
void Logger::error(const std::string& message)
{
LogEntry entry;
entry.type = LogType::error;
entry.message = "[" + current_datetime_string() + "] [ERROR]: " + message;
std::cerr << "\x1B[91m" << entry.message << "\033[0m" << std::endl;
messages_.push_back(entry);
}

48
src/logger.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef LOGGER_H_
#define LOGGER_H_
#include <sstream>
#include <string>
#include <vector>
// Utility: Concatenate any types into a string
template <typename... Args>
std::string sstr(Args&&... args)
{
std::ostringstream stream;
stream << std::dec;
((stream << args), ...);
return stream.str();
}
// Log types
enum class LogType {
info = 0,
warn,
error
};
// Log entry structure
struct LogEntry {
LogType type{LogType::info};
std::string message{};
};
// Logger class
class Logger {
public:
static void info(const std::string& message);
static void warn(const std::string& message);
static void error(const std::string& message);
[[nodiscard]] static const std::vector<LogEntry>& messages()
{
return messages_;
}
static void clear() { messages_.clear(); }
private:
inline static std::vector<LogEntry> messages_{};
};
#endif // LOGGER_H_

View File

@@ -1,13 +1,13 @@
#include "shader.h" #include "shader.h"
#include <vector>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <iostream> #include <vector>
#include "../lib/glew/GL/glew.h" #include "../lib/glew/GL/glew.h"
#include "../lib/glfw/glfw3.h" #include "../lib/glfw/glfw3.h"
#include "logger.h"
#include "vertex.h" #include "vertex.h"
Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath) Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath)
@@ -106,7 +106,8 @@ std::string Shader::read_shader_file(const std::string& filename)
{ {
std::ifstream file(filename); std::ifstream file(filename);
if (!file) { if (!file) {
error_ = "Failed to open shader file: " + filename + "\n"; error_ = "Failed to open shader file: " + filename;
Logger::error(sstr("Failed to open shader file: ", filename));
return std::string{0}; return std::string{0};
} }
@@ -117,11 +118,16 @@ std::string Shader::read_shader_file(const std::string& filename)
uint32_t Shader::compile_shader(uint32_t type, const std::string& source_path) uint32_t Shader::compile_shader(uint32_t type, const std::string& source_path)
{ {
const char* shader_type_name =
(type == GL_VERTEX_SHADER) ? "vertex" : "fragment";
std::string source = read_shader_file(source_path); std::string source = read_shader_file(source_path);
// std::cout << "SHADER FILE: " << source << "\n";
if (source.empty()) if (source.empty())
return 0; return 0;
Logger::info(
sstr("Compiling ", shader_type_name, " shader: ", source_path));
const uint32_t shader = glCreateShader(type); const uint32_t shader = glCreateShader(type);
const char* shader_code = source.c_str(); const char* shader_code = source.c_str();
@@ -135,9 +141,13 @@ uint32_t Shader::compile_shader(uint32_t type, const std::string& source_path)
char buffer[1024]; char buffer[1024];
glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer); glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer);
error_ = buffer; error_ = buffer;
Logger::error(
sstr("Shader compilation failed (", shader_type_name, "): ",
buffer));
glDeleteShader(shader); glDeleteShader(shader);
return 0; return 0;
} }
Logger::info(sstr(shader_type_name, " shader compiled successfully"));
return shader; return shader;
} }

View File

@@ -1,8 +1,11 @@
#include "world.h" #include "world.h"
#include "entity.h"
#include "camera.h"
#include <algorithm> #include <algorithm>
#include "camera.h"
#include "entity.h"
#include "logger.h"
void World::add_entity(const std::shared_ptr<Entity>& entity) void World::add_entity(const std::shared_ptr<Entity>& entity)
{ {
entities_.push_back(entity); entities_.push_back(entity);
@@ -12,6 +15,11 @@ void World::add_entity(const std::shared_ptr<Entity>& entity)
std::dynamic_pointer_cast<Camera>(entity); std::dynamic_pointer_cast<Camera>(entity);
if (camera) { if (camera) {
cameras_.push_back(camera); cameras_.push_back(camera);
Logger::info(sstr("Camera added to world (total cameras: ",
cameras_.size(), ")"));
} else {
Logger::info(sstr("Entity added to world (total entities: ",
entities_.size(), ")"));
} }
} }
@@ -21,6 +29,7 @@ void World::remove_entity(const std::shared_ptr<Entity>& entity)
auto it = std::find(entities_.begin(), entities_.end(), entity); auto it = std::find(entities_.begin(), entities_.end(), entity);
if (it != entities_.end()) { if (it != entities_.end()) {
entities_.erase(it); entities_.erase(it);
Logger::info("Entity removed from world");
} }
// Check if entity is a camera and remove from cameras list // Check if entity is a camera and remove from cameras list
@@ -31,6 +40,7 @@ void World::remove_entity(const std::shared_ptr<Entity>& entity)
std::find(cameras_.begin(), cameras_.end(), camera); std::find(cameras_.begin(), cameras_.end(), camera);
if (camIt != cameras_.end()) { if (camIt != cameras_.end()) {
cameras_.erase(camIt); cameras_.erase(camIt);
Logger::info("Camera removed from world");
} }
} }
} }

View File

@@ -163,6 +163,7 @@
<ClInclude Include="src\camera.h" /> <ClInclude Include="src\camera.h" />
<ClInclude Include="src\engine.h" /> <ClInclude Include="src\engine.h" />
<ClInclude Include="src\entity.h" /> <ClInclude Include="src\entity.h" />
<ClInclude Include="src\logger.h" />
<ClInclude Include="src\mesh.h" /> <ClInclude Include="src\mesh.h" />
<ClInclude Include="src\model.h" /> <ClInclude Include="src\model.h" />
<ClInclude Include="src\shader.h" /> <ClInclude Include="src\shader.h" />
@@ -176,6 +177,7 @@
<ClCompile Include="src\camera.cpp" /> <ClCompile Include="src\camera.cpp" />
<ClCompile Include="src\engine.cpp" /> <ClCompile Include="src\engine.cpp" />
<ClCompile Include="src\entity.cpp" /> <ClCompile Include="src\entity.cpp" />
<ClCompile Include="src\logger.cpp" />
<ClCompile Include="src\main.cpp" /> <ClCompile Include="src\main.cpp" />
<ClCompile Include="src\mesh.cpp" /> <ClCompile Include="src\mesh.cpp" />
<ClCompile Include="src\model.cpp" /> <ClCompile Include="src\model.cpp" />

View File

@@ -63,6 +63,9 @@
<ClInclude Include="src\engine.h"> <ClInclude Include="src\engine.h">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\logger.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\main.cpp"> <ClCompile Include="src\main.cpp">
@@ -98,6 +101,9 @@
<ClCompile Include="src\engine.cpp"> <ClCompile Include="src\engine.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="data\fragment.glsl"> <None Include="data\fragment.glsl">