diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-08 12:00:45 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-08 12:00:45 +0100 |
commit | 9acf4738b15738cb2b9646481b75ba0c05a01e78 (patch) | |
tree | d8a8ce5007ea77f86d33136cdfa014e45d31d72b | |
parent | a083f5c2124a6a907727b35a5c43d8175d396d73 (diff) |
draw, editor: visualize bounding boxes
-rw-r--r-- | draw/quad-floor.hpp | 2 | ||||
-rw-r--r-- | draw/quad-wall-n.hpp | 2 | ||||
-rw-r--r-- | draw/quad-wall-w.hpp | 2 | ||||
-rw-r--r-- | draw/quad.cpp | 30 | ||||
-rw-r--r-- | draw/quad.hpp | 29 | ||||
-rw-r--r-- | editor/app.hpp | 6 | ||||
-rw-r--r-- | editor/draw.cpp | 45 | ||||
-rw-r--r-- | editor/events.cpp | 29 | ||||
-rw-r--r-- | editor/imgui.cpp | 7 | ||||
-rw-r--r-- | editor/keys.hpp | 1 | ||||
-rw-r--r-- | editor/update.cpp | 9 | ||||
-rw-r--r-- | floormat/main.hpp | 1 | ||||
-rw-r--r-- | main/draw.cpp | 2 | ||||
-rw-r--r-- | main/main-impl.hpp | 1 | ||||
-rw-r--r-- | src/chunk-bbox.cpp | 14 | ||||
-rw-r--r-- | src/chunk.hpp | 4 |
16 files changed, 153 insertions, 31 deletions
diff --git a/draw/quad-floor.hpp b/draw/quad-floor.hpp index 7a8ec59a..7d974798 100644 --- a/draw/quad-floor.hpp +++ b/draw/quad-floor.hpp @@ -13,7 +13,7 @@ struct quad_floor final quad_floor(Vector3 center, Vector2 size, float line_width); static constexpr std::size_t num_vertices = 4, num_indexes = 0; - static constexpr GL::MeshPrimitive primitive = GL::MeshPrimitive::LineLoop; + static constexpr auto primitive = GL::MeshPrimitive::LineLoop; using vertex_array = std::array<Vector3, num_vertices>; diff --git a/draw/quad-wall-n.hpp b/draw/quad-wall-n.hpp index 30d69e01..f07d7d06 100644 --- a/draw/quad-wall-n.hpp +++ b/draw/quad-wall-n.hpp @@ -12,7 +12,7 @@ struct quad_wall_n final quad_wall_n(Vector3 center, Vector3 size, float line_width); static constexpr std::size_t num_vertices = 4, num_indexes = 0; - static constexpr GL::MeshPrimitive primitive = GL::MeshPrimitive::LineLoop; + static constexpr auto primitive = GL::MeshPrimitive::LineLoop; using vertex_array = std::array<Vector3, num_vertices>; diff --git a/draw/quad-wall-w.hpp b/draw/quad-wall-w.hpp index fb087865..cca70b30 100644 --- a/draw/quad-wall-w.hpp +++ b/draw/quad-wall-w.hpp @@ -12,7 +12,7 @@ struct quad_wall_w final quad_wall_w(Vector3 center, Vector3 size, float line_width); static constexpr std::size_t num_vertices = 4, num_indexes = 0; - static constexpr GL::MeshPrimitive primitive = GL::MeshPrimitive::LineLoop; + static constexpr auto primitive = GL::MeshPrimitive::LineLoop; using vertex_array = std::array<Vector3, num_vertices>; diff --git a/draw/quad.cpp b/draw/quad.cpp new file mode 100644 index 00000000..d7be52f2 --- /dev/null +++ b/draw/quad.cpp @@ -0,0 +1,30 @@ +#include "quad.hpp" +#include "wireframe.hpp" +#include <Magnum/GL/Renderer.h> + +namespace floormat::wireframe { + +quad::quad(Vector3 center, Vector2 size, float line_width) : + center{center}, size{size}, line_width{line_width} +{} + +quad::vertex_array quad::make_vertex_array() const +{ + const auto Sx = size[0]*.5f, Sy = size[1]*.5f; + const auto Cx_0 = center[0] - Sx, Cx_1 = center[0] + Sx; + const auto Cy_0 = center[1] - Sy, Cy_1 = center[1] + Sy; + const auto Cz = center[2] + 0; + return {{ + { Cx_0, Cy_0, Cz }, + { Cx_1, Cy_0, Cz }, + { Cx_1, Cy_1, Cz }, + { Cx_0, Cy_1, Cz }, + }}; +} + +void quad::on_draw() const +{ + mesh_base::set_line_width(line_width); +} + +} // namespace floormat::wireframe diff --git a/draw/quad.hpp b/draw/quad.hpp new file mode 100644 index 00000000..7bccebae --- /dev/null +++ b/draw/quad.hpp @@ -0,0 +1,29 @@ +#pragma once +#include <array> +#include <Corrade/Containers/ArrayViewStl.h> +#include <Magnum/Math/Vector3.h> +#include <Magnum/GL/Mesh.h> + +namespace floormat::wireframe { + +struct quad final +{ + quad(Vector3 start, Vector2 size, float line_width); + + static constexpr std::size_t num_vertices = 4, num_indexes = 0; + static constexpr GL::MeshPrimitive primitive = GL::MeshPrimitive::LineLoop; + + using vertex_array = std::array<Vector3, num_vertices>; + using index_array = std::array<UnsignedShort, num_indexes>; + + vertex_array make_vertex_array() const; + static ArrayView<const void> make_index_array() { return {}; } + void on_draw() const; + +private: + Vector3 center; + Vector2 size; + float line_width = 2; +}; + +} // namespace floormat::wireframe diff --git a/editor/app.hpp b/editor/app.hpp index c34b7ebd..ba1133d7 100644 --- a/editor/app.hpp +++ b/editor/app.hpp @@ -6,12 +6,11 @@ #include "draw/quad-floor.hpp" #include "draw/quad-wall-n.hpp" #include "draw/quad-wall-w.hpp" +#include "draw/quad.hpp" #include "draw/box.hpp" #include "floormat/app.hpp" #include "keys.hpp" - #include <memory> - #include <Corrade/Containers/Pointer.h> #include <Corrade/Containers/Optional.h> #include <Magnum/ImGuiIntegration/Context.h> @@ -93,6 +92,7 @@ private: void do_quickload(); void do_new_file(); + void draw_collision_boxes(); void draw_editor_pane(float main_menu_height); void draw_editor_tile_pane_atlas(tile_editor& ed, StringView name, const std::shared_ptr<tile_atlas>& atlas); void draw_editor_scenery_pane(scenery_editor& ed); @@ -122,10 +122,12 @@ private: wireframe_mesh<wireframe::quad_wall_n> _wireframe_wall_n {_wireframe_texture}; wireframe_mesh<wireframe::quad_wall_w> _wireframe_wall_w {_wireframe_texture}; wireframe_mesh<wireframe::box> _wireframe_box {_wireframe_texture}; + wireframe_mesh<wireframe::quad> _wireframe_rect {_wireframe_texture}; editor _editor; key_set keys; std::array<int, key_set::COUNT> key_modifiers = {}; cursor_state cursor; + bool _draw_collision_boxes : 1 = false; }; } // namespace floormat diff --git a/editor/draw.cpp b/editor/draw.cpp index 275d99fc..32319c1b 100644 --- a/editor/draw.cpp +++ b/editor/draw.cpp @@ -6,6 +6,8 @@ #include "src/anim-atlas.hpp" #include "draw/anim.hpp" #include "src/camera-offset.hpp" +#include "src/world.hpp" +#include "src/collision.hpp" #include <Magnum/Math/Color.h> #include <Magnum/Math/Vector3.h> @@ -54,10 +56,53 @@ void app::draw_cursor() } } } + shader.set_tint({1, 1, 1, 1}); +} + +void app::draw_collision_boxes() +{ + const auto [minx, maxx, miny, maxy] = M->get_draw_bounds(); + const auto sz = M->window_size(); + auto& world = M->world(); + auto& shader = M->shader(); + + shader.set_tint({0, .5f, 1, 1}); + + for (std::int16_t y = miny; y <= maxy; y++) + for (std::int16_t x = minx; x <= maxx; x++) + { + const chunk_coords pos{x, y}; + auto& c = world[pos]; + if (c.empty()) + continue; + c.ensure_passability(); + auto* lqt = c.lqt_from_collision_type(collision::move); + if (!lqt) + continue; + const with_shifted_camera_offset o{shader, pos, {minx, miny}, {maxx, maxy}}; + if (floormat_main::check_chunk_visible(shader.camera_offset(), sz)) + { + auto bb = lqt->GetLooseBoundingBox(); + bb.left -= bb.width; bb.top -= bb.height; + bb.width *= 2; bb.height *= 2; + auto q = lqt->QueryInsideRegion(bb); + using extractor = std::decay_t<decltype(*lqt)>::BoundingBoxExtractor; + while (!q.EndOfQuery()) + { + loose_quadtree::BoundingBox<std::int16_t> bb{0, 0, 0, 0}; + extractor::ExtractBoundingBox(q.GetCurrent(), &bb); + _wireframe_rect.draw(shader, { Vector3(bb.left+bb.width/2.f, bb.top+bb.height/2.f, 0), Vector2(bb.width, bb.height), 3 }); + q.Next(); + } + } + } + shader.set_tint({1, 1, 1, 1}); } void app::draw() { + if (_draw_collision_boxes) + draw_collision_boxes(); if (_editor.current_tile_editor() || _editor.current_scenery_editor()) draw_cursor(); draw_ui(); diff --git a/editor/events.cpp b/editor/events.cpp index 6bf4b3e7..96f5c82c 100644 --- a/editor/events.cpp +++ b/editor/events.cpp @@ -113,20 +113,21 @@ auto app::resolve_keybinding(int k_, int mods_) const -> std::tuple<key, int> switch (int mods = k2 & kmod_mask; k2) { default: continue; - case SDLK_w: return { key_camera_up, mods }; - case SDLK_a: return { key_camera_left, mods }; - case SDLK_s: return { key_camera_down, mods }; - case SDLK_d: return { key_camera_right, mods }; - case SDLK_HOME: return { key_camera_reset, mods }; - case SDLK_r: return { key_rotate_tile, mods }; - case SDLK_1: return { key_mode_none, mods }; - case SDLK_2: return { key_mode_floor, mods }; - case SDLK_3: return { key_mode_walls, mods }; - case SDLK_4: return { key_mode_scenery, mods }; - case SDLK_F5: return { key_quicksave, mods }; - case SDLK_F9: return { key_quickload, mods }; - case SDLK_q | CTRL: return { key_quit, mods }; - case SDLK_n | CTRL: return { key_new_file, mods }; + case SDLK_w: return { key_camera_up, mods }; + case SDLK_a: return { key_camera_left, mods }; + case SDLK_s: return { key_camera_down, mods }; + case SDLK_d: return { key_camera_right, mods }; + case SDLK_HOME: return { key_camera_reset, mods }; + case SDLK_r: return { key_rotate_tile, mods }; + case SDLK_1: return { key_mode_none, mods }; + case SDLK_2: return { key_mode_floor, mods }; + case SDLK_3: return { key_mode_walls, mods }; + case SDLK_4: return { key_mode_scenery, mods }; + case SDLK_F5: return { key_quicksave, mods }; + case SDLK_F9: return { key_quickload, mods }; + case SDLK_q | CTRL: return { key_quit, mods }; + case SDLK_n | CTRL: return { key_new_file, mods }; + case SDLK_b | ALT: return { key_collision_boxes, mods }; } } } diff --git a/editor/imgui.cpp b/editor/imgui.cpp index 1b219561..69037861 100644 --- a/editor/imgui.cpp +++ b/editor/imgui.cpp @@ -77,6 +77,13 @@ float app::draw_main_menu() if (b_rotate) do_key(key_rotate_tile); } + if (auto b = begin_menu("View")) + { + bool show_collisions = _draw_collision_boxes; + ImGui::MenuItem("Collision boxes", "Alt+B", &show_collisions); + if (show_collisions) + do_key(key_collision_boxes); + } main_menu_height = ImGui::GetContentRegionMax().y; } diff --git a/editor/keys.hpp b/editor/keys.hpp index 1f56cb69..3311a69c 100644 --- a/editor/keys.hpp +++ b/editor/keys.hpp @@ -17,6 +17,7 @@ enum key : unsigned { key_NO_REPEAT, key_rotate_tile, key_mode_none, key_mode_floor, key_mode_walls, key_mode_scenery, + key_collision_boxes, key_GLOBAL, key_new_file, key_quit, diff --git a/editor/update.cpp b/editor/update.cpp index f6d64411..4dde4ffc 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -104,6 +104,8 @@ void app::do_key(key k, int mods) return _editor.set_mode(editor_mode::walls); case key_mode_scenery: return _editor.set_mode(editor_mode::scenery); + case key_collision_boxes: + return void(_draw_collision_boxes = !_draw_collision_boxes); case key_quicksave: return do_quicksave(); case key_quickload: @@ -130,9 +132,14 @@ void app::update_world(float dt) minx--; miny--; maxx++; maxy++; for (std::int16_t y = miny; y <= maxy; y++) for (std::int16_t x = minx; x <= maxx; x++) - for (chunk_coords c{x, y}; auto [x, k, pt] : world[c]) + for (auto& c = world[chunk_coords{x, y}]; auto [x, k, pt] : c) if (auto [atlas, scenery] = x.scenery(); atlas != nullptr) + { + auto pass0 = scenery.passability; scenery.update(dt, *atlas); + if (pass0 != scenery.passability) + c.mark_scenery_modified(); + } } void app::update(float dt) diff --git a/floormat/main.hpp b/floormat/main.hpp index 7803cd3c..84f25eda 100644 --- a/floormat/main.hpp +++ b/floormat/main.hpp @@ -56,6 +56,7 @@ struct floormat_main virtual global_coords pixel_to_tile(Vector2d position) const noexcept = 0; virtual draw_bounds get_draw_bounds() const noexcept = 0; + [[nodiscard]] static bool check_chunk_visible(const Vector2d& offset, const Vector2i& size) noexcept; virtual struct meshes meshes() noexcept = 0; virtual struct world& world() noexcept = 0; diff --git a/main/draw.cpp b/main/draw.cpp index 88cd2745..1cb9b396 100644 --- a/main/draw.cpp +++ b/main/draw.cpp @@ -127,7 +127,7 @@ void main_impl::draw_world() noexcept GL::Renderer::disable(GL::Renderer::Feature::DepthTest); } -bool main_impl::check_chunk_visible(const Vector2d& offset, const Vector2i& size) noexcept +bool floormat_main::check_chunk_visible(const Vector2d& offset, const Vector2i& size) noexcept { constexpr Vector3d len = dTILE_SIZE * TILE_MAX_DIM20d; enum : std::size_t { x, y, }; diff --git a/main/main-impl.hpp b/main/main-impl.hpp index 2ea8f940..9178d8a6 100644 --- a/main/main-impl.hpp +++ b/main/main-impl.hpp @@ -90,7 +90,6 @@ private: void draw_world() noexcept; draw_bounds get_draw_bounds() const noexcept override; - [[nodiscard]] static bool check_chunk_visible(const Vector2d& offset, const Vector2i& size) noexcept; char maybe_register_debug_callback(fm_gpu_debug flag); void register_debug_callback(); diff --git a/src/chunk-bbox.cpp b/src/chunk-bbox.cpp index 8d99515b..b951da10 100644 --- a/src/chunk-bbox.cpp +++ b/src/chunk-bbox.cpp @@ -118,7 +118,7 @@ auto chunk::query_collisions(Vector4s vec, collision type) const -> Query { const_cast<chunk&>(*this).ensure_passability(); loose_quadtree::BoundingBox<std::int16_t> bbox { vec[0], vec[1], vec[2], vec[3] }; - return { lqt_from_collision_type(type).QueryIntersectsRegion(bbox) }; + return { lqt_from_collision_type(type)->QueryIntersectsRegion(bbox) }; } auto chunk::query_collisions(Vector2s position, Vector2us size, collision type) const -> Query @@ -127,7 +127,7 @@ auto chunk::query_collisions(Vector2s position, Vector2us size, collision type) constexpr auto half = sTILE_SIZE2/2; const auto start = position - half; loose_quadtree::BoundingBox<std::int16_t> bbox {start[0], start[1], (Short)size[0], (Short)size[1] }; - return { lqt_from_collision_type(type).QueryIntersectsRegion(bbox) }; + return { lqt_from_collision_type(type)->QueryIntersectsRegion(bbox) }; } auto chunk::query_collisions(local_coords p, Vector2us size, Vector2s offset, collision type) const -> Query @@ -136,19 +136,19 @@ auto chunk::query_collisions(local_coords p, Vector2us size, Vector2s offset, co const auto pos = Vector2s(p.x, p.y) * sTILE_SIZE2 + offset; const auto start = pos - Vector2s(size/2); loose_quadtree::BoundingBox<std::int16_t> bbox { start[0], start[1], (Short)size[0], (Short)size[1] }; - return { lqt_from_collision_type(type).QueryIntersectsRegion(bbox) }; + return { lqt_from_collision_type(type)->QueryIntersectsRegion(bbox) }; } -auto chunk::lqt_from_collision_type(collision type) const noexcept -> lqt& +auto chunk::lqt_from_collision_type(collision type) const noexcept -> lqt* { switch (type) { case collision::move: - return *_lqt_move; + return _lqt_move.get(); case collision::shoot: - return *_lqt_shoot; + return _lqt_shoot.get(); case collision::view: - return *_lqt_view; + return _lqt_view.get(); } fm_abort("wrong collision type '%hhu'", std::uint8_t(type)); } diff --git a/src/chunk.hpp b/src/chunk.hpp index d0df8e5d..ebe58d5a 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -107,6 +107,8 @@ struct chunk final Query query_collisions(local_coords p, Vector2us size, Vector2s offset, collision type) const; Query query_collisions(Vector4s vec, collision type) const; + lqt* lqt_from_collision_type(collision type) const noexcept; + private: std::array<std::shared_ptr<tile_atlas>, TILE_COUNT> _ground_atlases; std::array<std::uint8_t, TILE_COUNT> ground_indexes = {}; @@ -129,8 +131,6 @@ private: _walls_modified : 1 = true, _scenery_modified : 1 = true, _pass_modified : 1 = true; - - lqt& lqt_from_collision_type(collision type) const noexcept; static std::unique_ptr<lqt> make_lqt(); void cleanup_lqt(); }; |