Skip to content

Commit 94f6f67

Browse files
committed
redo outlines using XFact's normal calculations
1 parent e1b05e9 commit 94f6f67

File tree

6 files changed

+144
-64
lines changed

6 files changed

+144
-64
lines changed

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
import java.util.List;
55
import java.util.Map;
66
import java.util.function.Function;
7-
import mekanism.client.render.lib.Quad;
8-
import mekanism.client.render.lib.QuadUtils;
9-
import mekanism.client.render.lib.Vertex;
107
import mekanism.common.Mekanism;
118
import net.minecraft.client.Minecraft;
129
import net.minecraft.client.renderer.RenderType;
@@ -189,12 +186,6 @@ protected void setup(RegisterAdditional event) {
189186
event.register(rl);
190187
}
191188

192-
public void collectQuadVertices(List<Vertex[]> vertices, RandomSource random) {
193-
for (Quad quad : QuadUtils.unpack(getQuads(random))) {
194-
vertices.add(quad.getVertices());
195-
}
196-
}
197-
198189
public List<BakedQuad> getQuads(RandomSource random) {
199190
//TODO: Decide if this should just redirect to the other get quads method (some impls might be different depending on if it gets data and render type vs not)
200191
return getBakedModel().getQuads(null, null, random);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ protected static void renderPartsAsWireFrame(List<ModelPart> parts, PoseStack po
6565
}
6666
}
6767

68+
//todo make this use XFact's code
6869
public static void renderWireFrame(ModelPart part, PoseStack matrix, VertexConsumer vertexConsumer, int red, int green, int blue, int alpha) {
6970
if (part.visible) {
7071
part.visit(matrix, (pose, name, cubeIndex, cube) -> {

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

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import mekanism.client.render.armor.ISpecialGear;
2020
import mekanism.client.render.armor.MekaSuitArmor;
2121
import mekanism.client.render.hud.RadiationOverlay;
22+
import mekanism.client.render.lib.Outlines;
23+
import mekanism.client.render.lib.Outlines.Line;
2224
import mekanism.client.render.lib.Quad;
2325
import mekanism.client.render.lib.QuadUtils;
2426
import mekanism.client.render.lib.Vertex;
@@ -95,6 +97,7 @@
9597
import net.neoforged.neoforge.event.TickEvent.Phase;
9698
import org.jetbrains.annotations.NotNull;
9799
import org.jetbrains.annotations.Nullable;
100+
import org.joml.Matrix3f;
98101
import org.joml.Matrix4f;
99102
import org.joml.Vector3f;
100103
import org.joml.Vector4f;
@@ -103,7 +106,7 @@ public class RenderTickHandler {
103106

104107
public static final Minecraft minecraft = Minecraft.getInstance();
105108

106-
private static final Map<BlockState, List<Vertex[]>> cachedWireFrames = new HashMap<>();
109+
private static final Map<BlockState, List<Line>> cachedWireFrames = new HashMap<>();
107110
private static final Map<Direction, Map<TransmissionType, Model3D>> cachedOverlays = new EnumMap<>(Direction.class);
108111
private static final List<LazyRender> transparentRenderers = new ArrayList<>();
109112
private static final BoltRenderer boltRenderer = new BoltRenderer();
@@ -401,9 +404,9 @@ public void onBlockHover(RenderHighlightEvent.Block event) {
401404
VertexConsumer buffer = renderer.getBuffer(RenderType.lines());
402405
//0.4 Alpha
403406
if (wireFrameRenderer.isCombined()) {
404-
renderQuadsWireFrame(actualState, buffer, matrix, world.random, 0, 0, 0, 0x66);
407+
renderQuadsWireFrame(actualState, buffer, matrix, world.random);
405408
}
406-
wireFrameRenderer.renderWireFrame(tile, event.getPartialTick(), matrix, buffer, 0, 0, 0, 0x66);
409+
wireFrameRenderer.renderWireFrame(tile, event.getPartialTick(), matrix, buffer, 0, 0, 0, 102);
407410
matrix.popPose();
408411
shouldCancel = true;
409412
}
@@ -414,7 +417,7 @@ public void onBlockHover(RenderHighlightEvent.Block event) {
414417
Vec3 viewPosition = info.getPosition();
415418
matrix.translate(actualPos.getX() - viewPosition.x, actualPos.getY() - viewPosition.y, actualPos.getZ() - viewPosition.z);
416419
//0.4 Alpha
417-
renderQuadsWireFrame(actualState, renderer.getBuffer(RenderType.lines()), matrix, world.random, 0, 0, 0, 0x66);
420+
renderQuadsWireFrame(actualState, renderer.getBuffer(RenderType.lines()), matrix, world.random);
418421
matrix.popPose();
419422
shouldCancel = true;
420423
}
@@ -465,53 +468,33 @@ public void onBlockHover(RenderHighlightEvent.Block event) {
465468
}
466469
}
467470

468-
private void renderQuadsWireFrame(BlockState state, VertexConsumer buffer, PoseStack matrix, RandomSource rand, int red, int green, int blue, int alpha) {
469-
List<Vertex[]> vertices = cachedWireFrames.get(state);
470-
if (vertices == null) {
471+
private void renderQuadsWireFrame(BlockState state, VertexConsumer buffer, PoseStack matrix, RandomSource rand) {
472+
List<Line> lines = cachedWireFrames.get(state);
473+
if (lines == null) {
471474
BakedModel bakedModel = Minecraft.getInstance().getBlockRenderer().getBlockModel(state);
472475
//TODO: Eventually we may want to add support for Model data and maybe render type
473476
ModelData modelData = ModelData.EMPTY;
474-
vertices = new ArrayList<>();
475-
for (Direction direction : EnumUtils.DIRECTIONS) {
476-
for (Quad quad : QuadUtils.unpack(bakedModel.getQuads(state, direction, rand, modelData, null))) {
477-
vertices.add(quad.getVertices());
478-
}
479-
}
480-
for (Quad quad : QuadUtils.unpack(bakedModel.getQuads(state, null, rand, modelData, null))) {
481-
vertices.add(quad.getVertices());
482-
}
483-
cachedWireFrames.put(state, vertices);
477+
lines = Outlines.extract(bakedModel, state, rand, modelData);
478+
cachedWireFrames.put(state, lines);
484479
}
485-
renderVertexWireFrame(vertices, buffer, matrix.last().pose(), red, green, blue, alpha);
480+
PoseStack.Pose pose = matrix.last();
481+
renderVertexWireFrame(lines, buffer, pose.pose(), pose.normal());
486482
}
487483

488-
public static void renderVertexWireFrame(List<Vertex[]> allVertices, VertexConsumer buffer, Matrix4f matrix, int red, int green, int blue, int alpha) {
489-
for (Vertex[] vertices : allVertices) {
490-
Vector4f vertex = getVertex(matrix, vertices[0]);
491-
Vector3f normal = vertices[0].getNormal();
492-
Vector4f vertex2 = getVertex(matrix, vertices[1]);
493-
Vector3f normal2 = vertices[1].getNormal();
494-
Vector4f vertex3 = getVertex(matrix, vertices[2]);
495-
Vector3f normal3 = vertices[2].getNormal();
496-
Vector4f vertex4 = getVertex(matrix, vertices[3]);
497-
Vector3f normal4 = vertices[3].getNormal();
498-
buffer.vertex(vertex.x(), vertex.y(), vertex.z()).color(red, green, blue, alpha).normal(normal.x(), normal.y(), normal.z()).endVertex();
499-
buffer.vertex(vertex2.x(), vertex2.y(), vertex2.z()).color(red, green, blue, alpha).normal(normal2.x(), normal2.y(), normal2.z()).endVertex();
500-
501-
buffer.vertex(vertex3.x(), vertex3.y(), vertex3.z()).color(red, green, blue, alpha).normal(normal3.x(), normal3.y(), normal3.z()).endVertex();
502-
buffer.vertex(vertex4.x(), vertex4.y(), vertex4.z()).color(red, green, blue, alpha).normal(normal4.x(), normal4.y(), normal4.z()).endVertex();
503-
504-
buffer.vertex(vertex2.x(), vertex2.y(), vertex2.z()).color(red, green, blue, alpha).normal(normal2.x(), normal2.y(), normal2.z()).endVertex();
505-
buffer.vertex(vertex3.x(), vertex3.y(), vertex3.z()).color(red, green, blue, alpha).normal(normal3.x(), normal3.y(), normal3.z()).endVertex();
506-
507-
buffer.vertex(vertex.x(), vertex.y(), vertex.z()).color(red, green, blue, alpha).normal(normal.x(), normal.y(), normal.z()).endVertex();
508-
buffer.vertex(vertex4.x(), vertex4.y(), vertex4.z()).color(red, green, blue, alpha).normal(normal4.x(), normal4.y(), normal4.z()).endVertex();
509-
}
510-
}
484+
public static void renderVertexWireFrame(List<Line> lines, VertexConsumer buffer, Matrix4f pose, Matrix3f poseNormal) {
485+
//tmp variables to avoid allocating each loop
486+
Vector4f pos = new Vector4f();
487+
Vector3f normal = new Vector3f();
488+
489+
for (Line line : lines) {
490+
poseNormal.transform(line.nX(), line.nY(), line.nZ(), normal);
511491

512-
private static Vector4f getVertex(Matrix4f matrix4f, Vertex vertex) {
513-
Vector4f vector4f = new Vector4f((float) vertex.getPos().x(), (float) vertex.getPos().y(), (float) vertex.getPos().z(), 1);
514-
return vector4f.mul(matrix4f);
492+
pose.transform(line.x1(), line.y1(), line.z1(), 1F, pos);
493+
buffer.vertex(pos.x, pos.y, pos.z).color(0, 0, 0, 102).normal(normal.x, normal.y, normal.z).endVertex();
494+
495+
pose.transform(line.x2(), line.y2(), line.z2(), 1F, pos);
496+
buffer.vertex(pos.x, pos.y, pos.z).color(0, 0, 0, 102).normal(normal.x, normal.y, normal.z).endVertex();
497+
}
515498
}
516499

517500
private void renderJetpackSmoke(Level world, Vec3 pos, Vec3 motion) {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package mekanism.client.render.lib;
2+
3+
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
4+
import java.nio.ByteBuffer;
5+
import java.nio.IntBuffer;
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.List;
9+
import mekanism.common.util.EnumUtils;
10+
import net.minecraft.MethodsReturnNonnullByDefault;
11+
import net.minecraft.client.renderer.block.model.BakedQuad;
12+
import net.minecraft.client.resources.model.BakedModel;
13+
import net.minecraft.core.Direction;
14+
import net.minecraft.util.RandomSource;
15+
import net.minecraft.world.level.block.state.BlockState;
16+
import net.minecraft.world.phys.Vec3;
17+
import net.neoforged.neoforge.client.model.data.ModelData;
18+
import org.lwjgl.system.MemoryStack;
19+
20+
public class Outlines {
21+
22+
public static List<Line> extract(BakedModel model, BlockState state, RandomSource rand, ModelData modelData) {
23+
List<Line> lines = new ArrayList<>();
24+
VertexExtractor consumer = new VertexExtractor(lines);
25+
for (Direction direction : EnumUtils.DIRECTIONS) {
26+
//TODO: Eventually we may want to add support for Model data and maybe render type
27+
for (BakedQuad quad : model.getQuads(state, direction, rand, modelData, null)) {
28+
consumer.unpack(quad);
29+
}
30+
}
31+
32+
for (BakedQuad quad : model.getQuads(state, null, rand, modelData, null)) {
33+
consumer.unpack(quad);
34+
}
35+
return lines;
36+
}
37+
38+
//modified version of VertexConsumer
39+
@MethodsReturnNonnullByDefault
40+
private static class VertexExtractor {
41+
42+
final List<Line> lines;
43+
final Vec3[] vertices = new Vec3[4];
44+
int vertexIndex = 0;
45+
46+
private VertexExtractor(List<Line> lines) {
47+
this.lines = lines;
48+
}
49+
50+
public void vertex(double pX, double pY, double pZ) {
51+
vertices[vertexIndex++] = new Vec3(pX, pY, pZ);
52+
if (vertexIndex == 4) {
53+
vertexIndex = 0;
54+
addLine(vertices[0].x, vertices[0].y, vertices[0].z, vertices[1].x, vertices[1].y, vertices[1].z);
55+
addLine(vertices[1].x, vertices[1].y, vertices[1].z, vertices[2].x, vertices[2].y, vertices[2].z);
56+
addLine(vertices[2].x, vertices[2].y, vertices[2].z, vertices[3].x, vertices[3].y, vertices[3].z);
57+
addLine(vertices[3].x, vertices[3].y, vertices[3].z, vertices[0].x, vertices[0].y, vertices[0].z);
58+
Arrays.fill(vertices, null);
59+
}
60+
}
61+
62+
//slimmed down version of putBulkData
63+
public void unpack(BakedQuad pQuad) {
64+
int[] quadVertices = pQuad.getVertices();
65+
int elementCount = quadVertices.length / 8;
66+
67+
try (MemoryStack memorystack = MemoryStack.stackPush()) {
68+
ByteBuffer bytebuffer = memorystack.malloc(DefaultVertexFormat.BLOCK.getVertexSize());
69+
IntBuffer intbuffer = bytebuffer.asIntBuffer();
70+
71+
for (int k = 0; k < elementCount; ++k) {
72+
intbuffer.clear();
73+
intbuffer.put(quadVertices, k * 8, 8);
74+
float f = bytebuffer.getFloat(0);
75+
float f1 = bytebuffer.getFloat(4);
76+
float f2 = bytebuffer.getFloat(8);
77+
this.vertex(f, f1, f2);
78+
}
79+
}
80+
}
81+
82+
private void addLine(double x1, double y1, double z1, double x2, double y2, double z2) {
83+
double nX = (x2 - x1);
84+
double nY = (y2 - y1);
85+
double nZ = (z2 - z1);
86+
double nLen = Math.sqrt(nX * nX + nY * nY + nZ * nZ);
87+
88+
nX = nX / nLen;
89+
nY = nY / nLen;
90+
nZ = nZ / nLen;
91+
92+
lines.add(new Line((float) x1, (float) y1, (float) z1, (float) x2, (float) y2, (float) z2, (float) nX, (float) nY, (float) nZ));
93+
}
94+
95+
}
96+
97+
public record Line(float x1, float y1, float z1, float x2, float y2, float z2, float nX, float nY, float nZ) {}
98+
}

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import mekanism.api.annotations.NothingNullByDefault;
1010
import mekanism.client.model.MekanismModelCache;
1111
import mekanism.client.render.RenderTickHandler;
12+
import mekanism.client.render.lib.Outlines;
13+
import mekanism.client.render.lib.Outlines.Line;
1214
import mekanism.client.render.lib.Vertex;
1315
import mekanism.common.base.ProfilerConstants;
1416
import mekanism.common.block.attribute.Attribute;
@@ -22,15 +24,16 @@
2224
import net.minecraft.world.level.block.state.BlockState;
2325
import net.minecraft.world.phys.AABB;
2426
import net.minecraft.world.phys.Vec3;
27+
import net.neoforged.neoforge.client.model.data.ModelData;
2528

2629
@NothingNullByDefault
2730
public class RenderPigmentMixer extends MekanismTileEntityRenderer<TileEntityPigmentMixer> implements IWireFrameRenderer {
2831

29-
private static final List<Vertex[]> vertices = new ArrayList<>();
32+
private static final List<Line> lines = new ArrayList<>();
3033
private static final float SHAFT_SPEED = 5F;
3134

3235
public static void resetCached() {
33-
vertices.clear();
36+
lines.clear();
3437
}
3538

3639
public RenderPigmentMixer(BlockEntityRendererProvider.Context context) {
@@ -73,11 +76,12 @@ public boolean isCombined() {
7376
@Override
7477
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer, int red, int green, int blue, int alpha) {
7578
if (tile instanceof TileEntityPigmentMixer mixer) {
76-
if (vertices.isEmpty()) {
77-
MekanismModelCache.INSTANCE.PIGMENT_MIXER_SHAFT.collectQuadVertices(vertices, tile.getLevel().random);
79+
if (lines.isEmpty()) {
80+
lines.addAll(Outlines.extract(MekanismModelCache.INSTANCE.PIGMENT_MIXER_SHAFT.getBakedModel(), null, tile.getLevel().random, ModelData.EMPTY));
7881
}
7982
setupRenderer(mixer, partialTick, matrix);
80-
RenderTickHandler.renderVertexWireFrame(vertices, buffer, matrix.last().pose(), red, green, blue, alpha);
83+
Pose pose = matrix.last();
84+
RenderTickHandler.renderVertexWireFrame(lines, buffer, pose.pose(), pose.normal());
8185
matrix.popPose();
8286
}
8387
}

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import mekanism.api.annotations.NothingNullByDefault;
99
import mekanism.client.model.MekanismModelCache;
1010
import mekanism.client.render.RenderTickHandler;
11-
import mekanism.client.render.lib.Vertex;
11+
import mekanism.client.render.lib.Outlines;
12+
import mekanism.client.render.lib.Outlines.Line;
1213
import mekanism.common.base.ProfilerConstants;
1314
import mekanism.common.tile.machine.TileEntitySeismicVibrator;
1415
import net.minecraft.client.renderer.MultiBufferSource;
@@ -19,14 +20,15 @@
1920
import net.minecraft.util.profiling.ProfilerFiller;
2021
import net.minecraft.world.level.block.entity.BlockEntity;
2122
import net.minecraft.world.phys.AABB;
23+
import net.neoforged.neoforge.client.model.data.ModelData;
2224

2325
@NothingNullByDefault
2426
public class RenderSeismicVibrator extends MekanismTileEntityRenderer<TileEntitySeismicVibrator> implements IWireFrameRenderer {
2527

26-
private static final List<Vertex[]> vertices = new ArrayList<>();
28+
private static final List<Line> lines = new ArrayList<>();
2729

2830
public static void resetCached() {
29-
vertices.clear();
31+
lines.clear();
3032
}
3133

3234
public RenderSeismicVibrator(BlockEntityRendererProvider.Context context) {
@@ -58,11 +60,12 @@ public boolean isCombined() {
5860
@Override
5961
public void renderWireFrame(BlockEntity tile, float partialTick, PoseStack matrix, VertexConsumer buffer, int red, int green, int blue, int alpha) {
6062
if (tile instanceof TileEntitySeismicVibrator vibrator) {
61-
if (vertices.isEmpty()) {
62-
MekanismModelCache.INSTANCE.VIBRATOR_SHAFT.collectQuadVertices(vertices, tile.getLevel().random);
63+
if (lines.isEmpty()) {
64+
lines.addAll(Outlines.extract(MekanismModelCache.INSTANCE.VIBRATOR_SHAFT.getBakedModel(), null, tile.getLevel().random, ModelData.EMPTY));
6365
}
6466
setupRenderer(vibrator, partialTick, matrix);
65-
RenderTickHandler.renderVertexWireFrame(vertices, buffer, matrix.last().pose(), red, green, blue, alpha);
67+
Pose pose = matrix.last();
68+
RenderTickHandler.renderVertexWireFrame(lines, buffer, pose.pose(), pose.normal());
6669
matrix.popPose();
6770
}
6871
}

0 commit comments

Comments
 (0)