From c0b561e2fe79b6e47b868d41b14d526ed34e4fc7 Mon Sep 17 00:00:00 2001 From: Sophie Date: Thu, 26 Feb 2026 00:09:09 +0100 Subject: [PATCH 1/2] Add thickLine tracers & reprojectBehindCamera --- .../meteorclient/renderer/Renderer3D.java | 147 +++++++++++++++++- .../modules/render/blockesp/BlockESP.java | 13 ++ .../modules/render/blockesp/ESPGroup.java | 2 +- 3 files changed, 156 insertions(+), 6 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java b/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java index 84ac6b162a..7fc81818d1 100644 --- a/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java +++ b/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java @@ -47,17 +47,149 @@ public void render(MatrixStack matrices) { // Lines + public void line(double x1, double y1, double z1, double x2, double y2, double z2, Color color) { + line(x1, y1, z1, x2, y2, z2, color, color); + } + + public void thickLine(double x1, double y1, double z1, double x2, double y2, double z2, Color color, double width) { + thickLine(x1, y1, z1, x2, y2, z2, color, color, width); + } + public void line(double x1, double y1, double z1, double x2, double y2, double z2, Color color1, Color color2) { - lines.ensureLineCapacity(); + double[] p = reprojectBehindCamera(x1, y1, z1, x2, y2, z2); + lines.ensureLineCapacity(); lines.line( - lines.vec3(x1, y1, z1).color(color1).next(), - lines.vec3(x2, y2, z2).color(color2).next() + lines.vec3(p[0], p[1], p[2]).color(color1).next(), + lines.vec3(p[3], p[4], p[5]).color(color2).next() ); } - public void line(double x1, double y1, double z1, double x2, double y2, double z2, Color color) { - line(x1, y1, z1, x2, y2, z2, color, color); + public void thickLine(double x1, double y1, double z1, double x2, double y2, double z2, Color color1, Color color2, double width) { + width = sliderToLinearWidth(width); + if (width <= 0) { + line(x1, y1, z1, x2, y2, z2, color1, color2); + return; + } + + double[] p = reprojectBehindCamera(x1, y1, z1, x2, y2, z2); + x1 = p[0]; y1 = p[1]; z1 = p[2]; + x2 = p[3]; y2 = p[4]; z2 = p[5]; + + var camera = MinecraftClient.getInstance().gameRenderer.getCamera(); + var cameraPos = camera.getCameraPos(); + double camX = cameraPos.x; + double camY = cameraPos.y; + double camZ = cameraPos.z; + + // Camera forward direction + double yawRad = Math.toRadians(camera.getYaw()); + double pitchRad = Math.toRadians(camera.getPitch()); + double fwdX = -Math.sin(yawRad) * Math.cos(pitchRad); + double fwdY = -Math.sin(pitchRad); + double fwdZ = Math.cos(yawRad) * Math.cos(pitchRad); + + double dx = x2 - x1; + double dy = y2 - y1; + double dz = z2 - z1; + + double length = Math.sqrt(dx * dx + dy * dy + dz * dz); + if (length == 0) return; + + double lineDirX = dx / length; + double lineDirY = dy / length; + double lineDirZ = dz / length; + + // Perpendicular = cross(lineDir, cameraForward) + // This always lies in the camera's view plane, so basically you always see a rectangle + double perpX = lineDirY * fwdZ - lineDirZ * fwdY; + double perpY = lineDirZ * fwdX - lineDirX * fwdZ; + double perpZ = lineDirX * fwdY - lineDirY * fwdX; + + double perpLen = Math.sqrt(perpX * perpX + perpY * perpY + perpZ * perpZ); + + if (perpLen < 1e-6) { + // Line is parallel to camera forward - use camera right vector as fallback + perpX = Math.cos(yawRad); + perpY = 0; + perpZ = Math.sin(yawRad); + perpLen = Math.sqrt(perpX * perpX + perpY * perpY + perpZ * perpZ); + if (perpLen < 1e-6) return; + } + + perpX /= perpLen; + perpY /= perpLen; + perpZ /= perpLen; + + double dist1 = Math.sqrt((x1 - camX) * (x1 - camX) + (y1 - camY) * (y1 - camY) + (z1 - camZ) * (z1 - camZ)); + double dist2 = Math.sqrt((x2 - camX) * (x2 - camX) + (y2 - camY) * (y2 - camY) + (z2 - camZ) * (z2 - camZ)); + + double hw1 = width * dist1; + double hw2 = width * dist2; + + triangles.ensureCapacity(4, 6); + + quad( + x1 - perpX * hw1, y1 - perpY * hw1, z1 - perpZ * hw1, + x1 + perpX * hw1, y1 + perpY * hw1, z1 + perpZ * hw1, + x2 + perpX * hw2, y2 + perpY * hw2, z2 + perpZ * hw2, + x2 - perpX * hw2, y2 - perpY * hw2, z2 - perpZ * hw2, + color1, color1, color2, color2 + ); + } + + private double[] reprojectBehindCamera(double x1, double y1, double z1, double x2, double y2, double z2) { + var camera = MinecraftClient.getInstance().gameRenderer.getCamera(); + var cameraPos = camera.getCameraPos(); + double camX = cameraPos.x; + double camY = cameraPos.y; + double camZ = cameraPos.z; + + double yawRad = Math.toRadians(camera.getYaw()); + double pitchRad = Math.toRadians(camera.getPitch()); + double fwdX = -Math.sin(yawRad) * Math.cos(pitchRad); + double fwdY = -Math.sin(pitchRad); + double fwdZ = Math.cos(yawRad) * Math.cos(pitchRad); + + double[] result = { x1, y1, z1, x2, y2, z2 }; + + for (int i = 0; i < 2; i++) { + double px = result[i * 3] - camX; + double py = result[i * 3 + 1] - camY; + double pz = result[i * 3 + 2] - camZ; + double dot = px * fwdX + py * fwdY + pz * fwdZ; + + if (dot >= 0.05) continue; + + double latX = px - fwdX * dot; + double latY = py - fwdY * dot; + double latZ = pz - fwdZ * dot; + double latLen = Math.sqrt(latX * latX + latY * latY + latZ * latZ); + + if (latLen < 1e-6) { + if (Math.abs(fwdY) < 0.9) { + latX = fwdZ; + latY = 0; + latZ = -fwdX; + } else { + latX = 1; + latY = 0; + latZ = 0; + } + latLen = Math.sqrt(latX * latX + latY * latY + latZ * latZ); + } + + latX /= latLen; + latY /= latLen; + latZ /= latLen; + + double pushDist = 1000.0; + result[i * 3] = camX + fwdX * 0.1 + latX * pushDist; + result[i * 3 + 1] = camY + fwdY * 0.1 + latY * pushDist; + result[i * 3 + 2] = camZ + fwdZ * 0.1 + latZ * pushDist; + } + + return result; } @SuppressWarnings("Duplicates") @@ -238,4 +370,9 @@ public void box(Box box, Color sideColor, Color lineColor, ShapeMode mode, int e if (mode.lines()) boxLines(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, lineColor, excludeDir); if (mode.sides()) boxSides(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, sideColor, excludeDir); } + + private double sliderToLinearWidth(double sliderValue) { + if (sliderValue <= 0) return 0; + return 0.001 + (sliderValue / 10.0) * (0.01 - 0.001); + } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java index 8cfe86c072..31c6c14410 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java @@ -76,6 +76,15 @@ public class BlockESP extends Module { .build() ); + private final Setting tracerThickness = sgGeneral.add(new DoubleSetting.Builder() + .name("tracer-thickness") + .description("Tracer line thickness.") + .defaultValue(2.0) + .min(0) + .max(10.0) + .build() + ); + private final BlockPos.Mutable blockPos = new BlockPos.Mutable(); private final Long2ObjectMap chunks = new Long2ObjectOpenHashMap<>(); @@ -124,6 +133,10 @@ ESPBlockData getBlockData(Block block) { return blockData == null ? defaultBlockConfig.get() : blockData; } + double getTracerThickness() { + return tracerThickness.get(); + } + private void updateChunk(int x, int z) { ESPChunk chunk = chunks.get(ChunkPos.toLong(x, z)); if (chunk != null) chunk.update(); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java index f103f75c79..c1ec71aa0f 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java @@ -142,7 +142,7 @@ public void render(Render3DEvent event) { ESPBlockData blockData = blockEsp.getBlockData(block); if (blockData.tracer) { - event.renderer.line(RenderUtils.center.x, RenderUtils.center.y, RenderUtils.center.z, sumX / blocks.size() + 0.5, sumY / blocks.size() + 0.5, sumZ / blocks.size() + 0.5, blockData.tracerColor); + event.renderer.thickLine(RenderUtils.center.x, RenderUtils.center.y, RenderUtils.center.z, sumX / blocks.size() + 0.5, sumY / blocks.size() + 0.5, sumZ / blocks.size() + 0.5, blockData.tracerColor, blockEsp.getTracerThickness()); } } } From c8b9e790438b86af55ba0fa0a990b690a18d2bc0 Mon Sep 17 00:00:00 2001 From: Sophie Date: Thu, 26 Feb 2026 02:40:36 +0100 Subject: [PATCH 2/2] remove thickLine stuff --- .../meteorclient/renderer/Renderer3D.java | 82 ------------------- .../modules/render/blockesp/BlockESP.java | 13 --- .../modules/render/blockesp/ESPGroup.java | 2 +- 3 files changed, 1 insertion(+), 96 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java b/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java index 7fc81818d1..5f7fc12dbd 100644 --- a/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java +++ b/src/main/java/meteordevelopment/meteorclient/renderer/Renderer3D.java @@ -51,10 +51,6 @@ public void line(double x1, double y1, double z1, double x2, double y2, double z line(x1, y1, z1, x2, y2, z2, color, color); } - public void thickLine(double x1, double y1, double z1, double x2, double y2, double z2, Color color, double width) { - thickLine(x1, y1, z1, x2, y2, z2, color, color, width); - } - public void line(double x1, double y1, double z1, double x2, double y2, double z2, Color color1, Color color2) { double[] p = reprojectBehindCamera(x1, y1, z1, x2, y2, z2); @@ -65,79 +61,6 @@ public void line(double x1, double y1, double z1, double x2, double y2, double z ); } - public void thickLine(double x1, double y1, double z1, double x2, double y2, double z2, Color color1, Color color2, double width) { - width = sliderToLinearWidth(width); - if (width <= 0) { - line(x1, y1, z1, x2, y2, z2, color1, color2); - return; - } - - double[] p = reprojectBehindCamera(x1, y1, z1, x2, y2, z2); - x1 = p[0]; y1 = p[1]; z1 = p[2]; - x2 = p[3]; y2 = p[4]; z2 = p[5]; - - var camera = MinecraftClient.getInstance().gameRenderer.getCamera(); - var cameraPos = camera.getCameraPos(); - double camX = cameraPos.x; - double camY = cameraPos.y; - double camZ = cameraPos.z; - - // Camera forward direction - double yawRad = Math.toRadians(camera.getYaw()); - double pitchRad = Math.toRadians(camera.getPitch()); - double fwdX = -Math.sin(yawRad) * Math.cos(pitchRad); - double fwdY = -Math.sin(pitchRad); - double fwdZ = Math.cos(yawRad) * Math.cos(pitchRad); - - double dx = x2 - x1; - double dy = y2 - y1; - double dz = z2 - z1; - - double length = Math.sqrt(dx * dx + dy * dy + dz * dz); - if (length == 0) return; - - double lineDirX = dx / length; - double lineDirY = dy / length; - double lineDirZ = dz / length; - - // Perpendicular = cross(lineDir, cameraForward) - // This always lies in the camera's view plane, so basically you always see a rectangle - double perpX = lineDirY * fwdZ - lineDirZ * fwdY; - double perpY = lineDirZ * fwdX - lineDirX * fwdZ; - double perpZ = lineDirX * fwdY - lineDirY * fwdX; - - double perpLen = Math.sqrt(perpX * perpX + perpY * perpY + perpZ * perpZ); - - if (perpLen < 1e-6) { - // Line is parallel to camera forward - use camera right vector as fallback - perpX = Math.cos(yawRad); - perpY = 0; - perpZ = Math.sin(yawRad); - perpLen = Math.sqrt(perpX * perpX + perpY * perpY + perpZ * perpZ); - if (perpLen < 1e-6) return; - } - - perpX /= perpLen; - perpY /= perpLen; - perpZ /= perpLen; - - double dist1 = Math.sqrt((x1 - camX) * (x1 - camX) + (y1 - camY) * (y1 - camY) + (z1 - camZ) * (z1 - camZ)); - double dist2 = Math.sqrt((x2 - camX) * (x2 - camX) + (y2 - camY) * (y2 - camY) + (z2 - camZ) * (z2 - camZ)); - - double hw1 = width * dist1; - double hw2 = width * dist2; - - triangles.ensureCapacity(4, 6); - - quad( - x1 - perpX * hw1, y1 - perpY * hw1, z1 - perpZ * hw1, - x1 + perpX * hw1, y1 + perpY * hw1, z1 + perpZ * hw1, - x2 + perpX * hw2, y2 + perpY * hw2, z2 + perpZ * hw2, - x2 - perpX * hw2, y2 - perpY * hw2, z2 - perpZ * hw2, - color1, color1, color2, color2 - ); - } - private double[] reprojectBehindCamera(double x1, double y1, double z1, double x2, double y2, double z2) { var camera = MinecraftClient.getInstance().gameRenderer.getCamera(); var cameraPos = camera.getCameraPos(); @@ -370,9 +293,4 @@ public void box(Box box, Color sideColor, Color lineColor, ShapeMode mode, int e if (mode.lines()) boxLines(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, lineColor, excludeDir); if (mode.sides()) boxSides(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, sideColor, excludeDir); } - - private double sliderToLinearWidth(double sliderValue) { - if (sliderValue <= 0) return 0; - return 0.001 + (sliderValue / 10.0) * (0.01 - 0.001); - } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java index 31c6c14410..8cfe86c072 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java @@ -76,15 +76,6 @@ public class BlockESP extends Module { .build() ); - private final Setting tracerThickness = sgGeneral.add(new DoubleSetting.Builder() - .name("tracer-thickness") - .description("Tracer line thickness.") - .defaultValue(2.0) - .min(0) - .max(10.0) - .build() - ); - private final BlockPos.Mutable blockPos = new BlockPos.Mutable(); private final Long2ObjectMap chunks = new Long2ObjectOpenHashMap<>(); @@ -133,10 +124,6 @@ ESPBlockData getBlockData(Block block) { return blockData == null ? defaultBlockConfig.get() : blockData; } - double getTracerThickness() { - return tracerThickness.get(); - } - private void updateChunk(int x, int z) { ESPChunk chunk = chunks.get(ChunkPos.toLong(x, z)); if (chunk != null) chunk.update(); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java index c1ec71aa0f..f103f75c79 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPGroup.java @@ -142,7 +142,7 @@ public void render(Render3DEvent event) { ESPBlockData blockData = blockEsp.getBlockData(block); if (blockData.tracer) { - event.renderer.thickLine(RenderUtils.center.x, RenderUtils.center.y, RenderUtils.center.z, sumX / blocks.size() + 0.5, sumY / blocks.size() + 0.5, sumZ / blocks.size() + 0.5, blockData.tracerColor, blockEsp.getTracerThickness()); + event.renderer.line(RenderUtils.center.x, RenderUtils.center.y, RenderUtils.center.z, sumX / blocks.size() + 0.5, sumY / blocks.size() + 0.5, sumZ / blocks.size() + 0.5, blockData.tracerColor); } } }