mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-27 06:20:02 +00:00
Shared object placement layout
- Object placement bakes split into one per-object layout (palette, tiles, canopy) and per-variant offsets - Variants beyond the per-object limit are built transiently instead of clearing the variant map - High-variant golden and no-rebuild tests
This commit is contained in:
1 parent
d7cad729e4
commit
bf9e65252c
4 files changed
+244
-121
No files matched your search
@@ -4,9 +4,16 @@ import art.arcane.iris.generation.geometry.IrisBlockVector;
|
||||
import art.arcane.iris.testsupport.KeyedBlockState;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ObjectPlacementBakeTest {
|
||||
@Test
|
||||
@@ -65,6 +72,57 @@ public class ObjectPlacementBakeTest {
|
||||
assertSame(after, ObjectPlacementBake.of(object, spin, false, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void highVariantPlacementsKeepCachedVariantsAndNeverRebuildTheLayout() {
|
||||
IrisObject object = object();
|
||||
IrisObjectRotation pine = new IrisObjectRotation();
|
||||
pine.setEnabled(true);
|
||||
pine.setXAxis(new IrisAxisRotationClamp(true, false, -9D, 9D, 1D));
|
||||
pine.setYAxis(new IrisAxisRotationClamp(true, false, 0D, 270D, 90D));
|
||||
pine.setZAxis(new IrisAxisRotationClamp(true, false, -9D, 9D, 1D));
|
||||
IrisBlockVector translate = new IrisBlockVector(0D, -6D, 0D);
|
||||
Random random = new Random(1444L);
|
||||
ObjectPlacementBake first = ObjectPlacementBake.of(object, new SpinKernel(pine, 0, 0, 0), false, translate);
|
||||
Map<ObjectPlacementBake.Key, ObjectPlacementBake> settled = null;
|
||||
Set<ObjectPlacementBake.Key> distinct = new HashSet<>();
|
||||
for (int placement = 0; placement < 4000; placement++) {
|
||||
SpinKernel spin = new SpinKernel(pine, random.nextInt(360), random.nextInt(360), random.nextInt(360));
|
||||
ObjectPlacementBake bake = ObjectPlacementBake.of(object, spin, false, translate);
|
||||
distinct.add(ObjectPlacementBake.Key.of(spin, false, translate));
|
||||
assertSame(first.palette(), bake.palette());
|
||||
assertTrue(object.placementBakes.size() <= 32);
|
||||
assertTransformed(object, spin, translate, bake);
|
||||
if (placement == 2000) {
|
||||
settled = new HashMap<>(object.placementBakes);
|
||||
}
|
||||
}
|
||||
assertTrue(distinct.size() > 40);
|
||||
assertEquals(32, settled.size());
|
||||
assertEquals(settled.keySet(), object.placementBakes.keySet());
|
||||
for (Map.Entry<ObjectPlacementBake.Key, ObjectPlacementBake> entry : settled.entrySet()) {
|
||||
assertSame(entry.getValue(), object.placementBakes.get(entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertTransformed(IrisObject object, SpinKernel spin, IrisBlockVector translate, ObjectPlacementBake bake) {
|
||||
double[] exact = bake.exact(object, spin);
|
||||
int index = 0;
|
||||
for (IrisBlockVector source : object.getBlocks().keys()) {
|
||||
IrisBlockVector expected = source.clone();
|
||||
spin.rotate(expected);
|
||||
expected.add(translate);
|
||||
assertEquals((int) Math.round(expected.getX()), bake.offsetX(index));
|
||||
assertEquals((int) Math.round(expected.getY()), bake.offsetY(index));
|
||||
assertEquals((int) Math.round(expected.getZ()), bake.offsetZ(index));
|
||||
assertEquals(expected.getBlockY(), bake.layerY(index));
|
||||
assertEquals(expected.getX(), exact[index * 3], 0D);
|
||||
assertEquals(expected.getY(), exact[index * 3 + 1], 0D);
|
||||
assertEquals(expected.getZ(), exact[index * 3 + 2], 0D);
|
||||
index++;
|
||||
}
|
||||
assertEquals(bake.count(), index);
|
||||
}
|
||||
|
||||
private static IrisObject object() {
|
||||
IrisObject object = new IrisObject(5, 5, 5);
|
||||
KeyedBlockState stone = new KeyedBlockState("minecraft:stone");
|
||||
|
||||
@@ -65,6 +65,7 @@ public class ObjectPlacementGoldenTest {
|
||||
private static final int SEEDS = 5;
|
||||
private static final long GOLDEN = 0x408f9d4113015897L;
|
||||
private static final long MARKER_GOLDEN = 0x60b4bbf1144b239cL;
|
||||
private static final long HIGH_VARIANT_GOLDEN = 0xf017622340ecac42L;
|
||||
|
||||
private static final List<String> PALETTE = List.of(
|
||||
"minecraft:stone",
|
||||
@@ -229,6 +230,34 @@ public class ObjectPlacementGoldenTest {
|
||||
assertEquals(Long.toHexString(MARKER_GOLDEN), Long.toHexString(combined));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void highVariantPlacementsMatchTheRecordedBlockStream() {
|
||||
Random random = new Random(1444L);
|
||||
IrisObjectRotation pine = rotation(new IrisAxisRotationClamp(true, false, -9D, 9D, 1D),
|
||||
new IrisAxisRotationClamp(true, false, 0D, 270D, 90D), new IrisAxisRotationClamp(true, false, -9D, 9D, 1D));
|
||||
long combined = 29L;
|
||||
int writes = 0;
|
||||
for (int index = 0; index < 16; index++) {
|
||||
IrisObject object = randomObject(random, index);
|
||||
object.setLoader(objectData);
|
||||
IrisObjectPlacement placement = randomPlacement(random).toPlacement("pine");
|
||||
placement.setRotation(pine);
|
||||
for (int seed = 0; seed < 150; seed++) {
|
||||
RNG rng = new RNG(index * 104_729L + seed);
|
||||
GoldenPlacer placer = new GoldenPlacer(engine, (seed & 1) == 0);
|
||||
int y = seed % 3 == 0 ? 90 + (seed & 7) : -1;
|
||||
int result = object.place(300 + seed, y, -400 + index * 7, placer, placement, rng, null, null, data);
|
||||
long hash = mix(placer.hash, result);
|
||||
hash = mix(hash, rng.nextLong());
|
||||
combined = mix(combined, hash);
|
||||
writes += placer.writes;
|
||||
}
|
||||
assertTrue(object.placementBakes.size() <= 32);
|
||||
}
|
||||
assertTrue(writes > 10_000);
|
||||
assertEquals(Long.toHexString(HIGH_VARIANT_GOLDEN), Long.toHexString(combined));
|
||||
}
|
||||
|
||||
private static long mix(long hash, long value) {
|
||||
long mixed = (hash ^ value) * 0x9E3779B97F4A7C15L;
|
||||
return mixed ^ (mixed >>> 29);
|
||||
|
||||
Reference in new issue
Block a user