diff options
| -rw-r--r-- | editor/camera.cpp | 32 | ||||
| -rw-r--r-- | editor/draw.cpp | 17 | ||||
| -rw-r--r-- | floormat/main.hpp | 5 | ||||
| -rw-r--r-- | main/main-impl.hpp | 3 | ||||
| -rw-r--r-- | main/projection.cpp | 19 |
5 files changed, 34 insertions, 42 deletions
diff --git a/editor/camera.cpp b/editor/camera.cpp index 4bd316e1..3fa8d9d3 100644 --- a/editor/camera.cpp +++ b/editor/camera.cpp @@ -71,22 +71,15 @@ object_id app::get_object_colliding_with_cursor() auto& shader = M->shader(); using rtree_type = std::decay_t<decltype(*world[chunk_coords_{}].rtree())>; - using rect_type = typename rtree_type::Rect; + using rect_type = rtree_type::Rect; if (cursor.pixel) { auto pos = tile_shader::project(Vector3d{0., 0., -_z_level*dTILE_SIZE[2]}); - auto pixel = Vector2d{*cursor.pixel} + pos; - auto coord = M->pixel_to_tile(pixel); - auto tile = global_coords{coord.chunk(), coord.local(), 0}; - - constexpr auto eps = 1e-6f; - constexpr auto m = TILE_SIZE2 * Vector2(1- eps, 1- eps); - const auto tile_ = Vector2(M->pixel_to_tile_(Vector2d(pixel))); + const auto [tile, subpixelʹ] = M->pixel_to_point(Vector2d{*cursor.pixel} + pos); const auto curchunk = Vector2(tile.chunk()), curtile = Vector2(tile.local()); - const auto subpixelʹ = Math::fmod(tile_, 1.f); - const auto subpixel = m * Vector2(curchunk[0] < 0 ? 1 + subpixelʹ[0] : subpixelʹ[0], - curchunk[1] < 0 ? 1 + subpixelʹ[1] : subpixelʹ[1]); + const auto subpixel = Vector2(subpixelʹ); + for (int16_t y = miny; y <= maxy; y++) for (int16_t x = minx; x <= maxx; x++) { @@ -99,10 +92,9 @@ object_id app::get_object_colliding_with_cursor() const with_shifted_camera_offset o{shader, c_pos, {minx, miny}, {maxx, maxy}}; if (floormat_main::check_chunk_visible(shader.camera_offset(), sz)) { - constexpr auto half_tile = TILE_SIZE2/2; constexpr auto chunk_size = TILE_SIZE2 * TILE_MAX_DIM; auto chunk_dist = (curchunk - Vector2(c_pos.x, c_pos.y))*chunk_size; - auto t0 = chunk_dist + curtile*TILE_SIZE2 + subpixel - half_tile; + auto t0 = chunk_dist + curtile*TILE_SIZE2 + subpixel; auto t1 = t0+Vector2(1e-4f); const auto* rtree = c.rtree(); object_id ret = 0; @@ -136,19 +128,9 @@ void app::update_cursor_tile(const Optional<Vector2i>& pixel) // assert_invariant !!cursor.tile == !!cursor.subpixel; if (pixel) { - auto coord = M->pixel_to_tile(Vector2d{*pixel}); - auto tile = global_coords{coord.chunk(), coord.local(), _z_level}; + auto [tile, subpixel] = M->pixel_to_point(Vector2d(*pixel), _z_level); cursor.tile = tile; - - const auto tile_ = Vector2(M->pixel_to_tile_(Vector2d(*pixel))); - const auto curchunk = Vector2(tile.chunk()); - const auto subpixelʹ = Math::fmod(tile_, 1.f); - auto subpixel = TILE_SIZE2 * Vector2(curchunk.x() < 0 ? 1 + subpixelʹ.x() : subpixelʹ.x(), - curchunk.y() < 0 ? 1 + subpixelʹ.y() : subpixelʹ.y()); - constexpr auto half_tile = Vector2(iTILE_SIZE2/2); - subpixel -= half_tile; - subpixel = Math::clamp(Math::round(subpixel), -half_tile, half_tile-Vector2{1.f}); - cursor.subpixel = Vector2b(subpixel); + cursor.subpixel = subpixel; } else { diff --git a/editor/draw.cpp b/editor/draw.cpp index 590c2ff1..f0d642bc 100644 --- a/editor/draw.cpp +++ b/editor/draw.cpp @@ -155,17 +155,9 @@ void app::draw_collision_boxes() { auto pos = tile_shader::project(Vector3d{0., 0., -_z_level*dTILE_SIZE[2]}); auto pixel = Vector2d{*cursor.pixel} + pos; - auto coord = M->pixel_to_tile(pixel); - auto tile = global_coords{coord.chunk(), coord.local(), 0}; - - constexpr auto eps = 1e-6f; - constexpr auto m = TILE_SIZE2 * Vector2(1- eps, 1- eps); - const auto tile_ = Vector2(M->pixel_to_tile_(Vector2d(pixel))); - const auto curchunk = Vector2(tile.chunk()), curtile = Vector2(tile.local()); - const auto subpixelʹ = Math::fmod(tile_, 1.f); - // todo use this formula for dragging objs - const auto subpixel = m * Vector2(curchunk[0] < 0 ? 1 + subpixelʹ[0] : subpixelʹ[0], - curchunk[1] < 0 ? 1 + subpixelʹ[1] : subpixelʹ[1]); + const auto [coord, subpixelʹ] = M->pixel_to_point(Vector2d(pixel)); + const auto curchunk = Vector2(coord.chunk()), curtile = Vector2(coord.local()); + const auto subpixel = Vector2(subpixelʹ); for (int16_t y = miny; y <= maxy; y++) for (int16_t x = minx; x <= maxx; x++) { @@ -178,10 +170,9 @@ void app::draw_collision_boxes() const with_shifted_camera_offset o{shader, c_pos, {minx, miny}, {maxx, maxy}}; if (floormat_main::check_chunk_visible(shader.camera_offset(), sz)) { - constexpr auto half_tile = TILE_SIZE2/2; constexpr auto chunk_size = TILE_SIZE2 * TILE_MAX_DIM; auto chunk_dist = (curchunk - Vector2(c_pos.x, c_pos.y))*chunk_size; - auto t0 = chunk_dist + curtile*TILE_SIZE2 + subpixel - half_tile; + auto t0 = chunk_dist + curtile*TILE_SIZE2 + subpixel; auto t1 = t0+Vector2(1e-4f); const auto* rtree = c.rtree(); rtree->Search(t0.data(), t1.data(), [&](uint64_t data, const rect_type& rect) { diff --git a/floormat/main.hpp b/floormat/main.hpp index 2ed8518f..8239a05a 100644 --- a/floormat/main.hpp +++ b/floormat/main.hpp @@ -24,6 +24,7 @@ struct anim_mesh; struct texture_unit_cache; class path_search; class astar; +struct point; struct floormat_main { @@ -68,8 +69,10 @@ struct floormat_main virtual void set_cursor(uint32_t cursor) noexcept = 0; virtual uint32_t cursor() const noexcept = 0; - virtual global_coords pixel_to_tile(Vector2d position) const noexcept = 0; + virtual global_coords pixel_to_tile(Vector2d position, int8_t z_level = 0) const noexcept = 0; virtual Vector2d pixel_to_tile_(Vector2d position) const noexcept = 0; + virtual point pixel_to_point(Vector2d position, int8_t z_level = 0) 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; diff --git a/main/main-impl.hpp b/main/main-impl.hpp index 39e07d4c..66f143d1 100644 --- a/main/main-impl.hpp +++ b/main/main-impl.hpp @@ -65,8 +65,9 @@ struct main_impl final : Platform::Sdl2Application, floormat_main fm_settings& settings() noexcept override; const fm_settings& settings() const noexcept override; - global_coords pixel_to_tile(Vector2d position) const noexcept override; + global_coords pixel_to_tile(Vector2d position, int8_t z_level = 0) const noexcept override; Vector2d pixel_to_tile_(Vector2d position) const noexcept override; + point pixel_to_point(Vector2d position, int8_t z_level = 0) const noexcept override; ArrayView<const clickable> clickable_scenery() const noexcept override; ArrayView<clickable> clickable_scenery() noexcept override; diff --git a/main/projection.cpp b/main/projection.cpp index 8b32777e..b7ee01da 100644 --- a/main/projection.cpp +++ b/main/projection.cpp @@ -1,15 +1,16 @@ #include "main-impl.hpp" #include "src/tile-constants.hpp" +#include "src/point.hpp" #include <algorithm> #include <limits> namespace floormat { -global_coords main_impl::pixel_to_tile(Vector2d position) const noexcept +global_coords main_impl::pixel_to_tile(Vector2d position, int8_t z_level) const noexcept { auto vec = pixel_to_tile_(position); auto vec_ = Math::floor(vec); - return { (int32_t)vec_.x(), (int32_t)vec_.y(), 0 }; + return { (int32_t)vec_.x(), (int32_t)vec_.y(), z_level }; } Vector2d main_impl::pixel_to_tile_(Vector2d position) const noexcept @@ -20,6 +21,20 @@ Vector2d main_impl::pixel_to_tile_(Vector2d position) const noexcept return tile_shader::unproject(px*.5) / pixel_size + half; } +point main_impl::pixel_to_point(Vector2d pixel, int8_t z_level) const noexcept +{ + const auto tileʹ = pixel_to_tile_(pixel); + const auto tileʹʹ = Math::floor(tileʹ); + const auto tile = global_coords{(int)tileʹʹ.x(), (int)tileʹʹ.y(), z_level}; + const auto subpixelʹ = Math::fmod(Vector2(tileʹ), 1.f); + const auto subpixelʹ_neg = Vector2{Vector2i(tile.chunk()) < Vector2i{}}; + auto subpixel = TILE_SIZE2 * (subpixelʹ + subpixelʹ_neg); + constexpr auto half_tile = Vector2(iTILE_SIZE2/2); + subpixel -= half_tile; + subpixel = Math::clamp(Math::round(subpixel), -half_tile, half_tile-Vector2{1.f}); + return point{ tile, Vector2b{subpixel} }; +} + auto main_impl::get_draw_bounds() const noexcept -> draw_bounds { using limits = std::numeric_limits<int16_t>; |
