/** * \file main.cpp * \brief Univerxel game * \author Maelys Bois * \version 0.0.1 * * Univerxel main program. */ #include #include #include #include #include "render/window.hpp" #include "render/UI.hpp" #include "control/InputMap.hpp" #include "control/Camera.hpp" #include "render/Renderer.hpp" #include "render/pass/ColorProgram.hpp" #include "render/buffer/Colored.hpp" #include "world/Universe.hpp" #include "state.h" #include /// Entry point int main(int, char *[]){ options options; state state; reports reports; GLFWwindow *window = createWindow(options.samples); if(window == NULL) return 1; glClearColor(options.renderer.clear_color.x, options.renderer.clear_color.y, options.renderer.clear_color.z, options.renderer.clear_color.w); glfwSwapInterval(options.target_fps < MIN_FPS); InputMap inputs(window); Camera camera(window, inputs, options.camera); Renderer *renderer = new Renderer(options.renderer); renderer->LightInvDir = glm::vec3(-0.5f, 2, -2); UI::setup(window); GLuint aimTexture = pass::Program::loadTexture("ui/Aim", false); pass::ColorProgram *lookProgram = new pass::ColorProgram(); buffer::Colored lookBuffer(GL_LINES, 24, { glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), glm::vec3(0, 0, 1), glm::vec3(0, 1, 1), glm::vec3(0, 1, 1), glm::vec3(0, 1, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), glm::vec3(1, 0, 1), glm::vec3(1, 0, 1), glm::vec3(1, 1, 1), glm::vec3(1, 1, 1), glm::vec3(1, 1, 0), glm::vec3(1, 1, 0), glm::vec3(1, 0, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), glm::vec3(0, 0, 1), glm::vec3(1, 0, 1), glm::vec3(0, 1, 1), glm::vec3(1, 1, 1), glm::vec3(0, 1, 0), glm::vec3(1, 1, 0), }, { glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1), }); Remotery *rmt; rmt_CreateGlobalInstance(&rmt); rmt_BindOpenGL(); #if RMT_ENABLED std::cout << "Profiling !" << std::endl; #endif world::Universe world = world::Universe(options.world); world.setContouring(contouring::load(options.contouring_idx, options.contouring_data)); state.contouring = world.getContouring(); do { const double startTime = glfwGetTime(); { // Update rmt_ScopedCPUSample(Update, 0); const double partTime = glfwGetTime(); inputs.toggle(state.capture_mouse, Input::Mouse); inputs.toggle(options.show_debug_menu, Input::Debug); camera.update(state.capture_mouse, !UI::isFocus()); renderer->lookFrom(camera); state.position = camera.getPosition(); state.look_at = world.raycast(camera.getRay() / options.voxel_size); if (state.capture_mouse && state.look_at.has_value()) { if (inputs.isPressing(Mouse::Left)) world.setCube(state.look_at.value().first, world::Voxel{0, 0}, options.tool.radius); else if (inputs.isPressing(Mouse::Right)) world.setCube(state.look_at.value().first, world::Voxel{UCHAR_MAX, options.tool.material}, options.tool.radius); } world.update(state.position / options.voxel_size, reports.world); inputs.saveKeys(); reports.main.update.push((glfwGetTime() - partTime) * 1000); } { rmt_ScopedCPUSample(UI, 0); const auto actions = UI::draw(options, state, reports, aimTexture); if (actions && UI::Actions::FPS) { glfwSwapInterval(options.target_fps < MIN_FPS); } if (actions && UI::Actions::FullScreen) { // MAYBE: real fullscreen if(options.fullscreen) { GLFWmonitor *monitor = glfwGetPrimaryMonitor(); const GLFWvidmode *mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); } else { glfwSetWindowMonitor(window, NULL, 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, GLFW_DONT_CARE); } } if(actions && UI::Actions::ClearColor) { renderer->FogColor = glm::vec3(options.renderer.clear_color.x, options.renderer.clear_color.y, options.renderer.clear_color.z); glClearColor(options.renderer.clear_color.x, options.renderer.clear_color.y, options.renderer.clear_color.z, options.renderer.clear_color.w); } if(actions && UI::Actions::RendererSharders) { renderer->reloadShaders(options.renderer.main); } if(actions && UI::Actions::RendererTextures) { renderer->reloadTextures(options.renderer.textures, options.renderer.mipMapLOD); } if(actions && UI::Actions::World) { world.setOptions(options.world); } if(actions && UI::Actions::Camera) { camera.setOptions(options.camera); } if(actions && UI::Actions::ChangeContouring) { state.contouring = NULL; world.setContouring(contouring::load(options.contouring_idx, options.contouring_data)); state.contouring = world.getContouring(); } renderer->SkyEnable = options.renderer.skybox; } { // Rendering rmt_ScopedCPUSample(Render, 0); const double partTime = glfwGetTime(); auto pass = renderer->getPass(); pass.start(); std::vector> models; std::optional frustum; if(options.culling) { frustum = {camera.getFrustum()}; } world.getContouring()->getModels(models, frustum, options.voxel_size); reports.main.models_count = 0; reports.main.tris_count = 0; rmt_ScopedOpenGLSample(Render); for (auto [model, buffer] : models) { reports.main.models_count++; reports.main.tris_count += buffer->draw(pass.setup(model)); } if(state.look_at.has_value()) { lookProgram->useIt(); lookProgram->start(renderer); const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), glm::vec3(options.voxel_size)), glm::vec3(state.look_at.value().first) - glm::vec3(.5 + options.tool.radius)), glm::vec3(1 + options.tool.radius * 2)); lookBuffer.draw(lookProgram->setup(renderer, model)); } renderer->postProcess(); UI::render(); reports.main.render.push((glfwGetTime() - partTime) * 1000); } { // Swap buffers rmt_ScopedCPUSample(Swap, 0); rmt_ScopedOpenGLSample(Swap); const double partTime = glfwGetTime(); glfwSwapBuffers(window); glfwPollEvents(); reports.main.swap.push((glfwGetTime() - partTime) * 1000); } { // Wait target fps const double partTime = glfwGetTime(); if(options.target_fps >= MIN_FPS && options.target_fps <= MAX_FPS) { while (glfwGetTime() < startTime + 1.0 / options.target_fps) { std::this_thread::sleep_for(std::chrono::microseconds(100)); } } reports.main.wait.push((glfwGetTime() - partTime) * 1000); } reports.main.fps.push(1.0 / (glfwGetTime() - startTime)); } // Check if the ESC key was pressed or the window was closed while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0); UI::unload(); delete renderer; rmt_UnbindOpenGL(); rmt_DestroyGlobalInstance(rmt); // Close OpenGL window and terminate GLFW glfwTerminate(); contouring::save(options.contouring_idx, state.contouring, options.contouring_data); options.save(); return 0; }