Begun refactoring chunk render. Not implemented properly.

This commit is contained in:
OLEGSHA 2020-08-25 21:11:55 +03:00
parent 1caf82bf8c
commit d58d028e1c
12 changed files with 245 additions and 90 deletions

View File

@ -77,8 +77,7 @@ public class Faces {
Vec3 blockCenter, Vec3 blockCenter,
BlockFace face BlockFace face
) { ) {
switch (face) { if (face == BlockFace.TOP) {
case TOP:
return createRectangle( return createRectangle(
program, program,
texture, colorMultiplier, texture, colorMultiplier,
@ -86,7 +85,7 @@ public class Faces {
new Vec3( 0, -1, 0), new Vec3( 0, -1, 0),
new Vec3(+1, 0, 0) new Vec3(+1, 0, 0)
); );
case BOTTOM: } else if (face == BlockFace.BOTTOM) {
return createRectangle( return createRectangle(
program, program,
texture, colorMultiplier, texture, colorMultiplier,
@ -94,7 +93,7 @@ public class Faces {
new Vec3( 0, +1, 0), new Vec3( 0, +1, 0),
new Vec3(+1, 0, 0) new Vec3(+1, 0, 0)
); );
case NORTH: } else if (face == BlockFace.NORTH) {
return createRectangle( return createRectangle(
program, program,
texture, colorMultiplier, texture, colorMultiplier,
@ -102,7 +101,7 @@ public class Faces {
new Vec3( 0, +1, 0), new Vec3( 0, +1, 0),
new Vec3( 0, 0, +1) new Vec3( 0, 0, +1)
); );
case SOUTH: } else if (face == BlockFace.SOUTH) {
return createRectangle( return createRectangle(
program, program,
texture, colorMultiplier, texture, colorMultiplier,
@ -110,7 +109,7 @@ public class Faces {
new Vec3( 0, -1, 0), new Vec3( 0, -1, 0),
new Vec3( 0, 0, +1) new Vec3( 0, 0, +1)
); );
case EAST: } else if (face == BlockFace.EAST) {
return createRectangle( return createRectangle(
program, program,
texture, colorMultiplier, texture, colorMultiplier,
@ -118,7 +117,7 @@ public class Faces {
new Vec3(+1, 0, 0), new Vec3(+1, 0, 0),
new Vec3( 0, 0, +1) new Vec3( 0, 0, +1)
); );
case WEST: } else if (face == BlockFace.WEST) {
return createRectangle( return createRectangle(
program, program,
texture, colorMultiplier, texture, colorMultiplier,
@ -126,7 +125,7 @@ public class Faces {
new Vec3(-1, 0, 0), new Vec3(-1, 0, 0),
new Vec3( 0, 0, +1) new Vec3( 0, 0, +1)
); );
default: } else {
throw new NullPointerException("face"); throw new NullPointerException("face");
} }
} }

View File

@ -17,8 +17,8 @@
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.client.world; package ru.windcorp.progressia.client.world;
import java.util.HashMap; import java.util.Collection;
import java.util.Map; import java.util.stream.Collectors;
import glm.mat._4.Mat4; import glm.mat._4.Mat4;
import ru.windcorp.progressia.client.graphics.model.Model; import ru.windcorp.progressia.client.graphics.model.Model;
@ -87,16 +87,12 @@ public class ChunkRender {
} }
private void buildModel() { private void buildModel() {
Map<String, BlockRenderOptimizer> optimizers = new HashMap<>(); Collection<BlockRenderOptimizer> optimizers =
BlockRenderOptimizerGenerators.getAll().stream()
.map(BlockRenderOptimizerGenerator::createOptimizer)
.collect(Collectors.toList());
for ( optimizers.forEach(bro -> bro.startRender(this));
BlockRenderOptimizerGenerator generator :
BlockRenderOptimizerGenerators.getAll()
) {
BlockRenderOptimizer optimizer = generator.createOptimizer();
optimizers.put(generator.getId(), optimizer);
optimizer.startRender(this);
}
StaticModel.Builder builder = StaticModel.builder(); StaticModel.Builder builder = StaticModel.builder();
@ -110,7 +106,9 @@ public class ChunkRender {
continue; continue;
} }
if (tryToForwardToOptimizers(block, x, y, z, optimizers)) { forwardToOptimizers(block, x, y, z, optimizers);
if (!block.needsOwnRenderable()) {
continue; continue;
} }
@ -123,7 +121,7 @@ public class ChunkRender {
} }
} }
for (BlockRenderOptimizer optimizer : optimizers.values()) { for (BlockRenderOptimizer optimizer : optimizers) {
Shape result = optimizer.endRender(); Shape result = optimizer.endRender();
if (result != null) { if (result != null) {
builder.addPart(result); builder.addPart(result);
@ -134,22 +132,11 @@ public class ChunkRender {
needsUpdate = false; needsUpdate = false;
} }
private boolean tryToForwardToOptimizers( private void forwardToOptimizers(
BlockRender block, int x, int y, int z, BlockRender block, int x, int y, int z,
Map<String, BlockRenderOptimizer> optimizers Collection<BlockRenderOptimizer> optimizers
) { ) {
if (!block.isOptimized()) { optimizers.forEach(bro -> bro.processBlock(block, x, y, z));
return false;
}
BlockRenderOptimizer optimizer = optimizers.get(block.getOptimizer());
if (optimizer == null) {
return false;
}
optimizer.processBlock(block, x, y, z);
return true;
} }
private boolean tryToCreateRenderable( private boolean tryToCreateRenderable(

View File

@ -19,31 +19,18 @@ 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.bro.BlockRenderOptimizer;
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 {
private String optimizer = null;
public BlockRender(String namespace, String name) { public BlockRender(String namespace, String name) {
super(namespace, 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) { public void render(ShapeRenderHelper renderer) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"BlockRender.render() not implemented" "BlockRender.render() not implemented in " + this
); );
} }
@ -51,4 +38,12 @@ public abstract class BlockRender extends Namespaced {
return null; return null;
} }
public boolean canBeOptimized(BlockRenderOptimizer optimizer) {
return true;
}
public boolean needsOwnRenderable() {
return true;
}
} }

View File

@ -31,4 +31,9 @@ public class BlockRenderNone extends BlockRender {
return EmptyModel.getInstance(); return EmptyModel.getInstance();
} }
@Override
public boolean needsOwnRenderable() {
return false;
}
} }

View File

@ -15,10 +15,10 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ *******************************************************************************/
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.graphics.texture.Texture;
import ru.windcorp.progressia.client.world.renders.BlockRenderTexturedCube; import ru.windcorp.progressia.common.block.BlockFace;
public class BlockRenderOpaqueCube extends BlockRenderTexturedCube { public class BlockRenderOpaqueCube extends BlockRenderTexturedCube {
@ -34,7 +34,33 @@ public class BlockRenderOpaqueCube extends BlockRenderTexturedCube {
northTexture, southTexture, northTexture, southTexture,
eastTexture, westTexture 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;
} }
} }

View File

@ -19,18 +19,21 @@ package ru.windcorp.progressia.client.world.renders;
import static ru.windcorp.progressia.common.block.BlockFace.*; 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.Shapes;
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.bro.BlockRenderCubeOptimizer.OpaqueCube;
import ru.windcorp.progressia.common.block.BlockFace; import ru.windcorp.progressia.common.block.BlockFace;
public abstract class BlockRenderTexturedCube extends BlockRender { public abstract class BlockRenderTexturedCube
extends BlockRender
implements OpaqueCube {
private final EnumMap<BlockFace, Texture> textures = private final Map<BlockFace, Texture> textures = new HashMap<>();
new EnumMap<>(BlockFace.class);
public BlockRenderTexturedCube( public BlockRenderTexturedCube(
String namespace, String name, String namespace, String name,
@ -48,6 +51,7 @@ public abstract class BlockRenderTexturedCube extends BlockRender {
textures.put(WEST, westTexture); textures.put(WEST, westTexture);
} }
@Override
public Texture getTexture(BlockFace face) { public Texture getTexture(BlockFace face) {
return textures.get(face); return textures.get(face);
} }

View File

@ -18,6 +18,7 @@
package ru.windcorp.progressia.client.world.renders; package ru.windcorp.progressia.client.world.renders;
import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.common.block.BlockFace;
public class BlockRenderTransparentCube extends BlockRenderTexturedCube { public class BlockRenderTransparentCube extends BlockRenderTexturedCube {
@ -35,4 +36,26 @@ public class BlockRenderTransparentCube extends BlockRenderTexturedCube {
); );
} }
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;
}
} }

View File

@ -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.Atlases.AtlasGroup;
import ru.windcorp.progressia.client.graphics.texture.SimpleTexture; import ru.windcorp.progressia.client.graphics.texture.SimpleTexture;
import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.client.world.renders.bro.BlockRenderOpaqueCube;
import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.resource.ResourceManager;
public class BlockRenders { public class BlockRenders {

View File

@ -34,7 +34,13 @@ import ru.windcorp.progressia.client.world.renders.BlockRender;
import ru.windcorp.progressia.common.block.BlockFace; import ru.windcorp.progressia.common.block.BlockFace;
import ru.windcorp.progressia.common.world.ChunkData; 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; private static final int BLOCK_MASK = 1 << 7;
@ -59,6 +65,11 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer {
@Override @Override
public void processBlock(BlockRender block, int x, int y, int z) { 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.TOP);
addFace(x, y, z, BlockFace.BOTTOM); addFace(x, y, z, BlockFace.BOTTOM);
addFace(x, y, z, BlockFace.NORTH); 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) { protected void addFace(int x, int y, int z, BlockFace face) {
switch (face) { if (face == BlockFace.BOTTOM) {
case BOTTOM:
z -= 1; z -= 1;
face = BlockFace.TOP; face = BlockFace.TOP;
break; } else if (face == BlockFace.SOUTH) {
case SOUTH:
x -= 1; x -= 1;
face = BlockFace.NORTH; face = BlockFace.NORTH;
break; } else if (face == BlockFace.EAST) {
case EAST:
y -= 1; y -= 1;
face = BlockFace.WEST; 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) { 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) { protected boolean hasFace(int x, int y, int z, BlockFace face) {
switch (face) { if (face == BlockFace.BOTTOM) {
case BOTTOM:
z -= 1; z -= 1;
face = BlockFace.TOP; face = BlockFace.TOP;
break; } else if (face == BlockFace.SOUTH) {
case SOUTH:
x -= 1; x -= 1;
face = BlockFace.NORTH; face = BlockFace.NORTH;
break; } else if (face == BlockFace.EAST) {
case EAST:
y -= 1; y -= 1;
face = BlockFace.WEST; 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) { protected boolean hasBlock(int x, int y, int z) {
@ -134,26 +135,21 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer {
Face shapeFace = null; Face shapeFace = null;
if (!hasBlock(x, y, z)) { if (!hasBlock(x, y, z)) {
switch (face) { if (face == BlockFace.TOP) {
case TOP:
shapeFace = createFace( shapeFace = createFace(
x, y, z + 1, x, y, z + 1,
BlockFace.BOTTOM BlockFace.BOTTOM
); );
break; } else if (face == BlockFace.NORTH) {
case NORTH:
shapeFace = createFace( shapeFace = createFace(
x + 1, y, z, x + 1, y, z,
BlockFace.SOUTH BlockFace.SOUTH
); );
break; } else if (face == BlockFace.WEST) {
case WEST:
shapeFace = createFace( shapeFace = createFace(
x, y + 1, z, x, y + 1, z,
BlockFace.EAST BlockFace.EAST
); );
break;
default:
} }
} else { } else {
shapeFace = createFace(x, y, z, face); 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) { private Face createFace(int x, int y, int z, BlockFace face) {
BlockRenderOpaqueCube blockRender = OpaqueCube blockRender =
(BlockRenderOpaqueCube) chunk.getBlock(x, y, z); (OpaqueCube) chunk.getBlock(x, y, z);
Texture texture = blockRender.getTexture(face); Texture texture = blockRender.getTexture(face);
return Faces.createBlockFace( return Faces.createBlockFace(
@ -187,4 +183,15 @@ public class BlockRenderOpaqueCubeOptimizer extends BlockRenderOptimizer {
); );
} }
// 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;
}
} }

View File

@ -32,7 +32,7 @@ public class BlockRenderOptimizerGenerators {
register(new BlockRenderOptimizerGenerator("Default", "OpaqueCube") { register(new BlockRenderOptimizerGenerator("Default", "OpaqueCube") {
@Override @Override
public BlockRenderOptimizer createOptimizer() { public BlockRenderOptimizer createOptimizer() {
return new BlockRenderOpaqueCubeOptimizer(); return new BlockRenderCubeOptimizer();
} }
}); });
} }

View File

@ -17,8 +17,56 @@
*******************************************************************************/ *******************************************************************************/
package ru.windcorp.progressia.common.block; package ru.windcorp.progressia.common.block;
public enum BlockFace { import com.google.common.collect.ImmutableList;
TOP, BOTTOM, NORTH, SOUTH, EAST, WEST; public final class BlockFace extends BlockRelation {
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<BlockFace> ALL_VALUES =
ImmutableList.of(TOP, BOTTOM, NORTH, SOUTH, WEST, EAST);
public static ImmutableList<BlockFace> 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;
}
} }

View File

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