mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-11 00:09:39 +00:00
Chunk: improved heightmap calculation performance
recalculateHeightMapColumn is stateless, so it can't make any assumptions about which subchunks to check for blocks. However, in most the average case (6 allocated subchunks), this causes 2500+ useless SubChunk->getHighestBlockAt() calls (10 per column). Since we're calculating in bulk, we can figure out which subchunks are empty one time and ignore them for all 256 columns. In the average case, this produced a 50-60% performance improvement for heightmap calculation (~1.1 ms -> 0.5 ms). In extreme cases where the height is extremely varied, this produces no observable performance benefit, but for most cases with flattish terrain, it's an improvement. It can likely be further improved, but further performance improvements are outside the scope of this commit and will likely result in more complexity increases.
This commit is contained in:
parent
e1816bd415
commit
6b6f77f8af
@ -266,9 +266,38 @@ class Chunk{
|
||||
* @phpstan-param \SplFixedArray<bool> $lightDiffusers
|
||||
*/
|
||||
public function recalculateHeightMap(\SplFixedArray $lightFilters, \SplFixedArray $lightDiffusers) : void{
|
||||
$maxSubChunkY = $this->subChunks->count() - 1;
|
||||
for(; $maxSubChunkY >= 0; $maxSubChunkY--){
|
||||
if(!$this->getSubChunk($maxSubChunkY)->isEmptyFast()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($maxSubChunkY === -1){ //whole column is definitely empty
|
||||
$this->setHeightMapArray(array_fill(0, 256, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
for($x = 0; $x < 16; ++$x){
|
||||
$this->recalculateHeightMapColumn($x, $z, $lightFilters, $lightDiffusers);
|
||||
$y = null;
|
||||
for($subChunkY = $maxSubChunkY; $subChunkY >= 0; $subChunkY--){
|
||||
$subHighestBlockY = $this->getSubChunk($subChunkY)->getHighestBlockAt($x, $z);
|
||||
if($subHighestBlockY !== -1){
|
||||
$y = ($subChunkY * 16) + $subHighestBlockY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($y === null){ //no blocks in the column
|
||||
$this->setHeightMap($x, $z, 0);
|
||||
}else{
|
||||
for(; $y >= 0; --$y){
|
||||
if($lightFilters[$state = $this->getFullBlock($x, $y, $z)] > 1 or $lightDiffusers[$state]){
|
||||
$this->setHeightMap($x, $z, $y + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user