Skip to content

Commit 2f4c4b6

Browse files
committed
Remove capturing lambda's from MekanismJavaModel's wireframe rendering, and calculate normals of the wireframes properly. Also use hashes for comparing lines
1 parent ab256d4 commit 2f4c4b6

File tree

9 files changed

+116
-72
lines changed

9 files changed

+116
-72
lines changed

src/generators/java/mekanism/generators/client/model/ModelWindGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public void renderToBuffer(@NotNull PoseStack poseStack, @NotNull VertexConsumer
158158
renderPartsToBuffer(parts, poseStack, vertexConsumer, light, overlayLight, red, green, blue, alpha);
159159
}
160160

161-
public void renderWireFrame(PoseStack matrix, VertexConsumer vertexBuilder, double angle, int red, int green, int blue, int alpha) {
161+
public void renderWireFrame(PoseStack matrix, VertexConsumer vertexBuilder, double angle) {
162162
float baseRotation = getAbsoluteRotation(angle);
163163
setRotation(blade1a, 0F, 0F, baseRotation);
164164
setRotation(blade1b, 0F, 0F, 0.0349066F + baseRotation);
@@ -173,7 +173,7 @@ public void renderWireFrame(PoseStack matrix, VertexConsumer vertexBuilder, doub
173173

174174
setRotation(bladeCap, 0F, 0F, baseRotation);
175175
setRotation(bladeCenter, 0F, 0F, baseRotation);
176-
renderPartsAsWireFrame(parts, matrix, vertexBuilder, red, green, blue, alpha);
176+
renderPartsAsWireFrame(parts, matrix, vertexBuilder);
177177
}
178178

179179
private float getAbsoluteRotation(double angle) {

src/generators/java/mekanism/generators/client/render/RenderWindGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ public AABB getRenderBoundingBox(TileEntityWindGenerator tile) {
4949
}
5050

5151
@Override
52-
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer, int red, int green, int blue, int alpha) {
52+
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer) {
5353
if (tile instanceof TileEntityWindGenerator windGenerator) {
5454
double angle = setupRenderer(windGenerator, partialTick, matrix);
55-
model.renderWireFrame(matrix, buffer, angle, red, green, blue, alpha);
55+
model.renderWireFrame(matrix, buffer, angle);
5656
matrix.popPose();
5757
}
5858
}

src/main/java/mekanism/client/model/MekanismJavaModel.java

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33
import com.mojang.blaze3d.vertex.PoseStack;
44
import com.mojang.blaze3d.vertex.VertexConsumer;
55
import java.util.ArrayList;
6+
import java.util.HashSet;
67
import java.util.List;
8+
import java.util.Set;
79
import java.util.function.Function;
10+
import mekanism.client.render.RenderTickHandler;
11+
import mekanism.client.render.lib.Outlines.Line;
812
import net.minecraft.client.model.Model;
913
import net.minecraft.client.model.geom.ModelPart;
14+
import net.minecraft.client.model.geom.ModelPart.Cube;
1015
import net.minecraft.client.model.geom.builders.LayerDefinition;
1116
import net.minecraft.client.model.geom.builders.MeshDefinition;
1217
import net.minecraft.client.model.geom.builders.PartDefinition;
@@ -15,6 +20,7 @@
1520
import net.minecraft.client.renderer.entity.ItemRenderer;
1621
import net.minecraft.resources.ResourceLocation;
1722
import org.jetbrains.annotations.NotNull;
23+
import org.joml.Matrix3f;
1824
import org.joml.Matrix4f;
1925
import org.joml.Vector3f;
2026
import org.joml.Vector4f;
@@ -59,45 +65,54 @@ protected static LayerDefinition createLayerDefinition(int textureWidth, int tex
5965
return LayerDefinition.create(meshdefinition, textureWidth, textureHeight);
6066
}
6167

62-
protected static void renderPartsAsWireFrame(List<ModelPart> parts, PoseStack poseStack, @NotNull VertexConsumer vertexConsumer, int red, int green, int blue, int alpha) {
68+
protected static void renderPartsAsWireFrame(List<ModelPart> parts, PoseStack poseStack, @NotNull VertexConsumer vertexConsumer) {
69+
//tmp variables to avoid allocating for each model part
70+
Vector4f pos = new Vector4f();
71+
Vector3f normal = new Vector3f();
72+
Vector3f v0 = new Vector3f();
73+
Vector3f v1 = new Vector3f();
74+
Vector3f v2 = new Vector3f();
75+
Vector3f v3 = new Vector3f();
6376
for (ModelPart part : parts) {
64-
renderWireFrame(part, poseStack, vertexConsumer, red, green, blue, alpha);
77+
visit(part, poseStack, vertexConsumer, pos, normal, v0, v1, v2, v3);
6578
}
6679
}
6780

68-
//todo make this use XFact's code
69-
public static void renderWireFrame(ModelPart part, PoseStack matrix, VertexConsumer vertexConsumer, int red, int green, int blue, int alpha) {
81+
//Simplified version of ModelPart#visit that also avoids capturing lambdas
82+
private static void visit(ModelPart part, PoseStack poseStack, VertexConsumer vertexConsumer,
83+
//Variables that are just used to skip allocating extra times
84+
Vector4f pos, Vector3f normal, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f v3) {
7085
if (part.visible) {
71-
part.visit(matrix, (pose, name, cubeIndex, cube) -> {
72-
Matrix4f matrix4f = pose.pose();
73-
for (ModelPart.Polygon quad : cube.polygons) {
74-
Vector3f normal = new Vector3f(quad.normal);
75-
normal.mul(pose.normal());
76-
float normalX = normal.x();
77-
float normalY = normal.y();
78-
float normalZ = normal.z();
79-
Vector4f vertex = getVertex(matrix4f, quad.vertices[0]);
80-
Vector4f vertex2 = getVertex(matrix4f, quad.vertices[1]);
81-
Vector4f vertex3 = getVertex(matrix4f, quad.vertices[2]);
82-
Vector4f vertex4 = getVertex(matrix4f, quad.vertices[3]);
83-
vertexConsumer.vertex(vertex.x(), vertex.y(), vertex.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
84-
vertexConsumer.vertex(vertex2.x(), vertex2.y(), vertex2.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
85-
86-
vertexConsumer.vertex(vertex3.x(), vertex3.y(), vertex3.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
87-
vertexConsumer.vertex(vertex4.x(), vertex4.y(), vertex4.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
88-
//Vertices missing from base implementation
89-
vertexConsumer.vertex(vertex2.x(), vertex2.y(), vertex2.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
90-
vertexConsumer.vertex(vertex3.x(), vertex3.y(), vertex3.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
91-
92-
vertexConsumer.vertex(vertex.x(), vertex.y(), vertex.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
93-
vertexConsumer.vertex(vertex4.x(), vertex4.y(), vertex4.z()).color(red, green, blue, alpha).normal(normalX, normalY, normalZ).endVertex();
86+
if (!part.isEmpty() || !part.children.isEmpty()) {
87+
poseStack.pushPose();
88+
part.translateAndRotate(poseStack);
89+
visitAndRender(part.cubes, poseStack, vertexConsumer, pos, normal, v0, v1, v2, v3);
90+
for (ModelPart child : part.children.values()) {
91+
visit(child, poseStack, vertexConsumer, pos, normal, v0, v1, v2, v3);
9492
}
95-
});
93+
poseStack.popPose();
94+
}
9695
}
9796
}
9897

99-
private static Vector4f getVertex(Matrix4f matrix4f, ModelPart.Vertex vertex) {
100-
Vector4f vector4f = new Vector4f(vertex.pos.x() / 16F, vertex.pos.y() / 16F, vertex.pos.z() / 16F, 1);
101-
return vector4f.mul(matrix4f);
98+
private static void visitAndRender(List<ModelPart.Cube> cubes, PoseStack matrix, VertexConsumer buffer,
99+
//Variables that are just used to skip allocating extra times
100+
Vector4f pos, Vector3f normal, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f v3) {
101+
Matrix4f pose = matrix.last().pose();
102+
Matrix3f poseNormal = matrix.last().normal();
103+
Set<Line> lines = new HashSet<>();
104+
for (Cube cube : cubes) {
105+
for (ModelPart.Polygon quad : cube.polygons) {
106+
quad.vertices[0].pos.div(16, v0);
107+
quad.vertices[1].pos.div(16, v1);
108+
quad.vertices[2].pos.div(16, v2);
109+
quad.vertices[3].pos.div(16, v3);
110+
lines.add(new Line(v0, v1));
111+
lines.add(new Line(v1, v2));
112+
lines.add(new Line(v2, v3));
113+
lines.add(new Line(v3, v0));
114+
}
115+
}
116+
RenderTickHandler.renderVertexWireFrame(lines, buffer, pose, poseNormal, pos, normal);
102117
}
103118
}

src/main/java/mekanism/client/render/RenderTickHandler.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Map;
1111
import java.util.Map.Entry;
1212
import java.util.Objects;
13+
import java.util.Set;
1314
import java.util.UUID;
1415
import mekanism.api.RelativeSide;
1516
import mekanism.client.gui.GuiMekanism;
@@ -102,7 +103,7 @@ public class RenderTickHandler {
102103

103104
public static final Minecraft minecraft = Minecraft.getInstance();
104105

105-
private static final Map<BlockState, List<Line>> cachedWireFrames = new Reference2ObjectOpenHashMap<>();
106+
private static final Map<BlockState, Set<Line>> cachedWireFrames = new Reference2ObjectOpenHashMap<>();
106107
private static final Map<Direction, Map<TransmissionType, Model3D>> cachedOverlays = new EnumMap<>(Direction.class);
107108
private static final List<LazyRender> transparentRenderers = new ArrayList<>();
108109
private static final BoltRenderer boltRenderer = new BoltRenderer();
@@ -402,7 +403,7 @@ public void onBlockHover(RenderHighlightEvent.Block event) {
402403
if (wireFrameRenderer.isCombined()) {
403404
renderQuadsWireFrame(actualState, buffer, matrix, world.random);
404405
}
405-
wireFrameRenderer.renderWireFrame(tile, event.getPartialTick(), matrix, buffer, 0, 0, 0, 102);
406+
wireFrameRenderer.renderWireFrame(tile, event.getPartialTick(), matrix, buffer);
406407
matrix.popPose();
407408
shouldCancel = true;
408409
}
@@ -465,7 +466,7 @@ public void onBlockHover(RenderHighlightEvent.Block event) {
465466
}
466467

467468
private void renderQuadsWireFrame(BlockState state, VertexConsumer buffer, PoseStack matrix, RandomSource rand) {
468-
List<Line> lines = cachedWireFrames.get(state);
469+
Set<Line> lines = cachedWireFrames.get(state);
469470
if (lines == null) {
470471
BakedModel bakedModel = Minecraft.getInstance().getBlockRenderer().getBlockModel(state);
471472
//TODO: Eventually we may want to add support for Model data and maybe render type
@@ -476,11 +477,14 @@ private void renderQuadsWireFrame(BlockState state, VertexConsumer buffer, PoseS
476477
renderVertexWireFrame(lines, buffer, pose.pose(), pose.normal());
477478
}
478479

479-
public static void renderVertexWireFrame(List<Line> lines, VertexConsumer buffer, Matrix4f pose, Matrix3f poseNormal) {
480+
public static void renderVertexWireFrame(Set<Line> lines, VertexConsumer buffer, Matrix4f pose, Matrix3f poseNormal) {
480481
//tmp variables to avoid allocating each loop
481482
Vector4f pos = new Vector4f();
482483
Vector3f normal = new Vector3f();
484+
renderVertexWireFrame(lines, buffer, pose, poseNormal, pos, normal);
485+
}
483486

487+
public static void renderVertexWireFrame(Set<Line> lines, VertexConsumer buffer, Matrix4f pose, Matrix3f poseNormal, Vector4f pos, Vector3f normal) {
484488
for (Line line : lines) {
485489
poseNormal.transform(line.nX(), line.nY(), line.nZ(), normal);
486490

src/main/java/mekanism/client/render/lib/Outlines.java

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package mekanism.client.render.lib;
22

3-
import java.util.ArrayList;
43
import java.util.Arrays;
5-
import java.util.List;
4+
import java.util.HashSet;
5+
import java.util.Objects;
6+
import java.util.Set;
67
import mekanism.common.util.EnumUtils;
78
import net.minecraft.MethodsReturnNonnullByDefault;
89
import net.minecraft.client.renderer.RenderType;
@@ -19,8 +20,8 @@
1920

2021
public class Outlines {
2122

22-
public static List<Line> extract(BakedModel model, @Nullable BlockState state, RandomSource rand, ModelData modelData, @Nullable RenderType renderType) {
23-
List<Line> lines = new ArrayList<>();
23+
public static Set<Line> extract(BakedModel model, @Nullable BlockState state, RandomSource rand, ModelData modelData, @Nullable RenderType renderType) {
24+
Set<Line> lines = new HashSet<>();
2425
VertexExtractor consumer = new VertexExtractor(lines);
2526
for (Direction direction : EnumUtils.DIRECTIONS) {
2627
for (BakedQuad quad : model.getQuads(state, direction, rand, modelData, renderType)) {
@@ -38,33 +39,26 @@ public static List<Line> extract(BakedModel model, @Nullable BlockState state, R
3839
@MethodsReturnNonnullByDefault
3940
private static class VertexExtractor {
4041

41-
final List<Line> lines;
42+
final Set<Line> lines;
4243
final Vector3f[] vertices = new Vector3f[4];
4344
int vertexIndex = 0;
4445

45-
private VertexExtractor(List<Line> lines) {
46+
private VertexExtractor(Set<Line> lines) {
4647
this.lines = lines;
4748
}
4849

4950
public void vertex(float pX, float pY, float pZ) {
5051
vertices[vertexIndex++] = new Vector3f(pX, pY, pZ);
5152
if (vertexIndex == 4) {
5253
vertexIndex = 0;
53-
addLine(vertices[0], vertices[1]);
54-
addLine(vertices[1], vertices[2]);
55-
addLine(vertices[2], vertices[3]);
56-
addLine(vertices[3], vertices[0]);
54+
lines.add(new Line(vertices[0], vertices[1]));
55+
lines.add(new Line(vertices[1], vertices[2]));
56+
lines.add(new Line(vertices[2], vertices[3]));
57+
lines.add(new Line(vertices[3], vertices[0]));
5758
Arrays.fill(vertices, null);
5859
}
5960
}
6061

61-
private void addLine(Vector3f v1, Vector3f v2) {
62-
Line line = new Line(v1, v2);
63-
if (!lines.contains(line)) {
64-
lines.add(line);
65-
}
66-
}
67-
6862
//Based on how QuadTransformers#applying extracts the vertex positions
6963
public void unpack(BakedQuad pQuad) {
7064
int[] quadVertices = pQuad.getVertices();
@@ -78,7 +72,11 @@ public void unpack(BakedQuad pQuad) {
7872
}
7973
}
8074

81-
public record Line(float x1, float y1, float z1, float x2, float y2, float z2, float nX, float nY, float nZ) {
75+
public record Line(float x1, float y1, float z1, float x2, float y2, float z2, float nX, float nY, float nZ, int hash) {
76+
77+
public Line(float x1, float y1, float z1, float x2, float y2, float z2, float nX, float nY, float nZ) {
78+
this(x1, y1, z1, x2, y2, z2, nX, nY, nZ, calculateHash(x1, y1, z1, x2, y2, z2));
79+
}
8280

8381
public Line(Vector3f v1, Vector3f v2, Vector3f normal) {
8482
this(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, normal.x, normal.y, normal.z);
@@ -88,6 +86,29 @@ public Line(Vector3f v1, Vector3f v2) {
8886
this(v1, v2, v2.sub(v1, new Vector3f()).normalize());
8987
}
9088

89+
private static int calculateHash(float x1, float y1, float z1, float x2, float y2, float z2) {
90+
float minX = Math.min(x1, x2);
91+
float minY = Math.min(y1, y2);
92+
float minZ = Math.min(z1, z2);
93+
float maxX = Math.max(x1, x2);
94+
float maxY = Math.max(x1, x2);
95+
float maxZ = Math.max(x1, x2);
96+
//Supports up to a scale of 0.005 in the json (which the miner uses for LEDs)
97+
return Objects.hash(
98+
(long) (minX * 3_200),
99+
(long) (minY * 3_200),
100+
(long) (minZ * 3_200),
101+
(long) (maxX * 3_200),
102+
(long) (maxY * 3_200),
103+
(long) (maxZ * 3_200)
104+
);
105+
}
106+
107+
@Override
108+
public int hashCode() {
109+
return hash;
110+
}
111+
91112
@SuppressWarnings("SuspiciousNameCombination")
92113
@Override
93114
public boolean equals(Object obj) {

src/main/java/mekanism/client/render/tileentity/IWireFrameRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
public interface IWireFrameRenderer {
99

10-
void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer, int red, int green, int blue, int alpha);
10+
void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer);
1111

1212
default boolean hasSelectionBox(BlockState state) {
1313
return true;

src/main/java/mekanism/client/render/tileentity/RenderPigmentMixer.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
import com.mojang.blaze3d.vertex.PoseStack.Pose;
55
import com.mojang.blaze3d.vertex.VertexConsumer;
66
import com.mojang.math.Axis;
7-
import java.util.ArrayList;
8-
import java.util.List;
7+
import java.util.Set;
98
import mekanism.api.annotations.NothingNullByDefault;
109
import mekanism.client.model.MekanismModelCache;
1110
import mekanism.client.render.RenderTickHandler;
@@ -24,15 +23,17 @@
2423
import net.minecraft.world.phys.AABB;
2524
import net.minecraft.world.phys.Vec3;
2625
import net.neoforged.neoforge.client.model.data.ModelData;
26+
import org.jetbrains.annotations.Nullable;
2727

2828
@NothingNullByDefault
2929
public class RenderPigmentMixer extends MekanismTileEntityRenderer<TileEntityPigmentMixer> implements IWireFrameRenderer {
3030

31-
private static final List<Line> lines = new ArrayList<>();
3231
private static final float SHAFT_SPEED = 5F;
32+
@Nullable
33+
private static Set<Line> lines;
3334

3435
public static void resetCached() {
35-
lines.clear();
36+
lines = null;
3637
}
3738

3839
public RenderPigmentMixer(BlockEntityRendererProvider.Context context) {
@@ -73,10 +74,10 @@ public boolean isCombined() {
7374
}
7475

7576
@Override
76-
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer, int red, int green, int blue, int alpha) {
77+
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer) {
7778
if (tile instanceof TileEntityPigmentMixer mixer) {
78-
if (lines.isEmpty()) {
79-
lines.addAll(Outlines.extract(MekanismModelCache.INSTANCE.PIGMENT_MIXER_SHAFT.getBakedModel(), null, tile.getLevel().random, ModelData.EMPTY, null));
79+
if (lines == null) {
80+
lines = Outlines.extract(MekanismModelCache.INSTANCE.PIGMENT_MIXER_SHAFT.getBakedModel(), null, tile.getLevel().random, ModelData.EMPTY, null);
8081
}
8182
setupRenderer(mixer, partialTick, matrix);
8283
Pose pose = matrix.last();

src/main/java/mekanism/client/render/tileentity/RenderSeismicVibrator.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import com.mojang.blaze3d.vertex.PoseStack;
44
import com.mojang.blaze3d.vertex.PoseStack.Pose;
55
import com.mojang.blaze3d.vertex.VertexConsumer;
6-
import java.util.ArrayList;
7-
import java.util.List;
6+
import java.util.Set;
87
import mekanism.api.annotations.NothingNullByDefault;
98
import mekanism.client.model.MekanismModelCache;
109
import mekanism.client.render.RenderTickHandler;
@@ -21,14 +20,16 @@
2120
import net.minecraft.world.level.block.entity.BlockEntity;
2221
import net.minecraft.world.phys.AABB;
2322
import net.neoforged.neoforge.client.model.data.ModelData;
23+
import org.jetbrains.annotations.Nullable;
2424

2525
@NothingNullByDefault
2626
public class RenderSeismicVibrator extends MekanismTileEntityRenderer<TileEntitySeismicVibrator> implements IWireFrameRenderer {
2727

28-
private static final List<Line> lines = new ArrayList<>();
28+
@Nullable
29+
private static Set<Line> lines;
2930

3031
public static void resetCached() {
31-
lines.clear();
32+
lines = null;
3233
}
3334

3435
public RenderSeismicVibrator(BlockEntityRendererProvider.Context context) {
@@ -58,10 +59,10 @@ public boolean isCombined() {
5859
}
5960

6061
@Override
61-
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer, int red, int green, int blue, int alpha) {
62+
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer) {
6263
if (tile instanceof TileEntitySeismicVibrator vibrator) {
63-
if (lines.isEmpty()) {
64-
lines.addAll(Outlines.extract(MekanismModelCache.INSTANCE.VIBRATOR_SHAFT.getBakedModel(), null, tile.getLevel().random, ModelData.EMPTY, null));
64+
if (lines == null) {
65+
lines = Outlines.extract(MekanismModelCache.INSTANCE.VIBRATOR_SHAFT.getBakedModel(), null, tile.getLevel().random, ModelData.EMPTY, null);
6566
}
6667
setupRenderer(vibrator, partialTick, matrix);
6768
Pose pose = matrix.last();

0 commit comments

Comments
 (0)