procedural-terrains 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{FiniteTerrain-B34WMz5S.js → FiniteTerrain-B5_3y6xX.js} +3 -3
- package/dist/{FiniteTerrain-B34WMz5S.js.map → FiniteTerrain-B5_3y6xX.js.map} +1 -1
- package/dist/{InfiniteTerrain-SgoJz3qJ.js → InfiniteTerrain-jeCy6RED.js} +5 -5
- package/dist/{InfiniteTerrain-SgoJz3qJ.js.map → InfiniteTerrain-jeCy6RED.js.map} +1 -1
- package/dist/{MiniTerrain-Blt0H1S0.js → MiniTerrain-Bb5VYkZU.js} +8 -8
- package/dist/MiniTerrain-Bb5VYkZU.js.map +1 -0
- package/dist/{PlanetMaterial-B1_ZPlx5.js → PlanetMaterial-Cs-_x6vr.js} +4 -4
- package/dist/{PlanetMaterial-B1_ZPlx5.js.map → PlanetMaterial-Cs-_x6vr.js.map} +1 -1
- package/dist/{PlanetTerrain-DCvxS1Q8.js → PlanetTerrain-Bsfx7YA6.js} +5 -5
- package/dist/{PlanetTerrain-DCvxS1Q8.js.map → PlanetTerrain-Bsfx7YA6.js.map} +1 -1
- package/dist/{RevisionScope-J__6V9I_.js → RevisionScope-Dl4yjj-0.js} +2 -2
- package/dist/{RevisionScope-J__6V9I_.js.map → RevisionScope-Dl4yjj-0.js.map} +1 -1
- package/dist/{TerrainClouds-BuKvwnWw.js → TerrainClouds-DV6ny7P1.js} +31 -19
- package/dist/TerrainClouds-DV6ny7P1.js.map +1 -0
- package/dist/{TerrainHeightCache-Dsde6EDL.js → TerrainHeightCache-DIZxi9jz.js} +2 -2
- package/dist/{TerrainHeightCache-Dsde6EDL.js.map → TerrainHeightCache-DIZxi9jz.js.map} +1 -1
- package/dist/{TerrainParameters-A3fcNJTR.js → TerrainParameters-DMCjnnxz.js} +10 -8
- package/dist/TerrainParameters-DMCjnnxz.js.map +1 -0
- package/dist/{TerrainWater-Cil7waG3.js → TerrainWater-CX4XdwA0.js} +17 -11
- package/dist/TerrainWater-CX4XdwA0.js.map +1 -0
- package/dist/{WaterMaterial-BUsAp0SS.js → WaterMaterial-C9h1xm9E.js} +7 -5
- package/dist/WaterMaterial-C9h1xm9E.js.map +1 -0
- package/dist/{biomeGLSL-CIkhxIlH.js → biomeGLSL-DWGDDBqT.js} +6 -3
- package/dist/{biomeGLSL-CIkhxIlH.js.map → biomeGLSL-DWGDDBqT.js.map} +1 -1
- package/dist/clouds.js +1 -1
- package/dist/documents.js +6 -6
- package/dist/export.js +2 -2
- package/dist/index.js +1 -1
- package/dist/infinite.js +1 -1
- package/dist/mini.js +1 -1
- package/dist/planet.js +1 -1
- package/dist/{planetGLSL-2xas0f3o.js → planetGLSL-D9Zy2IAw.js} +2 -2
- package/dist/{planetGLSL-2xas0f3o.js.map → planetGLSL-D9Zy2IAw.js.map} +1 -1
- package/dist/real-world.js +1 -1
- package/dist/render.js +1 -1
- package/dist/viewer.js +1 -1
- package/dist/water.js +1 -1
- package/package.json +1 -1
- package/dist/MiniTerrain-Blt0H1S0.js.map +0 -1
- package/dist/TerrainClouds-BuKvwnWw.js.map +0 -1
- package/dist/TerrainParameters-A3fcNJTR.js.map +0 -1
- package/dist/TerrainWater-Cil7waG3.js.map +0 -1
- package/dist/WaterMaterial-BUsAp0SS.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as THREE from "three";
|
|
2
|
-
import { b as buildChunkGeometry, s as setChunkBounds, p as publishMorphUniforms, d as createCullingContext, e as cullChunks, a as stepTemporalLod, F as FiniteTerrain } from "./FiniteTerrain-
|
|
3
|
-
import { b as buildHeightGLSL, C as COMMON_UNIFORMS_GLSL, N as NOISE_GLSL, B as BIOME_GLSL } from "./biomeGLSL-
|
|
2
|
+
import { b as buildChunkGeometry, s as setChunkBounds, p as publishMorphUniforms, d as createCullingContext, e as cullChunks, a as stepTemporalLod, F as FiniteTerrain } from "./FiniteTerrain-B5_3y6xX.js";
|
|
3
|
+
import { b as buildHeightGLSL, C as COMMON_UNIFORMS_GLSL, N as NOISE_GLSL, B as BIOME_GLSL } from "./biomeGLSL-DWGDDBqT.js";
|
|
4
4
|
import { g as generateStackGLSL, d as defaultLegacyStack } from "./noiseStackCodegen-C4R9Y3L8.js";
|
|
5
|
-
import { f as createInfiniteTerrainMaterial } from "./TerrainParameters-
|
|
6
|
-
import { c as createInfiniteWaterMaterial } from "./WaterMaterial-
|
|
5
|
+
import { f as createInfiniteTerrainMaterial } from "./TerrainParameters-DMCjnnxz.js";
|
|
6
|
+
import { c as createInfiniteWaterMaterial } from "./WaterMaterial-C9h1xm9E.js";
|
|
7
7
|
import { c as compileMaterial } from "./CompileMaterial-DZiWxNZC.js";
|
|
8
8
|
import { w as withRendererState } from "./RendererState-BwgUc9ze.js";
|
|
9
9
|
const DEFAULT_BUDGET_MS = 1.5;
|
|
@@ -1244,4 +1244,4 @@ async function createInfiniteTerrain(options) {
|
|
|
1244
1244
|
export {
|
|
1245
1245
|
createInfiniteTerrain as c
|
|
1246
1246
|
};
|
|
1247
|
-
//# sourceMappingURL=InfiniteTerrain-
|
|
1247
|
+
//# sourceMappingURL=InfiniteTerrain-jeCy6RED.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfiniteTerrain-SgoJz3qJ.js","sources":["../../../src/engine/terrain/ChunkStreamScheduler.js","../../../src/engine/terrain/InfiniteTerrainBatches.js","../../../src/engine/terrain/MergeQuadtree.js","../../../src/engine/terrain/InfiniteWorld.js","../../../src/engine/terrain/InfiniteTerrainClipmap.js","../../../src/runtime/worlds/InfiniteTerrain.js"],"sourcesContent":["const DEFAULT_BUDGET_MS = 1.5;\nconst DEFAULT_AUTO_MAX_ITEMS = 24;\n\nconst radialOffsetCache = new Map();\n\n/**\n * Return the integer offsets inside a circular radius, nearest first.\n * The immutable result is cached because every chunk-boundary crossing uses\n * the same pattern translated around a new player chunk.\n */\nexport function getRadialOffsets(radius) {\n const r = Math.max(0, Math.floor(Number(radius) || 0));\n let cached = radialOffsetCache.get(r);\n if (cached) return cached;\n\n const r2 = r * r;\n const offsets = [];\n for (let dz = -r; dz <= r; dz++) {\n for (let dx = -r; dx <= r; dx++) {\n const dist2 = dx * dx + dz * dz;\n if (dist2 <= r2) offsets.push(Object.freeze({ dx, dz, dist2 }));\n }\n }\n offsets.sort((a, b) => a.dist2 - b.dist2 || a.dz - b.dz || a.dx - b.dx);\n cached = Object.freeze(offsets);\n radialOffsetCache.set(r, cached);\n return cached;\n}\n\n/**\n * Small time-budgeted FIFO used by InfiniteWorld. reset() intentionally\n * replaces pending work: after a fast player move, old chunk requests are no\n * longer useful and must not delay the new nearest chunks.\n */\nexport class ChunkStreamScheduler {\n constructor({ budgetMs = DEFAULT_BUDGET_MS, autoMaxItems = DEFAULT_AUTO_MAX_ITEMS, now } = {}) {\n this.budgetMs = budgetMs;\n this.autoMaxItems = autoMaxItems;\n this._now = now || (() => performance.now());\n this._items = [];\n this._head = 0;\n }\n\n get pendingCount() {\n return Math.max(0, this._items.length - this._head);\n }\n\n reset(items = []) {\n this._items = Array.isArray(items) ? items : [...items];\n this._head = 0;\n }\n\n clear() {\n this._items = [];\n this._head = 0;\n }\n\n /**\n * Process nearest-first work until either the time or item budget is spent.\n * maxItems=0 means automatic scheduling, not unlimited work.\n */\n process(create, { budgetMs = this.budgetMs, maxItems = 0 } = {}) {\n if (typeof create !== 'function' || this.pendingCount === 0) {\n return { processed: 0, created: 0, elapsedMs: 0, pendingCount: this.pendingCount };\n }\n\n const itemLimit = maxItems > 0\n ? Math.max(1, Math.floor(maxItems))\n : this.autoMaxItems;\n const timeLimit = Number.isFinite(budgetMs) && budgetMs > 0\n ? budgetMs\n : DEFAULT_BUDGET_MS;\n const startedAt = this._now();\n let processed = 0;\n let created = 0;\n\n while (this._head < this._items.length && processed < itemLimit) {\n // Always allow the first item, then enforce the elapsed-time budget.\n if (processed > 0 && this._now() - startedAt >= timeLimit) break;\n const item = this._items[this._head++];\n processed++;\n if (create(item) !== false) created++;\n }\n\n if (this._head >= this._items.length) this.clear();\n return {\n processed,\n created,\n elapsedMs: this._now() - startedAt,\n pendingCount: this.pendingCount,\n };\n }\n}\n\nexport const CHUNK_STREAM_DEFAULTS = Object.freeze({\n budgetMs: DEFAULT_BUDGET_MS,\n autoMaxItems: DEFAULT_AUTO_MAX_ITEMS,\n});\n","import * as THREE from 'three';\n\nconst LOD_COUNT = 4;\n\n/**\n * Render logical Infinite World chunks through one InstancedMesh per LOD.\n * Streaming creates lightweight records only; scene-graph objects and terrain\n * draw calls stay constant as the player moves.\n */\nexport class InfiniteTerrainBatches {\n constructor({ group, material, geometries, capacity }) {\n this.group = group;\n this.material = material;\n this.geometries = geometries;\n this.capacity = Math.max(1, Math.ceil(capacity));\n this.meshes = [];\n this.counts = [0, 0, 0, 0];\n this._matrix = new THREE.Matrix4();\n this._createMeshes();\n }\n\n // Per-instance temporal geomorph factor (see LodMorph.stepTemporalLod).\n // The LOD geometries are owned by this batch set, so the instanced\n // attribute lives directly on them.\n _attachMorphAttribute(geometry) {\n const current = geometry.getAttribute('aMorphK');\n if (current && current.count >= this.capacity) return current;\n const attribute = new THREE.InstancedBufferAttribute(new Float32Array(this.capacity), 1);\n attribute.setUsage(THREE.DynamicDrawUsage);\n geometry.setAttribute('aMorphK', attribute);\n return attribute;\n }\n\n _createMeshes() {\n this.meshes = this.geometries.map((geometry, lod) => {\n this._attachMorphAttribute(geometry);\n const mesh = new THREE.InstancedMesh(geometry, this.material, this.capacity);\n mesh.name = `infinite-terrain-lod-${lod}`;\n mesh.count = 0;\n mesh.frustumCulled = false;\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage);\n this.group.add(mesh);\n return mesh;\n });\n }\n\n ensureCapacity(capacity) {\n const required = Math.max(1, Math.ceil(capacity));\n if (required <= this.capacity) return false;\n\n for (const mesh of this.meshes) this.group.remove(mesh);\n this.capacity = required;\n this._createMeshes();\n return true;\n }\n\n updateGeometry(lod, geometry) {\n this._attachMorphAttribute(geometry);\n this.geometries[lod] = geometry;\n this.meshes[lod].geometry = geometry;\n }\n\n /**\n * Compact visible records into their LOD batch. Matrices are uploaded only\n * when InfiniteWorld reports a topology, visibility or LOD change.\n */\n commit(chunks, chunkSize) {\n const counts = [0, 0, 0, 0];\n for (const chunk of chunks) {\n if (chunk.visible === false) continue;\n const lod = Math.min(LOD_COUNT - 1, Math.max(0, chunk.lod | 0));\n const slot = counts[lod]++;\n if (slot >= this.capacity) {\n throw new RangeError(`Infinite terrain batch ${lod} exceeded capacity ${this.capacity}`);\n }\n this._matrix.makeScale(chunkSize, chunkSize, chunkSize);\n this._matrix.setPosition(chunk.cx * chunkSize, 0, chunk.cz * chunkSize);\n this.meshes[lod].setMatrixAt(slot, this._matrix);\n const morph = this.meshes[lod].geometry.getAttribute('aMorphK');\n if (morph) morph.array[slot] = chunk.morph || 0;\n }\n\n for (let lod = 0; lod < LOD_COUNT; lod++) {\n const mesh = this.meshes[lod];\n mesh.count = counts[lod];\n if (counts[lod] > 0 || this.counts[lod] > 0) {\n mesh.instanceMatrix.needsUpdate = true;\n const morph = mesh.geometry.getAttribute('aMorphK');\n if (morph) morph.needsUpdate = true;\n }\n }\n this.counts = counts;\n return counts;\n }\n\n setVisible(visible) {\n for (const mesh of this.meshes) mesh.visible = visible;\n }\n\n dispose() {\n for (const mesh of this.meshes) this.group.remove(mesh);\n this.meshes = [];\n this.counts = [0, 0, 0, 0];\n }\n}\n","import * as THREE from 'three';\nimport { buildChunkGeometry } from './ChunkGeometry.js';\n\n// ============================================================================\n// MergeQuadtree: shared chunked-LOD merge layer for the FLAT GPU-displaced\n// terrain modes (Tile board + Infinite world). The host's chunks are the\n// leaves of a quadtree on their integer grid; each internal node covers a\n// power-of-two square block and folds into ONE flat unit-grid mesh (same\n// material) once the camera is far enough for its size. Folding happens 2x2 at\n// a time, so the visible set is a smooth cut — fine chunks near the camera,\n// progressively larger merged blocks outward — never a hard jump.\n//\n// A node only folds when it is FULL (its whole square is tiled by existing\n// chunks); partial nodes (streaming edge / assembly boundary) never fold, so a\n// merged mesh can't paint terrain across a gap. Height is GPU-driven, so a\n// merged node is just a bigger unit grid — no baking/cache/async. The win is\n// fewer draw calls / matrix updates / frustum checks (CPU), not GPU triangles.\n//\n// The host owns the chunk objects; the tree only reads { mesh, center } and\n// writes { merged, mesh.visible, ix, iz, node }. After update() the host culls:\n// skip chunks where `merged`, and cull the meshes in `mergedNodes`.\n// ============================================================================\n\nexport class MergeQuadtree {\n constructor(group, material) {\n this.group = group;\n this.material = material;\n\n this.enabled = true;\n this.quadsPerChunk = 8; // merged grid density per chunk span (8 == LOD3)\n this.mergeDistance = 4; // a node folds when nearest > spanWorld × this\n this.allowRoot = true; // allow the whole region to fold to one mesh\n this.distanceScale = 1; // mirrors the host's LOD distance scale\n this.chunkSize = 1;\n\n this._geo = new Map(); // \"res:aLod\" -> shared BufferGeometry\n this._root = null;\n this._dirty = true;\n this._gridOriginX = 0;\n this._gridOriginZ = 0;\n\n this.mergedNodes = []; // nodes folded this frame (host culls these)\n this.hiddenCount = 0; // chunks hidden by folds (for stats)\n }\n\n setChunkSize(cs) {\n if (cs !== this.chunkSize) { this.chunkSize = cs; this._dirty = true; this._disposeNodeMeshes(); }\n }\n\n setOptions({ enabled, quadsPerChunk, mergeDistance, allowRoot, distanceScale } = {}) {\n if (enabled !== undefined) this.enabled = !!enabled;\n if (allowRoot !== undefined) this.allowRoot = !!allowRoot;\n if (distanceScale !== undefined && Number.isFinite(+distanceScale)) this.distanceScale = +distanceScale;\n if (mergeDistance !== undefined && Number.isFinite(+mergeDistance)) this.mergeDistance = Math.max(0.5, +mergeDistance);\n if (quadsPerChunk !== undefined) {\n const v = Math.max(2, Math.round(quadsPerChunk));\n if (v !== this.quadsPerChunk) { this.quadsPerChunk = v; this._disposeNodeMeshes(); }\n }\n }\n\n markDirty() { this._dirty = true; }\n\n // Walk the tree and fold/unfold nodes for the current camera. `chunks` is any\n // iterable of the host's chunk objects ({ mesh, center, merged }).\n update(chunks, camPos) {\n if (!this.enabled) { this._restore(chunks); return; }\n if (this._dirty) this._rebuild(chunks);\n\n this.mergedNodes.length = 0;\n this.hiddenCount = 0;\n if (this._root) this._visit(this._root, camPos);\n }\n\n // --- tree build ----------------------------------------------------------\n _rebuild(chunks) {\n this._dirty = false;\n this._disposeNodeMeshes();\n const list = Array.isArray(chunks) ? chunks : [...chunks];\n if (!list.length) { this._root = null; return; }\n\n const cs = this.chunkSize;\n let minX = Infinity, minZ = Infinity;\n for (const c of list) {\n const x0 = c.center.x - cs / 2, z0 = c.center.z - cs / 2;\n if (x0 < minX) minX = x0;\n if (z0 < minZ) minZ = z0;\n }\n this._gridOriginX = minX;\n this._gridOriginZ = minZ;\n\n let gw = 0, gh = 0;\n for (const c of list) {\n c.ix = Math.round((c.center.x - cs / 2 - minX) / cs);\n c.iz = Math.round((c.center.z - cs / 2 - minZ) / cs);\n if (c.ix + 1 > gw) gw = c.ix + 1;\n if (c.iz + 1 > gh) gh = c.iz + 1;\n c.node = null;\n c.merged = false;\n c.mesh.visible = true;\n }\n\n let size = 1;\n while (size < Math.max(gw, gh, 1)) size *= 2;\n this._root = this._buildNode(list, 0, 0, size, 0);\n }\n\n _buildNode(chunks, x0, z0, size, level) {\n if (!chunks.length) return null;\n if (size === 1) return this._leafNode(chunks[0], x0, z0, level);\n\n const half = size / 2;\n const midX = x0 + half, midZ = z0 + half;\n const q = [[], [], [], []];\n for (const c of chunks) {\n const qx = c.ix < midX ? 0 : 1;\n const qz = c.iz < midZ ? 0 : 1;\n q[qz * 2 + qx].push(c);\n }\n const offs = [[x0, z0], [midX, z0], [x0, midZ], [midX, midZ]];\n const children = [];\n for (let i = 0; i < 4; i++) {\n if (!q[i].length) continue;\n const child = this._buildNode(q[i], offs[i][0], offs[i][1], half, level + 1);\n if (child) children.push(child);\n }\n const full = chunks.length === size * size;\n if (!full && children.length === 1) return children[0];\n return this._internalNode(children, chunks, x0, z0, size, level, full);\n }\n\n _leafNode(chunk, x0, z0, level) {\n const cs = this.chunkSize;\n const minX = this._gridOriginX + x0 * cs, minZ = this._gridOriginZ + z0 * cs;\n const node = {\n leaf: true, chunk, children: null, chunks: [chunk], full: true,\n minX, minZ, spanX: cs, spanZ: cs, spanWorld: cs, spanChunks: 1,\n center: new THREE.Vector3(minX + cs / 2, 0, minZ + cs / 2),\n half: cs * 0.7072, level, mesh: null, merged: false,\n };\n chunk.node = node;\n return node;\n }\n\n _internalNode(children, chunks, x0, z0, size, level, full) {\n const cs = this.chunkSize;\n const minX = this._gridOriginX + x0 * cs, minZ = this._gridOriginZ + z0 * cs;\n const span = size * cs;\n return {\n leaf: false, chunk: null, children, chunks, full,\n minX, minZ, spanX: span, spanZ: span, spanWorld: span, spanChunks: size,\n center: new THREE.Vector3(minX + span / 2, 0, minZ + span / 2),\n half: 0.5 * Math.SQRT2 * span, level, mesh: null, merged: false,\n };\n }\n\n // --- traversal -----------------------------------------------------------\n _visit(node, camPos) {\n if (node.leaf) {\n if (node.chunk.merged) { node.chunk.merged = false; node.chunk.mesh.visible = true; }\n return;\n }\n const canFold = node.full && (this.allowRoot || node.level > 0);\n if (canFold) {\n const nearest = Math.hypot(node.center.x - camPos.x, camPos.y, node.center.z - camPos.z) - node.half;\n const foldDist = node.spanWorld * this.mergeDistance * this.distanceScale;\n const want = node.merged ? nearest > foldDist * 0.85 : nearest > foldDist;\n if (want) {\n if (!node.merged) this._fold(node);\n this.mergedNodes.push(node);\n this.hiddenCount += node.chunks.length;\n return;\n }\n }\n if (node.merged) this._unfold(node);\n for (const child of node.children) this._visit(child, camPos);\n }\n\n _fold(node) {\n node.merged = true;\n if (!node.mesh) {\n const tier = Math.max(1, Math.round(Math.log2(node.spanChunks)));\n const res = Math.min(160, Math.max(8, node.spanChunks * this.quadsPerChunk));\n const aLod = 3 + Math.min(5, tier);\n const mesh = new THREE.Mesh(this._geometry(res, aLod), this.material);\n mesh.position.set(node.minX, 0, node.minZ);\n mesh.scale.set(node.spanX, 1, node.spanZ);\n mesh.matrixAutoUpdate = false;\n mesh.frustumCulled = false;\n mesh.updateMatrix();\n mesh.updateMatrixWorld(true);\n this.group.add(mesh);\n node.mesh = mesh;\n }\n node.mesh.visible = true;\n for (const c of node.chunks) { c.merged = true; c.mesh.visible = false; }\n this._forEachDescendantInternal(node, (d) => {\n d.merged = false;\n if (d.mesh) d.mesh.visible = false;\n });\n }\n\n _unfold(node) {\n node.merged = false;\n if (node.mesh) node.mesh.visible = false;\n }\n\n _geometry(res, aLod) {\n const key = `${res}:${aLod}`;\n let geo = this._geo.get(key);\n if (!geo) {\n geo = buildChunkGeometry(res, aLod);\n this._geo.set(key, geo);\n }\n return geo;\n }\n\n _forEachDescendantInternal(node, fn) {\n if (!node.children) return;\n for (const child of node.children) {\n if (child.leaf) continue;\n fn(child);\n this._forEachDescendantInternal(child, fn);\n }\n }\n\n _forEachInternal(fn) {\n const rec = (n) => {\n if (!n || n.leaf) return;\n fn(n);\n for (const c of n.children) rec(c);\n };\n rec(this._root);\n }\n\n _restore(chunks) {\n for (const c of chunks.values ? chunks.values() : chunks) {\n if (c.merged) { c.merged = false; c.mesh.visible = true; }\n }\n this._forEachInternal((n) => { n.merged = false; if (n.mesh) n.mesh.visible = false; });\n this.mergedNodes.length = 0;\n this.hiddenCount = 0;\n }\n\n _disposeNodeMeshes() {\n this._forEachInternal((n) => {\n if (n.mesh) { this.group.remove(n.mesh); n.mesh = null; }\n n.merged = false;\n });\n this.mergedNodes.length = 0;\n }\n\n dispose() {\n this._disposeNodeMeshes();\n for (const geo of this._geo.values()) geo.dispose();\n this._geo.clear();\n this._root = null;\n this._dirty = true;\n this.mergedNodes.length = 0;\n this.hiddenCount = 0;\n }\n}\n","import * as THREE from 'three';\nimport { buildChunkGeometry, setChunkBounds } from './ChunkGeometry.js';\nimport { publishMorphUniforms, stepTemporalLod } from './LodMorph.js';\nimport { createCullingContext, cullChunks } from './InfiniteTerrainCulling.js';\nimport { ChunkStreamScheduler, getRadialOffsets } from './ChunkStreamScheduler.js';\nimport { InfiniteTerrainBatches } from './InfiniteTerrainBatches.js';\nimport { MergeQuadtree } from './MergeQuadtree.js';\n\n// ============================================================================\n// InfiniteWorld: streams terrain chunks around the player camera.\n// Chunks are lightweight logical records on an integer grid (cx, cz). Visible\n// records are compacted into four InstancedMesh batches, one per LOD, keeping\n// terrain draw calls and scene-graph objects constant while the player moves.\n// ============================================================================\n\nconst LOD_RESOLUTIONS = [64, 32, 16, 8];\nconst DEFAULT_LOD_DISTANCES = [4, 8, 14]; // × chunkSize\nconst DEFAULT_MAX_CREATES = 0;\n\nexport class InfiniteWorld {\n /**\n * @param {THREE.Scene} scene\n * @param {THREE.Material} terrainMaterial — infinite-mode terrain material\n * @param {THREE.Material} waterMaterial — infinite-mode water material\n * @param {Object} opts\n * @param {number} opts.chunkSize — world units per chunk side\n * @param {number} opts.viewRadius — how many chunks outward to load\n * @param {number} opts.maxHeight — vertical ceiling for bounding boxes\n * @param {number} opts.skirtDepth — skirt depth for geometry bounds\n * @param {number} opts.seaLevel — water plane height\n * @param {number[]} [opts.lodSegments] — per-LOD quads per chunk side\n * @param {number[]} [opts.lodDistances] — LOD thresholds (× chunkSize)\n * @param {number} [opts.waterDistance] — water extent as fraction of terrain\n */\n constructor(scene, terrainMaterial, waterMaterial, opts) {\n this.scene = scene;\n this.terrainMaterial = terrainMaterial;\n this.waterMaterial = waterMaterial;\n\n this.chunkSize = opts.chunkSize;\n this.viewRadius = opts.viewRadius || 12;\n this.maxHeight = opts.maxHeight;\n this.skirtDepth = opts.skirtDepth;\n this.seaLevel = opts.seaLevel ?? 42;\n this.maxCreatesPerFrame = DEFAULT_MAX_CREATES;\n this.chunkStreamBudgetMs = 1.5;\n this.lodSegments = opts.lodSegments ? [...opts.lodSegments] : [...LOD_RESOLUTIONS];\n\n // Culling options\n this.cullingEnabled = true;\n this.behindCameraCulling = true;\n this.cullingAggressiveness = 1.0;\n\n // Triangle budget: when the rendered triangle count exceeds the budget,\n // LOD thresholds are scaled down progressively (no geometry rebuild)\n // until the scene fits; they recover when there is headroom.\n this.triangleBudget = 0; // 0 = unlimited\n this._budgetScale = 1.0;\n this._lastTriangles = 0;\n this._budgetCheckAt = 0;\n\n // Gradual LOD geometry rebuild queue (one LOD level per frame)\n this._lodRebuildQueue = [];\n this._targetSegments = null;\n\n // Water render distance as a fraction of the terrain render distance\n this._waterDistanceFactor = opts.waterDistance ?? 1.0;\n\n // group contains all terrain chunks\n this.group = new THREE.Group();\n this.group.name = 'infinite-world';\n this.scene.add(this.group);\n\n // water plane — follows player, sized to match terrain radius\n this.waterPlane = new THREE.Mesh(\n new THREE.PlaneGeometry(1, 1),\n this.waterMaterial\n );\n this.waterPlane.geometry.rotateX(-Math.PI / 2);\n this.waterPlane.renderOrder = 10;\n this.waterPlane.frustumCulled = false;\n this.waterPlane.position.y = this.seaLevel;\n this._updateWaterSize();\n this.scene.add(this.waterPlane);\n\n // shared geometries per LOD\n this.geometries = this.lodSegments.map((res, lodIndex) => {\n const geo = buildChunkGeometry(res, lodIndex, { morph: true });\n setChunkBounds(geo, this.chunkSize, this.maxHeight, this.skirtDepth);\n return geo;\n });\n\n // LOD distance thresholds (scale with chunk size and quality)\n this._baseLodThresholds = opts.lodDistances\n ? [...opts.lodDistances]\n : [...DEFAULT_LOD_DISTANCES]; // multiplied by chunkSize\n this._lodMultiplier = 1.0;\n this.lodThresholds = this._baseLodThresholds.map(m => m * this.chunkSize);\n this._lodThresholds2 = this.lodThresholds.map(t => t * t);\n // Temporal geomorphing (smooth LOD transitions) — see LodMorph.js\n this.morphEnabled = true;\n this.morphDuration = 0.4;\n this.morphingChunkCount = 0;\n this._lastLodStepAt = null;\n\n // chunk map: \"cx,cz\" -> { cx, cz, centerX, centerZ, lod, visible }\n this.chunks = new Map();\n\n // player chunk tracking\n this._lastPlayerCX = Infinity;\n this._lastPlayerCZ = Infinity;\n\n // Time-budgeted nearest-first chunk streaming queue.\n this.streamScheduler = new ChunkStreamScheduler({\n budgetMs: this.chunkStreamBudgetMs,\n });\n\n // Instancing already solves the draw-call problem that MergeQuadtree was\n // built for. Keep the public merge object for settings/diagnostics, but do\n // not build or visit its tree on the instanced path.\n this.merge = new MergeQuadtree(this.group, this.terrainMaterial);\n this.merge.setChunkSize(this.chunkSize);\n this.merge.setOptions({ enabled: false });\n this.mergedGroupCount = 0;\n this.savedDrawCalls = 0;\n\n this.batches = new InfiniteTerrainBatches({\n group: this.group,\n material: this.terrainMaterial,\n geometries: this.geometries,\n capacity: getRadialOffsets(this.viewRadius + 2).length,\n });\n this._batchesDirty = true;\n this._cullingContext = {};\n\n // stats\n this.activeChunkCount = 0;\n this.visibleChunkCount = 0;\n this.culledChunkCount = 0;\n this.lodCounts = [0, 0, 0, 0];\n this.pendingChunkCount = 0;\n this.createdChunkCount = 0;\n this.removedChunkCount = 0;\n this.streamTimeMs = 0;\n this.terrainDrawCallCount = 0;\n }\n\n /** Tune the merge layer (performance settings). */\n setMergeOptions(opts) {\n // Merge meshes and instanced batches solve the same draw-call problem.\n // Building both would add traversal/rebuild cost without reducing draws.\n this.merge.setOptions({ ...opts, enabled: false });\n }\n\n /** Toggle the merge-debug surface tint (drives the shared uMergeDebug). */\n setMergeDebug(on) {\n const u = this.terrainMaterial?.uniforms?.uMergeDebug;\n if (u) u.value = on ? 1.0 : 0.0;\n }\n\n /**\n * Update water plane size to match terrain render distance.\n * Water extends exactly to the terrain edge (viewRadius * 2 + 1 chunks)\n * so it never renders beyond where terrain exists.\n */\n _updateWaterSize() {\n const waterSize = this.chunkSize * (this.viewRadius * 2 + 1) * this._waterDistanceFactor;\n this.waterPlane.scale.set(waterSize, 1, waterSize);\n\n // Update water fade distance uniforms (if available)\n if (this.waterMaterial.uniforms.uWaterFadeStart) {\n const fadeStart = waterSize * 0.42;\n const fadeEnd = waterSize * 0.50;\n this.waterMaterial.uniforms.uWaterFadeStart.value = fadeStart;\n this.waterMaterial.uniforms.uWaterFadeEnd.value = fadeEnd;\n }\n }\n\n /**\n * Change the view radius at runtime (e.g. quality preset change).\n * Recalculates chunk set, water size, and LOD thresholds without\n * rebuilding chunk geometry.\n */\n setViewRadius(r) {\n if (r === this.viewRadius) return;\n this.viewRadius = r;\n this._recalcLodThresholds();\n this._updateWaterSize();\n if (this.batches.ensureCapacity(getRadialOffsets(this.viewRadius + 2).length)) {\n this._batchesDirty = true;\n }\n // Force recalc on next update\n this._lastPlayerCX = Infinity;\n this._lastPlayerCZ = Infinity;\n }\n\n /**\n * Change the LOD distance multiplier (quality preset).\n * Lower = chunks drop to low-detail sooner (better perf).\n * Higher = chunks keep high-detail further out (better visuals).\n */\n setLodMultiplier(m) {\n this._lodMultiplier = m;\n this._recalcLodThresholds();\n }\n\n /**\n * Change the base LOD distance thresholds (in chunk-size units).\n */\n setLodDistances(distances) {\n this._baseLodThresholds = [...distances];\n this._recalcLodThresholds();\n }\n\n /** Recompute LOD thresholds from base × chunkSize × multiplier × budget. */\n _recalcLodThresholds() {\n this.lodThresholds = this._baseLodThresholds.map(\n m => m * this.chunkSize * this._lodMultiplier * this._budgetScale\n );\n this._lodThresholds2 = this.lodThresholds.map(t => t * t);\n }\n\n setMorphEnabled(enabled) {\n this.morphEnabled = !!enabled;\n }\n\n /**\n * Change max chunk creates per frame. 0 selects the automatic time-budgeted\n * scheduler; it no longer means unbounded work in one frame.\n */\n setMaxCreatesPerFrame(n) {\n const v = Number(n);\n if (!Number.isFinite(v)) {\n this.maxCreatesPerFrame = DEFAULT_MAX_CREATES;\n } else if (v <= 0) {\n this.maxCreatesPerFrame = DEFAULT_MAX_CREATES;\n } else {\n this.maxCreatesPerFrame = Math.max(1, Math.round(v));\n }\n }\n\n setChunkStreamBudget(ms) {\n const value = Number(ms);\n if (!Number.isFinite(value) || value <= 0) return;\n this.chunkStreamBudgetMs = Math.min(8, Math.max(0.25, value));\n this.streamScheduler.budgetMs = this.chunkStreamBudgetMs;\n }\n\n /**\n * Change per-LOD segment counts. Geometry is rebuilt GRADUALLY — one LOD\n * level per frame in update() — so the app never freezes, and chunks keep\n * their old shared geometry until the replacement is ready.\n */\n setLodSegments(segments) {\n const same = segments.length === this.lodSegments.length\n && segments.every((s, i) => s === this.lodSegments[i])\n && !this._lodRebuildQueue.length;\n if (same) return;\n this._targetSegments = [...segments];\n // Rebuild cheap (far) LODs first so streaming chunks pick them up early\n this._lodRebuildQueue = [3, 2, 1, 0];\n }\n\n /** Build one queued LOD geometry and swap it on the chunks using it. */\n _processLodRebuild() {\n if (!this._lodRebuildQueue.length || !this._targetSegments) return;\n const lod = this._lodRebuildQueue.shift();\n const res = this._targetSegments[lod];\n if (res === this.lodSegments[lod]) return; // this level is unchanged\n\n const geo = buildChunkGeometry(res, lod, { morph: true });\n setChunkBounds(geo, this.chunkSize, this.maxHeight, this.skirtDepth);\n const old = this.geometries[lod];\n this.geometries[lod] = geo;\n this.lodSegments[lod] = res;\n\n this.batches.updateGeometry(lod, geo);\n this._batchesDirty = true;\n old.dispose();\n }\n\n /**\n * Set the maximum triangle budget (0 = unlimited). Enforced by scaling\n * LOD thresholds down — cheap LOD swaps only, never a rebuild.\n */\n setTriangleBudget(n) {\n this.triangleBudget = n;\n if (!n) {\n this._budgetScale = 1.0;\n this._recalcLodThresholds();\n }\n }\n\n /**\n * Feed the renderer's triangle count (called from Engine after render).\n * Adjusts the budget scale at most twice per second.\n */\n notifyTriangles(triangles) {\n this._lastTriangles = triangles;\n if (!this.triangleBudget) return;\n const now = performance.now();\n if (now - this._budgetCheckAt < 500) return;\n this._budgetCheckAt = now;\n\n if (triangles > this.triangleBudget && this._budgetScale > 0.35) {\n this._budgetScale = Math.max(0.35, this._budgetScale * 0.9);\n this._recalcLodThresholds();\n } else if (triangles < this.triangleBudget * 0.7 && this._budgetScale < 1.0) {\n this._budgetScale = Math.min(1.0, this._budgetScale * 1.05);\n this._recalcLodThresholds();\n }\n }\n\n /**\n * Set water render distance as a fraction (0.25–1) of terrain distance.\n * Only affects the water plane — terrain is untouched.\n */\n setWaterDistanceFactor(f) {\n const clamped = Math.min(1, Math.max(0.25, f));\n if (clamped === this._waterDistanceFactor) return;\n this._waterDistanceFactor = clamped;\n this._updateWaterSize();\n }\n\n /**\n * Called each frame from Engine._tick(). Determines which chunks should\n * exist, creates missing ones (throttled), removes distant ones, updates\n * LOD, and culls invisible chunks.\n */\n update(playerPos, camera) {\n const cs = this.chunkSize;\n const pcx = Math.floor(playerPos.x / cs);\n const pcz = Math.floor(playerPos.z / cs);\n\n // Move water plane to follow player (keeps precision reasonable)\n this.waterPlane.position.x = pcx * cs;\n this.waterPlane.position.z = pcz * cs;\n\n // If player crossed a chunk boundary, recalculate desired set\n if (pcx !== this._lastPlayerCX || pcz !== this._lastPlayerCZ) {\n this._lastPlayerCX = pcx;\n this._lastPlayerCZ = pcz;\n this._recalcChunkSet(pcx, pcz);\n }\n\n // Create pending chunks (throttled)\n this._createPending();\n\n // Process at most one gradual LOD geometry rebuild per frame\n this._processLodRebuild();\n\n // Select logical LODs, then cull and compact only visible records into the\n // four persistent GPU batches. Morph bands follow the (budget-scaled)\n // thresholds every frame.\n this._updateLOD(playerPos);\n // Instanced chunks morph temporally (per-instance factor); the distance\n // bands are a Tile-board feature, so only the grid ladder is published.\n publishMorphUniforms(this.terrainMaterial?.uniforms, null, this.lodSegments, false);\n const segs = this.terrainMaterial?.uniforms?.uLodGridSegments;\n if (segs) segs.value.set(this.lodSegments[0], this.lodSegments[1], this.lodSegments[2], this.lodSegments[3]);\n if (camera) this._cull(camera);\n if (this._batchesDirty) {\n const batchCounts = this.batches.commit(this.chunks.values(), this.chunkSize);\n this.terrainDrawCallCount = batchCounts.reduce(\n (total, count) => total + (count > 0 ? 1 : 0),\n 0\n );\n this._batchesDirty = false;\n }\n }\n\n /** Frustum + behind-camera cull for active chunks and folded node meshes. */\n _cull(camera) {\n if (!this.cullingEnabled) {\n let visibleCount = 0;\n for (const chunk of this.chunks.values()) {\n if (chunk.visible === false) {\n chunk.visible = true;\n this._batchesDirty = true;\n }\n visibleCount++;\n }\n this.visibleChunkCount = visibleCount;\n this.culledChunkCount = 0;\n return;\n }\n\n camera.updateMatrixWorld(true);\n createCullingContext(\n camera,\n this.chunkSize,\n this.behindCameraCulling,\n this.cullingAggressiveness,\n this._cullingContext,\n -this.skirtDepth\n );\n const chunkResult = cullChunks(\n this.chunks, camera, this.chunkSize,\n this.maxHeight, this.behindCameraCulling, this.cullingAggressiveness,\n this._cullingContext\n );\n if (chunkResult.changedCount) this._batchesDirty = true;\n this.visibleChunkCount = chunkResult.visibleCount;\n this.culledChunkCount = chunkResult.culledCount;\n }\n\n /**\n * Recalculate which chunks should exist around the player chunk.\n * Queue missing chunks for creation, remove ones outside radius.\n */\n _recalcChunkSet(pcx, pcz) {\n const r = this.viewRadius;\n const unloadR2 = (r + 2) * (r + 2); // hysteresis buffer\n\n const pending = [];\n for (const { dx, dz, dist2 } of getRadialOffsets(r)) {\n const cx = pcx + dx;\n const cz = pcz + dz;\n const key = `${cx},${cz}`;\n if (!this.chunks.has(key)) pending.push({ cx, cz, dist2 });\n }\n this.streamScheduler.reset(pending);\n this.pendingChunkCount = pending.length;\n\n // Remove chunks outside unload radius\n let removed = 0;\n for (const [key, chunk] of this.chunks) {\n const dx = chunk.cx - pcx;\n const dz = chunk.cz - pcz;\n if (dx * dx + dz * dz > unloadR2) {\n this.chunks.delete(key);\n removed++;\n }\n }\n this.removedChunkCount = removed;\n if (removed) this._batchesDirty = true;\n }\n\n /**\n * Create a batch of pending chunks (up to maxCreatesPerFrame).\n */\n _createPending() {\n const result = this.streamScheduler.process(({ cx, cz }) => {\n const key = `${cx},${cz}`;\n if (this.chunks.has(key)) return false;\n this.chunks.set(key, {\n cx, cz,\n centerX: cx * this.chunkSize + this.chunkSize / 2,\n centerZ: cz * this.chunkSize + this.chunkSize / 2,\n lod: 3,\n morph: 0,\n fresh: true,\n visible: true,\n });\n return true;\n }, {\n budgetMs: this.chunkStreamBudgetMs,\n maxItems: this.maxCreatesPerFrame,\n });\n this.createdChunkCount = result.created;\n this.pendingChunkCount = result.pendingCount;\n this.streamTimeMs = result.elapsedMs;\n if (result.created) this._batchesDirty = true;\n }\n\n /**\n * Update LOD level per chunk based on distance from player.\n */\n _updateLOD(playerPos) {\n const [t0, t1, t2] = this._lodThresholds2;\n const counts = [0, 0, 0, 0];\n const now = performance.now();\n const dt = this._lastLodStepAt == null ? 0 : Math.min(0.1, Math.max(0, (now - this._lastLodStepAt) / 1000));\n this._lastLodStepAt = now;\n const step = dt / Math.max(0.05, this.morphDuration);\n let morphing = 0;\n\n for (const chunk of this.chunks.values()) {\n const dx = chunk.centerX - playerPos.x;\n const dy = -playerPos.y;\n const dz = chunk.centerZ - playerPos.z;\n const d2 = dx * dx + dy * dy + dz * dz;\n const lod = d2 < t0 ? 0 : d2 < t1 ? 1 : d2 < t2 ? 2 : 3;\n if (stepTemporalLod(chunk, lod, step, this.lodSegments, this.morphEnabled)) {\n this._batchesDirty = true;\n }\n if (chunk.lod !== lod || chunk.morph > 0) morphing++;\n counts[chunk.lod]++;\n }\n this.morphingChunkCount = morphing;\n\n this.lodCounts = counts;\n this.activeChunkCount = this.chunks.size;\n }\n\n /**\n * Update settings that can change while infinite mode is active.\n */\n updateSettings({ maxHeight, skirtDepth, seaLevel }) {\n if (maxHeight !== undefined) this.maxHeight = maxHeight;\n if (skirtDepth !== undefined) this.skirtDepth = skirtDepth;\n if (seaLevel !== undefined) {\n this.seaLevel = seaLevel;\n this.waterPlane.position.y = seaLevel;\n this.waterPlane.visible = seaLevel > 0.5;\n }\n\n // Update geometry bounds\n for (const geo of this.geometries) {\n setChunkBounds(geo, this.chunkSize, this.maxHeight, this.skirtDepth);\n }\n }\n\n /**\n * Show/hide the entire infinite world.\n */\n setVisible(visible) {\n this.group.visible = visible;\n this.batches.setVisible(visible);\n this.waterPlane.visible = visible && this.seaLevel > 0.5;\n }\n\n /**\n * Dispose all chunks and remove from scene.\n */\n dispose() {\n this.merge.dispose();\n this.batches.dispose();\n this.chunks.clear();\n this.streamScheduler.clear();\n this._lodRebuildQueue = [];\n\n for (const geo of this.geometries) {\n geo.dispose();\n }\n this.geometries = [];\n\n this.scene.remove(this.group);\n this.scene.remove(this.waterPlane);\n this.waterPlane.geometry.dispose();\n }\n}\n","import * as THREE from 'three';\nimport {\n COMMON_UNIFORMS_GLSL,\n NOISE_GLSL,\n buildHeightGLSL,\n} from './terrainGLSL.js';\nimport { BIOME_GLSL } from './biomeGLSL.js';\nimport { generateStackGLSL } from './noise/noiseStackCodegen.js';\nimport { defaultLegacyStack } from './noise/NoiseStack.js';\n\nconst DEFAULT_STACK_GLSL = generateStackGLSL(defaultLegacyStack());\n\nconst VERTEX = /* glsl */ `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\nconst buildFragment = (heightGLSL) => /* glsl */ `\nprecision highp float;\n${COMMON_UNIFORMS_GLSL}\n${NOISE_GLSL}\n${BIOME_GLSL}\n${heightGLSL}\n\nuniform vec2 uClipBakeOrigin;\nuniform vec2 uClipBakeSpan;\nvarying vec2 vUv;\n\nvoid main() {\n vec2 xz = uClipBakeOrigin + vUv * uClipBakeSpan;\n Climate climate = climateAt(xz * uFrequency + uSeedOffset);\n float h01 = heightAtWithClimate(xz, climate) / max(uHeightScale, 1e-3);\n gl_FragColor = vec4(h01, climate.temp, climate.moist, climate.cont);\n}\n`;\n\nconst LEVEL_COUNT = 3;\n\n/**\n * Rolling three-level terrain field cache for Infinite World.\n *\n * One level is refreshed per frame and origins are snapped to texels. Terrain\n * and water share the same uniform objects, so a completed level becomes\n * visible to both without material rebuilds or texture copies.\n */\nexport class InfiniteTerrainClipmap {\n constructor({\n renderer,\n uniforms,\n chunkSize,\n viewRadius,\n octaves,\n stackGLSL = DEFAULT_STACK_GLSL,\n resolutions = [512, 384, 256],\n requirePrepared = false,\n }) {\n this.renderer = renderer;\n this.uniforms = uniforms;\n this.chunkSize = Math.max(1, chunkSize);\n this.viewRadius = Math.max(2, viewRadius);\n this.levels = [];\n this.queue = [];\n this.generation = -1;\n this._disposed = false;\n this._requirePrepared = requirePrepared;\n\n const maxSpan = this.chunkSize * (this.viewRadius * 2 + 4);\n const spans = [\n this.chunkSize * 8,\n this.chunkSize * 24,\n Math.max(this.chunkSize * 32, maxSpan),\n ];\n for (let index = 0; index < LEVEL_COUNT; index++) {\n const resolution = Math.max(64, Math.round(resolutions[index] || 256));\n const target = new THREE.WebGLRenderTarget(resolution, resolution, {\n type: THREE.HalfFloatType,\n format: THREE.RGBAFormat,\n internalFormat: 'RGBA16F',\n minFilter: THREE.LinearFilter,\n magFilter: THREE.LinearFilter,\n depthBuffer: false,\n generateMipmaps: false,\n });\n target.texture.colorSpace = THREE.NoColorSpace;\n target.texture.name = `InfiniteTerrainFieldL${index}`;\n this.levels.push({\n index,\n resolution,\n span: spans[index],\n origin: new THREE.Vector2(),\n pendingOrigin: new THREE.Vector2(),\n ready: false,\n target,\n });\n uniforms[`uInfiniteFieldTex${index}`].value = target.texture;\n }\n\n this.scene = new THREE.Scene();\n this.camera = new THREE.Camera();\n this.material = this._makeProgramMaterial(octaves, stackGLSL);\n this._octaves = octaves;\n this._stackSig = stackGLSL.heightSig || stackGLSL.sig;\n this._programSerial = 0;\n this._programPrepared = false;\n this.mesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), this.material);\n this.mesh.frustumCulled = false;\n this.scene.add(this.mesh);\n uniforms.uUseInfiniteFieldCache.value = 1;\n this._publishReady();\n }\n\n _makeProgramMaterial(octaves, stackGLSL) {\n return new THREE.ShaderMaterial({\n uniforms: {\n ...this.uniforms,\n uClipBakeOrigin: { value: new THREE.Vector2() },\n uClipBakeSpan: { value: new THREE.Vector2(1, 1) },\n },\n defines: { OCTAVES: octaves },\n vertexShader: VERTEX,\n fragmentShader: buildFragment(buildHeightGLSL(stackGLSL.body2d)),\n depthTest: false,\n depthWrite: false,\n });\n }\n\n prepareProgram(octaves, stackGLSL = DEFAULT_STACK_GLSL) {\n if (this._disposed) return null;\n const serial = ++this._programSerial;\n const programSig = stackGLSL.heightSig || stackGLSL.sig;\n const current = this._programPrepared\n && this._octaves === octaves\n && this._stackSig === programSig;\n if (current) return { serial, current: true, octaves, stackSig: programSig, passes: [] };\n const material = this._makeProgramMaterial(octaves, stackGLSL);\n return {\n serial, current: false, material, octaves, stackSig: programSig,\n passes: [{\n scene: this.scene, camera: this.camera, mesh: this.mesh, material,\n renderTarget: this.levels[0]?.target ?? null,\n }],\n };\n }\n\n publishPrepared(handle) {\n if (!handle || this._disposed || handle.serial !== this._programSerial) return false;\n if (!handle.current) {\n const previous = this.material;\n this.material = handle.material;\n this.mesh.material = this.material;\n this._octaves = handle.octaves;\n this._stackSig = handle.stackSig;\n handle.published = true;\n previous?.dispose();\n }\n this._programPrepared = true;\n this.generation = -1;\n this.queue.length = 0;\n for (const level of this.levels) level.ready = false;\n this._publishReady();\n return true;\n }\n\n discardPrepared(handle) {\n if (handle?.material && !handle.published && handle.material !== this.material) {\n handle.material.dispose();\n }\n }\n\n setProgram(octaves, stackGLSL = DEFAULT_STACK_GLSL) {\n if (this._disposed) return false;\n const programSig = stackGLSL.heightSig || stackGLSL.sig;\n if (this._octaves === octaves && this._stackSig === programSig && this._programPrepared) return false;\n const handle = this.prepareProgram(octaves, stackGLSL);\n this.publishPrepared(handle);\n return true;\n }\n request(center, generation) {\n if (this._disposed) return;\n const generationChanged = generation !== this.generation;\n if (generationChanged) {\n this.generation = generation;\n this.queue.length = 0;\n for (const level of this.levels) level.ready = false;\n }\n\n for (const level of this.levels) {\n const texel = level.span / level.resolution;\n const snappedX = Math.floor((center.x - level.span * 0.5) / texel) * texel;\n const snappedZ = Math.floor((center.z - level.span * 0.5) / texel) * texel;\n const margin = level.span * 0.22;\n const insideStableRegion = level.ready\n && center.x >= level.origin.x + margin\n && center.x <= level.origin.x + level.span - margin\n && center.z >= level.origin.y + margin\n && center.z <= level.origin.y + level.span - margin;\n if (generationChanged || !insideStableRegion) {\n level.pendingOrigin.set(snappedX, snappedZ);\n if (!this.queue.includes(level.index)) this.queue.push(level.index);\n }\n }\n this._publishReady();\n }\n\n update(center, generation) {\n if (this._disposed || (this._requirePrepared && !this._programPrepared)) return false;\n this.request(center, generation);\n if (!this.queue.length) return false;\n const index = this.queue.shift();\n const level = this.levels[index];\n const previousTarget = this.renderer.getRenderTarget();\n const u = this.material.uniforms;\n u.uClipBakeOrigin.value.copy(level.pendingOrigin);\n u.uClipBakeSpan.value.setScalar(level.span);\n try {\n this.renderer.setRenderTarget(level.target);\n this.renderer.render(this.scene, this.camera);\n } finally {\n this.renderer.setRenderTarget(previousTarget);\n }\n level.origin.copy(level.pendingOrigin);\n level.ready = true;\n this.uniforms[`uInfiniteFieldOrigin${index}`].value.copy(level.origin);\n this.uniforms[`uInfiniteFieldSpan${index}`].value.setScalar(level.span);\n this._publishReady();\n return true;\n }\n\n _publishReady() {\n const ready = this.uniforms.uInfiniteFieldReady.value;\n ready.set(\n this.levels[0]?.ready ? 1 : 0,\n this.levels[1]?.ready ? 1 : 0,\n this.levels[2]?.ready ? 1 : 0,\n );\n }\n\n diagnostics() {\n return {\n generation: this.generation,\n pendingLevels: [...this.queue],\n levels: this.levels.map((level) => ({\n resolution: level.resolution,\n span: level.span,\n ready: level.ready,\n origin: { x: level.origin.x, z: level.origin.y },\n })),\n };\n }\n\n dispose() {\n this._disposed = true;\n this.uniforms.uUseInfiniteFieldCache.value = 0;\n this.uniforms.uInfiniteFieldReady.value.set(0, 0, 0);\n for (const level of this.levels) level.target.dispose();\n this.mesh.geometry.dispose();\n this.material.dispose();\n this.levels = [];\n this.queue = [];\n }\n}\n","import * as THREE from 'three';\nimport { FiniteTerrain } from '../FiniteTerrain.js';\nimport { InfiniteWorld } from '../../engine/terrain/InfiniteWorld.js';\nimport { InfiniteTerrainClipmap } from '../../engine/terrain/InfiniteTerrainClipmap.js';\nimport { createInfiniteTerrainMaterial } from '../../engine/terrain/TerrainMaterial.js';\nimport { createInfiniteWaterMaterial } from '../../engine/terrain/WaterMaterial.js';\nimport { compileMaterial } from '../resources/CompileMaterial.js';\nimport { withRendererState } from '../resources/RendererState.js';\n\nfunction validate(l) {\n for (const [name, min, max] of [\n ['viewRadius', 2, 32],\n ['triangleBudget', 0, 20000000],\n ['maxCreatesPerFrame', 1, 1024],\n ['streamBudgetMs', 0.1, 20],\n ['cacheResolution', 64, 1024],\n ]) {\n if (!Number.isFinite(l[name]) || l[name] < min || l[name] > max)\n throw new RangeError(`layout.${name} must be ${min}..${max}`);\n }\n for (const key of ['viewRadius', 'maxCreatesPerFrame', 'cacheResolution'])\n if (!Number.isInteger(l[key])) throw new TypeError(`layout.${key} must be an integer`);\n}\n\nexport const infiniteAdapter = {\n mode: 'infinite',\n layoutDefaults: {\n viewRadius: 8,\n triangleBudget: 1000000,\n maxCreatesPerFrame: 16,\n streamBudgetMs: 1.5,\n cacheResolution: 256,\n },\n validateLayout: validate,\n createMaterial: (t, octaves, program) =>\n createInfiniteTerrainMaterial(t._uniforms, octaves, program, {\n variant: t._surface ? 'surface' : 'base',\n }),\n createRuntime(t) {\n return {\n world: null,\n cache: null,\n key: '',\n get group() {\n return this.world.group;\n },\n update(camera) {\n this.world.update(camera.position, camera);\n this.world.waterPlane.visible = false;\n },\n diagnostics() {\n const w = this.world;\n return {\n chunks: w.chunks.size,\n visible: w.visibleChunkCount,\n culled: w.culledChunkCount,\n lodCounts: [...w.lodCounts],\n cache: this.cache.diagnostics(),\n };\n },\n dispose() {\n this.world?.dispose();\n this.cache?.dispose();\n this.waterMaterial?.dispose();\n },\n };\n },\n apply(t, c) {\n const r = t._runtime,\n l = c.layout,\n u = t._uniforms;\n const key = JSON.stringify([l.chunkSize, l.viewRadius, l.cacheResolution]);\n if (r.key !== key) {\n r.dispose();\n r.key = key;\n r.waterMaterial = createInfiniteWaterMaterial(u, c.source.octaves, t._stackGLSL);\n r.world = new InfiniteWorld(t.object, t._material, r.waterMaterial, {\n chunkSize: l.chunkSize,\n viewRadius: l.viewRadius,\n maxHeight: c.heightScale * 1.35 + 2,\n skirtDepth: Math.max(24, c.heightScale * 0.08),\n seaLevel: 0,\n lodSegments: c.quality.lodSegments,\n });\n r.world.waterPlane.visible = false;\n r.cache = new InfiniteTerrainClipmap({\n renderer: t._renderer,\n uniforms: u,\n chunkSize: l.chunkSize,\n viewRadius: l.viewRadius,\n octaves: c.source.octaves,\n stackGLSL: t._stackGLSL,\n resolutions: [l.cacheResolution, l.cacheResolution, l.cacheResolution],\n requirePrepared: true,\n });\n }\n r.world.setMaxCreatesPerFrame(l.maxCreatesPerFrame);\n r.world.setChunkStreamBudget(l.streamBudgetMs);\n r.world.setTriangleBudget(l.triangleBudget);\n r.world.setLodMultiplier(c.quality.lodDistanceScale);\n r.world.setViewRadius(l.viewRadius);\n r.world.setLodSegments(c.quality.lodSegments);\n r.world.setMorphEnabled(c.quality.morphEnabled);\n r.world.setMergeOptions({ enabled: c.quality.mergeEnabled });\n r.world.cullingEnabled = c.quality.cullingEnabled;\n r.world.updateSettings({\n maxHeight: c.heightScale * 1.35 + 2,\n skirtDepth: Math.max(24, c.heightScale * 0.08),\n seaLevel: c.seaLevel,\n });\n u.uUseInfiniteFieldCache.value = 1;\n },\n async prepare(t, camera, signal, check = () => t._assertAlive()) {\n const cache = t._runtime.cache;\n const h = cache.prepareProgram(t.configuration.source.octaves, t._stackGLSL);\n try {\n for (const p of h.passes ?? [{ material: h.material ?? cache.material }])\n await compileMaterial(t._renderer, p.material, p.camera ?? camera, {\n geometry: p.mesh?.geometry.clone(),\n });\n signal?.throwIfAborted();\n check();\n cache.publishPrepared(h);\n } catch (e) {\n cache.discardPrepared(h);\n throw e;\n }\n withRendererState(t._renderer, () => {\n for (let i = 0; i < 3; i++) cache.update(t._cameraPosition, t._revision);\n });\n },\n async sourceChanged(t, source, { signal, check, sourceChanged }) {\n if (sourceChanged)\n await this.prepare(t, t._viewCamera ?? new THREE.PerspectiveCamera(), signal, check);\n t._runtime.world.terrainMaterial = t._material;\n t._runtime.world.merge.material = t._material;\n t._runtime.world.batches.material = t._material;\n },\n update(t) {\n withRendererState(t._renderer, () => t._runtime.cache.update(t._cameraPosition, t._revision));\n },\n createProbe(t, material) {\n const geometry = t._runtime.world.batches.meshes[0].geometry.clone();\n const mesh = new THREE.InstancedMesh(geometry, material, 1);\n return { geometry, mesh };\n },\n};\n\nexport async function createInfiniteTerrain(options) {\n return new FiniteTerrain({ ...options, _world: infiniteAdapter });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InfiniteTerrain-jeCy6RED.js","sources":["../../../src/engine/terrain/ChunkStreamScheduler.js","../../../src/engine/terrain/InfiniteTerrainBatches.js","../../../src/engine/terrain/MergeQuadtree.js","../../../src/engine/terrain/InfiniteWorld.js","../../../src/engine/terrain/InfiniteTerrainClipmap.js","../../../src/runtime/worlds/InfiniteTerrain.js"],"sourcesContent":["const DEFAULT_BUDGET_MS = 1.5;\nconst DEFAULT_AUTO_MAX_ITEMS = 24;\n\nconst radialOffsetCache = new Map();\n\n/**\n * Return the integer offsets inside a circular radius, nearest first.\n * The immutable result is cached because every chunk-boundary crossing uses\n * the same pattern translated around a new player chunk.\n */\nexport function getRadialOffsets(radius) {\n const r = Math.max(0, Math.floor(Number(radius) || 0));\n let cached = radialOffsetCache.get(r);\n if (cached) return cached;\n\n const r2 = r * r;\n const offsets = [];\n for (let dz = -r; dz <= r; dz++) {\n for (let dx = -r; dx <= r; dx++) {\n const dist2 = dx * dx + dz * dz;\n if (dist2 <= r2) offsets.push(Object.freeze({ dx, dz, dist2 }));\n }\n }\n offsets.sort((a, b) => a.dist2 - b.dist2 || a.dz - b.dz || a.dx - b.dx);\n cached = Object.freeze(offsets);\n radialOffsetCache.set(r, cached);\n return cached;\n}\n\n/**\n * Small time-budgeted FIFO used by InfiniteWorld. reset() intentionally\n * replaces pending work: after a fast player move, old chunk requests are no\n * longer useful and must not delay the new nearest chunks.\n */\nexport class ChunkStreamScheduler {\n constructor({ budgetMs = DEFAULT_BUDGET_MS, autoMaxItems = DEFAULT_AUTO_MAX_ITEMS, now } = {}) {\n this.budgetMs = budgetMs;\n this.autoMaxItems = autoMaxItems;\n this._now = now || (() => performance.now());\n this._items = [];\n this._head = 0;\n }\n\n get pendingCount() {\n return Math.max(0, this._items.length - this._head);\n }\n\n reset(items = []) {\n this._items = Array.isArray(items) ? items : [...items];\n this._head = 0;\n }\n\n clear() {\n this._items = [];\n this._head = 0;\n }\n\n /**\n * Process nearest-first work until either the time or item budget is spent.\n * maxItems=0 means automatic scheduling, not unlimited work.\n */\n process(create, { budgetMs = this.budgetMs, maxItems = 0 } = {}) {\n if (typeof create !== 'function' || this.pendingCount === 0) {\n return { processed: 0, created: 0, elapsedMs: 0, pendingCount: this.pendingCount };\n }\n\n const itemLimit = maxItems > 0\n ? Math.max(1, Math.floor(maxItems))\n : this.autoMaxItems;\n const timeLimit = Number.isFinite(budgetMs) && budgetMs > 0\n ? budgetMs\n : DEFAULT_BUDGET_MS;\n const startedAt = this._now();\n let processed = 0;\n let created = 0;\n\n while (this._head < this._items.length && processed < itemLimit) {\n // Always allow the first item, then enforce the elapsed-time budget.\n if (processed > 0 && this._now() - startedAt >= timeLimit) break;\n const item = this._items[this._head++];\n processed++;\n if (create(item) !== false) created++;\n }\n\n if (this._head >= this._items.length) this.clear();\n return {\n processed,\n created,\n elapsedMs: this._now() - startedAt,\n pendingCount: this.pendingCount,\n };\n }\n}\n\nexport const CHUNK_STREAM_DEFAULTS = Object.freeze({\n budgetMs: DEFAULT_BUDGET_MS,\n autoMaxItems: DEFAULT_AUTO_MAX_ITEMS,\n});\n","import * as THREE from 'three';\n\nconst LOD_COUNT = 4;\n\n/**\n * Render logical Infinite World chunks through one InstancedMesh per LOD.\n * Streaming creates lightweight records only; scene-graph objects and terrain\n * draw calls stay constant as the player moves.\n */\nexport class InfiniteTerrainBatches {\n constructor({ group, material, geometries, capacity }) {\n this.group = group;\n this.material = material;\n this.geometries = geometries;\n this.capacity = Math.max(1, Math.ceil(capacity));\n this.meshes = [];\n this.counts = [0, 0, 0, 0];\n this._matrix = new THREE.Matrix4();\n this._createMeshes();\n }\n\n // Per-instance temporal geomorph factor (see LodMorph.stepTemporalLod).\n // The LOD geometries are owned by this batch set, so the instanced\n // attribute lives directly on them.\n _attachMorphAttribute(geometry) {\n const current = geometry.getAttribute('aMorphK');\n if (current && current.count >= this.capacity) return current;\n const attribute = new THREE.InstancedBufferAttribute(new Float32Array(this.capacity), 1);\n attribute.setUsage(THREE.DynamicDrawUsage);\n geometry.setAttribute('aMorphK', attribute);\n return attribute;\n }\n\n _createMeshes() {\n this.meshes = this.geometries.map((geometry, lod) => {\n this._attachMorphAttribute(geometry);\n const mesh = new THREE.InstancedMesh(geometry, this.material, this.capacity);\n mesh.name = `infinite-terrain-lod-${lod}`;\n mesh.count = 0;\n mesh.frustumCulled = false;\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage);\n this.group.add(mesh);\n return mesh;\n });\n }\n\n ensureCapacity(capacity) {\n const required = Math.max(1, Math.ceil(capacity));\n if (required <= this.capacity) return false;\n\n for (const mesh of this.meshes) this.group.remove(mesh);\n this.capacity = required;\n this._createMeshes();\n return true;\n }\n\n updateGeometry(lod, geometry) {\n this._attachMorphAttribute(geometry);\n this.geometries[lod] = geometry;\n this.meshes[lod].geometry = geometry;\n }\n\n /**\n * Compact visible records into their LOD batch. Matrices are uploaded only\n * when InfiniteWorld reports a topology, visibility or LOD change.\n */\n commit(chunks, chunkSize) {\n const counts = [0, 0, 0, 0];\n for (const chunk of chunks) {\n if (chunk.visible === false) continue;\n const lod = Math.min(LOD_COUNT - 1, Math.max(0, chunk.lod | 0));\n const slot = counts[lod]++;\n if (slot >= this.capacity) {\n throw new RangeError(`Infinite terrain batch ${lod} exceeded capacity ${this.capacity}`);\n }\n this._matrix.makeScale(chunkSize, chunkSize, chunkSize);\n this._matrix.setPosition(chunk.cx * chunkSize, 0, chunk.cz * chunkSize);\n this.meshes[lod].setMatrixAt(slot, this._matrix);\n const morph = this.meshes[lod].geometry.getAttribute('aMorphK');\n if (morph) morph.array[slot] = chunk.morph || 0;\n }\n\n for (let lod = 0; lod < LOD_COUNT; lod++) {\n const mesh = this.meshes[lod];\n mesh.count = counts[lod];\n if (counts[lod] > 0 || this.counts[lod] > 0) {\n mesh.instanceMatrix.needsUpdate = true;\n const morph = mesh.geometry.getAttribute('aMorphK');\n if (morph) morph.needsUpdate = true;\n }\n }\n this.counts = counts;\n return counts;\n }\n\n setVisible(visible) {\n for (const mesh of this.meshes) mesh.visible = visible;\n }\n\n dispose() {\n for (const mesh of this.meshes) this.group.remove(mesh);\n this.meshes = [];\n this.counts = [0, 0, 0, 0];\n }\n}\n","import * as THREE from 'three';\nimport { buildChunkGeometry } from './ChunkGeometry.js';\n\n// ============================================================================\n// MergeQuadtree: shared chunked-LOD merge layer for the FLAT GPU-displaced\n// terrain modes (Tile board + Infinite world). The host's chunks are the\n// leaves of a quadtree on their integer grid; each internal node covers a\n// power-of-two square block and folds into ONE flat unit-grid mesh (same\n// material) once the camera is far enough for its size. Folding happens 2x2 at\n// a time, so the visible set is a smooth cut — fine chunks near the camera,\n// progressively larger merged blocks outward — never a hard jump.\n//\n// A node only folds when it is FULL (its whole square is tiled by existing\n// chunks); partial nodes (streaming edge / assembly boundary) never fold, so a\n// merged mesh can't paint terrain across a gap. Height is GPU-driven, so a\n// merged node is just a bigger unit grid — no baking/cache/async. The win is\n// fewer draw calls / matrix updates / frustum checks (CPU), not GPU triangles.\n//\n// The host owns the chunk objects; the tree only reads { mesh, center } and\n// writes { merged, mesh.visible, ix, iz, node }. After update() the host culls:\n// skip chunks where `merged`, and cull the meshes in `mergedNodes`.\n// ============================================================================\n\nexport class MergeQuadtree {\n constructor(group, material) {\n this.group = group;\n this.material = material;\n\n this.enabled = true;\n this.quadsPerChunk = 8; // merged grid density per chunk span (8 == LOD3)\n this.mergeDistance = 4; // a node folds when nearest > spanWorld × this\n this.allowRoot = true; // allow the whole region to fold to one mesh\n this.distanceScale = 1; // mirrors the host's LOD distance scale\n this.chunkSize = 1;\n\n this._geo = new Map(); // \"res:aLod\" -> shared BufferGeometry\n this._root = null;\n this._dirty = true;\n this._gridOriginX = 0;\n this._gridOriginZ = 0;\n\n this.mergedNodes = []; // nodes folded this frame (host culls these)\n this.hiddenCount = 0; // chunks hidden by folds (for stats)\n }\n\n setChunkSize(cs) {\n if (cs !== this.chunkSize) { this.chunkSize = cs; this._dirty = true; this._disposeNodeMeshes(); }\n }\n\n setOptions({ enabled, quadsPerChunk, mergeDistance, allowRoot, distanceScale } = {}) {\n if (enabled !== undefined) this.enabled = !!enabled;\n if (allowRoot !== undefined) this.allowRoot = !!allowRoot;\n if (distanceScale !== undefined && Number.isFinite(+distanceScale)) this.distanceScale = +distanceScale;\n if (mergeDistance !== undefined && Number.isFinite(+mergeDistance)) this.mergeDistance = Math.max(0.5, +mergeDistance);\n if (quadsPerChunk !== undefined) {\n const v = Math.max(2, Math.round(quadsPerChunk));\n if (v !== this.quadsPerChunk) { this.quadsPerChunk = v; this._disposeNodeMeshes(); }\n }\n }\n\n markDirty() { this._dirty = true; }\n\n // Walk the tree and fold/unfold nodes for the current camera. `chunks` is any\n // iterable of the host's chunk objects ({ mesh, center, merged }).\n update(chunks, camPos) {\n if (!this.enabled) { this._restore(chunks); return; }\n if (this._dirty) this._rebuild(chunks);\n\n this.mergedNodes.length = 0;\n this.hiddenCount = 0;\n if (this._root) this._visit(this._root, camPos);\n }\n\n // --- tree build ----------------------------------------------------------\n _rebuild(chunks) {\n this._dirty = false;\n this._disposeNodeMeshes();\n const list = Array.isArray(chunks) ? chunks : [...chunks];\n if (!list.length) { this._root = null; return; }\n\n const cs = this.chunkSize;\n let minX = Infinity, minZ = Infinity;\n for (const c of list) {\n const x0 = c.center.x - cs / 2, z0 = c.center.z - cs / 2;\n if (x0 < minX) minX = x0;\n if (z0 < minZ) minZ = z0;\n }\n this._gridOriginX = minX;\n this._gridOriginZ = minZ;\n\n let gw = 0, gh = 0;\n for (const c of list) {\n c.ix = Math.round((c.center.x - cs / 2 - minX) / cs);\n c.iz = Math.round((c.center.z - cs / 2 - minZ) / cs);\n if (c.ix + 1 > gw) gw = c.ix + 1;\n if (c.iz + 1 > gh) gh = c.iz + 1;\n c.node = null;\n c.merged = false;\n c.mesh.visible = true;\n }\n\n let size = 1;\n while (size < Math.max(gw, gh, 1)) size *= 2;\n this._root = this._buildNode(list, 0, 0, size, 0);\n }\n\n _buildNode(chunks, x0, z0, size, level) {\n if (!chunks.length) return null;\n if (size === 1) return this._leafNode(chunks[0], x0, z0, level);\n\n const half = size / 2;\n const midX = x0 + half, midZ = z0 + half;\n const q = [[], [], [], []];\n for (const c of chunks) {\n const qx = c.ix < midX ? 0 : 1;\n const qz = c.iz < midZ ? 0 : 1;\n q[qz * 2 + qx].push(c);\n }\n const offs = [[x0, z0], [midX, z0], [x0, midZ], [midX, midZ]];\n const children = [];\n for (let i = 0; i < 4; i++) {\n if (!q[i].length) continue;\n const child = this._buildNode(q[i], offs[i][0], offs[i][1], half, level + 1);\n if (child) children.push(child);\n }\n const full = chunks.length === size * size;\n if (!full && children.length === 1) return children[0];\n return this._internalNode(children, chunks, x0, z0, size, level, full);\n }\n\n _leafNode(chunk, x0, z0, level) {\n const cs = this.chunkSize;\n const minX = this._gridOriginX + x0 * cs, minZ = this._gridOriginZ + z0 * cs;\n const node = {\n leaf: true, chunk, children: null, chunks: [chunk], full: true,\n minX, minZ, spanX: cs, spanZ: cs, spanWorld: cs, spanChunks: 1,\n center: new THREE.Vector3(minX + cs / 2, 0, minZ + cs / 2),\n half: cs * 0.7072, level, mesh: null, merged: false,\n };\n chunk.node = node;\n return node;\n }\n\n _internalNode(children, chunks, x0, z0, size, level, full) {\n const cs = this.chunkSize;\n const minX = this._gridOriginX + x0 * cs, minZ = this._gridOriginZ + z0 * cs;\n const span = size * cs;\n return {\n leaf: false, chunk: null, children, chunks, full,\n minX, minZ, spanX: span, spanZ: span, spanWorld: span, spanChunks: size,\n center: new THREE.Vector3(minX + span / 2, 0, minZ + span / 2),\n half: 0.5 * Math.SQRT2 * span, level, mesh: null, merged: false,\n };\n }\n\n // --- traversal -----------------------------------------------------------\n _visit(node, camPos) {\n if (node.leaf) {\n if (node.chunk.merged) { node.chunk.merged = false; node.chunk.mesh.visible = true; }\n return;\n }\n const canFold = node.full && (this.allowRoot || node.level > 0);\n if (canFold) {\n const nearest = Math.hypot(node.center.x - camPos.x, camPos.y, node.center.z - camPos.z) - node.half;\n const foldDist = node.spanWorld * this.mergeDistance * this.distanceScale;\n const want = node.merged ? nearest > foldDist * 0.85 : nearest > foldDist;\n if (want) {\n if (!node.merged) this._fold(node);\n this.mergedNodes.push(node);\n this.hiddenCount += node.chunks.length;\n return;\n }\n }\n if (node.merged) this._unfold(node);\n for (const child of node.children) this._visit(child, camPos);\n }\n\n _fold(node) {\n node.merged = true;\n if (!node.mesh) {\n const tier = Math.max(1, Math.round(Math.log2(node.spanChunks)));\n const res = Math.min(160, Math.max(8, node.spanChunks * this.quadsPerChunk));\n const aLod = 3 + Math.min(5, tier);\n const mesh = new THREE.Mesh(this._geometry(res, aLod), this.material);\n mesh.position.set(node.minX, 0, node.minZ);\n mesh.scale.set(node.spanX, 1, node.spanZ);\n mesh.matrixAutoUpdate = false;\n mesh.frustumCulled = false;\n mesh.updateMatrix();\n mesh.updateMatrixWorld(true);\n this.group.add(mesh);\n node.mesh = mesh;\n }\n node.mesh.visible = true;\n for (const c of node.chunks) { c.merged = true; c.mesh.visible = false; }\n this._forEachDescendantInternal(node, (d) => {\n d.merged = false;\n if (d.mesh) d.mesh.visible = false;\n });\n }\n\n _unfold(node) {\n node.merged = false;\n if (node.mesh) node.mesh.visible = false;\n }\n\n _geometry(res, aLod) {\n const key = `${res}:${aLod}`;\n let geo = this._geo.get(key);\n if (!geo) {\n geo = buildChunkGeometry(res, aLod);\n this._geo.set(key, geo);\n }\n return geo;\n }\n\n _forEachDescendantInternal(node, fn) {\n if (!node.children) return;\n for (const child of node.children) {\n if (child.leaf) continue;\n fn(child);\n this._forEachDescendantInternal(child, fn);\n }\n }\n\n _forEachInternal(fn) {\n const rec = (n) => {\n if (!n || n.leaf) return;\n fn(n);\n for (const c of n.children) rec(c);\n };\n rec(this._root);\n }\n\n _restore(chunks) {\n for (const c of chunks.values ? chunks.values() : chunks) {\n if (c.merged) { c.merged = false; c.mesh.visible = true; }\n }\n this._forEachInternal((n) => { n.merged = false; if (n.mesh) n.mesh.visible = false; });\n this.mergedNodes.length = 0;\n this.hiddenCount = 0;\n }\n\n _disposeNodeMeshes() {\n this._forEachInternal((n) => {\n if (n.mesh) { this.group.remove(n.mesh); n.mesh = null; }\n n.merged = false;\n });\n this.mergedNodes.length = 0;\n }\n\n dispose() {\n this._disposeNodeMeshes();\n for (const geo of this._geo.values()) geo.dispose();\n this._geo.clear();\n this._root = null;\n this._dirty = true;\n this.mergedNodes.length = 0;\n this.hiddenCount = 0;\n }\n}\n","import * as THREE from 'three';\nimport { buildChunkGeometry, setChunkBounds } from './ChunkGeometry.js';\nimport { publishMorphUniforms, stepTemporalLod } from './LodMorph.js';\nimport { createCullingContext, cullChunks } from './InfiniteTerrainCulling.js';\nimport { ChunkStreamScheduler, getRadialOffsets } from './ChunkStreamScheduler.js';\nimport { InfiniteTerrainBatches } from './InfiniteTerrainBatches.js';\nimport { MergeQuadtree } from './MergeQuadtree.js';\n\n// ============================================================================\n// InfiniteWorld: streams terrain chunks around the player camera.\n// Chunks are lightweight logical records on an integer grid (cx, cz). Visible\n// records are compacted into four InstancedMesh batches, one per LOD, keeping\n// terrain draw calls and scene-graph objects constant while the player moves.\n// ============================================================================\n\nconst LOD_RESOLUTIONS = [64, 32, 16, 8];\nconst DEFAULT_LOD_DISTANCES = [4, 8, 14]; // × chunkSize\nconst DEFAULT_MAX_CREATES = 0;\n\nexport class InfiniteWorld {\n /**\n * @param {THREE.Scene} scene\n * @param {THREE.Material} terrainMaterial — infinite-mode terrain material\n * @param {THREE.Material} waterMaterial — infinite-mode water material\n * @param {Object} opts\n * @param {number} opts.chunkSize — world units per chunk side\n * @param {number} opts.viewRadius — how many chunks outward to load\n * @param {number} opts.maxHeight — vertical ceiling for bounding boxes\n * @param {number} opts.skirtDepth — skirt depth for geometry bounds\n * @param {number} opts.seaLevel — water plane height\n * @param {number[]} [opts.lodSegments] — per-LOD quads per chunk side\n * @param {number[]} [opts.lodDistances] — LOD thresholds (× chunkSize)\n * @param {number} [opts.waterDistance] — water extent as fraction of terrain\n */\n constructor(scene, terrainMaterial, waterMaterial, opts) {\n this.scene = scene;\n this.terrainMaterial = terrainMaterial;\n this.waterMaterial = waterMaterial;\n\n this.chunkSize = opts.chunkSize;\n this.viewRadius = opts.viewRadius || 12;\n this.maxHeight = opts.maxHeight;\n this.skirtDepth = opts.skirtDepth;\n this.seaLevel = opts.seaLevel ?? 42;\n this.maxCreatesPerFrame = DEFAULT_MAX_CREATES;\n this.chunkStreamBudgetMs = 1.5;\n this.lodSegments = opts.lodSegments ? [...opts.lodSegments] : [...LOD_RESOLUTIONS];\n\n // Culling options\n this.cullingEnabled = true;\n this.behindCameraCulling = true;\n this.cullingAggressiveness = 1.0;\n\n // Triangle budget: when the rendered triangle count exceeds the budget,\n // LOD thresholds are scaled down progressively (no geometry rebuild)\n // until the scene fits; they recover when there is headroom.\n this.triangleBudget = 0; // 0 = unlimited\n this._budgetScale = 1.0;\n this._lastTriangles = 0;\n this._budgetCheckAt = 0;\n\n // Gradual LOD geometry rebuild queue (one LOD level per frame)\n this._lodRebuildQueue = [];\n this._targetSegments = null;\n\n // Water render distance as a fraction of the terrain render distance\n this._waterDistanceFactor = opts.waterDistance ?? 1.0;\n\n // group contains all terrain chunks\n this.group = new THREE.Group();\n this.group.name = 'infinite-world';\n this.scene.add(this.group);\n\n // water plane — follows player, sized to match terrain radius\n this.waterPlane = new THREE.Mesh(\n new THREE.PlaneGeometry(1, 1),\n this.waterMaterial\n );\n this.waterPlane.geometry.rotateX(-Math.PI / 2);\n this.waterPlane.renderOrder = 10;\n this.waterPlane.frustumCulled = false;\n this.waterPlane.position.y = this.seaLevel;\n this._updateWaterSize();\n this.scene.add(this.waterPlane);\n\n // shared geometries per LOD\n this.geometries = this.lodSegments.map((res, lodIndex) => {\n const geo = buildChunkGeometry(res, lodIndex, { morph: true });\n setChunkBounds(geo, this.chunkSize, this.maxHeight, this.skirtDepth);\n return geo;\n });\n\n // LOD distance thresholds (scale with chunk size and quality)\n this._baseLodThresholds = opts.lodDistances\n ? [...opts.lodDistances]\n : [...DEFAULT_LOD_DISTANCES]; // multiplied by chunkSize\n this._lodMultiplier = 1.0;\n this.lodThresholds = this._baseLodThresholds.map(m => m * this.chunkSize);\n this._lodThresholds2 = this.lodThresholds.map(t => t * t);\n // Temporal geomorphing (smooth LOD transitions) — see LodMorph.js\n this.morphEnabled = true;\n this.morphDuration = 0.4;\n this.morphingChunkCount = 0;\n this._lastLodStepAt = null;\n\n // chunk map: \"cx,cz\" -> { cx, cz, centerX, centerZ, lod, visible }\n this.chunks = new Map();\n\n // player chunk tracking\n this._lastPlayerCX = Infinity;\n this._lastPlayerCZ = Infinity;\n\n // Time-budgeted nearest-first chunk streaming queue.\n this.streamScheduler = new ChunkStreamScheduler({\n budgetMs: this.chunkStreamBudgetMs,\n });\n\n // Instancing already solves the draw-call problem that MergeQuadtree was\n // built for. Keep the public merge object for settings/diagnostics, but do\n // not build or visit its tree on the instanced path.\n this.merge = new MergeQuadtree(this.group, this.terrainMaterial);\n this.merge.setChunkSize(this.chunkSize);\n this.merge.setOptions({ enabled: false });\n this.mergedGroupCount = 0;\n this.savedDrawCalls = 0;\n\n this.batches = new InfiniteTerrainBatches({\n group: this.group,\n material: this.terrainMaterial,\n geometries: this.geometries,\n capacity: getRadialOffsets(this.viewRadius + 2).length,\n });\n this._batchesDirty = true;\n this._cullingContext = {};\n\n // stats\n this.activeChunkCount = 0;\n this.visibleChunkCount = 0;\n this.culledChunkCount = 0;\n this.lodCounts = [0, 0, 0, 0];\n this.pendingChunkCount = 0;\n this.createdChunkCount = 0;\n this.removedChunkCount = 0;\n this.streamTimeMs = 0;\n this.terrainDrawCallCount = 0;\n }\n\n /** Tune the merge layer (performance settings). */\n setMergeOptions(opts) {\n // Merge meshes and instanced batches solve the same draw-call problem.\n // Building both would add traversal/rebuild cost without reducing draws.\n this.merge.setOptions({ ...opts, enabled: false });\n }\n\n /** Toggle the merge-debug surface tint (drives the shared uMergeDebug). */\n setMergeDebug(on) {\n const u = this.terrainMaterial?.uniforms?.uMergeDebug;\n if (u) u.value = on ? 1.0 : 0.0;\n }\n\n /**\n * Update water plane size to match terrain render distance.\n * Water extends exactly to the terrain edge (viewRadius * 2 + 1 chunks)\n * so it never renders beyond where terrain exists.\n */\n _updateWaterSize() {\n const waterSize = this.chunkSize * (this.viewRadius * 2 + 1) * this._waterDistanceFactor;\n this.waterPlane.scale.set(waterSize, 1, waterSize);\n\n // Update water fade distance uniforms (if available)\n if (this.waterMaterial.uniforms.uWaterFadeStart) {\n const fadeStart = waterSize * 0.42;\n const fadeEnd = waterSize * 0.50;\n this.waterMaterial.uniforms.uWaterFadeStart.value = fadeStart;\n this.waterMaterial.uniforms.uWaterFadeEnd.value = fadeEnd;\n }\n }\n\n /**\n * Change the view radius at runtime (e.g. quality preset change).\n * Recalculates chunk set, water size, and LOD thresholds without\n * rebuilding chunk geometry.\n */\n setViewRadius(r) {\n if (r === this.viewRadius) return;\n this.viewRadius = r;\n this._recalcLodThresholds();\n this._updateWaterSize();\n if (this.batches.ensureCapacity(getRadialOffsets(this.viewRadius + 2).length)) {\n this._batchesDirty = true;\n }\n // Force recalc on next update\n this._lastPlayerCX = Infinity;\n this._lastPlayerCZ = Infinity;\n }\n\n /**\n * Change the LOD distance multiplier (quality preset).\n * Lower = chunks drop to low-detail sooner (better perf).\n * Higher = chunks keep high-detail further out (better visuals).\n */\n setLodMultiplier(m) {\n this._lodMultiplier = m;\n this._recalcLodThresholds();\n }\n\n /**\n * Change the base LOD distance thresholds (in chunk-size units).\n */\n setLodDistances(distances) {\n this._baseLodThresholds = [...distances];\n this._recalcLodThresholds();\n }\n\n /** Recompute LOD thresholds from base × chunkSize × multiplier × budget. */\n _recalcLodThresholds() {\n this.lodThresholds = this._baseLodThresholds.map(\n m => m * this.chunkSize * this._lodMultiplier * this._budgetScale\n );\n this._lodThresholds2 = this.lodThresholds.map(t => t * t);\n }\n\n setMorphEnabled(enabled) {\n this.morphEnabled = !!enabled;\n }\n\n /**\n * Change max chunk creates per frame. 0 selects the automatic time-budgeted\n * scheduler; it no longer means unbounded work in one frame.\n */\n setMaxCreatesPerFrame(n) {\n const v = Number(n);\n if (!Number.isFinite(v)) {\n this.maxCreatesPerFrame = DEFAULT_MAX_CREATES;\n } else if (v <= 0) {\n this.maxCreatesPerFrame = DEFAULT_MAX_CREATES;\n } else {\n this.maxCreatesPerFrame = Math.max(1, Math.round(v));\n }\n }\n\n setChunkStreamBudget(ms) {\n const value = Number(ms);\n if (!Number.isFinite(value) || value <= 0) return;\n this.chunkStreamBudgetMs = Math.min(8, Math.max(0.25, value));\n this.streamScheduler.budgetMs = this.chunkStreamBudgetMs;\n }\n\n /**\n * Change per-LOD segment counts. Geometry is rebuilt GRADUALLY — one LOD\n * level per frame in update() — so the app never freezes, and chunks keep\n * their old shared geometry until the replacement is ready.\n */\n setLodSegments(segments) {\n const same = segments.length === this.lodSegments.length\n && segments.every((s, i) => s === this.lodSegments[i])\n && !this._lodRebuildQueue.length;\n if (same) return;\n this._targetSegments = [...segments];\n // Rebuild cheap (far) LODs first so streaming chunks pick them up early\n this._lodRebuildQueue = [3, 2, 1, 0];\n }\n\n /** Build one queued LOD geometry and swap it on the chunks using it. */\n _processLodRebuild() {\n if (!this._lodRebuildQueue.length || !this._targetSegments) return;\n const lod = this._lodRebuildQueue.shift();\n const res = this._targetSegments[lod];\n if (res === this.lodSegments[lod]) return; // this level is unchanged\n\n const geo = buildChunkGeometry(res, lod, { morph: true });\n setChunkBounds(geo, this.chunkSize, this.maxHeight, this.skirtDepth);\n const old = this.geometries[lod];\n this.geometries[lod] = geo;\n this.lodSegments[lod] = res;\n\n this.batches.updateGeometry(lod, geo);\n this._batchesDirty = true;\n old.dispose();\n }\n\n /**\n * Set the maximum triangle budget (0 = unlimited). Enforced by scaling\n * LOD thresholds down — cheap LOD swaps only, never a rebuild.\n */\n setTriangleBudget(n) {\n this.triangleBudget = n;\n if (!n) {\n this._budgetScale = 1.0;\n this._recalcLodThresholds();\n }\n }\n\n /**\n * Feed the renderer's triangle count (called from Engine after render).\n * Adjusts the budget scale at most twice per second.\n */\n notifyTriangles(triangles) {\n this._lastTriangles = triangles;\n if (!this.triangleBudget) return;\n const now = performance.now();\n if (now - this._budgetCheckAt < 500) return;\n this._budgetCheckAt = now;\n\n if (triangles > this.triangleBudget && this._budgetScale > 0.35) {\n this._budgetScale = Math.max(0.35, this._budgetScale * 0.9);\n this._recalcLodThresholds();\n } else if (triangles < this.triangleBudget * 0.7 && this._budgetScale < 1.0) {\n this._budgetScale = Math.min(1.0, this._budgetScale * 1.05);\n this._recalcLodThresholds();\n }\n }\n\n /**\n * Set water render distance as a fraction (0.25–1) of terrain distance.\n * Only affects the water plane — terrain is untouched.\n */\n setWaterDistanceFactor(f) {\n const clamped = Math.min(1, Math.max(0.25, f));\n if (clamped === this._waterDistanceFactor) return;\n this._waterDistanceFactor = clamped;\n this._updateWaterSize();\n }\n\n /**\n * Called each frame from Engine._tick(). Determines which chunks should\n * exist, creates missing ones (throttled), removes distant ones, updates\n * LOD, and culls invisible chunks.\n */\n update(playerPos, camera) {\n const cs = this.chunkSize;\n const pcx = Math.floor(playerPos.x / cs);\n const pcz = Math.floor(playerPos.z / cs);\n\n // Move water plane to follow player (keeps precision reasonable)\n this.waterPlane.position.x = pcx * cs;\n this.waterPlane.position.z = pcz * cs;\n\n // If player crossed a chunk boundary, recalculate desired set\n if (pcx !== this._lastPlayerCX || pcz !== this._lastPlayerCZ) {\n this._lastPlayerCX = pcx;\n this._lastPlayerCZ = pcz;\n this._recalcChunkSet(pcx, pcz);\n }\n\n // Create pending chunks (throttled)\n this._createPending();\n\n // Process at most one gradual LOD geometry rebuild per frame\n this._processLodRebuild();\n\n // Select logical LODs, then cull and compact only visible records into the\n // four persistent GPU batches. Morph bands follow the (budget-scaled)\n // thresholds every frame.\n this._updateLOD(playerPos);\n // Instanced chunks morph temporally (per-instance factor); the distance\n // bands are a Tile-board feature, so only the grid ladder is published.\n publishMorphUniforms(this.terrainMaterial?.uniforms, null, this.lodSegments, false);\n const segs = this.terrainMaterial?.uniforms?.uLodGridSegments;\n if (segs) segs.value.set(this.lodSegments[0], this.lodSegments[1], this.lodSegments[2], this.lodSegments[3]);\n if (camera) this._cull(camera);\n if (this._batchesDirty) {\n const batchCounts = this.batches.commit(this.chunks.values(), this.chunkSize);\n this.terrainDrawCallCount = batchCounts.reduce(\n (total, count) => total + (count > 0 ? 1 : 0),\n 0\n );\n this._batchesDirty = false;\n }\n }\n\n /** Frustum + behind-camera cull for active chunks and folded node meshes. */\n _cull(camera) {\n if (!this.cullingEnabled) {\n let visibleCount = 0;\n for (const chunk of this.chunks.values()) {\n if (chunk.visible === false) {\n chunk.visible = true;\n this._batchesDirty = true;\n }\n visibleCount++;\n }\n this.visibleChunkCount = visibleCount;\n this.culledChunkCount = 0;\n return;\n }\n\n camera.updateMatrixWorld(true);\n createCullingContext(\n camera,\n this.chunkSize,\n this.behindCameraCulling,\n this.cullingAggressiveness,\n this._cullingContext,\n -this.skirtDepth\n );\n const chunkResult = cullChunks(\n this.chunks, camera, this.chunkSize,\n this.maxHeight, this.behindCameraCulling, this.cullingAggressiveness,\n this._cullingContext\n );\n if (chunkResult.changedCount) this._batchesDirty = true;\n this.visibleChunkCount = chunkResult.visibleCount;\n this.culledChunkCount = chunkResult.culledCount;\n }\n\n /**\n * Recalculate which chunks should exist around the player chunk.\n * Queue missing chunks for creation, remove ones outside radius.\n */\n _recalcChunkSet(pcx, pcz) {\n const r = this.viewRadius;\n const unloadR2 = (r + 2) * (r + 2); // hysteresis buffer\n\n const pending = [];\n for (const { dx, dz, dist2 } of getRadialOffsets(r)) {\n const cx = pcx + dx;\n const cz = pcz + dz;\n const key = `${cx},${cz}`;\n if (!this.chunks.has(key)) pending.push({ cx, cz, dist2 });\n }\n this.streamScheduler.reset(pending);\n this.pendingChunkCount = pending.length;\n\n // Remove chunks outside unload radius\n let removed = 0;\n for (const [key, chunk] of this.chunks) {\n const dx = chunk.cx - pcx;\n const dz = chunk.cz - pcz;\n if (dx * dx + dz * dz > unloadR2) {\n this.chunks.delete(key);\n removed++;\n }\n }\n this.removedChunkCount = removed;\n if (removed) this._batchesDirty = true;\n }\n\n /**\n * Create a batch of pending chunks (up to maxCreatesPerFrame).\n */\n _createPending() {\n const result = this.streamScheduler.process(({ cx, cz }) => {\n const key = `${cx},${cz}`;\n if (this.chunks.has(key)) return false;\n this.chunks.set(key, {\n cx, cz,\n centerX: cx * this.chunkSize + this.chunkSize / 2,\n centerZ: cz * this.chunkSize + this.chunkSize / 2,\n lod: 3,\n morph: 0,\n fresh: true,\n visible: true,\n });\n return true;\n }, {\n budgetMs: this.chunkStreamBudgetMs,\n maxItems: this.maxCreatesPerFrame,\n });\n this.createdChunkCount = result.created;\n this.pendingChunkCount = result.pendingCount;\n this.streamTimeMs = result.elapsedMs;\n if (result.created) this._batchesDirty = true;\n }\n\n /**\n * Update LOD level per chunk based on distance from player.\n */\n _updateLOD(playerPos) {\n const [t0, t1, t2] = this._lodThresholds2;\n const counts = [0, 0, 0, 0];\n const now = performance.now();\n const dt = this._lastLodStepAt == null ? 0 : Math.min(0.1, Math.max(0, (now - this._lastLodStepAt) / 1000));\n this._lastLodStepAt = now;\n const step = dt / Math.max(0.05, this.morphDuration);\n let morphing = 0;\n\n for (const chunk of this.chunks.values()) {\n const dx = chunk.centerX - playerPos.x;\n const dy = -playerPos.y;\n const dz = chunk.centerZ - playerPos.z;\n const d2 = dx * dx + dy * dy + dz * dz;\n const lod = d2 < t0 ? 0 : d2 < t1 ? 1 : d2 < t2 ? 2 : 3;\n if (stepTemporalLod(chunk, lod, step, this.lodSegments, this.morphEnabled)) {\n this._batchesDirty = true;\n }\n if (chunk.lod !== lod || chunk.morph > 0) morphing++;\n counts[chunk.lod]++;\n }\n this.morphingChunkCount = morphing;\n\n this.lodCounts = counts;\n this.activeChunkCount = this.chunks.size;\n }\n\n /**\n * Update settings that can change while infinite mode is active.\n */\n updateSettings({ maxHeight, skirtDepth, seaLevel }) {\n if (maxHeight !== undefined) this.maxHeight = maxHeight;\n if (skirtDepth !== undefined) this.skirtDepth = skirtDepth;\n if (seaLevel !== undefined) {\n this.seaLevel = seaLevel;\n this.waterPlane.position.y = seaLevel;\n this.waterPlane.visible = seaLevel > 0.5;\n }\n\n // Update geometry bounds\n for (const geo of this.geometries) {\n setChunkBounds(geo, this.chunkSize, this.maxHeight, this.skirtDepth);\n }\n }\n\n /**\n * Show/hide the entire infinite world.\n */\n setVisible(visible) {\n this.group.visible = visible;\n this.batches.setVisible(visible);\n this.waterPlane.visible = visible && this.seaLevel > 0.5;\n }\n\n /**\n * Dispose all chunks and remove from scene.\n */\n dispose() {\n this.merge.dispose();\n this.batches.dispose();\n this.chunks.clear();\n this.streamScheduler.clear();\n this._lodRebuildQueue = [];\n\n for (const geo of this.geometries) {\n geo.dispose();\n }\n this.geometries = [];\n\n this.scene.remove(this.group);\n this.scene.remove(this.waterPlane);\n this.waterPlane.geometry.dispose();\n }\n}\n","import * as THREE from 'three';\nimport {\n COMMON_UNIFORMS_GLSL,\n NOISE_GLSL,\n buildHeightGLSL,\n} from './terrainGLSL.js';\nimport { BIOME_GLSL } from './biomeGLSL.js';\nimport { generateStackGLSL } from './noise/noiseStackCodegen.js';\nimport { defaultLegacyStack } from './noise/NoiseStack.js';\n\nconst DEFAULT_STACK_GLSL = generateStackGLSL(defaultLegacyStack());\n\nconst VERTEX = /* glsl */ `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\nconst buildFragment = (heightGLSL) => /* glsl */ `\nprecision highp float;\n${COMMON_UNIFORMS_GLSL}\n${NOISE_GLSL}\n${BIOME_GLSL}\n${heightGLSL}\n\nuniform vec2 uClipBakeOrigin;\nuniform vec2 uClipBakeSpan;\nvarying vec2 vUv;\n\nvoid main() {\n vec2 xz = uClipBakeOrigin + vUv * uClipBakeSpan;\n Climate climate = climateAt(xz * uFrequency + uSeedOffset);\n float h01 = heightAtWithClimate(xz, climate) / max(uHeightScale, 1e-3);\n gl_FragColor = vec4(h01, climate.temp, climate.moist, climate.cont);\n}\n`;\n\nconst LEVEL_COUNT = 3;\n\n/**\n * Rolling three-level terrain field cache for Infinite World.\n *\n * One level is refreshed per frame and origins are snapped to texels. Terrain\n * and water share the same uniform objects, so a completed level becomes\n * visible to both without material rebuilds or texture copies.\n */\nexport class InfiniteTerrainClipmap {\n constructor({\n renderer,\n uniforms,\n chunkSize,\n viewRadius,\n octaves,\n stackGLSL = DEFAULT_STACK_GLSL,\n resolutions = [512, 384, 256],\n requirePrepared = false,\n }) {\n this.renderer = renderer;\n this.uniforms = uniforms;\n this.chunkSize = Math.max(1, chunkSize);\n this.viewRadius = Math.max(2, viewRadius);\n this.levels = [];\n this.queue = [];\n this.generation = -1;\n this._disposed = false;\n this._requirePrepared = requirePrepared;\n\n const maxSpan = this.chunkSize * (this.viewRadius * 2 + 4);\n const spans = [\n this.chunkSize * 8,\n this.chunkSize * 24,\n Math.max(this.chunkSize * 32, maxSpan),\n ];\n for (let index = 0; index < LEVEL_COUNT; index++) {\n const resolution = Math.max(64, Math.round(resolutions[index] || 256));\n const target = new THREE.WebGLRenderTarget(resolution, resolution, {\n type: THREE.HalfFloatType,\n format: THREE.RGBAFormat,\n internalFormat: 'RGBA16F',\n minFilter: THREE.LinearFilter,\n magFilter: THREE.LinearFilter,\n depthBuffer: false,\n generateMipmaps: false,\n });\n target.texture.colorSpace = THREE.NoColorSpace;\n target.texture.name = `InfiniteTerrainFieldL${index}`;\n this.levels.push({\n index,\n resolution,\n span: spans[index],\n origin: new THREE.Vector2(),\n pendingOrigin: new THREE.Vector2(),\n ready: false,\n target,\n });\n uniforms[`uInfiniteFieldTex${index}`].value = target.texture;\n }\n\n this.scene = new THREE.Scene();\n this.camera = new THREE.Camera();\n this.material = this._makeProgramMaterial(octaves, stackGLSL);\n this._octaves = octaves;\n this._stackSig = stackGLSL.heightSig || stackGLSL.sig;\n this._programSerial = 0;\n this._programPrepared = false;\n this.mesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), this.material);\n this.mesh.frustumCulled = false;\n this.scene.add(this.mesh);\n uniforms.uUseInfiniteFieldCache.value = 1;\n this._publishReady();\n }\n\n _makeProgramMaterial(octaves, stackGLSL) {\n return new THREE.ShaderMaterial({\n uniforms: {\n ...this.uniforms,\n uClipBakeOrigin: { value: new THREE.Vector2() },\n uClipBakeSpan: { value: new THREE.Vector2(1, 1) },\n },\n defines: { OCTAVES: octaves },\n vertexShader: VERTEX,\n fragmentShader: buildFragment(buildHeightGLSL(stackGLSL.body2d)),\n depthTest: false,\n depthWrite: false,\n });\n }\n\n prepareProgram(octaves, stackGLSL = DEFAULT_STACK_GLSL) {\n if (this._disposed) return null;\n const serial = ++this._programSerial;\n const programSig = stackGLSL.heightSig || stackGLSL.sig;\n const current = this._programPrepared\n && this._octaves === octaves\n && this._stackSig === programSig;\n if (current) return { serial, current: true, octaves, stackSig: programSig, passes: [] };\n const material = this._makeProgramMaterial(octaves, stackGLSL);\n return {\n serial, current: false, material, octaves, stackSig: programSig,\n passes: [{\n scene: this.scene, camera: this.camera, mesh: this.mesh, material,\n renderTarget: this.levels[0]?.target ?? null,\n }],\n };\n }\n\n publishPrepared(handle) {\n if (!handle || this._disposed || handle.serial !== this._programSerial) return false;\n if (!handle.current) {\n const previous = this.material;\n this.material = handle.material;\n this.mesh.material = this.material;\n this._octaves = handle.octaves;\n this._stackSig = handle.stackSig;\n handle.published = true;\n previous?.dispose();\n }\n this._programPrepared = true;\n this.generation = -1;\n this.queue.length = 0;\n for (const level of this.levels) level.ready = false;\n this._publishReady();\n return true;\n }\n\n discardPrepared(handle) {\n if (handle?.material && !handle.published && handle.material !== this.material) {\n handle.material.dispose();\n }\n }\n\n setProgram(octaves, stackGLSL = DEFAULT_STACK_GLSL) {\n if (this._disposed) return false;\n const programSig = stackGLSL.heightSig || stackGLSL.sig;\n if (this._octaves === octaves && this._stackSig === programSig && this._programPrepared) return false;\n const handle = this.prepareProgram(octaves, stackGLSL);\n this.publishPrepared(handle);\n return true;\n }\n request(center, generation) {\n if (this._disposed) return;\n const generationChanged = generation !== this.generation;\n if (generationChanged) {\n this.generation = generation;\n this.queue.length = 0;\n for (const level of this.levels) level.ready = false;\n }\n\n for (const level of this.levels) {\n const texel = level.span / level.resolution;\n const snappedX = Math.floor((center.x - level.span * 0.5) / texel) * texel;\n const snappedZ = Math.floor((center.z - level.span * 0.5) / texel) * texel;\n const margin = level.span * 0.22;\n const insideStableRegion = level.ready\n && center.x >= level.origin.x + margin\n && center.x <= level.origin.x + level.span - margin\n && center.z >= level.origin.y + margin\n && center.z <= level.origin.y + level.span - margin;\n if (generationChanged || !insideStableRegion) {\n level.pendingOrigin.set(snappedX, snappedZ);\n if (!this.queue.includes(level.index)) this.queue.push(level.index);\n }\n }\n this._publishReady();\n }\n\n update(center, generation) {\n if (this._disposed || (this._requirePrepared && !this._programPrepared)) return false;\n this.request(center, generation);\n if (!this.queue.length) return false;\n const index = this.queue.shift();\n const level = this.levels[index];\n const previousTarget = this.renderer.getRenderTarget();\n const u = this.material.uniforms;\n u.uClipBakeOrigin.value.copy(level.pendingOrigin);\n u.uClipBakeSpan.value.setScalar(level.span);\n try {\n this.renderer.setRenderTarget(level.target);\n this.renderer.render(this.scene, this.camera);\n } finally {\n this.renderer.setRenderTarget(previousTarget);\n }\n level.origin.copy(level.pendingOrigin);\n level.ready = true;\n this.uniforms[`uInfiniteFieldOrigin${index}`].value.copy(level.origin);\n this.uniforms[`uInfiniteFieldSpan${index}`].value.setScalar(level.span);\n this._publishReady();\n return true;\n }\n\n _publishReady() {\n const ready = this.uniforms.uInfiniteFieldReady.value;\n ready.set(\n this.levels[0]?.ready ? 1 : 0,\n this.levels[1]?.ready ? 1 : 0,\n this.levels[2]?.ready ? 1 : 0,\n );\n }\n\n diagnostics() {\n return {\n generation: this.generation,\n pendingLevels: [...this.queue],\n levels: this.levels.map((level) => ({\n resolution: level.resolution,\n span: level.span,\n ready: level.ready,\n origin: { x: level.origin.x, z: level.origin.y },\n })),\n };\n }\n\n dispose() {\n this._disposed = true;\n this.uniforms.uUseInfiniteFieldCache.value = 0;\n this.uniforms.uInfiniteFieldReady.value.set(0, 0, 0);\n for (const level of this.levels) level.target.dispose();\n this.mesh.geometry.dispose();\n this.material.dispose();\n this.levels = [];\n this.queue = [];\n }\n}\n","import * as THREE from 'three';\nimport { FiniteTerrain } from '../FiniteTerrain.js';\nimport { InfiniteWorld } from '../../engine/terrain/InfiniteWorld.js';\nimport { InfiniteTerrainClipmap } from '../../engine/terrain/InfiniteTerrainClipmap.js';\nimport { createInfiniteTerrainMaterial } from '../../engine/terrain/TerrainMaterial.js';\nimport { createInfiniteWaterMaterial } from '../../engine/terrain/WaterMaterial.js';\nimport { compileMaterial } from '../resources/CompileMaterial.js';\nimport { withRendererState } from '../resources/RendererState.js';\n\nfunction validate(l) {\n for (const [name, min, max] of [\n ['viewRadius', 2, 32],\n ['triangleBudget', 0, 20000000],\n ['maxCreatesPerFrame', 1, 1024],\n ['streamBudgetMs', 0.1, 20],\n ['cacheResolution', 64, 1024],\n ]) {\n if (!Number.isFinite(l[name]) || l[name] < min || l[name] > max)\n throw new RangeError(`layout.${name} must be ${min}..${max}`);\n }\n for (const key of ['viewRadius', 'maxCreatesPerFrame', 'cacheResolution'])\n if (!Number.isInteger(l[key])) throw new TypeError(`layout.${key} must be an integer`);\n}\n\nexport const infiniteAdapter = {\n mode: 'infinite',\n layoutDefaults: {\n viewRadius: 8,\n triangleBudget: 1000000,\n maxCreatesPerFrame: 16,\n streamBudgetMs: 1.5,\n cacheResolution: 256,\n },\n validateLayout: validate,\n createMaterial: (t, octaves, program) =>\n createInfiniteTerrainMaterial(t._uniforms, octaves, program, {\n variant: t._surface ? 'surface' : 'base',\n }),\n createRuntime(t) {\n return {\n world: null,\n cache: null,\n key: '',\n get group() {\n return this.world.group;\n },\n update(camera) {\n this.world.update(camera.position, camera);\n this.world.waterPlane.visible = false;\n },\n diagnostics() {\n const w = this.world;\n return {\n chunks: w.chunks.size,\n visible: w.visibleChunkCount,\n culled: w.culledChunkCount,\n lodCounts: [...w.lodCounts],\n cache: this.cache.diagnostics(),\n };\n },\n dispose() {\n this.world?.dispose();\n this.cache?.dispose();\n this.waterMaterial?.dispose();\n },\n };\n },\n apply(t, c) {\n const r = t._runtime,\n l = c.layout,\n u = t._uniforms;\n const key = JSON.stringify([l.chunkSize, l.viewRadius, l.cacheResolution]);\n if (r.key !== key) {\n r.dispose();\n r.key = key;\n r.waterMaterial = createInfiniteWaterMaterial(u, c.source.octaves, t._stackGLSL);\n r.world = new InfiniteWorld(t.object, t._material, r.waterMaterial, {\n chunkSize: l.chunkSize,\n viewRadius: l.viewRadius,\n maxHeight: c.heightScale * 1.35 + 2,\n skirtDepth: Math.max(24, c.heightScale * 0.08),\n seaLevel: 0,\n lodSegments: c.quality.lodSegments,\n });\n r.world.waterPlane.visible = false;\n r.cache = new InfiniteTerrainClipmap({\n renderer: t._renderer,\n uniforms: u,\n chunkSize: l.chunkSize,\n viewRadius: l.viewRadius,\n octaves: c.source.octaves,\n stackGLSL: t._stackGLSL,\n resolutions: [l.cacheResolution, l.cacheResolution, l.cacheResolution],\n requirePrepared: true,\n });\n }\n r.world.setMaxCreatesPerFrame(l.maxCreatesPerFrame);\n r.world.setChunkStreamBudget(l.streamBudgetMs);\n r.world.setTriangleBudget(l.triangleBudget);\n r.world.setLodMultiplier(c.quality.lodDistanceScale);\n r.world.setViewRadius(l.viewRadius);\n r.world.setLodSegments(c.quality.lodSegments);\n r.world.setMorphEnabled(c.quality.morphEnabled);\n r.world.setMergeOptions({ enabled: c.quality.mergeEnabled });\n r.world.cullingEnabled = c.quality.cullingEnabled;\n r.world.updateSettings({\n maxHeight: c.heightScale * 1.35 + 2,\n skirtDepth: Math.max(24, c.heightScale * 0.08),\n seaLevel: c.seaLevel,\n });\n u.uUseInfiniteFieldCache.value = 1;\n },\n async prepare(t, camera, signal, check = () => t._assertAlive()) {\n const cache = t._runtime.cache;\n const h = cache.prepareProgram(t.configuration.source.octaves, t._stackGLSL);\n try {\n for (const p of h.passes ?? [{ material: h.material ?? cache.material }])\n await compileMaterial(t._renderer, p.material, p.camera ?? camera, {\n geometry: p.mesh?.geometry.clone(),\n });\n signal?.throwIfAborted();\n check();\n cache.publishPrepared(h);\n } catch (e) {\n cache.discardPrepared(h);\n throw e;\n }\n withRendererState(t._renderer, () => {\n for (let i = 0; i < 3; i++) cache.update(t._cameraPosition, t._revision);\n });\n },\n async sourceChanged(t, source, { signal, check, sourceChanged }) {\n if (sourceChanged)\n await this.prepare(t, t._viewCamera ?? new THREE.PerspectiveCamera(), signal, check);\n t._runtime.world.terrainMaterial = t._material;\n t._runtime.world.merge.material = t._material;\n t._runtime.world.batches.material = t._material;\n },\n update(t) {\n withRendererState(t._renderer, () => t._runtime.cache.update(t._cameraPosition, t._revision));\n },\n createProbe(t, material) {\n const geometry = t._runtime.world.batches.meshes[0].geometry.clone();\n const mesh = new THREE.InstancedMesh(geometry, material, 1);\n return { geometry, mesh };\n },\n};\n\nexport async function createInfiniteTerrain(options) {\n return new FiniteTerrain({ ...options, _world: infiniteAdapter });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as THREE from "three";
|
|
2
2
|
import { P as PRESETS, D as DEFAULT_PARAMS, t as terrainStyle, b as terrainMaterial } from "./ProgramHealthGate-DS47bUo1.js";
|
|
3
|
-
import { c as createTerrain } from "./FiniteTerrain-
|
|
3
|
+
import { c as createTerrain } from "./FiniteTerrain-B5_3y6xX.js";
|
|
4
4
|
import { M as MINI_VISUAL_PARAMS, a as MINI_LIGHTING_GLSL, b as miniLightingUniforms, c as createMiniWaterCutMaterial, m as miniStylePatch, d as miniWaterColors, e as applyMiniWaterLook, f as createMiniWaterSurfaceMaterial } from "./MiniWaterMaterial-DLml0hi6.js";
|
|
5
|
-
import { m as miniCutColor, d as applyTerrainShapeUniforms, e as applyTerrainShadingUniforms } from "./TerrainParameters-
|
|
5
|
+
import { m as miniCutColor, d as applyTerrainShapeUniforms, e as applyTerrainShadingUniforms } from "./TerrainParameters-DMCjnnxz.js";
|
|
6
6
|
import { m as miniFootprint, M as MINI_BEVEL_GLSL } from "./TerrainSources-Bye63rDk.js";
|
|
7
|
-
import { T as TerrainHeightCache } from "./TerrainHeightCache-
|
|
7
|
+
import { T as TerrainHeightCache } from "./TerrainHeightCache-DIZxi9jz.js";
|
|
8
8
|
import { c as compileMaterial } from "./CompileMaterial-DZiWxNZC.js";
|
|
9
9
|
import { w as withRendererState } from "./RendererState-BwgUc9ze.js";
|
|
10
10
|
const MINI_TERRAIN_VERSION = 3;
|
|
@@ -71,7 +71,7 @@ const MINI_RECIPES = Object.freeze({
|
|
|
71
71
|
cutStyle: "strata",
|
|
72
72
|
water: "tropical",
|
|
73
73
|
vegetation: 0.7,
|
|
74
|
-
clouds: 0,
|
|
74
|
+
clouds: 0.75,
|
|
75
75
|
climate: null
|
|
76
76
|
}),
|
|
77
77
|
cove: Object.freeze({
|
|
@@ -91,7 +91,7 @@ const MINI_RECIPES = Object.freeze({
|
|
|
91
91
|
cutStyle: "strata",
|
|
92
92
|
water: "tropical",
|
|
93
93
|
vegetation: 0.75,
|
|
94
|
-
clouds: 0,
|
|
94
|
+
clouds: 0.75,
|
|
95
95
|
climate: { tempBias: 0.42, moistBias: 0.3 }
|
|
96
96
|
}),
|
|
97
97
|
islet: Object.freeze({
|
|
@@ -109,7 +109,7 @@ const MINI_RECIPES = Object.freeze({
|
|
|
109
109
|
cutStyle: "soil",
|
|
110
110
|
water: "tropical",
|
|
111
111
|
vegetation: 0.9,
|
|
112
|
-
clouds: 0,
|
|
112
|
+
clouds: 0.75,
|
|
113
113
|
climate: { tempBias: 0.45, moistBias: 0.38 }
|
|
114
114
|
}),
|
|
115
115
|
lake: Object.freeze({
|
|
@@ -127,7 +127,7 @@ const MINI_RECIPES = Object.freeze({
|
|
|
127
127
|
cutStyle: "dark",
|
|
128
128
|
water: "lake",
|
|
129
129
|
vegetation: 0.6,
|
|
130
|
-
clouds: 0,
|
|
130
|
+
clouds: 0.75,
|
|
131
131
|
climate: { tempBias: 0.32, moistBias: 0.25 }
|
|
132
132
|
})
|
|
133
133
|
});
|
|
@@ -1985,4 +1985,4 @@ export {
|
|
|
1985
1985
|
normalizeMiniTerrainState as n,
|
|
1986
1986
|
resolveMiniFraming as r
|
|
1987
1987
|
};
|
|
1988
|
-
//# sourceMappingURL=MiniTerrain-
|
|
1988
|
+
//# sourceMappingURL=MiniTerrain-Bb5VYkZU.js.map
|