From d58d028e1c9b7bd5c87d1e007f17adf0e9c10b24 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Tue, 25 Aug 2020 21:11:55 +0300 Subject: [PATCH] Begun refactoring chunk render. Not implemented properly. --- .../client/graphics/model/Faces.java | 15 ++--- .../progressia/client/world/ChunkRender.java | 41 ++++-------- .../client/world/renders/BlockRender.java | 25 +++---- .../client/world/renders/BlockRenderNone.java | 5 ++ .../{bro => }/BlockRenderOpaqueCube.java | 32 ++++++++- .../renders/BlockRenderTexturedCube.java | 12 ++-- .../renders/BlockRenderTransparentCube.java | 23 +++++++ .../client/world/renders/BlockRenders.java | 1 - ...zer.java => BlockRenderCubeOptimizer.java} | 65 ++++++++++--------- .../bro/BlockRenderOptimizerGenerators.java | 2 +- .../progressia/common/block/BlockFace.java | 52 ++++++++++++++- .../common/block/BlockRelation.java | 62 ++++++++++++++++++ 12 files changed, 245 insertions(+), 90 deletions(-) rename src/main/java/ru/windcorp/progressia/client/world/renders/{bro => }/BlockRenderOpaqueCube.java (69%) rename src/main/java/ru/windcorp/progressia/client/world/renders/bro/{BlockRenderOpaqueCubeOptimizer.java => BlockRenderCubeOptimizer.java} (76%) create mode 100644 src/main/java/ru/windcorp/progressia/common/block/BlockRelation.java diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java b/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java index b3e2a14..e62de8c 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/model/Faces.java @@ -77,8 +77,7 @@ public class Faces { Vec3 blockCenter, BlockFace face ) { - switch (face) { - case TOP: + if (face == BlockFace.TOP) { return createRectangle( program, texture, colorMultiplier, @@ -86,7 +85,7 @@ public class Faces { new Vec3( 0, -1, 0), new Vec3(+1, 0, 0) ); - case BOTTOM: + } else if (face == BlockFace.BOTTOM) { return createRectangle( program, texture, colorMultiplier, @@ -94,7 +93,7 @@ public class Faces { new Vec3( 0, +1, 0), new Vec3(+1, 0, 0) ); - case NORTH: + } else if (face == BlockFace.NORTH) { return createRectangle( program, texture, colorMultiplier, @@ -102,7 +101,7 @@ public class Faces { new Vec3( 0, +1, 0), new Vec3( 0, 0, +1) ); - case SOUTH: + } else if (face == BlockFace.SOUTH) { return createRectangle( program, texture, colorMultiplier, @@ -110,7 +109,7 @@ public class Faces { new Vec3( 0, -1, 0), new Vec3( 0, 0, +1) ); - case EAST: + } else if (face == BlockFace.EAST) { return createRectangle( program, texture, colorMultiplier, @@ -118,7 +117,7 @@ public class Faces { new Vec3(+1, 0, 0), new Vec3( 0, 0, +1) ); - case WEST: + } else if (face == BlockFace.WEST) { return createRectangle( program, texture, colorMultiplier, @@ -126,7 +125,7 @@ public class Faces { new Vec3(-1, 0, 0), new Vec3( 0, 0, +1) ); - default: + } else { throw new NullPointerException("face"); } } 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 c1dbd3d..ff117fc 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -17,8 +17,8 @@ *******************************************************************************/ package ru.windcorp.progressia.client.world; -import java.util.HashMap; -import java.util.Map; +import java.util.Collection; +import java.util.stream.Collectors; import glm.mat._4.Mat4; import ru.windcorp.progressia.client.graphics.model.Model; @@ -87,16 +87,12 @@ public class ChunkRender { } private void buildModel() { - Map optimizers = new HashMap<>(); + Collection optimizers = + BlockRenderOptimizerGenerators.getAll().stream() + .map(BlockRenderOptimizerGenerator::createOptimizer) + .collect(Collectors.toList()); - for ( - BlockRenderOptimizerGenerator generator : - BlockRenderOptimizerGenerators.getAll() - ) { - BlockRenderOptimizer optimizer = generator.createOptimizer(); - optimizers.put(generator.getId(), optimizer); - optimizer.startRender(this); - } + optimizers.forEach(bro -> bro.startRender(this)); StaticModel.Builder builder = StaticModel.builder(); @@ -110,7 +106,9 @@ public class ChunkRender { continue; } - if (tryToForwardToOptimizers(block, x, y, z, optimizers)) { + forwardToOptimizers(block, x, y, z, optimizers); + + if (!block.needsOwnRenderable()) { continue; } @@ -123,7 +121,7 @@ public class ChunkRender { } } - for (BlockRenderOptimizer optimizer : optimizers.values()) { + for (BlockRenderOptimizer optimizer : optimizers) { Shape result = optimizer.endRender(); if (result != null) { builder.addPart(result); @@ -134,22 +132,11 @@ public class ChunkRender { needsUpdate = false; } - private boolean tryToForwardToOptimizers( + private void forwardToOptimizers( BlockRender block, int x, int y, int z, - Map optimizers + Collection optimizers ) { - if (!block.isOptimized()) { - return false; - } - BlockRenderOptimizer optimizer = optimizers.get(block.getOptimizer()); - - if (optimizer == null) { - return false; - } - - optimizer.processBlock(block, x, y, z); - - return true; + optimizers.forEach(bro -> bro.processBlock(block, x, y, z)); } private boolean tryToCreateRenderable( 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 775c384..e3791c2 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,36 +19,31 @@ 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.bro.BlockRenderOptimizer; import ru.windcorp.progressia.common.util.Namespaced; public abstract class BlockRender extends Namespaced { - private String optimizer = null; - public BlockRender(String namespace, String name) { super(namespace, name); } - - public String getOptimizer() { - return optimizer; - } - - public boolean isOptimized() { - return getOptimizer() != null; - } - - public void setOptimizer(String optimizer) { - this.optimizer = optimizer; - } public void render(ShapeRenderHelper renderer) { throw new UnsupportedOperationException( - "BlockRender.render() not implemented" + "BlockRender.render() not implemented in " + this ); } public WorldRenderable createRenderable() { return null; } + + public boolean canBeOptimized(BlockRenderOptimizer optimizer) { + return true; + } + + public boolean needsOwnRenderable() { + return true; + } } diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderNone.java b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderNone.java index 6968341..01a3dee 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderNone.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderNone.java @@ -30,5 +30,10 @@ public class BlockRenderNone extends BlockRender { public WorldRenderable createRenderable() { return EmptyModel.getInstance(); } + + @Override + public boolean needsOwnRenderable() { + return false; + } } diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOpaqueCube.java b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderOpaqueCube.java similarity index 69% rename from src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOpaqueCube.java rename to src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderOpaqueCube.java index 56465a9..87a77e7 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOpaqueCube.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderOpaqueCube.java @@ -15,10 +15,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . *******************************************************************************/ -package ru.windcorp.progressia.client.world.renders.bro; +package ru.windcorp.progressia.client.world.renders; import ru.windcorp.progressia.client.graphics.texture.Texture; -import ru.windcorp.progressia.client.world.renders.BlockRenderTexturedCube; +import ru.windcorp.progressia.common.block.BlockFace; public class BlockRenderOpaqueCube extends BlockRenderTexturedCube { @@ -34,7 +34,33 @@ public class BlockRenderOpaqueCube extends BlockRenderTexturedCube { northTexture, southTexture, eastTexture, westTexture ); - setOptimizer("Default:OpaqueCube"); + } + + public BlockRenderOpaqueCube( + String namespace, String name, + Texture texture + ) { + this( + namespace, name, + texture, texture, + texture, texture, + texture, texture + ); + } + + @Override + public boolean isOpaque(BlockFace face) { + return true; + } + + @Override + public boolean isBlockOpaque() { + return true; + } + + @Override + public boolean needsOwnRenderable() { + return false; } } diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTexturedCube.java b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTexturedCube.java index a774d1a..d09ad24 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTexturedCube.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTexturedCube.java @@ -19,18 +19,21 @@ package ru.windcorp.progressia.client.world.renders; import static ru.windcorp.progressia.common.block.BlockFace.*; -import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; import ru.windcorp.progressia.client.graphics.model.Shapes; 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.bro.BlockRenderCubeOptimizer.OpaqueCube; import ru.windcorp.progressia.common.block.BlockFace; -public abstract class BlockRenderTexturedCube extends BlockRender { +public abstract class BlockRenderTexturedCube +extends BlockRender +implements OpaqueCube { - private final EnumMap textures = - new EnumMap<>(BlockFace.class); + private final Map textures = new HashMap<>(); public BlockRenderTexturedCube( String namespace, String name, @@ -48,6 +51,7 @@ public abstract class BlockRenderTexturedCube extends BlockRender { textures.put(WEST, westTexture); } + @Override public Texture getTexture(BlockFace face) { return textures.get(face); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTransparentCube.java b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTransparentCube.java index b9744e1..1cc9e0e 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTransparentCube.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/BlockRenderTransparentCube.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.client.world.renders; import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.common.block.BlockFace; public class BlockRenderTransparentCube extends BlockRenderTexturedCube { @@ -34,5 +35,27 @@ public class BlockRenderTransparentCube extends BlockRenderTexturedCube { eastTexture, westTexture ); } + + public BlockRenderTransparentCube( + String namespace, String name, + Texture texture + ) { + this( + namespace, name, + texture, texture, + texture, texture, + texture, texture + ); + } + + @Override + public boolean isOpaque(BlockFace face) { + return false; + } + + @Override + public boolean isBlockOpaque() { + return false; + } } 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 78a91a8..cc1cd6f 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 @@ -24,7 +24,6 @@ import ru.windcorp.progressia.client.graphics.texture.Atlases; import ru.windcorp.progressia.client.graphics.texture.Atlases.AtlasGroup; import ru.windcorp.progressia.client.graphics.texture.SimpleTexture; import ru.windcorp.progressia.client.graphics.texture.Texture; -import ru.windcorp.progressia.client.world.renders.bro.BlockRenderOpaqueCube; import ru.windcorp.progressia.common.resource.ResourceManager; public class BlockRenders { diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOpaqueCubeOptimizer.java b/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderCubeOptimizer.java similarity index 76% rename from src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOpaqueCubeOptimizer.java rename to src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderCubeOptimizer.java index 6c90b82..5743254 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOpaqueCubeOptimizer.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderCubeOptimizer.java @@ -34,7 +34,13 @@ import ru.windcorp.progressia.client.world.renders.BlockRender; import ru.windcorp.progressia.common.block.BlockFace; import ru.windcorp.progressia.common.world.ChunkData; -public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer { +public class BlockRenderCubeOptimizer extends BlockRenderOptimizer { + + public static interface OpaqueCube { + public Texture getTexture(BlockFace face); + public boolean isOpaque(BlockFace face); + public boolean isBlockOpaque(); + } private static final int BLOCK_MASK = 1 << 7; @@ -59,6 +65,11 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer { @Override public void processBlock(BlockRender block, int x, int y, int z) { + if (!(block instanceof OpaqueCube)) return; + OpaqueCube opaqueCube = (OpaqueCube) block; + + if (!opaqueCube.isBlockOpaque()) return; // FIXME + addFace(x, y, z, BlockFace.TOP); addFace(x, y, z, BlockFace.BOTTOM); addFace(x, y, z, BlockFace.NORTH); @@ -69,23 +80,18 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer { } protected void addFace(int x, int y, int z, BlockFace face) { - switch (face) { - case BOTTOM: + if (face == BlockFace.BOTTOM) { z -= 1; face = BlockFace.TOP; - break; - case SOUTH: + } else if (face == BlockFace.SOUTH) { x -= 1; face = BlockFace.NORTH; - break; - case EAST: + } else if (face == BlockFace.EAST) { y -= 1; face = BlockFace.WEST; - break; - default: } - data[x + 1][y + 1][z + 1] ^= 1 << face.ordinal(); + data[x + 1][y + 1][z + 1] ^= 1 << getBit(face); } protected void addBlock(int x, int y, int z) { @@ -93,23 +99,18 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer { } protected boolean hasFace(int x, int y, int z, BlockFace face) { - switch (face) { - case BOTTOM: + if (face == BlockFace.BOTTOM) { z -= 1; face = BlockFace.TOP; - break; - case SOUTH: + } else if (face == BlockFace.SOUTH) { x -= 1; face = BlockFace.NORTH; - break; - case EAST: + } else if (face == BlockFace.EAST) { y -= 1; face = BlockFace.WEST; - break; - default: } - return (data[x + 1][y + 1][z + 1] & 1 << face.ordinal()) != 0; + return (data[x + 1][y + 1][z + 1] & 1 << getBit(face)) != 0; } protected boolean hasBlock(int x, int y, int z) { @@ -134,26 +135,21 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer { Face shapeFace = null; if (!hasBlock(x, y, z)) { - switch (face) { - case TOP: + if (face == BlockFace.TOP) { shapeFace = createFace( x, y, z + 1, BlockFace.BOTTOM ); - break; - case NORTH: + } else if (face == BlockFace.NORTH) { shapeFace = createFace( x + 1, y, z, BlockFace.SOUTH ); - break; - case WEST: + } else if (face == BlockFace.WEST) { shapeFace = createFace( x, y + 1, z, BlockFace.EAST ); - break; - default: } } else { shapeFace = createFace(x, y, z, face); @@ -174,8 +170,8 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer { } private Face createFace(int x, int y, int z, BlockFace face) { - BlockRenderOpaqueCube blockRender = - (BlockRenderOpaqueCube) chunk.getBlock(x, y, z); + OpaqueCube blockRender = + (OpaqueCube) chunk.getBlock(x, y, z); Texture texture = blockRender.getTexture(face); return Faces.createBlockFace( @@ -186,5 +182,16 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer { face ); } + + // TODO refactor + private static int getBit(BlockFace face) { + if (face == BlockFace.TOP) return 0; + if (face == BlockFace.BOTTOM) return 1; + if (face == BlockFace.NORTH) return 2; + if (face == BlockFace.SOUTH) return 3; + if (face == BlockFace.WEST) return 4; + if (face == BlockFace.EAST) return 5; + return -1; + } } diff --git a/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOptimizerGenerators.java b/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOptimizerGenerators.java index 610acbd..d5a680c 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOptimizerGenerators.java +++ b/src/main/java/ru/windcorp/progressia/client/world/renders/bro/BlockRenderOptimizerGenerators.java @@ -32,7 +32,7 @@ public class BlockRenderOptimizerGenerators { register(new BlockRenderOptimizerGenerator("Default", "OpaqueCube") { @Override public BlockRenderOptimizer createOptimizer() { - return new BlockRenderOpaqueCubeOptimizer(); + return new BlockRenderCubeOptimizer(); } }); } diff --git a/src/main/java/ru/windcorp/progressia/common/block/BlockFace.java b/src/main/java/ru/windcorp/progressia/common/block/BlockFace.java index e8bb395..9f24e3f 100644 --- a/src/main/java/ru/windcorp/progressia/common/block/BlockFace.java +++ b/src/main/java/ru/windcorp/progressia/common/block/BlockFace.java @@ -17,8 +17,56 @@ *******************************************************************************/ package ru.windcorp.progressia.common.block; -public enum BlockFace { +import com.google.common.collect.ImmutableList; + +public final class BlockFace extends BlockRelation { - TOP, BOTTOM, NORTH, SOUTH, EAST, WEST; + public static final BlockFace + TOP = new BlockFace( 0, 0, +1, true), + BOTTOM = new BlockFace( 0, 0, -1, false), + NORTH = new BlockFace(+1, 0, 0, true), + SOUTH = new BlockFace(-1, 0, 0, false), + WEST = new BlockFace( 0, +1, 0, true), + EAST = new BlockFace( 0, -1, 0, false); + + private static final ImmutableList ALL_VALUES = + ImmutableList.of(TOP, BOTTOM, NORTH, SOUTH, WEST, EAST); + + public static ImmutableList getValues() { + return ALL_VALUES; + } + + static { + link(TOP, BOTTOM); + link(NORTH, SOUTH); + link(WEST, EAST); + } + + private static void link(BlockFace a, BlockFace b) { + a.counterFace = b; + b.counterFace = a; + } + + private BlockFace counterFace; + private final boolean isPrimary; + + private BlockFace(int x, int y, int z, boolean isPrimary) { + super(x, y, z); + this.isPrimary = isPrimary; + } + + public boolean isPrimary() { + return isPrimary; + } + + public BlockFace getPrimary() { + if (isPrimary) return this; + else return counterFace; + } + + public BlockFace getSecondary() { + if (isPrimary) return counterFace; + else return this; + } } diff --git a/src/main/java/ru/windcorp/progressia/common/block/BlockRelation.java b/src/main/java/ru/windcorp/progressia/common/block/BlockRelation.java new file mode 100644 index 0000000..821cd35 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/block/BlockRelation.java @@ -0,0 +1,62 @@ +package ru.windcorp.progressia.common.block; + +import static java.lang.Math.abs; +import static java.lang.Math.max; + +import glm.vec._3.Vec3; +import glm.vec._3.i.Vec3i; + +public class BlockRelation { + + private final Vec3i vector = new Vec3i(); + private final Vec3 normalized = new Vec3(); + + public BlockRelation(int x, int y, int z) { + vector.set(x, y, z); + normalized.set(x, y, z).normalize(); + } + + public BlockRelation(Vec3i vector) { + this(vector.x, vector.y, vector.z); + } + + public Vec3i getVector() { + return vector; + } + + public Vec3 getNormalized() { + return normalized; + } + + /** + * Returns the distance between the source and destination blocks, as + * defined by the Euclidean space. Your everyday distance. + * @return square root of the sum of the squares of the coordinates + */ + public float getEuclideanDistance() { + return vector.length(); + } + + /** + * Returns the Manhattan distance, also known as the taxicab distance, + * between the source and the destination blocks. Manhattan distance is + * defined as the sum of the absolute values of the coordinates, + * which is also the minimum amount of block faces that need to be crossed + * to move from source to destination. + * @return the sum of the absolute values of the coordinates + */ + public int getManhattanDistance() { + return abs(vector.x) + abs(vector.y) + abs(vector.z); + } + + /** + * Returns the Chebyshev distance between the source and the destination + * blocks. Chebyshev distance is defined as the maximum of the absolute + * values of the coordinates. + * @return the maximum of the absolute values of the coordinates + */ + public int getChebyshevDistance() { + return max(abs(vector.x), max(abs(vector.y), abs(vector.z))); + } + +}