19 std::array<uint64_t, k_brick_dim> slices {};
22 constexpr auto operator[](uint32_t z)
noexcept -> uint64_t& {
23 assert(z < k_brick_dim);
28 constexpr auto operator[](uint32_t z)
const noexcept ->
const uint64_t& {
29 assert(z < k_brick_dim);
34 constexpr auto operator==(
const BrickOccupancy&)
const noexcept ->
bool =
default;
39inline constexpr BrickOccupancy k_full_brick {
40 {~0ull, ~0ull, ~0ull, ~0ull, ~0ull, ~0ull, ~0ull, ~0ull}
43inline constexpr uint64_t k_column_x_min = 0x0101010101010101ull;
45inline constexpr uint64_t k_column_x_max = 0x8080808080808080ull;
47inline constexpr uint64_t k_row_y_min = 0x00000000000000FFull;
49inline constexpr uint64_t k_row_y_max = 0xFF00000000000000ull;
52constexpr auto localIndex(
const uint32_t x,
const uint32_t y,
const uint32_t z)
noexcept -> uint32_t {
53 assert(x < k_brick_dim && y < k_brick_dim && z < k_brick_dim);
54 return x + (y * k_brick_dim) + (z * k_brick_dim * k_brick_dim);
63 constexpr auto operator==(
const BrickCoord&)
const noexcept ->
bool =
default;
67constexpr auto localFromIndex(uint32_t index)
noexcept ->
BrickCoord {
68 assert(index < k_brick_voxel_count);
69 return BrickCoord {index & 7u, (index >> 3u) & 7u, index >> 6u};
73constexpr auto sliceBit(uint32_t x, uint32_t y)
noexcept -> uint32_t {
74 assert(x < k_brick_dim && y < k_brick_dim);
75 return (y * k_brick_dim) + x;
79constexpr auto isSolid(
const BrickOccupancy& brick, uint32_t x, uint32_t y, uint32_t z)
noexcept ->
bool {
80 assert(z < k_brick_dim);
81 return ((brick[z] >> sliceBit(x, y)) & 1ull) != 0ull;
85constexpr auto isSolid(
const BrickOccupancy& brick, uint32_t local_index)
noexcept ->
bool {
86 const BrickCoord c = localFromIndex(local_index);
87 return isSolid(brick, c.x, c.y, c.z);
90constexpr void setSolid(
BrickOccupancy& brick, uint32_t x, uint32_t y, uint32_t z,
bool solid)
noexcept {
91 assert(z < k_brick_dim);
92 const uint64_t bit = 1ull << sliceBit(x, y);
100constexpr void setSolid(
BrickOccupancy& brick, uint32_t local_index,
bool solid)
noexcept {
101 const BrickCoord c = localFromIndex(local_index);
102 setSolid(brick, c.x, c.y, c.z, solid);
106constexpr auto isEmpty(
const BrickOccupancy& brick)
noexcept ->
bool {
107 for (uint64_t slice : brick.slices) {
116constexpr auto isFull(
const BrickOccupancy& brick)
noexcept ->
bool {
117 for (uint64_t slice : brick.slices) {
118 if (slice != ~0ull) {
126constexpr auto popCount(
const BrickOccupancy& brick)
noexcept -> uint32_t {
128 for (uint64_t slice : brick.slices) {
129 total +=
static_cast<uint32_t
>(std::popcount(slice));
143 uint32_t z_min = k_brick_dim;
145 for (uint32_t z = 0; z < k_brick_dim; ++z) {
146 if (brick[z] != 0ull) {
148 z_min = z < z_min ? z : z_min;
153 uint32_t columns = 0;
154 uint32_t y_min = k_brick_dim;
156 for (uint32_t y = 0; y < k_brick_dim; ++y) {
157 const auto row =
static_cast<uint32_t
>((merged >> (y * k_brick_dim)) & 0xFFull);
160 y_min = y < y_min ? y : y_min;
166 .min = {
static_cast<uint32_t
>(std::countr_zero(columns)), y_min, z_min},
167 .max = {31u -
static_cast<uint32_t
>(std::countl_zero(columns)), y_max, z_max},
172constexpr auto operator&(
const BrickOccupancy& a,
const BrickOccupancy& b)
noexcept -> BrickOccupancy {
173 BrickOccupancy out {};
174 for (uint32_t z = 0; z < k_brick_dim; ++z) {
175 out[z] = a[z] & b[z];
183 for (uint32_t z = 0; z < k_brick_dim; ++z) {
184 out[z] = a[z] | b[z];
192 for (uint32_t z = 0; z < k_brick_dim; ++z) {
201 for (uint32_t z = 0; z < k_brick_dim; ++z) {
202 out[z] = (brick[z] & ~k_column_x_max) << 1;
203 if (adjacent !=
nullptr) {
204 out[z] |= ((*adjacent)[z] >> 7) & k_column_x_min;
213 for (uint32_t z = 0; z < k_brick_dim; ++z) {
214 out[z] = (brick[z] & ~k_column_x_min) >> 1;
215 if (adjacent !=
nullptr) {
216 out[z] |= ((*adjacent)[z] << 7) & k_column_x_max;
225 for (uint32_t z = 0; z < k_brick_dim; ++z) {
226 out[z] = brick[z] << k_brick_dim;
227 if (adjacent !=
nullptr) {
228 out[z] |= (*adjacent)[z] >> 56;
237 for (uint32_t z = 0; z < k_brick_dim; ++z) {
238 out[z] = brick[z] >> k_brick_dim;
239 if (adjacent !=
nullptr) {
240 out[z] |= (*adjacent)[z] << 56;
249 out[0] = adjacent !=
nullptr ? (*adjacent)[k_brick_dim - 1] : 0ull;
250 for (uint32_t z = 1; z < k_brick_dim; ++z) {
251 out[z] = brick[z - 1];
259 for (uint32_t z = 0; z + 1 < k_brick_dim; ++z) {
260 out[z] = brick[z + 1];
262 out[k_brick_dim - 1] = adjacent !=
nullptr ? (*adjacent)[0] : 0ull;
277 return brick & neighboursNegX(brick, neighbours.neg_x) & neighboursPosX(brick, neighbours.pos_x) &
278 neighboursNegY(brick, neighbours.neg_y) & neighboursPosY(brick, neighbours.pos_y) &
279 neighboursNegZ(brick, neighbours.neg_z) & neighboursPosZ(brick, neighbours.pos_z);
284 return brick & ~interior(brick, neighbours);
289 return brick | neighboursNegX(brick) | neighboursPosX(brick) | neighboursNegY(brick) | neighboursPosY(brick) |
290 neighboursNegZ(brick) | neighboursPosZ(brick);
297 for (uint32_t z = 0; z < k_brick_dim; ++z) {
298 for (uint32_t y = 0; y < k_brick_dim; ++y) {
299 if (((brick[z] >> sliceBit(0, y)) & 1ull) != 0ull) {
300 out |= 1ull << ((z * k_brick_dim) + y);
311 for (uint32_t z = 0; z < k_brick_dim; ++z) {
312 for (uint32_t y = 0; y < k_brick_dim; ++y) {
313 if (((brick[z] >> sliceBit(k_brick_dim - 1, y)) & 1ull) != 0ull) {
314 out |= 1ull << ((z * k_brick_dim) + y);
325 for (uint32_t z = 0; z < k_brick_dim; ++z) {
326 out |= (brick[z] & k_row_y_min) << (z * k_brick_dim);
335 for (uint32_t z = 0; z < k_brick_dim; ++z) {
336 out |= (brick[z] >> 56) << (z * k_brick_dim);
350 return brick[k_brick_dim - 1];
362 constexpr auto operator==(
const BrickFaces&)
const noexcept ->
bool =
default;
371constexpr auto facesConnect(uint64_t face_a, uint64_t face_b)
noexcept ->
bool {
372 return (face_a & face_b) != 0ull;
constexpr auto faceNegX(const BrickOccupancy &brick) noexcept -> uint64_t
x == 0 plane with bit z * 8 + y
Definition brick.hpp:295
constexpr auto occupiedExtent(const BrickOccupancy &brick) noexcept -> BrickExtent
Brick must not be empty.
Definition brick.hpp:141
constexpr auto facePosX(const BrickOccupancy &brick) noexcept -> uint64_t
x == 7 plane with bit z * 8 + y
Definition brick.hpp:309
constexpr auto facePosZ(const BrickOccupancy &brick) noexcept -> uint64_t
z == 7 plane with bit y * 8 + x
Definition brick.hpp:349
constexpr auto faceNegY(const BrickOccupancy &brick) noexcept -> uint64_t
y == 0 plane with bit z * 8 + x
Definition brick.hpp:323
constexpr auto facePosY(const BrickOccupancy &brick) noexcept -> uint64_t
y == 7 plane with bit z * 8 + x
Definition brick.hpp:333
constexpr auto faceNegZ(const BrickOccupancy &brick) noexcept -> uint64_t
z == 0 plane with bit y * 8 + x
Definition brick.hpp:343
One 64-bit word per z-slice with bit y * 8 + x.
Definition brick.hpp:18