#include #include #include #include #include #include "imgui.h" #include "imgui_internal.h" // For Im_PI #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include "VoxelGame.h" // Global camera variables. float yaw = -90.0f; float pitch = 0.0f; float lastX = 400.0f, lastY = 300.0f; bool firstMouse = true; float cameraPos[3] = {32.0f, 32.0f, 80.0f}; float cameraFront[3] = {0.0f, 0.0f, -1.0f}; float cameraUp[3] = {0.0f, 1.0f, 0.0f}; void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_NORMAL) return; if (firstMouse) { lastX = static_cast(xpos); lastY = static_cast(ypos); firstMouse = false; } float xoffset = static_cast(xpos) - lastX; float yoffset = lastY - static_cast(ypos); lastX = static_cast(xpos); lastY = static_cast(ypos); float sensitivity = 0.1f; xoffset *= sensitivity; yoffset *= sensitivity; yaw += xoffset; pitch += yoffset; if (pitch > 89.0f) pitch = 89.0f; if (pitch < -89.0f) pitch = -89.0f; float radYaw = yaw * static_cast(IM_PI) / 180.0f; float radPitch = pitch * static_cast(IM_PI) / 180.0f; cameraFront[0] = cos(radYaw) * cos(radPitch); cameraFront[1] = sin(radPitch); cameraFront[2] = sin(radYaw) * cos(radPitch); float len = std::sqrt(cameraFront[0]*cameraFront[0] + cameraFront[1]*cameraFront[1] + cameraFront[2]*cameraFront[2]); cameraFront[0] /= len; cameraFront[1] /= len; cameraFront[2] /= len; } GLFWwindow* initWindow(int width, int height, const char* title) { if (!glfwInit()) { std::cerr << "Failed to initialize GLFW\n"; return nullptr; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); GLFWwindow* window = glfwCreateWindow(width, height, title, nullptr, nullptr); if (!window) { std::cerr << "Failed to create GLFW window\n"; glfwTerminate(); return nullptr; } glfwMakeContextCurrent(window); glfwSetCursorPosCallback(window, mouse_callback); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cerr << "GLEW Error\n"; return nullptr; } return window; } int main() { GLFWwindow* window = initWindow(800, 600, "Voxel Game"); if (!window) return -1; IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO &io = ImGui::GetIO(); (void)io; ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 330"); VoxelGame game; if (!game.init()) { std::cerr << "Failed to initialize game\n"; return -1; } float deltaTime = 0.0f, lastFrame = 0.0f; static bool cursorEnabled = false; static bool f1Pressed = false; while (!glfwWindowShouldClose(window)) { float currentFrame = static_cast(glfwGetTime()); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glfwPollEvents(); // Toggle cursor lock with F1 (if ImGui isn’t capturing the mouse). if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_PRESS && !ImGui::GetIO().WantCaptureMouse) { if (!f1Pressed) { cursorEnabled = !cursorEnabled; glfwSetInputMode(window, GLFW_CURSOR, cursorEnabled ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED); f1Pressed = true; firstMouse = true; } } else if (glfwGetKey(window, GLFW_KEY_F1) == GLFW_RELEASE) { f1Pressed = false; } float cameraSpeed = 5.0f * deltaTime; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { cameraPos[0] += cameraFront[0] * cameraSpeed; cameraPos[1] += cameraFront[1] * cameraSpeed; cameraPos[2] += cameraFront[2] * cameraSpeed; } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { cameraPos[0] -= cameraFront[0] * cameraSpeed; cameraPos[1] -= cameraFront[1] * cameraSpeed; cameraPos[2] -= cameraFront[2] * cameraSpeed; } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { float right[3] = { cameraFront[1]*cameraUp[2] - cameraFront[2]*cameraUp[1], cameraFront[2]*cameraUp[0] - cameraFront[0]*cameraUp[2], cameraFront[0]*cameraUp[1] - cameraFront[1]*cameraUp[0] }; float rLen = std::sqrt(right[0]*right[0] + right[1]*right[1] + right[2]*right[2]); right[0] /= rLen; right[1] /= rLen; right[2] /= rLen; cameraPos[0] -= right[0] * cameraSpeed; cameraPos[1] -= right[1] * cameraSpeed; cameraPos[2] -= right[2] * cameraSpeed; } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { float right[3] = { cameraFront[1]*cameraUp[2] - cameraFront[2]*cameraUp[1], cameraFront[2]*cameraUp[0] - cameraFront[0]*cameraUp[2], cameraFront[0]*cameraUp[1] - cameraFront[1]*cameraUp[0] }; float rLen = std::sqrt(right[0]*right[0] + right[1]*right[1] + right[2]*right[2]); right[0] /= rLen; right[1] /= rLen; right[2] /= rLen; cameraPos[0] += right[0] * cameraSpeed; cameraPos[1] += right[1] * cameraSpeed; cameraPos[2] += right[2] * cameraSpeed; } ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, 800.0/600.0, 0.1, 200.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float centerX = cameraPos[0] + cameraFront[0]; float centerY = cameraPos[1] + cameraFront[1]; float centerZ = cameraPos[2] + cameraFront[2]; gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2], centerX, centerY, centerZ, cameraUp[0], cameraUp[1], cameraUp[2]); game.update(deltaTime, cameraPos); game.render(); game.debugUI(); ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); return 0; }