Files
b_engine/src/main.cpp

282 lines
8.1 KiB
C++
Raw Normal View History

2026-04-29 00:17:00 -04:00
#include "glad/gl.h"
#include "GLFW/glfw3.h"
#include "spdlog/spdlog.h"
#include "glm/glm.hpp"
#include "glm/ext/matrix_clip_space.hpp"
2026-05-08 23:44:20 -04:00
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "Camera.h"
#include "Components.h"
#include "EditorContext.h"
#include "FreeCameraController.h"
#include "InputManager.h"
#include "ModelManager.h"
2026-05-09 23:40:52 -04:00
#include "Scene.h"
#include "ShaderManager.h"
#include "ShaderProgram.h"
#include "TextureManager.h"
#include "UIManager.h"
#include "ui/UIEntityInspector.h"
#include "ui/UIMenuBar.h"
#include "ui/UISceneGraph.h"
#include "ui/UISceneViewer.h"
GLFWwindow* gWindow = nullptr;
int gWindowWidth = 1920;
int gWindowHeight = 1080;
2026-04-29 00:17:00 -04:00
int glVersionMajor = 0;
int glVersionMinor = 0;
float gAspectRatio = 0.f;
float gMouseSensitivity = 0.1f;
Camera gCamera {};
2026-05-09 23:40:52 -04:00
Scene gScene{};
EditorContext gEditorCtx{};
FreeCameraController gCameraController{};
2026-05-11 08:07:36 -04:00
2026-04-29 00:17:00 -04:00
void glfw_error_callback(int error, const char* description);
void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height);
void init_glfw();
void create_main_window();
void load_gl();
void init_camera();
void init_scene();
void load_default_textures();
void load_shaders();
2026-05-08 23:44:20 -04:00
void load_inputs();
void load_default_models();
2026-05-02 21:24:21 -04:00
void loop();
void create_entity(entt::entity parent);
auto xAxis = glm::vec3{1.f, 0.f, 0.f};
auto yAxis = glm::vec3{0.f, 1.f, 0.f};
auto zAxis = glm::vec3{0.f, 0.f, 1.f};
2026-04-29 00:17:00 -04:00
int main() {
2026-05-09 23:40:52 -04:00
spdlog::info("b_engine v0.0.3 start");
2026-04-29 00:17:00 -04:00
init_glfw();
2026-04-29 00:17:00 -04:00
create_main_window();
2026-04-29 00:17:00 -04:00
load_gl();
2026-04-29 00:17:00 -04:00
stbi_set_flip_vertically_on_load(true);
2026-04-29 00:17:00 -04:00
load_default_textures();
2026-04-29 00:17:00 -04:00
load_shaders();
2026-04-29 00:17:00 -04:00
2026-05-08 23:44:20 -04:00
load_inputs();
2026-04-29 00:17:00 -04:00
2026-05-08 23:44:20 -04:00
load_default_models();
2026-04-29 00:17:00 -04:00
UIManager::init(gWindow);
UIMenuBar* menuBar = UIManager::add_ui_panel<UIMenuBar>("menu_bar");
menuBar->create_entity = create_entity;
UIManager::add_ui_panel<UISceneViewer>("scene_viewer");
UIManager::add_ui_panel<UISceneGraph>("scene_graph");
UIManager::add_ui_panel<UIEntityInspector>("entity_inspector");
2026-05-09 23:40:52 -04:00
init_camera();
init_scene();
gCameraController.set_camera(gCamera);
gCameraController.look_sensitivity = 0.2;
gCameraController.movement_speed = 0.2;
InputManager::add_mouse_listener([](float xoff, float yoff) {
gCameraController.on_mouse_delta(xoff, yoff);
});
gEditorCtx.scene = &gScene;
gEditorCtx.window = gWindow;
gEditorCtx.selectedEntity = entt::null;
2026-05-02 21:24:21 -04:00
loop();
2026-04-29 00:17:00 -04:00
ShaderManager::shaders.clear();
TextureManager::textures.clear();
ModelManager::models.clear();
2026-04-29 00:17:00 -04:00
glfwDestroyWindow(gWindow);
glfwTerminate();
return 0;
}
void glfw_error_callback(int error, const char* description) {
spdlog::error("glfw error: {}", description);
}
void glfw_framebuffer_size_callback(GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
gAspectRatio = (float)width / (float)height;
gCamera.update_aspect_ratio(gAspectRatio);
2026-04-29 00:17:00 -04:00
}
void init_glfw()
{
if (!glfwInit()) {
spdlog::error("could not initialize glfw");
std::exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_SAMPLES, 4);
glfwSetErrorCallback(glfw_error_callback);
}
void create_main_window()
{
2026-05-09 23:40:52 -04:00
gWindow = glfwCreateWindow(gWindowWidth, gWindowHeight, "b_engine v0.0.3", nullptr, nullptr);
if (!gWindow) {
spdlog::error("failed to create glfw window");
std::exit(1);
}
glfwMakeContextCurrent(gWindow);
glfwSetKeyCallback(gWindow, InputManager::key_callback);
glfwSetCursorPosCallback(gWindow, InputManager::mouse_pos_callback);
glfwSetFramebufferSizeCallback(gWindow, glfw_framebuffer_size_callback);
2026-05-08 23:44:20 -04:00
#ifndef GLFW_CONTEXT_DEBUG
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
2026-05-08 23:44:20 -04:00
#endif
}
void load_gl()
{
int version = gladLoadGL(glfwGetProcAddress);
glVersionMajor = GLAD_VERSION_MAJOR(version);
glVersionMinor = GLAD_VERSION_MINOR(version);
spdlog::info("gl version {}.{}", glVersionMajor, glVersionMinor);
if (gWindow)
{
int fbWidth, fbHeight;
glfwGetFramebufferSize(gWindow, &fbWidth, &fbHeight);
gAspectRatio = (float)fbWidth / (float)fbHeight;
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
}
void init_camera() {
gCamera = {{10.f, 10.f, 10.f}, 0, 0, gAspectRatio};
gCamera.rotate_yaw(-135.f);
gCamera.rotate_pitch(-35.f);
}
void init_scene() {
gScene.set_active_camera(&gCamera);
const auto defaultLight = gScene.create_game_object();
auto& [name] = gScene.fetch_component<Components::Tag>(defaultLight);
name = "Directional Light";
auto& [direction, ambient, diffuse, specular] = gScene.attach_component<Components::DirectionalLight>(defaultLight);
direction = glm::vec3(-1, -1, -1);
ambient = glm::vec3(0.3);
diffuse = glm::vec3(0.7);
specular = glm::vec3(1.0);
}
void load_default_textures() {
spdlog::info("creating default textures");
2026-05-09 23:40:52 -04:00
unsigned char defaultDiffuseData[4] = {static_cast<unsigned char>(255), 255, 255, 255};
TextureManager::textures["default_diffuse"] = TextureManager::load_from_data(reinterpret_cast<unsigned char*>(&defaultDiffuseData), 1, 1, 4);
unsigned char defaultSpecularData[4] = {static_cast<unsigned char>(64), 64, 64, 255};
TextureManager::textures["default_specular"] = TextureManager::load_from_data(reinterpret_cast<unsigned char*>(&defaultSpecularData), 1, 1, 4);
}
void load_shaders() {
spdlog::info("compiling shaders");
ShaderManager::shaders["phong_shader"] = ShaderManager::load("./resources/standard.vert", "./resources/standard.frag");
if (ShaderManager::shaders["phong_shader"] == nullptr)
{
spdlog::error("failed to compile phong shader");
std::exit(1);
}
}
2026-05-08 23:44:20 -04:00
void load_inputs() {
InputManager::generate_input_action("move_forward", {{GLFW_KEY_W, KEY_DOWN}});
InputManager::generate_input_action("move_backward", {{GLFW_KEY_S, KEY_DOWN}});
InputManager::generate_input_action("move_right", {{GLFW_KEY_D, KEY_DOWN}});
InputManager::generate_input_action("move_left", {{GLFW_KEY_A, KEY_DOWN}});
InputManager::generate_input_action("move_up", {{GLFW_KEY_SPACE, KEY_DOWN}});
InputManager::generate_input_action("move_down", {{GLFW_KEY_LEFT_SHIFT, KEY_DOWN}});
}
void load_default_models() {
spdlog::info("loading default models");
ModelManager::models["cube"] = ModelManager::load_from_file("./resources/cube.obj");
ModelManager::models["vette"] = ModelManager::load_from_file("./resources/c4/C4Fixed.obj");
ModelManager::models["male"] = ModelManager::load_from_file("./resources/male.obj");
}
2026-05-02 21:24:21 -04:00
void loop() {
while (!glfwWindowShouldClose(gWindow)) {
// input
2026-05-02 21:24:21 -04:00
glfwPollEvents();
// update
UIManager::update(gEditorCtx);
gCameraController.update(gEditorCtx);
if (gCamera.aspect_ratio() != gEditorCtx.viewportAspectRatio) {
gCamera.update_aspect_ratio(gEditorCtx.viewportAspectRatio);
}
gScene.update_transforms();
2026-05-02 21:24:21 -04:00
const auto* uiScenePanel = dynamic_cast<UISceneViewer*>(UIManager::get_ui_panel("scene_viewer").get());
if (uiScenePanel) {
uiScenePanel->bind_fbo();
2026-05-08 23:44:20 -04:00
}
// draw
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2026-05-09 23:40:52 -04:00
const auto shader = ShaderManager::shaders["phong_shader"];
gScene.draw_scene(shader.get());
glBindVertexArray(0);
ShaderProgram::unbind();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
UIManager::draw();
2026-05-02 21:24:21 -04:00
// end frame
2026-05-02 21:24:21 -04:00
glfwSwapBuffers(gWindow);
}
}
void create_entity(entt::entity parent) {
auto entity = gScene.create_game_object(parent);
auto& drawable = gScene.attach_component<Components::Drawable>(entity);
drawable.model = ModelManager::models["vette"];
auto& transform = gScene.fetch_component<Components::Transform>(entity);
transform.scale = {0.1, 0.1, 0.1};
transform.dirty = true;
}