Revert "Revert "Rewrite outline buffering""

This reverts commit 726bfaf0
This commit is contained in:
techno-sam 2023-05-08 20:26:16 -07:00
parent 435b4c1c16
commit fe049bc771
16 changed files with 885 additions and 322 deletions

View File

@ -37,7 +37,7 @@ public class ChassisRangeDisplay {
timer = DISPLAY_TIME; timer = DISPLAY_TIME;
CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(te)) CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(te))
.colored(0xFFFFFF) .colored(0xFFFFFF)
.disableNormals() .disableLineNormals()
.lineWidth(1 / 16f) .lineWidth(1 / 16f)
.withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED); .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED);
} }

View File

@ -100,7 +100,7 @@ public class SuperGlueSelectionHandler {
CreateClient.OUTLINER.showAABB(glueEntity, glueEntity.getBoundingBox()) CreateClient.OUTLINER.showAABB(glueEntity, glueEntity.getBoundingBox())
.colored(h ? HIGHLIGHT : PASSIVE) .colored(h ? HIGHLIGHT : PASSIVE)
.withFaceTextures(faceTex, faceTex) .withFaceTextures(faceTex, faceTex)
.disableNormals() .disableLineNormals()
.lineWidth(h ? 1 / 16f : 1 / 64f); .lineWidth(h ? 1 / 16f : 1 / 64f);
} }
} }
@ -155,12 +155,12 @@ public class SuperGlueSelectionHandler {
CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox) CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox)
.colored(canReach && canAfford && !cancel ? HIGHLIGHT : FAIL) .colored(canReach && canAfford && !cancel ? HIGHLIGHT : FAIL)
.withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.GLUE) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.GLUE)
.disableNormals() .disableLineNormals()
.lineWidth(1 / 16f); .lineWidth(1 / 16f);
CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster)
.colored(0x4D9162) .colored(0x4D9162)
.disableNormals() .disableLineNormals()
.lineWidth(1 / 64f); .lineWidth(1 / 64f);
} }
@ -259,7 +259,7 @@ public class SuperGlueSelectionHandler {
CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster)
.colored(0xB5F2C6) .colored(0xB5F2C6)
.withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.HIGHLIGHT_CHECKERED) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.HIGHLIGHT_CHECKERED)
.disableNormals() .disableLineNormals()
.lineWidth(1 / 24f); .lineWidth(1 / 24f);
discard(); discard();

View File

@ -39,7 +39,7 @@ public class ZapperRenderHandler extends ShootableGadgetRenderHandler {
cachedBeams.forEach(beam -> { cachedBeams.forEach(beam -> {
CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity, false) CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity, false)
.disableNormals() .disableLineNormals()
.colored(0xffffff) .colored(0xffffff)
.lineWidth(beam.itensity * 1 / 8f); .lineWidth(beam.itensity * 1 / 8f);
}); });

View File

@ -33,7 +33,7 @@ public class WorldshaperRenderHandler {
CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get()) CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get())
.colored(0xbfbfbf) .colored(0xbfbfbf)
.disableNormals() .disableLineNormals()
.lineWidth(1 / 32f) .lineWidth(1 / 32f)
.withFaceTexture(AllSpecialTextures.CHECKERED); .withFaceTexture(AllSpecialTextures.CHECKERED);
} }

View File

@ -124,7 +124,7 @@ public class TrainRelocator {
Vec3 vec2 = toVisualise.get(i + 1).add(offset); Vec3 vec2 = toVisualise.get(i + 1).add(offset);
CreateClient.OUTLINER.showLine(Pair.of(relocating, i), vec1.add(0, -.925f, 0), vec2.add(0, -.925f, 0)) 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) .colored(lastHoveredResult || i != toVisualise.size() - 2 ? 0x95CD41 : 0xEA5C2B)
.disableNormals() .disableLineNormals()
.lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f);
} }
} }
@ -272,7 +272,7 @@ public class TrainRelocator {
public static void visualise(Train train, int i, Vec3 v1, Vec3 v2, boolean valid) { 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)) CreateClient.OUTLINER.showLine(Pair.of(train, i), v1.add(0, -.825f, 0), v2.add(0, -.825f, 0))
.colored(valid ? 0x95CD41 : 0xEA5C2B) .colored(valid ? 0x95CD41 : 0xEA5C2B)
.disableNormals() .disableLineNormals()
.lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f);
} }

View File

@ -748,13 +748,13 @@ public class TrackPlacement {
.showLine(Pair.of(key, i * 2), VecHelper.lerp(s, middle1, previous1), .showLine(Pair.of(key, i * 2), VecHelper.lerp(s, middle1, previous1),
VecHelper.lerp(s, middle1, rail1)) VecHelper.lerp(s, middle1, rail1))
.colored(railcolor) .colored(railcolor)
.disableNormals() .disableLineNormals()
.lineWidth(lw); .lineWidth(lw);
CreateClient.OUTLINER CreateClient.OUTLINER
.showLine(Pair.of(key, i * 2 + 1), VecHelper.lerp(s, middle2, previous2), .showLine(Pair.of(key, i * 2 + 1), VecHelper.lerp(s, middle2, previous2),
VecHelper.lerp(s, middle2, rail2)) VecHelper.lerp(s, middle2, rail2))
.colored(railcolor) .colored(railcolor)
.disableNormals() .disableLineNormals()
.lineWidth(lw); .lineWidth(lw);
} }
@ -775,7 +775,7 @@ public class TrackPlacement {
int color = Color.mixColors(0xEA5C2B, 0x95CD41, animation.getValue()); int color = Color.mixColors(0xEA5C2B, 0x95CD41, animation.getValue());
CreateClient.OUTLINER.showLine(Pair.of("start", id), v1.subtract(o1), v1.add(ex)) CreateClient.OUTLINER.showLine(Pair.of("start", id), v1.subtract(o1), v1.add(ex))
.lineWidth(1 / 8f) .lineWidth(1 / 8f)
.disableNormals() .disableLineNormals()
.colored(color); .colored(color);
} }

View File

@ -72,7 +72,7 @@ public class FlipTool extends PlacementToolBase {
AllSpecialTextures tex = AllSpecialTextures.CHECKERED; AllSpecialTextures tex = AllSpecialTextures.CHECKERED;
outline.getParams() outline.getParams()
.lineWidth(1 / 16f) .lineWidth(1 / 16f)
.disableNormals() .disableLineNormals()
.colored(0xdddddd) .colored(0xdddddd)
.withFaceTextures(tex, tex); .withFaceTextures(tex, tex);
outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()); outline.render(ms, buffer, AnimationTickHolder.getPartialTicks());

View File

@ -32,7 +32,7 @@ public class RotateTool extends PlacementToolBase {
line.getParams() line.getParams()
.disableCull() .disableCull()
.disableNormals() .disableLineNormals()
.colored(0xdddddd) .colored(0xdddddd)
.lineWidth(1 / 16f); .lineWidth(1 / 16f);
line.set(start, end) line.set(start, end)

View File

@ -398,7 +398,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
aabbOutline.getParams() aabbOutline.getParams()
.lineWidth(1 / 64f) .lineWidth(1 / 64f)
.colored(0xefefef) .colored(0xefefef)
.disableNormals(); .disableLineNormals();
aabbOutline.render(ms, (SuperRenderTypeBuffer) buffer, pt); aabbOutline.render(ms, (SuperRenderTypeBuffer) buffer, pt);
ms.popPose(); ms.popPose();

View File

@ -87,9 +87,6 @@ public class ValueBox extends ChasingAABBOutline {
ms.translate(pos.getX(), pos.getY(), pos.getZ()); ms.translate(pos.getX(), pos.getY(), pos.getZ());
if (hasTransform) if (hasTransform)
transform.transform(blockState, ms); transform.transform(blockState, ms);
transformNormals = ms.last()
.normal()
.copy();
params.colored(isPassive ? passiveColor : highlightColor); params.colored(isPassive ? passiveColor : highlightColor);
super.render(ms, buffer, pt); super.render(ms, buffer, pt);

View File

@ -1,15 +1,18 @@
package com.simibubi.create.foundation.utility.outliner; package com.simibubi.create.foundation.utility.outliner;
import java.util.Optional;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; 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.RenderTypes;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.Direction; 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.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@ -17,85 +20,212 @@ public class AABBOutline extends Outline {
protected AABB bb; 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) { public AABBOutline(AABB bb) {
this.setBounds(bb); setBounds(bb);
} }
@Override public AABB getBounds() {
public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { return bb;
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 void setBounds(AABB bb) { public void setBounds(AABB bb) {
this.bb = 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<AllSpecialTextures> optionalFaceTexture = highlighted ? params.hightlightedFaceTexture : params.faceTexture;
Optional<AllSpecialTextures> 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);
}
} }

View File

@ -8,94 +8,156 @@ import java.util.Set;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; 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.AllSpecialTextures;
import com.simibubi.create.foundation.render.RenderTypes; import com.simibubi.create.foundation.render.RenderTypes;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection; import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.phys.Vec3;
public class BlockClusterOutline extends Outline { public class BlockClusterOutline extends Outline {
private Cluster cluster; private final Cluster cluster;
public BlockClusterOutline(Iterable<BlockPos> 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<BlockPos> positions) {
cluster = new Cluster(); cluster = new Cluster();
selection.forEach(cluster::include); positions.forEach(cluster::include);
} }
@Override @Override
public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) {
cluster.visibleEdges.forEach(edge -> { params.loadColor(colorTemp);
Vec3 start = Vec3.atLowerCornerOf(edge.pos); Vector4f color = colorTemp;
Direction direction = Direction.get(AxisDirection.POSITIVE, edge.axis); int lightmap = params.lightmap;
renderAACuboidLine(ms, buffer, start, Vec3.atLowerCornerOf(edge.pos.relative(direction))); boolean disableLineNormals = params.disableLineNormals;
});
Optional<AllSpecialTextures> faceTexture = params.faceTexture; renderFaces(ms, buffer, pt, color, lightmap);
if (!faceTexture.isPresent()) renderEdges(ms, buffer, pt, color, lightmap, disableLineNormals);
}
protected void renderFaces(PoseStack ms, SuperRenderTypeBuffer buffer, float pt, Vector4f color, int lightmap) {
Optional<AllSpecialTextures> optionalFaceTexture = params.faceTexture;
if (!optionalFaceTexture.isPresent())
return; return;
AllSpecialTextures faceTexture = optionalFaceTexture.get();
RenderType translucentType = RenderTypes.getOutlineTranslucent(faceTexture.get() PoseStack.Pose pose = ms.last();
.getLocation(), true); RenderType renderType = RenderTypes.getOutlineTranslucent(faceTexture.getLocation(), true);
VertexConsumer builder = buffer.getLateBuffer(translucentType); VertexConsumer consumer = buffer.getLateBuffer(renderType);
cluster.visibleFaces.forEach((face, axisDirection) -> { cluster.visibleFaces.forEach((face, axisDirection) -> {
Direction direction = Direction.get(axisDirection, face.axis); Direction direction = Direction.get(axisDirection, face.axis);
BlockPos pos = face.pos; BlockPos pos = face.pos;
if (axisDirection == AxisDirection.POSITIVE) if (axisDirection == AxisDirection.POSITIVE)
pos = pos.relative(direction.getOpposite()); 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); protected void renderEdges(PoseStack ms, SuperRenderTypeBuffer buffer, float pt, Vector4f color, int lightmap, boolean disableNormals) {
static Vec3 Xyz = new Vec3(.5, -.5, -.5); float lineWidth = params.getLineWidth();
static Vec3 xYz = new Vec3(-.5, .5, -.5); if (lineWidth == 0)
static Vec3 XYz = new Vec3(.5, .5, -.5); return;
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) { PoseStack.Pose pose = ms.last();
Vec3 center = VecHelper.getCenterOf(pos); VertexConsumer consumer = buffer.getBuffer(RenderTypes.getOutlineSolid());
Vec3 offset = Vec3.atLowerCornerOf(face.getNormal());
offset = offset.scale(1 / 128d);
center = center.add(offset);
ms.pushPose(); cluster.visibleEdges.forEach(edge -> {
ms.translate(center.x, center.y, center.z); 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) { switch (face) {
case DOWN: case DOWN -> {
putQuad(ms, builder, xyz, Xyz, XyZ, xyZ, face); // 0 1 2 3
break; pos0.set(0, 0, 1);
case EAST: pos1.set(0, 0, 0);
putQuad(ms, builder, XYz, XYZ, XyZ, Xyz, face); pos2.set(1, 0, 0);
break; pos3.set(1, 0, 1);
case NORTH: normal.set(0, -1, 0);
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 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 { private static class Cluster {

View File

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.utility.outliner; package com.simibubi.create.foundation.utility.outliner;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Vector4f;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@ -29,7 +30,12 @@ public class ChasingAABBOutline extends AABBOutline {
@Override @Override
public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { 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) { private static AABB interpolateBBs(AABB current, AABB target, float pt) {

View File

@ -1,6 +1,10 @@
package com.simibubi.create.foundation.utility.outliner; package com.simibubi.create.foundation.utility.outliner;
import com.mojang.blaze3d.vertex.PoseStack; 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 com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@ -8,33 +12,50 @@ import net.minecraft.world.phys.Vec3;
public class LineOutline extends Outline { public class LineOutline extends Outline {
protected Vec3 start = Vec3.ZERO; protected final Vector3f start = new Vector3f();
protected Vec3 end = Vec3.ZERO; 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) { public LineOutline set(Vec3 start, Vec3 end) {
this.start = start; this.start.set((float) start.x, (float) start.y, (float) start.z);
this.end = end; this.end.set((float) end.x, (float) end.y, (float) end.z);
return this; return this;
} }
@Override @Override
public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) { 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 { public static class EndChasingLineOutline extends LineOutline {
private float progress = 0;
float prevProgress = 0; private float prevProgress = 0;
float progress = 0;
private boolean lockStart; private boolean lockStart;
private final Vector3f startTemp = new Vector3f();
public EndChasingLineOutline(boolean lockStart) { public EndChasingLineOutline(boolean lockStart) {
this.lockStart = lockStart; this.lockStart = lockStart;
} }
@Override
public void tick() {}
public EndChasingLineOutline setProgress(float progress) { public EndChasingLineOutline setProgress(float progress) {
prevProgress = this.progress; prevProgress = this.progress;
this.progress = progress; this.progress = progress;
@ -42,25 +63,24 @@ public class LineOutline extends Outline {
} }
@Override @Override
public LineOutline set(Vec3 start, Vec3 end) { protected void renderInner(PoseStack ms, VertexConsumer consumer, float pt, float width, Vector4f color, int lightmap, boolean disableNormals) {
if (!end.equals(this.end))
super.set(start, end);
return this;
}
@Override
public void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt) {
float distanceToTarget = Mth.lerp(pt, prevProgress, progress); float distanceToTarget = Mth.lerp(pt, prevProgress, progress);
if (!lockStart) Vector3f end;
if (lockStart) {
end = this.start;
} else {
end = this.end;
distanceToTarget = 1 - distanceToTarget; distanceToTarget = 1 - distanceToTarget;
Vec3 start = lockStart ? this.end : this.start; }
Vec3 end = lockStart ? this.start : this.end;
start = end.add(this.start.subtract(end) Vector3f start = this.startTemp;
.scale(distanceToTarget)); start.load(this.start);
renderCuboidLine(ms, buffer, start, end); start.sub(end);
start.mul(distanceToTarget);
start.add(end);
bufferCuboidLine(ms, consumer, start, end, width, color, lightmap, disableNormals);
} }
} }
} }

View File

@ -8,156 +8,497 @@ import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Matrix3f; 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.AllSpecialTextures;
import com.simibubi.create.foundation.render.RenderTypes;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Color; 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.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
public abstract class Outline { public abstract class Outline {
protected OutlineParams params; protected final OutlineParams params;
protected Matrix3f transformNormals; // TODO: not used?
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() { public Outline() {
params = new OutlineParams(); params = new OutlineParams();
} }
public OutlineParams getParams() {
return params;
}
public abstract void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt); public abstract void render(PoseStack ms, SuperRenderTypeBuffer buffer, float pt);
public void tick() {} public void tick() {}
public OutlineParams getParams() { public void bufferCuboidLine(PoseStack poseStack, VertexConsumer consumer, Vector3f start, Vector3f end, float width, Vector4f color, int lightmap, boolean disableNormals) {
return params; 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) { public void bufferCuboidLine(PoseStack.Pose pose, VertexConsumer consumer, Vector3f origin, Direction direction, float length, float width, Vector4f color, int lightmap, boolean disableNormals) {
Vec3 diff = end.subtract(start); Vector3f minPos = minPosTemp;
float hAngle = AngleHelper.deg(Mth.atan2(diff.x, diff.z)); Vector3f maxPos = maxPosTemp;
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 renderAACuboidLine(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 start, Vec3 end) { float halfWidth = width / 2;
float lineWidth = params.getLineWidth(); minPos.set(origin.x() - halfWidth, origin.y() - halfWidth, origin.z() - halfWidth);
if (lineWidth == 0) maxPos.set(origin.x() + halfWidth, origin.y() + halfWidth, origin.z() + halfWidth);
return;
VertexConsumer builder = buffer.getBuffer(RenderTypes.getOutlineSolid()); switch (direction) {
case DOWN -> {
Vec3 diff = end.subtract(start); minPos.add(0, -length, 0);
if (diff.x + diff.y + diff.z < 0) { }
Vec3 temp = start; case UP -> {
start = end; maxPos.add(0, length, 0);
end = temp; }
diff = diff.scale(-1); 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() bufferCuboid(pose, consumer, minPos, maxPos, color, lightmap, disableNormals);
.scale(lineWidth / 2); }
Vec3 plane = VecHelper.axisAlingedPlaneOf(diff);
Direction face = Direction.getNearest(diff.x, diff.y, diff.z);
Axis axis = face.getAxis();
start = start.subtract(extension); public void bufferCuboid(PoseStack.Pose pose, VertexConsumer consumer, Vector3f minPos, Vector3f maxPos, Vector4f color, int lightmap, boolean disableNormals) {
end = end.add(extension); Vector4f posTransformTemp = this.posTransformTemp;
plane = plane.scale(lineWidth / 2); Vector3f normalTransformTemp = this.normalTransformTemp;
Vec3 a1 = plane.add(start); float minX = minPos.x();
Vec3 b1 = plane.add(end); float minY = minPos.y();
plane = VecHelper.rotate(plane, -90, axis); float minZ = minPos.z();
Vec3 a2 = plane.add(start); float maxX = maxPos.x();
Vec3 b2 = plane.add(end); float maxY = maxPos.y();
plane = VecHelper.rotate(plane, -90, axis); float maxZ = maxPos.z();
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);
if (params.disableNormals) { Matrix4f posMatrix = pose.pose();
face = Direction.UP;
putQuad(ms, builder, b4, b3, b2, b1, face); posTransformTemp.set(minX, minY, maxZ, 1);
putQuad(ms, builder, a1, a2, a3, a4, face); posTransformTemp.transform(posMatrix);
putQuad(ms, builder, a1, b1, b2, a2, face); double x0 = posTransformTemp.x();
putQuad(ms, builder, a2, b2, b3, a3, face); double y0 = posTransformTemp.y();
putQuad(ms, builder, a3, b3, b4, a4, face); double z0 = posTransformTemp.z();
putQuad(ms, builder, a4, b4, b1, a1, face);
return; 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); consumer.vertex(x0, y0, z0)
putQuad(ms, builder, a1, a2, a3, a4, face.getOpposite()); .color(r, g, b, a)
Vec3 vec = a1.subtract(a4); .uv(0, 0)
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)
.overlayCoords(OverlayTexture.NO_OVERLAY) .overlayCoords(OverlayTexture.NO_OVERLAY)
.uv2(params.lightMap) .uv2(lightmap)
.normal(pose.normal(), xOffset, yOffset, zOffset) .normal(nx0, ny0, nz0)
.endVertex(); .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 { public static class OutlineParams {
@ -166,9 +507,9 @@ public abstract class Outline {
protected Direction highlightedFace; protected Direction highlightedFace;
protected boolean fadeLineWidth; protected boolean fadeLineWidth;
protected boolean disableCull; protected boolean disableCull;
protected boolean disableNormals; protected boolean disableLineNormals;
protected float alpha; protected float alpha;
protected int lightMap; protected int lightmap;
protected Color rgb; protected Color rgb;
private float lineWidth; private float lineWidth;
@ -178,7 +519,7 @@ public abstract class Outline {
lineWidth = 1 / 32f; lineWidth = 1 / 32f;
fadeLineWidth = true; fadeLineWidth = true;
rgb = Color.WHITE; rgb = Color.WHITE;
lightMap = LightTexture.FULL_BRIGHT; lightmap = LightTexture.FULL_BRIGHT;
} }
// builder // builder
@ -193,8 +534,8 @@ public abstract class Outline {
return this; return this;
} }
public OutlineParams lightMap(int light) { public OutlineParams lightmap(int light) {
lightMap = light; lightmap = light;
return this; return this;
} }
@ -223,8 +564,8 @@ public abstract class Outline {
return this; return this;
} }
public OutlineParams disableNormals() { public OutlineParams disableLineNormals() {
disableNormals = true; disableLineNormals = true;
return this; return this;
} }
@ -243,6 +584,9 @@ public abstract class Outline {
return highlightedFace; return highlightedFace;
} }
public void loadColor(Vector4f vec) {
vec.set(rgb.getRedAsFloat(), rgb.getGreenAsFloat(), rgb.getBlueAsFloat(), rgb.getAlphaAsFloat() * alpha);
}
} }
} }

View File

@ -33,7 +33,7 @@ public class Outliner {
public OutlineParams showLine(Object slot, Vec3 start, Vec3 end) { public OutlineParams showLine(Object slot, Vec3 start, Vec3 end) {
if (!outlines.containsKey(slot)) { if (!outlines.containsKey(slot)) {
LineOutline outline = new LineOutline(); LineOutline outline = new LineOutline();
outlines.put(slot, new OutlineEntry(outline)); addOutline(slot, outline);
} }
OutlineEntry entry = outlines.get(slot); OutlineEntry entry = outlines.get(slot);
entry.ticksTillRemoval = 1; entry.ticksTillRemoval = 1;
@ -44,7 +44,7 @@ public class Outliner {
public OutlineParams endChasingLine(Object slot, Vec3 start, Vec3 end, float chasingProgress, boolean lockStart) { public OutlineParams endChasingLine(Object slot, Vec3 start, Vec3 end, float chasingProgress, boolean lockStart) {
if (!outlines.containsKey(slot)) { if (!outlines.containsKey(slot)) {
EndChasingLineOutline outline = new EndChasingLineOutline(lockStart); EndChasingLineOutline outline = new EndChasingLineOutline(lockStart);
outlines.put(slot, new OutlineEntry(outline)); addOutline(slot, outline);
} }
OutlineEntry entry = outlines.get(slot); OutlineEntry entry = outlines.get(slot);
entry.ticksTillRemoval = 1; entry.ticksTillRemoval = 1;
@ -76,12 +76,12 @@ public class Outliner {
public OutlineParams showCluster(Object slot, Iterable<BlockPos> selection) { public OutlineParams showCluster(Object slot, Iterable<BlockPos> selection) {
BlockClusterOutline outline = new BlockClusterOutline(selection); BlockClusterOutline outline = new BlockClusterOutline(selection);
OutlineEntry entry = new OutlineEntry(outline); addOutline(slot, outline);
outlines.put(slot, entry); return outline.getParams();
return entry.getOutline()
.getParams();
} }
//
public OutlineParams showItem(Object slot, Vec3 pos, ItemStack stack) { public OutlineParams showItem(Object slot, Vec3 pos, ItemStack stack) {
ItemOutline outline = new ItemOutline(pos, stack); ItemOutline outline = new ItemOutline(pos, stack);
OutlineEntry entry = new OutlineEntry(outline); OutlineEntry entry = new OutlineEntry(outline);
@ -113,17 +113,19 @@ public class Outliner {
// Utility // Utility
private void addOutline(Object slot, Outline outline) {
outlines.put(slot, new OutlineEntry(outline));
}
private void createAABBOutlineIfMissing(Object slot, AABB bb) { private void createAABBOutlineIfMissing(Object slot, AABB bb) {
if (!outlines.containsKey(slot) || !(outlines.get(slot).outline instanceof AABBOutline)) { if (!outlines.containsKey(slot) || !(outlines.get(slot).outline instanceof AABBOutline)) {
ChasingAABBOutline outline = new ChasingAABBOutline(bb); ChasingAABBOutline outline = new ChasingAABBOutline(bb);
outlines.put(slot, new OutlineEntry(outline)); addOutline(slot, outline);
} }
} }
private ChasingAABBOutline getAndRefreshAABB(Object slot) { private ChasingAABBOutline getAndRefreshAABB(Object slot) {
OutlineEntry entry = outlines.get(slot); return getAndRefreshAABB(slot, 1);
entry.ticksTillRemoval = 1;
return (ChasingAABBOutline) entry.getOutline();
} }
private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) { private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) {
@ -152,7 +154,7 @@ public class Outliner {
params.alpha = 1; params.alpha = 1;
if (entry.isFading()) { if (entry.isFading()) {
int prevTicks = entry.ticksTillRemoval + 1; int prevTicks = entry.ticksTillRemoval + 1;
float fadeticks = OutlineEntry.fadeTicks; float fadeticks = OutlineEntry.FADE_TICKS;
float lastAlpha = prevTicks >= 0 ? 1 : 1 + (prevTicks / fadeticks); float lastAlpha = prevTicks >= 0 ? 1 : 1 + (prevTicks / fadeticks);
float currentAlpha = 1 + (entry.ticksTillRemoval / fadeticks); float currentAlpha = 1 + (entry.ticksTillRemoval / fadeticks);
float alpha = Mth.lerp(pt, lastAlpha, currentAlpha); float alpha = Mth.lerp(pt, lastAlpha, currentAlpha);
@ -166,33 +168,35 @@ public class Outliner {
} }
public static class OutlineEntry { public static class OutlineEntry {
public static final int FADE_TICKS = 8;
static final int fadeTicks = 8; private final Outline outline;
private Outline outline; private int ticksTillRemoval = 1;
private int ticksTillRemoval;
public OutlineEntry(Outline outline) { public OutlineEntry(Outline outline) {
this.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() { public Outline getOutline() {
return outline; 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();
}
} }
} }