Seperated Planular 2d logic from threedee logic in mesher

Very interesting commit, creates some seperation between chunk logic and
planular logic. impliments some key needed code to allow all this to
work with projecting the planular into chunk coords and all.

No regressions so far, hopefully we keep going on a roll because
everything working is really really nice.
This commit is contained in:
Rebekah 2024-02-22 13:16:18 -05:00
parent fa73fb3ec3
commit f1d876e6f4
Signed by: oneechanhax
GPG Key ID: 183EB7902964DAE5

View File

@ -235,7 +235,9 @@ public:
using BlockType = uint8_t;
// Using a single digit to locate the exact voxel's byte in the chunk, for very fast use.
using ChunkDataType = std::array<uint8_t, _chunk_array_size>;
using ChunkVecType = geo::internal::BVec2<uint8_t>;
using PlaneVecType = geo::internal::BVec2<uint8_t>; // flat plane of blocks
// using ChunkVecType = geo::internal::BVec2<uint8_t>;
using ChunkVecType = Vector3i;
ChunkDataType raw_chunk_data = {
ENUM_BLOCK_TYPE::E_BLOCK_STONE,
ENUM_BLOCK_TYPE::E_BLOCK_STONE,
@ -494,14 +496,7 @@ public:
ENUM_BLOCK_TYPE::E_BLOCK_AIR,
ENUM_BLOCK_TYPE::E_BLOCK_STONE,
};
static ChunkVecType ExtractVec(std::size_t blockidx) {
auto coord = cChunkDef::IndexToCoordinate(blockidx);
ChunkVecType ret_pos;
ret_pos.x = coord.x;
ret_pos.y = coord.z;
return ret_pos;
}
static std::size_t GetVoxelFromPosInChunk(geo::internal::BVec2<uint8_t> in_pos) {
static std::size_t MakeIndexFromPlanularPosition(PlaneVecType in_pos) {
return cChunkDef::MakeIndex(in_pos.x, 0, in_pos.y);
}
BlockType GetVoxelType(std::size_t v) const {
@ -512,11 +507,12 @@ public:
ChunkVecType cur;
public:
using VecMaskType = glm::bvec2;
const VecMaskType mask, reverse_mask; // stick it in reverse spongebob!
constexpr AxisIterator(const ChunkVecType& src, std::pair<glm::bvec2, glm::bvec2> mask)
using VecMaskType = glm::bvec3;
const VecMaskType mask = { false, false, false }, reverse_mask = { false, false, false }; // stick it in reverse spongebob!
using FullMaskType = std::pair<VecMaskType, VecMaskType>;
constexpr AxisIterator(const ChunkVecType& src, FullMaskType mask)
: AxisIterator(src, mask.first, mask.second) { }
constexpr AxisIterator(const ChunkVecType& src, glm::bvec2 mask, glm::bvec2 reverse_mask = { false, false })
constexpr AxisIterator(const ChunkVecType& src, VecMaskType mask, VecMaskType reverse_mask = { false, false, false })
: cur(src)
, mask(mask)
, reverse_mask(reverse_mask) { }
@ -538,30 +534,34 @@ public:
return !(*this == other);
}
static constexpr AxisIterator end() {
AxisIterator ret({}, glm::bvec2 {});
AxisIterator ret({}, glm::bvec3 {});
ret.end_flagged = true;
return ret;
}
ChunkVecType GetPosToAdd() const {
ChunkVecType pos_to_add = { 0, 0 };
ChunkVecType pos_to_add = { 0, 0, 0 };
if (mask.x)
pos_to_add.x = 1;
if (mask.y)
pos_to_add.y = 1;
if (mask.z)
pos_to_add.z = 1;
if (reverse_mask.x && pos_to_add.x)
pos_to_add.x = -pos_to_add.x;
if (reverse_mask.y && pos_to_add.y)
pos_to_add.y = -pos_to_add.y;
if (reverse_mask.z && pos_to_add.z)
pos_to_add.z = -pos_to_add.z;
return pos_to_add;
}
static constexpr auto CreateCardinalDirectionalMask(const CardinalDirections dir) {
VecMaskType mask = { false, false }, reverse_mask = { false, false };
switch (dir) { // THIS ONLY WORKS FOR THE CURRENT VEC ORDERING + its stuck on only xz looking top down...
VecMaskType mask = { false, false, false }, reverse_mask = { false, false, false };
switch (dir) {
case CardinalDirections::kNorth:
reverse_mask.y = true;
reverse_mask.z = true;
[[fallthrough]];
case CardinalDirections::kSouth:
mask.y = true;
mask.z = true;
break;
case CardinalDirections::kWest:
reverse_mask.x = true;
@ -569,6 +569,12 @@ public:
case CardinalDirections::kEast:
mask.x = true;
break;
case CardinalDirections::kDown:
reverse_mask.y = true;
[[fallthrough]];
case CardinalDirections::kUp:
mask.y = true;
break;
default:
throw std::logic_error("Trying to access a cardinal Direction that does not work!");
}
@ -612,6 +618,15 @@ public:
return axis_directions;
}
};
static constexpr ChunkVecType ProjectPlanularToChunkVec(PlaneVecType plane_coords, const CardinalDirections facing_chunk_from_dir, std::size_t depth) {
ChunkVecType ret;
switch (facing_chunk_from_dir) {
case CardinalDirections::kUp:
return ChunkVecType(plane_coords.x, depth, plane_coords.y);
default:
throw std::logic_error("Trying to access a cardinal Direction that does not work!");
};
}
bool IsEmpty() const {
for (auto i : this->raw_chunk_data)
if (i != ENUM_BLOCK_TYPE::E_BLOCK_AIR)
@ -651,6 +666,8 @@ public:
const auto south_dir_mask = blockface_plane_geo_axis_info.first;
const auto east_dir_mask = blockface_plane_geo_axis_info.second;
const auto plane_facing_us_size = AxisIterator::GetPlaneSliceFacingFromDirectionSize(facing_direction_from);
std::vector<ChunkMeshedQuad> finished_quads;
if (gfx_mesher_debuglog)
std::cout << "Start Meshing: ";
@ -661,19 +678,16 @@ public:
if (gfx_mesher_debuglog)
std::cout << "Plain" << std::endl;
auto south_axis_crawl = AxisIterator({ 0, 0 }, south_dir_mask);
assert(south_axis_crawl.GetNumAxisDirections() == 1);
for (; south_axis_crawl != AxisIterator::end(); south_axis_crawl++) {
auto east_axis_crawl = AxisIterator(*south_axis_crawl, east_dir_mask);
assert(east_axis_crawl.GetNumAxisDirections() == 1);
for (; east_axis_crawl != AxisIterator::end(); east_axis_crawl++) {
const auto block_coords = *east_axis_crawl;
const std::size_t blockidx = GetVoxelFromPosInChunk(block_coords);
for (std::size_t south = 0; south < plane_facing_us_size.first; south++) {
for (std::size_t east = 0; east < plane_facing_us_size.second; east++) {
const auto planular_block_coords = PlaneVecType { south, east };
const auto block_coords = ProjectPlanularToChunkVec(planular_block_coords, facing_direction_from, depth);
const std::size_t blockidx = cChunkDef::MakeIndex(block_coords);
const auto type = this->GetVoxelType(blockidx);
if (type == ENUM_BLOCK_TYPE::E_BLOCK_AIR)
continue;
ChunkMeshedQuad new_face;
const auto start = geo::Vec2(block_coords.x * box_size, block_coords.y * box_size);
const auto start = geo::Vec2(planular_block_coords.x * box_size, planular_block_coords.y * box_size);
// auto end = /*start +*/ geo::Vec2(box_size, box_size);
const auto size = /*start +*/ geo::Vec2(box_size, box_size);
new_face.quad = geo::Box<geo::Vec2>(start, size);
@ -695,16 +709,17 @@ public:
if (gfx_mesher_debuglog)
std::cout << "Greedy" << std::endl;
// The Greedy mesher checksum utils use PLANULAR COORDS only, please convert between the two.
std::vector<bool> chunk_finished_checksum(AxisIterator::GetPlaneSliceFacingFromDirectionBlockCount(facing_direction_from), false); // i believe its faster(vs an array) when checking the entire thing for boolean
const auto IsBlockMarkedOff = [&](std::size_t blockidx) -> bool { return chunk_finished_checksum[blockidx]; };
using UnmeshedOpenSpacePosType = std::optional<std::pair<std::size_t, ChunkVecType>>;
using UnmeshedOpenSpacePosType = std::optional<std::pair<std::size_t, PlaneVecType>>; // WITHIN PLANULAR SPACE WARNING!!!
const auto FindOpenSpace = [&]() -> UnmeshedOpenSpacePosType {
for (std::size_t x = 0; x < cChunkDef::Width; x++) {
for (std::size_t z = 0; z < cChunkDef::Width; z++) {
auto blockidx = this->GetVoxelFromPosInChunk({ x, z });
auto block_coords = ExtractVec(blockidx); // lmao
if (!IsBlockMarkedOff(blockidx))
return std::make_pair(blockidx, block_coords);
for (std::size_t south = 0; south < plane_facing_us_size.first; south++) {
for (std::size_t east = 0; east < plane_facing_us_size.second; east++) {
const PlaneVecType planular_block_coords = { south, east };
const auto planular_blockidx = MakeIndexFromPlanularPosition(planular_block_coords);
if (!IsBlockMarkedOff(planular_blockidx))
return std::make_pair(planular_blockidx, planular_block_coords);
}
}
return UnmeshedOpenSpacePosType();
@ -721,21 +736,25 @@ public:
if (!unmeshed_face.has_value())
throw std::logic_error("Greedy ChunkMesher checksum thinks there is a unmeshed chunk but unable to find it!");
const auto seed_blockpos = unmeshed_face.value();
const auto seed_blockidx = seed_blockpos.first;
const auto seed_planular_blockpos = unmeshed_face.value();
// const auto seed_planular_blockidx = seed_planular_blockpos.first;
const auto seed_planular_block_coords = seed_planular_blockpos.second;
// if (gfx_mesher_debuglog) // TOO MUCH LOGS! enable it if ur debugging rly hard.
// std::cout << "Greedy found Seed block at planular coords: {" << (int)seed_planular_block_coords.x << ", " << (int)seed_planular_block_coords.y << "}" << std::endl;
const auto seed_block_coords = ProjectPlanularToChunkVec(seed_planular_block_coords, facing_direction_from, depth);
const auto seed_blockidx = cChunkDef::MakeIndex(seed_block_coords);
const auto seed_block_type = this->GetVoxelType(seed_blockidx);
if (seed_block_type == ENUM_BLOCK_TYPE::E_BLOCK_AIR) {
chunk_finished_checksum[seed_blockidx] = true;
continue;
}
if (gfx_mesher_debuglog) {
const auto seed_block_coords = seed_blockpos.second;
std::cout << "Greedy found Seed block \"" << (int)seed_block_type << "\": {" << (int)seed_block_coords.x << ", " << (int)seed_block_coords.y << "}" << std::endl;
}
if (gfx_mesher_debuglog)
std::cout << " Seed Block Real Coords: \"" << (int)seed_block_type << "\": {" << (int)seed_block_coords.x << ", " << (int)seed_block_coords.y << ", " << (int)seed_block_coords.z << "}" << std::endl;
PlaneVecType block_quad_size = { 1, 1 }; // in coords
ChunkVecType block_quad_size = { 1, 1 }; // in coords
const auto seed_block_coords = seed_blockpos.second;
// Need a better "search line down" func... instead of one block we need to check multiple and return how many are the same.
auto SearchLineSouthForSameTypes = [&](ChunkVecType src_line, std::uint8_t max_size = cChunkDef::Width) -> std::uint8_t {
std::size_t alike_counter = 0;
@ -743,7 +762,7 @@ public:
auto south_axis_crawl = AxisIterator(src_line, south_dir_mask);
assert(south_axis_crawl.GetNumAxisDirections() == 1);
for (; south_axis_crawl != AxisIterator::end(); south_axis_crawl++) {
const std::size_t south_blockidx_to_check = GetVoxelFromPosInChunk(*south_axis_crawl);
const std::size_t south_blockidx_to_check = cChunkDef::MakeIndex(*south_axis_crawl);
auto south_block_type = this->GetVoxelType(south_blockidx_to_check);
if (south_block_type != seed_block_type)
break;
@ -773,7 +792,7 @@ public:
east_axis_crawl++; // starting one ahead
std::size_t alike_counter = 1;
for (; east_axis_crawl != AxisIterator::end(); east_axis_crawl++) {
const std::size_t east_blockidx_to_check = GetVoxelFromPosInChunk(*east_axis_crawl);
const std::size_t east_blockidx_to_check = cChunkDef::MakeIndex(*east_axis_crawl);
const auto east_block_type = this->GetVoxelType(east_blockidx_to_check);
if (east_block_type != seed_block_type)
break;
@ -797,7 +816,7 @@ public:
}
ChunkMeshedQuad new_face;
const auto quad_start = geo::Vec2(seed_block_coords.x * box_size, seed_block_coords.y * box_size);
const auto quad_start = geo::Vec2(seed_planular_block_coords.x * box_size, seed_planular_block_coords.y * box_size);
const auto quad_size = geo::Vec2(block_quad_size.x * box_size, block_quad_size.y * box_size);
new_face.quad = geo::Box<geo::Vec2>(quad_start, quad_size);
@ -806,20 +825,21 @@ public:
std::cout << " *Added quad! : {" << quad_start.x << ", " << quad_start.y << "} with size {" << quad_size.x << ", " << quad_size.y << "}" << std::endl;
finished_quads.push_back(new_face);
const auto MarkAreaFinished = [&](ChunkVecType origin, ChunkVecType size) {
assert(size.x && size.y);
for (std::size_t x = 0; x < size.x; x++) {
for (std::size_t z = 0; z < size.y; z++) {
auto block_coords_to_clear = origin + ChunkVecType(x, z);
const auto MarkAreaFinished = [&](PlaneVecType origin_block, PlaneVecType size_in_blocks) {
assert(size_in_blocks.x && size_in_blocks.y);
for (std::size_t x = 0; x < size_in_blocks.x; x++) { // in faceing_planular space
for (std::size_t z = 0; z < size_in_blocks.y; z++) {
auto block_coords_to_clear = origin_block + PlaneVecType(x, z);
if (gfx_mesher_debuglog)
std::cout << " ------Marking Block Finished: {" << (int)block_coords_to_clear.x << ", " << (int)block_coords_to_clear.y << "}" << std::endl;
auto blockidx = this->GetVoxelFromPosInChunk(block_coords_to_clear);
auto blockidx = MakeIndexFromPlanularPosition(block_coords_to_clear);
assert(blockidx < chunk_finished_checksum.size());
assert(!IsBlockMarkedOff(blockidx));
chunk_finished_checksum[blockidx] = true;
}
}
};
MarkAreaFinished(seed_block_coords, block_quad_size);
MarkAreaFinished(seed_planular_block_coords, block_quad_size);
// mark it off of the chunk_finished_checksum by setting the chunk_finished_checksum[i] to 1
}
if (gfx_mesher_debuglog)
@ -837,10 +857,13 @@ public:
return finished_quads;
}
// static bool IsPosValidWithinPlane(ChunkVecType block_coords) {
static bool IsPosValidWithinChunk(ChunkVecType block_coords) {
if (!cChunkDef::IsValidWidth(block_coords.x))
return false;
if (!cChunkDef::IsValidWidth(block_coords.y))
if (!cChunkDef::IsValidHeight(block_coords))
return false;
if (!cChunkDef::IsValidWidth(block_coords.z))
return false;
return true;
}