Skip to content

Commit 05e3c61

Browse files
committed
remove per render region origin
1 parent 1efc938 commit 05e3c61

33 files changed

Lines changed: 653 additions & 760 deletions

src/main/kotlin/com/lambda/graphics/esp/RegionESP.kt

Lines changed: 0 additions & 126 deletions
This file was deleted.

src/main/kotlin/com/lambda/graphics/esp/ShapeScope.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
package com.lambda.graphics.esp
1919

2020
import com.lambda.graphics.mc.RegionShapeBuilder
21-
import com.lambda.graphics.mc.RenderRegion
2221
import com.lambda.graphics.renderer.esp.DirectionMask
2322
import com.lambda.graphics.renderer.esp.DynamicAABB
2423
import net.minecraft.block.BlockState
@@ -28,9 +27,13 @@ import net.minecraft.util.math.Vec3d
2827
import net.minecraft.util.shape.VoxelShape
2928
import java.awt.Color
3029

30+
/**
31+
* Scope for building ESP shapes with camera-relative coordinates.
32+
* @param cameraPos The camera position for computing relative coordinates
33+
*/
3134
@EspDsl
32-
class ShapeScope(val region: RenderRegion) {
33-
internal val builder = RegionShapeBuilder(region)
35+
class ShapeScope(cameraPos: Vec3d) {
36+
internal val builder = RegionShapeBuilder(cameraPos)
3437

3538
/** Start building a box. */
3639
fun box(box: Box, block: BoxScope.() -> Unit) {

src/main/kotlin/com/lambda/graphics/mc/ChunkedRegionESP.kt

Lines changed: 108 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,35 @@
1717

1818
package com.lambda.graphics.mc
1919

20+
import com.lambda.Lambda.mc
2021
import com.lambda.event.events.RenderEvent
2122
import com.lambda.event.events.TickEvent
2223
import com.lambda.event.events.WorldEvent
2324
import com.lambda.event.listener.SafeListener.Companion.listen
2425
import com.lambda.event.listener.SafeListener.Companion.listenConcurrently
25-
import com.lambda.graphics.esp.RegionESP
2626
import com.lambda.graphics.esp.ShapeScope
2727
import com.lambda.module.Module
2828
import com.lambda.module.modules.client.StyleEditor
2929
import com.lambda.threading.runSafe
3030
import com.lambda.util.world.FastVector
3131
import com.lambda.util.world.fastVectorOf
32+
import com.mojang.blaze3d.systems.RenderSystem
33+
import net.minecraft.util.math.Vec3d
3234
import net.minecraft.world.World
3335
import net.minecraft.world.chunk.WorldChunk
36+
import org.joml.Matrix4f
37+
import org.joml.Vector3f
38+
import org.joml.Vector4f
3439
import java.util.concurrent.ConcurrentHashMap
3540
import java.util.concurrent.ConcurrentLinkedDeque
3641

3742
/**
38-
* Region-based chunked ESP system using MC 1.21.11's new render pipeline.
43+
* Chunked ESP system using chunk-origin relative coordinates.
3944
*
4045
* This system:
41-
* - Uses region-relative coordinates for precision-safe rendering
42-
* - Maintains per-chunk geometry for efficient updates
46+
* - Stores geometry relative to chunk origin (stable, small floats)
47+
* - Only rebuilds when chunks are modified
48+
* - At render time, translates from chunk origin to camera-relative position
4349
*
4450
* @param owner The module that owns this ESP system
4551
* @param name The name of the ESP system
@@ -49,18 +55,23 @@ import java.util.concurrent.ConcurrentLinkedDeque
4955
class ChunkedRegionESP(
5056
owner: Module,
5157
name: String,
52-
depthTest: Boolean = false,
58+
private val depthTest: Boolean = false,
5359
private val update: ShapeScope.(World, FastVector) -> Unit
54-
) : RegionESP(name, depthTest) {
55-
private val chunkMap = ConcurrentHashMap<Long, RegionChunk>()
60+
) {
61+
private val chunkMap = ConcurrentHashMap<Long, ChunkData>()
5662

57-
private val WorldChunk.regionChunk
58-
get() = chunkMap.getOrPut(getRegionKey(pos.x shl 4, bottomY, pos.z shl 4)) {
59-
RegionChunk(this)
60-
}
63+
private val WorldChunk.chunkKey: Long
64+
get() = getChunkKey(pos.x, pos.z)
65+
66+
private val WorldChunk.chunkData
67+
get() = chunkMap.getOrPut(chunkKey) { ChunkData(this) }
6168

69+
private val rebuildQueue = ConcurrentLinkedDeque<ChunkData>()
6270
private val uploadQueue = ConcurrentLinkedDeque<() -> Unit>()
63-
private val rebuildQueue = ConcurrentLinkedDeque<RegionChunk>()
71+
72+
private fun getChunkKey(chunkX: Int, chunkZ: Int): Long {
73+
return (chunkX.toLong() and 0xFFFFFFFFL) or ((chunkZ.toLong() and 0xFFFFFFFFL) shl 32)
74+
}
6475

6576
/** Mark all tracked chunks for rebuild. */
6677
fun rebuild() {
@@ -76,37 +87,94 @@ class ChunkedRegionESP(
7687
runSafe {
7788
val chunksArray = world.chunkManager.chunks.chunks
7889
(0 until chunksArray.length()).forEach { i ->
79-
chunksArray.get(i)?.regionChunk?.markDirty()
90+
chunksArray.get(i)?.chunkData?.markDirty()
8091
}
8192
}
8293
}
8394

84-
override fun clear() {
95+
fun clear() {
8596
chunkMap.values.forEach { it.close() }
8697
chunkMap.clear()
8798
rebuildQueue.clear()
8899
uploadQueue.clear()
89100
}
90101

102+
fun close() {
103+
clear()
104+
}
105+
106+
/**
107+
* Render all chunks with camera-relative translation.
108+
*/
109+
fun render() {
110+
val cameraPos = mc.gameRenderer?.camera?.pos ?: return
111+
112+
val activeChunks = chunkMap.values.filter { it.renderer.hasData() }
113+
if (activeChunks.isEmpty()) return
114+
115+
val modelViewMatrix = com.lambda.graphics.RenderMain.modelViewMatrix
116+
117+
// Pre-compute all transforms BEFORE starting render passes
118+
val chunkTransforms = activeChunks.map { chunkData ->
119+
// Compute chunk-to-camera offset in double precision
120+
val offsetX = (chunkData.originX - cameraPos.x).toFloat()
121+
val offsetY = (chunkData.originY - cameraPos.y).toFloat()
122+
val offsetZ = (chunkData.originZ - cameraPos.z).toFloat()
123+
124+
val modelView = Matrix4f(modelViewMatrix).translate(offsetX, offsetY, offsetZ)
125+
val dynamicTransform = RenderSystem.getDynamicUniforms()
126+
.write(modelView, Vector4f(1f, 1f, 1f, 1f), Vector3f(0f, 0f, 0f), Matrix4f())
127+
128+
chunkData to dynamicTransform
129+
}
130+
131+
// Render Faces
132+
RegionRenderer.createRenderPass("ChunkedESP Faces", depthTest)?.use { pass ->
133+
val pipeline =
134+
if (depthTest) LambdaRenderPipelines.ESP_QUADS
135+
else LambdaRenderPipelines.ESP_QUADS_THROUGH
136+
pass.setPipeline(pipeline)
137+
RenderSystem.bindDefaultUniforms(pass)
138+
139+
chunkTransforms.forEach { (chunkData, transform) ->
140+
pass.setUniform("DynamicTransforms", transform)
141+
chunkData.renderer.renderFaces(pass)
142+
}
143+
}
144+
145+
// Render Edges
146+
RegionRenderer.createRenderPass("ChunkedESP Edges", depthTest)?.use { pass ->
147+
val pipeline =
148+
if (depthTest) LambdaRenderPipelines.ESP_LINES
149+
else LambdaRenderPipelines.ESP_LINES_THROUGH
150+
pass.setPipeline(pipeline)
151+
RenderSystem.bindDefaultUniforms(pass)
152+
153+
chunkTransforms.forEach { (chunkData, transform) ->
154+
pass.setUniform("DynamicTransforms", transform)
155+
chunkData.renderer.renderEdges(pass)
156+
}
157+
}
158+
}
159+
91160
init {
92161
owner.listen<WorldEvent.BlockUpdate.Client> { event ->
93162
val pos = event.pos
94-
world.getWorldChunk(pos)?.regionChunk?.markDirty()
163+
world.getWorldChunk(pos)?.chunkData?.markDirty()
95164

96165
val xInChunk = pos.x and 15
97166
val zInChunk = pos.z and 15
98167

99-
if (xInChunk == 0) world.getWorldChunk(pos.west())?.regionChunk?.markDirty()
100-
if (xInChunk == 15) world.getWorldChunk(pos.east())?.regionChunk?.markDirty()
101-
if (zInChunk == 0) world.getWorldChunk(pos.north())?.regionChunk?.markDirty()
102-
if (zInChunk == 15) world.getWorldChunk(pos.south())?.regionChunk?.markDirty()
168+
if (xInChunk == 0) world.getWorldChunk(pos.west())?.chunkData?.markDirty()
169+
if (xInChunk == 15) world.getWorldChunk(pos.east())?.chunkData?.markDirty()
170+
if (zInChunk == 0) world.getWorldChunk(pos.north())?.chunkData?.markDirty()
171+
if (zInChunk == 15) world.getWorldChunk(pos.south())?.chunkData?.markDirty()
103172
}
104173

105-
owner.listen<WorldEvent.ChunkEvent.Load> { event -> event.chunk.regionChunk.markDirty() }
174+
owner.listen<WorldEvent.ChunkEvent.Load> { event -> event.chunk.chunkData.markDirty() }
106175

107176
owner.listen<WorldEvent.ChunkEvent.Unload> {
108-
val pos = getRegionKey(it.chunk.pos.x shl 4, it.chunk.bottomY, it.chunk.pos.z shl 4)
109-
chunkMap.remove(pos)?.close()
177+
chunkMap.remove(it.chunk.chunkKey)?.close()
110178
}
111179

112180
owner.listenConcurrently<TickEvent.Pre> {
@@ -123,10 +191,15 @@ class ChunkedRegionESP(
123191
owner.listen<RenderEvent.Render> { render() }
124192
}
125193

126-
/** Per-chunk rendering data. */
127-
private inner class RegionChunk(val chunk: WorldChunk) {
128-
val region = RenderRegion.forChunk(chunk.pos.x, chunk.pos.z, chunk.bottomY)
129-
private val key = getRegionKey(chunk.pos.x shl 4, chunk.bottomY, chunk.pos.z shl 4)
194+
/** Per-chunk data with its own renderer and origin. */
195+
private inner class ChunkData(val chunk: WorldChunk) {
196+
// Chunk origin in world coordinates
197+
val originX: Double = (chunk.pos.x shl 4).toDouble()
198+
val originY: Double = chunk.bottomY.toDouble()
199+
val originZ: Double = (chunk.pos.z shl 4).toDouble()
200+
201+
// This chunk's own renderer
202+
val renderer = RegionRenderer()
130203

131204
private var isDirty = false
132205

@@ -137,9 +210,16 @@ class ChunkedRegionESP(
137210
}
138211
}
139212

213+
/**
214+
* Rebuild geometry relative to chunk origin.
215+
* Coordinates are stored as (worldPos - chunkOrigin).toFloat()
216+
*/
140217
fun rebuild() {
141218
if (!isDirty) return
142-
val scope = ShapeScope(region)
219+
220+
// Use chunk origin as the "camera" position for relative coords
221+
val chunkOriginVec = Vec3d(originX, originY, originZ)
222+
val scope = ShapeScope(chunkOriginVec)
143223

144224
for (x in chunk.pos.startX..chunk.pos.endX) {
145225
for (z in chunk.pos.startZ..chunk.pos.endZ) {
@@ -150,14 +230,13 @@ class ChunkedRegionESP(
150230
}
151231

152232
uploadQueue.add {
153-
val renderer = renderers.getOrPut(key) { RegionRenderer(region) }
154233
renderer.upload(scope.builder.collector)
155234
isDirty = false
156235
}
157236
}
158237

159238
fun close() {
160-
renderers.remove(key)?.close()
239+
renderer.close()
161240
}
162241
}
163242
}

0 commit comments

Comments
 (0)