1
1
#include " chunk.hpp"
2
2
#include " ground-atlas.hpp"
3
3
#include " object.hpp"
4
+ #include " world.hpp"
4
5
#include " src/RTree-search.hpp"
5
6
#include " rect-intersects.hpp"
7
+ #include " hole.hpp"
6
8
#include " src/chunk-scenery.hpp"
7
9
#include " src/tile-bbox.hpp"
8
10
#include " src/hole.hpp"
@@ -32,13 +34,6 @@ constexpr object_id make_id(collision_type type, pass_mode p, object_id id)
32
34
return std::bit_cast<object_id>(make_id_ (type, p, id));
33
35
}
34
36
35
- struct Data
36
- {
37
- object_id id;
38
- Vector2 min, max;
39
- };
40
-
41
- #if 0
42
37
template <bool IsNeighbor>
43
38
void add_holes_from (chunk::RTree& rtree, chunk& c, Vector2b chunk_offset)
44
39
{
@@ -65,35 +60,55 @@ void add_holes_from(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset)
65
60
}
66
61
}
67
62
68
- void filter_through_holes(chunk::RTree& rtree, Data bbox, unsigned stack)
63
+ #if 0
64
+ void filter_through_holes(chunk::RTree& rtree, object_id id, Vector2 min, Vector2 max, unsigned stack = 0)
69
65
{
70
- using Rect = typename chunk::RTree::Rect;
71
- Vector2 hmin, hmax ;
66
+ start:
67
+ CutResult<float>::rect hole ;
72
68
bool ret = true;
73
- rtree.Search(bbox. min.data(), bbox. max.data(), [&](uint64_t data, const Rect& r) {
69
+ rtree.Search(min.data(), max.data(), [&](uint64_t data, const chunk::RTree:: Rect& r) {
74
70
[[maybe_unused]] auto x = std::bit_cast<collision_data>(data);
75
71
if (x.pass == (uint64_t)pass_mode::pass && x.tag == (uint64_t)collision_type::none)
76
72
{
77
- hmin = Vector2(r.m_min[0], r.m_min[1]);
78
- hmax = Vector2(r.m_max[0], r.m_max[1]);
79
- return ret = false;
73
+ CutResult<float>::rect holeʹ {
74
+ .min = { r.m_min[0], r.m_min[1] },
75
+ .max = { r.m_max[0], r.m_max[1] },
76
+ };
77
+ if (rect_intersects(holeʹ.min, holeʹ.max, min, max))
78
+ {
79
+ hole = holeʹ;
80
+ return ret = false;
81
+ }
80
82
}
81
83
return true;
82
84
});
83
85
84
86
if (ret) [[likely]]
85
- rtree.Insert(bbox. min.data(), bbox. max.data(), bbox. id);
87
+ rtree.Insert(min.data(), max.data(), id);
86
88
else
87
89
{
88
- //auto res = cut_rectangle_result<float>::cut();
89
- //for (auto i = 0uz; i < )
90
- fm_assert(++stack <= 4096);
91
- }
90
+ auto res = CutResult<float>::cut(min, max, hole.min, hole.max);
91
+ if (!res.found)
92
+ {
93
+ rtree.Insert(min.data(), max.data(), id);
94
+ }
95
+ else if (res.size == 1)
96
+ {
97
+ min = res.array[0].min;
98
+ max = res.array[0].max;
99
+ goto start;
100
+ }
101
+ else
102
+ {
103
+ fm_assert(stack <= 1024);
104
+ for (auto i = 0uz; i < res.size; i++)
105
+ filter_through_holes(rtree, id, res.array[i].min, res.array[i].max, stack+1);
106
+ }}
92
107
}
93
108
#else
94
- void filter_through_holes (chunk::RTree& rtree, Data bbox, unsigned )
109
+ void filter_through_holes (chunk::RTree& rtree, object_id id, Vector2 min, Vector2 max, unsigned = 0 )
95
110
{
96
- rtree.Insert (bbox. min .data (), bbox. max .data (), bbox. id );
111
+ rtree.Insert (min.data (), max.data (), id);
97
112
}
98
113
#endif
99
114
@@ -109,13 +124,21 @@ void chunk::ensure_passability() noexcept
109
124
110
125
_rtree->RemoveAll ();
111
126
127
+ {
128
+ add_holes_from<false >(*_rtree, *this , {});
129
+ const auto nbs = _world->neighbors (_coord);
130
+ for (auto i = 0u ; i < 8 ; i++)
131
+ if (nbs[i])
132
+ add_holes_from<true >(*_rtree, *nbs[i], world::neighbor_offsets[i]);
133
+ }
134
+
112
135
for (auto i = 0uz; i < TILE_COUNT; i++)
113
136
{
114
137
if (const auto * atlas = ground_atlas_at (i))
115
138
{
116
139
auto [min, max] = whole_tile (i);
117
140
auto id = make_id (collision_type::geometry, atlas->pass_mode (), i+1 );
118
- filter_through_holes (*_rtree, { id, min, max}, 0 );
141
+ filter_through_holes (*_rtree, id, min, max);
119
142
}
120
143
}
121
144
for (auto i = 0uz; i < TILE_COUNT; i++)
@@ -125,25 +148,25 @@ void chunk::ensure_passability() noexcept
125
148
{
126
149
auto [min, max] = wall_north (i, (float )atlas->info ().depth );
127
150
auto id = make_id (collision_type::geometry, atlas->info ().passability , TILE_COUNT+i+1 );
128
- filter_through_holes (*_rtree, { id, min, max}, 0 );
151
+ filter_through_holes (*_rtree, id, min, max);
129
152
130
153
if (tile.wall_west_atlas ())
131
154
{
132
155
auto [min, max] = wall_pillar (i, (float )atlas->info ().depth );
133
- filter_through_holes (*_rtree, { id, min, max}, 0 );
156
+ filter_through_holes (*_rtree, id, min, max);
134
157
}
135
158
}
136
159
if (const auto * atlas = tile.wall_west_atlas ().get ())
137
160
{
138
161
auto [min, max] = wall_west (i, (float )atlas->info ().depth );
139
162
auto id = make_id (collision_type::geometry, atlas->info ().passability , TILE_COUNT*2 +i+1 );
140
- filter_through_holes (*_rtree, { id, min, max}, 0 );
163
+ filter_through_holes (*_rtree, id, min, max);
141
164
}
142
165
}
143
166
for (const std::shared_ptr<object>& s : objects ())
144
167
if (!s->is_dynamic ())
145
168
if (bbox box; _bbox_for_scenery (*s, box))
146
- filter_through_holes (*_rtree, { std::bit_cast<object_id>(box.data ), Vector2 (box.start ), Vector2 (box.end )}, 0 );
169
+ filter_through_holes (*_rtree, std::bit_cast<object_id>(box.data ), Vector2 (box.start ), Vector2 (box.end ));
147
170
148
171
// for (auto [id, min, max] : vec) _rtree->Insert(min.data(), max.data(), id);
149
172
// arrayResize(vec, 0); arrayResize(vec2, 0); // done with holes
0 commit comments