fix: use collision shape for Shape#isFaceFull instead of occlusion shape

This commit is contained in:
mworzala 2024-03-24 21:50:54 -04:00
parent 6e179dbd8a
commit ee17c032e7
No known key found for this signature in database
GPG Key ID: B148F922E64797C7
2 changed files with 19 additions and 7 deletions

View File

@ -18,6 +18,7 @@ public final class ShapeImpl implements Shape {
private static final Pattern PATTERN = Pattern.compile("\\d.\\d+", Pattern.MULTILINE); private static final Pattern PATTERN = Pattern.compile("\\d.\\d+", Pattern.MULTILINE);
private final BoundingBox[] collisionBoundingBoxes; private final BoundingBox[] collisionBoundingBoxes;
private final Point relativeStart, relativeEnd; private final Point relativeStart, relativeEnd;
private final byte fullFaces;
private final BoundingBox[] occlusionBoundingBoxes; private final BoundingBox[] occlusionBoundingBoxes;
private final byte blockOcclusion; private final byte blockOcclusion;
@ -49,10 +50,17 @@ public final class ShapeImpl implements Shape {
this.relativeEnd = new Vec(maxX, maxY, maxZ); this.relativeEnd = new Vec(maxX, maxY, maxZ);
} }
byte fullCollisionFaces = 0;
for (BlockFace f : BlockFace.values()) {
final byte res = isFaceCovered(computeOcclusionSet(f, collisionBoundingBoxes));
fullCollisionFaces |= ((res == 2) ? 0b1 : 0b0) << (byte) f.ordinal();
}
this.fullFaces = fullCollisionFaces;
byte airFaces = 0; byte airFaces = 0;
byte fullFaces = 0; byte fullFaces = 0;
for (BlockFace f : BlockFace.values()) { for (BlockFace f : BlockFace.values()) {
final byte res = isFaceCovered(computeOcclusionSet(f)); final byte res = isFaceCovered(computeOcclusionSet(f, occlusionBoundingBoxes));
airFaces |= ((res == 0) ? 0b1 : 0b0) << (byte) f.ordinal(); airFaces |= ((res == 0) ? 0b1 : 0b0) << (byte) f.ordinal();
fullFaces |= ((res == 2) ? 0b1 : 0b0) << (byte) f.ordinal(); fullFaces |= ((res == 2) ? 0b1 : 0b0) << (byte) f.ordinal();
} }
@ -145,14 +153,14 @@ public final class ShapeImpl implements Shape {
if (hasAirOcclusion || hasAirOcclusionOther) return false; if (hasAirOcclusion || hasAirOcclusionOther) return false;
// Comparing two partial faces. Computation needed // Comparing two partial faces. Computation needed
List<Rectangle> allRectangles = shapeImpl.computeOcclusionSet(face.getOppositeFace()); List<Rectangle> allRectangles = computeOcclusionSet(face.getOppositeFace(), shapeImpl.occlusionBoundingBoxes);
allRectangles.addAll(computeOcclusionSet(face)); allRectangles.addAll(computeOcclusionSet(face, occlusionBoundingBoxes));
return isFaceCovered(allRectangles) == 2; return isFaceCovered(allRectangles) == 2;
} }
@Override @Override
public boolean isFaceFull(@NotNull BlockFace face) { public boolean isFaceFull(@NotNull BlockFace face) {
return (((blockOcclusion >> face.ordinal()) & 1) == 1); return (((fullFaces >> face.ordinal()) & 1) == 1);
} }
@Override @Override
@ -184,9 +192,9 @@ public final class ShapeImpl implements Shape {
return block; return block;
} }
private List<Rectangle> computeOcclusionSet(BlockFace face) { private static @NotNull List<Rectangle> computeOcclusionSet(BlockFace face, BoundingBox[] boundingBoxes) {
List<Rectangle> rSet = new ArrayList<>(); List<Rectangle> rSet = new ArrayList<>();
for (BoundingBox boundingBox : this.occlusionBoundingBoxes) { for (BoundingBox boundingBox : boundingBoxes) {
switch (face) { switch (face) {
case NORTH -> // negative Z case NORTH -> // negative Z
{ {

View File

@ -20,7 +20,11 @@ public class TestShape {
Arguments.of(Block.ENCHANTING_TABLE, BlockFace.TOP, false), Arguments.of(Block.ENCHANTING_TABLE, BlockFace.TOP, false),
Arguments.of(Block.ENCHANTING_TABLE, BlockFace.NORTH, false), Arguments.of(Block.ENCHANTING_TABLE, BlockFace.NORTH, false),
Arguments.of(Block.ACACIA_FENCE, BlockFace.TOP, false), Arguments.of(Block.ACACIA_FENCE, BlockFace.TOP, false),
Arguments.of(Block.IRON_BARS, BlockFace.TOP, false) Arguments.of(Block.IRON_BARS, BlockFace.TOP, false),
// We are testing collision faces here, so this should be true even though it doesnt occlude light
Arguments.of(Block.GLASS, BlockFace.TOP, true),
Arguments.of(Block.DARK_OAK_DOOR, BlockFace.NORTH, false),
Arguments.of(Block.DARK_OAK_DOOR, BlockFace.SOUTH, true)
); );
} }