feat: add logger class
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
#include "buffer.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include "../lib/glew/GL/glew.h"
|
||||
#include "../lib/glfw/glfw3.h"
|
||||
|
||||
#include "logger.h"
|
||||
#include "vertex.h"
|
||||
|
||||
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),
|
||||
nullptr);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
Logger::info(sstr("Buffer created with ", vertices.size(),
|
||||
" vertices and ", indices.size(), " indices"));
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
@@ -37,6 +40,7 @@ Buffer::~Buffer()
|
||||
glDeleteVertexArrays(1, &vao_);
|
||||
glDeleteBuffers(1, &vbo_);
|
||||
glDeleteBuffers(1, &ebo_);
|
||||
Logger::info("Buffer destroyed");
|
||||
}
|
||||
|
||||
void Buffer::draw(const Shader& shader) const
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "engine.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../lib/glew/GL/glew.h"
|
||||
@@ -10,6 +9,7 @@
|
||||
|
||||
#include "buffer.h"
|
||||
#include "camera.h"
|
||||
#include "logger.h"
|
||||
#include "mesh.h"
|
||||
#include "model.h"
|
||||
#include "shader.h"
|
||||
@@ -17,32 +17,37 @@
|
||||
#include "vertex.h"
|
||||
#include "world.h"
|
||||
|
||||
constexpr int SCREEN_WIDTH = 800;
|
||||
constexpr int SCREEN_HEIGHT = 600;
|
||||
constexpr double FPS_LIMIT = 1.0 / 60.0;
|
||||
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)
|
||||
, screen_width_(screen_width)
|
||||
, screen_height_(screen_height)
|
||||
, last_update_time_(0.0)
|
||||
, last_frame_time_(0.0)
|
||||
, angle_(0.0)
|
||||
{
|
||||
Logger::info("Engine created");
|
||||
}
|
||||
|
||||
Engine::~Engine()
|
||||
{
|
||||
Logger::info("Engine destroyed");
|
||||
destroy();
|
||||
}
|
||||
|
||||
void Engine::initialize()
|
||||
{
|
||||
Logger::info("Initializing engine...");
|
||||
|
||||
// Initialize GLFW
|
||||
if (!glfwInit()) {
|
||||
std::cerr << "Failed to initialize GLFW\n";
|
||||
Logger::error("Failed to initialize GLFW");
|
||||
return;
|
||||
}
|
||||
Logger::info("GLFW initialized successfully");
|
||||
|
||||
glfwWindowHint(GLFW_RESIZABLE, false);
|
||||
glfwWindowHint(GLFW_SAMPLES, 8);
|
||||
@@ -51,7 +56,7 @@ void Engine::initialize()
|
||||
window_ = glfwCreateWindow(screen_width_, screen_height_,
|
||||
"Daniel Poveda", nullptr, nullptr);
|
||||
if (window_ == nullptr) {
|
||||
std::cerr << "Failed to create OpenGL window\n";
|
||||
Logger::error("Failed to create OpenGL window");
|
||||
glfwTerminate();
|
||||
return;
|
||||
}
|
||||
@@ -61,30 +66,39 @@ void Engine::initialize()
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
std::cout << "OpenGL initialized, version: " << glGetString(GL_VERSION)
|
||||
<< "\n";
|
||||
Logger::info(
|
||||
sstr("OpenGL initialized, version: ",
|
||||
reinterpret_cast<const char*>(glGetString(GL_VERSION))));
|
||||
|
||||
// Initialize GLEW
|
||||
glewExperimental = GL_TRUE;
|
||||
GLenum err = glewInit();
|
||||
if (err != GLEW_OK) {
|
||||
std::cerr << "Failed to initialize GLEW: "
|
||||
<< glewGetErrorString(err) << "\n";
|
||||
Logger::error(sstr(
|
||||
"Failed to initialize GLEW: ",
|
||||
reinterpret_cast<const char*>(glewGetErrorString(err))));
|
||||
glfwTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize default shader
|
||||
Logger::info("Loading default shaders...");
|
||||
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";
|
||||
Logger::error(sstr("Failed to initialize shaders: ",
|
||||
state::default_shader->error()));
|
||||
} else {
|
||||
Logger::info("Default shaders loaded successfully");
|
||||
}
|
||||
|
||||
Logger::info("Engine initialization complete");
|
||||
}
|
||||
|
||||
void Engine::run()
|
||||
{
|
||||
Logger::info("Starting game loop...");
|
||||
|
||||
setup();
|
||||
start();
|
||||
|
||||
@@ -98,26 +112,33 @@ void Engine::run()
|
||||
process_input();
|
||||
update(delta_time);
|
||||
|
||||
if (now - last_frame_time_ >= FPS_LIMIT) {
|
||||
if (now - last_frame_time_ >= fps_limit) {
|
||||
render();
|
||||
last_frame_time_ = now;
|
||||
}
|
||||
last_update_time_ = now;
|
||||
}
|
||||
|
||||
Logger::info("Game loop ended");
|
||||
}
|
||||
|
||||
void Engine::destroy()
|
||||
{
|
||||
if (window_) {
|
||||
Logger::info("Shutting down engine...");
|
||||
glfwTerminate();
|
||||
window_ = nullptr;
|
||||
Logger::info("Engine shutdown complete");
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::setup()
|
||||
{
|
||||
Logger::info("Setting up scene...");
|
||||
|
||||
// Create world
|
||||
world_ = std::make_unique<World>();
|
||||
Logger::info("World created");
|
||||
|
||||
// Create 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_clear_color(glm::vec3(0.1f, 0.1f, 0.1f));
|
||||
world_->add_entity(camera_);
|
||||
Logger::info("Camera created and added to world");
|
||||
|
||||
// Create triangle mesh
|
||||
std::vector<Vertex> vertices = {
|
||||
@@ -141,6 +163,8 @@ void Engine::setup()
|
||||
auto buffer = std::make_shared<Buffer>(vertices, indices);
|
||||
mesh_ = std::make_shared<Mesh>();
|
||||
mesh_->add_buffer(buffer);
|
||||
Logger::info(sstr("Mesh created with ", vertices.size(),
|
||||
" vertices and ", indices.size(), " indices"));
|
||||
|
||||
// Create 9 models in a 3x3 grid
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
@@ -153,6 +177,8 @@ void Engine::setup()
|
||||
world_->add_entity(model);
|
||||
}
|
||||
}
|
||||
Logger::info(sstr("Created ", models_.size(), " models in scene"));
|
||||
Logger::info("Scene setup complete");
|
||||
}
|
||||
|
||||
void Engine::start()
|
||||
|
||||
57
src/logger.cpp
Normal file
57
src/logger.cpp
Normal 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
48
src/logger.h
Normal 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_
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "shader.h"
|
||||
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../lib/glew/GL/glew.h"
|
||||
#include "../lib/glfw/glfw3.h"
|
||||
|
||||
#include "logger.h"
|
||||
#include "vertex.h"
|
||||
|
||||
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);
|
||||
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};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
const char* shader_type_name =
|
||||
(type == GL_VERTEX_SHADER) ? "vertex" : "fragment";
|
||||
|
||||
std::string source = read_shader_file(source_path);
|
||||
// std::cout << "SHADER FILE: " << source << "\n";
|
||||
if (source.empty())
|
||||
return 0;
|
||||
|
||||
Logger::info(
|
||||
sstr("Compiling ", shader_type_name, " shader: ", source_path));
|
||||
|
||||
const uint32_t shader = glCreateShader(type);
|
||||
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];
|
||||
glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer);
|
||||
error_ = buffer;
|
||||
Logger::error(
|
||||
sstr("Shader compilation failed (", shader_type_name, "): ",
|
||||
buffer));
|
||||
glDeleteShader(shader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Logger::info(sstr(shader_type_name, " shader compiled successfully"));
|
||||
return shader;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "world.h"
|
||||
#include "entity.h"
|
||||
#include "camera.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "camera.h"
|
||||
#include "entity.h"
|
||||
#include "logger.h"
|
||||
|
||||
void World::add_entity(const std::shared_ptr<Entity>& 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);
|
||||
if (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);
|
||||
if (it != entities_.end()) {
|
||||
entities_.erase(it);
|
||||
Logger::info("Entity removed from world");
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (camIt != cameras_.end()) {
|
||||
cameras_.erase(camIt);
|
||||
Logger::info("Camera removed from world");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
<ClInclude Include="src\camera.h" />
|
||||
<ClInclude Include="src\engine.h" />
|
||||
<ClInclude Include="src\entity.h" />
|
||||
<ClInclude Include="src\logger.h" />
|
||||
<ClInclude Include="src\mesh.h" />
|
||||
<ClInclude Include="src\model.h" />
|
||||
<ClInclude Include="src\shader.h" />
|
||||
@@ -176,6 +177,7 @@
|
||||
<ClCompile Include="src\camera.cpp" />
|
||||
<ClCompile Include="src\engine.cpp" />
|
||||
<ClCompile Include="src\entity.cpp" />
|
||||
<ClCompile Include="src\logger.cpp" />
|
||||
<ClCompile Include="src\main.cpp" />
|
||||
<ClCompile Include="src\mesh.cpp" />
|
||||
<ClCompile Include="src\model.cpp" />
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
<ClInclude Include="src\engine.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\logger.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\main.cpp">
|
||||
@@ -98,6 +101,9 @@
|
||||
<ClCompile Include="src\engine.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\logger.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="data\fragment.glsl">
|
||||
|
||||
Reference in New Issue
Block a user