minecraft-renderer 0.1.78 → 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 +32 -32
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +415 -415
- 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 +329 -301
- 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 +174 -99
- package/src/three/globalLegacyBuffer.ts +465 -136
- 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 +93 -0
- 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 +133 -25
- 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 +460 -58
- package/src/three/tests/legacyMultiDraw.test.ts +88 -0
- package/src/three/tests/pr3PerFrameCpuCuts.test.ts +370 -0
- 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 +131 -133
- 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
|
@@ -11,14 +11,14 @@ type ControlModeConfig = {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
interface MediaProperties {
|
|
14
|
-
position: { x: number
|
|
15
|
-
size: { width: number
|
|
14
|
+
position: { x: number; y: number; z: number }
|
|
15
|
+
size: { width: number; height: number }
|
|
16
16
|
src: string
|
|
17
17
|
rotation?: 0 | 1 | 2 | 3 // 0-3 for 0°, 90°, 180°, 270°
|
|
18
18
|
doubleSide?: boolean
|
|
19
19
|
background?: number // Hexadecimal color (e.g., 0x000000 for black)
|
|
20
20
|
opacity?: number // 0-1 value for transparency
|
|
21
|
-
uvMapping?: { startU: number
|
|
21
|
+
uvMapping?: { startU: number; endU: number; startV: number; endV: number }
|
|
22
22
|
allowOrigins?: string[] | boolean
|
|
23
23
|
loop?: boolean
|
|
24
24
|
volume?: number
|
|
@@ -34,12 +34,7 @@ interface MediaData {
|
|
|
34
34
|
video: HTMLVideoElement | undefined
|
|
35
35
|
pausedBecuaseHidden: boolean
|
|
36
36
|
texture: THREE.Texture
|
|
37
|
-
updateUVMapping: (config: {
|
|
38
|
-
startU: number
|
|
39
|
-
endU: number
|
|
40
|
-
startV: number
|
|
41
|
-
endV: number
|
|
42
|
-
}) => void
|
|
37
|
+
updateUVMapping: (config: { startU: number; endU: number; startV: number; endV: number }) => void
|
|
43
38
|
positionalAudio?: THREE.PositionalAudio
|
|
44
39
|
hadAutoPlayError?: boolean
|
|
45
40
|
ended?: boolean
|
|
@@ -95,7 +90,7 @@ export class ThreeJsMedia {
|
|
|
95
90
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
96
91
|
|
|
97
92
|
// Add background color
|
|
98
|
-
ctx.fillStyle = `rgba(${background >> 16 & 255}, ${background >> 8 & 255}, ${background & 255}, 1)`
|
|
93
|
+
ctx.fillStyle = `rgba(${(background >> 16) & 255}, ${(background >> 8) & 255}, ${background & 255}, 1)`
|
|
99
94
|
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
|
100
95
|
|
|
101
96
|
// Add red text with size relative to canvas dimensions
|
|
@@ -167,7 +162,13 @@ export class ThreeJsMedia {
|
|
|
167
162
|
|
|
168
163
|
const originSecurityError = props.allowOrigins !== undefined && !this.validateOrigin(props.src, props.allowOrigins)
|
|
169
164
|
if (originSecurityError) {
|
|
170
|
-
console.warn(
|
|
165
|
+
console.warn(
|
|
166
|
+
'Remote resource blocked due to security policy',
|
|
167
|
+
props.src,
|
|
168
|
+
'allowed origins:',
|
|
169
|
+
props.allowOrigins,
|
|
170
|
+
'you can control it with `remoteContentNotSameOrigin` option'
|
|
171
|
+
)
|
|
171
172
|
props.src = ''
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -247,12 +248,11 @@ export class ThreeJsMedia {
|
|
|
247
248
|
})
|
|
248
249
|
}
|
|
249
250
|
|
|
250
|
-
|
|
251
251
|
// Create background texture first
|
|
252
252
|
const backgroundTexture = this.createBackgroundTexture(
|
|
253
253
|
props.size.width,
|
|
254
254
|
props.size.height,
|
|
255
|
-
props.background
|
|
255
|
+
props.background
|
|
256
256
|
// props.opacity ?? 1
|
|
257
257
|
)
|
|
258
258
|
|
|
@@ -278,30 +278,32 @@ export class ThreeJsMedia {
|
|
|
278
278
|
if (video) {
|
|
279
279
|
texture = new THREE.VideoTexture(video)
|
|
280
280
|
} else if (workerVideoUnsupported) {
|
|
281
|
-
texture = this.createErrorTexture(
|
|
282
|
-
props.size.width,
|
|
283
|
-
props.size.height,
|
|
284
|
-
props.background,
|
|
285
|
-
'Video unavailable (multi-thread)',
|
|
286
|
-
)
|
|
281
|
+
texture = this.createErrorTexture(props.size.width, props.size.height, props.background, 'Video unavailable (multi-thread)')
|
|
287
282
|
} else if (isWebWorker) {
|
|
288
283
|
const loaded = loadThreeJsTextureFromUrlSync(props.src)
|
|
289
284
|
texture = loaded.texture
|
|
290
285
|
texture.minFilter = THREE.NearestFilter
|
|
291
286
|
texture.magFilter = THREE.NearestFilter
|
|
292
|
-
void loaded.promise
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
287
|
+
void loaded.promise
|
|
288
|
+
.then(() => {
|
|
289
|
+
if (this.customMedia.get(id)?.texture === texture) {
|
|
290
|
+
material.map = texture
|
|
291
|
+
material.needsUpdate = true
|
|
292
|
+
}
|
|
293
|
+
})
|
|
294
|
+
.catch(() => handleError())
|
|
298
295
|
} else {
|
|
299
|
-
texture = new THREE.TextureLoader().load(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
296
|
+
texture = new THREE.TextureLoader().load(
|
|
297
|
+
props.src,
|
|
298
|
+
() => {
|
|
299
|
+
if (this.customMedia.get(id)?.texture === texture) {
|
|
300
|
+
material.map = texture
|
|
301
|
+
material.needsUpdate = true
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
undefined,
|
|
305
|
+
() => handleError()
|
|
306
|
+
) // todo cache
|
|
305
307
|
}
|
|
306
308
|
texture.minFilter = THREE.NearestFilter
|
|
307
309
|
texture.magFilter = THREE.NearestFilter
|
|
@@ -312,7 +314,13 @@ export class ThreeJsMedia {
|
|
|
312
314
|
// Create inner mesh for offsets
|
|
313
315
|
const mesh = new THREE.Mesh(geometry, material)
|
|
314
316
|
|
|
315
|
-
const { mesh: panel } = this.positionMeshExact(
|
|
317
|
+
const { mesh: panel } = this.positionMeshExact(
|
|
318
|
+
mesh,
|
|
319
|
+
THREE.MathUtils.degToRad((props.rotation ?? 0) * 90),
|
|
320
|
+
props.position,
|
|
321
|
+
props.size.width,
|
|
322
|
+
props.size.height
|
|
323
|
+
)
|
|
316
324
|
|
|
317
325
|
scene.add(panel)
|
|
318
326
|
|
|
@@ -336,7 +344,7 @@ export class ThreeJsMedia {
|
|
|
336
344
|
}
|
|
337
345
|
|
|
338
346
|
// UV mapping configuration
|
|
339
|
-
const updateUVMapping = (config: { startU: number
|
|
347
|
+
const updateUVMapping = (config: { startU: number; endU: number; startV: number; endV: number }) => {
|
|
340
348
|
const uvs = geometry.attributes.uv.array as Float32Array
|
|
341
349
|
uvs[0] = config.startU
|
|
342
350
|
uvs[1] = config.startV
|
|
@@ -368,7 +376,7 @@ export class ThreeJsMedia {
|
|
|
368
376
|
if (videoData.destroyed) return
|
|
369
377
|
console.error(`Failed to play video ${id}:`, err)
|
|
370
378
|
// TODO!
|
|
371
|
-
const t = /* translate ?? */
|
|
379
|
+
const t = /* translate ?? */ txt => txt
|
|
372
380
|
handleError(err.name === 'NotAllowedError' || err.name === 'AbortError' ? t('Waiting for user interaction') : t('Failed to auto play'))
|
|
373
381
|
}
|
|
374
382
|
}
|
|
@@ -398,14 +406,15 @@ export class ThreeJsMedia {
|
|
|
398
406
|
return
|
|
399
407
|
}
|
|
400
408
|
|
|
401
|
-
void videoData.video
|
|
409
|
+
void videoData.video
|
|
410
|
+
.play()
|
|
402
411
|
.then(() => {
|
|
403
412
|
videoData.hadAutoPlayError = false
|
|
404
413
|
console.log(`Playing video ${id}`)
|
|
405
414
|
})
|
|
406
415
|
.catch(err => {
|
|
407
416
|
if (videoData.pausedBecuaseHidden) return
|
|
408
|
-
if (err.name === 'NotAllowedError' || err.name === 'AbortError' || err.message?.includes('not allowed') && !videoData.pausedBecuaseHidden) {
|
|
417
|
+
if (err.name === 'NotAllowedError' || err.name === 'AbortError' || (err.message?.includes('not allowed') && !videoData.pausedBecuaseHidden)) {
|
|
409
418
|
videoData.hadAutoPlayError = true
|
|
410
419
|
}
|
|
411
420
|
videoData.handleError(err)
|
|
@@ -518,14 +527,7 @@ export class ThreeJsMedia {
|
|
|
518
527
|
* @param depth Depth of the mesh (default: 1)
|
|
519
528
|
* @returns The positioned mesh for chaining
|
|
520
529
|
*/
|
|
521
|
-
positionMeshExact(
|
|
522
|
-
mesh: THREE.Mesh,
|
|
523
|
-
rotation: number,
|
|
524
|
-
startPosition: { x: number, y: number, z: number },
|
|
525
|
-
width: number,
|
|
526
|
-
height: number,
|
|
527
|
-
depth = 1
|
|
528
|
-
) {
|
|
530
|
+
positionMeshExact(mesh: THREE.Mesh, rotation: number, startPosition: { x: number; y: number; z: number }, width: number, height: number, depth = 1) {
|
|
529
531
|
// avoid z-fighting with the ground plane
|
|
530
532
|
if (rotation === 0) {
|
|
531
533
|
startPosition.z += 0.001
|
|
@@ -536,7 +538,7 @@ export class ThreeJsMedia {
|
|
|
536
538
|
if (rotation === Math.PI) {
|
|
537
539
|
startPosition.z -= 0.001
|
|
538
540
|
}
|
|
539
|
-
if (rotation === 3 * Math.PI / 2) {
|
|
541
|
+
if (rotation === (3 * Math.PI) / 2) {
|
|
540
542
|
startPosition.x += 0.001
|
|
541
543
|
}
|
|
542
544
|
|
|
@@ -547,12 +549,11 @@ export class ThreeJsMedia {
|
|
|
547
549
|
if (rotation === Math.PI) {
|
|
548
550
|
startPosition.x += 1
|
|
549
551
|
}
|
|
550
|
-
if (rotation === 3 * Math.PI / 2) {
|
|
552
|
+
if (rotation === (3 * Math.PI) / 2) {
|
|
551
553
|
startPosition.z += 1
|
|
552
554
|
startPosition.x += 1
|
|
553
555
|
}
|
|
554
556
|
|
|
555
|
-
|
|
556
557
|
// First, clean up any previous transformations
|
|
557
558
|
mesh.matrix.identity()
|
|
558
559
|
mesh.position.set(0, 0, 0)
|
|
@@ -563,7 +564,7 @@ export class ThreeJsMedia {
|
|
|
563
564
|
// We need to set up the proper orientation for our use case
|
|
564
565
|
// Rotate the plane to face the correct direction based on the rotation parameter
|
|
565
566
|
mesh.rotateY(rotation)
|
|
566
|
-
if (rotation === Math.PI / 2 || rotation === 3 * Math.PI / 2) {
|
|
567
|
+
if (rotation === Math.PI / 2 || rotation === (3 * Math.PI) / 2) {
|
|
567
568
|
mesh.rotateZ(-Math.PI)
|
|
568
569
|
mesh.rotateX(-Math.PI)
|
|
569
570
|
}
|
|
@@ -585,36 +586,24 @@ export class ThreeJsMedia {
|
|
|
585
586
|
debugGroup.add(mesh)
|
|
586
587
|
|
|
587
588
|
// Add a marker at the starting position (should be exactly at pos)
|
|
588
|
-
const startMarker = new THREE.Mesh(
|
|
589
|
-
new THREE.BoxGeometry(0.1, 0.1, 0.1),
|
|
590
|
-
new THREE.MeshBasicMaterial({ color: 0xff_00_00 })
|
|
591
|
-
)
|
|
589
|
+
const startMarker = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0xff_00_00 }))
|
|
592
590
|
startMarker.position.set(startPosition.x, startPosition.y, startPosition.z)
|
|
593
591
|
debugGroup.add(startMarker)
|
|
594
592
|
|
|
595
593
|
// Add a marker at the end position (width units away in the rotated direction)
|
|
596
594
|
const endX = startPosition.x + Math.cos(rotation) * width
|
|
597
595
|
const endZ = startPosition.z + Math.sin(rotation) * width
|
|
598
|
-
const endYMarker = new THREE.Mesh(
|
|
599
|
-
new THREE.BoxGeometry(0.1, 0.1, 0.1),
|
|
600
|
-
new THREE.MeshBasicMaterial({ color: 0x00_00_ff })
|
|
601
|
-
)
|
|
596
|
+
const endYMarker = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0x00_00_ff }))
|
|
602
597
|
endYMarker.position.set(startPosition.x, startPosition.y + height, startPosition.z)
|
|
603
598
|
debugGroup.add(endYMarker)
|
|
604
599
|
|
|
605
600
|
// Add a marker at the width endpoint
|
|
606
|
-
const endWidthMarker = new THREE.Mesh(
|
|
607
|
-
new THREE.BoxGeometry(0.1, 0.1, 0.1),
|
|
608
|
-
new THREE.MeshBasicMaterial({ color: 0xff_ff_00 })
|
|
609
|
-
)
|
|
601
|
+
const endWidthMarker = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0xff_ff_00 }))
|
|
610
602
|
endWidthMarker.position.set(endX, startPosition.y, endZ)
|
|
611
603
|
debugGroup.add(endWidthMarker)
|
|
612
604
|
|
|
613
605
|
// Add a marker at the corner diagonal endpoint (both width and height)
|
|
614
|
-
const endCornerMarker = new THREE.Mesh(
|
|
615
|
-
new THREE.BoxGeometry(0.1, 0.1, 0.1),
|
|
616
|
-
new THREE.MeshBasicMaterial({ color: 0xff_00_ff })
|
|
617
|
-
)
|
|
606
|
+
const endCornerMarker = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0xff_00_ff }))
|
|
618
607
|
endCornerMarker.position.set(endX, startPosition.y + height, endZ)
|
|
619
608
|
debugGroup.add(endCornerMarker)
|
|
620
609
|
|
|
@@ -624,12 +613,7 @@ export class ThreeJsMedia {
|
|
|
624
613
|
this.worldRenderer.sceneOrigin.toSceneY(startPosition.y),
|
|
625
614
|
this.worldRenderer.sceneOrigin.toSceneZ(startPosition.z)
|
|
626
615
|
)
|
|
627
|
-
const directionHelper = new THREE.ArrowHelper(
|
|
628
|
-
new THREE.Vector3(Math.cos(rotation), 0, Math.sin(rotation)),
|
|
629
|
-
sceneStartPos,
|
|
630
|
-
1,
|
|
631
|
-
0xff_00_00
|
|
632
|
-
)
|
|
616
|
+
const directionHelper = new THREE.ArrowHelper(new THREE.Vector3(Math.cos(rotation), 0, Math.sin(rotation)), sceneStartPos, 1, 0xff_00_00)
|
|
633
617
|
debugGroup.add(directionHelper)
|
|
634
618
|
|
|
635
619
|
return {
|
|
@@ -708,8 +692,7 @@ export class ThreeJsMedia {
|
|
|
708
692
|
// Find if this object belongs to any media
|
|
709
693
|
for (const [id, videoData] of this.customMedia.entries()) {
|
|
710
694
|
// Check if the intersected object is part of our media mesh
|
|
711
|
-
if (intersectedObject === videoData.mesh ||
|
|
712
|
-
videoData.mesh.children.includes(intersectedObject)) {
|
|
695
|
+
if (intersectedObject === videoData.mesh || videoData.mesh.children.includes(intersectedObject)) {
|
|
713
696
|
const { uv } = intersection
|
|
714
697
|
if (uv) {
|
|
715
698
|
const result = {
|
|
@@ -3,23 +3,23 @@ import * as THREE from 'three'
|
|
|
3
3
|
import type { SceneOrigin } from './sceneOrigin'
|
|
4
4
|
|
|
5
5
|
interface ParticleMesh extends THREE.Mesh {
|
|
6
|
-
velocity: THREE.Vector3
|
|
7
|
-
worldPos: THREE.Vector3
|
|
6
|
+
velocity: THREE.Vector3
|
|
7
|
+
worldPos: THREE.Vector3
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
interface ParticleConfig {
|
|
11
|
-
fountainHeight: number
|
|
12
|
-
resetHeight: number
|
|
13
|
-
xVelocityRange: number
|
|
14
|
-
zVelocityRange: number
|
|
15
|
-
particleCount: number
|
|
16
|
-
particleRadiusRange: { min: number; max: number }
|
|
17
|
-
yVelocityRange: { min: number; max: number }
|
|
11
|
+
fountainHeight: number
|
|
12
|
+
resetHeight: number
|
|
13
|
+
xVelocityRange: number
|
|
14
|
+
zVelocityRange: number
|
|
15
|
+
particleCount: number
|
|
16
|
+
particleRadiusRange: { min: number; max: number }
|
|
17
|
+
yVelocityRange: { min: number; max: number }
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface FountainOptions {
|
|
21
|
-
position?: { x: number
|
|
22
|
-
particleConfig?: Partial<ParticleConfig
|
|
21
|
+
position?: { x: number; y: number; z: number }
|
|
22
|
+
particleConfig?: Partial<ParticleConfig>
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export class Fountain {
|
|
@@ -29,15 +29,17 @@ export class Fountain {
|
|
|
29
29
|
private readonly sceneOrigin: SceneOrigin | undefined
|
|
30
30
|
container: THREE.Object3D | undefined
|
|
31
31
|
|
|
32
|
-
constructor
|
|
32
|
+
constructor(
|
|
33
|
+
public sectionId: string,
|
|
34
|
+
options: FountainOptions = {},
|
|
35
|
+
sceneOrigin?: SceneOrigin
|
|
36
|
+
) {
|
|
33
37
|
this.position = options.position ? new THREE.Vector3(options.position.x, options.position.y, options.position.z) : new THREE.Vector3(0, 0, 0)
|
|
34
38
|
this.config = this.createConfig(options.particleConfig)
|
|
35
39
|
this.sceneOrigin = sceneOrigin
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
private createConfig
|
|
39
|
-
particleConfigOverride?: Partial<ParticleConfig>
|
|
40
|
-
): { particleConfig: ParticleConfig } {
|
|
42
|
+
private createConfig(particleConfigOverride?: Partial<ParticleConfig>): { particleConfig: ParticleConfig } {
|
|
41
43
|
const particleConfig: ParticleConfig = {
|
|
42
44
|
fountainHeight: 10,
|
|
43
45
|
resetHeight: 0,
|
|
@@ -52,27 +54,26 @@ export class Fountain {
|
|
|
52
54
|
return { particleConfig }
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
private toSceneX
|
|
57
|
+
private toSceneX(worldX: number): number {
|
|
56
58
|
return this.sceneOrigin ? this.sceneOrigin.toSceneX(worldX) : worldX
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
private toSceneY
|
|
61
|
+
private toSceneY(worldY: number): number {
|
|
60
62
|
return this.sceneOrigin ? this.sceneOrigin.toSceneY(worldY) : worldY
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
private toSceneZ
|
|
65
|
+
private toSceneZ(worldZ: number): number {
|
|
64
66
|
return this.sceneOrigin ? this.sceneOrigin.toSceneZ(worldZ) : worldZ
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
createParticles (container: THREE.Object3D): void {
|
|
69
|
+
createParticles(container: THREE.Object3D): void {
|
|
69
70
|
this.container = container
|
|
70
71
|
const colorStart = new THREE.Color(0xff_ff_00)
|
|
71
72
|
const colorEnd = new THREE.Color(0xff_a5_00)
|
|
72
73
|
|
|
73
74
|
for (let i = 0; i < this.config.particleConfig.particleCount; i++) {
|
|
74
|
-
const radius =
|
|
75
|
-
(this.config.particleConfig.particleRadiusRange.max - this.config.particleConfig.particleRadiusRange.min) +
|
|
75
|
+
const radius =
|
|
76
|
+
Math.random() * (this.config.particleConfig.particleRadiusRange.max - this.config.particleConfig.particleRadiusRange.min) +
|
|
76
77
|
this.config.particleConfig.particleRadiusRange.min
|
|
77
78
|
const geometry = new THREE.SphereGeometry(radius)
|
|
78
79
|
const material = new THREE.MeshBasicMaterial({
|
|
@@ -103,7 +104,7 @@ export class Fountain {
|
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
render
|
|
107
|
+
render(): void {
|
|
107
108
|
for (const particle of this.particles) {
|
|
108
109
|
particle.velocity.y -= 0.01 + Math.random() * 0.1
|
|
109
110
|
particle.worldPos.add(particle.velocity)
|
|
@@ -121,15 +122,11 @@ export class Fountain {
|
|
|
121
122
|
)
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
particle.position.set(
|
|
125
|
-
this.toSceneX(particle.worldPos.x),
|
|
126
|
-
this.toSceneY(particle.worldPos.y),
|
|
127
|
-
this.toSceneZ(particle.worldPos.z)
|
|
128
|
-
)
|
|
125
|
+
particle.position.set(this.toSceneX(particle.worldPos.x), this.toSceneY(particle.worldPos.y), this.toSceneZ(particle.worldPos.z))
|
|
129
126
|
}
|
|
130
127
|
}
|
|
131
128
|
|
|
132
|
-
private updateParticleCount
|
|
129
|
+
private updateParticleCount(newCount: number): void {
|
|
133
130
|
if (newCount !== this.config.particleConfig.particleCount) {
|
|
134
131
|
this.config.particleConfig.particleCount = newCount
|
|
135
132
|
const currentCount = this.particles.length
|
|
@@ -142,7 +139,7 @@ export class Fountain {
|
|
|
142
139
|
}
|
|
143
140
|
}
|
|
144
141
|
|
|
145
|
-
private addParticles
|
|
142
|
+
private addParticles(count: number): void {
|
|
146
143
|
const geometry = new THREE.SphereGeometry(0.1)
|
|
147
144
|
const material = new THREE.MeshBasicMaterial({ color: 0x00_ff_00 })
|
|
148
145
|
|
|
@@ -150,24 +147,18 @@ export class Fountain {
|
|
|
150
147
|
const mesh = new THREE.Mesh(geometry, material)
|
|
151
148
|
const particle = mesh as unknown as ParticleMesh
|
|
152
149
|
particle.worldPos = this.position.clone()
|
|
153
|
-
particle.position.set(
|
|
154
|
-
this.toSceneX(this.position.x),
|
|
155
|
-
this.toSceneY(this.position.y),
|
|
156
|
-
this.toSceneZ(this.position.z)
|
|
157
|
-
)
|
|
150
|
+
particle.position.set(this.toSceneX(this.position.x), this.toSceneY(this.position.y), this.toSceneZ(this.position.z))
|
|
158
151
|
particle.velocity = new THREE.Vector3(
|
|
159
|
-
Math.random() * this.config.particleConfig.xVelocityRange -
|
|
160
|
-
this.config.particleConfig.xVelocityRange / 2,
|
|
152
|
+
Math.random() * this.config.particleConfig.xVelocityRange - this.config.particleConfig.xVelocityRange / 2,
|
|
161
153
|
Math.random() * 2,
|
|
162
|
-
Math.random() * this.config.particleConfig.zVelocityRange -
|
|
163
|
-
this.config.particleConfig.zVelocityRange / 2
|
|
154
|
+
Math.random() * this.config.particleConfig.zVelocityRange - this.config.particleConfig.zVelocityRange / 2
|
|
164
155
|
)
|
|
165
156
|
this.particles.push(particle)
|
|
166
157
|
this.container!.add(particle)
|
|
167
158
|
}
|
|
168
159
|
}
|
|
169
160
|
|
|
170
|
-
private removeParticles
|
|
161
|
+
private removeParticles(count: number): void {
|
|
171
162
|
for (let i = 0; i < count; i++) {
|
|
172
163
|
const particle = this.particles.pop()
|
|
173
164
|
if (particle) {
|
|
@@ -176,7 +167,7 @@ export class Fountain {
|
|
|
176
167
|
}
|
|
177
168
|
}
|
|
178
169
|
|
|
179
|
-
public dispose
|
|
170
|
+
public dispose(): void {
|
|
180
171
|
for (const particle of this.particles) {
|
|
181
172
|
particle.geometry.dispose()
|
|
182
173
|
if (Array.isArray(particle.material)) {
|
|
@@ -15,7 +15,7 @@ export class ThreeJsSound implements SoundSystem {
|
|
|
15
15
|
this.stopAll()
|
|
16
16
|
})
|
|
17
17
|
|
|
18
|
-
worldRenderer.onReactiveConfigUpdated('volume',
|
|
18
|
+
worldRenderer.onReactiveConfigUpdated('volume', volume => {
|
|
19
19
|
this.changeVolume(volume)
|
|
20
20
|
})
|
|
21
21
|
}
|
|
@@ -26,7 +26,7 @@ export class ThreeJsSound implements SoundSystem {
|
|
|
26
26
|
this.worldRenderer.camera.add(this.audioListener)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
playSound(position: { x: number
|
|
29
|
+
playSound(position: { x: number; y: number; z: number }, path: string, volume = 1, pitch = 1, timeout = 500) {
|
|
30
30
|
this.initAudioListener()
|
|
31
31
|
|
|
32
32
|
const sound = new THREE.PositionalAudio(this.audioListener!)
|
|
@@ -35,7 +35,7 @@ export class ThreeJsSound implements SoundSystem {
|
|
|
35
35
|
|
|
36
36
|
const audioLoader = new THREE.AudioLoader()
|
|
37
37
|
const start = Date.now()
|
|
38
|
-
void audioLoader.loadAsync(path).then(
|
|
38
|
+
void audioLoader.loadAsync(path).then(buffer => {
|
|
39
39
|
if (Date.now() - start > timeout) {
|
|
40
40
|
console.warn('Ignored playing sound', path, 'due to timeout:', timeout, 'ms <', Date.now() - start, 'ms')
|
|
41
41
|
return
|
|
@@ -70,17 +70,17 @@ export const loadThreeJsTextureFromBitmap = (image: ImageBitmap) => {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/** Worker-safe sync handle; image loads via fetch + OffscreenCanvas (not TextureLoader). */
|
|
73
|
-
export function loadNearestFilterTexture
|
|
73
|
+
export function loadNearestFilterTexture(imageUrl: string): THREE.Texture {
|
|
74
74
|
const { texture, promise } = loadThreeJsTextureFromUrlSync(imageUrl)
|
|
75
75
|
texture.magFilter = THREE.NearestFilter
|
|
76
76
|
texture.minFilter = THREE.NearestFilter
|
|
77
|
-
void promise.catch(
|
|
77
|
+
void promise.catch(err => {
|
|
78
78
|
console.error('[texture] failed to load', imageUrl, err)
|
|
79
79
|
})
|
|
80
80
|
return texture
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
export async function loadTexture
|
|
83
|
+
export async function loadTexture(texture: string, cb: (texture: THREE.Texture) => void, onLoad?: () => void): Promise<void> {
|
|
84
84
|
const cached = textureCache[texture]
|
|
85
85
|
if (!cached) {
|
|
86
86
|
const { promise, resolve } = Promise.withResolvers<THREE.Texture>()
|
package/src/three/threeWorker.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import { augmentWorkerMcData } from '../lib/buildWorkerMcDataIndexes'
|
|
3
3
|
|
|
4
|
-
globalThis.structuredClone ??=
|
|
4
|
+
globalThis.structuredClone ??= value => JSON.parse(JSON.stringify(value))
|
|
5
5
|
|
|
6
6
|
const applyWorkerMcData = (raw: Record<string, unknown>) => {
|
|
7
7
|
augmentWorkerMcData(raw)
|
|
@@ -23,7 +23,7 @@ self.addEventListener('message', (event: MessageEvent) => {
|
|
|
23
23
|
|
|
24
24
|
if (Array.isArray(data)) {
|
|
25
25
|
// eslint-disable-next-line unicorn/no-array-for-each
|
|
26
|
-
data.forEach(
|
|
26
|
+
data.forEach(msg => {
|
|
27
27
|
if (msg.type === 'mcData') {
|
|
28
28
|
applyWorkerMcData(msg.mcData)
|
|
29
29
|
}
|