Skip to content

Commit b8cca1a

Browse files
committed
Rotate voxelshape if model is rotated
1 parent 6d85f3f commit b8cca1a

File tree

4 files changed

+152
-11
lines changed

4 files changed

+152
-11
lines changed

common/src/main/java/ca/fxco/moreculling/mixin/models/cullshape/ModelManager_cullShapeMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class ModelManager_cullShapeMixin {
2525
remap = false
2626
),
2727
index = 1)
28-
private static Object actuallyDeserializeModel(Object originalModel, @Local Reader reader,
28+
private static Object moreculling$enableModelShape(Object originalModel, @Local Reader reader,
2929
@Local(argsOnly = true)
3030
Map.Entry<ResourceLocation, Resource> entry) {
3131
UnbakedModel model = (UnbakedModel) originalModel;
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package ca.fxco.moreculling.utils;
2+
3+
import net.minecraft.Util;
4+
import net.minecraft.core.Direction;
5+
import net.minecraft.world.phys.AABB;
6+
import net.minecraft.world.phys.shapes.BooleanOp;
7+
import net.minecraft.world.phys.shapes.Shapes;
8+
import net.minecraft.world.phys.shapes.VoxelShape;
9+
10+
import java.util.List;
11+
12+
public class ShapeUtils {
13+
private static final int[] DIR_ROT_X_2D_DATA = Util.make(new int[6], arr -> {
14+
arr[Direction.DOWN.ordinal()] = 2;
15+
arr[Direction.UP.ordinal()] = 0;
16+
arr[Direction.NORTH.ordinal()] = 3;
17+
arr[Direction.SOUTH.ordinal()] = 1;
18+
arr[Direction.WEST.ordinal()] = -1;
19+
arr[Direction.EAST.ordinal()] = -1;
20+
});
21+
private static final int[] DIR_ROT_Z_2D_DATA = Util.make(new int[6], arr -> {
22+
arr[Direction.DOWN.ordinal()] = 2;
23+
arr[Direction.UP.ordinal()] = 0;
24+
arr[Direction.NORTH.ordinal()] = -1;
25+
arr[Direction.SOUTH.ordinal()] = -1;
26+
arr[Direction.WEST.ordinal()] = 3;
27+
arr[Direction.EAST.ordinal()] = 1;
28+
});
29+
30+
public static VoxelShape rotateShapeAroundY(Direction from, Direction to, VoxelShape shape) {
31+
return rotateShapeUnoptimizedAroundY(from, to, shape).optimize();
32+
}
33+
34+
public static VoxelShape rotateShapeUnoptimizedAroundY(Direction from, Direction to, VoxelShape shape) {
35+
if (isY(from) || isY(to)) {
36+
throw new IllegalArgumentException("Invalid Direction!");
37+
}
38+
if (from == to) {
39+
return shape;
40+
}
41+
42+
List<AABB> sourceBoxes = shape.toAabbs();
43+
VoxelShape rotatedShape = Shapes.empty();
44+
int times = (to.get2DDataValue() - from.get2DDataValue() + 4) % 4;
45+
for (AABB box : sourceBoxes) {
46+
for (int i = 0; i < times; i++)
47+
{
48+
box = new AABB(1 - box.maxZ, box.minY, box.minX, 1 - box.minZ, box.maxY, box.maxX);
49+
}
50+
rotatedShape = orUnoptimized(rotatedShape, Shapes.create(box));
51+
}
52+
53+
return rotatedShape;
54+
}
55+
56+
public static VoxelShape rotateShapeAroundX(Direction from, Direction to, VoxelShape shape) {
57+
return rotateShapeUnoptimizedAroundX(from, to, shape).optimize();
58+
}
59+
60+
public static VoxelShape rotateShapeUnoptimizedAroundX(Direction from, Direction to, VoxelShape shape) {
61+
if (isX(from) || isX(to)) {
62+
throw new IllegalArgumentException("Invalid Direction!");
63+
}
64+
if (from == to)
65+
{
66+
return shape;
67+
}
68+
69+
List<AABB> sourceBoxes = shape.toAabbs();
70+
VoxelShape rotatedShape = Shapes.empty();
71+
int times = (DIR_ROT_X_2D_DATA[to.ordinal()] - DIR_ROT_X_2D_DATA[from.ordinal()] + 4) % 4;
72+
for (AABB box : sourceBoxes)
73+
{
74+
for (int i = 0; i < times; i++)
75+
{
76+
box = new AABB(box.minX, 1 - box.maxZ, box.minY, box.maxX, 1 - box.minZ, box.maxY);
77+
}
78+
rotatedShape = orUnoptimized(rotatedShape, Shapes.create(box));
79+
}
80+
81+
return rotatedShape;
82+
}
83+
84+
public static VoxelShape rotateShapeAroundZ(Direction from, Direction to, VoxelShape shape) {
85+
return rotateShapeUnoptimizedAroundZ(from, to, shape).optimize();
86+
}
87+
88+
public static VoxelShape rotateShapeUnoptimizedAroundZ(Direction from, Direction to, VoxelShape shape) {
89+
if (isZ(from) || isZ(to))
90+
{
91+
throw new IllegalArgumentException("Invalid Direction!");
92+
}
93+
if (from == to)
94+
{
95+
return shape;
96+
}
97+
98+
List<AABB> sourceBoxes = shape.toAabbs();
99+
VoxelShape rotatedShape = Shapes.empty();
100+
int times = (DIR_ROT_Z_2D_DATA[to.ordinal()] - DIR_ROT_Z_2D_DATA[from.ordinal()] + 4) % 4;
101+
for (AABB box : sourceBoxes)
102+
{
103+
for (int i = 0; i < times; i++)
104+
{
105+
//noinspection SuspiciousNameCombination
106+
box = new AABB(box.minY, 1 - box.maxX, box.minZ, box.maxY, 1 - box.minX, box.maxZ);
107+
}
108+
rotatedShape = orUnoptimized(rotatedShape, Shapes.create(box));
109+
}
110+
111+
return rotatedShape;
112+
}
113+
114+
public static boolean isX(Direction dir) {
115+
return dir.getAxis() == Direction.Axis.X;
116+
}
117+
118+
public static boolean isY(Direction dir) {
119+
return dir.getAxis() == Direction.Axis.Y;
120+
}
121+
122+
public static boolean isZ(Direction dir) {
123+
return dir.getAxis() == Direction.Axis.Z;
124+
}
125+
126+
public static VoxelShape orUnoptimized(VoxelShape first, VoxelShape second) {
127+
return Shapes.joinUnoptimized(first, second, BooleanOp.OR);
128+
}
129+
130+
}

fabric/src/main/java/ca/fxco/moreculling/mixin/models/cullshape/BlockModel_fabricCullShapeMixin.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,19 @@
33
import ca.fxco.moreculling.api.model.BakedOpacity;
44
import ca.fxco.moreculling.api.model.CullShapeElement;
55
import ca.fxco.moreculling.api.model.ExtendedUnbakedModel;
6+
import ca.fxco.moreculling.utils.ShapeUtils;
67
import net.minecraft.client.renderer.block.model.BlockElement;
78
import net.minecraft.client.renderer.block.model.BlockModel;
89
import net.minecraft.client.renderer.block.model.ItemTransforms;
910
import net.minecraft.client.renderer.block.model.TextureSlots;
10-
import net.minecraft.client.resources.model.BakedModel;
11-
import net.minecraft.client.resources.model.ModelBaker;
12-
import net.minecraft.client.resources.model.ModelState;
13-
import net.minecraft.client.resources.model.UnbakedModel;
11+
import net.minecraft.client.resources.model.*;
12+
import net.minecraft.core.Direction;
1413
import net.minecraft.resources.ResourceLocation;
1514
import net.minecraft.world.level.block.Block;
16-
import net.minecraft.world.phys.shapes.BooleanOp;
1715
import net.minecraft.world.phys.shapes.Shapes;
1816
import net.minecraft.world.phys.shapes.VoxelShape;
1917
import org.jetbrains.annotations.Nullable;
18+
import org.joml.Quaternionf;
2019
import org.spongepowered.asm.mixin.Mixin;
2120
import org.spongepowered.asm.mixin.Shadow;
2221
import org.spongepowered.asm.mixin.injection.At;
@@ -62,9 +61,14 @@ public abstract class BlockModel_fabricCullShapeMixin implements ExtendedUnbaked
6261
VoxelShape shape = Block.box(
6362
e.from.x, e.from.y, e.from.z, e.to.x, e.to.y, e.to.z
6463
);
65-
voxelShape = Shapes.joinUnoptimized(voxelShape, shape, BooleanOp.OR);
64+
voxelShape = ShapeUtils.orUnoptimized(voxelShape, shape);
6665
}
6766
}
67+
Quaternionf quaternion = settings.getRotation().getLeftRotation();
68+
if (quaternion.y != 0) {
69+
voxelShape = ShapeUtils.rotateShapeUnoptimizedAroundY(Direction.SOUTH,
70+
Direction.fromYRot(Math.toDegrees(2.0f * Math.acos(quaternion.w))), voxelShape);
71+
}
6872
bakedOpacity.moreculling$setCullingShape(voxelShape);
6973
}
7074
} else {
@@ -73,7 +77,7 @@ public abstract class BlockModel_fabricCullShapeMixin implements ExtendedUnbaked
7377
VoxelShape voxelShape = Shapes.empty();
7478
for (CullShapeElement e : cullShapeElementList) {
7579
VoxelShape shape = Block.box(e.from.x, e.from.y, e.from.z, e.to.x, e.to.y, e.to.z);
76-
voxelShape = Shapes.joinUnoptimized(voxelShape, shape, BooleanOp.OR);
80+
voxelShape = ShapeUtils.orUnoptimized(voxelShape, shape);
7781
}
7882
bakedOpacity.moreculling$setCullingShape(voxelShape);
7983
}

neoforge/src/main/java/ca/fxco/moreculling/mixin/models/cullshape/BlockModel_neoforgeCullShapeMixin.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import ca.fxco.moreculling.api.model.BakedOpacity;
44
import ca.fxco.moreculling.api.model.CullShapeElement;
55
import ca.fxco.moreculling.api.model.ExtendedUnbakedModel;
6+
import ca.fxco.moreculling.utils.ShapeUtils;
67
import net.minecraft.client.renderer.block.model.BlockElement;
78
import net.minecraft.client.renderer.block.model.BlockModel;
89
import net.minecraft.client.renderer.block.model.ItemTransforms;
@@ -11,13 +12,14 @@
1112
import net.minecraft.client.resources.model.ModelBaker;
1213
import net.minecraft.client.resources.model.ModelState;
1314
import net.minecraft.client.resources.model.UnbakedModel;
15+
import net.minecraft.core.Direction;
1416
import net.minecraft.resources.ResourceLocation;
1517
import net.minecraft.util.context.ContextMap;
1618
import net.minecraft.world.level.block.Block;
17-
import net.minecraft.world.phys.shapes.BooleanOp;
1819
import net.minecraft.world.phys.shapes.Shapes;
1920
import net.minecraft.world.phys.shapes.VoxelShape;
2021
import org.jetbrains.annotations.Nullable;
22+
import org.joml.Quaternionf;
2123
import org.spongepowered.asm.mixin.Mixin;
2224
import org.spongepowered.asm.mixin.Shadow;
2325
import org.spongepowered.asm.mixin.injection.At;
@@ -64,9 +66,14 @@ public abstract class BlockModel_neoforgeCullShapeMixin implements ExtendedUnbak
6466
VoxelShape shape = Block.box(
6567
e.from.x, e.from.y, e.from.z, e.to.x, e.to.y, e.to.z
6668
);
67-
voxelShape = Shapes.joinUnoptimized(voxelShape, shape, BooleanOp.OR);
69+
voxelShape = ShapeUtils.orUnoptimized(voxelShape, shape);
6870
}
6971
}
72+
Quaternionf quaternion = settings.getRotation().getLeftRotation();
73+
if (quaternion.y != 0) {
74+
voxelShape = ShapeUtils.rotateShapeUnoptimizedAroundY(Direction.SOUTH,
75+
Direction.fromYRot(Math.toDegrees(2.0f * Math.acos(quaternion.w))), voxelShape);
76+
}
7077
bakedOpacity.moreculling$setCullingShape(voxelShape);
7178
}
7279
} else {
@@ -75,7 +82,7 @@ public abstract class BlockModel_neoforgeCullShapeMixin implements ExtendedUnbak
7582
VoxelShape voxelShape = Shapes.empty();
7683
for (CullShapeElement e : cullShapeElementList) {
7784
VoxelShape shape = Block.box(e.from.x, e.from.y, e.from.z, e.to.x, e.to.y, e.to.z);
78-
voxelShape = Shapes.joinUnoptimized(voxelShape, shape, BooleanOp.OR);;
85+
voxelShape = ShapeUtils.orUnoptimized(voxelShape, shape);
7986
}
8087
bakedOpacity.moreculling$setCullingShape(voxelShape);
8188
}

0 commit comments

Comments
 (0)