Compare commits
23 Commits
experiment
...
master
Author | SHA1 | Date | |
---|---|---|---|
9e40de85e3 | |||
abc7031989 | |||
ef76408b80 | |||
73bf27bdda | |||
402caaf549 | |||
4eddb32190 | |||
53f962da1b | |||
5517d813e7 | |||
f6b403d852 | |||
aa3cf6d511 | |||
cfdbfd3a6a | |||
ac2f7def0c | |||
44f03b2c96 | |||
f1af00738e | |||
186cca3e27 | |||
d43d9456ee | |||
2957a899db | |||
f3578a4da5 | |||
28ae110e14 | |||
6dc0cf7fdf | |||
b30177a5c7 | |||
1e132c71ef | |||
0233b3fa49 |
@ -44,7 +44,6 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
accessWidenerPath = file("src/main/resources/reframed.accesswidener")
|
|
||||||
runs {
|
runs {
|
||||||
// This adds a new gradle task that runs the datagen API: "gradlew runDatagen"
|
// This adds a new gradle task that runs the datagen API: "gradlew runDatagen"
|
||||||
datagen {
|
datagen {
|
||||||
|
@ -103,7 +103,6 @@ public class ReFramed implements ModInitializer {
|
|||||||
BLUEPRINT = registerItem("blueprint" , new ReFramedBlueprintItem(new Item.Settings()));
|
BLUEPRINT = registerItem("blueprint" , new ReFramedBlueprintItem(new Item.Settings()));
|
||||||
BLUEPRINT_WRITTEN = registerItem("blueprint_written" , new ReFramedBlueprintWrittenItem(new Item.Settings().maxCount(1)));
|
BLUEPRINT_WRITTEN = registerItem("blueprint_written" , new ReFramedBlueprintWrittenItem(new Item.Settings().maxCount(1)));
|
||||||
|
|
||||||
registerBlock("test", new TestBlock(cp(Blocks.OAK_PLANKS).nonOpaque())); // TODO remove
|
|
||||||
|
|
||||||
REFRAMED_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("camo"),
|
REFRAMED_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, id("camo"),
|
||||||
BlockEntityType.Builder.create(
|
BlockEntityType.Builder.create(
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package fr.adrien1106.reframed.block;
|
|
||||||
|
|
||||||
import fr.adrien1106.reframed.client.voxel.MorphVoxel;
|
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.block.ShapeContext;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
|
||||||
import net.minecraft.world.BlockView;
|
|
||||||
|
|
||||||
public class TestBlock extends Block {
|
|
||||||
|
|
||||||
public static MorphVoxel voxel = new MorphVoxel(createCuboidShape(1, 1, 1, 15, 15, 15),
|
|
||||||
new Vec3d[] {
|
|
||||||
new Vec3d(0, 0, 0),
|
|
||||||
new Vec3d(1, 0, 0),
|
|
||||||
new Vec3d(1, 1, 1),
|
|
||||||
new Vec3d(0, 1, 1),
|
|
||||||
new Vec3d(0, 1, 1),
|
|
||||||
new Vec3d(1, 1, 1),
|
|
||||||
new Vec3d(1, 0, 1),
|
|
||||||
new Vec3d(0, 0, 1)
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
public TestBlock(Settings settings) {
|
|
||||||
super(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
|
|
||||||
return voxel;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package fr.adrien1106.reframed.client.util;
|
|
||||||
|
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
public record RaycastResult(Vec3d pos, Direction face, boolean inside) {
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package fr.adrien1106.reframed.client.voxel;
|
|
||||||
|
|
||||||
import fr.adrien1106.reframed.client.util.RaycastResult;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Box;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class MorphBox extends Box {
|
|
||||||
protected List<Triangle> triangles;
|
|
||||||
|
|
||||||
public MorphBox(List<Triangle> triangles) {
|
|
||||||
super(new BlockPos(0, 0, 0));
|
|
||||||
this.triangles = triangles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RaycastResult triangleRaycast(Vec3d min, Vec3d max) {
|
|
||||||
return triangles.stream()
|
|
||||||
.map(triangle -> {
|
|
||||||
Vec3d inter = triangle.intersection(min, max);
|
|
||||||
if (inter == null) return null;
|
|
||||||
return new RaycastResult(
|
|
||||||
inter,
|
|
||||||
triangle.face(),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.findFirst()
|
|
||||||
.orElseGet(() -> isInside(min) ? new RaycastResult(
|
|
||||||
min,
|
|
||||||
triangles.get(0).face(),
|
|
||||||
true
|
|
||||||
) : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInside(Vec3d point) {
|
|
||||||
return triangles.stream().allMatch(triangle -> triangle.after(point));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
package fr.adrien1106.reframed.client.voxel;
|
|
||||||
|
|
||||||
import fr.adrien1106.reframed.client.util.RaycastResult;
|
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
|
||||||
import net.minecraft.util.math.*;
|
|
||||||
import net.minecraft.util.shape.SimpleVoxelShape;
|
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
|
||||||
import net.minecraft.util.shape.VoxelShapes;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a VoxelShape that can be morphed using its 8 vertices.
|
|
||||||
* the vertices are distributed as follows:
|
|
||||||
* <pre><code>
|
|
||||||
* E--------F ABCD -> NORTH
|
|
||||||
* ^ /| /| EFGH -> SOUTH
|
|
||||||
* |/ | / | AHED -> EAST
|
|
||||||
* D--------C | BCGF -> WEST
|
|
||||||
* | |/ | | ABGH -> DOWN
|
|
||||||
* | H-----|--G CDFE -> UP
|
|
||||||
* | / | /
|
|
||||||
* |/ |/
|
|
||||||
* A--------B->
|
|
||||||
* </code></pre>
|
|
||||||
*/
|
|
||||||
public class MorphVoxel extends SimpleVoxelShape {
|
|
||||||
|
|
||||||
private static final int[][] EDGE_INDICES = {
|
|
||||||
{0, 1},
|
|
||||||
{1, 2},
|
|
||||||
{2, 3},
|
|
||||||
{3, 0},
|
|
||||||
{0, 7},
|
|
||||||
{1, 6},
|
|
||||||
{2, 5},
|
|
||||||
{3, 4},
|
|
||||||
{4, 5},
|
|
||||||
{5, 6},
|
|
||||||
{6, 7},
|
|
||||||
{7, 4}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final int[][] FACE_INDICES = {
|
|
||||||
{7, 6, 1, 0},
|
|
||||||
{5, 4, 3, 2},
|
|
||||||
{0, 1, 2, 3},
|
|
||||||
{4, 5, 6, 7},
|
|
||||||
{0, 3, 4, 7},
|
|
||||||
{6, 5, 2, 1}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected final Vec3d[] v;
|
|
||||||
MorphBox box;
|
|
||||||
|
|
||||||
public MorphVoxel(VoxelShape wrapper, Vec3d[] vertices) {
|
|
||||||
super(wrapper.voxels);
|
|
||||||
List<Triangle> triangles = new ArrayList<>();
|
|
||||||
Stream.of(Direction.values()).forEach(dir -> {
|
|
||||||
int i = dir.ordinal();
|
|
||||||
List<Vec3d> v = IntStream.range(0, 4).mapToObj(j -> { // remove matching vertices
|
|
||||||
if (vertices[FACE_INDICES[i][j]].equals(vertices[FACE_INDICES[i][(j+1)%4]])) return null;
|
|
||||||
return vertices[FACE_INDICES[i][j]];
|
|
||||||
}).filter(Objects::nonNull).toList();
|
|
||||||
|
|
||||||
if (v.size() < 3) return; // skip if there are less than 3 vertices (e.g. a line/dot)
|
|
||||||
triangles.add(Triangle.of(dir,v));
|
|
||||||
});
|
|
||||||
box = new MorphBox(triangles);
|
|
||||||
v = vertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public BlockHitResult raycast(Vec3d start, Vec3d end, BlockPos pos) {
|
|
||||||
RaycastResult result = box.triangleRaycast(start.subtract(pos.getX(), pos.getY(), pos.getZ()), end.subtract(pos.getX(), pos.getY(), pos.getZ()));
|
|
||||||
return result == null
|
|
||||||
? null
|
|
||||||
: new BlockHitResult(
|
|
||||||
result.pos().add(pos.getX(), pos.getY(), pos.getZ()),
|
|
||||||
result.face(),
|
|
||||||
pos,
|
|
||||||
result.inside()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void forEachEdge(VoxelShapes.BoxConsumer consumer) {
|
|
||||||
IntStream.range(0, 12).forEach(i -> {
|
|
||||||
Vec3d a = v[EDGE_INDICES[i][0]];
|
|
||||||
Vec3d b = v[EDGE_INDICES[i][1]];
|
|
||||||
consumer.consume(a.x, a.y, a.z, b.x, b.y, b.z);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
package fr.adrien1106.reframed.client.voxel;
|
|
||||||
|
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a Face of a MorphVoxel.
|
|
||||||
* @param v - list of vertices on the same plane
|
|
||||||
* @param e - list of the outer edges
|
|
||||||
* @param n - normal of the face
|
|
||||||
* @param face - the direction of the face
|
|
||||||
*/
|
|
||||||
public record Triangle(Vec3d[] v, Vec3d[] e, Vec3d n, Direction face) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Triangle from a list of vertices.
|
|
||||||
* @param face - the direction of the face
|
|
||||||
* @param vertices - list of vertices on the same plane
|
|
||||||
* @return the Triangle
|
|
||||||
*/
|
|
||||||
public static Triangle of(Direction face, List<Vec3d> vertices) {
|
|
||||||
assert vertices.size() >= 3;
|
|
||||||
Vec3d[] v = vertices.toArray(new Vec3d[0]);
|
|
||||||
|
|
||||||
// compute the edges
|
|
||||||
Vec3d[] e = new Vec3d[v.length];
|
|
||||||
IntStream.range(0, v.length).forEach(i -> e[i] = v[(i + 1) % v.length].subtract(v[i]));
|
|
||||||
|
|
||||||
// compute the normal
|
|
||||||
Vec3d n = v[1].subtract(v[0]).crossProduct(v[2].subtract(v[0])).normalize();
|
|
||||||
|
|
||||||
return new Triangle(v, e, n, face);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes the intersection of a ray with the triangle.
|
|
||||||
* @param start - the start of the ray
|
|
||||||
* @param end - the end of the ray
|
|
||||||
* @return the intersection point or null if there is no intersection
|
|
||||||
*/
|
|
||||||
public Vec3d intersection(Vec3d start, Vec3d end) {
|
|
||||||
Vec3d start_v0 = start.subtract(v[0]);
|
|
||||||
Vec3d end_v1 = end.subtract(v[1]);
|
|
||||||
|
|
||||||
// check if the ray intersects the plane
|
|
||||||
if (n.dotProduct(start_v0) * n.dotProduct(end_v1) >= 0) return null;
|
|
||||||
|
|
||||||
Vec3d ray = end.subtract(start);
|
|
||||||
double direction = n.dotProduct(ray);
|
|
||||||
|
|
||||||
// plane normal is facing away from the ray
|
|
||||||
if (direction < 0) return null;
|
|
||||||
|
|
||||||
// get Intersection point
|
|
||||||
double t = -n.dotProduct(start_v0) / direction;
|
|
||||||
Vec3d intersection = start.add(ray.multiply(t));
|
|
||||||
|
|
||||||
// check if the intersection is inside the triangle
|
|
||||||
for (int i = 0; i < v.length; i++) {
|
|
||||||
Vec3d edge = e[i];
|
|
||||||
Vec3d edge_intersection = intersection.subtract(v[i]);
|
|
||||||
if (edge_intersection.length() < 1e-6) break; // intersection is on the vertex
|
|
||||||
|
|
||||||
double a = n.dotProduct(edge.crossProduct(edge_intersection));
|
|
||||||
if (a <= 0) return null; // intersection is outside the triangle
|
|
||||||
if (a <= edge.length() * 1e-6) break; // intersection is on the edge
|
|
||||||
}
|
|
||||||
|
|
||||||
return intersection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean after(Vec3d point) {
|
|
||||||
return n.dotProduct(point.subtract(v[0])) > 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -53,8 +53,6 @@ public class GBlockstate extends FabricModelProvider {
|
|||||||
providers.put(ReFramedPostBlock.class, new Post());
|
providers.put(ReFramedPostBlock.class, new Post());
|
||||||
providers.put(ReFramedFenceBlock.class, new Fence());
|
providers.put(ReFramedFenceBlock.class, new Fence());
|
||||||
providers.put(ReFramedPostFenceBlock.class, new PostFence());
|
providers.put(ReFramedPostFenceBlock.class, new PostFence());
|
||||||
|
|
||||||
providers.put(TestBlock.class, new Test());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GBlockstate(FabricDataOutput output) {
|
public GBlockstate(FabricDataOutput output) {
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
package fr.adrien1106.reframed.generator.block;
|
|
||||||
|
|
||||||
import fr.adrien1106.reframed.generator.BlockStateProvider;
|
|
||||||
import fr.adrien1106.reframed.generator.GBlockstate;
|
|
||||||
import net.minecraft.block.Block;
|
|
||||||
import net.minecraft.data.client.BlockStateSupplier;
|
|
||||||
import net.minecraft.data.client.VariantsBlockStateSupplier;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import static net.minecraft.data.client.VariantSettings.Rotation.R0;
|
|
||||||
|
|
||||||
public class Test implements BlockStateProvider {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockStateSupplier getMultipart(Block block) {
|
|
||||||
return VariantsBlockStateSupplier.create(
|
|
||||||
block,
|
|
||||||
GBlockstate.variant(
|
|
||||||
new Identifier("block/barrier"),
|
|
||||||
true,
|
|
||||||
R0, R0
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,7 +25,6 @@
|
|||||||
"mixins": [
|
"mixins": [
|
||||||
"reframed.mixins.json"
|
"reframed.mixins.json"
|
||||||
],
|
],
|
||||||
"accessWidener": "reframed.accesswidener",
|
|
||||||
"depends": {
|
"depends": {
|
||||||
"minecraft": "${minecraft_version}",
|
"minecraft": "${minecraft_version}",
|
||||||
"fabricloader": "^${loader_version}",
|
"fabricloader": "^${loader_version}",
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
accessWidener v2 named
|
|
||||||
|
|
||||||
accessible field net/minecraft/util/shape/VoxelShape voxels Lnet/minecraft/util/shape/VoxelSet;
|
|
||||||
extendable class net/minecraft/util/shape/SimpleVoxelShape
|
|
Loading…
Reference in New Issue
Block a user