Optimized tile render and added CRO tile support

- CROs now support tiles
  - CROCube refactored
- Test content:
  - Added sand and flower tiles
  - Removed grass blocks, added grass tiles
This commit is contained in:
OLEGSHA 2020-08-27 20:58:27 +03:00
parent 60fbfa9578
commit 79c7aa91f8
17 changed files with 312 additions and 105 deletions

View File

@ -19,13 +19,13 @@ package ru.windcorp.progressia.client.world;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import glm.mat._4.Mat4; import glm.mat._4.Mat4;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import glm.vec._3.i.Vec3i; import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.client.graphics.model.Model; 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.ShapeRenderHelper;
import ru.windcorp.progressia.client.graphics.model.StaticModel; import ru.windcorp.progressia.client.graphics.model.StaticModel;
import ru.windcorp.progressia.client.graphics.model.WorldRenderable; import ru.windcorp.progressia.client.graphics.model.WorldRenderable;
@ -114,12 +114,10 @@ public class ChunkRender {
} }
} }
for (ChunkRenderOptimizer optimizer : optimizers) { optimizers.stream()
Shape result = optimizer.endRender(); .map(ChunkRenderOptimizer::endRender)
if (result != null) { .filter(Objects::nonNull)
builder.addPart(result); .forEach(builder::addPart);
}
}
model = new StaticModel(builder); model = new StaticModel(builder);
needsUpdate = false; needsUpdate = false;
@ -131,55 +129,41 @@ public class ChunkRender {
Builder builder Builder builder
) { ) {
BlockRender block = getBlock(cursor); BlockRender block = getBlock(cursor);
int x = cursor.x;
int y = cursor.y;
int z = cursor.z;
if (block instanceof BlockRenderNone) { if (block instanceof BlockRenderNone) {
return; return;
} }
forwardBlockToOptimizers(block, x, y, z, optimizers); forwardBlockToOptimizers(block, cursor, optimizers);
if (!block.needsOwnRenderable()) { if (!block.needsOwnRenderable()) {
return; return;
} }
if (tryToCreateBlockRenderable(block, x, y, z, builder)) { addBlockRenderable(block, cursor, builder);
return;
}
addBlockRenderAsRenderable(block, x, y, z, builder);
} }
private void forwardBlockToOptimizers( private void forwardBlockToOptimizers(
BlockRender block, int x, int y, int z, BlockRender block, Vec3i cursor,
Collection<ChunkRenderOptimizer> optimizers Collection<ChunkRenderOptimizer> optimizers
) { ) {
optimizers.forEach(bro -> bro.processBlock(block, x, y, z)); optimizers.forEach(cro -> cro.processBlock(block, cursor));
} }
private boolean tryToCreateBlockRenderable( private void addBlockRenderable(
BlockRender block, int x, int y, int z, BlockRender block,
Vec3i cursor,
Builder builder Builder builder
) { ) {
WorldRenderable renderable = block.createRenderable(); WorldRenderable renderable = block.createRenderable();
if (renderable == null) { 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( builder.addPart(
block::render, renderable,
new Mat4().identity().translate(x, y, z) 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); 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( Vec3 offset = Vectors.grab3().set(
face.getVector().x, face.getVector().y, face.getVector().z face.getVector().x, face.getVector().y, face.getVector().z
); );

View File

@ -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.ShapeRenderHelper;
import ru.windcorp.progressia.client.graphics.model.WorldRenderable; import ru.windcorp.progressia.client.graphics.model.WorldRenderable;
import ru.windcorp.progressia.client.world.renders.cro.ChunkRenderOptimizer;
import ru.windcorp.progressia.common.util.Namespaced; import ru.windcorp.progressia.common.util.Namespaced;
public abstract class BlockRender extends Namespaced { public abstract class BlockRender extends Namespaced {
@ -38,10 +37,6 @@ public abstract class BlockRender extends Namespaced {
return null; return null;
} }
public boolean canBeOptimized(ChunkRenderOptimizer optimizer) {
return true;
}
public boolean needsOwnRenderable() { public boolean needsOwnRenderable() {
return true; return true;
} }

View File

@ -34,9 +34,7 @@ public class BlockRenders {
private static final AtlasGroup BLOCKS_ATLAS_GROUP = private static final AtlasGroup BLOCKS_ATLAS_GROUP =
new AtlasGroup("Blocks", 1 << 12); new AtlasGroup("Blocks", 1 << 12);
private static Texture grassTop = getTexture("grass_top"); private static Texture dirt = getTexture("dirt");
private static Texture grassSide = getTexture("grass_side");
private static Texture dirt = getTexture("grass_bottom");
private static Texture stone = getTexture("stone"); private static Texture stone = getTexture("stone");
private static Texture glass = getTexture("glass_clear"); private static Texture glass = getTexture("glass_clear");
private static Texture compass = getTexture("compass"); private static Texture compass = getTexture("compass");
@ -44,7 +42,6 @@ public class BlockRenders {
private BlockRenders() {} private BlockRenders() {}
public static void registerTest() { 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", "Dirt", dirt, dirt, dirt, dirt, dirt, dirt));
register(new BlockRenderOpaqueCube("Test", "Stone", stone, stone, stone, stone, stone, stone)); register(new BlockRenderOpaqueCube("Test", "Stone", stone, stone, stone, stone, stone, stone));

View File

@ -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;
}
}

View File

@ -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.model.WorldRenderable;
import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; 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.block.BlockFace;
import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.Vectors;
public class TileRenderSimple extends TileRender { public class TileRenderSimple extends TileRender implements OpaqueTile {
private final Texture texture; private final Texture texture;
@ -20,10 +21,16 @@ public class TileRenderSimple extends TileRender {
this.texture = texture; this.texture = texture;
} }
public Texture getTexture() { @Override
public Texture getTexture(BlockFace face) {
return texture; return texture;
} }
@Override
public boolean isOpaque(BlockFace face) {
return false;
}
@Override @Override
public WorldRenderable createRenderable(BlockFace face) { public WorldRenderable createRenderable(BlockFace face) {
ShapeRenderProgram program = WorldRenderProgram.getDefault(); ShapeRenderProgram program = WorldRenderProgram.getDefault();
@ -35,7 +42,8 @@ public class TileRenderSimple extends TileRender {
return new Shape( return new Shape(
Usage.STATIC, WorldRenderProgram.getDefault(), Usage.STATIC, WorldRenderProgram.getDefault(),
Faces.createBlockFace( Faces.createBlockFace(
program, texture, color, center, face, false program, getTexture(face), color,
center, face, false
) )
); );
} finally { } finally {
@ -43,5 +51,10 @@ public class TileRenderSimple extends TileRender {
Vectors.release(center); Vectors.release(center);
} }
} }
@Override
public boolean needsOwnRenderable() {
return false;
}
} }

View File

@ -37,7 +37,11 @@ public class TileRenders {
private TileRenders() {} private TileRenders() {}
public static void registerTest() { 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", "Stones", getTexture("stones")));
register(new TileRenderSimple("Test", "YellowFlowers", getTexture("yellow_flowers")));
register(new TileRenderSimple("Test", "Sand", getTexture("sand")));
} }
public static TileRender get(String name) { public static TileRender get(String name) {

View File

@ -17,15 +17,26 @@
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.client.world.renders.cro; 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.graphics.model.Shape;
import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.renders.BlockRender; 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 class ChunkRenderOptimizer {
public abstract void startRender(ChunkRender chunk); 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(); public abstract Shape endRender();

View File

@ -17,7 +17,9 @@
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.client.world.renders.cro; 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.BLOCKS_PER_CHUNK;
import static ru.windcorp.progressia.common.world.ChunkData.TILES_PER_FACE;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; 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.graphics.world.WorldRenderProgram;
import ru.windcorp.progressia.client.world.ChunkRender; import ru.windcorp.progressia.client.world.ChunkRender;
import ru.windcorp.progressia.client.world.renders.BlockRender; 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.block.BlockFace;
import ru.windcorp.progressia.common.util.Vectors;
public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer { public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer {
@ -43,12 +47,58 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer {
public boolean isBlockOpaque(); 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 static final Vec3 COLOR_MULTIPLIER = new Vec3(1, 1, 1);
private final OpaqueCube[][][] data = // private final OpaqueCube[][][] blocks =
new OpaqueCube[BLOCKS_PER_CHUNK] // new OpaqueCube[BLOCKS_PER_CHUNK]
[BLOCKS_PER_CHUNK] // [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 @Override
public void startRender(ChunkRender chunk) { public void startRender(ChunkRender chunk) {
@ -56,19 +106,43 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer {
} }
@Override @Override
public void processBlock(BlockRender block, int x, int y, int z) { public void processBlock(BlockRender block, Vec3i pos) {
if (!(block instanceof OpaqueCube)) return; if (!(block instanceof OpaqueCube)) return;
OpaqueCube opaqueCube = (OpaqueCube) block; OpaqueCube opaqueCube = (OpaqueCube) block;
addBlock(x, y, z, opaqueCube); addBlock(pos, opaqueCube);
} }
protected void addBlock(int x, int y, int z, OpaqueCube cube) { @Override
data[x][y][z] = cube; 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]; return data[cursor.x][cursor.y][cursor.z];
} }
protected FaceInfo getFace(Vec3i cursor, BlockFace face) {
return getBlock(cursor).faces[face.getId()];
}
@Override @Override
public Shape endRender() { 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.x = 0; cursor.x < BLOCKS_PER_CHUNK; ++cursor.x) {
for (cursor.y = 0; cursor.y < BLOCKS_PER_CHUNK; ++cursor.y) { for (cursor.y = 0; cursor.y < BLOCKS_PER_CHUNK; ++cursor.y) {
for (cursor.z = 0; cursor.z < BLOCKS_PER_CHUNK; ++cursor.z) { for (cursor.z = 0; cursor.z < BLOCKS_PER_CHUNK; ++cursor.z) {
OpaqueCube block = getBlock(cursor); processInnerFaces(cursor, shapeFaces::add);
processOuterFaces(cursor, shapeFaces::add);
if (block == null) continue;
processInnerFaces(block, cursor, shapeFaces::add);
processOuterFaces(block, cursor, shapeFaces::add);
} }
} }
} }
@ -98,63 +168,83 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer {
shapeFaces.toArray(new Face[shapeFaces.size()]) shapeFaces.toArray(new Face[shapeFaces.size()])
); );
} }
private void processInnerFaces(
OpaqueCube block,
Vec3i cursor,
Consumer<Face> 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( private void processOuterFaces(
OpaqueCube block,
Vec3i cursor, Vec3i cursor,
Consumer<Face> output Consumer<Face> output
) { ) {
Vec3 faceOrigin = Vectors.grab3();
Vec3 offset = Vectors.grab3();
for (BlockFace face : BlockFace.getFaces()) { for (BlockFace face : BlockFace.getFaces()) {
if (!shouldRenderOuterFace(cursor, face)) continue;
Texture texture = block.getTexture(face); faceOrigin.set(cursor.x, cursor.y, cursor.z);
if (texture == null) continue; 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( if (info.topOpaqueTile == FaceInfo.NO_OPAQUE_TILES) {
WorldRenderProgram.getDefault(), OpaqueCube block = getBlock(cursor).block;
texture,
COLOR_MULTIPLIER, if (block != null) {
new Vec3(cursor.x, cursor.y, cursor.z), addFace(
face, faceOrigin, face,
false 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<Face> 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()); cursor.add(face.getVector());
try { try {
// TODO handle neighboring chunks properly // TODO handle neighboring chunks properly
if (!isInBounds(cursor)) return true; if (!isInBounds(cursor)) return true;
OpaqueCube adjacent = getBlock(cursor); OpaqueCube adjacent = getBlock(cursor).block;
if (adjacent == null) return true; if (adjacent == null) return true;
if (adjacent.isOpaque(face)) return false; if (adjacent.isOpaque(face)) return false;
@ -166,6 +256,29 @@ public class ChunkRenderOptimizerCube extends ChunkRenderOptimizer {
} }
} }
private void processInnerFaces(
Vec3i cursor,
Consumer<Face> 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) { private boolean isInBounds(Vec3i cursor) {
return return
isInBounds(cursor.x) && isInBounds(cursor.x) &&

View File

@ -25,7 +25,6 @@ public class BlockDataRegistry {
private static final Map<String, BlockData> REGISTRY = new HashMap<>(); private static final Map<String, BlockData> REGISTRY = new HashMap<>();
static { static {
register(new BlockData("Test", "Grass"));
register(new BlockData("Test", "Dirt")); register(new BlockData("Test", "Dirt"));
register(new BlockData("Test", "Stone")); register(new BlockData("Test", "Stone"));
register(new BlockData("Test", "Air")); register(new BlockData("Test", "Air"));

View File

@ -25,7 +25,10 @@ public class TileDataRegistry {
private static final Map<String, TileData> REGISTRY = new HashMap<>(); private static final Map<String, TileData> REGISTRY = new HashMap<>();
static { static {
register(new TileData("Test", "Grass"));
register(new TileData("Test", "Stones")); register(new TileData("Test", "Stones"));
register(new TileData("Test", "YellowFlowers"));
register(new TileData("Test", "Sand"));
} }
public static TileData get(String name) { public static TileData get(String name) {

View File

@ -59,12 +59,14 @@ public class ChunkData {
} }
private void tmp_generate() { private void tmp_generate() {
BlockData grass = BlockDataRegistry.get("Test:Grass");
BlockData dirt = BlockDataRegistry.get("Test:Dirt"); BlockData dirt = BlockDataRegistry.get("Test:Dirt");
BlockData stone = BlockDataRegistry.get("Test:Stone"); BlockData stone = BlockDataRegistry.get("Test:Stone");
BlockData air = BlockDataRegistry.get("Test:Air"); BlockData air = BlockDataRegistry.get("Test:Air");
TileData grass = TileDataRegistry.get("Test:Grass");
TileData stones = TileDataRegistry.get("Test:Stones"); 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 aPoint = new Vec3i(5, 0, BLOCKS_PER_CHUNK + BLOCKS_PER_CHUNK/2);
Vec3i pos = new Vec3i(); 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); 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) { if (hash % 5 == 0) {
getTiles(pos, BlockFace.TOP).add(stones); 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 return
(blockInChunk.x == min && face == SOUTH ) || (blockInChunk.x == min && face == SOUTH ) ||
(blockInChunk.x == max && face == NORTH ) || (blockInChunk.x == max && face == NORTH ) ||
(blockInChunk.y == min && face == WEST ) || (blockInChunk.y == min && face == EAST ) ||
(blockInChunk.y == max && face == EAST ) || (blockInChunk.y == max && face == WEST ) ||
(blockInChunk.z == min && face == BOTTOM) || (blockInChunk.z == min && face == BOTTOM) ||
(blockInChunk.z == max && face == TOP ); (blockInChunk.z == max && face == TOP );
} }

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B