3#include <tess/core/shape.h>
12enum class ChunkState : std::uint8_t {
16static_assert(
sizeof(ChunkState) ==
sizeof(std::uint8_t));
27 ChunkState state = ChunkState::ResidentSleeping;
28 std::uint32_t version = 0;
29 std::uint32_t topology_version = 0;
30 std::uint32_t active_count = 0;
31 std::uint32_t entity_count = 0;
42 std::uint32_t flags = 0;
44 std::uint32_t version = 0;
49[[nodiscard]]
constexpr std::uint32_t popcount(std::uint32_t flags)
noexcept {
52 return static_cast<std::uint32_t
>(std::popcount(flags));
58[[nodiscard]]
constexpr std::int64_t box_axis_end(
59 std::int64_t origin, std::uint64_t extent)
noexcept {
60 constexpr auto max = std::numeric_limits<std::int64_t>::max();
61 if (extent >
static_cast<std::uint64_t
>(max)) {
64 const auto delta =
static_cast<std::int64_t
>(extent);
65 return origin > max - delta ? max : origin + delta;
68[[nodiscard]]
constexpr std::int64_t box_min(std::int64_t lhs,
69 std::int64_t rhs)
noexcept {
70 return lhs < rhs ? lhs : rhs;
73[[nodiscard]]
constexpr std::int64_t box_max(std::int64_t lhs,
74 std::int64_t rhs)
noexcept {
75 return lhs < rhs ? rhs : lhs;
78[[nodiscard]]
constexpr Box3 union_box(Box3 lhs, Box3 rhs)
noexcept {
79 const auto min_x = box_min(lhs.origin.x, rhs.origin.x);
80 const auto min_y = box_min(lhs.origin.y, rhs.origin.y);
81 const auto min_z = box_min(lhs.origin.z, rhs.origin.z);
82 const auto max_x = box_max(box_axis_end(lhs.origin.x, lhs.extent.x),
83 box_axis_end(rhs.origin.x, rhs.extent.x));
84 const auto max_y = box_max(box_axis_end(lhs.origin.y, lhs.extent.y),
85 box_axis_end(rhs.origin.y, rhs.extent.y));
86 const auto max_z = box_max(box_axis_end(lhs.origin.z, lhs.extent.z),
87 box_axis_end(rhs.origin.z, rhs.extent.z));
89 Coord3{min_x, min_y, min_z},
93 abs_delta(max_x, min_x),
94 abs_delta(max_y, min_y),
95 abs_delta(max_z, min_z),
105inline void meta_mark_dirty(std::uint32_t& dirty_flags, Box3& dirty_bounds,
106 ChunkMeta& meta, std::uint32_t flags,
107 Box3 bounds)
noexcept {
111 if (dirty_flags == 0) {
112 dirty_bounds = bounds;
114 dirty_bounds = union_box(dirty_bounds, bounds);
116 dirty_flags |= flags;
120inline void meta_clear_dirty(std::uint32_t& dirty_flags, Box3& dirty_bounds,
121 std::uint32_t flags)
noexcept {
125 dirty_flags &= ~flags;
126 if (dirty_flags == 0) {
131[[nodiscard]]
inline DirtyObservation meta_observe_dirty(
132 std::uint32_t dirty_flags, Box3 dirty_bounds,
const ChunkMeta& meta,
133 std::uint32_t flags)
noexcept {
134 return DirtyObservation{
141inline bool meta_clear_dirty_observed(std::uint32_t& dirty_flags,
142 Box3& dirty_bounds,
const ChunkMeta& meta,
143 DirtyObservation observed)
noexcept {
144 if (meta.version != observed.version) {
147 meta_clear_dirty(dirty_flags, dirty_bounds, observed.flags);
151inline void meta_mark_active(std::uint32_t& active_flags, ChunkMeta& meta,
152 std::uint32_t flags)
noexcept {
156 const auto before = active_flags;
157 active_flags |= flags;
158 meta.active_count = popcount(active_flags);
159 if (before == 0 && active_flags != 0) {
160 meta.state = ChunkState::ResidentActive;
164inline void meta_clear_active(std::uint32_t& active_flags, ChunkMeta& meta,
165 std::uint32_t flags)
noexcept {
169 active_flags &= ~flags;
170 meta.active_count = popcount(active_flags);
171 if (active_flags == 0) {
172 meta.state = ChunkState::ResidentSleeping;
Definition chunk_meta.h:41