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;
return ret_pos;
}
class LocalVoxel {
public:
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;
static std::size_t GetVoxelFromPosInChunk(geo::internal::BVec2<uint8_t> in_pos) {
return cChunkDef::MakeIndex(in_pos.x, 0, in_pos.y);
}
BlockType GetVoxelType(std::size_t v) const {
return raw_chunk_data[v];
}
class AxisIterator {
public:
bool end_flagged = false;
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)
@ -535,6 +522,7 @@ public:
this->end_flagged = true;
return *this;
}
const ChunkVecType& operator*() { return this->cur; }
bool operator==(const AxisIterator& other) const {
if (other.end_flagged)
return this->end_flagged;
@ -587,7 +575,7 @@ public:
kIntrinsicGreedy, // Using bitwise operations :O
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...
struct ChunkMeshedQuad {
geo::Box<geo::Vec2> quad;
@ -603,47 +591,53 @@ public:
glez::color::green, // sapling
glez::color::black // bedrock
};
static constexpr bool gfx_mesher_debuglog = false;
std::vector<ChunkMeshedQuad> MeshChunk(MesherComplexity cmplxity) const {
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();
switch (cmplxity) {
case MesherComplexity::kNieve: // I dont think this is possible in 2d for the time being...
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_y = 0; dim_y < cChunkDef::Width; dim_y++) {
LocalVoxel cube = GetVoxelFromPosInChunk({ dim_x, dim_y });
const auto type = this->GetVoxelType(cube.pos);
for (uint dim_z = 0; dim_z < cChunkDef::Width; dim_z++) {
std::size_t blockidx = GetVoxelFromPosInChunk({ dim_x, dim_z });
const auto type = this->GetVoxelType(blockidx);
if (type == ENUM_BLOCK_TYPE::E_BLOCK_AIR)
continue;
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);
const auto size = /*start +*/ geo::Vec2(box_size, box_size);
new_face.quad = geo::Box<geo::Vec2>(start, size);
new_face.clr = chunk_textures[type];
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;
}
/*case MesherComplexity::kNieve: {
} */
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;
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> {
for (std::size_t x = 0; x < cChunkDef::Width; x++) {
for (std::size_t y = 0; y < cChunkDef::Width; y++) {
auto vox = this->GetVoxelFromPosInChunk({ x, y });
if (!IsBlockMarkedOff(vox.pos))
return vox.pos;
for (std::size_t z = 0; z < cChunkDef::Width; z++) {
auto blockidx = this->GetVoxelFromPosInChunk({ x, z });
if (!IsBlockMarkedOff(blockidx))
return blockidx;
}
}
return std::optional<std::size_t>();
@ -653,32 +647,30 @@ public:
if (!unmeshed_face.has_value())
throw std::logic_error("Greedy ChunkMesher checksum thinks there is a unmeshed chunk but unable to find it!");
LocalVoxel cube;
cube.pos = unmeshed_face.value();
const auto type = this->GetVoxelType(cube.pos);
if (type == ENUM_BLOCK_TYPE::E_BLOCK_AIR) {
chunk_finished_checksum[cube.pos] = true;
const auto seed_blockidx = unmeshed_face.value();
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;
}
{
const auto ext_cube = cube.ExtractVec();
std::cout << "Greedy found Seed block \"" << (int)type << "\": {" << (int)ext_cube.x << ", " << (int)ext_cube.y << "}" << std::endl;
if (gfx_mesher_debuglog) {
const auto seed_block_coords = ExtractVec(seed_blockidx);
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 };
const auto src_block_loc = cube.ExtractVec();
ChunkVecType block_quad_size = { 1, 1 }; // in coords
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.
constexpr auto south_dir_mask = AxisIterator::CreateCardinalMask(CardinalDirections::kSouth);
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;
const auto end = AxisIterator::end();
for (auto axis_crawl = AxisIterator(src_line, south_dir_mask); axis_crawl != end; axis_crawl++) {
const LocalVoxel block_to_check = GetVoxelFromPosInChunk(axis_crawl.cur);
auto below_block_type = this->GetVoxelType(block_to_check.pos);
if (below_block_type != type)
for (auto south_axis_crawl = AxisIterator(src_line, south_dir_mask); south_axis_crawl != AxisIterator::end(); south_axis_crawl++) {
const std::size_t south_blockidx_to_check = GetVoxelFromPosInChunk(*south_axis_crawl);
auto south_block_type = this->GetVoxelType(south_blockidx_to_check);
if (south_block_type != seed_block_type)
break;
if (IsBlockMarkedOff(block_to_check.pos))
if (IsBlockMarkedOff(south_blockidx_to_check))
break;
alike_counter++;
if (alike_counter >= max_size)
@ -686,68 +678,74 @@ public:
}
return alike_counter;
};
const auto same_blocks_south_count = SearchLineSouthForSameTypes(src_block_loc);
assert(same_blocks_south_count);
block_quad_size.y = same_blocks_south_count;
const auto south_same_block_count = SearchLineSouthForSameTypes(seed_block_coords);
assert(south_same_block_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 {
std::size_t alike_counter = 1;
const auto end = AxisIterator::end();
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 (side_axis_crawl != end) {
std::cout << " Searching More East!!" << std::endl;
for (; side_axis_crawl != end; side_axis_crawl++) {
LocalVoxel side_block_to_check = GetVoxelFromPosInChunk(side_axis_crawl.cur);
auto below_block_type = this->GetVoxelType(side_block_to_check.pos);
if (below_block_type != type)
if (gfx_mesher_debuglog)
std::cout << " Searching More East!!" << std::endl;
auto east_axis_crawl = AxisIterator(seed_block_coords, east_dir_mask);
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 auto east_block_type = this->GetVoxelType(east_blockidx_to_check);
if (east_block_type != seed_block_type)
break;
assert(!IsBlockMarkedOff(side_block_to_check.pos));
assert(!IsBlockMarkedOff(east_blockidx_to_check));
// 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);
assert(additional_same_blocks_south_count <= same_blocks_south_count);
if (additional_same_blocks_south_count < same_blocks_south_count)
const auto east_south_same_block_count = SearchLineSouthForSameTypes(*east_axis_crawl, south_same_block_count);
assert(east_south_same_block_count <= south_same_block_count);
if (east_south_same_block_count < south_same_block_count)
break;
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();
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;
const auto start = geo::Vec2(src_block_loc.x * box_size, src_block_loc.y * box_size);
const auto size = geo::Vec2(block_quad_size.x * box_size, block_quad_size.y * box_size);
const auto quad_start = geo::Vec2(seed_block_coords.x * box_size, seed_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>(start, size);
new_face.clr = chunk_textures[type];
std::cout << " *Added quad! : {" << start.x << ", " << start.y << "} with size {" << size.x << ", " << size.y << "}" << std::endl;
new_face.quad = geo::Box<geo::Vec2>(quad_start, quad_size);
new_face.clr = chunk_textures[seed_block_type];
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);
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 y = 0; y < size.y; y++) {
auto block_to_clear = origin + ChunkVecType(x, y);
std::cout << " ------Marking Block Finished: {" << (int)block_to_clear.x << ", " << (int)block_to_clear.y << "}" << std::endl;
auto voxel_pos = this->GetVoxelFromPosInChunk(block_to_clear);
assert(!IsBlockMarkedOff(voxel_pos.pos));
chunk_finished_checksum[voxel_pos.pos] = true;
for (std::size_t z = 0; z < size.y; z++) {
auto block_coords_to_clear = origin + ChunkVecType(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);
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
}
std::cout << "Greedy ";
if (gfx_mesher_debuglog)
std::cout << "Greedy ";
break;
}
default:
@ -756,14 +754,15 @@ public:
};
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();
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;
}
static bool IsPosValidWithinChunk(ChunkVecType voxel_loc) {
if (voxel_loc.x >= cChunkDef::Width)
static bool IsPosValidWithinChunk(ChunkVecType block_coords) {
if (block_coords.x >= cChunkDef::Width)
return false;
if (voxel_loc.y >= cChunkDef::Width)
if (block_coords.y >= cChunkDef::Width)
return false;
return true;
}
@ -829,7 +828,7 @@ public:
settings->dropdown->SetCallback([&](CDropdown*, int value) {
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;
virtual void Draw(ICanvas* the_drawing_machine) override {
@ -854,15 +853,17 @@ public:
if (current_render_quads.empty()) {
current_render_quads = world_slice->MeshChunk(FalseChunk::MesherComplexity(settings->dropdown->Value()));
std::pair<int, int> found_size;
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads) {
const auto max_coord = kinda_a_vert.quad.GetMax();
if (max_coord.x > found_size.first)
found_size.first = max_coord.x;
if (max_coord.y > found_size.second)
found_size.second = max_coord.y;
if (FalseChunk::gfx_mesher_debuglog) {
std::pair<int, int> found_size;
for (const FalseChunk::ChunkMeshedQuad& kinda_a_vert : current_render_quads) {
const auto max_coord = kinda_a_vert.quad.GetMax();
if (max_coord.x > found_size.first)
found_size.first = max_coord.x;
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;
}
}
};