minecraft-renderer 0.1.79 → 0.1.80
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/README.md +29 -25
- package/dist/mesher.js +36 -36
- package/dist/mesher.js.map +4 -4
- package/dist/mesherWasm.js +217 -217
- package/dist/minecraft-renderer.js +27 -27
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +133 -133
- package/package.json +5 -2
- package/src/bundler/bundlePrepare.ts +3 -8
- package/src/graphicsBackend/appViewer.ts +10 -7
- package/src/graphicsBackend/config.ts +1 -5
- package/src/graphicsBackend/playerState.ts +35 -34
- package/src/graphicsBackend/preloadWorkers.ts +43 -41
- package/src/graphicsBackend/rendererDefaultOptions.ts +68 -70
- package/src/graphicsBackend/rendererOptionsSync.ts +24 -50
- package/src/graphicsBackend/types.ts +2 -2
- package/src/index.ts +6 -27
- package/src/lib/DebugGui.ts +34 -31
- package/src/lib/animationController.ts +9 -9
- package/src/lib/bakeLegacyLight.ts +1 -6
- package/src/lib/bindAbortableListener.test.ts +32 -12
- package/src/lib/bindAbortableListener.ts +14 -6
- package/src/lib/blockEntityLightRegistry.ts +11 -20
- package/src/lib/blockEntityLighting.test.ts +1 -6
- package/src/lib/blockEntityLighting.ts +5 -5
- package/src/lib/buildSharedConfig.mjs +4 -4
- package/src/lib/buildWorkerMcDataIndexes.test.ts +4 -4
- package/src/lib/buildWorkerMcDataIndexes.ts +11 -19
- package/src/lib/cameraBobbing.ts +1 -1
- package/src/lib/canvas2DOverlay.example.ts +13 -33
- package/src/lib/canvas2DOverlay.quickstart.ts +24 -54
- package/src/lib/canvas2DOverlay.ts +28 -47
- package/src/lib/cleanupDecorator.ts +2 -2
- package/src/lib/createPlayerObject.test.ts +2 -7
- package/src/lib/createPlayerObject.ts +18 -25
- package/src/lib/frameTimingCollector.ts +2 -5
- package/src/lib/guiRenderer.ts +57 -42
- package/src/lib/items.ts +15 -9
- package/src/lib/mesherlogReader.ts +5 -6
- package/src/lib/simpleUtils.ts +5 -5
- package/src/lib/skyLight.ts +3 -3
- package/src/lib/smoothSwitcher.ts +11 -18
- package/src/lib/ui/newStats.ts +10 -12
- package/src/lib/utils/proxy.ts +7 -1
- package/src/lib/utils/skins.ts +4 -4
- package/src/lib/utils.ts +1 -1
- package/src/lib/workerMessageSanitize.ts +5 -12
- package/src/lib/workerProxy.ts +52 -42
- package/src/lib/workerSyncOps.test.ts +58 -41
- package/src/lib/worldrendererCommon.reconfigure.test.ts +24 -21
- package/src/lib/worldrendererCommon.removeColumn.test.ts +11 -13
- package/src/lib/worldrendererCommon.ts +338 -211
- package/src/mesher-legacy/mesher.ts +9 -4
- package/src/mesher-legacy/test/a.ts +1 -1
- package/src/mesher-legacy/test/mesherTester.ts +2 -2
- package/src/mesher-legacy/test/playground.ts +1 -1
- package/src/mesher-legacy/test/run/test-js.ts +1 -1
- package/src/mesher-legacy/test/snapshotUtils.ts +3 -8
- package/src/mesher-legacy/test/test-perf.ts +1 -1
- package/src/mesher-legacy/test/tests.test.ts +2 -2
- package/src/mesher-shared/blockEntityMetadata.test.ts +7 -5
- package/src/mesher-shared/blockEntityMetadata.ts +28 -19
- package/src/mesher-shared/blockPropertiesForMeshing.ts +2 -2
- package/src/mesher-shared/computeHeightmap.ts +2 -4
- package/src/mesher-shared/exportedGeometryTypes.ts +3 -3
- package/src/mesher-shared/faceOcclusion.ts +324 -0
- package/src/mesher-shared/models.ts +80 -131
- package/src/mesher-shared/modelsGeometryCommon.ts +30 -15
- package/src/mesher-shared/shared.ts +46 -46
- package/src/mesher-shared/standaloneRenderer.ts +40 -44
- package/src/mesher-shared/tests/faceOcclusion.test.ts +179 -0
- package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +12 -8
- package/src/mesher-shared/vertexShading.ts +2 -11
- package/src/mesher-shared/world.ts +19 -19
- package/src/mesher-shared/worldLighting.test.ts +2 -2
- package/src/performanceMonitor/PerformanceMonitor.ts +4 -13
- package/src/performanceMonitor/formatPerformanceFactorsDebug.ts +2 -2
- package/src/performanceMonitor/index.ts +1 -5
- package/src/performanceMonitor/types.ts +1 -1
- package/src/playerState/playerState.ts +55 -50
- package/src/playerState/types.ts +2 -8
- package/src/playground/allEntitiesDebug.ts +19 -16
- package/src/playground/baseScene.ts +29 -32
- package/src/playground/mobileControls.tsx +133 -129
- package/src/playground/playground.html +76 -73
- package/src/playground/playground.ts +14 -1
- package/src/playground/playgroundUi.tsx +100 -74
- package/src/playground/reactUtils.ts +3 -7
- package/src/playground/scenes/entities.ts +10 -7
- package/src/playground/scenes/frequentUpdates.ts +5 -5
- package/src/playground/scenes/geometryExport.ts +6 -20
- package/src/playground/scenes/highPosEntityUpdates.ts +2 -10
- package/src/playground/scenes/index.ts +1 -1
- package/src/playground/scenes/lightingStarfield.ts +18 -12
- package/src/playground/scenes/main.ts +15 -11
- package/src/playground/scenes/partialBlockCulling.ts +31 -0
- package/src/playground/scenes/railsCobweb.ts +1 -1
- package/src/playground/scenes/rotationIssue.ts +1 -1
- package/src/playground/scenes/slabsOptimization.ts +1 -2
- package/src/playground/scenes/transparencyIssue.ts +1 -1
- package/src/playground/shared.ts +2 -2
- package/src/resourcesManager/resourcesManager.ts +29 -54
- package/src/resourcesManager/resourcesManager.worker.test.ts +6 -10
- package/src/shims/minecraftData.ts +70 -24
- package/src/sign-renderer/index.html +10 -12
- package/src/sign-renderer/index.ts +29 -29
- package/src/sign-renderer/playground.ts +22 -15
- package/src/sign-renderer/tests.test.ts +16 -13
- package/src/sign-renderer/vite.config.ts +2 -2
- package/src/three/appShared.ts +46 -25
- package/src/three/bannerRenderer.ts +33 -61
- package/src/three/cameraShake.ts +15 -6
- package/src/three/chunkMeshManager.ts +239 -282
- package/src/three/cinimaticScript.ts +26 -15
- package/src/three/cubeDrawSpans.ts +27 -37
- package/src/three/cubeMultiDraw.ts +9 -22
- package/src/three/documentRenderer.ts +15 -18
- package/src/three/entities.ts +175 -150
- package/src/three/entity/EntityMesh.ts +114 -108
- package/src/three/entity/animations.js +3 -3
- package/src/three/entity/armorModels.ts +15 -15
- package/src/three/entity/gltfAnimationUtils.ts +2 -5
- package/src/three/fireworks.ts +34 -32
- package/src/three/fireworksRenderer.ts +32 -29
- package/src/three/globalBlockBuffer.ts +167 -100
- package/src/three/globalLegacyBuffer.ts +257 -166
- package/src/three/graphicsBackendBase.ts +19 -25
- package/src/three/graphicsBackendOffThread.ts +12 -15
- package/src/three/hand.ts +21 -21
- package/src/three/handLegacy.ts +3 -13
- package/src/three/holdingBlock.ts +116 -79
- package/src/three/holdingBlockFactory.ts +1 -4
- package/src/three/holdingBlockItemIdentity.test.ts +25 -17
- package/src/three/holdingBlockItemIdentity.ts +9 -6
- package/src/three/holdingBlockLegacy.ts +113 -132
- package/src/three/itemMesh.ts +20 -29
- package/src/three/legacyMultiDraw.ts +10 -16
- package/src/three/legacySectionCull.ts +8 -14
- package/src/three/menuBackground/activeView.ts +1 -4
- package/src/three/menuBackground/assetUrl.ts +1 -1
- package/src/three/menuBackground/classic.ts +4 -12
- package/src/three/menuBackground/gpuPreference.ts +1 -3
- package/src/three/menuBackground/index.ts +2 -11
- package/src/three/menuBackground/renderer.ts +1 -5
- package/src/three/menuBackground/types.ts +1 -4
- package/src/three/menuBackground/v2.ts +196 -96
- package/src/three/menuBackground/v2Meta.ts +3 -3
- package/src/three/menuBackground/worldBlocks.ts +37 -35
- package/src/three/modules/blockBreakParticles.ts +59 -28
- package/src/three/modules/cameraBobbing.ts +3 -6
- package/src/three/modules/index.ts +1 -1
- package/src/three/modules/rain.ts +10 -23
- package/src/three/modules/sciFiWorldReveal.ts +11 -25
- package/src/three/modules/starfield.ts +7 -13
- package/src/three/renderSlot.ts +28 -16
- package/src/three/rendererModuleSystem.ts +1 -3
- package/src/three/sceneOrigin.ts +96 -33
- package/src/three/sectionRaycastAabb.ts +30 -18
- package/src/three/shaderCubeMesh.ts +6 -17
- package/src/three/shaders/cubeBlockShader.ts +85 -96
- package/src/three/shaders/legacyBlockShader.ts +21 -43
- package/src/three/shaders/textureIndexMapping.ts +89 -95
- package/src/three/shaders/tintPalette.ts +156 -170
- package/src/three/signTextureCache.ts +9 -12
- package/src/three/skyboxRenderer.ts +62 -70
- package/src/three/tests/chunkMeshManagerLegacy.test.ts +34 -34
- package/src/three/tests/cubeDrawSpans.test.ts +55 -25
- package/src/three/tests/globalBlockBuffer.test.ts +217 -0
- package/src/three/tests/globalLegacyBuffer.test.ts +300 -41
- package/src/three/tests/legacyMultiDraw.test.ts +8 -29
- package/src/three/tests/pr3PerFrameCpuCuts.test.ts +106 -29
- package/src/three/tests/signTextureCache.test.ts +4 -4
- package/src/three/threeJsMedia.ts +55 -72
- package/src/three/threeJsParticles.ts +32 -41
- package/src/three/threeJsSound.ts +3 -3
- package/src/three/threeJsUtils.ts +3 -3
- package/src/three/threeWorker.ts +2 -2
- package/src/three/waypointSprite.ts +55 -82
- package/src/three/waypoints.ts +20 -23
- package/src/three/world/cursorBlock.ts +25 -12
- package/src/three/world/vr.ts +11 -17
- package/src/three/worldGeometryExport.ts +15 -34
- package/src/three/worldRendererThree.ts +117 -129
- package/src/wasm-mesher/bridge/convertChunk.ts +3 -9
- package/src/wasm-mesher/bridge/render-from-wasm.ts +204 -229
- package/src/wasm-mesher/bridge/shaderCubeBridge.ts +26 -67
- package/src/wasm-mesher/tests/cullingRegression.test.ts +307 -0
- package/src/wasm-mesher/tests/heightmapParity.test.ts +8 -18
- package/src/wasm-mesher/tests/mesherWasmConversionCache.test.ts +2 -2
- package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +17 -4
- package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +103 -141
- package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +14 -22
- package/src/wasm-mesher/worker/mesherWasm.ts +150 -141
- package/src/wasm-mesher/worker/mesherWasmConversionCache.ts +2 -8
- package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +1 -3
- package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +1 -5
- package/src/wasm-mesher/worker/mesherWasmRequestTracker.ts +42 -42
- package/src/worldView/worldView.spiral.test.ts +1 -1
- package/src/worldView/worldView.ts +34 -39
- package/src/worldView/worldViewWorkerBridge.test.ts +4 -4
|
@@ -4,8 +4,24 @@ import * as nbt from 'prismarine-nbt'
|
|
|
4
4
|
import { Vec3 } from 'vec3'
|
|
5
5
|
import { MesherGeometryOutput } from '../mesher-shared/shared'
|
|
6
6
|
import { getShaderCubeResources, SHADER_CUBES_WORDS_PER_FACE } from '../wasm-mesher/bridge/shaderCubeBridge'
|
|
7
|
-
import {
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
createCubeBlockMaterial,
|
|
9
|
+
computeSectionOriginRel,
|
|
10
|
+
setCubeSkyLevel,
|
|
11
|
+
setCubeShadingTheme,
|
|
12
|
+
setCubeLightmapParams,
|
|
13
|
+
type BlockLightmapParams
|
|
14
|
+
} from './shaders/cubeBlockShader'
|
|
15
|
+
import {
|
|
16
|
+
computeCameraRelativeUniforms,
|
|
17
|
+
createGlobalLegacyBlendMaterial,
|
|
18
|
+
createGlobalLegacyBlockMaterial,
|
|
19
|
+
createLegacyBlockMaterial,
|
|
20
|
+
setLegacyCameraOrigin,
|
|
21
|
+
setLegacySkyLevel,
|
|
22
|
+
setLegacyLightmapParams,
|
|
23
|
+
type RenderOrigin
|
|
24
|
+
} from './shaders/legacyBlockShader'
|
|
9
25
|
import { LEGACY_SECTION_HALF_EXTENT, sectionIntersectsFrustum, setupLegacySectionMatrix, updateLegacySectionCullState } from './legacySectionCull'
|
|
10
26
|
import { createShaderCubeMesh, disposeShaderCubeMesh } from './shaderCubeMesh'
|
|
11
27
|
import { GlobalBlockBuffer } from './globalBlockBuffer'
|
|
@@ -17,7 +33,7 @@ import {
|
|
|
17
33
|
raycastAabb,
|
|
18
34
|
raycastShaderBlocksAabb,
|
|
19
35
|
sectionAabbIntersectsRay,
|
|
20
|
-
type ShaderSectionRaycastEntry
|
|
36
|
+
type ShaderSectionRaycastEntry
|
|
21
37
|
} from './sectionRaycastAabb'
|
|
22
38
|
import { getMesh } from './entity/EntityMesh'
|
|
23
39
|
import type { WorldRendererThree } from './worldRendererThree'
|
|
@@ -39,7 +55,7 @@ export interface SectionObject extends THREE.Group {
|
|
|
39
55
|
/** Per-section instanced shader mesh (sci-fi reveal defer only). */
|
|
40
56
|
shaderMesh?: THREE.Mesh<THREE.InstancedBufferGeometry, THREE.ShaderMaterial>
|
|
41
57
|
/** Shader cube words kept for migration to global buffer after reveal. */
|
|
42
|
-
deferredShaderCubes?: { words: Uint32Array
|
|
58
|
+
deferredShaderCubes?: { words: Uint32Array; count: number }
|
|
43
59
|
/** Opaque legacy geometry deferred from global buffer during sci-fi reveal. */
|
|
44
60
|
deferredLegacyOpaque?: LegacySectionGeometry
|
|
45
61
|
/** Blend legacy geometry deferred from global buffer during sci-fi reveal. */
|
|
@@ -139,10 +155,11 @@ export class ChunkMeshManager {
|
|
|
139
155
|
private readonly _legacyCullBox = new THREE.Box3()
|
|
140
156
|
private readonly _legacyCullBoxMin = new THREE.Vector3()
|
|
141
157
|
private readonly _legacyCullBoxMax = new THREE.Vector3()
|
|
142
|
-
private readonly _visibleSectionSpans: Array<{ key: string
|
|
158
|
+
private readonly _visibleSectionSpans: Array<{ key: string; distSq: number }> = []
|
|
143
159
|
/** Sections with geometry in global legacy opaque and/or blend buffers — cull/raycast scan only these. */
|
|
144
|
-
private readonly legacyCullSections = new Map<string, { worldX: number
|
|
160
|
+
private readonly legacyCullSections = new Map<string, { worldX: number; worldY: number; worldZ: number }>()
|
|
145
161
|
private _lastCullFingerprint = ''
|
|
162
|
+
private lastBufferStateKey = ''
|
|
146
163
|
/** Drives per-frame cull + span rebuild; cleared after updateSectionCullAndSort. */
|
|
147
164
|
cullDirty = true
|
|
148
165
|
private readonly _lastCullCamPos = new THREE.Vector3()
|
|
@@ -173,20 +190,20 @@ export class ChunkMeshManager {
|
|
|
173
190
|
private lastPerformanceCheck = 0
|
|
174
191
|
private readonly performanceCheckInterval = 2000 // Check every 2 seconds
|
|
175
192
|
|
|
176
|
-
get performanceOverrideDistance
|
|
193
|
+
get performanceOverrideDistance() {
|
|
177
194
|
return this._performanceOverrideDistance ?? 0
|
|
178
195
|
}
|
|
179
|
-
set performanceOverrideDistance
|
|
196
|
+
set performanceOverrideDistance(value: number | undefined) {
|
|
180
197
|
this._performanceOverrideDistance = value
|
|
181
198
|
this.updateSectionsVisibility()
|
|
182
199
|
}
|
|
183
200
|
|
|
184
|
-
constructor
|
|
201
|
+
constructor(
|
|
185
202
|
public worldRenderer: WorldRendererThree,
|
|
186
203
|
public scene: THREE.Object3D,
|
|
187
204
|
public material: THREE.Material,
|
|
188
205
|
public worldHeight: number,
|
|
189
|
-
viewDistance = 3
|
|
206
|
+
viewDistance = 3
|
|
190
207
|
) {
|
|
191
208
|
this.updateViewDistance(viewDistance)
|
|
192
209
|
this.signHeadsRenderer = new SignHeadsRenderer(worldRenderer)
|
|
@@ -194,7 +211,7 @@ export class ChunkMeshManager {
|
|
|
194
211
|
this.initializePool()
|
|
195
212
|
}
|
|
196
213
|
|
|
197
|
-
private initializePool
|
|
214
|
+
private initializePool() {
|
|
198
215
|
// Create initial pool
|
|
199
216
|
for (let i = 0; i < this.poolSize; i++) {
|
|
200
217
|
const geometry = new THREE.BufferGeometry()
|
|
@@ -215,18 +232,18 @@ export class ChunkMeshManager {
|
|
|
215
232
|
}
|
|
216
233
|
|
|
217
234
|
/** True when section has legacy vertices and/or GPU shader cube instances. */
|
|
218
|
-
sectionHasRenderableContent
|
|
235
|
+
sectionHasRenderableContent(geometryData: MesherGeometryOutput): boolean {
|
|
219
236
|
if (geometryData.positions.length > 0) return true
|
|
220
237
|
if ((geometryData.blend?.positions.length ?? 0) > 0) return true
|
|
221
238
|
if (!this.isShaderCubesGpuEnabled()) return false
|
|
222
239
|
return (geometryData.shaderCubes?.count ?? 0) > 0
|
|
223
240
|
}
|
|
224
241
|
|
|
225
|
-
isShaderCubesGpuEnabled
|
|
242
|
+
isShaderCubesGpuEnabled(): boolean {
|
|
226
243
|
return this.worldRenderer.shaderCubeBlocksEnabled()
|
|
227
244
|
}
|
|
228
245
|
|
|
229
|
-
syncCubeShaderUniforms
|
|
246
|
+
syncCubeShaderUniforms(): void {
|
|
230
247
|
if (!this.isShaderCubesGpuEnabled()) return
|
|
231
248
|
const mat = this.cubeShaderMaterial ?? this.getCubeShaderMaterial()
|
|
232
249
|
if (!mat) return
|
|
@@ -243,7 +260,7 @@ export class ChunkMeshManager {
|
|
|
243
260
|
mat.needsUpdate = true
|
|
244
261
|
}
|
|
245
262
|
|
|
246
|
-
syncLegacyShaderUniforms
|
|
263
|
+
syncLegacyShaderUniforms(): void {
|
|
247
264
|
const atlas = (this.material as THREE.MeshBasicMaterial).map ?? null
|
|
248
265
|
if (this.legacyShaderMaterial) {
|
|
249
266
|
this.legacyShaderMaterial.uniforms.u_atlas.value = atlas
|
|
@@ -260,7 +277,7 @@ export class ChunkMeshManager {
|
|
|
260
277
|
}
|
|
261
278
|
|
|
262
279
|
/** Render-time sky light cap (0–1, from time-of-day / 15). */
|
|
263
|
-
setSkyLevel
|
|
280
|
+
setSkyLevel(value: number): void {
|
|
264
281
|
const cube = this.cubeShaderMaterial ?? (this.isShaderCubesGpuEnabled() ? this.getCubeShaderMaterial() : null)
|
|
265
282
|
if (cube) setCubeSkyLevel(cube, value)
|
|
266
283
|
if (this.legacyShaderMaterial) setLegacySkyLevel(this.legacyShaderMaterial, value)
|
|
@@ -269,13 +286,13 @@ export class ChunkMeshManager {
|
|
|
269
286
|
this.blockEntityLightRegistry.setSkyLevel(value)
|
|
270
287
|
}
|
|
271
288
|
|
|
272
|
-
setShadingTheme
|
|
289
|
+
setShadingTheme(theme: 'vanilla' | 'high-contrast', cardinalLight: string): void {
|
|
273
290
|
const cube = this.cubeShaderMaterial ?? (this.isShaderCubesGpuEnabled() ? this.getCubeShaderMaterial() : null)
|
|
274
291
|
if (cube) setCubeShadingTheme(cube, theme, cardinalLight)
|
|
275
292
|
}
|
|
276
293
|
|
|
277
294
|
/** Vanilla-like lightmap curve params (live tuning via window.setBlockLightmap). */
|
|
278
|
-
setBlockLightmapParams
|
|
295
|
+
setBlockLightmapParams(params: BlockLightmapParams): void {
|
|
279
296
|
const cube = this.cubeShaderMaterial ?? (this.isShaderCubesGpuEnabled() ? this.getCubeShaderMaterial() : null)
|
|
280
297
|
if (cube) setCubeLightmapParams(cube, params)
|
|
281
298
|
if (this.legacyShaderMaterial) setLegacyLightmapParams(this.legacyShaderMaterial, params)
|
|
@@ -284,7 +301,7 @@ export class ChunkMeshManager {
|
|
|
284
301
|
this.blockEntityLightRegistry.setLightmapParams(params)
|
|
285
302
|
}
|
|
286
303
|
|
|
287
|
-
private getLegacyShaderMaterial
|
|
304
|
+
private getLegacyShaderMaterial(): THREE.ShaderMaterial {
|
|
288
305
|
if (!this.legacyShaderMaterial) {
|
|
289
306
|
this.legacyShaderMaterial = createLegacyBlockMaterial()
|
|
290
307
|
this.syncLegacyShaderUniforms()
|
|
@@ -292,7 +309,7 @@ export class ChunkMeshManager {
|
|
|
292
309
|
return this.legacyShaderMaterial
|
|
293
310
|
}
|
|
294
311
|
|
|
295
|
-
private getGlobalLegacyShaderMaterial
|
|
312
|
+
private getGlobalLegacyShaderMaterial(): THREE.ShaderMaterial {
|
|
296
313
|
if (!this.globalLegacyShaderMaterial) {
|
|
297
314
|
this.globalLegacyShaderMaterial = createGlobalLegacyBlockMaterial()
|
|
298
315
|
this.syncLegacyShaderUniforms()
|
|
@@ -300,18 +317,15 @@ export class ChunkMeshManager {
|
|
|
300
317
|
return this.globalLegacyShaderMaterial
|
|
301
318
|
}
|
|
302
319
|
|
|
303
|
-
private getGlobalLegacyBuffer
|
|
320
|
+
private getGlobalLegacyBuffer(): GlobalLegacyBuffer {
|
|
304
321
|
if (!this.globalLegacyBuffer) {
|
|
305
|
-
this.globalLegacyBuffer = new GlobalLegacyBuffer(
|
|
306
|
-
this.getGlobalLegacyShaderMaterial(),
|
|
307
|
-
this.scene,
|
|
308
|
-
)
|
|
322
|
+
this.globalLegacyBuffer = new GlobalLegacyBuffer(this.getGlobalLegacyShaderMaterial(), this.scene)
|
|
309
323
|
this.globalLegacyBuffer.setRenderOrigin(this.renderOrigin)
|
|
310
324
|
}
|
|
311
325
|
return this.globalLegacyBuffer
|
|
312
326
|
}
|
|
313
327
|
|
|
314
|
-
private getGlobalLegacyBlendShaderMaterial
|
|
328
|
+
private getGlobalLegacyBlendShaderMaterial(): THREE.ShaderMaterial {
|
|
315
329
|
if (!this.globalLegacyBlendShaderMaterial) {
|
|
316
330
|
this.globalLegacyBlendShaderMaterial = createGlobalLegacyBlendMaterial()
|
|
317
331
|
this.syncLegacyShaderUniforms()
|
|
@@ -319,32 +333,28 @@ export class ChunkMeshManager {
|
|
|
319
333
|
return this.globalLegacyBlendShaderMaterial
|
|
320
334
|
}
|
|
321
335
|
|
|
322
|
-
private getGlobalLegacyBlendBuffer
|
|
336
|
+
private getGlobalLegacyBlendBuffer(): GlobalLegacyBuffer {
|
|
323
337
|
if (!this.globalLegacyBlendBuffer) {
|
|
324
|
-
this.globalLegacyBlendBuffer = new GlobalLegacyBuffer(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
initialCapacityQuads: 32_000,
|
|
330
|
-
growthIncrementQuads: 32_000,
|
|
331
|
-
},
|
|
332
|
-
)
|
|
338
|
+
this.globalLegacyBlendBuffer = new GlobalLegacyBuffer(this.getGlobalLegacyBlendShaderMaterial(), this.scene, {
|
|
339
|
+
name: 'globalLegacyBlend',
|
|
340
|
+
initialCapacityQuads: 32_000,
|
|
341
|
+
growthIncrementQuads: 32_000
|
|
342
|
+
})
|
|
333
343
|
this.globalLegacyBlendBuffer.setRenderOrigin(this.renderOrigin)
|
|
334
344
|
}
|
|
335
345
|
return this.globalLegacyBlendBuffer
|
|
336
346
|
}
|
|
337
347
|
|
|
338
|
-
getRenderOrigin
|
|
348
|
+
getRenderOrigin(): Readonly<RenderOrigin> {
|
|
339
349
|
return this.renderOrigin
|
|
340
350
|
}
|
|
341
351
|
|
|
342
|
-
maybeRebase
|
|
352
|
+
maybeRebase(camera: RenderOrigin): void {
|
|
343
353
|
const R = this.renderOrigin
|
|
344
354
|
if (
|
|
345
|
-
Math.abs(camera.x - R.x) <= ChunkMeshManager.REBASE_THRESHOLD
|
|
346
|
-
|
|
347
|
-
|
|
355
|
+
Math.abs(camera.x - R.x) <= ChunkMeshManager.REBASE_THRESHOLD &&
|
|
356
|
+
Math.abs(camera.y - R.y) <= ChunkMeshManager.REBASE_THRESHOLD &&
|
|
357
|
+
Math.abs(camera.z - R.z) <= ChunkMeshManager.REBASE_THRESHOLD
|
|
348
358
|
) {
|
|
349
359
|
return
|
|
350
360
|
}
|
|
@@ -352,12 +362,12 @@ export class ChunkMeshManager {
|
|
|
352
362
|
const newOrigin: RenderOrigin = {
|
|
353
363
|
x: Math.round(camera.x / 16) * 16,
|
|
354
364
|
y: Math.round(camera.y / 16) * 16,
|
|
355
|
-
z: Math.round(camera.z / 16) * 16
|
|
365
|
+
z: Math.round(camera.z / 16) * 16
|
|
356
366
|
}
|
|
357
367
|
const delta: RenderOrigin = {
|
|
358
368
|
x: newOrigin.x - R.x,
|
|
359
369
|
y: newOrigin.y - R.y,
|
|
360
|
-
z: newOrigin.z - R.z
|
|
370
|
+
z: newOrigin.z - R.z
|
|
361
371
|
}
|
|
362
372
|
|
|
363
373
|
this.globalLegacyBuffer?.rebase(delta)
|
|
@@ -368,13 +378,7 @@ export class ChunkMeshManager {
|
|
|
368
378
|
if (!sectionKey) continue
|
|
369
379
|
const sectionObject = this.sectionObjects[sectionKey]
|
|
370
380
|
if (!sectionObject) continue
|
|
371
|
-
setupLegacySectionMatrix(
|
|
372
|
-
poolEntry.mesh,
|
|
373
|
-
sectionObject.worldX ?? 0,
|
|
374
|
-
sectionObject.worldY ?? 0,
|
|
375
|
-
sectionObject.worldZ ?? 0,
|
|
376
|
-
newOrigin,
|
|
377
|
-
)
|
|
381
|
+
setupLegacySectionMatrix(poolEntry.mesh, sectionObject.worldX ?? 0, sectionObject.worldY ?? 0, sectionObject.worldZ ?? 0, newOrigin)
|
|
378
382
|
}
|
|
379
383
|
|
|
380
384
|
this.renderOrigin = newOrigin
|
|
@@ -383,15 +387,15 @@ export class ChunkMeshManager {
|
|
|
383
387
|
}
|
|
384
388
|
|
|
385
389
|
/** Whether a section still holds a pooled legacy mesh (defer / invariant fallback). */
|
|
386
|
-
sectionUsesPooledLegacyMesh
|
|
390
|
+
sectionUsesPooledLegacyMesh(sectionKey: string): boolean {
|
|
387
391
|
return this.activeSections.has(sectionKey)
|
|
388
392
|
}
|
|
389
393
|
|
|
390
|
-
private registerLegacyCullSection
|
|
394
|
+
private registerLegacyCullSection(sectionKey: string, worldX: number, worldY: number, worldZ: number): void {
|
|
391
395
|
this.legacyCullSections.set(sectionKey, { worldX, worldY, worldZ })
|
|
392
396
|
}
|
|
393
397
|
|
|
394
|
-
private maybeUnregisterLegacyCullSection
|
|
398
|
+
private maybeUnregisterLegacyCullSection(sectionKey: string): void {
|
|
395
399
|
const inOpaque = this.globalLegacyBuffer?.hasSection(sectionKey) ?? false
|
|
396
400
|
const inBlend = this.globalLegacyBlendBuffer?.hasSection(sectionKey) ?? false
|
|
397
401
|
if (!inOpaque && !inBlend) {
|
|
@@ -399,11 +403,7 @@ export class ChunkMeshManager {
|
|
|
399
403
|
}
|
|
400
404
|
}
|
|
401
405
|
|
|
402
|
-
private updatePooledLegacyCullState
|
|
403
|
-
cameraWorldX: number,
|
|
404
|
-
cameraWorldY: number,
|
|
405
|
-
cameraWorldZ: number,
|
|
406
|
-
): void {
|
|
406
|
+
private updatePooledLegacyCullState(cameraWorldX: number, cameraWorldY: number, cameraWorldZ: number): void {
|
|
407
407
|
for (const poolEntry of this.activeSections.values()) {
|
|
408
408
|
const sectionKey = poolEntry.sectionKey
|
|
409
409
|
if (!sectionKey) continue
|
|
@@ -421,7 +421,7 @@ export class ChunkMeshManager {
|
|
|
421
421
|
this._legacyCullFrustum,
|
|
422
422
|
this._legacyCullBox,
|
|
423
423
|
this._legacyCullBoxMin,
|
|
424
|
-
this._legacyCullBoxMax
|
|
424
|
+
this._legacyCullBoxMax
|
|
425
425
|
)
|
|
426
426
|
}
|
|
427
427
|
}
|
|
@@ -429,7 +429,7 @@ export class ChunkMeshManager {
|
|
|
429
429
|
/**
|
|
430
430
|
* Shared section visibility + span groups for global legacy and cube buffers.
|
|
431
431
|
*/
|
|
432
|
-
updateSectionCullAndSort
|
|
432
|
+
updateSectionCullAndSort(camera: THREE.Camera, cameraWorldX: number, cameraWorldY: number, cameraWorldZ: number): void {
|
|
433
433
|
this._legacyCullProjScreen.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
|
|
434
434
|
this._legacyCullFrustum.setFromProjectionMatrix(this._legacyCullProjScreen)
|
|
435
435
|
|
|
@@ -449,7 +449,7 @@ export class ChunkMeshManager {
|
|
|
449
449
|
this._legacyCullFrustum,
|
|
450
450
|
this._legacyCullBox,
|
|
451
451
|
this._legacyCullBoxMin,
|
|
452
|
-
this._legacyCullBoxMax
|
|
452
|
+
this._legacyCullBoxMax
|
|
453
453
|
)
|
|
454
454
|
if (inFrustum) {
|
|
455
455
|
visible.push({ key: sectionKey, distSq })
|
|
@@ -471,7 +471,7 @@ export class ChunkMeshManager {
|
|
|
471
471
|
const blendKeys = blendVisible.map(v => v.key)
|
|
472
472
|
|
|
473
473
|
const cubeVisibleKeys: string[] = []
|
|
474
|
-
const visibleSlots: Array<{ start: number
|
|
474
|
+
const visibleSlots: Array<{ start: number; count: number }> = []
|
|
475
475
|
if (gb) {
|
|
476
476
|
gb.forEachSectionSlot((key, slot) => {
|
|
477
477
|
const sectionObject = this.sectionObjects[key]
|
|
@@ -491,15 +491,16 @@ export class ChunkMeshManager {
|
|
|
491
491
|
this._legacyCullFrustum,
|
|
492
492
|
this._legacyCullBox,
|
|
493
493
|
this._legacyCullBoxMin,
|
|
494
|
-
this._legacyCullBoxMax
|
|
494
|
+
this._legacyCullBoxMax
|
|
495
495
|
)
|
|
496
496
|
if (!inFrustum) {
|
|
497
497
|
return
|
|
498
498
|
}
|
|
499
499
|
cubeVisibleKeys.push(key)
|
|
500
500
|
const drawStart = gb.getSectionDrawStart(key)
|
|
501
|
-
|
|
502
|
-
|
|
501
|
+
const drawCount = gb.getSectionDrawCount(key)
|
|
502
|
+
if (drawStart !== undefined && drawCount !== undefined) {
|
|
503
|
+
visibleSlots.push({ start: drawStart, count: drawCount })
|
|
503
504
|
}
|
|
504
505
|
})
|
|
505
506
|
}
|
|
@@ -512,9 +513,12 @@ export class ChunkMeshManager {
|
|
|
512
513
|
opaqueBuf?.getLayoutVersion() ?? 0,
|
|
513
514
|
blendBuf?.getLayoutVersion() ?? 0,
|
|
514
515
|
gb?.getLayoutVersion() ?? 0,
|
|
516
|
+
opaqueBuf?.getUploadEpoch() ?? 0,
|
|
517
|
+
blendBuf?.getUploadEpoch() ?? 0,
|
|
518
|
+
gb?.getUploadEpoch() ?? 0
|
|
515
519
|
].join('|')
|
|
516
520
|
|
|
517
|
-
if (fingerprint === this._lastCullFingerprint) {
|
|
521
|
+
if (fingerprint === this._lastCullFingerprint && !this.hasPendingBufferWork()) {
|
|
518
522
|
this.updatePooledLegacyCullState(cameraWorldX, cameraWorldY, cameraWorldZ)
|
|
519
523
|
return
|
|
520
524
|
}
|
|
@@ -524,19 +528,53 @@ export class ChunkMeshManager {
|
|
|
524
528
|
blendBuf?.updateDrawSpans(visible, 'sortedBlend')
|
|
525
529
|
|
|
526
530
|
if (gb) {
|
|
527
|
-
const spans = buildVisibleCubeSpans(
|
|
531
|
+
const spans = buildVisibleCubeSpans(
|
|
532
|
+
visibleSlots,
|
|
533
|
+
gb.getHighWatermark(),
|
|
534
|
+
gb.canUseFullDrawShortcut(),
|
|
535
|
+
(start, end) => gb.isRangeFullyUploaded(start, end),
|
|
536
|
+
gb.getPendingDirtyRanges()
|
|
537
|
+
)
|
|
528
538
|
gb.setVisibleSpans(spans)
|
|
529
539
|
}
|
|
530
540
|
|
|
541
|
+
this.lastBufferStateKey = this.bufferStateKey()
|
|
531
542
|
this.updatePooledLegacyCullState(cameraWorldX, cameraWorldY, cameraWorldZ)
|
|
532
543
|
}
|
|
533
544
|
|
|
534
|
-
|
|
545
|
+
private bufferStateKey(): string {
|
|
546
|
+
const b = this.globalBlockBuffer
|
|
547
|
+
const o = this.globalLegacyBuffer
|
|
548
|
+
const bl = this.globalLegacyBlendBuffer
|
|
549
|
+
return [
|
|
550
|
+
o?.getLayoutVersion() ?? 0,
|
|
551
|
+
o?.getUploadEpoch() ?? 0,
|
|
552
|
+
bl?.getLayoutVersion() ?? 0,
|
|
553
|
+
bl?.getUploadEpoch() ?? 0,
|
|
554
|
+
b?.getLayoutVersion() ?? 0,
|
|
555
|
+
b?.getUploadEpoch() ?? 0
|
|
556
|
+
].join('|')
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** Mark cull dirty when any buffer's layout or upload state changed since the last cull. */
|
|
560
|
+
markCullDirtyIfBufferStateChanged(): void {
|
|
561
|
+
const key = this.bufferStateKey()
|
|
562
|
+
if (key !== this.lastBufferStateKey) {
|
|
563
|
+
this.markCullDirty()
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
markCullDirty(): void {
|
|
535
568
|
this.cullDirty = true
|
|
536
569
|
}
|
|
537
570
|
|
|
571
|
+
hasPendingBufferWork(): boolean {
|
|
572
|
+
const buffers = [this.globalLegacyBuffer, this.globalLegacyBlendBuffer, this.globalBlockBuffer]
|
|
573
|
+
return buffers.some(b => b != null && (b.hasPendingUploads() || b.hasPendingReplace() || b.getPendingMove() != null))
|
|
574
|
+
}
|
|
575
|
+
|
|
538
576
|
/** Compare camera pose; mark cull dirty when position or rotation changed. */
|
|
539
|
-
updateCullDirtyFromCamera
|
|
577
|
+
updateCullDirtyFromCamera(camera: THREE.Camera, cameraWorldX: number, cameraWorldY: number, cameraWorldZ: number): void {
|
|
540
578
|
camera.getWorldQuaternion(this._cullViewQuat)
|
|
541
579
|
if (!this._cullCamInitialized) {
|
|
542
580
|
this._lastCullCamPos.set(cameraWorldX, cameraWorldY, cameraWorldZ)
|
|
@@ -545,10 +583,7 @@ export class ChunkMeshManager {
|
|
|
545
583
|
this.cullDirty = true
|
|
546
584
|
return
|
|
547
585
|
}
|
|
548
|
-
const posChanged =
|
|
549
|
-
this._lastCullCamPos.x !== cameraWorldX ||
|
|
550
|
-
this._lastCullCamPos.y !== cameraWorldY ||
|
|
551
|
-
this._lastCullCamPos.z !== cameraWorldZ
|
|
586
|
+
const posChanged = this._lastCullCamPos.x !== cameraWorldX || this._lastCullCamPos.y !== cameraWorldY || this._lastCullCamPos.z !== cameraWorldZ
|
|
552
587
|
const quatChanged =
|
|
553
588
|
this._lastCullCamQuat.x !== this._cullViewQuat.x ||
|
|
554
589
|
this._lastCullCamQuat.y !== this._cullViewQuat.y ||
|
|
@@ -561,11 +596,11 @@ export class ChunkMeshManager {
|
|
|
561
596
|
}
|
|
562
597
|
}
|
|
563
598
|
|
|
564
|
-
clearCullDirty
|
|
599
|
+
clearCullDirty(): void {
|
|
565
600
|
this.cullDirty = false
|
|
566
601
|
}
|
|
567
602
|
|
|
568
|
-
setLegacyCameraOrigin
|
|
603
|
+
setLegacyCameraOrigin(x: number, y: number, z: number): void {
|
|
569
604
|
const R = this.renderOrigin
|
|
570
605
|
setLegacyCameraOrigin(this.getLegacyShaderMaterial(), R, x, y, z)
|
|
571
606
|
setLegacyCameraOrigin(this.getGlobalLegacyShaderMaterial(), R, x, y, z)
|
|
@@ -592,7 +627,7 @@ export class ChunkMeshManager {
|
|
|
592
627
|
}
|
|
593
628
|
}
|
|
594
629
|
|
|
595
|
-
private getCubeShaderMaterial
|
|
630
|
+
private getCubeShaderMaterial(): THREE.ShaderMaterial | null {
|
|
596
631
|
if (!this.isShaderCubesGpuEnabled()) return null
|
|
597
632
|
if (!this.cubeShaderMaterial) {
|
|
598
633
|
this.cubeShaderMaterial = createCubeBlockMaterial()
|
|
@@ -603,7 +638,7 @@ export class ChunkMeshManager {
|
|
|
603
638
|
return this.cubeShaderMaterial
|
|
604
639
|
}
|
|
605
640
|
|
|
606
|
-
private getGlobalBlockBuffer
|
|
641
|
+
private getGlobalBlockBuffer(): GlobalBlockBuffer | null {
|
|
607
642
|
const mat = this.getCubeShaderMaterial()
|
|
608
643
|
if (!mat) return null
|
|
609
644
|
if (!this.globalBlockBuffer) {
|
|
@@ -612,12 +647,12 @@ export class ChunkMeshManager {
|
|
|
612
647
|
return this.globalBlockBuffer
|
|
613
648
|
}
|
|
614
649
|
|
|
615
|
-
private shouldDeferLegacyOpaqueToPerSection
|
|
650
|
+
private shouldDeferLegacyOpaqueToPerSection(sectionKey: string): boolean {
|
|
616
651
|
return this.shouldDeferShaderToPerSection(sectionKey)
|
|
617
652
|
}
|
|
618
653
|
|
|
619
654
|
/** Sci-fi reveal keeps geometry off global buffers until the section finishes reveal. */
|
|
620
|
-
private shouldDeferShaderToPerSection
|
|
655
|
+
private shouldDeferShaderToPerSection(sectionKey: string): boolean {
|
|
621
656
|
const sciFi = this.worldRenderer.getModule<{
|
|
622
657
|
shouldDeferSectionGeometry?: (key: string) => boolean
|
|
623
658
|
}>('futuristicReveal')
|
|
@@ -627,7 +662,7 @@ export class ChunkMeshManager {
|
|
|
627
662
|
/**
|
|
628
663
|
* Move deferred per-section shader cubes into the global buffer after reveal completes.
|
|
629
664
|
*/
|
|
630
|
-
migrateDeferredShaderToGlobal
|
|
665
|
+
migrateDeferredShaderToGlobal(sectionKey: string): void {
|
|
631
666
|
const section = this.sectionObjects[sectionKey]
|
|
632
667
|
if (!section?.deferredShaderCubes) return
|
|
633
668
|
|
|
@@ -660,7 +695,7 @@ export class ChunkMeshManager {
|
|
|
660
695
|
/**
|
|
661
696
|
* Move deferred per-section opaque legacy into the global buffer after reveal completes.
|
|
662
697
|
*/
|
|
663
|
-
migrateDeferredLegacyToGlobal
|
|
698
|
+
migrateDeferredLegacyToGlobal(sectionKey: string): void {
|
|
664
699
|
const section = this.sectionObjects[sectionKey]
|
|
665
700
|
if (!section) return
|
|
666
701
|
|
|
@@ -670,13 +705,7 @@ export class ChunkMeshManager {
|
|
|
670
705
|
const wy = section.worldY
|
|
671
706
|
const wz = section.worldZ
|
|
672
707
|
if (wx !== undefined && wy !== undefined && wz !== undefined) {
|
|
673
|
-
const added = this.getGlobalLegacyBuffer().addSection(
|
|
674
|
-
sectionKey,
|
|
675
|
-
{ positions, colors, skyLights, blockLights, uvs, indices },
|
|
676
|
-
wx,
|
|
677
|
-
wy,
|
|
678
|
-
wz,
|
|
679
|
-
)
|
|
708
|
+
const added = this.getGlobalLegacyBuffer().addSection(sectionKey, { positions, colors, skyLights, blockLights, uvs, indices }, wx, wy, wz)
|
|
680
709
|
if (added) {
|
|
681
710
|
this.registerLegacyCullSection(sectionKey, wx, wy, wz)
|
|
682
711
|
}
|
|
@@ -690,13 +719,7 @@ export class ChunkMeshManager {
|
|
|
690
719
|
const wy = section.worldY
|
|
691
720
|
const wz = section.worldZ
|
|
692
721
|
if (wx !== undefined && wy !== undefined && wz !== undefined) {
|
|
693
|
-
const added = this.getGlobalLegacyBlendBuffer().addSection(
|
|
694
|
-
sectionKey,
|
|
695
|
-
{ positions, colors, skyLights, blockLights, uvs, indices },
|
|
696
|
-
wx,
|
|
697
|
-
wy,
|
|
698
|
-
wz,
|
|
699
|
-
)
|
|
722
|
+
const added = this.getGlobalLegacyBlendBuffer().addSection(sectionKey, { positions, colors, skyLights, blockLights, uvs, indices }, wx, wy, wz)
|
|
700
723
|
if (added) {
|
|
701
724
|
this.registerLegacyCullSection(sectionKey, wx, wy, wz)
|
|
702
725
|
}
|
|
@@ -709,17 +732,13 @@ export class ChunkMeshManager {
|
|
|
709
732
|
const hadLegacyAsPrimary = section.mesh === this.activeSections.get(sectionKey)?.mesh
|
|
710
733
|
this.releasePooledMesh(sectionKey)
|
|
711
734
|
if (hadLegacyAsPrimary) {
|
|
712
|
-
section.mesh = section.shaderMesh as unknown as THREE.Mesh<THREE.BufferGeometry, THREE.Material> | undefined ?? undefined
|
|
735
|
+
section.mesh = (section.shaderMesh as unknown as THREE.Mesh<THREE.BufferGeometry, THREE.Material> | undefined) ?? undefined
|
|
713
736
|
}
|
|
714
737
|
}
|
|
715
738
|
this.markCullDirty()
|
|
716
739
|
}
|
|
717
740
|
|
|
718
|
-
raycastGlobalLegacySections
|
|
719
|
-
raycaster: THREE.Raycaster,
|
|
720
|
-
origin: THREE.Vector3,
|
|
721
|
-
maxCenterDistance: number,
|
|
722
|
-
): number | undefined {
|
|
741
|
+
raycastGlobalLegacySections(raycaster: THREE.Raycaster, origin: THREE.Vector3, maxCenterDistance: number): number | undefined {
|
|
723
742
|
const maxDistSq = maxCenterDistance * maxCenterDistance
|
|
724
743
|
const dirX = raycaster.ray.direction.x
|
|
725
744
|
const dirY = raycaster.ray.direction.y
|
|
@@ -734,19 +753,8 @@ export class ChunkMeshManager {
|
|
|
734
753
|
const dy = (section.worldY ?? 0) - origin.y
|
|
735
754
|
const dz = (section.worldZ ?? 0) - origin.z
|
|
736
755
|
if (dx * dx + dy * dy + dz * dz > maxDistSq) continue
|
|
737
|
-
if (!sectionAabbIntersectsRay(
|
|
738
|
-
|
|
739
|
-
section.worldY ?? 0,
|
|
740
|
-
section.worldZ ?? 0,
|
|
741
|
-
origin.x,
|
|
742
|
-
origin.y,
|
|
743
|
-
origin.z,
|
|
744
|
-
dirX,
|
|
745
|
-
dirY,
|
|
746
|
-
dirZ,
|
|
747
|
-
far,
|
|
748
|
-
halfExtent,
|
|
749
|
-
)) continue
|
|
756
|
+
if (!sectionAabbIntersectsRay(section.worldX, section.worldY ?? 0, section.worldZ ?? 0, origin.x, origin.y, origin.z, dirX, dirY, dirZ, far, halfExtent))
|
|
757
|
+
continue
|
|
750
758
|
candidates.push(key)
|
|
751
759
|
}
|
|
752
760
|
|
|
@@ -759,13 +767,13 @@ export class ChunkMeshManager {
|
|
|
759
767
|
return hits[0]?.distance
|
|
760
768
|
}
|
|
761
769
|
|
|
762
|
-
registerShaderSectionRaycastBox
|
|
770
|
+
registerShaderSectionRaycastBox(
|
|
763
771
|
sectionKey: string,
|
|
764
772
|
words: Uint32Array,
|
|
765
773
|
faceCount: number,
|
|
766
774
|
sectionCenterX: number,
|
|
767
775
|
sectionCenterY: number,
|
|
768
|
-
sectionCenterZ: number
|
|
776
|
+
sectionCenterZ: number
|
|
769
777
|
): void {
|
|
770
778
|
const box = computeShaderSectionRaycastAabb(words, faceCount, sectionCenterX, sectionCenterY, sectionCenterZ)
|
|
771
779
|
if (box) {
|
|
@@ -773,24 +781,19 @@ export class ChunkMeshManager {
|
|
|
773
781
|
box,
|
|
774
782
|
sectionCenterX,
|
|
775
783
|
sectionCenterY,
|
|
776
|
-
sectionCenterZ
|
|
784
|
+
sectionCenterZ
|
|
777
785
|
})
|
|
778
786
|
} else {
|
|
779
787
|
this.shaderSectionRaycastBoxes.delete(sectionKey)
|
|
780
788
|
}
|
|
781
789
|
}
|
|
782
790
|
|
|
783
|
-
unregisterShaderSectionRaycastBox
|
|
791
|
+
unregisterShaderSectionRaycastBox(sectionKey: string): void {
|
|
784
792
|
this.shaderSectionRaycastBoxes.delete(sectionKey)
|
|
785
793
|
}
|
|
786
794
|
|
|
787
795
|
/** Closest hit against registered shader-cube AABBs (world-space ray). */
|
|
788
|
-
raycastShaderSectionAABBs
|
|
789
|
-
originWorld: THREE.Vector3,
|
|
790
|
-
direction: THREE.Vector3,
|
|
791
|
-
maxDist: number,
|
|
792
|
-
maxCenterDistance = 80,
|
|
793
|
-
): number | undefined {
|
|
796
|
+
raycastShaderSectionAABBs(originWorld: THREE.Vector3, direction: THREE.Vector3, maxDist: number, maxCenterDistance = 80): number | undefined {
|
|
794
797
|
const ox = originWorld.x
|
|
795
798
|
const oy = originWorld.y
|
|
796
799
|
const oz = originWorld.z
|
|
@@ -818,11 +821,7 @@ export class ChunkMeshManager {
|
|
|
818
821
|
const dcz = box.cz - oz
|
|
819
822
|
if (dcx * dcx + dcy * dcy + dcz * dcz > maxCenterDistSq) continue
|
|
820
823
|
|
|
821
|
-
let t = raycastAabb(
|
|
822
|
-
ox, oy, oz, dx, dy, dz,
|
|
823
|
-
box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ,
|
|
824
|
-
closest,
|
|
825
|
-
)
|
|
824
|
+
let t = raycastAabb(ox, oy, oz, dx, dy, dz, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, closest)
|
|
826
825
|
if (t === undefined && isPointInsideAabb(ox, oy, oz, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ)) {
|
|
827
826
|
const gb = this.globalBlockBuffer
|
|
828
827
|
const slot = gb?.getSectionSlot(key)
|
|
@@ -835,10 +834,15 @@ export class ChunkMeshManager {
|
|
|
835
834
|
entry.sectionCenterX,
|
|
836
835
|
entry.sectionCenterY,
|
|
837
836
|
entry.sectionCenterZ,
|
|
838
|
-
ox,
|
|
837
|
+
ox,
|
|
838
|
+
oy,
|
|
839
|
+
oz,
|
|
840
|
+
dx,
|
|
841
|
+
dy,
|
|
842
|
+
dz,
|
|
839
843
|
closest,
|
|
840
844
|
this.blockRaycastVisitGen,
|
|
841
|
-
this.blockRaycastVisitStamp
|
|
845
|
+
this.blockRaycastVisitStamp
|
|
842
846
|
)
|
|
843
847
|
} else {
|
|
844
848
|
const def = this.sectionObjects[key]?.deferredShaderCubes
|
|
@@ -851,10 +855,15 @@ export class ChunkMeshManager {
|
|
|
851
855
|
entry.sectionCenterX,
|
|
852
856
|
entry.sectionCenterY,
|
|
853
857
|
entry.sectionCenterZ,
|
|
854
|
-
ox,
|
|
858
|
+
ox,
|
|
859
|
+
oy,
|
|
860
|
+
oz,
|
|
861
|
+
dx,
|
|
862
|
+
dy,
|
|
863
|
+
dz,
|
|
855
864
|
closest,
|
|
856
865
|
this.blockRaycastVisitGen,
|
|
857
|
-
this.blockRaycastVisitStamp
|
|
866
|
+
this.blockRaycastVisitStamp
|
|
858
867
|
)
|
|
859
868
|
}
|
|
860
869
|
}
|
|
@@ -871,12 +880,12 @@ export class ChunkMeshManager {
|
|
|
871
880
|
/**
|
|
872
881
|
* Update or create a section with new geometry data
|
|
873
882
|
*/
|
|
874
|
-
private uploadLegacyPooledMesh
|
|
883
|
+
private uploadLegacyPooledMesh(
|
|
875
884
|
poolEntry: ChunkMeshPool,
|
|
876
885
|
geometryData: MesherGeometryOutput | MesherGeometryOutput['blend'],
|
|
877
886
|
sx: number,
|
|
878
887
|
sy: number,
|
|
879
|
-
sz: number
|
|
888
|
+
sz: number
|
|
880
889
|
): THREE.Mesh<THREE.BufferGeometry, THREE.Material> {
|
|
881
890
|
const { mesh } = poolEntry
|
|
882
891
|
const geo = geometryData!
|
|
@@ -887,14 +896,8 @@ export class ChunkMeshManager {
|
|
|
887
896
|
this.updateGeometryAttribute(mesh.geometry, 'a_blockLight', geo.blockLights, 1)
|
|
888
897
|
this.updateGeometryAttribute(mesh.geometry, 'uv', geo.uvs, 2)
|
|
889
898
|
mesh.geometry.index = new THREE.BufferAttribute(geo.indices as Uint32Array | Uint16Array, 1)
|
|
890
|
-
mesh.geometry.boundingBox = new THREE.Box3(
|
|
891
|
-
|
|
892
|
-
new THREE.Vector3(8, 8, 8),
|
|
893
|
-
)
|
|
894
|
-
mesh.geometry.boundingSphere = new THREE.Sphere(
|
|
895
|
-
new THREE.Vector3(0, 0, 0),
|
|
896
|
-
Math.sqrt(3 * 8 ** 2),
|
|
897
|
-
)
|
|
899
|
+
mesh.geometry.boundingBox = new THREE.Box3(new THREE.Vector3(-8, -8, -8), new THREE.Vector3(8, 8, 8))
|
|
900
|
+
mesh.geometry.boundingSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), Math.sqrt(3 * 8 ** 2))
|
|
898
901
|
setupLegacySectionMatrix(mesh, sx, sy, sz, this.renderOrigin)
|
|
899
902
|
mesh.visible = false
|
|
900
903
|
mesh.name = 'mesh'
|
|
@@ -902,7 +905,7 @@ export class ChunkMeshManager {
|
|
|
902
905
|
return mesh as THREE.Mesh<THREE.BufferGeometry, THREE.Material>
|
|
903
906
|
}
|
|
904
907
|
|
|
905
|
-
private acquirePooledSectionMesh
|
|
908
|
+
private acquirePooledSectionMesh(sectionKey: string): ChunkMeshPool | null {
|
|
906
909
|
let poolEntry = this.activeSections.get(sectionKey)
|
|
907
910
|
if (!poolEntry) {
|
|
908
911
|
poolEntry = this.acquireMesh()
|
|
@@ -916,12 +919,18 @@ export class ChunkMeshManager {
|
|
|
916
919
|
return poolEntry
|
|
917
920
|
}
|
|
918
921
|
|
|
919
|
-
updateSection
|
|
922
|
+
updateSection(sectionKey: string, geometryData: MesherGeometryOutput): SectionObject | null {
|
|
920
923
|
const hasOpaque = geometryData.positions.length > 0
|
|
921
924
|
const hasBlend = (geometryData.blend?.positions.length ?? 0) > 0
|
|
922
925
|
const hasLegacy = hasOpaque || hasBlend
|
|
923
926
|
const shaderData = geometryData.shaderCubes
|
|
924
927
|
const hasShader = this.isShaderCubesGpuEnabled() && (shaderData?.count ?? 0) > 0
|
|
928
|
+
const deferOpaque = hasOpaque && this.shouldDeferLegacyOpaqueToPerSection(sectionKey)
|
|
929
|
+
const deferBlend = hasBlend && this.shouldDeferLegacyOpaqueToPerSection(sectionKey)
|
|
930
|
+
const deferShader = hasShader && this.shouldDeferShaderToPerSection(sectionKey)
|
|
931
|
+
const willAddOpaqueGlobal = hasOpaque && !deferOpaque
|
|
932
|
+
const willAddBlendGlobal = hasBlend && !deferBlend
|
|
933
|
+
const willAddCubeGlobal = hasShader && !!shaderData && !deferShader
|
|
925
934
|
|
|
926
935
|
if (!hasLegacy && !hasShader) {
|
|
927
936
|
this.releaseSection(sectionKey)
|
|
@@ -930,10 +939,19 @@ export class ChunkMeshManager {
|
|
|
930
939
|
|
|
931
940
|
// Remove existing section object from scene if it exists
|
|
932
941
|
let sectionObject = this.sectionObjects[sectionKey]
|
|
942
|
+
const wasRemesh = sectionObject != null
|
|
933
943
|
if (sectionObject) {
|
|
934
944
|
this.cleanupSection(sectionKey, { forRemesh: true })
|
|
935
945
|
}
|
|
936
946
|
|
|
947
|
+
if (wasRemesh) {
|
|
948
|
+
if (!willAddCubeGlobal) this.globalBlockBuffer?.removeSection(sectionKey)
|
|
949
|
+
if (!willAddOpaqueGlobal) this.globalLegacyBuffer?.removeSection(sectionKey)
|
|
950
|
+
if (!willAddBlendGlobal) this.globalLegacyBlendBuffer?.removeSection(sectionKey)
|
|
951
|
+
if (!(hasShader && shaderData)) this.unregisterShaderSectionRaycastBox(sectionKey)
|
|
952
|
+
if (!willAddOpaqueGlobal && !willAddBlendGlobal) this.maybeUnregisterLegacyCullSection(sectionKey)
|
|
953
|
+
}
|
|
954
|
+
|
|
937
955
|
if (!hasBlend) {
|
|
938
956
|
this.releasePooledMesh(sectionKey)
|
|
939
957
|
}
|
|
@@ -950,9 +968,8 @@ export class ChunkMeshManager {
|
|
|
950
968
|
skyLights: geometryData.skyLights as Float32Array,
|
|
951
969
|
blockLights: geometryData.blockLights as Float32Array,
|
|
952
970
|
uvs: geometryData.uvs as Float32Array,
|
|
953
|
-
indices: geometryData.indices as Uint32Array | Uint16Array
|
|
971
|
+
indices: geometryData.indices as Uint32Array | Uint16Array
|
|
954
972
|
}
|
|
955
|
-
const deferOpaque = this.shouldDeferLegacyOpaqueToPerSection(sectionKey)
|
|
956
973
|
if (deferOpaque) {
|
|
957
974
|
deferredLegacyOpaque = {
|
|
958
975
|
positions: new Float32Array(opaqueGeo.positions),
|
|
@@ -960,9 +977,7 @@ export class ChunkMeshManager {
|
|
|
960
977
|
skyLights: new Float32Array(opaqueGeo.skyLights),
|
|
961
978
|
blockLights: new Float32Array(opaqueGeo.blockLights),
|
|
962
979
|
uvs: new Float32Array(opaqueGeo.uvs),
|
|
963
|
-
indices: opaqueGeo.indices instanceof Uint32Array
|
|
964
|
-
? new Uint32Array(opaqueGeo.indices)
|
|
965
|
-
: new Uint16Array(opaqueGeo.indices),
|
|
980
|
+
indices: opaqueGeo.indices instanceof Uint32Array ? new Uint32Array(opaqueGeo.indices) : new Uint16Array(opaqueGeo.indices)
|
|
966
981
|
}
|
|
967
982
|
if (!hasBlend) {
|
|
968
983
|
const poolEntry = this.acquirePooledSectionMesh(sectionKey)
|
|
@@ -970,13 +985,7 @@ export class ChunkMeshManager {
|
|
|
970
985
|
legacyMesh = this.uploadLegacyPooledMesh(poolEntry, geometryData, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
971
986
|
}
|
|
972
987
|
} else {
|
|
973
|
-
const added = this.getGlobalLegacyBuffer().addSection(
|
|
974
|
-
sectionKey,
|
|
975
|
-
opaqueGeo,
|
|
976
|
-
geometryData.sx,
|
|
977
|
-
geometryData.sy,
|
|
978
|
-
geometryData.sz,
|
|
979
|
-
)
|
|
988
|
+
const added = this.getGlobalLegacyBuffer().addSection(sectionKey, opaqueGeo, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
980
989
|
if (added) {
|
|
981
990
|
this.registerLegacyCullSection(sectionKey, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
982
991
|
} else {
|
|
@@ -994,9 +1003,8 @@ export class ChunkMeshManager {
|
|
|
994
1003
|
skyLights: geometryData.blend.skyLights as Float32Array,
|
|
995
1004
|
blockLights: geometryData.blend.blockLights as Float32Array,
|
|
996
1005
|
uvs: geometryData.blend.uvs as Float32Array,
|
|
997
|
-
indices: geometryData.blend.indices as Uint32Array | Uint16Array
|
|
1006
|
+
indices: geometryData.blend.indices as Uint32Array | Uint16Array
|
|
998
1007
|
}
|
|
999
|
-
const deferBlend = this.shouldDeferLegacyOpaqueToPerSection(sectionKey)
|
|
1000
1008
|
if (deferBlend) {
|
|
1001
1009
|
deferredLegacyBlend = {
|
|
1002
1010
|
positions: new Float32Array(blendGeo.positions),
|
|
@@ -1004,42 +1012,22 @@ export class ChunkMeshManager {
|
|
|
1004
1012
|
skyLights: new Float32Array(blendGeo.skyLights),
|
|
1005
1013
|
blockLights: new Float32Array(blendGeo.blockLights),
|
|
1006
1014
|
uvs: new Float32Array(blendGeo.uvs),
|
|
1007
|
-
indices: blendGeo.indices instanceof Uint32Array
|
|
1008
|
-
? new Uint32Array(blendGeo.indices)
|
|
1009
|
-
: new Uint16Array(blendGeo.indices),
|
|
1015
|
+
indices: blendGeo.indices instanceof Uint32Array ? new Uint32Array(blendGeo.indices) : new Uint16Array(blendGeo.indices)
|
|
1010
1016
|
}
|
|
1011
1017
|
const poolEntry = this.acquirePooledSectionMesh(sectionKey)
|
|
1012
1018
|
if (!poolEntry) return null
|
|
1013
|
-
const blendMesh = this.uploadLegacyPooledMesh(
|
|
1014
|
-
poolEntry,
|
|
1015
|
-
geometryData.blend,
|
|
1016
|
-
geometryData.sx,
|
|
1017
|
-
geometryData.sy,
|
|
1018
|
-
geometryData.sz,
|
|
1019
|
-
)
|
|
1019
|
+
const blendMesh = this.uploadLegacyPooledMesh(poolEntry, geometryData.blend, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
1020
1020
|
legacyMesh = legacyMesh ?? blendMesh
|
|
1021
1021
|
hasBlendMesh = true
|
|
1022
1022
|
} else {
|
|
1023
|
-
const added = this.getGlobalLegacyBlendBuffer().addSection(
|
|
1024
|
-
sectionKey,
|
|
1025
|
-
blendGeo,
|
|
1026
|
-
geometryData.sx,
|
|
1027
|
-
geometryData.sy,
|
|
1028
|
-
geometryData.sz,
|
|
1029
|
-
)
|
|
1023
|
+
const added = this.getGlobalLegacyBlendBuffer().addSection(sectionKey, blendGeo, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
1030
1024
|
if (added) {
|
|
1031
1025
|
this.registerLegacyCullSection(sectionKey, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
1032
1026
|
} else {
|
|
1033
1027
|
console.warn(`ChunkMeshManager: blend invariant violation for section ${sectionKey}, using pooled mesh fallback`)
|
|
1034
1028
|
const poolEntry = this.acquirePooledSectionMesh(sectionKey)
|
|
1035
1029
|
if (!poolEntry) return null
|
|
1036
|
-
const blendMesh = this.uploadLegacyPooledMesh(
|
|
1037
|
-
poolEntry,
|
|
1038
|
-
geometryData.blend,
|
|
1039
|
-
geometryData.sx,
|
|
1040
|
-
geometryData.sy,
|
|
1041
|
-
geometryData.sz,
|
|
1042
|
-
)
|
|
1030
|
+
const blendMesh = this.uploadLegacyPooledMesh(poolEntry, geometryData.blend, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
1043
1031
|
legacyMesh = legacyMesh ?? blendMesh
|
|
1044
1032
|
hasBlendMesh = true
|
|
1045
1033
|
}
|
|
@@ -1048,7 +1036,6 @@ export class ChunkMeshManager {
|
|
|
1048
1036
|
|
|
1049
1037
|
const cubeMaterial = hasShader ? this.getCubeShaderMaterial() : null
|
|
1050
1038
|
let shaderMesh: THREE.Mesh<THREE.InstancedBufferGeometry, THREE.ShaderMaterial> | undefined
|
|
1051
|
-
const deferShader = hasShader && this.shouldDeferShaderToPerSection(sectionKey)
|
|
1052
1039
|
if (hasShader && shaderData) {
|
|
1053
1040
|
if (deferShader && cubeMaterial) {
|
|
1054
1041
|
shaderMesh = createShaderCubeMesh(shaderData, cubeMaterial)
|
|
@@ -1069,7 +1056,7 @@ export class ChunkMeshManager {
|
|
|
1069
1056
|
if (shaderData) {
|
|
1070
1057
|
sectionObject.deferredShaderCubes = {
|
|
1071
1058
|
words: shaderData.words,
|
|
1072
|
-
count: shaderData.count
|
|
1059
|
+
count: shaderData.count
|
|
1073
1060
|
}
|
|
1074
1061
|
}
|
|
1075
1062
|
if (!sectionObject.mesh) {
|
|
@@ -1083,14 +1070,7 @@ export class ChunkMeshManager {
|
|
|
1083
1070
|
sectionObject.deferredLegacyBlend = deferredLegacyBlend
|
|
1084
1071
|
}
|
|
1085
1072
|
if (hasShader && shaderData) {
|
|
1086
|
-
this.registerShaderSectionRaycastBox(
|
|
1087
|
-
sectionKey,
|
|
1088
|
-
shaderData.words,
|
|
1089
|
-
shaderData.count,
|
|
1090
|
-
geometryData.sx,
|
|
1091
|
-
geometryData.sy,
|
|
1092
|
-
geometryData.sz,
|
|
1093
|
-
)
|
|
1073
|
+
this.registerShaderSectionRaycastBox(sectionKey, shaderData.words, shaderData.count, geometryData.sx, geometryData.sy, geometryData.sz)
|
|
1094
1074
|
}
|
|
1095
1075
|
|
|
1096
1076
|
let tilesCount = 0
|
|
@@ -1165,20 +1145,12 @@ export class ChunkMeshManager {
|
|
|
1165
1145
|
const bannerTexture = getBannerTexture(this.worldRenderer, blockName, nbt.simplify(bannerBlockEntity))
|
|
1166
1146
|
if (!bannerTexture) continue
|
|
1167
1147
|
const skyLevel = this.blockEntityLightRegistry.getSkyLevel()
|
|
1168
|
-
const banner = createBannerMesh(
|
|
1169
|
-
new Vec3(+x, +y, +z),
|
|
1170
|
-
rotation,
|
|
1171
|
-
isWall,
|
|
1172
|
-
bannerTexture,
|
|
1173
|
-
blockLightNorm,
|
|
1174
|
-
skyLightNorm,
|
|
1175
|
-
skyLevel,
|
|
1176
|
-
)
|
|
1148
|
+
const banner = createBannerMesh(new Vec3(+x, +y, +z), rotation, isWall, bannerTexture, blockLightNorm, skyLightNorm, skyLevel)
|
|
1177
1149
|
if (banner.bannerMaterial) {
|
|
1178
1150
|
this.blockEntityLightRegistry.register({
|
|
1179
1151
|
material: banner.bannerMaterial,
|
|
1180
1152
|
blockLightNorm,
|
|
1181
|
-
skyLightNorm
|
|
1153
|
+
skyLightNorm
|
|
1182
1154
|
})
|
|
1183
1155
|
}
|
|
1184
1156
|
const { x: bwx, y: bwy, z: bwz } = banner.position
|
|
@@ -1212,8 +1184,7 @@ export class ChunkMeshManager {
|
|
|
1212
1184
|
// setting so the near-first reveal gate has sections to hold.
|
|
1213
1185
|
const chunkCoords = sectionKey.split(',')
|
|
1214
1186
|
const chunkKey = `${chunkCoords[0]},${chunkCoords[2]}`
|
|
1215
|
-
const renderByChunks = !!this.worldRenderer.displayOptions
|
|
1216
|
-
?.inWorldRenderingConfig?._renderByChunks
|
|
1187
|
+
const renderByChunks = !!this.worldRenderer.displayOptions?.inWorldRenderingConfig?._renderByChunks
|
|
1217
1188
|
const forceBatchForWasm = !!this.worldRenderer.worldRendererConfig?.wasmMesher
|
|
1218
1189
|
if ((renderByChunks || forceBatchForWasm) && !this.worldRenderer.finishedChunks[chunkKey]) {
|
|
1219
1190
|
sectionObject.visible = false
|
|
@@ -1234,7 +1205,7 @@ export class ChunkMeshManager {
|
|
|
1234
1205
|
* reveal is deferred (parked in `pendingNearReveal`) and re-checked on
|
|
1235
1206
|
* the next chunkFinished / player-move / grace-expiry.
|
|
1236
1207
|
*/
|
|
1237
|
-
finishChunkDisplay
|
|
1208
|
+
finishChunkDisplay(chunkKey: string): void {
|
|
1238
1209
|
const sectionKeys = this.waitingChunksToDisplay[chunkKey]
|
|
1239
1210
|
if (!sectionKeys) {
|
|
1240
1211
|
// No held sections (empty column / non-batched path) — but the
|
|
@@ -1253,7 +1224,7 @@ export class ChunkMeshManager {
|
|
|
1253
1224
|
this.tryRevealPending()
|
|
1254
1225
|
}
|
|
1255
1226
|
|
|
1256
|
-
private flushChunkDisplay
|
|
1227
|
+
private flushChunkDisplay(chunkKey: string): void {
|
|
1257
1228
|
const sectionKeys = this.waitingChunksToDisplay[chunkKey]
|
|
1258
1229
|
this.pendingNearReveal.delete(chunkKey)
|
|
1259
1230
|
this.clearNearRevealTimer(chunkKey)
|
|
@@ -1273,7 +1244,7 @@ export class ChunkMeshManager {
|
|
|
1273
1244
|
// Single pass is enough — pending entries are already finished, so flushing
|
|
1274
1245
|
// one cannot un-block another via this code path (cascading happens via
|
|
1275
1246
|
// chunkFinished events and per-pending grace timers).
|
|
1276
|
-
tryRevealPending
|
|
1247
|
+
tryRevealPending(): void {
|
|
1277
1248
|
if (this.pendingNearReveal.size === 0) return
|
|
1278
1249
|
const now = Date.now()
|
|
1279
1250
|
for (const [chunkKey, enqueuedAt] of [...this.pendingNearReveal]) {
|
|
@@ -1285,7 +1256,7 @@ export class ChunkMeshManager {
|
|
|
1285
1256
|
|
|
1286
1257
|
// Drop gate state for an unloaded column and re-evaluate any farther
|
|
1287
1258
|
// chunks that may have been blocked by it.
|
|
1288
|
-
onChunkRemovedFromGate
|
|
1259
|
+
onChunkRemovedFromGate(chunkKey: string): void {
|
|
1289
1260
|
this.pendingNearReveal.delete(chunkKey)
|
|
1290
1261
|
this.clearNearRevealTimer(chunkKey)
|
|
1291
1262
|
this.clearExpectedGraceTimer(chunkKey)
|
|
@@ -1293,7 +1264,7 @@ export class ChunkMeshManager {
|
|
|
1293
1264
|
this.tryRevealPending()
|
|
1294
1265
|
}
|
|
1295
1266
|
|
|
1296
|
-
private isWasmGateActive
|
|
1267
|
+
private isWasmGateActive(): boolean {
|
|
1297
1268
|
return !!this.worldRenderer.worldRendererConfig?.wasmMesher
|
|
1298
1269
|
}
|
|
1299
1270
|
|
|
@@ -1307,7 +1278,7 @@ export class ChunkMeshManager {
|
|
|
1307
1278
|
* - After grace: only actually-loaded-but-not-finished columns block,
|
|
1308
1279
|
* so a never-arriving column does not freeze the view.
|
|
1309
1280
|
*/
|
|
1310
|
-
private isBlockedByNearer
|
|
1281
|
+
private isBlockedByNearer(chunkKey: string, ageMs: number): boolean {
|
|
1311
1282
|
const viewer = this.worldRenderer.viewerChunkPosition
|
|
1312
1283
|
if (!viewer) return false
|
|
1313
1284
|
const ownParts = chunkKey.split(',')
|
|
@@ -1354,7 +1325,7 @@ export class ChunkMeshManager {
|
|
|
1354
1325
|
return false
|
|
1355
1326
|
}
|
|
1356
1327
|
|
|
1357
|
-
private armNearRevealTimer
|
|
1328
|
+
private armNearRevealTimer(chunkKey: string): void {
|
|
1358
1329
|
if (this.nearRevealTimers.has(chunkKey)) return
|
|
1359
1330
|
const timer = setTimeout(() => {
|
|
1360
1331
|
this.nearRevealTimers.delete(chunkKey)
|
|
@@ -1366,7 +1337,7 @@ export class ChunkMeshManager {
|
|
|
1366
1337
|
this.nearRevealTimers.set(chunkKey, timer)
|
|
1367
1338
|
}
|
|
1368
1339
|
|
|
1369
|
-
private clearNearRevealTimer
|
|
1340
|
+
private clearNearRevealTimer(chunkKey: string): void {
|
|
1370
1341
|
const timer = this.nearRevealTimers.get(chunkKey)
|
|
1371
1342
|
if (timer) {
|
|
1372
1343
|
clearTimeout(timer)
|
|
@@ -1379,7 +1350,7 @@ export class ChunkMeshManager {
|
|
|
1379
1350
|
* "expected but never arrived" positions stop blocking promptly,
|
|
1380
1351
|
* without waiting for the next chunkFinished / player-move event.
|
|
1381
1352
|
*/
|
|
1382
|
-
private armExpectedGraceTimer
|
|
1353
|
+
private armExpectedGraceTimer(chunkKey: string): void {
|
|
1383
1354
|
if (this.nearRevealGraceTimers.has(chunkKey)) return
|
|
1384
1355
|
const timer = setTimeout(() => {
|
|
1385
1356
|
this.nearRevealGraceTimers.delete(chunkKey)
|
|
@@ -1389,7 +1360,7 @@ export class ChunkMeshManager {
|
|
|
1389
1360
|
this.nearRevealGraceTimers.set(chunkKey, timer)
|
|
1390
1361
|
}
|
|
1391
1362
|
|
|
1392
|
-
private clearExpectedGraceTimer
|
|
1363
|
+
private clearExpectedGraceTimer(chunkKey: string): void {
|
|
1393
1364
|
const timer = this.nearRevealGraceTimers.get(chunkKey)
|
|
1394
1365
|
if (timer) {
|
|
1395
1366
|
clearTimeout(timer)
|
|
@@ -1397,7 +1368,7 @@ export class ChunkMeshManager {
|
|
|
1397
1368
|
}
|
|
1398
1369
|
}
|
|
1399
1370
|
|
|
1400
|
-
cleanupSection
|
|
1371
|
+
cleanupSection(sectionKey: string, opts?: { forRemesh?: boolean }) {
|
|
1401
1372
|
// Remove section object from scene
|
|
1402
1373
|
const sectionObject = this.sectionObjects[sectionKey]
|
|
1403
1374
|
if (sectionObject) {
|
|
@@ -1416,7 +1387,7 @@ export class ChunkMeshManager {
|
|
|
1416
1387
|
// Cleanup banner textures before disposing
|
|
1417
1388
|
if (sectionObject.bannersContainer) {
|
|
1418
1389
|
for (const child of sectionObject.bannersContainer.children) {
|
|
1419
|
-
const banner = child as THREE.Group & { bannerMaterial?: THREE.MeshBasicMaterial
|
|
1390
|
+
const banner = child as THREE.Group & { bannerMaterial?: THREE.MeshBasicMaterial; bannerTexture?: THREE.Texture }
|
|
1420
1391
|
if (banner.bannerMaterial) {
|
|
1421
1392
|
this.blockEntityLightRegistry.unregister(banner.bannerMaterial)
|
|
1422
1393
|
}
|
|
@@ -1426,11 +1397,13 @@ export class ChunkMeshManager {
|
|
|
1426
1397
|
}
|
|
1427
1398
|
this.disposeContainer(sectionObject.bannersContainer)
|
|
1428
1399
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1400
|
+
if (!opts?.forRemesh) {
|
|
1401
|
+
this.globalBlockBuffer?.removeSection(sectionKey)
|
|
1402
|
+
this.globalLegacyBuffer?.removeSection(sectionKey)
|
|
1403
|
+
this.globalLegacyBlendBuffer?.removeSection(sectionKey)
|
|
1404
|
+
this.maybeUnregisterLegacyCullSection(sectionKey)
|
|
1405
|
+
this.unregisterShaderSectionRaycastBox(sectionKey)
|
|
1406
|
+
}
|
|
1434
1407
|
this.markCullDirty()
|
|
1435
1408
|
delete sectionObject.deferredLegacyOpaque
|
|
1436
1409
|
delete sectionObject.deferredLegacyBlend
|
|
@@ -1469,8 +1442,7 @@ export class ChunkMeshManager {
|
|
|
1469
1442
|
}
|
|
1470
1443
|
delete this.sectionObjects[sectionKey]
|
|
1471
1444
|
if (!opts?.forRemesh) {
|
|
1472
|
-
this.worldRenderer.getModule<{ onSectionRemoved?: (key: string) => void }>('futuristicReveal')
|
|
1473
|
-
?.onSectionRemoved?.(sectionKey)
|
|
1445
|
+
this.worldRenderer.getModule<{ onSectionRemoved?: (key: string) => void }>('futuristicReveal')?.onSectionRemoved?.(sectionKey)
|
|
1474
1446
|
}
|
|
1475
1447
|
}
|
|
1476
1448
|
}
|
|
@@ -1478,7 +1450,7 @@ export class ChunkMeshManager {
|
|
|
1478
1450
|
/**
|
|
1479
1451
|
* Release a section and return its mesh to the pool
|
|
1480
1452
|
*/
|
|
1481
|
-
private releasePooledMesh
|
|
1453
|
+
private releasePooledMesh(sectionKey: string): void {
|
|
1482
1454
|
const poolEntry = this.activeSections.get(sectionKey)
|
|
1483
1455
|
if (!poolEntry) return
|
|
1484
1456
|
|
|
@@ -1491,7 +1463,7 @@ export class ChunkMeshManager {
|
|
|
1491
1463
|
this.cleanupExcessMeshes()
|
|
1492
1464
|
}
|
|
1493
1465
|
|
|
1494
|
-
releaseSection
|
|
1466
|
+
releaseSection(sectionKey: string): boolean {
|
|
1495
1467
|
this.cleanupSection(sectionKey)
|
|
1496
1468
|
|
|
1497
1469
|
const poolEntry = this.activeSections.get(sectionKey)
|
|
@@ -1519,14 +1491,14 @@ export class ChunkMeshManager {
|
|
|
1519
1491
|
/**
|
|
1520
1492
|
* Get section object if it exists
|
|
1521
1493
|
*/
|
|
1522
|
-
getSectionObject
|
|
1494
|
+
getSectionObject(sectionKey: string): SectionObject | undefined {
|
|
1523
1495
|
return this.sectionObjects[sectionKey]
|
|
1524
1496
|
}
|
|
1525
1497
|
|
|
1526
1498
|
/**
|
|
1527
1499
|
* Update box helper for a section
|
|
1528
1500
|
*/
|
|
1529
|
-
updateBoxHelper
|
|
1501
|
+
updateBoxHelper(sectionKey: string, showChunkBorders: boolean, chunkBoxMaterial: THREE.Material = this.chunkBoxMaterial) {
|
|
1530
1502
|
const sectionObject = this.sectionObjects[sectionKey]
|
|
1531
1503
|
if (!sectionObject) return
|
|
1532
1504
|
|
|
@@ -1562,7 +1534,7 @@ export class ChunkMeshManager {
|
|
|
1562
1534
|
* after the move from `WorldBlockGeometry` (which created the helpers
|
|
1563
1535
|
* eagerly per section) to the pooled `ChunkMeshManager`.
|
|
1564
1536
|
*/
|
|
1565
|
-
updateAllBoxHelpers
|
|
1537
|
+
updateAllBoxHelpers(showChunkBorders: boolean) {
|
|
1566
1538
|
for (const sectionKey of Object.keys(this.sectionObjects)) {
|
|
1567
1539
|
this.updateBoxHelper(sectionKey, showChunkBorders)
|
|
1568
1540
|
}
|
|
@@ -1571,21 +1543,21 @@ export class ChunkMeshManager {
|
|
|
1571
1543
|
/**
|
|
1572
1544
|
* Get mesh for section if it exists
|
|
1573
1545
|
*/
|
|
1574
|
-
getSectionMesh
|
|
1546
|
+
getSectionMesh(sectionKey: string): THREE.Mesh | undefined {
|
|
1575
1547
|
return this.activeSections.get(sectionKey)?.mesh
|
|
1576
1548
|
}
|
|
1577
1549
|
|
|
1578
1550
|
/**
|
|
1579
1551
|
* Check if section is managed by this pool
|
|
1580
1552
|
*/
|
|
1581
|
-
hasSection
|
|
1553
|
+
hasSection(sectionKey: string): boolean {
|
|
1582
1554
|
return this.activeSections.has(sectionKey)
|
|
1583
1555
|
}
|
|
1584
1556
|
|
|
1585
1557
|
/**
|
|
1586
1558
|
* Update pool size based on new view distance
|
|
1587
1559
|
*/
|
|
1588
|
-
updateViewDistance
|
|
1560
|
+
updateViewDistance(maxViewDistance: number) {
|
|
1589
1561
|
// Calculate dynamic pool size based on view distance
|
|
1590
1562
|
const chunksInView = (maxViewDistance * 2 + 1) ** 2
|
|
1591
1563
|
const maxSectionsPerChunk = this.worldHeight / 16
|
|
@@ -1606,7 +1578,7 @@ export class ChunkMeshManager {
|
|
|
1606
1578
|
/**
|
|
1607
1579
|
* Get pool statistics
|
|
1608
1580
|
*/
|
|
1609
|
-
getGlobalBufferStats
|
|
1581
|
+
getGlobalBufferStats(): GlobalBufferStats {
|
|
1610
1582
|
const snapshotLegacy = (buffer: GlobalLegacyBuffer | null): GlobalBufferSlotStats | null => {
|
|
1611
1583
|
if (!buffer) return null
|
|
1612
1584
|
return {
|
|
@@ -1614,7 +1586,7 @@ export class ChunkMeshManager {
|
|
|
1614
1586
|
capacity: buffer.getCapacityQuads(),
|
|
1615
1587
|
sections: buffer.getSectionCount(),
|
|
1616
1588
|
usedBytes: buffer.getUsedMemoryBytes(),
|
|
1617
|
-
capacityBytes: buffer.getMemoryBytes()
|
|
1589
|
+
capacityBytes: buffer.getMemoryBytes()
|
|
1618
1590
|
}
|
|
1619
1591
|
}
|
|
1620
1592
|
|
|
@@ -1626,17 +1598,17 @@ export class ChunkMeshManager {
|
|
|
1626
1598
|
capacity: cubes.getCapacityFaces(),
|
|
1627
1599
|
sections: cubes.getSectionCount(),
|
|
1628
1600
|
usedBytes: cubes.getUsedMemoryBytes(),
|
|
1629
|
-
capacityBytes: cubes.getMemoryBytes()
|
|
1601
|
+
capacityBytes: cubes.getMemoryBytes()
|
|
1630
1602
|
}
|
|
1631
1603
|
: null,
|
|
1632
1604
|
legacyOpaque: snapshotLegacy(this.globalLegacyBuffer),
|
|
1633
|
-
legacyBlend: snapshotLegacy(this.globalLegacyBlendBuffer)
|
|
1605
|
+
legacyBlend: snapshotLegacy(this.globalLegacyBlendBuffer)
|
|
1634
1606
|
}
|
|
1635
1607
|
}
|
|
1636
1608
|
|
|
1637
|
-
getStats
|
|
1609
|
+
getStats() {
|
|
1638
1610
|
const freeCount = this.meshPool.filter(entry => !entry.inUse).length
|
|
1639
|
-
const hitRate = this.hits + this.misses > 0 ? (this.hits / (this.hits + this.misses) * 100).toFixed(1) : '0'
|
|
1611
|
+
const hitRate = this.hits + this.misses > 0 ? ((this.hits / (this.hits + this.misses)) * 100).toFixed(1) : '0'
|
|
1640
1612
|
const memoryUsage = this.getEstimatedMemoryUsage()
|
|
1641
1613
|
|
|
1642
1614
|
return {
|
|
@@ -1653,21 +1625,21 @@ export class ChunkMeshManager {
|
|
|
1653
1625
|
/**
|
|
1654
1626
|
* Get total tiles rendered
|
|
1655
1627
|
*/
|
|
1656
|
-
getTotalTiles
|
|
1628
|
+
getTotalTiles(): number {
|
|
1657
1629
|
return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj.tilesCount || 0), 0)
|
|
1658
1630
|
}
|
|
1659
1631
|
|
|
1660
1632
|
/**
|
|
1661
1633
|
* Get total blocks rendered
|
|
1662
1634
|
*/
|
|
1663
|
-
getTotalBlocks
|
|
1635
|
+
getTotalBlocks(): number {
|
|
1664
1636
|
return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj.blocksCount || 0), 0)
|
|
1665
1637
|
}
|
|
1666
1638
|
|
|
1667
1639
|
/**
|
|
1668
1640
|
* Estimate memory usage in MB
|
|
1669
1641
|
*/
|
|
1670
|
-
getEstimatedMemoryUsage
|
|
1642
|
+
getEstimatedMemoryUsage(): { total: string; breakdown: any } {
|
|
1671
1643
|
let totalBytes = 0
|
|
1672
1644
|
let positionBytes = 0
|
|
1673
1645
|
let normalBytes = 0
|
|
@@ -1756,7 +1728,7 @@ export class ChunkMeshManager {
|
|
|
1756
1728
|
color: `${(colorBytes / (1024 * 1024)).toFixed(2)} MB`,
|
|
1757
1729
|
uv: `${(uvBytes / (1024 * 1024)).toFixed(2)} MB`,
|
|
1758
1730
|
index: `${(indexBytes / (1024 * 1024)).toFixed(2)} MB`,
|
|
1759
|
-
shaderInstances: `${(shaderInstanceBytes / (1024 * 1024)).toFixed(2)} MB
|
|
1731
|
+
shaderInstances: `${(shaderInstanceBytes / (1024 * 1024)).toFixed(2)} MB`
|
|
1760
1732
|
}
|
|
1761
1733
|
}
|
|
1762
1734
|
}
|
|
@@ -1764,7 +1736,7 @@ export class ChunkMeshManager {
|
|
|
1764
1736
|
/**
|
|
1765
1737
|
* Cleanup and dispose resources
|
|
1766
1738
|
*/
|
|
1767
|
-
dispose
|
|
1739
|
+
dispose() {
|
|
1768
1740
|
// Release all active sections (snapshot keys to avoid mutating map during iteration)
|
|
1769
1741
|
const activeKeys = [...this.activeSections.keys()]
|
|
1770
1742
|
for (const sectionKey of activeKeys) {
|
|
@@ -1783,6 +1755,7 @@ export class ChunkMeshManager {
|
|
|
1783
1755
|
this.activeSections.clear()
|
|
1784
1756
|
this.chunkBoxMaterial.dispose()
|
|
1785
1757
|
this.shaderSectionRaycastBoxes.clear()
|
|
1758
|
+
this.lastBufferStateKey = ''
|
|
1786
1759
|
this.globalBlockBuffer?.dispose()
|
|
1787
1760
|
this.globalBlockBuffer = null
|
|
1788
1761
|
this.globalLegacyBuffer?.dispose()
|
|
@@ -1807,7 +1780,7 @@ export class ChunkMeshManager {
|
|
|
1807
1780
|
|
|
1808
1781
|
// Private helper methods
|
|
1809
1782
|
|
|
1810
|
-
private acquireMesh
|
|
1783
|
+
private acquireMesh(): ChunkMeshPool | undefined {
|
|
1811
1784
|
if (this.bypassPooling) {
|
|
1812
1785
|
const entry: ChunkMeshPool = {
|
|
1813
1786
|
mesh: new THREE.Mesh(new THREE.BufferGeometry(), this.getLegacyShaderMaterial()),
|
|
@@ -1854,7 +1827,7 @@ export class ChunkMeshManager {
|
|
|
1854
1827
|
throw new Error('ChunkMeshManager: Failed to acquire mesh after pool expansion')
|
|
1855
1828
|
}
|
|
1856
1829
|
|
|
1857
|
-
private expandPool
|
|
1830
|
+
private expandPool(newSize: number) {
|
|
1858
1831
|
const currentLength = this.meshPool.length
|
|
1859
1832
|
this.poolSize = newSize
|
|
1860
1833
|
|
|
@@ -1877,12 +1850,7 @@ export class ChunkMeshManager {
|
|
|
1877
1850
|
}
|
|
1878
1851
|
}
|
|
1879
1852
|
|
|
1880
|
-
private updateGeometryAttribute
|
|
1881
|
-
geometry: THREE.BufferGeometry,
|
|
1882
|
-
name: string,
|
|
1883
|
-
array: Float32Array,
|
|
1884
|
-
itemSize: number
|
|
1885
|
-
) {
|
|
1853
|
+
private updateGeometryAttribute(geometry: THREE.BufferGeometry, name: string, array: Float32Array, itemSize: number) {
|
|
1886
1854
|
const attribute = geometry.getAttribute(name)
|
|
1887
1855
|
|
|
1888
1856
|
if (attribute && attribute.count === array.length / itemSize) {
|
|
@@ -1895,7 +1863,7 @@ export class ChunkMeshManager {
|
|
|
1895
1863
|
}
|
|
1896
1864
|
}
|
|
1897
1865
|
|
|
1898
|
-
private clearGeometry
|
|
1866
|
+
private clearGeometry(geometry: THREE.BufferGeometry) {
|
|
1899
1867
|
const attributes = ['position', 'normal', 'color', 'a_skyLight', 'a_blockLight', 'uv']
|
|
1900
1868
|
for (const name of attributes) {
|
|
1901
1869
|
if (geometry.hasAttribute(name)) {
|
|
@@ -1909,7 +1877,7 @@ export class ChunkMeshManager {
|
|
|
1909
1877
|
geometry.boundingSphere = null
|
|
1910
1878
|
}
|
|
1911
1879
|
|
|
1912
|
-
private cleanupExcessMeshes
|
|
1880
|
+
private cleanupExcessMeshes() {
|
|
1913
1881
|
// If pool size exceeds max and we have free meshes, remove some
|
|
1914
1882
|
if (this.poolSize > this.maxPoolSize) {
|
|
1915
1883
|
const freeCount = this.meshPool.filter(entry => !entry.inUse).length
|
|
@@ -1929,14 +1897,14 @@ export class ChunkMeshManager {
|
|
|
1929
1897
|
}
|
|
1930
1898
|
}
|
|
1931
1899
|
|
|
1932
|
-
private disposeContainer
|
|
1900
|
+
private disposeContainer(container: THREE.Group, cleanTextures = true) {
|
|
1933
1901
|
disposeObject(container, cleanTextures)
|
|
1934
1902
|
}
|
|
1935
1903
|
|
|
1936
1904
|
/**
|
|
1937
1905
|
* Record render time for performance monitoring
|
|
1938
1906
|
*/
|
|
1939
|
-
recordRenderTime
|
|
1907
|
+
recordRenderTime(renderTime: number): void {
|
|
1940
1908
|
this.renderTimes.push(renderTime)
|
|
1941
1909
|
if (this.renderTimes.length > this.maxRenderTimeSamples) {
|
|
1942
1910
|
this.renderTimes.shift()
|
|
@@ -1953,31 +1921,31 @@ export class ChunkMeshManager {
|
|
|
1953
1921
|
/**
|
|
1954
1922
|
* Get current effective render distance
|
|
1955
1923
|
*/
|
|
1956
|
-
getEffectiveRenderDistance
|
|
1924
|
+
getEffectiveRenderDistance(): number {
|
|
1957
1925
|
return this.performanceOverrideDistance || this.worldRenderer.viewDistance
|
|
1958
1926
|
}
|
|
1959
1927
|
|
|
1960
1928
|
/**
|
|
1961
1929
|
* Force reset performance override
|
|
1962
1930
|
*/
|
|
1963
|
-
resetPerformanceOverride
|
|
1931
|
+
resetPerformanceOverride(): void {
|
|
1964
1932
|
this.performanceOverrideDistance = undefined
|
|
1965
1933
|
this.renderTimes.length = 0
|
|
1966
1934
|
console.log('ChunkMeshManager: Performance override reset')
|
|
1967
1935
|
}
|
|
1968
1936
|
|
|
1969
1937
|
/**
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
getAverageRenderTime
|
|
1938
|
+
* Get average render time
|
|
1939
|
+
*/
|
|
1940
|
+
getAverageRenderTime(): number {
|
|
1973
1941
|
if (this.renderTimes.length === 0) return 0
|
|
1974
1942
|
return this.renderTimes.reduce((sum, time) => sum + time, 0) / this.renderTimes.length
|
|
1975
1943
|
}
|
|
1976
1944
|
|
|
1977
1945
|
/**
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
private checkPerformance
|
|
1946
|
+
* Check if performance is degraded and adjust render distance
|
|
1947
|
+
*/
|
|
1948
|
+
private checkPerformance(): void {
|
|
1981
1949
|
if (this.renderTimes.length < this.maxRenderTimeSamples) return
|
|
1982
1950
|
|
|
1983
1951
|
const avgRenderTime = this.getAverageRenderTime()
|
|
@@ -2008,7 +1976,7 @@ export class ChunkMeshManager {
|
|
|
2008
1976
|
/**
|
|
2009
1977
|
* Hide sections beyond performance override distance
|
|
2010
1978
|
*/
|
|
2011
|
-
updateSectionsVisibility
|
|
1979
|
+
updateSectionsVisibility(): void {
|
|
2012
1980
|
const cameraPos = this.worldRenderer.cameraSectionPos
|
|
2013
1981
|
for (const [sectionKey, sectionObject] of Object.entries(this.sectionObjects)) {
|
|
2014
1982
|
// Don't override "Batch Chunks Display" hiding — those sections must
|
|
@@ -2035,16 +2003,14 @@ export class ChunkMeshManager {
|
|
|
2035
2003
|
}
|
|
2036
2004
|
}
|
|
2037
2005
|
|
|
2038
|
-
|
|
2039
2006
|
class SignHeadsRenderer {
|
|
2040
|
-
constructor
|
|
2041
|
-
}
|
|
2007
|
+
constructor(public worldRendererThree: WorldRendererThree) {}
|
|
2042
2008
|
|
|
2043
|
-
dispose
|
|
2009
|
+
dispose() {
|
|
2044
2010
|
disposeAllSignTextures()
|
|
2045
2011
|
}
|
|
2046
2012
|
|
|
2047
|
-
renderHead
|
|
2013
|
+
renderHead(position: Vec3, rotation: number, isWall: boolean, blockEntity) {
|
|
2048
2014
|
let textureData: string
|
|
2049
2015
|
if (blockEntity.SkullOwner) {
|
|
2050
2016
|
textureData = blockEntity.SkullOwner.Properties?.textures?.[0]?.Value
|
|
@@ -2058,8 +2024,7 @@ class SignHeadsRenderer {
|
|
|
2058
2024
|
let skinUrl = decodedData.textures?.SKIN?.url
|
|
2059
2025
|
const { skinTexturesProxy } = this.worldRendererThree.worldRendererConfig
|
|
2060
2026
|
if (skinTexturesProxy) {
|
|
2061
|
-
skinUrl = skinUrl?.replace('http://textures.minecraft.net/', skinTexturesProxy)
|
|
2062
|
-
.replace('https://textures.minecraft.net/', skinTexturesProxy)
|
|
2027
|
+
skinUrl = skinUrl?.replace('http://textures.minecraft.net/', skinTexturesProxy).replace('https://textures.minecraft.net/', skinTexturesProxy)
|
|
2063
2028
|
}
|
|
2064
2029
|
|
|
2065
2030
|
const mesh = getMesh(this.worldRendererThree, skinUrl, armorModel.head as any)
|
|
@@ -2072,11 +2037,7 @@ class SignHeadsRenderer {
|
|
|
2072
2037
|
group.add(mesh)
|
|
2073
2038
|
this.worldRendererThree.sceneOrigin.track(group)
|
|
2074
2039
|
group.position.set(position.x + 0.5, position.y + 0.045, position.z + 0.5)
|
|
2075
|
-
group.rotation.set(
|
|
2076
|
-
0,
|
|
2077
|
-
-THREE.MathUtils.degToRad(rotation * (isWall ? 90 : 45 / 2)),
|
|
2078
|
-
0
|
|
2079
|
-
)
|
|
2040
|
+
group.rotation.set(0, -THREE.MathUtils.degToRad(rotation * (isWall ? 90 : 45 / 2)), 0)
|
|
2080
2041
|
group.scale.set(0.8, 0.8, 0.8)
|
|
2081
2042
|
return group
|
|
2082
2043
|
} catch (err) {
|
|
@@ -2084,7 +2045,7 @@ class SignHeadsRenderer {
|
|
|
2084
2045
|
}
|
|
2085
2046
|
}
|
|
2086
2047
|
|
|
2087
|
-
renderSign
|
|
2048
|
+
renderSign(position: Vec3, rotation: number, isWall: boolean, isHanging: boolean, blockEntity) {
|
|
2088
2049
|
const tex = getSignTexture(this.worldRendererThree, blockEntity, isHanging)
|
|
2089
2050
|
|
|
2090
2051
|
if (!tex) return
|
|
@@ -2105,11 +2066,7 @@ class SignHeadsRenderer {
|
|
|
2105
2066
|
}
|
|
2106
2067
|
|
|
2107
2068
|
const group = new THREE.Group() as THREE.Group & { signTexture?: THREE.Texture }
|
|
2108
|
-
group.rotation.set(
|
|
2109
|
-
0,
|
|
2110
|
-
-THREE.MathUtils.degToRad(rotation * (isWall ? 90 : 45 / 2)),
|
|
2111
|
-
0
|
|
2112
|
-
)
|
|
2069
|
+
group.rotation.set(0, -THREE.MathUtils.degToRad(rotation * (isWall ? 90 : 45 / 2)), 0)
|
|
2113
2070
|
group.add(mesh)
|
|
2114
2071
|
group.signTexture = tex
|
|
2115
2072
|
const height = (isHanging ? 10 : 8) / 16
|