minecraft-renderer 0.1.79 → 0.1.81
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 +66 -26
- package/dist/mesher.js +36 -36
- package/dist/mesher.js.map +4 -4
- package/dist/mesherWasm.js +217 -217
- package/dist/minecraft-renderer.js +66 -66
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +450 -450
- 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 +349 -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/cameraCollisionBlockCache.ts +156 -0
- package/src/three/cameraCollisionSolidity.ts +50 -0
- package/src/three/cameraShake.ts +15 -6
- package/src/three/chunkMeshManager.ts +223 -390
- 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 +248 -264
- 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 +24 -110
- 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 -64
- 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/thirdPersonVoxelRaycast.ts +120 -0
- 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 +144 -166
- 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/cameraCollisionBlockCache.test.ts +82 -0
- 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 +1 -93
- package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +103 -141
- package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +14 -22
- package/src/wasm-mesher/tests/thirdPersonVoxelRaycast.test.ts +63 -0
- 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
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { describe, expect, test } from 'vitest'
|
|
3
|
+
import * as THREE from 'three'
|
|
4
|
+
import { GlobalBlockBuffer } from '../globalBlockBuffer'
|
|
5
|
+
import { buildVisibleCubeSpans } from '../cubeDrawSpans'
|
|
6
|
+
import { createCubeBlockMaterial } from '../shaders/cubeBlockShader'
|
|
7
|
+
import { packWord3 } from '../../wasm-mesher/bridge/shaderCubeBridge'
|
|
8
|
+
|
|
9
|
+
type BufferInternals = {
|
|
10
|
+
pendingRanges: Array<{ start: number; end: number }>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getInternals(buffer: GlobalBlockBuffer): BufferInternals {
|
|
14
|
+
return buffer as unknown as BufferInternals
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function drainUploads(buffer: GlobalBlockBuffer): void {
|
|
18
|
+
while (getInternals(buffer).pendingRanges.length) buffer.uploadDirtyRange()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function makeSectionWords(faceW0: number[]): Uint32Array {
|
|
22
|
+
const words = new Uint32Array(faceW0.length * 4)
|
|
23
|
+
for (let i = 0; i < faceW0.length; i++) {
|
|
24
|
+
words[i * 4] = faceW0[i]!
|
|
25
|
+
words[i * 4 + 1] = 0
|
|
26
|
+
words[i * 4 + 2] = 0
|
|
27
|
+
words[i * 4 + 3] = packWord3(0, 0)
|
|
28
|
+
}
|
|
29
|
+
return words
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function finishCurrentMove(buffer: GlobalBlockBuffer): void {
|
|
33
|
+
drainUploads(buffer)
|
|
34
|
+
buffer.compactStep()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
test('GlobalBlockBuffer: new section gated until upload completes', () => {
|
|
38
|
+
const scene = new THREE.Scene()
|
|
39
|
+
const mat = createCubeBlockMaterial()
|
|
40
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
41
|
+
|
|
42
|
+
buffer.addSection('a', makeSectionWords([1]), 1)
|
|
43
|
+
expect(buffer.getSectionDrawStart('a')).toBeUndefined()
|
|
44
|
+
|
|
45
|
+
drainUploads(buffer)
|
|
46
|
+
expect(buffer.getSectionDrawStart('a')).toBe(0)
|
|
47
|
+
|
|
48
|
+
buffer.dispose()
|
|
49
|
+
mat.dispose()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test('GlobalBlockBuffer: remesh double-buffers old geometry until upload', () => {
|
|
53
|
+
const scene = new THREE.Scene()
|
|
54
|
+
const mat = createCubeBlockMaterial()
|
|
55
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
56
|
+
|
|
57
|
+
buffer.addSection('a', makeSectionWords([10]), 1)
|
|
58
|
+
drainUploads(buffer)
|
|
59
|
+
const oldStart = buffer.getSectionSlot('a')!.start
|
|
60
|
+
|
|
61
|
+
buffer.addSection('a', makeSectionWords([20]), 1)
|
|
62
|
+
expect(buffer.getSectionDrawStart('a')).toBe(oldStart)
|
|
63
|
+
expect(buffer.hasPendingReplace()).toBe(true)
|
|
64
|
+
|
|
65
|
+
const w0 = buffer.mesh.geometry.getAttribute('a_w0').array as Uint32Array
|
|
66
|
+
expect(w0[oldStart]).toBe(10)
|
|
67
|
+
|
|
68
|
+
const epochBefore = buffer.getUploadEpoch()
|
|
69
|
+
drainUploads(buffer)
|
|
70
|
+
buffer.compactStep()
|
|
71
|
+
expect(buffer.hasPendingReplace()).toBe(false)
|
|
72
|
+
expect(buffer.getUploadEpoch()).toBeGreaterThan(epochBefore)
|
|
73
|
+
finishCurrentMove(buffer)
|
|
74
|
+
expect(buffer.getSectionDrawStart('a')).toBe(buffer.getSectionSlot('a')!.start)
|
|
75
|
+
expect(w0[buffer.getSectionSlot('a')!.start]).toBe(20)
|
|
76
|
+
|
|
77
|
+
buffer.dispose()
|
|
78
|
+
mat.dispose()
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('GlobalBlockBuffer: remesh before previous upload completes keeps fully-uploaded fallback', () => {
|
|
82
|
+
const scene = new THREE.Scene()
|
|
83
|
+
const mat = createCubeBlockMaterial()
|
|
84
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
85
|
+
|
|
86
|
+
buffer.addSection('a', makeSectionWords([10]), 1)
|
|
87
|
+
drainUploads(buffer)
|
|
88
|
+
buffer.compactStep()
|
|
89
|
+
const slotA = buffer.getSectionSlot('a')!.start
|
|
90
|
+
|
|
91
|
+
buffer.addSection('a', makeSectionWords([20]), 1)
|
|
92
|
+
expect(buffer.hasPendingReplace()).toBe(true)
|
|
93
|
+
expect(buffer.hasPendingUploads()).toBe(true)
|
|
94
|
+
|
|
95
|
+
buffer.addSection('a', makeSectionWords([30]), 1)
|
|
96
|
+
|
|
97
|
+
const drawStart = buffer.getSectionDrawStart('a')
|
|
98
|
+
const drawCount = buffer.getSectionDrawCount('a')!
|
|
99
|
+
expect(drawStart).toBe(slotA)
|
|
100
|
+
expect(buffer.isRangeFullyUploaded(drawStart!, drawStart! + drawCount - 1)).toBe(true)
|
|
101
|
+
|
|
102
|
+
const spans = buildVisibleCubeSpans(
|
|
103
|
+
[{ start: drawStart!, count: drawCount }],
|
|
104
|
+
buffer.getHighWatermark(),
|
|
105
|
+
false,
|
|
106
|
+
(start, end) => buffer.isRangeFullyUploaded(start, end),
|
|
107
|
+
buffer.getPendingDirtyRanges()
|
|
108
|
+
)
|
|
109
|
+
expect(spans.length).toBeGreaterThan(0)
|
|
110
|
+
expect(spans.some(s => s.start <= drawStart! && s.start + s.count > drawStart!)).toBe(true)
|
|
111
|
+
|
|
112
|
+
const w0 = buffer.mesh.geometry.getAttribute('a_w0').array as Uint32Array
|
|
113
|
+
expect(w0[slotA]).toBe(10)
|
|
114
|
+
|
|
115
|
+
drainUploads(buffer)
|
|
116
|
+
buffer.compactStep()
|
|
117
|
+
finishCurrentMove(buffer)
|
|
118
|
+
const slotC = buffer.getSectionSlot('a')!.start
|
|
119
|
+
expect(buffer.getSectionDrawStart('a')).toBe(slotC)
|
|
120
|
+
expect(w0[slotC]).toBe(30)
|
|
121
|
+
|
|
122
|
+
buffer.dispose()
|
|
123
|
+
mat.dispose()
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('GlobalBlockBuffer: remesh stays drawable when slot kept (updateSection flow)', () => {
|
|
127
|
+
const scene = new THREE.Scene()
|
|
128
|
+
const mat = createCubeBlockMaterial()
|
|
129
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
130
|
+
|
|
131
|
+
buffer.addSection('a', makeSectionWords([10]), 1)
|
|
132
|
+
drainUploads(buffer)
|
|
133
|
+
expect(buffer.getSectionDrawStart('a')).toBe(0)
|
|
134
|
+
|
|
135
|
+
// updateSection forRemesh: do NOT removeSection before addSection
|
|
136
|
+
buffer.addSection('a', makeSectionWords([20]), 1)
|
|
137
|
+
expect(buffer.getSectionDrawStart('a')).toBeDefined()
|
|
138
|
+
expect(buffer.hasPendingReplace()).toBe(true)
|
|
139
|
+
|
|
140
|
+
drainUploads(buffer)
|
|
141
|
+
buffer.compactStep()
|
|
142
|
+
expect(buffer.hasPendingReplace()).toBe(false)
|
|
143
|
+
finishCurrentMove(buffer)
|
|
144
|
+
expect(buffer.getSectionDrawStart('a')).toBe(buffer.getSectionSlot('a')!.start)
|
|
145
|
+
|
|
146
|
+
buffer.dispose()
|
|
147
|
+
mat.dispose()
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('GlobalBlockBuffer: pre-remove before remesh leaves drawable hole until upload', () => {
|
|
151
|
+
const scene = new THREE.Scene()
|
|
152
|
+
const mat = createCubeBlockMaterial()
|
|
153
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
154
|
+
|
|
155
|
+
buffer.addSection('a', makeSectionWords([10]), 1)
|
|
156
|
+
drainUploads(buffer)
|
|
157
|
+
|
|
158
|
+
buffer.removeSection('a')
|
|
159
|
+
buffer.addSection('a', makeSectionWords([20]), 1)
|
|
160
|
+
expect(buffer.getSectionDrawStart('a')).toBeUndefined()
|
|
161
|
+
expect(buffer.hasPendingReplace()).toBe(false)
|
|
162
|
+
|
|
163
|
+
drainUploads(buffer)
|
|
164
|
+
expect(buffer.getSectionDrawStart('a')).toBeDefined()
|
|
165
|
+
|
|
166
|
+
buffer.dispose()
|
|
167
|
+
mat.dispose()
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('GlobalBlockBuffer: canUseFullDrawShortcut false while uploads pending', () => {
|
|
171
|
+
const scene = new THREE.Scene()
|
|
172
|
+
const mat = createCubeBlockMaterial()
|
|
173
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
174
|
+
|
|
175
|
+
buffer.addSection('a', makeSectionWords([1, 2, 3]), 3)
|
|
176
|
+
expect(buffer.canUseFullDrawShortcut()).toBe(false)
|
|
177
|
+
|
|
178
|
+
drainUploads(buffer)
|
|
179
|
+
expect(buffer.canUseFullDrawShortcut()).toBe(true)
|
|
180
|
+
|
|
181
|
+
buffer.dispose()
|
|
182
|
+
mat.dispose()
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
test('GlobalBlockBuffer: uploadEpoch increments on partial upload advance', () => {
|
|
186
|
+
const scene = new THREE.Scene()
|
|
187
|
+
const mat = createCubeBlockMaterial()
|
|
188
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
189
|
+
|
|
190
|
+
const faceCount = 20_000
|
|
191
|
+
const words = new Uint32Array(faceCount * 4)
|
|
192
|
+
for (let i = 0; i < faceCount; i++) {
|
|
193
|
+
words[i * 4] = i + 1
|
|
194
|
+
}
|
|
195
|
+
buffer.addSection('a', words, faceCount)
|
|
196
|
+
const epoch0 = buffer.getUploadEpoch()
|
|
197
|
+
buffer.uploadDirtyRange()
|
|
198
|
+
expect(buffer.getUploadEpoch()).toBe(epoch0 + 1)
|
|
199
|
+
expect(buffer.hasPendingUploads()).toBe(true)
|
|
200
|
+
|
|
201
|
+
buffer.dispose()
|
|
202
|
+
mat.dispose()
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
test('GlobalBlockBuffer: uploadEpoch increments when dirty range drains', () => {
|
|
206
|
+
const scene = new THREE.Scene()
|
|
207
|
+
const mat = createCubeBlockMaterial()
|
|
208
|
+
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
209
|
+
|
|
210
|
+
const epoch0 = buffer.getUploadEpoch()
|
|
211
|
+
buffer.addSection('a', makeSectionWords([1]), 1)
|
|
212
|
+
drainUploads(buffer)
|
|
213
|
+
expect(buffer.getUploadEpoch()).toBeGreaterThan(epoch0)
|
|
214
|
+
|
|
215
|
+
buffer.dispose()
|
|
216
|
+
mat.dispose()
|
|
217
|
+
})
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import { describe, expect, test } from 'vitest'
|
|
3
3
|
import * as THREE from 'three'
|
|
4
|
-
import { GlobalLegacyBuffer, MAX_OPAQUE_SPANS } from '../globalLegacyBuffer'
|
|
4
|
+
import { GlobalLegacyBuffer, MAX_OPAQUE_SPANS, carveSpansAroundPendingRanges } from '../globalLegacyBuffer'
|
|
5
5
|
import { createGlobalLegacyBlockMaterial } from '../shaders/legacyBlockShader'
|
|
6
6
|
|
|
7
|
-
function makeQuadGeometry
|
|
7
|
+
function makeQuadGeometry(): {
|
|
8
8
|
positions: Float32Array
|
|
9
9
|
colors: Float32Array
|
|
10
10
|
skyLights: Float32Array
|
|
@@ -13,50 +13,35 @@ function makeQuadGeometry (): {
|
|
|
13
13
|
indices: Uint32Array
|
|
14
14
|
} {
|
|
15
15
|
return {
|
|
16
|
-
positions: new Float32Array([
|
|
17
|
-
|
|
18
|
-
1, 0, -1,
|
|
19
|
-
1, 0, 1,
|
|
20
|
-
-1, 0, 1,
|
|
21
|
-
]),
|
|
22
|
-
colors: new Float32Array([
|
|
23
|
-
1, 1, 1,
|
|
24
|
-
1, 1, 1,
|
|
25
|
-
1, 1, 1,
|
|
26
|
-
1, 1, 1,
|
|
27
|
-
]),
|
|
16
|
+
positions: new Float32Array([-1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1]),
|
|
17
|
+
colors: new Float32Array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
|
|
28
18
|
skyLights: new Float32Array([1, 1, 1, 1]),
|
|
29
19
|
blockLights: new Float32Array([0, 0, 0, 0]),
|
|
30
|
-
uvs: new Float32Array([
|
|
31
|
-
|
|
32
|
-
1, 0,
|
|
33
|
-
1, 1,
|
|
34
|
-
0, 1,
|
|
35
|
-
]),
|
|
36
|
-
indices: new Uint32Array([0, 1, 2, 0, 2, 3]),
|
|
20
|
+
uvs: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
|
|
21
|
+
indices: new Uint32Array([0, 1, 2, 0, 2, 3])
|
|
37
22
|
}
|
|
38
23
|
}
|
|
39
24
|
|
|
40
25
|
type BufferInternals = {
|
|
41
|
-
pendingRanges: Array<{ start: number
|
|
42
|
-
pendingMove: { key: string
|
|
26
|
+
pendingRanges: Array<{ start: number; end: number }>
|
|
27
|
+
pendingMove: { key: string; oldStart: number; newStart: number; count: number } | null
|
|
43
28
|
growCapacity: (minQuads: number) => void
|
|
44
29
|
}
|
|
45
30
|
|
|
46
|
-
function getInternals
|
|
31
|
+
function getInternals(buffer: GlobalLegacyBuffer): BufferInternals {
|
|
47
32
|
return buffer as unknown as BufferInternals
|
|
48
33
|
}
|
|
49
34
|
|
|
50
|
-
function drainUploads
|
|
35
|
+
function drainUploads(buffer: GlobalLegacyBuffer): void {
|
|
51
36
|
while (getInternals(buffer).pendingRanges.length) buffer.uploadDirtyRange()
|
|
52
37
|
}
|
|
53
38
|
|
|
54
|
-
function finishCurrentMove
|
|
39
|
+
function finishCurrentMove(buffer: GlobalLegacyBuffer): void {
|
|
55
40
|
drainUploads(buffer)
|
|
56
41
|
buffer.compactStep()
|
|
57
42
|
}
|
|
58
43
|
|
|
59
|
-
function readSectionIndices
|
|
44
|
+
function readSectionIndices(buffer: GlobalLegacyBuffer, key: string): number[] {
|
|
60
45
|
const slot = buffer.getSectionSlot(key)
|
|
61
46
|
if (!slot) throw new Error(`missing section ${key}`)
|
|
62
47
|
const indexAttr = buffer.mesh.geometry.index!.array as Uint32Array
|
|
@@ -207,7 +192,14 @@ test('GlobalLegacyBuffer: updateDrawSpans opaque merges nearby spans', () => {
|
|
|
207
192
|
|
|
208
193
|
buffer.addSection('a', geo, 0, 0, 0)
|
|
209
194
|
buffer.addSection('b', geo, 16, 0, 0)
|
|
210
|
-
buffer
|
|
195
|
+
drainUploads(buffer)
|
|
196
|
+
buffer.updateDrawSpans(
|
|
197
|
+
[
|
|
198
|
+
{ key: 'a', distSq: 1 },
|
|
199
|
+
{ key: 'b', distSq: 4 }
|
|
200
|
+
],
|
|
201
|
+
'opaque'
|
|
202
|
+
)
|
|
211
203
|
|
|
212
204
|
const spans = buffer.getVisibleIndexSpans()
|
|
213
205
|
expect(spans.length).toBe(1)
|
|
@@ -226,7 +218,15 @@ test('GlobalLegacyBuffer: updateDrawSpans opaque full draw when most quads visib
|
|
|
226
218
|
buffer.addSection('a', geo, 0, 0, 0)
|
|
227
219
|
buffer.addSection('b', geo, 16, 0, 0)
|
|
228
220
|
buffer.addSection('c', geo, 32, 0, 0)
|
|
229
|
-
buffer
|
|
221
|
+
drainUploads(buffer)
|
|
222
|
+
buffer.updateDrawSpans(
|
|
223
|
+
[
|
|
224
|
+
{ key: 'a', distSq: 1 },
|
|
225
|
+
{ key: 'b', distSq: 2 },
|
|
226
|
+
{ key: 'c', distSq: 3 }
|
|
227
|
+
],
|
|
228
|
+
'opaque'
|
|
229
|
+
)
|
|
230
230
|
|
|
231
231
|
const spans = buffer.getVisibleIndexSpans()
|
|
232
232
|
expect(spans.length).toBe(1)
|
|
@@ -245,10 +245,14 @@ test('GlobalLegacyBuffer: updateDrawSpans sortedBlend orders back-to-front', ()
|
|
|
245
245
|
|
|
246
246
|
buffer.addSection('near', geo, 0, 0, 0)
|
|
247
247
|
buffer.addSection('far', geo, 16, 0, 0)
|
|
248
|
-
buffer
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
drainUploads(buffer)
|
|
249
|
+
buffer.updateDrawSpans(
|
|
250
|
+
[
|
|
251
|
+
{ key: 'near', distSq: 1 },
|
|
252
|
+
{ key: 'far', distSq: 100 }
|
|
253
|
+
],
|
|
254
|
+
'sortedBlend'
|
|
255
|
+
)
|
|
252
256
|
|
|
253
257
|
const spans = buffer.getVisibleIndexSpans()
|
|
254
258
|
expect(spans.length).toBe(2)
|
|
@@ -266,6 +270,7 @@ test('GlobalLegacyBuffer: updateDrawSpans skips missing keys', () => {
|
|
|
266
270
|
const geo = makeQuadGeometry()
|
|
267
271
|
|
|
268
272
|
buffer.addSection('a', geo, 0, 0, 0)
|
|
273
|
+
drainUploads(buffer)
|
|
269
274
|
buffer.updateDrawSpans([{ key: 'missing', distSq: 1 }], 'opaque')
|
|
270
275
|
|
|
271
276
|
expect(buffer.getVisibleIndexSpans().length).toBe(0)
|
|
@@ -281,6 +286,7 @@ test('GlobalLegacyBuffer: reset clears visible spans', () => {
|
|
|
281
286
|
const geo = makeQuadGeometry()
|
|
282
287
|
|
|
283
288
|
buffer.addSection('a', geo, 0, 0, 0)
|
|
289
|
+
drainUploads(buffer)
|
|
284
290
|
buffer.updateDrawSpans([{ key: 'a', distSq: 1 }], 'opaque')
|
|
285
291
|
expect(buffer.getVisibleIndexSpans().length).toBeGreaterThan(0)
|
|
286
292
|
|
|
@@ -291,14 +297,14 @@ test('GlobalLegacyBuffer: reset clears visible spans', () => {
|
|
|
291
297
|
mat.dispose()
|
|
292
298
|
})
|
|
293
299
|
|
|
294
|
-
test('GlobalLegacyBuffer: updateDrawSpans opaque
|
|
300
|
+
test('GlobalLegacyBuffer: updateDrawSpans opaque does not bridge interior gaps', () => {
|
|
295
301
|
const scene = new THREE.Scene()
|
|
296
302
|
const mat = createGlobalLegacyBlockMaterial()
|
|
297
303
|
const visibleSectionCount = MAX_OPAQUE_SPANS + 5
|
|
298
304
|
const padQuads = 257
|
|
299
305
|
const buffer = new GlobalLegacyBuffer(mat, scene, {
|
|
300
306
|
initialCapacityQuads: visibleSectionCount * (padQuads + 1) + padQuads,
|
|
301
|
-
growthIncrementQuads: 1024
|
|
307
|
+
growthIncrementQuads: 1024
|
|
302
308
|
})
|
|
303
309
|
const geo = makeQuadGeometry()
|
|
304
310
|
const padGeo = {
|
|
@@ -308,13 +314,13 @@ test('GlobalLegacyBuffer: updateDrawSpans opaque caps at MAX_OPAQUE_SPANS with f
|
|
|
308
314
|
skyLights: new Float32Array(padQuads * 4).fill(1),
|
|
309
315
|
blockLights: new Float32Array(padQuads * 4).fill(0),
|
|
310
316
|
uvs: new Float32Array(padQuads * 4 * 2),
|
|
311
|
-
indices: new Uint32Array(padQuads * 6)
|
|
317
|
+
indices: new Uint32Array(padQuads * 6)
|
|
312
318
|
}
|
|
313
319
|
for (let q = 0; q < padQuads; q++) {
|
|
314
320
|
const vb = q * 4
|
|
315
321
|
padGeo.indices.set([vb, vb + 1, vb + 2, vb, vb + 2, vb + 3], q * 6)
|
|
316
322
|
}
|
|
317
|
-
const visible: Array<{ key: string
|
|
323
|
+
const visible: Array<{ key: string; distSq: number }> = []
|
|
318
324
|
|
|
319
325
|
for (let i = 0; i < visibleSectionCount; i++) {
|
|
320
326
|
const key = `s${i}`
|
|
@@ -331,10 +337,11 @@ test('GlobalLegacyBuffer: updateDrawSpans opaque caps at MAX_OPAQUE_SPANS with f
|
|
|
331
337
|
expect(next.start - (cur.start + cur.count)).toBeGreaterThan(256)
|
|
332
338
|
}
|
|
333
339
|
|
|
340
|
+
drainUploads(buffer)
|
|
334
341
|
buffer.updateDrawSpans(visible, 'opaque')
|
|
335
342
|
|
|
336
343
|
const spans = buffer.getVisibleIndexSpans()
|
|
337
|
-
expect(spans.length).toBe(
|
|
344
|
+
expect(spans.length).toBe(visibleSectionCount)
|
|
338
345
|
|
|
339
346
|
const covered = new Set<number>()
|
|
340
347
|
for (const span of spans) {
|
|
@@ -366,7 +373,7 @@ test('GlobalLegacyBuffer: addSection rejects non-quad geometry', () => {
|
|
|
366
373
|
skyLights: new Float32Array(3).fill(1),
|
|
367
374
|
blockLights: new Float32Array(3).fill(0),
|
|
368
375
|
uvs: new Float32Array(6),
|
|
369
|
-
indices: new Uint32Array([0, 1, 2])
|
|
376
|
+
indices: new Uint32Array([0, 1, 2])
|
|
370
377
|
}
|
|
371
378
|
expect(buffer.addSection('bad', bad, 0, 0, 0)).toBe(false)
|
|
372
379
|
|
|
@@ -469,10 +476,10 @@ test('GlobalLegacyBuffer: sortedBlend accepts more than MAX_OPAQUE_SPANS section
|
|
|
469
476
|
const sectionCount = MAX_OPAQUE_SPANS + 6
|
|
470
477
|
const buffer = new GlobalLegacyBuffer(mat, scene, {
|
|
471
478
|
initialCapacityQuads: sectionCount + 4,
|
|
472
|
-
growthIncrementQuads: 64
|
|
479
|
+
growthIncrementQuads: 64
|
|
473
480
|
})
|
|
474
481
|
const geo = makeQuadGeometry()
|
|
475
|
-
const visible: Array<{ key: string
|
|
482
|
+
const visible: Array<{ key: string; distSq: number }> = []
|
|
476
483
|
|
|
477
484
|
for (let i = 0; i < sectionCount; i++) {
|
|
478
485
|
const key = `s${i}`
|
|
@@ -480,6 +487,7 @@ test('GlobalLegacyBuffer: sortedBlend accepts more than MAX_OPAQUE_SPANS section
|
|
|
480
487
|
visible.push({ key, distSq: sectionCount - i })
|
|
481
488
|
}
|
|
482
489
|
|
|
490
|
+
drainUploads(buffer)
|
|
483
491
|
buffer.updateDrawSpans(visible, 'sortedBlend')
|
|
484
492
|
expect(buffer.getVisibleIndexSpans().length).toBe(sectionCount)
|
|
485
493
|
|
|
@@ -487,6 +495,257 @@ test('GlobalLegacyBuffer: sortedBlend accepts more than MAX_OPAQUE_SPANS section
|
|
|
487
495
|
mat.dispose()
|
|
488
496
|
})
|
|
489
497
|
|
|
498
|
+
test('GlobalLegacyBuffer: new section gated until upload completes', () => {
|
|
499
|
+
const scene = new THREE.Scene()
|
|
500
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
501
|
+
const buffer = new GlobalLegacyBuffer(mat, scene)
|
|
502
|
+
const geo = makeQuadGeometry()
|
|
503
|
+
|
|
504
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
505
|
+
expect(buffer.getSectionDrawStart('a')).toBeUndefined()
|
|
506
|
+
buffer.updateDrawSpans([{ key: 'a', distSq: 1 }], 'opaque')
|
|
507
|
+
expect(buffer.getVisibleIndexSpans().length).toBe(0)
|
|
508
|
+
|
|
509
|
+
drainUploads(buffer)
|
|
510
|
+
expect(buffer.getSectionDrawStart('a')).toBe(0)
|
|
511
|
+
buffer.updateDrawSpans([{ key: 'a', distSq: 1 }], 'opaque')
|
|
512
|
+
expect(buffer.getVisibleIndexSpans().length).toBe(1)
|
|
513
|
+
|
|
514
|
+
buffer.dispose()
|
|
515
|
+
mat.dispose()
|
|
516
|
+
})
|
|
517
|
+
|
|
518
|
+
test('GlobalLegacyBuffer: remesh double-buffers old geometry until upload', () => {
|
|
519
|
+
const scene = new THREE.Scene()
|
|
520
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
521
|
+
const buffer = new GlobalLegacyBuffer(mat, scene)
|
|
522
|
+
const geo = makeQuadGeometry()
|
|
523
|
+
|
|
524
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
525
|
+
drainUploads(buffer)
|
|
526
|
+
const oldStart = buffer.getSectionSlot('a')!.start
|
|
527
|
+
|
|
528
|
+
buffer.addSection('a', geo, 16, 0, 0)
|
|
529
|
+
expect(buffer.getSectionDrawStart('a')).toBe(oldStart)
|
|
530
|
+
expect(buffer.hasPendingReplace()).toBe(true)
|
|
531
|
+
|
|
532
|
+
const indexAttr = buffer.mesh.geometry.index!.array as Uint32Array
|
|
533
|
+
expect(indexAttr[oldStart * 6 + 1]).not.toBe(0)
|
|
534
|
+
|
|
535
|
+
buffer.updateDrawSpans([{ key: 'a', distSq: 1 }], 'opaque')
|
|
536
|
+
expect(buffer.getVisibleIndexSpans()[0]!.indexStart).toBe(oldStart * 6)
|
|
537
|
+
|
|
538
|
+
const epochBefore = buffer.getUploadEpoch()
|
|
539
|
+
drainUploads(buffer)
|
|
540
|
+
buffer.compactStep()
|
|
541
|
+
expect(buffer.hasPendingReplace()).toBe(false)
|
|
542
|
+
expect(buffer.getUploadEpoch()).toBeGreaterThan(epochBefore)
|
|
543
|
+
finishCurrentMove(buffer)
|
|
544
|
+
expect(buffer.getSectionDrawStart('a')).toBe(buffer.getSectionSlot('a')!.start)
|
|
545
|
+
|
|
546
|
+
buffer.dispose()
|
|
547
|
+
mat.dispose()
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
test('GlobalLegacyBuffer: remesh before previous upload completes keeps fully-uploaded fallback', () => {
|
|
551
|
+
const scene = new THREE.Scene()
|
|
552
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
553
|
+
const buffer = new GlobalLegacyBuffer(mat, scene)
|
|
554
|
+
const geo = makeQuadGeometry()
|
|
555
|
+
|
|
556
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
557
|
+
drainUploads(buffer)
|
|
558
|
+
buffer.compactStep()
|
|
559
|
+
const slotA = buffer.getSectionSlot('a')!.start
|
|
560
|
+
|
|
561
|
+
buffer.addSection('a', geo, 16, 0, 0)
|
|
562
|
+
expect(buffer.hasPendingReplace()).toBe(true)
|
|
563
|
+
expect(buffer.hasPendingUploads()).toBe(true)
|
|
564
|
+
|
|
565
|
+
buffer.addSection('a', geo, 32, 0, 0)
|
|
566
|
+
|
|
567
|
+
const drawStart = buffer.getSectionDrawStart('a')
|
|
568
|
+
const drawCount = buffer.getSectionDrawCount('a')!
|
|
569
|
+
expect(drawStart).toBe(slotA)
|
|
570
|
+
expect(buffer.isRangeFullyUploaded(drawStart!, drawStart! + drawCount - 1)).toBe(true)
|
|
571
|
+
|
|
572
|
+
buffer.updateDrawSpans([{ key: 'a', distSq: 1 }], 'opaque')
|
|
573
|
+
const spans = buffer.getVisibleIndexSpans()
|
|
574
|
+
expect(spans.length).toBeGreaterThan(0)
|
|
575
|
+
expect(spans.some(s => s.indexStart <= slotA * 6 && s.indexStart + s.indexCount > slotA * 6)).toBe(true)
|
|
576
|
+
|
|
577
|
+
const indexAttr = buffer.mesh.geometry.index!.array as Uint32Array
|
|
578
|
+
expect(indexAttr[slotA * 6 + 1]).not.toBe(0)
|
|
579
|
+
|
|
580
|
+
drainUploads(buffer)
|
|
581
|
+
buffer.compactStep()
|
|
582
|
+
finishCurrentMove(buffer)
|
|
583
|
+
const slotC = buffer.getSectionSlot('a')!.start
|
|
584
|
+
expect(buffer.getSectionDrawStart('a')).toBe(slotC)
|
|
585
|
+
expect(indexAttr[slotC * 6 + 1]).not.toBe(0)
|
|
586
|
+
|
|
587
|
+
buffer.dispose()
|
|
588
|
+
mat.dispose()
|
|
589
|
+
})
|
|
590
|
+
|
|
591
|
+
test('GlobalLegacyBuffer: full-draw blocked when uploads pending', () => {
|
|
592
|
+
const scene = new THREE.Scene()
|
|
593
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
594
|
+
const buffer = new GlobalLegacyBuffer(mat, scene, { initialCapacityQuads: 8, growthIncrementQuads: 8 })
|
|
595
|
+
const geo = makeQuadGeometry()
|
|
596
|
+
|
|
597
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
598
|
+
buffer.addSection('b', geo, 16, 0, 0)
|
|
599
|
+
buffer.addSection('c', geo, 32, 0, 0)
|
|
600
|
+
drainUploads(buffer)
|
|
601
|
+
buffer.addSection('d', geo, 48, 0, 0)
|
|
602
|
+
|
|
603
|
+
buffer.updateDrawSpans(
|
|
604
|
+
[
|
|
605
|
+
{ key: 'a', distSq: 1 },
|
|
606
|
+
{ key: 'b', distSq: 2 },
|
|
607
|
+
{ key: 'c', distSq: 3 }
|
|
608
|
+
],
|
|
609
|
+
'opaque'
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
const spans = buffer.getVisibleIndexSpans()
|
|
613
|
+
expect(spans.length).toBeGreaterThan(0)
|
|
614
|
+
expect(spans.some(s => s.indexStart === 0 && s.indexCount === buffer.getHighWatermark() * 6)).toBe(false)
|
|
615
|
+
expect(spans.reduce((sum, s) => sum + s.indexCount, 0)).toBe(18)
|
|
616
|
+
|
|
617
|
+
buffer.dispose()
|
|
618
|
+
mat.dispose()
|
|
619
|
+
})
|
|
620
|
+
|
|
621
|
+
test('GlobalLegacyBuffer: full-draw allowed when buffer is clean', () => {
|
|
622
|
+
const scene = new THREE.Scene()
|
|
623
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
624
|
+
const buffer = new GlobalLegacyBuffer(mat, scene, { initialCapacityQuads: 4, growthIncrementQuads: 4 })
|
|
625
|
+
const geo = makeQuadGeometry()
|
|
626
|
+
|
|
627
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
628
|
+
buffer.addSection('b', geo, 16, 0, 0)
|
|
629
|
+
buffer.addSection('c', geo, 32, 0, 0)
|
|
630
|
+
drainUploads(buffer)
|
|
631
|
+
|
|
632
|
+
buffer.updateDrawSpans(
|
|
633
|
+
[
|
|
634
|
+
{ key: 'a', distSq: 1 },
|
|
635
|
+
{ key: 'b', distSq: 2 },
|
|
636
|
+
{ key: 'c', distSq: 3 }
|
|
637
|
+
],
|
|
638
|
+
'opaque'
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
const spans = buffer.getVisibleIndexSpans()
|
|
642
|
+
expect(spans.length).toBe(1)
|
|
643
|
+
expect(spans[0]!.indexStart).toBe(0)
|
|
644
|
+
expect(spans[0]!.indexCount).toBe(buffer.getHighWatermark() * 6)
|
|
645
|
+
|
|
646
|
+
buffer.dispose()
|
|
647
|
+
mat.dispose()
|
|
648
|
+
})
|
|
649
|
+
|
|
650
|
+
test('GlobalLegacyBuffer: uploadEpoch increments on partial upload advance', () => {
|
|
651
|
+
const scene = new THREE.Scene()
|
|
652
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
653
|
+
const buffer = new GlobalLegacyBuffer(mat, scene)
|
|
654
|
+
const geo = makeQuadGeometry()
|
|
655
|
+
|
|
656
|
+
for (let i = 0; i < 6000; i++) {
|
|
657
|
+
buffer.addSection(`s${i}`, geo, i * 16, 0, 0)
|
|
658
|
+
}
|
|
659
|
+
const epoch0 = buffer.getUploadEpoch()
|
|
660
|
+
buffer.uploadDirtyRange()
|
|
661
|
+
expect(buffer.getUploadEpoch()).toBe(epoch0 + 1)
|
|
662
|
+
expect(buffer.hasPendingUploads()).toBe(true)
|
|
663
|
+
buffer.uploadDirtyRange()
|
|
664
|
+
expect(buffer.getUploadEpoch()).toBe(epoch0 + 2)
|
|
665
|
+
|
|
666
|
+
buffer.dispose()
|
|
667
|
+
mat.dispose()
|
|
668
|
+
})
|
|
669
|
+
|
|
670
|
+
test('GlobalLegacyBuffer: carveSpansAroundPendingRanges splits merged span', () => {
|
|
671
|
+
const carved = carveSpansAroundPendingRanges([{ start: 0, count: 100 }], [{ start: 40, end: 59 }])
|
|
672
|
+
expect(carved).toEqual([
|
|
673
|
+
{ start: 0, count: 40 },
|
|
674
|
+
{ start: 60, count: 40 }
|
|
675
|
+
])
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
test('GlobalLegacyBuffer: uploadEpoch increments when dirty range drains', () => {
|
|
679
|
+
const scene = new THREE.Scene()
|
|
680
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
681
|
+
const buffer = new GlobalLegacyBuffer(mat, scene)
|
|
682
|
+
const geo = makeQuadGeometry()
|
|
683
|
+
|
|
684
|
+
const epoch0 = buffer.getUploadEpoch()
|
|
685
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
686
|
+
drainUploads(buffer)
|
|
687
|
+
expect(buffer.getUploadEpoch()).toBeGreaterThan(epoch0)
|
|
688
|
+
|
|
689
|
+
buffer.dispose()
|
|
690
|
+
mat.dispose()
|
|
691
|
+
})
|
|
692
|
+
|
|
693
|
+
test('GlobalLegacyBuffer: mergeOpaqueSpans only merges adjacent slots', () => {
|
|
694
|
+
const scene = new THREE.Scene()
|
|
695
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
696
|
+
const buffer = new GlobalLegacyBuffer(mat, scene, { initialCapacityQuads: 16, growthIncrementQuads: 8 })
|
|
697
|
+
const geo = makeQuadGeometry()
|
|
698
|
+
|
|
699
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
700
|
+
buffer.addSection('b', geo, 16, 0, 0)
|
|
701
|
+
buffer.addSection('c', geo, 32, 0, 0)
|
|
702
|
+
drainUploads(buffer)
|
|
703
|
+
|
|
704
|
+
buffer.updateDrawSpans(
|
|
705
|
+
[
|
|
706
|
+
{ key: 'a', distSq: 1 },
|
|
707
|
+
{ key: 'b', distSq: 2 },
|
|
708
|
+
{ key: 'c', distSq: 3 }
|
|
709
|
+
],
|
|
710
|
+
'opaque'
|
|
711
|
+
)
|
|
712
|
+
expect(buffer.getVisibleIndexSpans().length).toBe(1)
|
|
713
|
+
|
|
714
|
+
buffer.dispose()
|
|
715
|
+
mat.dispose()
|
|
716
|
+
})
|
|
717
|
+
|
|
718
|
+
test('GlobalLegacyBuffer: mergeOpaqueSpans skips gap with pending upload', () => {
|
|
719
|
+
const scene = new THREE.Scene()
|
|
720
|
+
const mat = createGlobalLegacyBlockMaterial()
|
|
721
|
+
const buffer = new GlobalLegacyBuffer(mat, scene, { initialCapacityQuads: 8, growthIncrementQuads: 8 })
|
|
722
|
+
const geo = makeQuadGeometry()
|
|
723
|
+
|
|
724
|
+
buffer.addSection('a', geo, 0, 0, 0)
|
|
725
|
+
buffer.addSection('b', geo, 16, 0, 0)
|
|
726
|
+
buffer.addSection('c', geo, 32, 0, 0)
|
|
727
|
+
drainUploads(buffer)
|
|
728
|
+
buffer.removeSection('b')
|
|
729
|
+
drainUploads(buffer)
|
|
730
|
+
|
|
731
|
+
buffer.addSection('b', geo, 16, 0, 0)
|
|
732
|
+
buffer.updateDrawSpans(
|
|
733
|
+
[
|
|
734
|
+
{ key: 'a', distSq: 1 },
|
|
735
|
+
{ key: 'c', distSq: 2 }
|
|
736
|
+
],
|
|
737
|
+
'opaque'
|
|
738
|
+
)
|
|
739
|
+
|
|
740
|
+
const spans = buffer.getVisibleIndexSpans()
|
|
741
|
+
expect(spans.length).toBe(2)
|
|
742
|
+
expect(spans[0]!.indexCount).toBe(6)
|
|
743
|
+
expect(spans[1]!.indexCount).toBe(6)
|
|
744
|
+
|
|
745
|
+
buffer.dispose()
|
|
746
|
+
mat.dispose()
|
|
747
|
+
})
|
|
748
|
+
|
|
490
749
|
test('GlobalLegacyBuffer: suppressThreeDraw uses minimal non-zero draw range', () => {
|
|
491
750
|
const scene = new THREE.Scene()
|
|
492
751
|
const mat = createGlobalLegacyBlockMaterial()
|