summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-10-17 13:28:37 +0200
committerStanislaw Halik <sthalik@misaki.pl>2022-10-17 13:28:37 +0200
commit7f01dc47b0fd322d8c2b3f27eb1a94cd450a26a5 (patch)
treeac6201f9179a0315449ad46d742d2db325775eff
parente65ebe30d3f2af77d57cb15e5e2b30efa454b6a8 (diff)
a
-rw-r--r--main/app.cpp23
-rw-r--r--main/app.hpp28
-rw-r--r--main/draw.cpp79
-rw-r--r--main/editor.cpp7
-rw-r--r--main/editor.hpp3
-rw-r--r--main/update.cpp23
-rw-r--r--src/chunk.cpp6
-rw-r--r--src/chunk.hpp1
-rw-r--r--src/global-coords.cpp9
-rw-r--r--src/global-coords.hpp26
-rw-r--r--src/world.cpp31
-rw-r--r--src/world.hpp33
12 files changed, 160 insertions, 109 deletions
diff --git a/main/app.cpp b/main/app.cpp
index b412c81b..4150e452 100644
--- a/main/app.cpp
+++ b/main/app.cpp
@@ -30,6 +30,10 @@ app::app(const Arguments& arguments):
_imgui = ImGuiIntegration::Context(Vector2{windowSize()}, windowSize(), framebufferSize());
setup_menu();
SDL_MaximizeWindow(window());
+ {
+ auto c = _world[chunk_coords{0, 0}];
+ make_test_chunk(*c);
+ }
timeline.start();
}
@@ -130,3 +134,22 @@ void app::event_mouse_enter()
}
} // namespace floormat
+
+MAGNUM_APPLICATION_MAIN(floormat::app)
+
+#ifdef _MSC_VER
+#include <cstdlib> // for __arg{c,v}
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wmain"
+#endif
+extern "C" int __stdcall WinMain(void*, void*, void*, int);
+
+extern "C" int __stdcall WinMain(void*, void*, void*, int)
+{
+ return main(__argc, __argv);
+}
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
+#endif
diff --git a/main/app.hpp b/main/app.hpp
index 403b8888..1237f205 100644
--- a/main/app.hpp
+++ b/main/app.hpp
@@ -10,6 +10,7 @@
#include "draw/wireframe-box.hpp"
#include "compat/enum-bitset.hpp"
#include "editor.hpp"
+#include "world.hpp"
#include <Magnum/Timeline.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/GL/DebugOutput.h>
@@ -25,10 +26,14 @@ struct app final : Platform::Application
explicit app(const Arguments& arguments);
virtual ~app();
- void drawEvent() override;
+
void update(float dt);
- void do_camera(float dt);
+
void reset_camera_offset();
+ void update_window_scale(Vector2i window_size);
+
+ void do_camera(float dt);
+ void do_key(KeyEvent::Key k, KeyEvent::Modifiers m, bool pressed, bool repeated);
void keyPressEvent(KeyEvent& event) override;
void keyReleaseEvent(KeyEvent& event) override;
@@ -37,29 +42,30 @@ struct app final : Platform::Application
void mouseMoveEvent(MouseMoveEvent& event) override;
void mouseScrollEvent(MouseScrollEvent& event) override;
void textInputEvent(TextInputEvent& event) override;
+ void viewportEvent(ViewportEvent& event) override;
void anyEvent(SDL_Event& event) override;
void event_leave();
void event_enter();
void event_mouse_enter();
void event_mouse_leave();
- void do_key(KeyEvent::Key k, KeyEvent::Modifiers m, bool pressed, bool repeated);
- void draw_chunk(chunk& c);
- void draw_wireframe_quad(local_coords pt);
+ void drawEvent() override;
+ void draw_world();
+ void draw_wireframe_quad(global_coords pt);
void draw_wireframe_box(local_coords pt);
- void update_window_scale(Vector2i window_size);
- void viewportEvent(ViewportEvent& event) override;
+
void do_menu();
void draw_menu_(tile_type& type, float main_menu_height);
void setup_menu();
void display_menu();
+
void debug_callback(GL::DebugOutput::Source src, GL::DebugOutput::Type type, UnsignedInt id,
GL::DebugOutput::Severity severity, const std::string& str) const;
void* register_debug_callback();
- Vector2 pixel_to_tile(Vector2 position) const;
+ global_coords pixel_to_tile(Vector2 position) const;
void draw_cursor_tile();
- void do_mouse_click(Vector2 pos, int button);
+ void do_mouse_click(global_coords pos, int button);
std::optional<Vector2i> _cursor_pos;
@@ -71,7 +77,7 @@ struct app final : Platform::Application
quit,
MAX
};
- chunk make_test_chunk();
+ void make_test_chunk(chunk& c);
const void* _dummy = register_debug_callback();
tile_shader _shader;
@@ -79,7 +85,6 @@ struct app final : Platform::Application
tile_atlas_ floor2 = loader.tile_atlas("metal1.tga", {2, 2});
tile_atlas_ wall1 = loader.tile_atlas("wood2.tga", {2, 2});
tile_atlas_ wall2 = loader.tile_atlas("wood1.tga", {2, 2});
- chunk _chunk = make_test_chunk();
floor_mesh _floor_mesh;
wall_mesh _wall_mesh;
@@ -88,6 +93,7 @@ struct app final : Platform::Application
ImGuiIntegration::Context _imgui{NoCreate};
+ world _world;
Vector2 camera_offset;
enum_bitset<key> keys;
Magnum::Timeline timeline;
diff --git a/main/draw.cpp b/main/draw.cpp
index 91277c34..fde48915 100644
--- a/main/draw.cpp
+++ b/main/draw.cpp
@@ -25,7 +25,7 @@ void app::drawEvent() {
}
_shader.set_tint({1, 1, 1, 1});
- draw_chunk(_chunk);
+ draw_world();
draw_cursor_tile();
display_menu();
@@ -34,16 +34,17 @@ void app::drawEvent() {
timeline.nextFrame();
}
-void app::draw_chunk(chunk& c)
+void app::draw_world()
{
+ // TODO chunk offset
+ std::int16_t minx = 0, maxx = 0, miny = 0, maxy = 0;
{
- int minx = 0, maxx = 0, miny = 0, maxy = 0;
- auto fn = [&](int x, int y) {
- const auto pos = pixel_to_tile({(float)x, (float)y}) / Vector2{TILE_MAX_DIM, TILE_MAX_DIM};
- minx = std::min(minx, (int)std::floor(pos[0]));
- maxx = std::max(maxx, (int)(pos[0]));
- miny = std::min(miny, (int)std::floor(pos[1]));
- maxy = std::max(maxy, (int)(pos[1]));
+ const auto fn = [&](int x, int y) {
+ const auto pos = pixel_to_tile({(float)x, (float)y}).chunk();
+ minx = std::min(minx, pos.x);
+ maxx = std::max(maxx, pos.x);
+ miny = std::min(miny, pos.y);
+ maxy = std::max(maxy, pos.y);
};
const auto sz = windowSize();
const auto x = sz[0], y = sz[1];
@@ -51,22 +52,49 @@ void app::draw_chunk(chunk& c)
fn(x, 0);
fn(0, y);
fn(x, y);
-
- // TODO
- printf(""); // put breakpoint here
}
+ const auto old_camera_offset = _shader.camera_offset();
_shader.set_tint({1, 1, 1, 1});
- _floor_mesh.draw(_shader, c);
- _wall_mesh.draw(_shader, c);
+
+ for (std::int16_t y = miny; y <= maxy; y++)
+ for (std::int16_t x = minx; x <= maxx; x++)
+ {
+ const auto offset = project({float(x)*TILE_MAX_DIM*TILE_SIZE[0],
+ float(y)*TILE_MAX_DIM*TILE_SIZE[1],
+ 0});
+ _shader.set_camera_offset(offset + old_camera_offset);
+ auto c = _world[chunk_coords{x, y}];
+ _floor_mesh.draw(_shader, *c);
+ }
+
+ for (std::int16_t y = miny; y <= maxy; y++)
+ for (std::int16_t x = minx; x <= maxx; x++)
+ {
+ const auto offset = project({float(x)*TILE_MAX_DIM*TILE_SIZE[0],
+ float(y)*TILE_MAX_DIM*TILE_SIZE[1],
+ 0});
+ _shader.set_camera_offset(offset + old_camera_offset);
+ auto c = _world[chunk_coords{x, y}];
+ _wall_mesh.draw(_shader, *c);
+ }
+
+ _shader.set_camera_offset(old_camera_offset);
}
-void app::draw_wireframe_quad(local_coords pt)
+void app::draw_wireframe_quad(global_coords pos)
{
constexpr float LINE_WIDTH = 1;
+ {
+ const auto c = _world[pos.chunk()];
+ if (const auto& tile = (*c)[pos.local()]; !tile.ground_image)
+ return;
+ }
+
+ const auto pt = pos.to_signed();
constexpr auto X = TILE_SIZE[0], Y = TILE_SIZE[1];
- const Vector3 center {X*pt.x, Y*pt.y, 0};
+ const Vector3 center {X*pt[0], Y*pt[1], 0};
_shader.set_tint({1, 0, 0, 1});
_wireframe_quad.draw(_shader, {center, {TILE_SIZE[0], TILE_SIZE[1]}, LINE_WIDTH});
}
@@ -83,22 +111,3 @@ void app::draw_wireframe_box(local_coords pt)
}
} // namespace floormat
-
-MAGNUM_APPLICATION_MAIN(floormat::app)
-
-#ifdef _MSC_VER
-#include <cstdlib> // for __arg{c,v}
-#ifdef __clang__
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wmain"
-#endif
-extern "C" int __stdcall WinMain(void*, void*, void*, int);
-
-extern "C" int __stdcall WinMain(void*, void*, void*, int)
-{
- return main(__argc, __argv);
-}
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
-#endif
diff --git a/main/editor.cpp b/main/editor.cpp
index e95bc6e3..04578adb 100644
--- a/main/editor.cpp
+++ b/main/editor.cpp
@@ -126,14 +126,11 @@ editor::editor()
{
}
-void editor::click_at_tile(Vector2 pos, int mouse_button)
+void editor::click_at_tile(const global_coords pos, int mouse_button)
{
if (mouse_button == 0)
{
- if (pos[0] >= 0 && pos[1] >= 0 && pos[0] < TILE_MAX_DIM && pos[1] < TILE_MAX_DIM)
- {
-
- }
+ // TODO
}
}
diff --git a/main/editor.hpp b/main/editor.hpp
index aac474c0..f9e2def7 100644
--- a/main/editor.hpp
+++ b/main/editor.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "compat/defs.hpp"
#include "tile-atlas.hpp"
+#include "global-coords.hpp"
#include <cstdint>
#include <map>
#include <memory>
@@ -66,7 +67,7 @@ struct editor final
tile_type& floor() { return _floor; }
const tile_type& floor() const { return _floor; }
- void click_at_tile(Vector2 pos, int mouse_button);
+ void click_at_tile(global_coords pos, int mouse_button);
editor();
editor(editor&&) noexcept = default;
diff --git a/main/update.cpp b/main/update.cpp
index 1c7bb500..28e1d985 100644
--- a/main/update.cpp
+++ b/main/update.cpp
@@ -2,10 +2,9 @@
namespace floormat {
-chunk app::make_test_chunk()
+void app::make_test_chunk(chunk& c)
{
constexpr auto N = TILE_MAX_DIM;
- chunk c;
for (auto [x, k, pt] : c) {
const auto& atlas = pt.x > N/2 && pt.y >= N/2 ? floor2 : floor1;
x.ground_image = { atlas, (std::uint8_t)(k % atlas->num_tiles().product()) };
@@ -15,10 +14,9 @@ chunk app::make_test_chunk()
c[{K, K }].wall_west = { wall2, 0 };
c[{K, K+1}].wall_north = { wall1, 0 };
c[{K+1, K }].wall_west = { wall2, 0 };
- return c;
}
-void app::do_mouse_click(const Vector2 pos, int button)
+void app::do_mouse_click(const global_coords pos, int button)
{
_editor.click_at_tile(pos, button);
}
@@ -31,23 +29,18 @@ void app::update(float dt)
Platform::Sdl2Application::exit(0);
}
-Vector2 app::pixel_to_tile(Vector2 position) const
+global_coords app::pixel_to_tile(Vector2 position) const
{
- const auto px = position - Vector2{windowSize()}*.5f - camera_offset;
- return unproject(px) / Vector2{TILE_SIZE[0]*.5f, TILE_SIZE[1]*.5f} + Vector2{.5f, .5f};
+ const Vector2 px = position - Vector2{windowSize()}*.5f - camera_offset;
+ const Vector2 vec = unproject(px) / Vector2{TILE_SIZE[0]*.5f, TILE_SIZE[1]*.5f} + Vector2{.5f, .5f};
+ const auto x = (std::int32_t)std::floor(vec[0]), y = (std::int32_t)std::floor(vec[1]);
+ return { x, y };
}
void app::draw_cursor_tile()
{
if (_cursor_pos)
- {
- const auto tile = pixel_to_tile(Vector2(*_cursor_pos));
- if (std::min(tile[0], tile[1]) >= 0 && std::max(tile[0], tile[1]) < (int)TILE_MAX_DIM)
- {
- const auto x = std::uint8_t(tile[0]), y = std::uint8_t(tile[1]);
- draw_wireframe_quad({x, y});
- }
- }
+ draw_wireframe_quad(pixel_to_tile(Vector2(*_cursor_pos)));
}
} // namespace floormat
diff --git a/src/chunk.cpp b/src/chunk.cpp
index 95904d81..d8c2d011 100644
--- a/src/chunk.cpp
+++ b/src/chunk.cpp
@@ -4,9 +4,15 @@ namespace floormat {
bool chunk::empty() const
{
+ if (!_maybe_empty)
+ return false;
+
for (const tile& x : _tiles)
if (x.ground_image || x.wall_north || x.wall_west)
+ {
+ _maybe_empty = false;
return false;
+ }
return true;
}
diff --git a/src/chunk.hpp b/src/chunk.hpp
index 7ef0bc94..9e41c5fb 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -41,6 +41,7 @@ struct chunk final
private:
std::array<tile, TILE_COUNT> _tiles = {};
+ mutable bool _maybe_empty = true;
};
} // namespace floormat
diff --git a/src/global-coords.cpp b/src/global-coords.cpp
index 997f1c11..e10e921f 100644
--- a/src/global-coords.cpp
+++ b/src/global-coords.cpp
@@ -9,9 +9,10 @@ static_assert(std::is_same_v<decltype(chunk_coords::x), decltype(chunk_coords::y
static_assert(std::is_same_v<decltype(chunk_coords::x), decltype(chunk_coords::y)>);
-static_assert(global_coords{{-1, -1}, {2, 3}} == global_coords{((-1 + (1 << 15)) << 4) + 2, ((-1 + (1 << 15)) << 4) + 3});
-static_assert(global_coords{15, 15}.chunk() == global_coords{}.chunk());
-static_assert(global_coords{15, 16}.chunk() != global_coords{}.chunk());
-static_assert(global_coords{(1 + (1<<15)) << 4 | 3, (2 + (1<<15)) << 4 | 4} == global_coords{{1, 2}, {3, 4}});
+static_assert(TILE_MAX_DIM == (1 << 4));
+
+static_assert(global_coords{(int)TILE_MAX_DIM-1, (int)TILE_MAX_DIM-1}.chunk() == global_coords{}.chunk());
+static_assert(global_coords{(int)TILE_MAX_DIM-1, (int)TILE_MAX_DIM}.chunk() != global_coords{}.chunk());
+static_assert(global_coords{(1u + (1<<15)) << 4 | 3, (2u + (1<<15)) << 4 | 4} == global_coords{{1, 2}, {3, 4}});
} // namespace floormat
diff --git a/src/global-coords.hpp b/src/global-coords.hpp
index e51dc6aa..d3c36c96 100644
--- a/src/global-coords.hpp
+++ b/src/global-coords.hpp
@@ -1,6 +1,8 @@
#pragma once
#include "local-coords.hpp"
#include "compat/assert.hpp"
+#include <Magnum/Magnum.h>
+#include <Magnum/Math/Vector2.h>
namespace floormat {
@@ -11,31 +13,47 @@ struct chunk_coords final {
};
struct global_coords final {
- std::uint32_t x = 0, y = 0;
+ std::uint32_t x = 1 << 15, y = 1 << 15;
constexpr global_coords(chunk_coords c, local_coords xy) :
x{ std::uint32_t(c.x + (1 << 15)) << 4 | (xy.x & 0x0f) },
y{ std::uint32_t(c.y + (1 << 15)) << 4 | (xy.y & 0x0f) }
{}
constexpr global_coords(std::uint32_t x, std::uint32_t y) noexcept : x{x}, y{y} {}
+ constexpr global_coords(std::int32_t x, std::int32_t y) noexcept :
+ x{std::uint32_t(x + (1 << 15))}, y{std::uint32_t(y + (1 << 15))}
+ {}
constexpr global_coords() noexcept = default;
constexpr local_coords local() const noexcept;
constexpr chunk_coords chunk() const noexcept;
+ constexpr Vector2i to_signed() const noexcept;
+
constexpr bool operator==(const global_coords& other) const noexcept = default;
};
constexpr local_coords global_coords::local() const noexcept
{
- return { (std::uint8_t)(x % TILE_MAX_DIM), (std::uint8_t)(y % TILE_MAX_DIM) };
+ return {
+ std::uint8_t(x & 0x0f),
+ std::uint8_t(y & 0x0f),
+ };
}
constexpr chunk_coords global_coords::chunk() const noexcept
{
return {
- (std::int16_t)(std::int32_t(x >> 4) - (1 << 15)),
- (std::int16_t)(std::int32_t(y >> 4) - (1 << 15)),
+ std::int16_t((x - (1 << 15)) >> 4),
+ std::int16_t((y - (1 << 15)) >> 4),
+ };
+}
+
+constexpr Vector2i global_coords::to_signed() const noexcept
+{
+ return {
+ std::int32_t(x - (1 << 15)),
+ std::int32_t(y - (1 << 15)),
};
}
diff --git a/src/world.cpp b/src/world.cpp
index 3057fca8..8337bfba 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -5,7 +5,7 @@ namespace floormat {
struct chunk_pointer_maker final
{
- operator std::shared_ptr<chunk>() const { return std::make_shared<chunk>(); }
+ inline operator std::shared_ptr<chunk>() const { return std::make_shared<chunk>(); }
};
world::world()
@@ -15,22 +15,26 @@ world::world()
std::shared_ptr<chunk> world::operator[](chunk_coords c) noexcept
{
+ maybe_collect();
+
+ if (_last_chunk)
+ {
+ auto& [ret, pos] = *_last_chunk;
+ if (pos == c)
+ return ret;
+ }
+
auto [it, inserted] = _chunks.try_emplace(c, chunk_pointer_maker{});
- const auto ret = it->second;
- return maybe_collect(), ret;
+ auto ret = it->second;
+ _last_chunk = { ret, c };
+ return ret;
}
-std::shared_ptr<chunk> world::maybe_chunk(chunk_coords c) noexcept
-{
- if (const auto it = _chunks.find(c); it != _chunks.cend())
- return it->second;
- else
- return nullptr;
-}
-std::shared_ptr<const chunk> world::maybe_chunk(chunk_coords c) const noexcept
+std::tuple<std::shared_ptr<chunk>, tile&> world::operator[](global_coords pt) noexcept
{
- return const_cast<world&>(*this).maybe_chunk(c);
+ auto c = operator[](pt.chunk());
+ return { c, (*c)[pt.local()] };
}
bool world::contains(chunk_coords c) const noexcept
@@ -41,6 +45,7 @@ bool world::contains(chunk_coords c) const noexcept
void world::clear()
{
_last_collection = 0;
+ _last_chunk = std::nullopt;
_chunks.clear();
_chunks.rehash(initial_capacity);
}
@@ -61,7 +66,9 @@ void world::collect()
else
++it;
}
+
_last_collection = _chunks.size();
+ _last_chunk = std::nullopt;
}
} // namespace floormat
diff --git a/src/world.hpp b/src/world.hpp
index 1e8469d9..7c256efc 100644
--- a/src/world.hpp
+++ b/src/world.hpp
@@ -1,24 +1,10 @@
#pragma once
#include "compat/int-hash.hpp"
#include "global-coords.hpp"
+#include "tile.hpp"
#include <unordered_map>
#include <memory>
-
-namespace std {
-
-template<typename> struct hash;
-
-template<>
-struct hash<floormat::chunk_coords> final
-{
- constexpr
- std::size_t operator()(floormat::chunk_coords c) const noexcept
- {
- return floormat::int_hash((std::size_t)c.y << 16 | (std::size_t)c.x);
- }
-};
-
-} // namespace std
+#include <optional>
namespace floormat {
@@ -28,20 +14,23 @@ struct world final
{
world();
std::shared_ptr<chunk> operator[](chunk_coords c) noexcept;
- std::shared_ptr<chunk> maybe_chunk(chunk_coords c) noexcept;
- std::shared_ptr<const chunk> maybe_chunk(chunk_coords c) const noexcept;
+ std::tuple<std::shared_ptr<chunk>, tile&> operator[](global_coords pt) noexcept;
bool contains(chunk_coords c) const noexcept;
void clear();
void collect();
private:
+ void maybe_collect();
+
static constexpr std::size_t initial_capacity = 64, collect_every = 32;
static constexpr float max_load_factor = .5;
- std::size_t _last_collection = 0;
+ static constexpr auto hasher = [](chunk_coords c) -> std::size_t {
+ return int_hash((std::size_t)c.y << 16 | (std::size_t)c.x);
+ };
- void maybe_collect();
-
- std::unordered_map<chunk_coords, std::shared_ptr<chunk>> _chunks{initial_capacity};
+ std::size_t _last_collection = 0;
+ mutable std::optional<std::tuple<std::shared_ptr<chunk>, chunk_coords>> _last_chunk;
+ std::unordered_map<chunk_coords, std::shared_ptr<chunk>, decltype(hasher)> _chunks{initial_capacity, hasher};
};
} // namespace floormat