@Override public void generateChunk(CoreChunk chunk, Region chunkRegion) { FloraFacet facet = chunkRegion.getFacet(FloraFacet.class); WhiteNoise noise = new WhiteNoise(chunk.getPosition().hashCode()); Map<BaseVector3i, FloraType> entries = facet.getRelativeEntries(); // check if some other rasterizer has already placed something here entries.keySet().stream().filter(pos -> chunk.getBlock(pos).equals(air)).forEach(pos -> { FloraType type = entries.get(pos); List<Block> list = flora.get(type); int blockIdx = Math.abs(noise.intNoise(pos.x(), pos.y(), pos.z())) % list.size(); Block block = list.get(blockIdx); chunk.setBlock(pos, block); }); } }
@Override public void generateChunk(CoreChunk chunk, Region chunkRegion) { TreeFacet facet = chunkRegion.getFacet(TreeFacet.class); for (Map.Entry<BaseVector3i, TreeGenerator> entry : facet.getRelativeEntries().entrySet()) { BaseVector3i pos = entry.getKey(); TreeGenerator treeGen = entry.getValue(); int seed = relativeToWorld(facet, pos).hashCode(); Random random = new FastRandom(seed); treeGen.generate(blockManager, chunk, random, pos.x(), pos.y(), pos.z()); } }
@Test public void testHash() { // k = 59 // j = k+1 = 60 // i = (k+k^2)(1+k)^2 = not important for collision // hash = (k+k^2)(1+k)^2 + x(1+k)^2 + (1+k)y + z // hash = i + xj^2 + jy + z // with x := 0 // hash = i + jy + z // set i + jy + z = i + jy' + z' // jy + z = jy' + z' // set z' := z + j -> z'-z = j // jy = jy' + j -> y' = y - 1 Vector3i a = new Vector3i(0, 10, 10); Vector3i b = new Vector3i(0, 9, 70); assertFalse(a.hashCode() == b.hashCode()); assertTrue(new Vector3i(0, 10, 10).hashCode() == new Vector3i(0, 10, 10).hashCode()); assertTrue(new Vector3i(-100, 10, 10).hashCode() == new Vector3i(-100, 10, 10).hashCode()); assertTrue(new Vector3i(0, -5, -5).hashCode() == new Vector3i(0, -5, -5).hashCode()); assertFalse(new Vector3i(1, 10, 10).hashCode() == new Vector3i(0, 10, 10).hashCode()); assertFalse(new Vector3i(-101, 10, 10).hashCode() == new Vector3i(-100, 10, 10).hashCode()); assertFalse(new Vector3i(0, -1, -5).hashCode() == new Vector3i(0, -5, -5).hashCode()); }
@Test public void testHashCollisions() { int range = 50; Set<Integer> alreadyUsedHashes = new HashSet<>(); for (int x = -range; x < range; ++x) { for (int y = -range; y < range; ++y) { for (int z = -range; z < range; ++z) { int hash = new Vector3i(x, y, z).hashCode(); if (alreadyUsedHashes.contains(hash)) { fail(String.format("duplicate hash %d at: %d,%d,%d", hash, x, y, z)); } else { alreadyUsedHashes.add(hash); } } } } } }