// src/Engine.cpp // Settings #define VSync 0 #include "Engine.h" #include <cstdio> #include <chrono> #include <GL/glew.h> #include <GLFW/glfw3.h> // Dear ImGui #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include "Windows/RenderWindow.h" #include "Windows/PerformanceWindow.h" #include "Windows/LoggerWindow.h" #include "Windows/InspectorWindow.h" AssetManager g_AssetManager; LoggerWindow *g_LoggerWindow; std::vector<GameObject> m_GameObjects; bool MyEngine::Init(int width, int height, const std::string& title) { DEBUG_PRINT("[START] Engine Init"); // ------------------------------------------ // 1) Initialize GLFW // ------------------------------------------ if (!glfwInit()) { fprintf(stderr, "[Engine] Failed to initialize GLFW\n"); return false; } // Setup hints for OpenGL 3.3 Core glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Create window m_Window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); if (!m_Window) { fprintf(stderr, "[Engine] Failed to create GLFW window\n"); glfwTerminate(); return false; } glfwMakeContextCurrent(m_Window); glfwSwapInterval(VSync); // vsync // ------------------------------------------ // 2) Initialize GLEW // ------------------------------------------ if (glewInit() != GLEW_OK) { fprintf(stderr, "[Engine] Failed to initialize GLEW\n"); return false; } // ------------------------------------------ // 3) Initialize ImGui // ------------------------------------------ IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; // Enable docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // (Optional) Multi-viewport // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Style ImGui::StyleColorsDark(); // Platform/Renderer bindings ImGui_ImplGlfw_InitForOpenGL(m_Window, true); ImGui_ImplOpenGL3_Init("#version 330"); // Initialize windows m_RenderWindow = std::make_unique<RenderWindow>(); m_PerformanceWindow = std::make_unique<PerformanceWindow>(); m_LoggerWindow = std::make_unique<LoggerWindow>(); m_InspectorWindow = std::make_unique<InspectorWindow>(); // Some initial logs m_LoggerWindow->AddLog("Engine initialized."); m_LoggerWindow->AddLog("Welcome to Tesseract Engine!"); g_LoggerWindow = m_LoggerWindow.get(); m_Running = true; m_LastTime = glfwGetTime(); DEBUG_PRINT("[OK] Engine Init "); return true; } GLuint CreateCubeVAO() { // Define cube vertices (Position + UVs) static float g_CubeVertices[] = { // Front face -1.f, -1.f, 1.f, 0.f, 0.f, 1.f, -1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f, -1.f, 1.f, 1.f, 0.f, 1.f, // Back face -1.f, -1.f, -1.f, 1.f, 0.f, 1.f, -1.f, -1.f, 0.f, 0.f, 1.f, 1.f, -1.f, 0.f, 1.f, -1.f, 1.f, -1.f, 1.f, 1.f, // Left face -1.f, -1.f, -1.f, 0.f, 0.f, -1.f, -1.f, 1.f, 1.f, 0.f, -1.f, 1.f, 1.f, 1.f, 1.f, -1.f, 1.f, -1.f, 0.f, 1.f, // Right face 1.f, -1.f, -1.f, 1.f, 0.f, 1.f, -1.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, -1.f, 1.f, 1.f, // Top face -1.f, 1.f, -1.f, 0.f, 0.f, 1.f, 1.f, -1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f, -1.f, 1.f, 1.f, 0.f, 1.f, // Bottom face -1.f, -1.f, -1.f, 1.f, 0.f, 1.f, -1.f, -1.f, 0.f, 0.f, 1.f, -1.f, 1.f, 0.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, }; // Define cube indices static unsigned int g_CubeIndices[] = { // Front face 0, 1, 2, 2, 3, 0, // Back face 4, 5, 6, 6, 7, 4, // Left face 8, 9, 10, 10, 11, 8, // Right face 12, 13, 14, 14, 15, 12, // Top face 16, 17, 18, 18, 19, 16, // Bottom face 20, 21, 22, 22, 23, 20 }; GLuint VAO, VBO, EBO; // Generate and bind VAO glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); // Generate and bind VBO glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(g_CubeVertices), g_CubeVertices, GL_STATIC_DRAW); // Generate and bind EBO glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_CubeIndices), g_CubeIndices, GL_STATIC_DRAW); // Define vertex attributes // Position attribute (location = 0) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // UV attribute (location = 1) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); // Unbind VAO (not EBO!) glBindVertexArray(0); // Optionally, unbind VBO and EBO for cleanliness glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Debug: Print VAO ID printf("[MeshUtils] Initialized CubeVAO with ID: %u\n", VAO); return VAO; } void MyEngine::Run() { DEBUG_PRINT("[START] Engine Run "); // Pseudocode: GameObject cube; cube.transform.position = glm::vec3(0.f, 0.f, 0.f); cube.transform.rotation = glm::vec3(0.f, 0.f, 0.f); cube.transform.scale = glm::vec3(1.f, 1.f, 1.f); // Suppose we loaded a VAO, an EBO with 36 indices for the cube, // and a texture ID from the asset manager cube.mesh.vao = CreateCubeVAO(); cube.mesh.indexCount = 36; cube.mesh.textureID = static_cast<GLuint>(reinterpret_cast<uintptr_t>(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"))); m_GameObjects.push_back(cube); // Possibly create more GameObjects with different positions or textures while (!glfwWindowShouldClose(m_Window) && m_Running) { // Poll glfwPollEvents(); // Calculate FPS double current_time = glfwGetTime(); double delta = current_time - m_LastTime; m_FrameCount++; if (delta >= 0.1) { m_Fps = (float)(m_FrameCount / delta); m_Ms = 100.0f / m_Fps; m_FrameCount = 0; m_LastTime = current_time; } // Start new frame BeginFrame(); // Show main DockSpace ShowDockSpace(); static Transform myTransform; static Script myScript; m_InspectorWindow->Show(myTransform, myScript); // Show our windows m_RenderWindow->Show(); // The spinning triangle as ImGui::Image m_PerformanceWindow->Show(m_Fps, m_Ms); // FPS & ms m_LoggerWindow->Show(); // Logs // After rendering m_PerformanceWindow->UpdatePerformanceStats(-1, -1); // End frame EndFrame(); } DEBUG_PRINT("[OK] Engine Run "); } void MyEngine::Cleanup() { DEBUG_PRINT("[START] Engine Cleanup "); // ImGui cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); // GLFW cleanup if (m_Window) { glfwDestroyWindow(m_Window); m_Window = nullptr; } glfwTerminate(); m_Running = false; DEBUG_PRINT("[OK] Engine Cleanup "); } void MyEngine::BeginFrame() { // ImGui new frame ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); } void MyEngine::EndFrame() { // Render ImGui ImGui::Render(); // Clear the default framebuffer int display_w, display_h; glfwGetFramebufferSize(m_Window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(0.05f, 0.05f, 0.06f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Draw the ImGui data ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // (Optional) handle multi-viewport ImGuiIO& io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { GLFWwindow* backup_current_context = glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); glfwMakeContextCurrent(backup_current_context); } // Swap glfwSwapBuffers(m_Window); } void MyEngine::ShowDockSpace() { static bool dockspaceOpen = true; static bool opt_fullscreen = true; static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; if (opt_fullscreen) { ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->WorkPos); ImGui::SetNextWindowSize(viewport->WorkSize); ImGui::SetNextWindowViewport(viewport->ID); window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; } // Style ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::Begin("DockSpace", &dockspaceOpen, window_flags); ImGui::PopStyleVar(2); // Menu bar example if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("Exit")) m_Running = false; // Stop the engine ImGui::EndMenu(); } ImGui::EndMenuBar(); } // DockSpace ImGuiIO& io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); } else { ImGui::Text("Docking is not enabled. Set io.ConfigFlags |= ImGuiConfigFlags_DockingEnable."); } ImGui::End(); }