#include #include #include #include #include #include #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include "VoxelGame.h" // camera globals static glm::vec3 cameraPos = {32.0f, 32.0f, 80.0f}; static glm::vec3 cameraFront = {0.0f, 0.0f, -1.0f}; static glm::vec3 cameraUp = {0.0f, 1.0f, 0.0f}; static float yaw = -90.0f, pitch = 0.0f; static bool firstMouse = true; static float lastX, lastY; static void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_NORMAL) return; // do not rotate if cursor is free if (firstMouse) { lastX = float(xpos); lastY = float(ypos); firstMouse = false; } float dx = float(xpos) - lastX; float dy = lastY - float(ypos); lastX = float(xpos); lastY = float(ypos); const float sensitivity = 0.1f; dx *= sensitivity; dy *= sensitivity; yaw += dx; pitch += dy; pitch = std::clamp(pitch, -89.0f, 89.0f); float ry = glm::radians(yaw); float rp = glm::radians(pitch); cameraFront = glm::normalize(glm::vec3( cos(ry)*cos(rp), sin(rp), sin(ry)*cos(rp) )); } static GLFWwindow* initWindow(int w, int h, const char* title) { if (!glfwInit()) return nullptr; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); #endif GLFWwindow* win = glfwCreateWindow(w, h, title, nullptr, nullptr); if (!win) { glfwTerminate(); return nullptr; } glfwMakeContextCurrent(win); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { glfwDestroyWindow(win); glfwTerminate(); return nullptr; } glViewport(0, 0, w, h); glfwSetCursorPosCallback(win, mouse_callback); // start with cursor disabled glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED); lastX = w / 2.0f; lastY = h / 2.0f; return win; } int main() { const int SCR_W = 1280, SCR_H = 720; GLFWwindow* window = initWindow(SCR_W, SCR_H, "Voxel CSM"); if (!window) return -1; // ImGui IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 330"); ImGui::StyleColorsDark(); // Our game VoxelGame game; if (!game.init(SCR_W, SCR_H)) { std::cerr << "Failed to init VoxelGame\n"; return -1; } float lastFrame = 0.0f; bool cursorEnabled = false; bool f1Pressed = false; while (!glfwWindowShouldClose(window)) { float now = float(glfwGetTime()); float dt = now - lastFrame; lastFrame = now; glfwPollEvents(); // Toggle cursor with F1 (when ImGui not capturing) ImGuiIO& io = ImGui::GetIO(); if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_PRESS && !io.WantCaptureMouse) { if (!f1Pressed) { cursorEnabled = !cursorEnabled; glfwSetInputMode(window, GLFW_CURSOR, cursorEnabled ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED); f1Pressed = true; firstMouse = true; // reset for mouse callback } } else if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_RELEASE) { f1Pressed = false; } // WASD movement float speed = 5.0f * dt; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) cameraPos += cameraFront * speed; if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) cameraPos -= cameraFront * speed; glm::vec3 right = glm::normalize(glm::cross(cameraFront, cameraUp)); if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) cameraPos -= right * speed; if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) cameraPos += right * speed; // Build view/proj glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); glm::mat4 proj = glm::perspective(glm::radians(45.0f), float(SCR_W)/SCR_H, 0.1f, 200.0f); // Update & render game.update(dt, cameraPos); game.render(view, proj); // Debug UI ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); game.debugUI(); ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } // Cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); return 0; }