Removal of client LocalVoxel to use cChunkDef

Now uses more server code, more of the indexing was corrected to work
with this somewhat.
The variables for positions, cube, voxels were all renamed to be more
clear with their expressions.
The stuff in the greedy mesher to do with AxisIterator was improved to
be more iterator like in the use, and the variables surrounding them
such as the iterator use themselves and the south_ and east_ names were
cleared up from "down" and "side".

Overral this was a big refactor and mostly a rename fest, looks nice so
far.

oh yea, debug if()s to help cut down on chat spam.
This commit is contained in:
Rebekah 2024-02-15 07:31:02 -05:00
parent 3a666b2480
commit 85c6edf829
Signed by: oneechanhax
GPG Key ID: 183EB7902964DAE5

View File

@ -496,30 +496,17 @@ public:
ret_pos.y = coord.z; ret_pos.y = coord.z;
return ret_pos; return ret_pos;
} }
class LocalVoxel { static std::size_t GetVoxelFromPosInChunk(geo::internal::BVec2<uint8_t> in_pos) {
public: return cChunkDef::MakeIndex(in_pos.x, 0, in_pos.y);
std::size_t pos; // yes a single integer, x y and z can all exist due to the way chunking keeps it localized and x + (z * 64) means the values co-exist.
ChunkVecType ExtractVec() const {
return FalseChunk::ExtractVec(this->pos);
}
// tmp, TODO replace/add with chunk pointer or chunk x and y... both??? oof if so
// need good way to keep the handle associated.
// Local HANDLES AND "standard voxel"/global voxel in other words one for chunk and one inheriting with the extra details? ah genious!
};
static LocalVoxel GetVoxelFromPosInChunk(geo::internal::BVec2<uint8_t> in_pos) {
LocalVoxel ret;
ret.pos = cChunkDef::MakeIndex(in_pos.x, 0, in_pos.y);
return ret;
} }
BlockType GetVoxelType(std::size_t v) const { BlockType GetVoxelType(std::size_t v) const {
return raw_chunk_data[v]; return raw_chunk_data[v];
} }
class AxisIterator { class AxisIterator {
public:
bool end_flagged = false; bool end_flagged = false;
ChunkVecType cur; ChunkVecType cur;
public:
using VecMaskType = glm::bvec2; using VecMaskType = glm::bvec2;
const VecMaskType mask, reverse_mask; // stick it in reverse spongebob! const VecMaskType mask, reverse_mask; // stick it in reverse spongebob!
constexpr AxisIterator(const ChunkVecType& src, std::pair<glm::bvec2, glm::bvec2> mask) constexpr AxisIterator(const ChunkVecType& src, std::pair<glm::bvec2, glm::bvec2> mask)
@ -535,6 +522,7 @@ public:
this->end_flagged = true; this->end_flagged = true;
return *this; return *this;
} }
const ChunkVecType& operator*() { return this->cur; }
bool operator==(const AxisIterator& other) const { bool operator==(const AxisIterator& other) const {
if (other.end_flagged) if (other.end_flagged)
return this->end_flagged; return this->end_flagged;
@ -587,7 +575,7 @@ public:
kIntrinsicGreedy, // Using bitwise operations :O kIntrinsicGreedy, // Using bitwise operations :O
kGlobalLattice // literally Impossible to recreate, meshing everything INCLUDING air, and rendering it straight up in shader kGlobalLattice // literally Impossible to recreate, meshing everything INCLUDING air, and rendering it straight up in shader
}; };
static constexpr float box_size = 25.0f; static constexpr float box_size = 25.0f; // TODO find out where its located!!! if we can find it in server, we can apply this then try to do some simple transformations.
// glez::vertex not verbose enough for us sadly... // glez::vertex not verbose enough for us sadly...
struct ChunkMeshedQuad { struct ChunkMeshedQuad {
geo::Box<geo::Vec2> quad; geo::Box<geo::Vec2> quad;
@ -603,47 +591,53 @@ public:
glez::color::green, // sapling glez::color::green, // sapling
glez::color::black // bedrock glez::color::black // bedrock
}; };
static constexpr bool gfx_mesher_debuglog = false;
std::vector<ChunkMeshedQuad> MeshChunk(MesherComplexity cmplxity) const { std::vector<ChunkMeshedQuad> MeshChunk(MesherComplexity cmplxity) const {
std::vector<ChunkMeshedQuad> finished_quads; std::vector<ChunkMeshedQuad> finished_quads;
std::cout << "Start Meshing: "; if (gfx_mesher_debuglog)
std::cout << "Start Meshing: ";
const auto start_time = std::chrono::high_resolution_clock::now(); const auto start_time = std::chrono::high_resolution_clock::now();
switch (cmplxity) { switch (cmplxity) {
case MesherComplexity::kNieve: // I dont think this is possible in 2d for the time being... case MesherComplexity::kNieve: // I dont think this is possible in 2d for the time being...
case MesherComplexity::kPlain: { case MesherComplexity::kPlain: {
std::cout << "Plain" << std::endl; if (gfx_mesher_debuglog)
std::cout << "Plain" << std::endl;
for (uint dim_x = 0; dim_x < cChunkDef::Width; dim_x++) { for (uint dim_x = 0; dim_x < cChunkDef::Width; dim_x++) {
for (uint dim_y = 0; dim_y < cChunkDef::Width; dim_y++) { for (uint dim_z = 0; dim_z < cChunkDef::Width; dim_z++) {
LocalVoxel cube = GetVoxelFromPosInChunk({ dim_x, dim_y }); std::size_t blockidx = GetVoxelFromPosInChunk({ dim_x, dim_z });
const auto type = this->GetVoxelType(cube.pos); const auto type = this->GetVoxelType(blockidx);
if (type == ENUM_BLOCK_TYPE::E_BLOCK_AIR) if (type == ENUM_BLOCK_TYPE::E_BLOCK_AIR)
continue; continue;
ChunkMeshedQuad new_face; ChunkMeshedQuad new_face;
const auto start = geo::Vec2(dim_x * box_size, dim_y * box_size); const auto start = geo::Vec2(dim_x * box_size, dim_z * box_size);
// auto end = /*start +*/ geo::Vec2(box_size, box_size); // auto end = /*start +*/ geo::Vec2(box_size, box_size);
const auto size = /*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); new_face.quad = geo::Box<geo::Vec2>(start, size);
new_face.clr = chunk_textures[type]; new_face.clr = chunk_textures[type];
finished_quads.push_back(new_face); finished_quads.push_back(new_face);
std::cout << " *Added quad! : {" << start.x << ", " << start.y << "} with size {" << size.x << ", " << size.y << "}" << std::endl; if (gfx_mesher_debuglog)
std::cout << " *Added quad! : {" << start.x << ", " << start.y << "} with size {" << size.x << ", " << size.y << "}" << std::endl;
} }
} }
std::cout << "Plain "; if (gfx_mesher_debuglog)
std::cout << "Plain ";
break; break;
} }
/*case MesherComplexity::kNieve: { /*case MesherComplexity::kNieve: {
} */ } */
case MesherComplexity::kGreedy: { // https://www.youtube.com/watch?v=4xs66m1Of4A - Greedy Meshing Voxels Fast - Optimism in Design Handmade Seattle 2022 case MesherComplexity::kGreedy: { // https://www.youtube.com/watch?v=4xs66m1Of4A - Greedy Meshing Voxels Fast - Optimism in Design Handmade Seattle 2022
std::cout << "Greedy" << std::endl; if (gfx_mesher_debuglog)
std::cout << "Greedy" << std::endl;
std::bitset<_chunk_array_size> chunk_finished_checksum; std::bitset<_chunk_array_size> chunk_finished_checksum;
const auto IsBlockMarkedOff = [&](std::size_t vox) -> bool { return chunk_finished_checksum[vox]; }; const auto IsBlockMarkedOff = [&](std::size_t blockidx) -> bool { return chunk_finished_checksum[blockidx]; };
const auto FindOpenSpace = [&]() -> std::optional<std::size_t> { const auto FindOpenSpace = [&]() -> std::optional<std::size_t> {
for (std::size_t x = 0; x < cChunkDef::Width; x++) { for (std::size_t x = 0; x < cChunkDef::Width; x++) {
for (std::size_t y = 0; y < cChunkDef::Width; y++) { for (std::size_t z = 0; z < cChunkDef::Width; z++) {
auto vox = this->GetVoxelFromPosInChunk({ x, y }); auto blockidx = this->GetVoxelFromPosInChunk({ x, z });
if (!IsBlockMarkedOff(vox.pos)) if (!IsBlockMarkedOff(blockidx))
return vox.pos; return blockidx;
} }
} }
return std::optional<std::size_t>(); return std::optional<std::size_t>();
@ -653,32 +647,30 @@ public:
if (!unmeshed_face.has_value()) if (!unmeshed_face.has_value())
throw std::logic_error("Greedy ChunkMesher checksum thinks there is a unmeshed chunk but unable to find it!"); throw std::logic_error("Greedy ChunkMesher checksum thinks there is a unmeshed chunk but unable to find it!");
LocalVoxel cube; const auto seed_blockidx = unmeshed_face.value();
cube.pos = unmeshed_face.value(); const auto seed_block_type = this->GetVoxelType(seed_blockidx);
const auto type = this->GetVoxelType(cube.pos); if (seed_block_type == ENUM_BLOCK_TYPE::E_BLOCK_AIR) {
if (type == ENUM_BLOCK_TYPE::E_BLOCK_AIR) { chunk_finished_checksum[seed_blockidx] = true;
chunk_finished_checksum[cube.pos] = true;
continue; continue;
} }
{ if (gfx_mesher_debuglog) {
const auto ext_cube = cube.ExtractVec(); const auto seed_block_coords = ExtractVec(seed_blockidx);
std::cout << "Greedy found Seed block \"" << (int)type << "\": {" << (int)ext_cube.x << ", " << (int)ext_cube.y << "}" << std::endl; std::cout << "Greedy found Seed block \"" << (int)seed_block_type << "\": {" << (int)seed_block_coords.x << ", " << (int)seed_block_coords.y << "}" << std::endl;
} }
ChunkVecType block_quad_size = { 1, 1 }; ChunkVecType block_quad_size = { 1, 1 }; // in coords
const auto src_block_loc = cube.ExtractVec(); const auto seed_block_coords = ExtractVec(seed_blockidx);
// Need a better "search line down" func... instead of one block we need to check multiple and return how many are the same. // Need a better "search line down" func... instead of one block we need to check multiple and return how many are the same.
constexpr auto south_dir_mask = AxisIterator::CreateCardinalMask(CardinalDirections::kSouth);
auto SearchLineSouthForSameTypes = [&](ChunkVecType src_line, std::uint8_t max_size = cChunkDef::Width) -> std::uint8_t { auto SearchLineSouthForSameTypes = [&](ChunkVecType src_line, std::uint8_t max_size = cChunkDef::Width) -> std::uint8_t {
constexpr auto south_dir_mask = AxisIterator::CreateCardinalMask(CardinalDirections::kSouth);
std::size_t alike_counter = 0; std::size_t alike_counter = 0;
const auto end = AxisIterator::end(); for (auto south_axis_crawl = AxisIterator(src_line, south_dir_mask); south_axis_crawl != AxisIterator::end(); south_axis_crawl++) {
for (auto axis_crawl = AxisIterator(src_line, south_dir_mask); axis_crawl != end; axis_crawl++) { const std::size_t south_blockidx_to_check = GetVoxelFromPosInChunk(*south_axis_crawl);
const LocalVoxel block_to_check = GetVoxelFromPosInChunk(axis_crawl.cur); auto south_block_type = this->GetVoxelType(south_blockidx_to_check);
auto below_block_type = this->GetVoxelType(block_to_check.pos); if (south_block_type != seed_block_type)
if (below_block_type != type)
break; break;
if (IsBlockMarkedOff(block_to_check.pos)) if (IsBlockMarkedOff(south_blockidx_to_check))
break; break;
alike_counter++; alike_counter++;
if (alike_counter >= max_size) if (alike_counter >= max_size)
@ -686,68 +678,74 @@ public:
} }
return alike_counter; return alike_counter;
}; };
const auto same_blocks_south_count = SearchLineSouthForSameTypes(src_block_loc); const auto south_same_block_count = SearchLineSouthForSameTypes(seed_block_coords);
assert(same_blocks_south_count); assert(south_same_block_count);
block_quad_size.y = same_blocks_south_count; block_quad_size.y = south_same_block_count;
std::cout << " Found blocks going south: " << (int)block_quad_size.y << std::endl; if (gfx_mesher_debuglog)
std::cout << " Found blocks going south: " << (int)block_quad_size.y << std::endl;
const auto SearchLineEastForSameTypes = [&]() -> std::uint8_t { const auto SearchLineEastForSameTypes = [&]() -> std::uint8_t {
std::size_t alike_counter = 1;
const auto end = AxisIterator::end();
constexpr auto east_dir_mask = AxisIterator::CreateCardinalMask(CardinalDirections::kEast); constexpr auto east_dir_mask = AxisIterator::CreateCardinalMask(CardinalDirections::kEast);
auto side_axis_crawl = AxisIterator(src_block_loc, east_dir_mask);
side_axis_crawl++; // starting one ahead if (gfx_mesher_debuglog)
// if (side_axis_crawl != end) { std::cout << " Searching More East!!" << std::endl;
std::cout << " Searching More East!!" << std::endl;
for (; side_axis_crawl != end; side_axis_crawl++) { auto east_axis_crawl = AxisIterator(seed_block_coords, east_dir_mask);
LocalVoxel side_block_to_check = GetVoxelFromPosInChunk(side_axis_crawl.cur); east_axis_crawl++; // starting one ahead
auto below_block_type = this->GetVoxelType(side_block_to_check.pos); std::size_t alike_counter = 1;
if (below_block_type != type) for (; east_axis_crawl != AxisIterator::end(); east_axis_crawl++) {
const std::size_t east_blockidx_to_check = GetVoxelFromPosInChunk(*east_axis_crawl);
const auto east_block_type = this->GetVoxelType(east_blockidx_to_check);
if (east_block_type != seed_block_type)
break; break;
assert(!IsBlockMarkedOff(side_block_to_check.pos)); assert(!IsBlockMarkedOff(east_blockidx_to_check));
// here we go again, dip down to this max length // here we go again, dip down to this max length
auto additional_same_blocks_south_count = SearchLineSouthForSameTypes(side_axis_crawl.cur, same_blocks_south_count); const auto east_south_same_block_count = SearchLineSouthForSameTypes(*east_axis_crawl, south_same_block_count);
assert(additional_same_blocks_south_count <= same_blocks_south_count); assert(east_south_same_block_count <= south_same_block_count);
if (additional_same_blocks_south_count < same_blocks_south_count) if (east_south_same_block_count < south_same_block_count)
break; break;
alike_counter++; alike_counter++;
} }
//} //}
return alike_counter; return alike_counter;
}; };
if (uint(src_block_loc.x + 1) < cChunkDef::Width) { // only if we have room to check! if (uint(seed_block_coords.x + 1) < cChunkDef::Width) { // only if we have room to check!
const auto same_blocks_east_count = SearchLineEastForSameTypes(); const auto same_blocks_east_count = SearchLineEastForSameTypes();
block_quad_size.x = same_blocks_east_count; block_quad_size.x = same_blocks_east_count;
std::cout << " Found blocks going east: " << (int)block_quad_size.x << std::endl; if (gfx_mesher_debuglog)
std::cout << " Found blocks going east: " << (int)block_quad_size.x << std::endl;
} }
ChunkMeshedQuad new_face; ChunkMeshedQuad new_face;
const auto start = geo::Vec2(src_block_loc.x * box_size, src_block_loc.y * box_size); const auto quad_start = geo::Vec2(seed_block_coords.x * box_size, seed_block_coords.y * box_size);
const auto size = geo::Vec2(block_quad_size.x * box_size, block_quad_size.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>(start, size); new_face.quad = geo::Box<geo::Vec2>(quad_start, quad_size);
new_face.clr = chunk_textures[type]; new_face.clr = chunk_textures[seed_block_type];
std::cout << " *Added quad! : {" << start.x << ", " << start.y << "} with size {" << size.x << ", " << size.y << "}" << std::endl; if (gfx_mesher_debuglog)
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); finished_quads.push_back(new_face);
const auto MarkAreaFinished = [&](ChunkVecType origin, ChunkVecType size) { const auto MarkAreaFinished = [&](ChunkVecType origin, ChunkVecType size) {
assert(size.x && size.y); assert(size.x && size.y);
for (std::size_t x = 0; x < size.x; x++) { for (std::size_t x = 0; x < size.x; x++) {
for (std::size_t y = 0; y < size.y; y++) { for (std::size_t z = 0; z < size.y; z++) {
auto block_to_clear = origin + ChunkVecType(x, y); auto block_coords_to_clear = origin + ChunkVecType(x, z);
std::cout << " ------Marking Block Finished: {" << (int)block_to_clear.x << ", " << (int)block_to_clear.y << "}" << std::endl; if (gfx_mesher_debuglog)
auto voxel_pos = this->GetVoxelFromPosInChunk(block_to_clear); std::cout << " ------Marking Block Finished: {" << (int)block_coords_to_clear.x << ", " << (int)block_coords_to_clear.y << "}" << std::endl;
assert(!IsBlockMarkedOff(voxel_pos.pos)); auto blockidx = this->GetVoxelFromPosInChunk(block_coords_to_clear);
chunk_finished_checksum[voxel_pos.pos] = true; assert(!IsBlockMarkedOff(blockidx));
chunk_finished_checksum[blockidx] = true;
} }
} }
}; };
MarkAreaFinished(src_block_loc, block_quad_size); MarkAreaFinished(seed_block_coords, block_quad_size);
// mark it off of the chunk_finished_checksum by setting the chunk_finished_checksum[i] to 1 // mark it off of the chunk_finished_checksum by setting the chunk_finished_checksum[i] to 1
} }
std::cout << "Greedy "; if (gfx_mesher_debuglog)
std::cout << "Greedy ";
break; break;
} }
default: default:
@ -756,14 +754,15 @@ public:
}; };
auto end_time = std::chrono::high_resolution_clock::now(); // Calculate duration and convert to milliseconds auto end_time = std::chrono::high_resolution_clock::now(); // Calculate duration and convert to milliseconds
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count();
std::cout << "Meshing Finished!!! QuadCount: " << (int)finished_quads.size() << ", Within: " << duration << " microseconds" << std::endl; if (gfx_mesher_debuglog)
std::cout << "Meshing Finished!!! QuadCount: " << (int)finished_quads.size() << ", Within: " << duration << " microseconds" << std::endl;
return finished_quads; return finished_quads;
} }
static bool IsPosValidWithinChunk(ChunkVecType voxel_loc) { static bool IsPosValidWithinChunk(ChunkVecType block_coords) {
if (voxel_loc.x >= cChunkDef::Width) if (block_coords.x >= cChunkDef::Width)
return false; return false;
if (voxel_loc.y >= cChunkDef::Width) if (block_coords.y >= cChunkDef::Width)
return false; return false;
return true; return true;
} }
@ -829,7 +828,7 @@ public:
settings->dropdown->SetCallback([&](CDropdown*, int value) { settings->dropdown->SetCallback([&](CDropdown*, int value) {
current_render_quads.clear(); current_render_quads.clear();
}); });
this->SetSize(min_size.first, min_size.second); this->SetSize(ChunkRenderer::min_size.first, ChunkRenderer::min_size.second);
} }
std::vector<FalseChunk::ChunkMeshedQuad> current_render_quads; std::vector<FalseChunk::ChunkMeshedQuad> current_render_quads;
virtual void Draw(ICanvas* the_drawing_machine) override { virtual void Draw(ICanvas* the_drawing_machine) override {
@ -854,15 +853,17 @@ public:
if (current_render_quads.empty()) { if (current_render_quads.empty()) {
current_render_quads = world_slice->MeshChunk(FalseChunk::MesherComplexity(settings->dropdown->Value())); current_render_quads = world_slice->MeshChunk(FalseChunk::MesherComplexity(settings->dropdown->Value()));
std::pair<int, int> found_size; if (FalseChunk::gfx_mesher_debuglog) {
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads) { std::pair<int, int> found_size;
const auto max_coord = kinda_a_vert.quad.GetMax(); for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads) {
if (max_coord.x > found_size.first) const auto max_coord = kinda_a_vert.quad.GetMax();
found_size.first = max_coord.x; if (max_coord.x > found_size.first)
if (max_coord.y > found_size.second) found_size.first = max_coord.x;
found_size.second = max_coord.y; if (max_coord.y > found_size.second)
found_size.second = max_coord.y;
}
std::cout << "Created mesh with pixel size: " << found_size.first << ", " << found_size.second << std::endl;
} }
std::cout << "Created mesh with pixel size: " << found_size.first << ", " << found_size.second << std::endl;
} }
} }
}; };