mirror of
https://github.com/Relintai/godot_voxel.git
synced 2025-02-14 12:10:07 +01:00
Move both meshing and loading sheduling to LodOctree polling
This commit is contained in:
parent
29298958e7
commit
a521501add
@ -38,6 +38,10 @@ public:
|
|||||||
void set_visible(bool visible);
|
void set_visible(bool visible);
|
||||||
bool is_visible() const;
|
bool is_visible() const;
|
||||||
|
|
||||||
|
inline bool is_mesh_update_scheduled() {
|
||||||
|
return _mesh_state == MESH_UPDATE_NOT_SENT || _mesh_state == MESH_UPDATE_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VoxelBlock();
|
VoxelBlock();
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ Vector3 VoxelLodTerrain::get_viewer_pos() const {
|
|||||||
return Vector3();
|
return Vector3();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelLodTerrain::load_block_and_neighbors(const Vector3i &p_bpos, unsigned int lod_index) {
|
void VoxelLodTerrain::try_schedule_loading_with_neighbors(const Vector3i &p_bpos, unsigned int lod_index) {
|
||||||
CRASH_COND(lod_index >= get_lod_count());
|
CRASH_COND(lod_index >= get_lod_count());
|
||||||
Lod &lod = _lods[lod_index];
|
Lod &lod = _lods[lod_index];
|
||||||
|
|
||||||
@ -338,6 +338,34 @@ void VoxelLodTerrain::load_block_and_neighbors(const Vector3i &p_bpos, unsigned
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VoxelLodTerrain::check_block_loaded_and_updated(const Vector3i &p_bpos, unsigned int lod_index) {
|
||||||
|
CRASH_COND(lod_index >= get_lod_count());
|
||||||
|
Lod &lod = _lods[lod_index];
|
||||||
|
|
||||||
|
VoxelBlock *block = lod.map->get_block(p_bpos);
|
||||||
|
|
||||||
|
if (block == nullptr) {
|
||||||
|
try_schedule_loading_with_neighbors(p_bpos, lod_index);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!block->has_been_meshed()) {
|
||||||
|
if (!block->is_mesh_update_scheduled()) {
|
||||||
|
if (lod.map->is_block_surrounded(block->pos)) {
|
||||||
|
|
||||||
|
lod.blocks_pending_update.push_back(block->pos);
|
||||||
|
block->set_mesh_state(VoxelBlock::MESH_UPDATE_NOT_SENT);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
try_schedule_loading_with_neighbors(p_bpos, lod_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void remove_positions_outside_box(
|
static void remove_positions_outside_box(
|
||||||
std::vector<Vector3i> &positions,
|
std::vector<Vector3i> &positions,
|
||||||
Rect3i box,
|
Rect3i box,
|
||||||
@ -430,32 +458,16 @@ void VoxelLodTerrain::_process() {
|
|||||||
|
|
||||||
bool can_do(LodOctree<bool>::Node *node, unsigned int lod_index) {
|
bool can_do(LodOctree<bool>::Node *node, unsigned int lod_index) {
|
||||||
CRASH_COND(lod_index == 0);
|
CRASH_COND(lod_index == 0);
|
||||||
|
|
||||||
unsigned int child_lod_index = lod_index - 1;
|
unsigned int child_lod_index = lod_index - 1;
|
||||||
Lod &lod = self->_lods[child_lod_index];
|
|
||||||
|
|
||||||
bool can = true;
|
bool can = true;
|
||||||
|
|
||||||
// Can only subdivide if higher detail meshes are ready to be shown, otherwise it will produce holes
|
// Can only subdivide if higher detail meshes are ready to be shown, otherwise it will produce holes
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i) {
|
||||||
Vector3i child_pos = LodOctree<bool>::get_child_position(node->position, i);
|
Vector3i child_pos = LodOctree<bool>::get_child_position(node->position, i);
|
||||||
VoxelBlock *block = lod.map->get_block(child_pos);
|
can &= self->check_block_loaded_and_updated(child_pos, child_lod_index);
|
||||||
|
|
||||||
if (block == nullptr) {
|
|
||||||
can = false;
|
|
||||||
self->load_block_and_neighbors(child_pos, child_lod_index);
|
|
||||||
|
|
||||||
} else if (!block->has_been_meshed()) {
|
|
||||||
// TODO There is a case where a whole region of map cannot load,
|
|
||||||
// because we end here everytime instead of the above.
|
|
||||||
can = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!can) {
|
if (!can) {
|
||||||
++blocked_count;
|
++blocked_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return can;
|
return can;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,6 +476,7 @@ void VoxelLodTerrain::_process() {
|
|||||||
Vector3i bpos = node->position;
|
Vector3i bpos = node->position;
|
||||||
VoxelBlock *block = lod.map->get_block(bpos);
|
VoxelBlock *block = lod.map->get_block(bpos);
|
||||||
CRASH_COND(block == nullptr);
|
CRASH_COND(block == nullptr);
|
||||||
|
CRASH_COND(!block->has_been_meshed()); // Never show a block that hasn't been meshed
|
||||||
block->set_visible(true);
|
block->set_visible(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -475,24 +488,11 @@ void VoxelLodTerrain::_process() {
|
|||||||
|
|
||||||
bool can_do(LodOctree<bool>::Node *node, unsigned int lod_index) {
|
bool can_do(LodOctree<bool>::Node *node, unsigned int lod_index) {
|
||||||
// Can only unsubdivide if the parent mesh is ready
|
// Can only unsubdivide if the parent mesh is ready
|
||||||
Lod &lod = self->_lods[lod_index];
|
|
||||||
const Vector3i &bpos = node->position;
|
const Vector3i &bpos = node->position;
|
||||||
VoxelBlock *block = lod.map->get_block(bpos);
|
bool can = self->check_block_loaded_and_updated(bpos, lod_index);
|
||||||
|
|
||||||
bool can = true;
|
|
||||||
|
|
||||||
if (block == nullptr) {
|
|
||||||
can = false;
|
|
||||||
self->load_block_and_neighbors(bpos, lod_index);
|
|
||||||
|
|
||||||
} else if (!block->has_been_meshed()) {
|
|
||||||
can = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!can) {
|
if (!can) {
|
||||||
++blocked_count;
|
++blocked_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return can;
|
return can;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,48 +580,10 @@ void VoxelLodTerrain::_process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store buffer
|
// Store buffer
|
||||||
bool check_neighbors = !lod.map->has_block(eo.block_position);
|
|
||||||
VoxelBlock *block = lod.map->set_block_buffer(eo.block_position, eo.voxels);
|
VoxelBlock *block = lod.map->set_block_buffer(eo.block_position, eo.voxels);
|
||||||
//print_line(String("Adding block {0} at lod {1}").format(varray(eo.block_position.to_vec3(), eo.lod)));
|
//print_line(String("Adding block {0} at lod {1}").format(varray(eo.block_position.to_vec3(), eo.lod)));
|
||||||
// The block will be made visible only by LodOctree
|
// The block will be made visible and meshed only by LodOctree
|
||||||
block->set_visible(false);
|
block->set_visible(false);
|
||||||
|
|
||||||
// if the block is surrounded or any of its neighbors becomes surrounded, and are marked to mesh,
|
|
||||||
// it should be added to meshing requests
|
|
||||||
if (check_neighbors) {
|
|
||||||
// The block was not there before, so its Moore neighbors may be surrounded now.
|
|
||||||
Vector3i ndir;
|
|
||||||
for (ndir.z = -1; ndir.z < 2; ++ndir.z) {
|
|
||||||
for (ndir.x = -1; ndir.x < 2; ++ndir.x) {
|
|
||||||
for (ndir.y = -1; ndir.y < 2; ++ndir.y) {
|
|
||||||
|
|
||||||
Vector3i npos = eo.block_position + ndir;
|
|
||||||
VoxelBlock *nblock = lod.map->get_block(npos);
|
|
||||||
|
|
||||||
if (nblock == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lod.map->is_block_surrounded(npos)) {
|
|
||||||
|
|
||||||
if (nblock->get_mesh_state() == VoxelBlock::MESH_UPDATE_NOT_SENT) {
|
|
||||||
// Assuming it is scheduled to be updated already.
|
|
||||||
// In case of BLOCK_UPDATE_SENT, we'll have to resend it.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
nblock->set_mesh_state(VoxelBlock::MESH_UPDATE_NOT_SENT);
|
|
||||||
lod.blocks_pending_update.push_back(npos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Only update the block, neighbors will probably follow if needed
|
|
||||||
block->set_mesh_state(VoxelBlock::MESH_UPDATE_NOT_SENT);
|
|
||||||
lod.blocks_pending_update.push_back(eo.block_position);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,8 @@ private:
|
|||||||
void immerge_block(Vector3i block_pos, unsigned int lod_index);
|
void immerge_block(Vector3i block_pos, unsigned int lod_index);
|
||||||
void reset_updater();
|
void reset_updater();
|
||||||
Vector3 get_viewer_pos() const;
|
Vector3 get_viewer_pos() const;
|
||||||
void load_block_and_neighbors(const Vector3i &p_bpos, unsigned int lod_index);
|
void try_schedule_loading_with_neighbors(const Vector3i &p_bpos, unsigned int lod_index);
|
||||||
|
bool check_block_loaded_and_updated(const Vector3i &p_bpos, unsigned int lod_index);
|
||||||
|
|
||||||
template <typename A>
|
template <typename A>
|
||||||
void for_all_blocks(A &action) {
|
void for_all_blocks(A &action) {
|
||||||
|
@ -160,6 +160,7 @@ bool VoxelMap::has_block(Vector3i pos) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelMap::is_block_surrounded(Vector3i pos) const {
|
bool VoxelMap::is_block_surrounded(Vector3i pos) const {
|
||||||
|
// TODO If that check proves to be too expensive with all blocks we deal with, cache it in VoxelBlocks
|
||||||
for (unsigned int i = 0; i < Cube::MOORE_NEIGHBORING_3D_COUNT; ++i) {
|
for (unsigned int i = 0; i < Cube::MOORE_NEIGHBORING_3D_COUNT; ++i) {
|
||||||
Vector3i bpos = pos + Cube::g_moore_neighboring_3d[i];
|
Vector3i bpos = pos + Cube::g_moore_neighboring_3d[i];
|
||||||
if (!has_block(bpos)) {
|
if (!has_block(bpos)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user