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,
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");
}
}

View File

@ -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<String, BlockRenderOptimizer> optimizers = new HashMap<>();
Collection<BlockRenderOptimizer> 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<String, BlockRenderOptimizer> optimizers
Collection<BlockRenderOptimizer> 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(

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.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
);
}
@ -51,4 +38,12 @@ public abstract class BlockRender extends Namespaced {
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();
}
@Override
public boolean needsOwnRenderable() {
return false;
}
}

View File

@ -15,10 +15,10 @@
* You should have received a copy of the GNU General Public License
* 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.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;
}
}

View File

@ -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<BlockFace, Texture> textures =
new EnumMap<>(BlockFace.class);
private final Map<BlockFace, Texture> 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);
}

View File

@ -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 {
@ -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.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 {

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.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(
@ -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") {
@Override
public BlockRenderOptimizer createOptimizer() {
return new BlockRenderOpaqueCubeOptimizer();
return new BlockRenderCubeOptimizer();
}
});
}

View File

@ -17,8 +17,56 @@
*******************************************************************************/
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)));
}
}