they shouldnt make dragons do vector math :(

This commit is contained in:
quat1024 2023-07-09 22:53:11 -04:00
parent d70997faa0
commit 8acb584fd2
5 changed files with 78 additions and 92 deletions

View File

@ -1,56 +1,46 @@
package io.github.cottonmc.templates.block; package io.github.cottonmc.templates.block;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import io.github.cottonmc.templates.util.EdgeDirection; import io.github.cottonmc.templates.api.TemplateInteractionUtil;
import io.github.cottonmc.templates.util.Edge;
import io.github.cottonmc.templates.util.StairShapeMaker; import io.github.cottonmc.templates.util.StairShapeMaker;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.EnumProperty;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class TemplateSlopeBlock extends WaterloggableTemplateBlock { public class TemplateSlopeBlock extends WaterloggableTemplateBlock {
public static final EnumProperty<EdgeDirection> FACING = EnumProperty.of("facing", EdgeDirection.class); public static final EnumProperty<Edge> EDGE = EnumProperty.of("edge", Edge.class);
private static final VoxelShape[] shapes = new VoxelShape[8]; private static final VoxelShape[] shapes = new VoxelShape[Edge.values().length];
private static int shapeIndex(Direction dir, BlockHalf half) {
return dir.getHorizontal() + (half == BlockHalf.TOP ? 4 : 0);
}
static { static {
//TODO for(Edge edge : Edge.values()) {
for(BlockHalf half : BlockHalf.values()) { shapes[edge.ordinal()] = StairShapeMaker.makeStair(edge, 1, 0.125d, 0.125d, 0.125d, 8);
for(Direction d : Direction.values()) {
if(d.getHorizontal() == -1) continue;
shapes[shapeIndex(d, half)] = StairShapeMaker.createHorizontal(d, half, 8, 0.125d, 0.125d);
}
} }
} }
public TemplateSlopeBlock(Settings settings) { public TemplateSlopeBlock(Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(FACING, EdgeDirection.DOWN_NORTH)); setDefaultState(getDefaultState().with(EDGE, Edge.DOWN_NORTH));
} }
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder.add(FACING)); super.appendProperties(builder.add(EDGE));
} }
@Nullable @Nullable
@Override @Override
public BlockState getPlacementState(ItemPlacementContext ctx) { public BlockState getPlacementState(ItemPlacementContext ctx) {
EdgeDirection.guessFromHitResult(ctx.getHitPos(), ctx.getBlockPos());
BlockState sup = super.getPlacementState(ctx); BlockState sup = super.getPlacementState(ctx);
if(sup != null) sup = sup.with(FACING, EdgeDirection.guessFromHitResult(ctx.getHitPos(), ctx.getBlockPos())); if(sup != null) sup = sup.with(EDGE, Edge.closestTo(ctx.getHitPos(), ctx.getBlockPos()));
return sup; return sup;
} }
@ -58,15 +48,13 @@ public class TemplateSlopeBlock extends WaterloggableTemplateBlock {
@Override @Override
public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
return MoreObjects.firstNonNull( return MoreObjects.firstNonNull(
super.getCollisionShape(state, view, pos, ctx), TemplateInteractionUtil.getCollisionShape(state, view, pos, ctx),
//shapes[shapeIndex(state.get(FACING_OLD), state.get(HALF_OLD))] shapes[state.get(EDGE).ordinal()]
shapes[0] //TODO
); );
} }
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) {
//return shapes[shapeIndex(state.get(FACING_OLD), state.get(HALF_OLD))]; return shapes[state.get(EDGE).ordinal()];
return shapes[0]; //TODO
} }
} }

View File

@ -55,6 +55,8 @@ public class SlopeBaseMesh {
return builder.build(); return builder.build();
} }
//My mfw (my face when) mfw face when you can't rotate blockmodels on the z axis from a blockstate file
//Fine i will do it myself !!!
public static Mesh makeSide() { public static Mesh makeSide() {
Matrix4f mat = new Matrix4f(); Matrix4f mat = new Matrix4f();
RotationAxis.POSITIVE_Z.rotationDegrees(90).get(mat); RotationAxis.POSITIVE_Z.rotationDegrees(90).get(mat);

View File

@ -2,13 +2,15 @@ package io.github.cottonmc.templates.util;
import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap; import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap;
import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap; import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap;
import net.minecraft.util.Pair;
import net.minecraft.util.StringIdentifiable; import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import org.joml.Vector3d;
import java.util.Locale; import java.util.Locale;
public enum EdgeDirection implements StringIdentifiable { public enum Edge implements StringIdentifiable {
DOWN_NORTH(AxisRelation.PARALLEL, AxisRelation.LOW_SIDE, AxisRelation.LOW_SIDE), DOWN_NORTH(AxisRelation.PARALLEL, AxisRelation.LOW_SIDE, AxisRelation.LOW_SIDE),
DOWN_SOUTH(AxisRelation.PARALLEL, AxisRelation.LOW_SIDE, AxisRelation.HIGH_SIDE), DOWN_SOUTH(AxisRelation.PARALLEL, AxisRelation.LOW_SIDE, AxisRelation.HIGH_SIDE),
UP_SOUTH(AxisRelation.PARALLEL, AxisRelation.HIGH_SIDE, AxisRelation.HIGH_SIDE), UP_SOUTH(AxisRelation.PARALLEL, AxisRelation.HIGH_SIDE, AxisRelation.HIGH_SIDE),
@ -23,20 +25,20 @@ public enum EdgeDirection implements StringIdentifiable {
DOWN_EAST(AxisRelation.HIGH_SIDE, AxisRelation.LOW_SIDE, AxisRelation.PARALLEL), DOWN_EAST(AxisRelation.HIGH_SIDE, AxisRelation.LOW_SIDE, AxisRelation.PARALLEL),
; ;
EdgeDirection(AxisRelation x, AxisRelation y, AxisRelation z) { Edge(AxisRelation x, AxisRelation y, AxisRelation z) {
this.key = key(x, y, z); this.key = key(x, y, z);
} }
private final byte key; private final byte key;
private static final Byte2ObjectMap<EdgeDirection> LOOKUP = new Byte2ObjectOpenHashMap<>(); private static final Byte2ObjectMap<Edge> LOOKUP = new Byte2ObjectOpenHashMap<>();
static { for(EdgeDirection e : values()) LOOKUP.put(e.key, e); } static { for(Edge e : values()) LOOKUP.put(e.key, e); }
private static byte key(AxisRelation x, AxisRelation y, AxisRelation z) { private static byte key(AxisRelation x, AxisRelation y, AxisRelation z) {
return (byte) (x.ordinal() + 1 << 4 | y.ordinal() + 1 << 2 | z.ordinal() + 1); return (byte) (x.ordinal() + 1 << 4 | y.ordinal() + 1 << 2 | z.ordinal() + 1);
} }
public static EdgeDirection guessFromHitResult(Vec3d precise, BlockPos coarse) { public static Edge closestTo(Vec3d precise, BlockPos coarse) {
double dx = precise.x - coarse.getX(); double dx = precise.x - coarse.getX();
double dy = precise.y - coarse.getY(); double dy = precise.y - coarse.getY();
double dz = precise.z - coarse.getZ(); double dz = precise.z - coarse.getZ();
@ -49,7 +51,7 @@ public enum EdgeDirection implements StringIdentifiable {
float distToLowZ = (float) (dz); float distToLowZ = (float) (dz);
float distToHighZ = (float) (1 - dz); float distToHighZ = (float) (1 - dz);
//distances your click was from either pair of edges (each 0..0.5) //distances your click was from either pair of edges (each 0..5)
float distToAnyX = Math.min(distToLowX, distToHighX); float distToAnyX = Math.min(distToLowX, distToHighX);
float distToAnyY = Math.min(distToLowY, distToHighY); float distToAnyY = Math.min(distToLowY, distToHighY);
float distToAnyZ = Math.min(distToLowZ, distToHighZ); float distToAnyZ = Math.min(distToLowZ, distToHighZ);
@ -73,6 +75,33 @@ public enum EdgeDirection implements StringIdentifiable {
return LOOKUP.getOrDefault(key(clickX, clickY, clickZ), DOWN_SOUTH); return LOOKUP.getOrDefault(key(clickX, clickY, clickZ), DOWN_SOUTH);
} }
//I may have skill issue
//Beep boop i am very maintainable yes
public record CoordinateFrame(Vector3d origin, Vector3d along, Vector3d a, Vector3d b) {}
private static final Vector3d ZR = new Vector3d();
private static final Vector3d PX = new Vector3d(1, 0, 0);
private static final Vector3d NX = new Vector3d(-1, 0, 0);
private static final Vector3d PY = new Vector3d(0, 1, 0);
private static final Vector3d NY = new Vector3d(0, -1, 0);
private static final Vector3d PZ = new Vector3d(0, 0, 1);
private static final Vector3d NZ = new Vector3d(0, 0, -1);
public CoordinateFrame makeCoordinateFrame() {
return switch(this) {
case DOWN_NORTH -> new CoordinateFrame(ZR, PX, PZ, PY);
case DOWN_EAST -> new CoordinateFrame(PX, PZ, NX, PY);
case DOWN_SOUTH -> new CoordinateFrame(new Vector3d(1, 0, 1), NX, NZ, PY);
case DOWN_WEST -> new CoordinateFrame(PZ, NZ, PX, PY);
case UP_NORTH -> new CoordinateFrame(PY, PX, PZ, NY);
case UP_EAST -> new CoordinateFrame(new Vector3d(1, 1, 0), PZ, NX, NY);
case UP_SOUTH -> new CoordinateFrame(new Vector3d(1, 1, 1), NX, NZ, NY);
case UP_WEST -> new CoordinateFrame(new Vector3d(0, 1, 1), NZ, PX, NY);
case NORTH_WEST -> new CoordinateFrame(ZR, PY, PZ, PX);
case NORTH_EAST -> new CoordinateFrame(PX, PY, NX, PZ);
case SOUTH_EAST -> new CoordinateFrame(new Vector3d(1, 0, 1), PY, NZ, NX);
case SOUTH_WEST -> new CoordinateFrame(PZ, PY, PX, NZ);
};
}
@Override @Override
public String asString() { public String asString() {
return name().toLowerCase(Locale.ROOT); return name().toLowerCase(Locale.ROOT);

View File

@ -1,64 +1,31 @@
package io.github.cottonmc.templates.util; package io.github.cottonmc.templates.util;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
import org.joml.Vector3d;
public class StairShapeMaker { public class StairShapeMaker {
public static VoxelShape createHorizontal(Direction shortSide, BlockHalf half, int steps, double rise, double run) { public static VoxelShape makeStair(Edge innerEdge, double stepIn, double initialStepRise, double stepRise, double stepRun, int stepCount) {
Edge.CoordinateFrame frame = innerEdge.makeCoordinateFrame();
Vector3d origin = frame.origin();
Vector3d in = new Vector3d(frame.a()).mul(stepIn);
Vector3d fstRise = new Vector3d(frame.b()).mul(initialStepRise);
Vector3d cursor = new Vector3d(origin).add(frame.along()).add(in).add(fstRise);
Vector3d step = new Vector3d(frame.b()).mul(stepRise).add(new Vector3d(frame.a()).mul(-stepRun));
VoxelShape shape = VoxelShapes.empty(); VoxelShape shape = VoxelShapes.empty();
for(int i = 0; i < stepCount; i++) {
Vec3d a, b, march; shape = VoxelShapes.union(shape, box(origin.x, origin.y, origin.z, cursor.x, cursor.y, cursor.z));
switch(shortSide) { cursor.add(step);
case SOUTH -> {
a = new Vec3d(0, 0, 1);
b = new Vec3d(1, rise, 0);
march = new Vec3d(0, rise, run);
}
case NORTH -> {
a = new Vec3d(0, 0, 0);
b = new Vec3d(1, rise, 1);
march = new Vec3d(0, rise, -run);
}
case EAST -> {
a = new Vec3d(1, 0, 0);
b = new Vec3d(0, rise, 1);
march = new Vec3d(run, rise, 0);
}
case WEST -> {
a = new Vec3d(0, 0, 0);
b = new Vec3d(1, rise, 1);
march = new Vec3d(-run, rise, 0);
}
default -> {
return VoxelShapes.fullCube(); //TODO
}
}
if(half == BlockHalf.TOP) {
a = new Vec3d(a.x, 1 - a.y, a.z);
b = new Vec3d(b.x, 1 - b.y, b.z);
march = march.multiply(1, -1, 1);
}
for(int i = 0; i < steps; i++) {
VoxelShape newShape = agh(a.x, a.y, a.z, b.x, b.y, b.z);
shape = VoxelShapes.union(shape, newShape);
b = b.add(march);
} }
return shape.simplify(); return shape.simplify();
} }
private static VoxelShape agh(double x1, double y1, double z1, double x2, double y2, double z2) { //VoxelShape's constructor is picky about specifying your mins before your maxs
double minX = Math.min(x1, x2); private static VoxelShape box(double x1, double y1, double z1, double x2, double y2, double z2) {
double maxX = Math.max(x1, x2); return VoxelShapes.cuboid(Math.min(x1, x2), Math.min(y1, y2), Math.min(z1, z2), Math.max(x1, x2), Math.max(y1, y2), Math.max(z1, z2));
double minY = Math.min(y1, y2);
double maxY = Math.max(y1, y2);
double minZ = Math.min(z1, z2);
double maxZ = Math.max(z1, z2);
return VoxelShapes.cuboid(minX, minY, minZ, maxX, maxY, maxZ);
} }
} }

View File

@ -1,61 +1,61 @@
{ {
"variants": { "variants": {
"facing=down_east": { "edge=down_east": {
"model": "templates:slope_special", "model": "templates:slope_special",
"uvlock": true, "uvlock": true,
"y": 270 "y": 270
}, },
"facing=down_north": { "edge=down_north": {
"model": "templates:slope_special", "model": "templates:slope_special",
"uvlock": true, "uvlock": true,
"y": 180 "y": 180
}, },
"facing=down_south": { "edge=down_south": {
"model": "templates:slope_special" "model": "templates:slope_special"
}, },
"facing=down_west": { "edge=down_west": {
"model": "templates:slope_special", "model": "templates:slope_special",
"uvlock": true, "uvlock": true,
"y": 90 "y": 90
}, },
"facing=up_east": { "edge=up_east": {
"model": "templates:slope_special", "model": "templates:slope_special",
"uvlock": true, "uvlock": true,
"x": 180, "x": 180,
"y": 90 "y": 90
}, },
"facing=up_north": { "edge=up_north": {
"model": "templates:slope_special", "model": "templates:slope_special",
"uvlock": true, "uvlock": true,
"x": 180 "x": 180
}, },
"facing=up_south": { "edge=up_south": {
"model": "templates:slope_special", "model": "templates:slope_special",
"uvlock": true, "uvlock": true,
"x": 180, "x": 180,
"y": 180 "y": 180
}, },
"facing=up_west": { "edge=up_west": {
"model": "templates:slope_special", "model": "templates:slope_special",
"uvlock": true, "uvlock": true,
"x": 180, "x": 180,
"y": 270 "y": 270
}, },
"facing=north_east": { "edge=north_east": {
"model": "templates:slope_side_special", "model": "templates:slope_side_special",
"uvlock": true, "uvlock": true,
"y": 270 "y": 270
}, },
"facing=north_west": { "edge=north_west": {
"model": "templates:slope_side_special", "model": "templates:slope_side_special",
"uvlock": true, "uvlock": true,
"y": 180 "y": 180
}, },
"facing=south_east": { "edge=south_east": {
"model": "templates:slope_side_special", "model": "templates:slope_side_special",
"uvlock": true "uvlock": true
}, },
"facing=south_west": { "edge=south_west": {
"model": "templates:slope_side_special", "model": "templates:slope_side_special",
"uvlock": true, "uvlock": true,
"y": 90 "y": 90