Begun refactoring chunk render. Not implemented properly.
This commit is contained in:
parent
1caf82bf8c
commit
d58d028e1c
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,5 +30,10 @@ public class BlockRenderNone extends BlockRender {
|
||||
public WorldRenderable createRenderable() {
|
||||
return EmptyModel.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsOwnRenderable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -32,7 +32,7 @@ public class BlockRenderOptimizerGenerators {
|
||||
register(new BlockRenderOptimizerGenerator("Default", "OpaqueCube") {
|
||||
@Override
|
||||
public BlockRenderOptimizer createOptimizer() {
|
||||
return new BlockRenderOpaqueCubeOptimizer();
|
||||
return new BlockRenderCubeOptimizer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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<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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user