diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index dea8fa2..122ad19 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -19,13 +19,13 @@ package ru.windcorp.progressia.client.world; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import glm.mat._4.Mat4; import glm.vec._3.Vec3; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.graphics.model.Model; -import ru.windcorp.progressia.client.graphics.model.Shape; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.graphics.model.StaticModel; import ru.windcorp.progressia.client.graphics.model.WorldRenderable; @@ -114,12 +114,10 @@ public class ChunkRender { } } - for (ChunkRenderOptimizer optimizer : optimizers) { - Shape result = optimizer.endRender(); - if (result != null) { - builder.addPart(result); - } - } + optimizers.stream() + .map(ChunkRenderOptimizer::endRender) + .filter(Objects::nonNull) + .forEach(builder::addPart); model = new StaticModel(builder); needsUpdate = false; @@ -131,55 +129,41 @@ public class ChunkRender { Builder builder ) { BlockRender block = getBlock(cursor); - int x = cursor.x; - int y = cursor.y; - int z = cursor.z; if (block instanceof BlockRenderNone) { return; } - forwardBlockToOptimizers(block, x, y, z, optimizers); + forwardBlockToOptimizers(block, cursor, optimizers); if (!block.needsOwnRenderable()) { return; } - if (tryToCreateBlockRenderable(block, x, y, z, builder)) { - return; - } - - addBlockRenderAsRenderable(block, x, y, z, builder); + addBlockRenderable(block, cursor, builder); } private void forwardBlockToOptimizers( - BlockRender block, int x, int y, int z, + BlockRender block, Vec3i cursor, Collection optimizers ) { - optimizers.forEach(bro -> bro.processBlock(block, x, y, z)); + optimizers.forEach(cro -> cro.processBlock(block, cursor)); } - - private boolean tryToCreateBlockRenderable( - BlockRender block, int x, int y, int z, + + private void addBlockRenderable( + BlockRender block, + Vec3i cursor, Builder builder ) { WorldRenderable renderable = block.createRenderable(); if (renderable == null) { - return false; + renderable = block::render; } - builder.addPart(renderable, new Mat4().identity().translate(x, y, z)); - return true; - } - - private void addBlockRenderAsRenderable( - BlockRender block, int x, int y, int z, - Builder builder - ) { builder.addPart( - block::render, - new Mat4().identity().translate(x, y, z) + renderable, + new Mat4().identity().translate(cursor.x, cursor.y, cursor.z) ); } @@ -230,6 +214,13 @@ public class ChunkRender { Vec3 pos = Vectors.grab3().set(cursor.x, cursor.y, cursor.z); + optimizers.forEach(cro -> cro.processTile(tile, cursor, face)); + + if (!tile.needsOwnRenderable()) { + Vectors.release(pos); + return; + } + Vec3 offset = Vectors.grab3().set( face.getVector().x, face.getVector().y, face.getVector().z ); diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRender.java b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRender.java index 7d4f218..b0635d1 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRender.java @@ -19,7 +19,6 @@ package ru.windcorp.progressia.client.world.renders; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; import ru.windcorp.progressia.client.graphics.model.WorldRenderable; -import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizer; import ru.windcorp.progressia.common.util.Namespaced; public abstract class BlockRender extends Namespaced { @@ -38,10 +37,6 @@ public abstract class BlockRender extends Namespaced { return null; } - public boolean canBeOptimized(ChunkRenderOptimizer optimizer) { - return true; - } - public boolean needsOwnRenderable() { return true; } diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenders.java b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenders.java index cc1cd6f..5c48a36 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenders.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenders.java @@ -34,9 +34,7 @@ public class BlockRenders { private static final AtlasGroup BLOCKS_ATLAS_GROUP = new AtlasGroup("Blocks", 1 << 12); - private static Texture grassTop = getTexture("grass_top"); - private static Texture grassSide = getTexture("grass_side"); - private static Texture dirt = getTexture("grass_bottom"); + private static Texture dirt = getTexture("dirt"); private static Texture stone = getTexture("stone"); private static Texture glass = getTexture("glass_clear"); private static Texture compass = getTexture("compass"); @@ -44,7 +42,6 @@ public class BlockRenders { private BlockRenders() {} public static void registerTest() { - register(new BlockRenderOpaqueCube("Test", "Grass", grassTop, dirt, grassSide, grassSide, grassSide, grassSide)); register(new BlockRenderOpaqueCube("Test", "Dirt", dirt, dirt, dirt, dirt, dirt, dirt)); register(new BlockRenderOpaqueCube("Test", "Stone", stone, stone, stone, stone, stone, stone)); diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenderGrass.java b/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenderGrass.java new file mode 100644 index 0000000..05fbed0 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenderGrass.java @@ -0,0 +1,65 @@ +package ru.windcorp.progressia.client.world.renders; + +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.graphics.backend.Usage; +import ru.windcorp.progressia.client.graphics.model.Faces; +import ru.windcorp.progressia.client.graphics.model.Shape; +import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram; +import ru.windcorp.progressia.client.graphics.model.WorldRenderable; +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizerCube.OpaqueTile; +import ru.windcorp.progressia.common.block.BlockFace; +import ru.windcorp.progressia.common.util.Vectors; + +public class TileRenderGrass extends TileRender implements OpaqueTile { + + private final Texture topTexture; + private final Texture sideTexture; + + public TileRenderGrass( + String namespace, String name, + Texture top, Texture side + ) { + super(namespace, name); + this.topTexture = top; + this.sideTexture = side; + } + + @Override + public Texture getTexture(BlockFace face) { + return (face == BlockFace.TOP) ? topTexture : sideTexture; + } + + @Override + public boolean isOpaque(BlockFace face) { + return face == BlockFace.TOP; + } + + @Override + public WorldRenderable createRenderable(BlockFace face) { + ShapeRenderProgram program = WorldRenderProgram.getDefault(); + + Vec3 color = Vectors.grab3().set(1, 1, 1); + Vec3 center = Vectors.grab3().set(0, 0, 0); + + try { + return new Shape( + Usage.STATIC, WorldRenderProgram.getDefault(), + Faces.createBlockFace( + program, getTexture(face), color, + center, face, false + ) + ); + } finally { + Vectors.release(color); + Vectors.release(center); + } + } + + @Override + public boolean needsOwnRenderable() { + return false; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenderSimple.java b/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenderSimple.java index 61dbf52..889be5b 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenderSimple.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenderSimple.java @@ -8,10 +8,11 @@ import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram; import ru.windcorp.progressia.client.graphics.model.WorldRenderable; import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; +import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizerCube.OpaqueTile; import ru.windcorp.progressia.common.block.BlockFace; import ru.windcorp.progressia.common.util.Vectors; -public class TileRenderSimple extends TileRender { +public class TileRenderSimple extends TileRender implements OpaqueTile { private final Texture texture; @@ -20,10 +21,16 @@ public class TileRenderSimple extends TileRender { this.texture = texture; } - public Texture getTexture() { + @Override + public Texture getTexture(BlockFace face) { return texture; } + @Override + public boolean isOpaque(BlockFace face) { + return false; + } + @Override public WorldRenderable createRenderable(BlockFace face) { ShapeRenderProgram program = WorldRenderProgram.getDefault(); @@ -35,7 +42,8 @@ public class TileRenderSimple extends TileRender { return new Shape( Usage.STATIC, WorldRenderProgram.getDefault(), Faces.createBlockFace( - program, texture, color, center, face, false + program, getTexture(face), color, + center, face, false ) ); } finally { @@ -43,5 +51,10 @@ public class TileRenderSimple extends TileRender { Vectors.release(center); } } + + @Override + public boolean needsOwnRenderable() { + return false; + } } diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenders.java b/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenders.java index 3c464ee..94a995c 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenders.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/TileRenders.java @@ -37,7 +37,11 @@ public class TileRenders { private TileRenders() {} public static void registerTest() { + register(new TileRenderGrass("Test", "Grass", getTexture("grass_top"), getTexture("grass_side"))); + register(new TileRenderSimple("Test", "Stones", getTexture("stones"))); + register(new TileRenderSimple("Test", "YellowFlowers", getTexture("yellow_flowers"))); + register(new TileRenderSimple("Test", "Sand", getTexture("sand"))); } public static TileRender get(String name) { diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizer.java b/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizer.java index abea2af..79153a2 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizer.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizer.java @@ -17,15 +17,26 @@ *******************************************************************************/ package ru.windcorp.progressia.client.world.renders.cro; +import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.graphics.model.Shape; import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.client.world.renders.BlockRender; +import ru.windcorp.progressia.client.world.renders.TileRender; +import ru.windcorp.progressia.common.block.BlockFace; public abstract class ChunkRenderOptimizer { public abstract void startRender(ChunkRender chunk); - public abstract void processBlock(BlockRender block, int x, int y, int z); + public abstract void processBlock( + BlockRender block, + Vec3i posInChunk + ); + + public abstract void processTile( + TileRender tile, + Vec3i posInChunk, BlockFace face + ); public abstract Shape endRender(); diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizerCube.java b/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizerCube.java index 3048a85..a720d75 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizerCube.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/cro/ChunkRenderOptimizerCube.java @@ -17,7 +17,9 @@ *******************************************************************************/ package ru.windcorp.progressia.client.world.renders.cro; +import static ru.windcorp.progressia.common.block.BlockFace.BLOCK_FACE_COUNT; import static ru.windcorp.progressia.common.world.ChunkData.BLOCKS_PER_CHUNK; +import static ru.windcorp.progressia.common.world.ChunkData.TILES_PER_FACE; import java.util.ArrayList; import java.util.Collection; @@ -33,7 +35,9 @@ import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.client.world.renders.BlockRender; +import ru.windcorp.progressia.client.world.renders.TileRender; import ru.windcorp.progressia.common.block.BlockFace; +import ru.windcorp.progressia.common.util.Vectors; public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer { @@ -43,12 +47,58 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer { public boolean isBlockOpaque(); } + public static interface OpaqueTile { + public Texture getTexture(BlockFace face); + public boolean isOpaque(BlockFace face); + } + + private static class BlockInfo { + OpaqueCube block; + final FaceInfo[] faces = new FaceInfo[BLOCK_FACE_COUNT]; + + { + for (int i = 0; i < faces.length; ++i) { + faces[i] = new FaceInfo(); + } + } + } + + private static class FaceInfo { + static final int NO_OPAQUE_TILES = -1; + + int topOpaqueTile = NO_OPAQUE_TILES; + final OpaqueTile[] tiles = new OpaqueTile[TILES_PER_FACE]; + int tileCount = 0; + } + private static final Vec3 COLOR_MULTIPLIER = new Vec3(1, 1, 1); - private final OpaqueCube[][][] data = - new OpaqueCube[BLOCKS_PER_CHUNK] - [BLOCKS_PER_CHUNK] - [BLOCKS_PER_CHUNK]; +// private final OpaqueCube[][][] blocks = +// new OpaqueCube[BLOCKS_PER_CHUNK] +// [BLOCKS_PER_CHUNK] +// [BLOCKS_PER_CHUNK]; +// +// private final OpaqueTile[][][][][] tiles = +// new OpaqueTile[BLOCKS_PER_CHUNK] +// [BLOCKS_PER_CHUNK] +// [BLOCKS_PER_CHUNK] +// [BLOCK_FACE_COUNT] +// [TILES_PER_FACE]; + + private final BlockInfo[][][] data = + new BlockInfo[BLOCKS_PER_CHUNK] + [BLOCKS_PER_CHUNK] + [BLOCKS_PER_CHUNK]; + + { + for (int x = 0; x < BLOCKS_PER_CHUNK; ++x) { + for (int y = 0; y < BLOCKS_PER_CHUNK; ++y) { + for (int z = 0; z < BLOCKS_PER_CHUNK; ++z) { + data[x][y][z] = new BlockInfo(); + } + } + } + } @Override public void startRender(ChunkRender chunk) { @@ -56,19 +106,43 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer { } @Override - public void processBlock(BlockRender block, int x, int y, int z) { + public void processBlock(BlockRender block, Vec3i pos) { if (!(block instanceof OpaqueCube)) return; OpaqueCube opaqueCube = (OpaqueCube) block; - addBlock(x, y, z, opaqueCube); + addBlock(pos, opaqueCube); } - protected void addBlock(int x, int y, int z, OpaqueCube cube) { - data[x][y][z] = cube; + @Override + public void processTile(TileRender tile, Vec3i pos, BlockFace face) { + if (!(tile instanceof OpaqueTile)) return; + OpaqueTile opaqueTile = (OpaqueTile) tile; + addTile(pos, face, opaqueTile); + } + + protected void addBlock(Vec3i pos, OpaqueCube cube) { + getBlock(pos).block = cube; } - protected OpaqueCube getBlock(Vec3i cursor) { + private void addTile(Vec3i pos, BlockFace face, OpaqueTile opaqueTile) { + FaceInfo faceInfo = getFace(pos, face); + + int index = faceInfo.tileCount; + faceInfo.tileCount++; + + faceInfo.tiles[index] = opaqueTile; + + if (opaqueTile.isOpaque(face)) { + faceInfo.topOpaqueTile = index; + } + } + + protected BlockInfo getBlock(Vec3i cursor) { return data[cursor.x][cursor.y][cursor.z]; } + + protected FaceInfo getFace(Vec3i cursor, BlockFace face) { + return getBlock(cursor).faces[face.getId()]; + } @Override public Shape endRender() { @@ -82,12 +156,8 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer { for (cursor.x = 0; cursor.x < BLOCKS_PER_CHUNK; ++cursor.x) { for (cursor.y = 0; cursor.y < BLOCKS_PER_CHUNK; ++cursor.y) { for (cursor.z = 0; cursor.z < BLOCKS_PER_CHUNK; ++cursor.z) { - OpaqueCube block = getBlock(cursor); - - if (block == null) continue; - - processInnerFaces(block, cursor, shapeFaces::add); - processOuterFaces(block, cursor, shapeFaces::add); + processInnerFaces(cursor, shapeFaces::add); + processOuterFaces(cursor, shapeFaces::add); } } } @@ -98,63 +168,83 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer { shapeFaces.toArray(new Face[shapeFaces.size()]) ); } - - private void processInnerFaces( - OpaqueCube block, - Vec3i cursor, - Consumer output - ) { - if (block.isBlockOpaque()) return; - - for (BlockFace face : BlockFace.getFaces()) { - - Texture texture = block.getTexture(face); - if (texture == null) continue; - - output.accept(Faces.createBlockFace( - WorldRenderProgram.getDefault(), - texture, - COLOR_MULTIPLIER, - new Vec3(cursor.x, cursor.y, cursor.z), - face, - true - )); - - } - } private void processOuterFaces( - OpaqueCube block, Vec3i cursor, Consumer output ) { + Vec3 faceOrigin = Vectors.grab3(); + Vec3 offset = Vectors.grab3(); + for (BlockFace face : BlockFace.getFaces()) { + if (!shouldRenderOuterFace(cursor, face)) continue; - Texture texture = block.getTexture(face); - if (texture == null) continue; + faceOrigin.set(cursor.x, cursor.y, cursor.z); + offset + .set(face.getVector().x, face.getVector().y, face.getVector().z) + .mul(1f / 128); - if (!shouldRenderFace(cursor, face)) continue; + FaceInfo info = getFace(cursor, face); - output.accept(Faces.createBlockFace( - WorldRenderProgram.getDefault(), - texture, - COLOR_MULTIPLIER, - new Vec3(cursor.x, cursor.y, cursor.z), - face, - false - )); + if (info.topOpaqueTile == FaceInfo.NO_OPAQUE_TILES) { + OpaqueCube block = getBlock(cursor).block; + + if (block != null) { + addFace( + faceOrigin, face, + getBlock(cursor).block.getTexture(face), + output + ); + + faceOrigin.add(offset); + } + } + int startLayer = info.topOpaqueTile; + if (startLayer == FaceInfo.NO_OPAQUE_TILES) { + startLayer = 0; + } + + for (int layer = startLayer; layer < info.tileCount; ++layer) { + addFace( + faceOrigin, face, + info.tiles[layer].getTexture(face), + output + ); + + faceOrigin.add(offset); + } } + + Vectors.release(offset); + Vectors.release(faceOrigin); } - private boolean shouldRenderFace(Vec3i cursor, BlockFace face) { + private void addFace( + Vec3 cursor, BlockFace face, + Texture texture, + Consumer output + ) { + if (texture == null) return; + + output.accept(Faces.createBlockFace( + WorldRenderProgram.getDefault(), + texture, + COLOR_MULTIPLIER, + new Vec3(cursor), + face, + false + )); + } + + private boolean shouldRenderOuterFace(Vec3i cursor, BlockFace face) { cursor.add(face.getVector()); try { // TODO handle neighboring chunks properly if (!isInBounds(cursor)) return true; - OpaqueCube adjacent = getBlock(cursor); + OpaqueCube adjacent = getBlock(cursor).block; if (adjacent == null) return true; if (adjacent.isOpaque(face)) return false; @@ -166,6 +256,29 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer { } } + private void processInnerFaces( + Vec3i cursor, + Consumer output + ) { +// if (block.isBlockOpaque()) return; +// +// for (BlockFace face : BlockFace.getFaces()) { +// +// Texture texture = block.getTexture(face); +// if (texture == null) continue; +// +// output.accept(Faces.createBlockFace( +// WorldRenderProgram.getDefault(), +// texture, +// COLOR_MULTIPLIER, +// new Vec3(cursor.x, cursor.y, cursor.z), +// face, +// true +// )); +// +// } + } + private boolean isInBounds(Vec3i cursor) { return isInBounds(cursor.x) && diff --git a/src/main/java/ru/windcorp/progressia/common/block/BlockDataRegistry.java b/src/main/java/ru/windcorp/progressia/common/block/BlockDataRegistry.java index 7aaafef..d7e67a4 100644 --- a/src/main/java/ru/windcorp/progressia/common/block/BlockDataRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/block/BlockDataRegistry.java @@ -25,7 +25,6 @@ public class BlockDataRegistry { private static final Map REGISTRY = new HashMap<>(); static { - register(new BlockData("Test", "Grass")); register(new BlockData("Test", "Dirt")); register(new BlockData("Test", "Stone")); register(new BlockData("Test", "Air")); diff --git a/src/main/java/ru/windcorp/progressia/common/block/TileDataRegistry.java b/src/main/java/ru/windcorp/progressia/common/block/TileDataRegistry.java index 9e9650f..2769546 100644 --- a/src/main/java/ru/windcorp/progressia/common/block/TileDataRegistry.java +++ b/src/main/java/ru/windcorp/progressia/common/block/TileDataRegistry.java @@ -25,7 +25,10 @@ public class TileDataRegistry { private static final Map REGISTRY = new HashMap<>(); static { + register(new TileData("Test", "Grass")); register(new TileData("Test", "Stones")); + register(new TileData("Test", "YellowFlowers")); + register(new TileData("Test", "Sand")); } public static TileData get(String name) { diff --git a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java index 58671df..6e7cfed 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/ChunkData.java @@ -59,12 +59,14 @@ public class ChunkData { } private void tmp_generate() { - BlockData grass = BlockDataRegistry.get("Test:Grass"); BlockData dirt = BlockDataRegistry.get("Test:Dirt"); BlockData stone = BlockDataRegistry.get("Test:Stone"); BlockData air = BlockDataRegistry.get("Test:Air"); - + + TileData grass = TileDataRegistry.get("Test:Grass"); TileData stones = TileDataRegistry.get("Test:Stones"); + TileData flowers = TileDataRegistry.get("Test:YellowFlowers"); + TileData sand = TileDataRegistry.get("Test:Sand"); Vec3i aPoint = new Vec3i(5, 0, BLOCKS_PER_CHUNK + BLOCKS_PER_CHUNK/2); Vec3i pos = new Vec3i(); @@ -95,12 +97,26 @@ public class ChunkData { for (pos.z = BLOCKS_PER_CHUNK - 1; pos.z >= 0 && getBlock(pos) == air; --pos.z); - setBlock(pos, grass); + getTiles(pos, BlockFace.TOP).add(grass); + for (BlockFace face : BlockFace.getFaces()) { + if (face.getVector().z != 0) continue; + getTiles(pos, face).add(grass); + } - int hash = x*x * 13 ^ y*y * 37 ^ pos.z*pos.z * 129; + int hash = x*x * 19 ^ y*y * 41 ^ pos.z*pos.z * 147; + if (hash % 5 == 0) { + getTiles(pos, BlockFace.TOP).add(sand); + } + + hash = x*x * 13 ^ y*y * 37 ^ pos.z*pos.z * 129; if (hash % 5 == 0) { getTiles(pos, BlockFace.TOP).add(stones); } + + hash = x*x * 17 ^ y*y * 39 ^ pos.z*pos.z * 131; + if (hash % 9 == 0) { + getTiles(pos, BlockFace.TOP).add(flowers); + } } } } @@ -218,8 +234,8 @@ public class ChunkData { return (blockInChunk.x == min && face == SOUTH ) || (blockInChunk.x == max && face == NORTH ) || - (blockInChunk.y == min && face == WEST ) || - (blockInChunk.y == max && face == EAST ) || + (blockInChunk.y == min && face == EAST ) || + (blockInChunk.y == max && face == WEST ) || (blockInChunk.z == min && face == BOTTOM) || (blockInChunk.z == max && face == TOP ); } diff --git a/src/main/resources/assets/textures/blocks/grass_bottom.png b/src/main/resources/assets/textures/blocks/dirt.png similarity index 100% rename from src/main/resources/assets/textures/blocks/grass_bottom.png rename to src/main/resources/assets/textures/blocks/dirt.png diff --git a/src/main/resources/assets/textures/blocks/grass_side.png b/src/main/resources/assets/textures/blocks/grass_side.png deleted file mode 100644 index f57c49f..0000000 Binary files a/src/main/resources/assets/textures/blocks/grass_side.png and /dev/null differ diff --git a/src/main/resources/assets/textures/tiles/grass_side.png b/src/main/resources/assets/textures/tiles/grass_side.png new file mode 100644 index 0000000..15aeb2d Binary files /dev/null and b/src/main/resources/assets/textures/tiles/grass_side.png differ diff --git a/src/main/resources/assets/textures/blocks/grass_top.png b/src/main/resources/assets/textures/tiles/grass_top.png similarity index 100% rename from src/main/resources/assets/textures/blocks/grass_top.png rename to src/main/resources/assets/textures/tiles/grass_top.png diff --git a/src/main/resources/assets/textures/tiles/sand.png b/src/main/resources/assets/textures/tiles/sand.png new file mode 100644 index 0000000..69b833a Binary files /dev/null and b/src/main/resources/assets/textures/tiles/sand.png differ diff --git a/src/main/resources/assets/textures/tiles/yellow_flowers.png b/src/main/resources/assets/textures/tiles/yellow_flowers.png new file mode 100644 index 0000000..51eccb0 Binary files /dev/null and b/src/main/resources/assets/textures/tiles/yellow_flowers.png differ