Split refcounts
This commit is contained in:
parent
f7d0039811
commit
63d9361a87
@ -11,8 +11,7 @@ public:
|
||||
Ref<VoxelBuffer> voxels;
|
||||
const Vector3i position;
|
||||
const unsigned int lod_index = 0;
|
||||
// TODO Only data view type can be used here. Split it?
|
||||
VoxelViewerRefCount viewers;
|
||||
VoxelRefCount viewers;
|
||||
|
||||
static VoxelDataBlock *create(Vector3i bpos, Ref<VoxelBuffer> buffer, unsigned int size, unsigned int p_lod_index) {
|
||||
const int bs = size;
|
||||
|
@ -29,7 +29,8 @@ public:
|
||||
Vector3i position;
|
||||
unsigned int lod_index = 0;
|
||||
bool pending_transition_update = false;
|
||||
VoxelViewerRefCount viewers;
|
||||
VoxelRefCount mesh_viewers;
|
||||
VoxelRefCount collision_viewers;
|
||||
bool got_first_mesh_update = false;
|
||||
|
||||
uint32_t last_collider_update_time = 0;
|
||||
|
@ -310,8 +310,7 @@ void VoxelTerrain::try_schedule_mesh_update(VoxelMeshBlock *mesh_block) {
|
||||
// Already in the list
|
||||
return;
|
||||
}
|
||||
if (mesh_block->viewers.get(VoxelViewerRefCount::TYPE_MESH) == 0 &&
|
||||
mesh_block->viewers.get(VoxelViewerRefCount::TYPE_COLLISION) == 0) {
|
||||
if (mesh_block->mesh_viewers.get() == 0 && mesh_block->collision_viewers.get() == 0) {
|
||||
// No viewers want mesh on this block (why even call this function then?)
|
||||
return;
|
||||
}
|
||||
@ -346,7 +345,7 @@ void VoxelTerrain::view_data_block(Vector3i bpos) {
|
||||
if (loading_block == nullptr) {
|
||||
// First viewer to request it
|
||||
LoadingBlock new_loading_block;
|
||||
new_loading_block.viewers.add(VoxelViewerRefCount::TYPE_DATA);
|
||||
new_loading_block.viewers.add();
|
||||
|
||||
// Schedule a loading request
|
||||
_loading_blocks.set(bpos, new_loading_block);
|
||||
@ -354,12 +353,12 @@ void VoxelTerrain::view_data_block(Vector3i bpos) {
|
||||
|
||||
} else {
|
||||
// More viewers
|
||||
loading_block->viewers.add(VoxelViewerRefCount::TYPE_DATA);
|
||||
loading_block->viewers.add();
|
||||
}
|
||||
|
||||
} else {
|
||||
// The block is loaded
|
||||
block->viewers.add(VoxelViewerRefCount::TYPE_DATA);
|
||||
block->viewers.add();
|
||||
|
||||
// TODO viewers with varying flags during the game is not supported at the moment.
|
||||
// They have to be re-created, which may cause world re-load...
|
||||
@ -389,7 +388,12 @@ void VoxelTerrain::view_mesh_block(Vector3i bpos, bool mesh_flag, bool collision
|
||||
view_data_block(data_bpos);
|
||||
});*/
|
||||
|
||||
block->viewers.add(false, mesh_flag, collision_flag);
|
||||
if (mesh_flag) {
|
||||
block->mesh_viewers.add();
|
||||
}
|
||||
if (collision_flag) {
|
||||
block->collision_viewers.add();
|
||||
}
|
||||
|
||||
// This is needed in case a viewer wants to view meshes in places data blocks are already present.
|
||||
// Before that, meshes were updated only when a data block was loaded or modified,
|
||||
@ -428,9 +432,9 @@ void VoxelTerrain::unview_data_block(Vector3i bpos) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading_block->viewers.remove(VoxelViewerRefCount::TYPE_DATA);
|
||||
loading_block->viewers.remove();
|
||||
|
||||
if (loading_block->viewers.get(VoxelViewerRefCount::TYPE_DATA) == 0) {
|
||||
if (loading_block->viewers.get() == 0) {
|
||||
// No longer want to load it
|
||||
_loading_blocks.erase(bpos);
|
||||
|
||||
@ -446,11 +450,8 @@ void VoxelTerrain::unview_data_block(Vector3i bpos) {
|
||||
|
||||
} else {
|
||||
// The block is loaded
|
||||
VoxelViewerRefCount &viewers = block->viewers;
|
||||
|
||||
viewers.remove(VoxelViewerRefCount::TYPE_DATA);
|
||||
|
||||
if (viewers.get(VoxelViewerRefCount::TYPE_DATA) == 0) {
|
||||
block->viewers.remove();
|
||||
if (block->viewers.get() == 0) {
|
||||
// The block itself is no longer wanted
|
||||
unload_data_block(bpos);
|
||||
}
|
||||
@ -470,25 +471,23 @@ void VoxelTerrain::unview_mesh_block(Vector3i bpos, bool mesh_flag, bool collisi
|
||||
unview_data_block(data_bpos);
|
||||
});*/
|
||||
|
||||
VoxelViewerRefCount &viewers = block->viewers;
|
||||
|
||||
if (mesh_flag) {
|
||||
viewers.remove(VoxelViewerRefCount::TYPE_MESH);
|
||||
if (viewers.get(VoxelViewerRefCount::TYPE_MESH) == 0) {
|
||||
block->mesh_viewers.remove();
|
||||
if (block->mesh_viewers.get() == 0) {
|
||||
// Mesh no longer required
|
||||
block->drop_mesh();
|
||||
}
|
||||
}
|
||||
|
||||
if (collision_flag) {
|
||||
viewers.remove(VoxelViewerRefCount::TYPE_COLLISION);
|
||||
if (viewers.get(VoxelViewerRefCount::TYPE_COLLISION) == 0) {
|
||||
block->collision_viewers.remove();
|
||||
if (block->collision_viewers.get() == 0) {
|
||||
// Collision no longer required
|
||||
block->drop_collision();
|
||||
}
|
||||
}
|
||||
|
||||
if (viewers.get(VoxelViewerRefCount::TYPE_MESH) == 0 && viewers.get(VoxelViewerRefCount::TYPE_COLLISION) == 0) {
|
||||
if (block->collision_viewers.get() == 0 && block->collision_viewers.get() == 0) {
|
||||
unload_mesh_block(bpos);
|
||||
}
|
||||
}
|
||||
@ -1555,8 +1554,7 @@ void VoxelTerrain::_process() {
|
||||
collidable_surfaces.clear();
|
||||
}
|
||||
|
||||
const bool gen_collisions =
|
||||
_generate_collisions && block->viewers.get(VoxelViewerRefCount::TYPE_COLLISION) > 0;
|
||||
const bool gen_collisions = _generate_collisions && block->collision_viewers.get() > 0;
|
||||
|
||||
block->set_mesh(mesh);
|
||||
if (gen_collisions) {
|
||||
|
@ -176,7 +176,7 @@ private:
|
||||
// Therefore, could a simple grid be better to use than a hashmap?
|
||||
|
||||
struct LoadingBlock {
|
||||
VoxelViewerRefCount viewers;
|
||||
VoxelRefCount viewers;
|
||||
};
|
||||
|
||||
HashMap<Vector3i, LoadingBlock, Vector3iHasher> _loading_blocks;
|
||||
|
@ -3,58 +3,23 @@
|
||||
|
||||
#include "../util/fixed_array.h"
|
||||
|
||||
class VoxelViewerRefCount {
|
||||
class VoxelRefCount {
|
||||
public:
|
||||
enum ViewerType {
|
||||
TYPE_DATA = 0, // This one is always counted, others are optional
|
||||
TYPE_MESH,
|
||||
TYPE_COLLISION,
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
VoxelViewerRefCount() {
|
||||
_counts.fill(0);
|
||||
inline void add() {
|
||||
++_count;
|
||||
}
|
||||
|
||||
inline void add(bool data, bool mesh, bool collision) {
|
||||
if (data) {
|
||||
add(TYPE_DATA);
|
||||
}
|
||||
if (mesh) {
|
||||
add(TYPE_MESH);
|
||||
}
|
||||
if (collision) {
|
||||
add(TYPE_COLLISION);
|
||||
}
|
||||
inline void remove() {
|
||||
ERR_FAIL_COND_MSG(_count == 0, "Trying to decrease refcount when it's already zero");
|
||||
--_count;
|
||||
}
|
||||
|
||||
inline void remove(bool data, bool mesh, bool collision) {
|
||||
if (data) {
|
||||
remove(TYPE_DATA);
|
||||
}
|
||||
if (mesh) {
|
||||
remove(TYPE_MESH);
|
||||
}
|
||||
if (collision) {
|
||||
remove(TYPE_COLLISION);
|
||||
}
|
||||
}
|
||||
|
||||
inline void add(ViewerType t) {
|
||||
++_counts[t];
|
||||
}
|
||||
|
||||
inline void remove(ViewerType t) {
|
||||
CRASH_COND_MSG(_counts[t] == 0, "Trying to remove a viewer to a block that had none");
|
||||
--_counts[t];
|
||||
}
|
||||
|
||||
inline uint32_t get(ViewerType t) const {
|
||||
return _counts[t];
|
||||
inline unsigned int get() const {
|
||||
return _count;
|
||||
}
|
||||
|
||||
private:
|
||||
FixedArray<uint32_t, TYPE_COUNT> _counts;
|
||||
unsigned int _count = 0;
|
||||
};
|
||||
|
||||
#endif // VOXEL_VIEWER_REF_COUNT_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user