From d4106d545b0381c3bec304e727a136ea105a8468 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Fri, 10 Mar 2023 16:10:47 -0800 Subject: [PATCH] Rewrite outline buffering - Outline buffering now uses Vector3f instead of Vec3 to avoid creating many objects and double to float casts - Remove OutlineParams.transformNormals since it was not used - Rename OutlineParams#disableNormals to disableLineNormals since only lines have normals disabled - Fix seats not having descriptions --- .../java/com/simibubi/create/AllBlocks.java | 2 +- .../chassis/ChassisRangeDisplay.java | 2 +- .../glue/SuperGlueSelectionHandler.java | 8 +- .../zapper/ZapperRenderHandler.java | 2 +- .../WorldshaperRenderHandler.java | 2 +- .../trains/entity/TrainRelocator.java | 4 +- .../trains/track/TrackPlacement.java | 6 +- .../schematics/client/tools/FlipTool.java | 2 +- .../schematics/client/tools/RotateTool.java | 2 +- .../ponder/element/WorldSectionElement.java | 2 +- .../tileEntity/behaviour/ValueBox.java | 3 - .../utility/outliner/AABBOutline.java | 278 ++++++--- .../utility/outliner/BlockClusterOutline.java | 166 +++-- .../utility/outliner/ChasingAABBOutline.java | 8 +- .../utility/outliner/LineOutline.java | 74 ++- .../foundation/utility/outliner/Outline.java | 588 ++++++++++++++---- .../foundation/utility/outliner/Outliner.java | 60 +- 17 files changed, 886 insertions(+), 323 deletions(-) diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index a79ad7503..255f0037e 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -1347,7 +1347,7 @@ public class AllBlocks { .unlockedBy("has_seat", RegistrateRecipeProvider.has(AllItemTags.SEATS.tag)) .save(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_seat")); }) - .onRegisterAfter(Registry.ITEM_REGISTRY, v -> TooltipHelper.referTo(v, "block.create.brown_seat")) + .onRegisterAfter(Registry.ITEM_REGISTRY, v -> TooltipHelper.referTo(v, "block.create.seat")) .tag(AllBlockTags.SEATS.tag) .item() .tag(AllItemTags.SEATS.tag) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java index 26a1ca324..28aa93eaa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java @@ -37,7 +37,7 @@ public class ChassisRangeDisplay { timer = DISPLAY_TIME; CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(te)) .colored(0xFFFFFF) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 16f) .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java index b6ecc76de..fd9659dfe 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java @@ -100,7 +100,7 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showAABB(glueEntity, glueEntity.getBoundingBox()) .colored(h ? HIGHLIGHT : PASSIVE) .withFaceTextures(faceTex, faceTex) - .disableNormals() + .disableLineNormals() .lineWidth(h ? 1 / 16f : 1 / 64f); } } @@ -155,12 +155,12 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox) .colored(canReach && canAfford && !cancel ? HIGHLIGHT : FAIL) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.GLUE) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 16f); CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) .colored(0x4D9162) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 64f); } @@ -259,7 +259,7 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) .colored(0xB5F2C6) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.HIGHLIGHT_CHECKERED) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 24f); discard(); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java index 9028abdaa..7d25a0443 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java @@ -39,7 +39,7 @@ public class ZapperRenderHandler extends ShootableGadgetRenderHandler { cachedBeams.forEach(beam -> { CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity, false) - .disableNormals() + .disableLineNormals() .colored(0xffffff) .lineWidth(beam.itensity * 1 / 8f); }); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java index b5e8ed028..888a706b5 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java @@ -33,7 +33,7 @@ public class WorldshaperRenderHandler { CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get()) .colored(0xbfbfbf) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 32f) .withFaceTexture(AllSpecialTextures.CHECKERED); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java index 838a536cc..149120c53 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java @@ -121,7 +121,7 @@ public class TrainRelocator { Vec3 vec2 = toVisualise.get(i + 1); CreateClient.OUTLINER.showLine(Pair.of(relocating, i), vec1.add(0, -.925f, 0), vec2.add(0, -.925f, 0)) .colored(lastHoveredResult || i != toVisualise.size() - 2 ? 0x95CD41 : 0xEA5C2B) - .disableNormals() + .disableLineNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); } } @@ -269,7 +269,7 @@ public class TrainRelocator { public static void visualise(Train train, int i, Vec3 v1, Vec3 v2, boolean valid) { CreateClient.OUTLINER.showLine(Pair.of(train, i), v1.add(0, -.825f, 0), v2.add(0, -.825f, 0)) .colored(valid ? 0x95CD41 : 0xEA5C2B) - .disableNormals() + .disableLineNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java index 5ba52a756..a34fa562d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java +++ b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java @@ -726,13 +726,13 @@ public class TrackPlacement { .showLine(Pair.of(key, i * 2), VecHelper.lerp(s, middle1, previous1), VecHelper.lerp(s, middle1, rail1)) .colored(railcolor) - .disableNormals() + .disableLineNormals() .lineWidth(lw); CreateClient.OUTLINER .showLine(Pair.of(key, i * 2 + 1), VecHelper.lerp(s, middle2, previous2), VecHelper.lerp(s, middle2, rail2)) .colored(railcolor) - .disableNormals() + .disableLineNormals() .lineWidth(lw); } @@ -753,7 +753,7 @@ public class TrackPlacement { int color = Color.mixColors(0xEA5C2B, 0x95CD41, animation.getValue()); CreateClient.OUTLINER.showLine(Pair.of("start", id), v1.subtract(o1), v1.add(ex)) .lineWidth(1 / 8f) - .disableNormals() + .disableLineNormals() .colored(color); } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java index 10ceb1547..fa653d28c 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java @@ -72,7 +72,7 @@ public class FlipTool extends PlacementToolBase { AllSpecialTextures tex = AllSpecialTextures.CHECKERED; outline.getParams() .lineWidth(1 / 16f) - .disableNormals() + .disableLineNormals() .colored(0xdddddd) .withFaceTextures(tex, tex); outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java index 55b3e3dcc..21dcda4ad 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java @@ -32,7 +32,7 @@ public class RotateTool extends PlacementToolBase { line.getParams() .disableCull() - .disableNormals() + .disableLineNormals() .colored(0xdddddd) .lineWidth(1 / 16f); line.set(start, end) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java b/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java index a4bfb3537..0c6321006 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java @@ -398,7 +398,7 @@ public class WorldSectionElement extends AnimatedSceneElement { aabbOutline.getParams() .lineWidth(1 / 64f) .colored(0xefefef) - .disableNormals(); + .disableLineNormals(); aabbOutline.render(ms, (SuperRenderTypeBuffer) buffer, pt); ms.popPose(); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java index 75d6367d2..9f5b064ce 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBox.java @@ -87,9 +87,6 @@ public class ValueBox extends ChasingAABBOutline { ms.translate(pos.getX(), pos.getY(), pos.getZ()); if (hasTransform) transform.transform(blockState, ms); - transformNormals = ms.last() - .normal() - .copy(); params.colored(isPassive ? passiveColor : highlightColor); super.render(ms, buffer, pt); diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java index 12af40349..81b34939e 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/AABBOutline.java @@ -1,15 +1,18 @@ package com.simibubi.create.foundation.utility.outliner; +import java.util.Optional; + import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Vector3f; +import com.mojang.math.Vector4f; +import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -17,85 +20,212 @@ public class AABBOutline extends Outline { protected AABB bb; + protected final Vector3f minPosTemp1 = new Vector3f(); + protected final Vector3f maxPosTemp1 = new Vector3f(); + + protected final Vector4f colorTemp1 = new Vector4f(); + protected final Vector3f pos0Temp = new Vector3f(); + protected final Vector3f pos1Temp = new Vector3f(); + protected final Vector3f pos2Temp = new Vector3f(); + protected final Vector3f pos3Temp = new Vector3f(); + protected final Vector3f normalTemp = new Vector3f(); + protected final Vector3f originTemp = new Vector3f(); + public AABBOutline(AABB bb) { - this.setBounds(bb); + setBounds(bb); } - @Override - public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - renderBB(ms, buffer, bb); - } - - public void renderBB(PoseStack ms, SuperRenderTypeBuffer buffer, AABB bb) { - Vec3 projectedView = Minecraft.getInstance().gameRenderer.getMainCamera() - .getPosition(); - boolean noCull = bb.contains(projectedView); - bb = bb.inflate(noCull ? -1 / 128d : 1 / 128d); - noCull |= params.disableCull; - - Vec3 xyz = new Vec3(bb.minX, bb.minY, bb.minZ); - Vec3 Xyz = new Vec3(bb.maxX, bb.minY, bb.minZ); - Vec3 xYz = new Vec3(bb.minX, bb.maxY, bb.minZ); - Vec3 XYz = new Vec3(bb.maxX, bb.maxY, bb.minZ); - Vec3 xyZ = new Vec3(bb.minX, bb.minY, bb.maxZ); - Vec3 XyZ = new Vec3(bb.maxX, bb.minY, bb.maxZ); - Vec3 xYZ = new Vec3(bb.minX, bb.maxY, bb.maxZ); - Vec3 XYZ = new Vec3(bb.maxX, bb.maxY, bb.maxZ); - - Vec3 start = xyz; - renderAACuboidLine(ms, buffer, start, Xyz); - renderAACuboidLine(ms, buffer, start, xYz); - renderAACuboidLine(ms, buffer, start, xyZ); - - start = XyZ; - renderAACuboidLine(ms, buffer, start, xyZ); - renderAACuboidLine(ms, buffer, start, XYZ); - renderAACuboidLine(ms, buffer, start, Xyz); - - start = XYz; - renderAACuboidLine(ms, buffer, start, xYz); - renderAACuboidLine(ms, buffer, start, Xyz); - renderAACuboidLine(ms, buffer, start, XYZ); - - start = xYZ; - renderAACuboidLine(ms, buffer, start, XYZ); - renderAACuboidLine(ms, buffer, start, xyZ); - renderAACuboidLine(ms, buffer, start, xYz); - - renderFace(ms, buffer, Direction.NORTH, xYz, XYz, Xyz, xyz, noCull); - renderFace(ms, buffer, Direction.SOUTH, XYZ, xYZ, xyZ, XyZ, noCull); - renderFace(ms, buffer, Direction.EAST, XYz, XYZ, XyZ, Xyz, noCull); - renderFace(ms, buffer, Direction.WEST, xYZ, xYz, xyz, xyZ, noCull); - renderFace(ms, buffer, Direction.UP, xYZ, XYZ, XYz, xYz, noCull); - renderFace(ms, buffer, Direction.DOWN, xyz, Xyz, XyZ, xyZ, noCull); - - } - - protected void renderFace(PoseStack ms, SuperRenderTypeBuffer buffer, Direction direction, Vec3 p1, Vec3 p2, - Vec3 p3, Vec3 p4, boolean noCull) { - if (!params.faceTexture.isPresent()) - return; - - ResourceLocation faceTexture = params.faceTexture.get() - .getLocation(); - float alphaBefore = params.alpha; - params.alpha = - (direction == params.getHighlightedFace() && params.hightlightedFaceTexture.isPresent()) ? 1 : 0.5f; - - RenderType translucentType = RenderTypes.getOutlineTranslucent(faceTexture, !noCull); - VertexConsumer builder = buffer.getLateBuffer(translucentType); - - Axis axis = direction.getAxis(); - Vec3 uDiff = p2.subtract(p1); - Vec3 vDiff = p4.subtract(p1); - float maxU = (float) Math.abs(axis == Axis.X ? uDiff.z : uDiff.x); - float maxV = (float) Math.abs(axis == Axis.Y ? vDiff.z : vDiff.y); - putQuadUV(ms, builder, p1, p2, p3, p4, 0, 0, maxU, maxV, Direction.UP); - params.alpha = alphaBefore; + public AABB getBounds() { + return bb; } public void setBounds(AABB bb) { this.bb = bb; } + @Override + public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { + params.loadColor(colorTemp); + Vector4f color = colorTemp; + int lightmap = params.lightmap; + boolean disableLineNormals = params.disableLineNormals; + + renderBox(ms, buffer, bb, color, lightmap, disableLineNormals); + } + + protected void renderBox(PoseStack ms, SuperRenderTypeBuffer buffer, AABB box, Vector4f color, int lightmap, boolean disableLineNormals) { + Vector3f minPos = minPosTemp1; + Vector3f maxPos = maxPosTemp1; + + Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera() + .getPosition(); + boolean cameraInside = box.contains(cameraPos); + boolean cull = !cameraInside && !params.disableCull; + float inflate = cameraInside ? -1 / 128f : 1 / 128f; + minPos.set((float) box.minX - inflate, (float) box.minY - inflate, (float) box.minZ - inflate); + maxPos.set((float) box.maxX + inflate, (float) box.maxY + inflate, (float) box.maxZ + inflate); + + renderBoxFaces(ms, buffer, cull, params.getHighlightedFace(), minPos, maxPos, color, lightmap); + + float lineWidth = params.getLineWidth(); + if (lineWidth == 0) + return; + + VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); + renderBoxEdges(ms, consumer, minPos, maxPos, lineWidth, color, lightmap, disableLineNormals); + } + + protected void renderBoxFaces(PoseStack ms, SuperRenderTypeBuffer buffer, boolean cull, Direction highlightedFace, Vector3f minPos, Vector3f maxPos, Vector4f color, int lightmap) { + PoseStack.Pose pose = ms.last(); + renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.DOWN, color, lightmap); + renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.UP, color, lightmap); + renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.NORTH, color, lightmap); + renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.SOUTH, color, lightmap); + renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.WEST, color, lightmap); + renderBoxFace(pose, buffer, cull, highlightedFace, minPos, maxPos, Direction.EAST, color, lightmap); + } + + protected void renderBoxFace(PoseStack.Pose pose, SuperRenderTypeBuffer buffer, boolean cull, Direction highlightedFace, Vector3f minPos, Vector3f maxPos, Direction face, Vector4f color, int lightmap) { + boolean highlighted = face == highlightedFace; + + // TODO: Presumably, the other texture should be used, but this was not noticed before so fixing it may lead to suboptimal visuals. +// Optional optionalFaceTexture = highlighted ? params.hightlightedFaceTexture : params.faceTexture; + Optional optionalFaceTexture = params.faceTexture; + if (!optionalFaceTexture.isPresent()) + return; + AllSpecialTextures faceTexture = optionalFaceTexture.get(); + + RenderType renderType = RenderTypes.getOutlineTranslucent(faceTexture.getLocation(), cull); + VertexConsumer consumer = buffer.getLateBuffer(renderType); + + float alphaMult = highlighted ? 1 : 0.5f; + colorTemp1.set(color.x(), color.y(), color.z(), color.w() * alphaMult); + color = colorTemp1; + + renderBoxFace(pose, consumer, minPos, maxPos, face, color, lightmap); + } + + protected void renderBoxFace(PoseStack.Pose pose, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, Direction face, Vector4f color, int lightmap) { + Vector3f pos0 = pos0Temp; + Vector3f pos1 = pos1Temp; + Vector3f pos2 = pos2Temp; + Vector3f pos3 = pos3Temp; + Vector3f normal = normalTemp; + + float minX = minPos.x(); + float minY = minPos.y(); + float minZ = minPos.z(); + float maxX = maxPos.x(); + float maxY = maxPos.y(); + float maxZ = maxPos.z(); + + float maxU; + float maxV; + + switch (face) { + case DOWN -> { + // 0 1 2 3 + pos0.set(minX, minY, maxZ); + pos1.set(minX, minY, minZ); + pos2.set(maxX, minY, minZ); + pos3.set(maxX, minY, maxZ); + maxU = maxX - minX; + maxV = maxZ - minZ; + normal.set(0, -1, 0); + } + case UP -> { + // 4 5 6 7 + pos0.set(minX, maxY, minZ); + pos1.set(minX, maxY, maxZ); + pos2.set(maxX, maxY, maxZ); + pos3.set(maxX, maxY, minZ); + maxU = maxX - minX; + maxV = maxZ - minZ; + normal.set(0, 1, 0); + } + case NORTH -> { + // 7 2 1 4 + pos0.set(maxX, maxY, minZ); + pos1.set(maxX, minY, minZ); + pos2.set(minX, minY, minZ); + pos3.set(minX, maxY, minZ); + maxU = maxX - minX; + maxV = maxY - minY; + normal.set(0, 0, -1); + } + case SOUTH -> { + // 5 0 3 6 + pos0.set(minX, maxY, maxZ); + pos1.set(minX, minY, maxZ); + pos2.set(maxX, minY, maxZ); + pos3.set(maxX, maxY, maxZ); + maxU = maxX - minX; + maxV = maxY - minY; + normal.set(0, 0, 1); + } + case WEST -> { + // 4 1 0 5 + pos0.set(minX, maxY, minZ); + pos1.set(minX, minY, minZ); + pos2.set(minX, minY, maxZ); + pos3.set(minX, maxY, maxZ); + maxU = maxZ - minZ; + maxV = maxY - minY; + normal.set(-1, 0, 0); + } + case EAST -> { + // 6 3 2 7 + pos0.set(maxX, maxY, maxZ); + pos1.set(maxX, minY, maxZ); + pos2.set(maxX, minY, minZ); + pos3.set(maxX, maxY, minZ); + maxU = maxZ - minZ; + maxV = maxY - minY; + normal.set(1, 0, 0); + } + default -> { + maxU = 1; + maxV = 1; + } + } + + bufferQuad(pose, consumer, pos0, pos1, pos2, pos3, color, 0, 0, maxU, maxV, lightmap, normal); + } + + protected void renderBoxEdges(PoseStack ms, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, float lineWidth, Vector4f color, int lightmap, boolean disableNormals) { + Vector3f origin = originTemp; + + PoseStack.Pose pose = ms.last(); + + float lineLengthX = maxPos.x() - minPos.x(); + float lineLengthY = maxPos.y() - minPos.y(); + float lineLengthZ = maxPos.z() - minPos.z(); + + origin.load(minPos); + bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); + bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); + bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); + + origin.set(maxPos.x(), minPos.y(), minPos.z()); + bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); + bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); + + origin.set(minPos.x(), maxPos.y(), minPos.z()); + bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); + bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); + + origin.set(minPos.x(), minPos.y(), maxPos.z()); + bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); + bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); + + origin.set(minPos.x(), maxPos.y(), maxPos.z()); + bufferCuboidLine(pose, consumer, origin, Direction.EAST, lineLengthX, lineWidth, color, lightmap, disableNormals); + + origin.set(maxPos.x(), minPos.y(), maxPos.z()); + bufferCuboidLine(pose, consumer, origin, Direction.UP, lineLengthY, lineWidth, color, lightmap, disableNormals); + + origin.set(maxPos.x(), maxPos.y(), minPos.z()); + bufferCuboidLine(pose, consumer, origin, Direction.SOUTH, lineLengthZ, lineWidth, color, lightmap, disableNormals); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java index 0f005a5bb..b0f646ec2 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/BlockClusterOutline.java @@ -8,94 +8,156 @@ import java.util.Set; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Vector3f; +import com.mojang.math.Vector4f; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.phys.Vec3; public class BlockClusterOutline extends Outline { - private Cluster cluster; + private final Cluster cluster; - public BlockClusterOutline(Iterable selection) { + protected final Vector3f pos0Temp = new Vector3f(); + protected final Vector3f pos1Temp = new Vector3f(); + protected final Vector3f pos2Temp = new Vector3f(); + protected final Vector3f pos3Temp = new Vector3f(); + protected final Vector3f normalTemp = new Vector3f(); + protected final Vector3f originTemp = new Vector3f(); + + public BlockClusterOutline(Iterable positions) { cluster = new Cluster(); - selection.forEach(cluster::include); + positions.forEach(cluster::include); } @Override public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - cluster.visibleEdges.forEach(edge -> { - Vec3 start = Vec3.atLowerCornerOf(edge.pos); - Direction direction = Direction.get(AxisDirection.POSITIVE, edge.axis); - renderAACuboidLine(ms, buffer, start, Vec3.atLowerCornerOf(edge.pos.relative(direction))); - }); + params.loadColor(colorTemp); + Vector4f color = colorTemp; + int lightmap = params.lightmap; + boolean disableLineNormals = params.disableLineNormals; - Optional faceTexture = params.faceTexture; - if (!faceTexture.isPresent()) + renderFaces(ms, buffer, pt, color, lightmap); + renderEdges(ms, buffer, pt, color, lightmap, disableLineNormals); + } + + protected void renderFaces(PoseStack ms, SuperRenderTypeBuffer buffer, float pt, Vector4f color, int lightmap) { + Optional optionalFaceTexture = params.faceTexture; + if (!optionalFaceTexture.isPresent()) return; + AllSpecialTextures faceTexture = optionalFaceTexture.get(); - RenderType translucentType = RenderTypes.getOutlineTranslucent(faceTexture.get() - .getLocation(), true); - VertexConsumer builder = buffer.getLateBuffer(translucentType); + PoseStack.Pose pose = ms.last(); + RenderType renderType = RenderTypes.getOutlineTranslucent(faceTexture.getLocation(), true); + VertexConsumer consumer = buffer.getLateBuffer(renderType); cluster.visibleFaces.forEach((face, axisDirection) -> { Direction direction = Direction.get(axisDirection, face.axis); BlockPos pos = face.pos; if (axisDirection == AxisDirection.POSITIVE) pos = pos.relative(direction.getOpposite()); - renderBlockFace(ms, builder, pos, direction); + bufferBlockFace(pose, consumer, pos, direction, color, lightmap); }); } - static Vec3 xyz = new Vec3(-.5, -.5, -.5); - static Vec3 Xyz = new Vec3(.5, -.5, -.5); - static Vec3 xYz = new Vec3(-.5, .5, -.5); - static Vec3 XYz = new Vec3(.5, .5, -.5); - static Vec3 xyZ = new Vec3(-.5, -.5, .5); - static Vec3 XyZ = new Vec3(.5, -.5, .5); - static Vec3 xYZ = new Vec3(-.5, .5, .5); - static Vec3 XYZ = new Vec3(.5, .5, .5); - - protected void renderBlockFace(PoseStack ms, VertexConsumer builder, BlockPos pos, Direction face) { - Vec3 center = VecHelper.getCenterOf(pos); - Vec3 offset = Vec3.atLowerCornerOf(face.getNormal()); - offset = offset.scale(1 / 128d); - center = center.add(offset); + protected void renderEdges(PoseStack ms, SuperRenderTypeBuffer buffer, float pt, Vector4f color, int lightmap, boolean disableNormals) { + float lineWidth = params.getLineWidth(); + if (lineWidth == 0) + return; - ms.pushPose(); - ms.translate(center.x, center.y, center.z); + PoseStack.Pose pose = ms.last(); + VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); + cluster.visibleEdges.forEach(edge -> { + BlockPos pos = edge.pos; + Vector3f origin = originTemp; + origin.set(pos.getX(), pos.getY(), pos.getZ()); + Direction direction = Direction.get(AxisDirection.POSITIVE, edge.axis); + bufferCuboidLine(pose, consumer, origin, direction, 1, lineWidth, color, lightmap, disableNormals); + }); + } + + public static void loadFaceData(Direction face, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector3f normal) { switch (face) { - case DOWN: - putQuad(ms, builder, xyz, Xyz, XyZ, xyZ, face); - break; - case EAST: - putQuad(ms, builder, XYz, XYZ, XyZ, Xyz, face); - break; - case NORTH: - putQuad(ms, builder, xYz, XYz, Xyz, xyz, face); - break; - case SOUTH: - putQuad(ms, builder, XYZ, xYZ, xyZ, XyZ, face); - break; - case UP: - putQuad(ms, builder, xYZ, XYZ, XYz, xYz, face); - break; - case WEST: - putQuad(ms, builder, xYZ, xYz, xyz, xyZ, face); - default: - break; + case DOWN -> { + // 0 1 2 3 + pos0.set(0, 0, 1); + pos1.set(0, 0, 0); + pos2.set(1, 0, 0); + pos3.set(1, 0, 1); + normal.set(0, -1, 0); } + case UP -> { + // 4 5 6 7 + pos0.set(0, 1, 0); + pos1.set(0, 1, 1); + pos2.set(1, 1, 1); + pos3.set(1, 1, 0); + normal.set(0, 1, 0); + } + case NORTH -> { + // 7 2 1 4 + pos0.set(1, 1, 0); + pos1.set(1, 0, 0); + pos2.set(0, 0, 0); + pos3.set(0, 1, 0); + normal.set(0, 0, -1); + } + case SOUTH -> { + // 5 0 3 6 + pos0.set(0, 1, 1); + pos1.set(0, 0, 1); + pos2.set(1, 0, 1); + pos3.set(1, 1, 1); + normal.set(0, 0, 1); + } + case WEST -> { + // 4 1 0 5 + pos0.set(0, 1, 0); + pos1.set(0, 0, 0); + pos2.set(0, 0, 1); + pos3.set(0, 1, 1); + normal.set(-1, 0, 0); + } + case EAST -> { + // 6 3 2 7 + pos0.set(1, 1, 1); + pos1.set(1, 0, 1); + pos2.set(1, 0, 0); + pos3.set(1, 1, 0); + normal.set(1, 0, 0); + } + } + } - ms.popPose(); + public static void addPos(float x, float y, float z, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3) { + pos0.add(x, y, z); + pos1.add(x, y, z); + pos2.add(x, y, z); + pos3.add(x, y, z); + } + + protected void bufferBlockFace(PoseStack.Pose pose, VertexConsumer consumer, BlockPos pos, Direction face, Vector4f color, int lightmap) { + Vector3f pos0 = pos0Temp; + Vector3f pos1 = pos1Temp; + Vector3f pos2 = pos2Temp; + Vector3f pos3 = pos3Temp; + Vector3f normal = normalTemp; + + loadFaceData(face, pos0, pos1, pos2, pos3, normal); + addPos(pos.getX() + face.getStepX() * 1 / 128f, + pos.getY() + face.getStepY() * 1 / 128f, + pos.getZ() + face.getStepZ() * 1 / 128f, + pos0, pos1, pos2, pos3); + + bufferQuad(pose, consumer, pos0, pos1, pos2, pos3, color, lightmap, normal); } private static class Cluster { diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java index 4c0b22ba4..6ca4b1550 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java @@ -1,6 +1,7 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Vector4f; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.util.Mth; @@ -29,7 +30,12 @@ public class ChasingAABBOutline extends AABBOutline { @Override public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - renderBB(ms, buffer, interpolateBBs(prevBB, bb, pt)); + params.loadColor(colorTemp); + Vector4f color = colorTemp; + int lightmap = params.lightmap; + boolean disableLineNormals = params.disableLineNormals; + + renderBox(ms, buffer, interpolateBBs(prevBB, bb, pt), color, lightmap, disableLineNormals); } private static AABB interpolateBBs(AABB current, AABB target, float pt) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java index 7803dbe84..d59aa203b 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java @@ -1,6 +1,10 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Vector3f; +import com.mojang.math.Vector4f; +import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.util.Mth; @@ -8,33 +12,50 @@ import net.minecraft.world.phys.Vec3; public class LineOutline extends Outline { - protected Vec3 start = Vec3.ZERO; - protected Vec3 end = Vec3.ZERO; + protected final Vector3f start = new Vector3f(); + protected final Vector3f end = new Vector3f(); + + public LineOutline set(Vector3f start, Vector3f end) { + this.start.load(start); + this.start.load(end); + return this; + } public LineOutline set(Vec3 start, Vec3 end) { - this.start = start; - this.end = end; + this.start.set((float) start.x, (float) start.y, (float) start.z); + this.end.set((float) end.x, (float) end.y, (float) end.z); return this; } @Override public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { - renderCuboidLine(ms, buffer, start, end); + float width = params.getLineWidth(); + if (width == 0) + return; + + VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid()); + params.loadColor(colorTemp); + Vector4f color = colorTemp; + int lightmap = params.lightmap; + boolean disableLineNormals = params.disableLineNormals; + renderInner(ms, consumer, pt, width, color, lightmap, disableLineNormals); + } + + protected void renderInner(PoseStack ms, VertexConsumer consumer, float pt, float width, Vector4f color, int lightmap, boolean disableNormals) { + bufferCuboidLine(ms, consumer, start, end, width, color, lightmap, disableNormals); } public static class EndChasingLineOutline extends LineOutline { - - float prevProgress = 0; - float progress = 0; + private float progress = 0; + private float prevProgress = 0; private boolean lockStart; + private final Vector3f startTemp = new Vector3f(); + public EndChasingLineOutline(boolean lockStart) { this.lockStart = lockStart; } - @Override - public void tick() {} - public EndChasingLineOutline setProgress(float progress) { prevProgress = this.progress; this.progress = progress; @@ -42,25 +63,24 @@ public class LineOutline extends Outline { } @Override - public LineOutline set(Vec3 start, Vec3 end) { - if (!end.equals(this.end)) - super.set(start, end); - return this; - } - - @Override - public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { + protected void renderInner(PoseStack ms, VertexConsumer consumer, float pt, float width, Vector4f color, int lightmap, boolean disableNormals) { float distanceToTarget = Mth.lerp(pt, prevProgress, progress); - if (!lockStart) + Vector3f end; + if (lockStart) { + end = this.start; + } else { + end = this.end; distanceToTarget = 1 - distanceToTarget; - Vec3 start = lockStart ? this.end : this.start; - Vec3 end = lockStart ? this.start : this.end; - - start = end.add(this.start.subtract(end) - .scale(distanceToTarget)); - renderCuboidLine(ms, buffer, start, end); - } + } + Vector3f start = this.startTemp; + start.load(this.start); + start.sub(end); + start.mul(distanceToTarget); + start.add(end); + + bufferCuboidLine(ms, consumer, start, end, width, color, lightmap, disableNormals); + } } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java index 8f0b7d62e..071274aab 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java @@ -8,156 +8,497 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; +import com.mojang.math.Vector3f; +import com.mojang.math.Vector4f; import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; import net.minecraft.util.Mth; -import net.minecraft.world.phys.Vec3; public abstract class Outline { - protected OutlineParams params; - protected Matrix3f transformNormals; // TODO: not used? + protected final OutlineParams params; + + protected final Vector4f colorTemp = new Vector4f(); + protected final Vector3f diffPosTemp = new Vector3f(); + protected final Vector3f minPosTemp = new Vector3f(); + protected final Vector3f maxPosTemp = new Vector3f(); + protected final Vector4f posTransformTemp = new Vector4f(); + protected final Vector3f normalTransformTemp = new Vector3f(); public Outline() { params = new OutlineParams(); } + public OutlineParams getParams() { + return params; + } + public abstract void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt); public void tick() {} - public OutlineParams getParams() { - return params; + public void bufferCuboidLine(PoseStack poseStack, VertexConsumer consumer, Vector3f start, Vector3f end, float width, Vector4f color, int lightmap, boolean disableNormals) { + Vector3f diff = this.diffPosTemp; + diff.load(end); + diff.sub(start); + + float length = Mth.sqrt(diff.x() * diff.x() + diff.y() * diff.y() + diff.z() * diff.z()); + float hAngle = AngleHelper.deg(Mth.atan2(diff.x(), diff.z())); + float hDistance = Mth.sqrt(diff.x() * diff.x() + diff.z() * diff.z()); + float vAngle = AngleHelper.deg(Mth.atan2(hDistance, diff.y())) - 90; + + poseStack.pushPose(); + TransformStack.cast(poseStack) + .rotateY(hAngle) + .rotateX(vAngle); + bufferCuboidLine(poseStack.last(), consumer, start, Direction.NORTH, length, width, color, lightmap, disableNormals); + poseStack.popPose(); } - public void renderCuboidLine(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 start, Vec3 end) { - Vec3 diff = end.subtract(start); - float hAngle = AngleHelper.deg(Mth.atan2(diff.x, diff.z)); - float hDistance = (float) diff.multiply(1, 0, 1) - .length(); - float vAngle = AngleHelper.deg(Mth.atan2(hDistance, diff.y)) - 90; - ms.pushPose(); - TransformStack.cast(ms) - .translate(start) - .rotateY(hAngle).rotateX(vAngle); - renderAACuboidLine(ms, buffer, Vec3.ZERO, new Vec3(0, 0, diff.length())); - ms.popPose(); - } + public void bufferCuboidLine(PoseStack.Pose pose, VertexConsumer consumer, Vector3f origin, Direction direction, float length, float width, Vector4f color, int lightmap, boolean disableNormals) { + Vector3f minPos = minPosTemp; + Vector3f maxPos = maxPosTemp; - public void renderAACuboidLine(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 start, Vec3 end) { - float lineWidth = params.getLineWidth(); - if (lineWidth == 0) - return; + float halfWidth = width / 2; + minPos.set(origin.x() - halfWidth, origin.y() - halfWidth, origin.z() - halfWidth); + maxPos.set(origin.x() + halfWidth, origin.y() + halfWidth, origin.z() + halfWidth); - VertexConsumer builder = buffer.getBuffer(RenderTypes.getOutlineSolid()); - - Vec3 diff = end.subtract(start); - if (diff.x + diff.y + diff.z < 0) { - Vec3 temp = start; - start = end; - end = temp; - diff = diff.scale(-1); + switch (direction) { + case DOWN -> { + minPos.add(0, -length, 0); + } + case UP -> { + maxPos.add(0, length, 0); + } + case NORTH -> { + minPos.add(0, 0, -length); + } + case SOUTH -> { + maxPos.add(0, 0, length); + } + case WEST -> { + minPos.add(-length, 0, 0); + } + case EAST -> { + maxPos.add(length, 0, 0); + } } - Vec3 extension = diff.normalize() - .scale(lineWidth / 2); - Vec3 plane = VecHelper.axisAlingedPlaneOf(diff); - Direction face = Direction.getNearest(diff.x, diff.y, diff.z); - Axis axis = face.getAxis(); + bufferCuboid(pose, consumer, minPos, maxPos, color, lightmap, disableNormals); + } - start = start.subtract(extension); - end = end.add(extension); - plane = plane.scale(lineWidth / 2); + public void bufferCuboid(PoseStack.Pose pose, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, Vector4f color, int lightmap, boolean disableNormals) { + Vector4f posTransformTemp = this.posTransformTemp; + Vector3f normalTransformTemp = this.normalTransformTemp; - Vec3 a1 = plane.add(start); - Vec3 b1 = plane.add(end); - plane = VecHelper.rotate(plane, -90, axis); - Vec3 a2 = plane.add(start); - Vec3 b2 = plane.add(end); - plane = VecHelper.rotate(plane, -90, axis); - Vec3 a3 = plane.add(start); - Vec3 b3 = plane.add(end); - plane = VecHelper.rotate(plane, -90, axis); - Vec3 a4 = plane.add(start); - Vec3 b4 = plane.add(end); + float minX = minPos.x(); + float minY = minPos.y(); + float minZ = minPos.z(); + float maxX = maxPos.x(); + float maxY = maxPos.y(); + float maxZ = maxPos.z(); - if (params.disableNormals) { - face = Direction.UP; - putQuad(ms, builder, b4, b3, b2, b1, face); - putQuad(ms, builder, a1, a2, a3, a4, face); - putQuad(ms, builder, a1, b1, b2, a2, face); - putQuad(ms, builder, a2, b2, b3, a3, face); - putQuad(ms, builder, a3, b3, b4, a4, face); - putQuad(ms, builder, a4, b4, b1, a1, face); - return; + Matrix4f posMatrix = pose.pose(); + + posTransformTemp.set(minX, minY, maxZ, 1); + posTransformTemp.transform(posMatrix); + double x0 = posTransformTemp.x(); + double y0 = posTransformTemp.y(); + double z0 = posTransformTemp.z(); + + posTransformTemp.set(minX, minY, minZ, 1); + posTransformTemp.transform(posMatrix); + double x1 = posTransformTemp.x(); + double y1 = posTransformTemp.y(); + double z1 = posTransformTemp.z(); + + posTransformTemp.set(maxX, minY, minZ, 1); + posTransformTemp.transform(posMatrix); + double x2 = posTransformTemp.x(); + double y2 = posTransformTemp.y(); + double z2 = posTransformTemp.z(); + + posTransformTemp.set(maxX, minY, maxZ, 1); + posTransformTemp.transform(posMatrix); + double x3 = posTransformTemp.x(); + double y3 = posTransformTemp.y(); + double z3 = posTransformTemp.z(); + + posTransformTemp.set(minX, maxY, minZ, 1); + posTransformTemp.transform(posMatrix); + double x4 = posTransformTemp.x(); + double y4 = posTransformTemp.y(); + double z4 = posTransformTemp.z(); + + posTransformTemp.set(minX, maxY, maxZ, 1); + posTransformTemp.transform(posMatrix); + double x5 = posTransformTemp.x(); + double y5 = posTransformTemp.y(); + double z5 = posTransformTemp.z(); + + posTransformTemp.set(maxX, maxY, maxZ, 1); + posTransformTemp.transform(posMatrix); + double x6 = posTransformTemp.x(); + double y6 = posTransformTemp.y(); + double z6 = posTransformTemp.z(); + + posTransformTemp.set(maxX, maxY, minZ, 1); + posTransformTemp.transform(posMatrix); + double x7 = posTransformTemp.x(); + double y7 = posTransformTemp.y(); + double z7 = posTransformTemp.z(); + + float r = color.x(); + float g = color.y(); + float b = color.z(); + float a = color.w(); + + Matrix3f normalMatrix = pose.normal(); + + // down + + if (disableNormals) { + normalTransformTemp.set(0, 1, 0); + } else { + normalTransformTemp.set(0, -1, 0); } + normalTransformTemp.transform(normalMatrix); + float nx0 = normalTransformTemp.x(); + float ny0 = normalTransformTemp.y(); + float nz0 = normalTransformTemp.z(); - putQuad(ms, builder, b4, b3, b2, b1, face); - putQuad(ms, builder, a1, a2, a3, a4, face.getOpposite()); - Vec3 vec = a1.subtract(a4); - face = Direction.getNearest(vec.x, vec.y, vec.z); - putQuad(ms, builder, a1, b1, b2, a2, face); - vec = VecHelper.rotate(vec, -90, axis); - face = Direction.getNearest(vec.x, vec.y, vec.z); - putQuad(ms, builder, a2, b2, b3, a3, face); - vec = VecHelper.rotate(vec, -90, axis); - face = Direction.getNearest(vec.x, vec.y, vec.z); - putQuad(ms, builder, a3, b3, b4, a4, face); - vec = VecHelper.rotate(vec, -90, axis); - face = Direction.getNearest(vec.x, vec.y, vec.z); - putQuad(ms, builder, a4, b4, b1, a1, face); - } - - public void putQuad(PoseStack ms, VertexConsumer builder, Vec3 v1, Vec3 v2, Vec3 v3, Vec3 v4, - Direction normal) { - putQuadUV(ms, builder, v1, v2, v3, v4, 0, 0, 1, 1, normal); - } - - public void putQuadUV(PoseStack ms, VertexConsumer builder, Vec3 v1, Vec3 v2, Vec3 v3, Vec3 v4, float minU, - float minV, float maxU, float maxV, Direction normal) { - putVertex(ms, builder, v1, minU, minV, normal); - putVertex(ms, builder, v2, maxU, minV, normal); - putVertex(ms, builder, v3, maxU, maxV, normal); - putVertex(ms, builder, v4, minU, maxV, normal); - } - - protected void putVertex(PoseStack ms, VertexConsumer builder, Vec3 pos, float u, float v, Direction normal) { - putVertex(ms.last(), builder, (float) pos.x, (float) pos.y, (float) pos.z, u, v, normal); - } - - protected void putVertex(PoseStack.Pose pose, VertexConsumer builder, float x, float y, float z, float u, float v, Direction normal) { - Color rgb = params.rgb; - if (transformNormals == null) - transformNormals = pose.normal(); - - int xOffset = 0; - int yOffset = 0; - int zOffset = 0; - - if (normal != null) { - xOffset = normal.getStepX(); - yOffset = normal.getStepY(); - zOffset = normal.getStepZ(); - } - - builder.vertex(pose.pose(), x, y, z) - .color(rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(), rgb.getAlphaAsFloat() * params.alpha) - .uv(u, v) + consumer.vertex(x0, y0, z0) + .color(r, g, b, a) + .uv(0, 0) .overlayCoords(OverlayTexture.NO_OVERLAY) - .uv2(params.lightMap) - .normal(pose.normal(), xOffset, yOffset, zOffset) + .uv2(lightmap) + .normal(nx0, ny0, nz0) .endVertex(); - transformNormals = null; + consumer.vertex(x1, y1, z1) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx0, ny0, nz0) + .endVertex(); + + consumer.vertex(x2, y2, z2) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx0, ny0, nz0) + .endVertex(); + + consumer.vertex(x3, y3, z3) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx0, ny0, nz0) + .endVertex(); + + // up + + normalTransformTemp.set(0, 1, 0); + normalTransformTemp.transform(normalMatrix); + float nx1 = normalTransformTemp.x(); + float ny1 = normalTransformTemp.y(); + float nz1 = normalTransformTemp.z(); + + consumer.vertex(x4, y4, z4) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + consumer.vertex(x5, y5, z5) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + consumer.vertex(x6, y6, z6) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + consumer.vertex(x7, y7, z7) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx1, ny1, nz1) + .endVertex(); + + // north + + if (disableNormals) { + normalTransformTemp.set(0, 1, 0); + } else { + normalTransformTemp.set(0, 0, -1); + } + normalTransformTemp.transform(normalMatrix); + float nx2 = normalTransformTemp.x(); + float ny2 = normalTransformTemp.y(); + float nz2 = normalTransformTemp.z(); + + consumer.vertex(x7, y7, z7) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + consumer.vertex(x2, y2, z2) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + consumer.vertex(x1, y1, z1) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + consumer.vertex(x4, y4, z4) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx2, ny2, nz2) + .endVertex(); + + // south + + if (disableNormals) { + normalTransformTemp.set(0, 1, 0); + } else { + normalTransformTemp.set(0, 0, 1); + } + normalTransformTemp.transform(normalMatrix); + float nx3 = normalTransformTemp.x(); + float ny3 = normalTransformTemp.y(); + float nz3 = normalTransformTemp.z(); + + consumer.vertex(x5, y5, z5) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + consumer.vertex(x0, y0, z0) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + consumer.vertex(x3, y3, z3) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + consumer.vertex(x6, y6, z6) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx3, ny3, nz3) + .endVertex(); + + // west + + if (disableNormals) { + normalTransformTemp.set(0, 1, 0); + } else { + normalTransformTemp.set(-1, 0, 0); + } + normalTransformTemp.transform(normalMatrix); + float nx4 = normalTransformTemp.x(); + float ny4 = normalTransformTemp.y(); + float nz4 = normalTransformTemp.z(); + + consumer.vertex(x4, y4, z4) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + consumer.vertex(x1, y1, z1) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + consumer.vertex(x0, y0, z0) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + consumer.vertex(x5, y5, z5) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx4, ny4, nz4) + .endVertex(); + + // east + + if (disableNormals) { + normalTransformTemp.set(0, 1, 0); + } else { + normalTransformTemp.set(1, 0, 0); + } + normalTransformTemp.transform(normalMatrix); + float nx5 = normalTransformTemp.x(); + float ny5 = normalTransformTemp.y(); + float nz5 = normalTransformTemp.z(); + + consumer.vertex(x6, y6, z6) + .color(r, g, b, a) + .uv(0, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + + consumer.vertex(x3, y3, z3) + .color(r, g, b, a) + .uv(0, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + + consumer.vertex(x2, y2, z2) + .color(r, g, b, a) + .uv(1, 1) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + + consumer.vertex(x7, y7, z7) + .color(r, g, b, a) + .uv(1, 0) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx5, ny5, nz5) + .endVertex(); + } + + public void bufferQuad(PoseStack.Pose pose, VertexConsumer consumer, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector4f color, int lightmap, Vector3f normal) { + bufferQuad(pose, consumer, pos0, pos1, pos2, pos3, color, 0, 0, 1, 1, lightmap, normal); + } + + public void bufferQuad(PoseStack.Pose pose, VertexConsumer consumer, Vector3f pos0, Vector3f pos1, Vector3f pos2, Vector3f pos3, Vector4f color, float minU, float minV, float maxU, float maxV, int lightmap, Vector3f normal) { + Vector4f posTransformTemp = this.posTransformTemp; + Vector3f normalTransformTemp = this.normalTransformTemp; + + Matrix4f posMatrix = pose.pose(); + + posTransformTemp.set(pos0.x(), pos0.y(), pos0.z(), 1); + posTransformTemp.transform(posMatrix); + double x0 = posTransformTemp.x(); + double y0 = posTransformTemp.y(); + double z0 = posTransformTemp.z(); + + posTransformTemp.set(pos1.x(), pos1.y(), pos1.z(), 1); + posTransformTemp.transform(posMatrix); + double x1 = posTransformTemp.x(); + double y1 = posTransformTemp.y(); + double z1 = posTransformTemp.z(); + + posTransformTemp.set(pos2.x(), pos2.y(), pos2.z(), 1); + posTransformTemp.transform(posMatrix); + double x2 = posTransformTemp.x(); + double y2 = posTransformTemp.y(); + double z2 = posTransformTemp.z(); + + posTransformTemp.set(pos3.x(), pos3.y(), pos3.z(), 1); + posTransformTemp.transform(posMatrix); + double x3 = posTransformTemp.x(); + double y3 = posTransformTemp.y(); + double z3 = posTransformTemp.z(); + + float r = color.x(); + float g = color.y(); + float b = color.z(); + float a = color.w(); + + normalTransformTemp.load(normal); + normalTransformTemp.transform(pose.normal()); + float nx = normalTransformTemp.x(); + float ny = normalTransformTemp.y(); + float nz = normalTransformTemp.z(); + + consumer.vertex(x0, y0, z0) + .color(r, g, b, a) + .uv(minU, minV) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx, ny, nz) + .endVertex(); + + consumer.vertex(x1, y1, z1) + .color(r, g, b, a) + .uv(minU, maxV) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx, ny, nz) + .endVertex(); + + consumer.vertex(x2, y2, z2) + .color(r, g, b, a) + .uv(maxU, maxV) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx, ny, nz) + .endVertex(); + + consumer.vertex(x3, y3, z3) + .color(r, g, b, a) + .uv(maxU, minV) + .overlayCoords(OverlayTexture.NO_OVERLAY) + .uv2(lightmap) + .normal(nx, ny, nz) + .endVertex(); } public static class OutlineParams { @@ -166,9 +507,9 @@ public abstract class Outline { protected Direction highlightedFace; protected boolean fadeLineWidth; protected boolean disableCull; - protected boolean disableNormals; + protected boolean disableLineNormals; protected float alpha; - protected int lightMap; + protected int lightmap; protected Color rgb; private float lineWidth; @@ -178,7 +519,7 @@ public abstract class Outline { lineWidth = 1 / 32f; fadeLineWidth = true; rgb = Color.WHITE; - lightMap = LightTexture.FULL_BRIGHT; + lightmap = LightTexture.FULL_BRIGHT; } // builder @@ -193,8 +534,8 @@ public abstract class Outline { return this; } - public OutlineParams lightMap(int light) { - lightMap = light; + public OutlineParams lightmap(int light) { + lightmap = light; return this; } @@ -223,8 +564,8 @@ public abstract class Outline { return this; } - public OutlineParams disableNormals() { - disableNormals = true; + public OutlineParams disableLineNormals() { + disableLineNormals = true; return this; } @@ -243,6 +584,9 @@ public abstract class Outline { return highlightedFace; } + public void loadColor(Vector4f vec) { + vec.set(rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(), rgb.getAlphaAsFloat() * alpha); + } } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java index c6f061cec..0e4b472d0 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java @@ -32,7 +32,7 @@ public class Outliner { public OutlineParams showLine(Object slot, Vec3 start, Vec3 end) { if (!outlines.containsKey(slot)) { LineOutline outline = new LineOutline(); - outlines.put(slot, new OutlineEntry(outline)); + addOutline(slot, outline); } OutlineEntry entry = outlines.get(slot); entry.ticksTillRemoval = 1; @@ -43,7 +43,7 @@ public class Outliner { public OutlineParams endChasingLine(Object slot, Vec3 start, Vec3 end, float chasingProgress, boolean lockStart) { if (!outlines.containsKey(slot)) { EndChasingLineOutline outline = new EndChasingLineOutline(lockStart); - outlines.put(slot, new OutlineEntry(outline)); + addOutline(slot, outline); } OutlineEntry entry = outlines.get(slot); entry.ticksTillRemoval = 1; @@ -75,12 +75,12 @@ public class Outliner { public OutlineParams showCluster(Object slot, Iterable selection) { BlockClusterOutline outline = new BlockClusterOutline(selection); - OutlineEntry entry = new OutlineEntry(outline); - outlines.put(slot, entry); - return entry.getOutline() - .getParams(); + addOutline(slot, outline); + return outline.getParams(); } + // + public void keep(Object slot) { if (outlines.containsKey(slot)) outlines.get(slot).ticksTillRemoval = 1; @@ -105,17 +105,19 @@ public class Outliner { // Utility + private void addOutline(Object slot, Outline outline) { + outlines.put(slot, new OutlineEntry(outline)); + } + private void createAABBOutlineIfMissing(Object slot, AABB bb) { if (!outlines.containsKey(slot) || !(outlines.get(slot).outline instanceof AABBOutline)) { ChasingAABBOutline outline = new ChasingAABBOutline(bb); - outlines.put(slot, new OutlineEntry(outline)); + addOutline(slot, outline); } } private ChasingAABBOutline getAndRefreshAABB(Object slot) { - OutlineEntry entry = outlines.get(slot); - entry.ticksTillRemoval = 1; - return (ChasingAABBOutline) entry.getOutline(); + return getAndRefreshAABB(slot, 1); } private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) { @@ -144,7 +146,7 @@ public class Outliner { params.alpha = 1; if (entry.isFading()) { int prevTicks = entry.ticksTillRemoval + 1; - float fadeticks = OutlineEntry.fadeTicks; + float fadeticks = OutlineEntry.FADE_TICKS; float lastAlpha = prevTicks >= 0 ? 1 : 1 + (prevTicks / fadeticks); float currentAlpha = 1 + (entry.ticksTillRemoval / fadeticks); float alpha = Mth.lerp(pt, lastAlpha, currentAlpha); @@ -158,33 +160,35 @@ public class Outliner { } public static class OutlineEntry { + public static final int FADE_TICKS = 8; - static final int fadeTicks = 8; - private Outline outline; - private int ticksTillRemoval; + private final Outline outline; + private int ticksTillRemoval = 1; public OutlineEntry(Outline outline) { this.outline = outline; - ticksTillRemoval = 1; - } - - public void tick() { - ticksTillRemoval--; - outline.tick(); - } - - public boolean isAlive() { - return ticksTillRemoval >= -fadeTicks; - } - - public boolean isFading() { - return ticksTillRemoval < 0; } public Outline getOutline() { return outline; } + public int getTicksTillRemoval() { + return ticksTillRemoval; + } + + public boolean isAlive() { + return ticksTillRemoval >= -FADE_TICKS; + } + + public boolean isFading() { + return ticksTillRemoval < 0; + } + + public void tick() { + ticksTillRemoval--; + outline.tick(); + } } }