Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
Expand Down Expand Up @@ -116,12 +117,22 @@ public void remove(Vector3ic coord) {

/**
* Queue all dirty items in our collection, in priority order.
* <p>
* Only the chunks actually being queued are sorted. Sorting the whole proximity list first and
* filtering while walking it - as this used to - orders thousands of chunks to decide the order of
* the handful that are dirty this frame, and the two give the same sequence either way. At the
* MEGA view distance (33x7x33 = 7623 chunks) that measured ~200us per frame against ~27us, on a
* list already near-sorted from last frame; the cost did not vary with how many chunks were dirty,
* which is the tell that it was all in touching the list rather than in the queueing.
* <p>
* The comparator is not cheap per call either - it re-reads the camera through a Provider and
* allocates two Vector3f per comparison, via {@code Chunk.getRenderPosition()} - so the win is in
* calling it O(dirty log dirty) times instead of O(n log n).
*
* @return the number of dirty chunks added to the queue
*/
public int update() {
int statDirtyChunks = 0;
chunksInProximityOfCamera.sort(frontToBackComparator);
List<Chunk> toQueue = new ArrayList<>();
for (Chunk chunk : chunksInProximityOfCamera) {
if (!chunk.isReady()) {
// Chunk was added as part of some region, but not yet ready.
Expand All @@ -133,6 +144,20 @@ public int update() {
// Will poll it again next tick to see if it got dirty since then.
continue;
}
toQueue.add(chunk);
}

toQueue.sort(frontToBackComparator);

int statDirtyChunks = 0;
for (Chunk chunk : toQueue) {
// Re-checked here, not just when the list was built: emitting can drive mesh generation
// synchronously, and that clears the flag. A chunk sitting in the proximity list more than
// once - add() does not deduplicate - would otherwise be queued again for a mesh the
// emission before it has already produced.
if (!chunk.isDirty()) {
continue;
}
Comment thread
soloturn marked this conversation as resolved.
statDirtyChunks++;
Sinks.EmitResult result = chunkMeshPublisher.tryEmitNext(chunk);
if (result.isFailure()) {
Expand Down
Loading