diff options
Diffstat (limited to 'main/floormat-main-impl.cpp')
-rw-r--r-- | main/floormat-main-impl.cpp | 119 |
1 files changed, 104 insertions, 15 deletions
diff --git a/main/floormat-main-impl.cpp b/main/floormat-main-impl.cpp index 56c19882..85fd5cb9 100644 --- a/main/floormat-main-impl.cpp +++ b/main/floormat-main-impl.cpp @@ -3,11 +3,17 @@ #include "floormat-app.hpp" #include "compat/assert.hpp" #include "compat/fpu.hpp" +#include "src/chunk.hpp" +#include "src/world.hpp" +#include "src/camera-offset.hpp" + +//#define FM_SKIP_MSAA namespace floormat { floormat_main::floormat_main() noexcept = default; floormat_main::~floormat_main() noexcept = default; +main_impl::~main_impl() noexcept = default; static const char* const fm_fake_argv[] = { "floormat", nullptr }; @@ -28,7 +34,15 @@ auto main_impl::make_window_flags(const fm_options& s) -> Configuration::WindowF return flags; } -void main_impl::recalc_viewport(Vector2i size) +auto main_impl::make_conf(const fm_options& s) -> Configuration +{ + return Configuration{} + .setTitle(s.title) + .setSize(s.resolution) + .setWindowFlags(make_window_flags(s)); +} + +void main_impl::recalc_viewport(Vector2i size) noexcept { GL::defaultFramebuffer.setViewport({{}, size }); #ifdef FM_MSAA @@ -40,23 +54,15 @@ void main_impl::recalc_viewport(Vector2i size) #endif _shader.set_scale(Vector2(size)); app.on_viewport_event(size); - setMinimalLoopPeriod(5); } -auto main_impl::make_conf(const fm_options& s) -> Configuration -{ - return Configuration{} - .setTitle(s.title) - .setSize(s.resolution) - .setWindowFlags(make_window_flags(s)); -} - -main_impl::main_impl(floormat_app& app, const fm_options& s) : +// NOLINTNEXTLINE(performance-unnecessary-value-param) +main_impl::main_impl(floormat_app& app, fm_options s) noexcept : Platform::Sdl2Application{Arguments{fake_argc, fm_fake_argv}, make_conf(s), make_gl_conf(s)}, - app{app}, s{s} + app{app}, s{std::move(s)} { - switch (s.vsync) + switch (s.vsync) // NOLINT(bugprone-use-after-move) { case fm_tristate::on: (void)setSwapInterval(1); @@ -75,7 +81,60 @@ main_impl::main_impl(floormat_app& app, const fm_options& s) : timeline.start(); } -main_impl::~main_impl() = default; +global_coords main_impl::pixel_to_tile(Vector2d position) const noexcept +{ + constexpr Vector2d pixel_size{dTILE_SIZE[0], dTILE_SIZE[1]}; + constexpr Vector2d half{.5, .5}; + const Vector2d px = position - Vector2d{windowSize()}*.5 - _shader.camera_offset()*.5; + const Vector2d vec = tile_shader::unproject(px) / pixel_size + half; + const auto x = (std::int32_t)std::floor(vec[0]), y = (std::int32_t)std::floor(vec[1]); + return { x, y }; +} + +auto main_impl::get_draw_bounds() const noexcept -> draw_bounds +{ + + using limits = std::numeric_limits<std::int16_t>; + auto x0 = limits::max(), x1 = limits::min(), y0 = limits::max(), y1 = limits::min(); + + for (const auto win = Vector2d(windowSize()); + auto p : {pixel_to_tile(Vector2d{0, 0}).chunk(), + pixel_to_tile(Vector2d{win[0]-1, 0}).chunk(), + pixel_to_tile(Vector2d{0, win[1]-1}).chunk(), + pixel_to_tile(Vector2d{win[0]-1, win[1]-1}).chunk()}) + { + x0 = std::min(x0, p.x); + x1 = std::max(x1, p.x); + y0 = std::min(y0, p.y); + y1 = std::max(y1, p.y); + } + return {x0, x1, y0, y1}; +} + +void main_impl::draw_world() noexcept +{ + auto [minx, maxx, miny, maxy] = get_draw_bounds(); + + for (std::int16_t y = miny; y <= maxy; y++) + for (std::int16_t x = minx; x <= maxx; x++) + { +#if 0 + if (const chunk_coords c = {x, y}; !_world.contains(c)) + make_test_chunk(*_world[c]); +#endif + const chunk_coords c{x, y}; + const with_shifted_camera_offset o{_shader, c}; + _floor_mesh.draw(_shader, *_world[c]); + } + + for (std::int16_t y = miny; y <= maxy; y++) + for (std::int16_t x = minx; x <= maxx; x++) + { + const chunk_coords c{x, y}; + const with_shifted_camera_offset o{_shader, c}; + _wall_mesh.draw(_shader, *_world[c]); + } +} void main_impl::drawEvent() { @@ -87,15 +146,45 @@ void main_impl::drawEvent() _frame_time = _frame_time*(1-alpha) + alpha*dt; } else + { swapBuffers(); timeline.nextFrame(); + } - const auto dt = std::clamp((double)timeline.previousFrameDuration(), 1e-6, 1e-1); + const float dt = std::clamp(timeline.previousFrameDuration(), 1e-6f, 1e-1f); app.update(dt); _shader.set_tint({1, 1, 1, 1}); + + { + GL::defaultFramebuffer.clear(GL::FramebufferClear::Color); +#if defined FM_MSAA && !defined FM_SKIP_MSAA + _msaa_framebuffer.clear(GL::FramebufferClear::Color); + _msaa_framebuffer.bind(); +#endif + draw_world(); + app.draw_msaa(); +#if defined FM_MSAA && !defined FM_SKIP_MSAA + GL::defaultFramebuffer.bind(); + GL::Framebuffer::blit(_msaa_framebuffer, GL::defaultFramebuffer, {{}, windowSize()}, GL::FramebufferBlit::Color); +#endif + } + + app.draw(); + + swapBuffers(); + redraw(); + timeline.nextFrame(); } +void main_impl::quit(int status) +{ + Platform::Sdl2Application::exit(status); +} + +Vector2i main_impl::window_size() const noexcept { return windowSize(); } +tile_shader& shader() noexcept { return _shader; } + floormat_main* floormat_main::create(floormat_app& app, const fm_options& options) { auto* ret = new main_impl(app, options); |