mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-14 01:14:08 +00:00
Sort block entities back to front before dispatch
This commit is contained in:
3 files changed
+116
-38
No files matched your search
+6
-38
@@ -1,8 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.bop.FogBiomeCache;
|
||||
@@ -95,9 +93,7 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
private final ObjectArrayList<TileEntity> frameTEs = new ObjectArrayList<>();
|
||||
private final ObjectArrayList<TileEntity> frameOverride = new ObjectArrayList<>();
|
||||
|
||||
// For sorting transparent TESRs
|
||||
private final TileEntityOrderer tileEntityOrderer = new TileEntityOrderer();
|
||||
private final ArrayList<TileEntity> sortedTileEntities = new ArrayList<>();
|
||||
private final TileEntityDepthOrder depthOrder = new TileEntityDepthOrder();
|
||||
|
||||
private CeleritasWorldRenderer(Minecraft mc) {
|
||||
// Private constructor for singleton
|
||||
@@ -172,7 +168,6 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
DynamicLights.setActiveRenderer(null);
|
||||
this.frameTEs.clear();
|
||||
this.frameOverride.clear();
|
||||
this.sortedTileEntities.clear();
|
||||
ShadowRenderer.visibleTileEntities.clear();
|
||||
ShadowRenderer.globalTileEntities.clear();
|
||||
TesrLifecycle.reset();
|
||||
@@ -442,6 +437,9 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
this.teTransform = null;
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_TESR_DISPATCH);
|
||||
try {
|
||||
if (ClientProxy.options().performance.translucencySorting) {
|
||||
depthOrder.sortBackToFront(frameTEs, teCamX, teCamY, teCamZ);
|
||||
}
|
||||
for (int i = 0; i < frameTEs.size(); i++) {
|
||||
final TileEntity te = frameTEs.get(i);
|
||||
if (!(te instanceof OverridesShouldRenderInPass)) {
|
||||
@@ -461,20 +459,13 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
} else {
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_TESR_DISPATCH);
|
||||
try {
|
||||
sortedTileEntities.clear();
|
||||
for (int i = 0; i < frameOverride.size(); i++) {
|
||||
final TileEntity te = frameOverride.get(i);
|
||||
if (te.shouldRenderInPass(pass)) {
|
||||
sortedTileEntities.add(te);
|
||||
dispatchTE(te, partialTicks);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (sortedTileEntities.size() > 1 && ClientProxy.options().performance.translucencySorting) {
|
||||
sortedTileEntities.sort(tileEntityOrderer.setLastCameraState(lastCameraState));
|
||||
}
|
||||
for (int i = 0; i < sortedTileEntities.size(); i++) {
|
||||
dispatchTE(sortedTileEntities.get(i), partialTicks);
|
||||
}
|
||||
count = sortedTileEntities.size();
|
||||
} finally {
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
}
|
||||
@@ -673,27 +664,4 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TileEntityOrderer implements Comparator<TileEntity> {
|
||||
public CameraState lastCameraState;
|
||||
|
||||
public TileEntityOrderer() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TileEntityOrderer setLastCameraState(CameraState lastCameraState) {
|
||||
this.lastCameraState = lastCameraState;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(TileEntity te1, TileEntity te2) {
|
||||
final double x = this.lastCameraState.x();
|
||||
final double y = this.lastCameraState.y();
|
||||
final double z = this.lastCameraState.z();
|
||||
final double d1 = te1.getDistanceFrom(x, y, z);
|
||||
final double d2 = te2.getDistanceFrom(x, y, z);
|
||||
return Double.compare(d2, d1);
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
final class TileEntityDepthOrder {
|
||||
|
||||
private static final int RADIX_BITS = 8;
|
||||
private static final int BUCKETS = 1 << RADIX_BITS;
|
||||
|
||||
private final int[] counts = new int[BUCKETS];
|
||||
private int[] keys = new int[0];
|
||||
private int[] keysScratch = new int[0];
|
||||
private int[] order = new int[0];
|
||||
private int[] orderScratch = new int[0];
|
||||
private TileEntity[] entities = new TileEntity[0];
|
||||
|
||||
void sortBackToFront(ObjectArrayList<TileEntity> list, double camX, double camY, double camZ) {
|
||||
final int n = list.size();
|
||||
if (n < 2) return;
|
||||
final Object[] source = list.elements();
|
||||
if (keys.length < n) {
|
||||
final int capacity = source.length;
|
||||
keys = new int[capacity];
|
||||
keysScratch = new int[capacity];
|
||||
order = new int[capacity];
|
||||
orderScratch = new int[capacity];
|
||||
entities = new TileEntity[capacity];
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
final TileEntity te = (TileEntity) source[i];
|
||||
final double dx = te.xCoord + 0.5 - camX;
|
||||
final double dy = te.yCoord + 0.5 - camY;
|
||||
final double dz = te.zCoord + 0.5 - camZ;
|
||||
keys[i] = Integer.MAX_VALUE - Float.floatToRawIntBits((float) (dx * dx + dy * dy + dz * dz));
|
||||
order[i] = i;
|
||||
entities[i] = te;
|
||||
}
|
||||
final int[] sorted = sortOrder(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
source[i] = entities[sorted[i]];
|
||||
entities[sorted[i]] = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int[] sortOrder(int n) {
|
||||
int[] keyIn = keys, keyOut = keysScratch;
|
||||
int[] idxIn = order, idxOut = orderScratch;
|
||||
for (int shift = 0; shift < Integer.SIZE; shift += RADIX_BITS) {
|
||||
Arrays.fill(counts, 0);
|
||||
for (int i = 0; i < n; i++) counts[(keyIn[i] >>> shift) & (BUCKETS - 1)]++;
|
||||
if (counts[(keyIn[0] >>> shift) & (BUCKETS - 1)] == n) continue;
|
||||
int sum = 0;
|
||||
for (int b = 0; b < BUCKETS; b++) {
|
||||
final int c = counts[b];
|
||||
counts[b] = sum;
|
||||
sum += c;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
final int dst = counts[(keyIn[i] >>> shift) & (BUCKETS - 1)]++;
|
||||
keyOut[dst] = keyIn[i];
|
||||
idxOut[dst] = idxIn[i];
|
||||
}
|
||||
final int[] k = keyIn;
|
||||
keyIn = keyOut;
|
||||
keyOut = k;
|
||||
final int[] x = idxIn;
|
||||
idxIn = idxOut;
|
||||
idxOut = x;
|
||||
}
|
||||
keys = keyIn;
|
||||
keysScratch = keyOut;
|
||||
order = idxIn;
|
||||
orderScratch = idxOut;
|
||||
return idxIn;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.gtnewhorizons.angelica.rendering.celeritas;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class TileEntityDepthOrderTest {
|
||||
|
||||
private static TileEntity at(int x, int y, int z) {
|
||||
final TileEntity te = new TileEntity();
|
||||
te.xCoord = x;
|
||||
te.yCoord = y;
|
||||
te.zCoord = z;
|
||||
return te;
|
||||
}
|
||||
|
||||
@Test
|
||||
void sortsFarthestFirstAndKeepsTiesInListOrder() {
|
||||
final TileEntity near = at(0, 0, 2);
|
||||
final TileEntity far = at(0, 0, 181);
|
||||
final TileEntity mid = at(0, 0, 5);
|
||||
final TileEntity midOpposite = at(0, 0, -5);
|
||||
final ObjectArrayList<TileEntity> list = new ObjectArrayList<>(Arrays.asList(near, far, mid, midOpposite));
|
||||
new TileEntityDepthOrder().sortBackToFront(list, 0.5, 0.5, 0.5);
|
||||
assertEquals(Arrays.asList(far, mid, midOpposite, near), list);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user