small-projects/cpp-voxel-engine/main.cpp

194 lines
6.8 KiB
C++
Raw Normal View History

2025-04-06 02:03:23 +00:00
#include <iostream>
2025-04-06 03:14:06 +00:00
#include <cmath>
2025-04-06 02:09:28 +00:00
#include <GL/glew.h>
2025-04-06 02:03:23 +00:00
#include <GLFW/glfw3.h>
2025-04-06 03:14:06 +00:00
#include <GL/glu.h>
2025-04-06 02:03:23 +00:00
#include "imgui.h"
2025-04-06 03:14:06 +00:00
#include "imgui_internal.h" // For Im_PI
2025-04-06 02:03:23 +00:00
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
2025-04-06 03:14:06 +00:00
#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<float>(xpos);
lastY = static_cast<float>(ypos);
firstMouse = false;
}
float xoffset = static_cast<float>(xpos) - lastX;
float yoffset = lastY - static_cast<float>(ypos);
lastX = static_cast<float>(xpos);
lastY = static_cast<float>(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<float>(IM_PI) / 180.0f;
float radPitch = pitch * static_cast<float>(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;
}
2025-04-06 02:03:23 +00:00
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);
2025-04-06 03:14:06 +00:00
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
2025-04-06 02:03:23 +00:00
GLFWwindow* window = glfwCreateWindow(width, height, title, nullptr, nullptr);
if (!window) {
std::cerr << "Failed to create GLFW window\n";
glfwTerminate();
return nullptr;
}
glfwMakeContextCurrent(window);
2025-04-06 03:14:06 +00:00
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
2025-04-06 02:09:28 +00:00
2025-04-06 03:14:06 +00:00
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "GLEW Error\n";
return nullptr;
}
2025-04-06 02:03:23 +00:00
return window;
}
int main() {
GLFWwindow* window = initWindow(800, 600, "Voxel Game");
if (!window)
return -1;
2025-04-06 03:14:06 +00:00
2025-04-06 02:03:23 +00:00
IMGUI_CHECKVERSION();
ImGui::CreateContext();
2025-04-06 03:14:06 +00:00
ImGuiIO &io = ImGui::GetIO(); (void)io;
2025-04-06 02:03:23 +00:00
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 330");
2025-04-06 03:14:06 +00:00
2025-04-06 02:03:23 +00:00
VoxelGame game;
if (!game.init()) {
std::cerr << "Failed to initialize game\n";
return -1;
}
2025-04-06 03:14:06 +00:00
float deltaTime = 0.0f, lastFrame = 0.0f;
static bool cursorEnabled = false;
static bool f1Pressed = false;
2025-04-06 02:03:23 +00:00
while (!glfwWindowShouldClose(window)) {
2025-04-06 03:14:06 +00:00
float currentFrame = static_cast<float>(glfwGetTime());
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
2025-04-06 02:03:23 +00:00
glfwPollEvents();
2025-04-06 03:14:06 +00:00
// Toggle cursor lock with F1 (if ImGui isnt 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;
}
2025-04-06 02:03:23 +00:00
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
2025-04-06 03:14:06 +00:00
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();
2025-04-06 02:03:23 +00:00
game.debugUI();
2025-04-06 03:14:06 +00:00
2025-04-06 02:03:23 +00:00
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
2025-04-06 03:14:06 +00:00
2025-04-06 02:03:23 +00:00
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}