#include #include #include #include #include #include "Window.hpp" #include "Mesh.hpp" #include "Camera.hpp" #include "Binder.hpp" #include "Math/MVP.hpp" #include "Shader/ShaderProgram.hpp" #define APP_NAME "Meowcraft" #define WINDOW_WIDTH 1000 #define WINDOW_HEIGHT 800 #define ASPECT static_cast(WINDOW_WIDTH) / WINDOW_HEIGHT #define FOV 45 void run(); void render(MC::BindableMesh&); void process_input(MC::Window&, MC::Camera&); void setup_gl(); void fix_macos_render(MC::Window&); int main() { glfwInit(); try { run(); } catch (std::runtime_error& error) { std::cout << "An error occurred: " << error.what() << std::endl; glfwTerminate(); return 1; } glfwTerminate(); return 0; } void run() { MC::Window window(APP_NAME, WINDOW_WIDTH, WINDOW_HEIGHT); setup_gl(); glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); window.on_size_change([](GLFWwindow* window, int w, int h) { glViewport(0, 0, w, h); }); MC::Mesh shape({ {-0.5f, -0.5f, 0.5f}, {0.5f, -0.5f, 0.5f}, {0.5f, 0.5f, 0.5f}, {-0.5f, 0.5f, 0.5f}, {-0.5f, -0.5f, -0.5f}, {0.5f, -0.5f, -0.5f}, {0.5f, 0.5f, -0.5f}, {-0.5f, 0.5f, -0.5f} }, { 0, 1, 2, 2, 3, 0, 1, 5, 6, 6, 2, 1, 7, 6, 5, 5, 4, 7, 4, 0, 3, 3, 7, 4, 4, 5, 1, 1, 0, 4, 3, 2, 6, 6, 7, 3 }); auto mesh = MC::Binder::load(shape); MC::Camera camera{}; camera.set_position({0.0f, 0.0f, 3.0f}); MC::ShaderProgram program(MC::Shader::create_fragment(), MC::Shader::create_vertex()); auto model_uniform = program.uniform("model_matrix"); auto view_uniform = program.uniform("view_matrix"); auto projection_uniform = program.uniform("projection_matrix"); program.bind(); auto projection = Math::MVP::projection(ASPECT, FOV, 0.1f, 100.0f); projection_uniform.set(projection); uint64_t time = 0; while (!window.should_close()) { window.start_frame(); #ifdef __APPLE__ fix_macos_render(window); #endif process_input(window, camera); program.bind(); auto angle = fmod(time / 10.0f, 360.0f); auto model = Math::MVP::model({0.0f, 0.0f, 0.0f}, {angle, angle, 0.0f}); model_uniform.set(model); auto view = Math::MVP::view(camera.position(), camera.angles()); view_uniform.set(view); render(mesh); time++; } } void render(MC::BindableMesh& mesh) { glClearColor(0.85f, 0.85f, 0.85f, 1.0f); // #DBDBDB glClear(GL_COLOR_BUFFER_BIT); mesh.bind(); glDrawElements(GL_TRIANGLES, mesh.size(), GL_UNSIGNED_INT, 0); mesh.unbind(); } void process_input(MC::Window& window, MC::Camera& camera) { if (window.key(GLFW_KEY_ESCAPE, GLFW_PRESS)) { window.close(); } auto key = [&](int key) -> float { return window.key(key, GLFW_PRESS); }; float x = key(GLFW_KEY_D) - key(GLFW_KEY_A); float y = key(GLFW_KEY_SPACE) - key(GLFW_KEY_LEFT_SHIFT); float z = key(GLFW_KEY_S) - key(GLFW_KEY_W); float rx = key(GLFW_KEY_DOWN) - key(GLFW_KEY_UP); float ry = key(GLFW_KEY_RIGHT) - key(GLFW_KEY_LEFT); auto speed = 0.05f; camera.move({x * speed, y * speed, z * speed}); camera.rotate({rx * speed, ry * speed, 0.0f}); } void setup_gl() { GLenum error; if ((error = glewInit()) != GLEW_OK) { std::string error_string(reinterpret_cast(glewGetErrorString(error))); throw std::runtime_error("Failed to load GL functions: " + error_string); } } void fix_macos_render(MC::Window& window) { static bool moved = false; if(!moved) { int x, y; glfwGetWindowPos(window.get(), &x, &y); glfwSetWindowPos(window.get(), ++x, y); moved = true; } }