Store pointer to block in map to remove one indirection

This commit is contained in:
Marc Gilleron 2022-06-04 22:59:28 +01:00
parent 3b152842aa
commit 82ae631894

View File

@ -30,7 +30,7 @@ public:
} }
auto it = _blocks_map.find(bpos); auto it = _blocks_map.find(bpos);
if (it != _blocks_map.end()) { if (it != _blocks_map.end()) {
const unsigned int i = it->second; const unsigned int i = it->second.index;
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
CRASH_COND(i >= _blocks.size()); CRASH_COND(i >= _blocks.size());
#endif #endif
@ -48,13 +48,14 @@ public:
} }
auto it = _blocks_map.find(bpos); auto it = _blocks_map.find(bpos);
if (it != _blocks_map.end()) { if (it != _blocks_map.end()) {
const unsigned int i = it->second;
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
const unsigned int i = it->second.index;
CRASH_COND(i >= _blocks.size()); CRASH_COND(i >= _blocks.size());
#endif
MeshBlock_T *block = _blocks[i]; MeshBlock_T *block = _blocks[i];
CRASH_COND(block == nullptr); // The map should not contain null blocks CRASH_COND(block == nullptr); // The map should not contain null blocks
_last_accessed_block = block; CRASH_COND(it->second.block == nullptr);
#endif
_last_accessed_block = it->second.block;
return _last_accessed_block; return _last_accessed_block;
} }
return nullptr; return nullptr;
@ -66,15 +67,16 @@ public:
} }
auto it = _blocks_map.find(bpos); auto it = _blocks_map.find(bpos);
if (it != _blocks_map.end()) { if (it != _blocks_map.end()) {
const unsigned int i = it->second;
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
const unsigned int i = it->second.index;
CRASH_COND(i >= _blocks.size()); CRASH_COND(i >= _blocks.size());
#endif MeshBlock_T *block = _blocks[i];
// TODO This function can't cache _last_accessed_block, because it's const, so repeated accesses are hashing
// again...
const MeshBlock_T *block = _blocks[i];
CRASH_COND(block == nullptr); // The map should not contain null blocks CRASH_COND(block == nullptr); // The map should not contain null blocks
return block; CRASH_COND(it->second.block == nullptr);
#endif
// This function can't cache _last_accessed_block, because it's const, so repeated accesses are hashing
// again...
return it->second.block;
} }
return nullptr; return nullptr;
} }
@ -90,7 +92,7 @@ public:
#endif #endif
unsigned int i = _blocks.size(); unsigned int i = _blocks.size();
_blocks.push_back(block); _blocks.push_back(block);
_blocks_map.insert({ bpos, i }); _blocks_map.insert({ bpos, { block, i } });
} }
bool has_block(Vector3i pos) const { bool has_block(Vector3i pos) const {
@ -143,7 +145,13 @@ public:
} }
private: private:
void remove_block_internal(std::unordered_map<Vector3i, unsigned int>::iterator rm_it, unsigned int index) { struct MapItem {
MeshBlock_T *block;
// Index of the block within the vector storage
unsigned int index;
};
void remove_block_internal(typename std::unordered_map<Vector3i, MapItem>::iterator rm_it, unsigned int index) {
// TODO `erase` can occasionally be very slow (milliseconds) if the map contains lots of items. // TODO `erase` can occasionally be very slow (milliseconds) if the map contains lots of items.
// This might be caused by internal rehashing/resizing. // This might be caused by internal rehashing/resizing.
// We should look for a faster container, or reduce the number of entries. // We should look for a faster container, or reduce the number of entries.
@ -161,7 +169,7 @@ private:
if (index < _blocks.size()) { if (index < _blocks.size()) {
auto moved_block_index_it = _blocks_map.find(moved_block->position); auto moved_block_index_it = _blocks_map.find(moved_block->position);
CRASH_COND(moved_block_index_it == _blocks_map.end()); CRASH_COND(moved_block_index_it == _blocks_map.end());
moved_block_index_it->second = index; moved_block_index_it->second.index = index;
} }
} }
@ -182,8 +190,9 @@ private:
private: private:
// Blocks stored with a spatial hash in all 3D directions. // Blocks stored with a spatial hash in all 3D directions.
std::unordered_map<Vector3i, unsigned int> _blocks_map; std::unordered_map<Vector3i, MapItem> _blocks_map;
// Blocks are stored in a vector to allow faster iteration over all of them // Blocks are stored in a vector to allow faster iteration over all of them.
// Use cases for this include updating the transform of the meshes
std::vector<MeshBlock_T *> _blocks; std::vector<MeshBlock_T *> _blocks;
// Voxel access will most frequently be in contiguous areas, so the same blocks are accessed. // Voxel access will most frequently be in contiguous areas, so the same blocks are accessed.