minecraft-renderer 0.1.42 → 0.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mesher.js +52 -52
- package/dist/mesher.js.map +3 -3
- package/dist/mesherWasm.js +51 -51
- package/dist/minecraft-renderer.js +59 -59
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +458 -458
- package/package.json +1 -1
- package/src/graphicsBackend/appViewer.ts +19 -7
- package/src/graphicsBackend/types.ts +5 -1
- package/src/index.ts +33 -0
- package/src/lib/ui/newStats.ts +16 -2
- package/src/lib/worldrendererCommon.ts +3 -2
- package/src/mesher-legacy/mesher.ts +10 -1
- package/src/mesher-shared/models.ts +41 -0
- package/src/mesher-shared/shared.ts +2 -0
- package/src/three/entities.ts +22 -6
- package/src/three/graphicsBackendBase.ts +28 -20
- package/src/three/graphicsBackendOffThread.ts +1 -2
- package/src/three/menuBackground/activeView.ts +19 -0
- package/src/three/menuBackground/classic.ts +148 -0
- package/src/three/menuBackground/config.ts +23 -0
- package/src/three/menuBackground/defaultOptions.ts +141 -0
- package/src/three/menuBackground/futuristic.ts +859 -0
- package/src/three/menuBackground/index.ts +36 -0
- package/src/three/menuBackground/renderer.ts +97 -0
- package/src/three/menuBackground/shared.ts +3 -0
- package/src/three/menuBackground/types.ts +37 -0
- package/src/three/menuBackground/worldBlocks.ts +144 -0
- package/src/three/modules/sciFiWorldReveal.ts +6 -0
- package/src/three/waypointSprite.ts +108 -106
- package/src/three/worldRendererThree.ts +10 -13
- package/src/wasm-mesher/runtime-build/wasm_mesher.d.ts +25 -0
- package/src/wasm-mesher/runtime-build/wasm_mesher.js +68 -0
- package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
- package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm.d.ts +2 -0
- package/src/wasm-mesher/worker/mesherWasm.ts +14 -0
- package/src/three/panorama.ts +0 -312
- package/src/three/panoramaShared.ts +0 -2
|
@@ -9,7 +9,7 @@ import { renderSign } from '../sign-renderer'
|
|
|
9
9
|
import { DisplayWorldOptions, GraphicsInitOptions } from '../graphicsBackend/types'
|
|
10
10
|
import { chunkPos, sectionPos } from '../lib/simpleUtils'
|
|
11
11
|
import { WorldRendererCommon } from '../lib/worldrendererCommon'
|
|
12
|
-
import { addNewStat } from '../lib/ui/newStats'
|
|
12
|
+
import { addNewStat, MC_RENDERER_DEBUG_OVERLAY_CLASS } from '../lib/ui/newStats'
|
|
13
13
|
import { MesherGeometryOutput } from '../mesher-shared/shared'
|
|
14
14
|
import { ItemSpecificContextProperties } from '../playerState/types'
|
|
15
15
|
import { setBlockPosition } from '../mesher-shared/standaloneRenderer'
|
|
@@ -387,7 +387,7 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
387
387
|
if ((prop === 'x' || prop === 'y' || prop === 'z') && typeof value === 'number' && Math.abs(value) > WORLD_COORD_THRESHOLD) {
|
|
388
388
|
warnOnce()
|
|
389
389
|
}
|
|
390
|
-
;(target as any)[prop] = value
|
|
390
|
+
; (target as any)[prop] = value
|
|
391
391
|
return true
|
|
392
392
|
},
|
|
393
393
|
get(target, prop, receiver) {
|
|
@@ -701,22 +701,19 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
701
701
|
addDebugOverlay() {
|
|
702
702
|
if (this.debugOverlayAdded) return
|
|
703
703
|
this.debugOverlayAdded = true
|
|
704
|
-
const pane = addNewStat('debug-overlay')
|
|
704
|
+
const pane = addNewStat('debug-overlay', 80, 0, undefined, { className: MC_RENDERER_DEBUG_OVERLAY_CLASS })
|
|
705
705
|
setInterval(() => {
|
|
706
706
|
pane.setVisibility(this.displayAdvancedStats)
|
|
707
707
|
if (this.displayAdvancedStats) {
|
|
708
|
-
const
|
|
709
|
-
|
|
710
|
-
}
|
|
708
|
+
const formatFull = (num: number) => new Intl.NumberFormat('en-US', {}).format(num)
|
|
709
|
+
const formatCompact = (num: number) => new Intl.NumberFormat('en-US', { notation: 'compact', maximumFractionDigits: 1 }).format(num)
|
|
711
710
|
let text = ''
|
|
712
|
-
text += `
|
|
713
|
-
text += `
|
|
714
|
-
text += `
|
|
715
|
-
text += `F: ${formatBigNumber(this.tilesRendered)} `
|
|
716
|
-
text += `B: ${formatBigNumber(this.blocksRendered)} `
|
|
711
|
+
text += `TE: ${formatFull(this.renderer.info.memory.textures)} `
|
|
712
|
+
text += `F: ${formatCompact(this.tilesRendered)} `
|
|
713
|
+
text += `B: ${formatCompact(this.blocksRendered)} `
|
|
717
714
|
text += `MEM: ${this.chunkMeshManager.getEstimatedMemoryUsage().total} `
|
|
718
715
|
const poolStats = this.chunkMeshManager.getStats()
|
|
719
|
-
text += `POOL: ${poolStats.activeCount}/${poolStats.poolSize}
|
|
716
|
+
text += `POOL: ${poolStats.activeCount}/${poolStats.poolSize}`
|
|
720
717
|
pane.updateText(text)
|
|
721
718
|
this.backendInfoReport = text
|
|
722
719
|
}
|
|
@@ -909,7 +906,7 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
909
906
|
const yOffset = this.playerStateReactive.eyeHeight
|
|
910
907
|
|
|
911
908
|
this.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch)
|
|
912
|
-
this.media.tryIntersectMedia()
|
|
909
|
+
// this.media.tryIntersectMedia()
|
|
913
910
|
this.updateCameraSectionPos()
|
|
914
911
|
}
|
|
915
912
|
|
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
/* tslint:disable */
|
|
3
3
|
/* eslint-disable */
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Compute wireframe edge positions from a triangle mesh.
|
|
7
|
+
*
|
|
8
|
+
* Takes flat position and index arrays from an assembled mesh and returns a
|
|
9
|
+
* flat array of line-segment positions (x1,y1,z1,x2,y2,z2, ...) representing
|
|
10
|
+
* the unique edges of the mesh. Edge deduplication uses a `HashSet<(u32,u32)>`
|
|
11
|
+
* keyed on (min_vertex_index, max_vertex_index).
|
|
12
|
+
*
|
|
13
|
+
* `positions` — flat `Float32Array` of vertex positions (3 floats per vertex).
|
|
14
|
+
* `indices` — flat `Uint32Array` of triangle indices (3 indices per triangle).
|
|
15
|
+
* For 16-bit index arrays, prefer [`compute_wireframe_edges_u16`]
|
|
16
|
+
* to avoid an extra JS-side `Uint32Array` allocation.
|
|
17
|
+
*/
|
|
18
|
+
export function computeWireframeEdges(positions: Float32Array, indices: Uint32Array): Float32Array;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Same as [`compute_wireframe_edges`] but accepts a `Uint16Array` of indices.
|
|
22
|
+
*
|
|
23
|
+
* Avoids the JS-side `new Uint32Array(uint16)` allocation when the assembled
|
|
24
|
+
* section uses 16-bit indices (typical for sections with < 65k vertices).
|
|
25
|
+
*/
|
|
26
|
+
export function computeWireframeEdgesU16(positions: Float32Array, indices: Uint16Array): Float32Array;
|
|
27
|
+
|
|
5
28
|
/**
|
|
6
29
|
* VITALY's path: parse 1.18+ dump + light → run the mesher → return ONLY the final
|
|
7
30
|
* geometry. Avoids marshalling the intermediate ~300KB block_states/biomes/lights
|
|
@@ -218,6 +241,8 @@ export interface InitOutput {
|
|
|
218
241
|
readonly generateGeometryFromParsedV16V17: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number) => any;
|
|
219
242
|
readonly generateGeometryFromMapChunkV18PlusMulti: (a: any, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number) => any;
|
|
220
243
|
readonly generateGeometryFromParsedV16V17Multi: (a: any, b: number, c: number, d: number, e: number, f: number, g: any, h: number, i: any, j: any, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number, h1: number) => any;
|
|
244
|
+
readonly computeWireframeEdges: (a: number, b: number, c: number, d: number) => [number, number];
|
|
245
|
+
readonly computeWireframeEdgesU16: (a: number, b: number, c: number, d: number) => [number, number];
|
|
221
246
|
readonly parseUpdateLightV17: (a: number, b: number, c: number) => any;
|
|
222
247
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
223
248
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
@@ -71,6 +71,11 @@ function debugString(val) {
|
|
|
71
71
|
return className;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
function getArrayF32FromWasm0(ptr, len) {
|
|
75
|
+
ptr = ptr >>> 0;
|
|
76
|
+
return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
function getArrayI32FromWasm0(ptr, len) {
|
|
75
80
|
ptr = ptr >>> 0;
|
|
76
81
|
return getInt32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
|
|
@@ -94,6 +99,14 @@ function getDataViewMemory0() {
|
|
|
94
99
|
return cachedDataViewMemory0;
|
|
95
100
|
}
|
|
96
101
|
|
|
102
|
+
let cachedFloat32ArrayMemory0 = null;
|
|
103
|
+
function getFloat32ArrayMemory0() {
|
|
104
|
+
if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) {
|
|
105
|
+
cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer);
|
|
106
|
+
}
|
|
107
|
+
return cachedFloat32ArrayMemory0;
|
|
108
|
+
}
|
|
109
|
+
|
|
97
110
|
let cachedInt32ArrayMemory0 = null;
|
|
98
111
|
function getInt32ArrayMemory0() {
|
|
99
112
|
if (cachedInt32ArrayMemory0 === null || cachedInt32ArrayMemory0.byteLength === 0) {
|
|
@@ -161,6 +174,13 @@ function passArray8ToWasm0(arg, malloc) {
|
|
|
161
174
|
return ptr;
|
|
162
175
|
}
|
|
163
176
|
|
|
177
|
+
function passArrayF32ToWasm0(arg, malloc) {
|
|
178
|
+
const ptr = malloc(arg.length * 4, 4) >>> 0;
|
|
179
|
+
getFloat32ArrayMemory0().set(arg, ptr / 4);
|
|
180
|
+
WASM_VECTOR_LEN = arg.length;
|
|
181
|
+
return ptr;
|
|
182
|
+
}
|
|
183
|
+
|
|
164
184
|
function passStringToWasm0(arg, malloc, realloc) {
|
|
165
185
|
if (realloc === undefined) {
|
|
166
186
|
const buf = cachedTextEncoder.encode(arg);
|
|
@@ -227,6 +247,53 @@ if (!('encodeInto' in cachedTextEncoder)) {
|
|
|
227
247
|
|
|
228
248
|
let WASM_VECTOR_LEN = 0;
|
|
229
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Compute wireframe edge positions from a triangle mesh.
|
|
252
|
+
*
|
|
253
|
+
* Takes flat position and index arrays from an assembled mesh and returns a
|
|
254
|
+
* flat array of line-segment positions (x1,y1,z1,x2,y2,z2, ...) representing
|
|
255
|
+
* the unique edges of the mesh. Edge deduplication uses a `HashSet<(u32,u32)>`
|
|
256
|
+
* keyed on (min_vertex_index, max_vertex_index).
|
|
257
|
+
*
|
|
258
|
+
* `positions` — flat `Float32Array` of vertex positions (3 floats per vertex).
|
|
259
|
+
* `indices` — flat `Uint32Array` of triangle indices (3 indices per triangle).
|
|
260
|
+
* For 16-bit index arrays, prefer [`compute_wireframe_edges_u16`]
|
|
261
|
+
* to avoid an extra JS-side `Uint32Array` allocation.
|
|
262
|
+
* @param {Float32Array} positions
|
|
263
|
+
* @param {Uint32Array} indices
|
|
264
|
+
* @returns {Float32Array}
|
|
265
|
+
*/
|
|
266
|
+
export function computeWireframeEdges(positions, indices) {
|
|
267
|
+
const ptr0 = passArrayF32ToWasm0(positions, wasm.__wbindgen_malloc);
|
|
268
|
+
const len0 = WASM_VECTOR_LEN;
|
|
269
|
+
const ptr1 = passArray32ToWasm0(indices, wasm.__wbindgen_malloc);
|
|
270
|
+
const len1 = WASM_VECTOR_LEN;
|
|
271
|
+
const ret = wasm.computeWireframeEdges(ptr0, len0, ptr1, len1);
|
|
272
|
+
var v3 = getArrayF32FromWasm0(ret[0], ret[1]).slice();
|
|
273
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
274
|
+
return v3;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Same as [`compute_wireframe_edges`] but accepts a `Uint16Array` of indices.
|
|
279
|
+
*
|
|
280
|
+
* Avoids the JS-side `new Uint32Array(uint16)` allocation when the assembled
|
|
281
|
+
* section uses 16-bit indices (typical for sections with < 65k vertices).
|
|
282
|
+
* @param {Float32Array} positions
|
|
283
|
+
* @param {Uint16Array} indices
|
|
284
|
+
* @returns {Float32Array}
|
|
285
|
+
*/
|
|
286
|
+
export function computeWireframeEdgesU16(positions, indices) {
|
|
287
|
+
const ptr0 = passArrayF32ToWasm0(positions, wasm.__wbindgen_malloc);
|
|
288
|
+
const len0 = WASM_VECTOR_LEN;
|
|
289
|
+
const ptr1 = passArray16ToWasm0(indices, wasm.__wbindgen_malloc);
|
|
290
|
+
const len1 = WASM_VECTOR_LEN;
|
|
291
|
+
const ret = wasm.computeWireframeEdgesU16(ptr0, len0, ptr1, len1);
|
|
292
|
+
var v3 = getArrayF32FromWasm0(ret[0], ret[1]).slice();
|
|
293
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
|
|
294
|
+
return v3;
|
|
295
|
+
}
|
|
296
|
+
|
|
230
297
|
/**
|
|
231
298
|
* VITALY's path: parse 1.18+ dump + light → run the mesher → return ONLY the final
|
|
232
299
|
* geometry. Avoids marshalling the intermediate ~300KB block_states/biomes/lights
|
|
@@ -1001,6 +1068,7 @@ function __wbg_finalize_init(instance, module) {
|
|
|
1001
1068
|
wasm = instance.exports;
|
|
1002
1069
|
__wbg_init.__wbindgen_wasm_module = module;
|
|
1003
1070
|
cachedDataViewMemory0 = null;
|
|
1071
|
+
cachedFloat32ArrayMemory0 = null;
|
|
1004
1072
|
cachedInt32ArrayMemory0 = null;
|
|
1005
1073
|
cachedUint16ArrayMemory0 = null;
|
|
1006
1074
|
cachedUint32ArrayMemory0 = null;
|
|
Binary file
|
|
@@ -16,6 +16,8 @@ export const parseChunkSectionsV16V17: (a: number, b: number, c: number, d: numb
|
|
|
16
16
|
export const generateGeometryFromParsedV16V17: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number) => any;
|
|
17
17
|
export const generateGeometryFromMapChunkV18PlusMulti: (a: any, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number) => any;
|
|
18
18
|
export const generateGeometryFromParsedV16V17Multi: (a: any, b: number, c: number, d: number, e: number, f: number, g: any, h: number, i: any, j: any, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number, h1: number) => any;
|
|
19
|
+
export const computeWireframeEdges: (a: number, b: number, c: number, d: number) => [number, number];
|
|
20
|
+
export const computeWireframeEdgesU16: (a: number, b: number, c: number, d: number) => [number, number];
|
|
19
21
|
export const parseUpdateLightV17: (a: number, b: number, c: number) => any;
|
|
20
22
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
21
23
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
@@ -1347,6 +1347,20 @@ function processColumnTick() {
|
|
|
1347
1347
|
//@ts-ignore
|
|
1348
1348
|
geometry.indices?.buffer,
|
|
1349
1349
|
].filter(Boolean)
|
|
1350
|
+
|
|
1351
|
+
if (exported.geometry.indices.length > 0 && config.computeWireframeEdges) {
|
|
1352
|
+
try {
|
|
1353
|
+
const wireframeF32 = geometry.indices instanceof Uint32Array
|
|
1354
|
+
? wasm!.computeWireframeEdges(geometry.positions as Float32Array, geometry.indices)
|
|
1355
|
+
: wasm!.computeWireframeEdgesU16(geometry.positions as Float32Array, geometry.indices as Uint16Array)
|
|
1356
|
+
if (wireframeF32.length > 0) {
|
|
1357
|
+
geometry.wireframePositions = wireframeF32
|
|
1358
|
+
transferable.push(wireframeF32.buffer)
|
|
1359
|
+
}
|
|
1360
|
+
} catch (err) {
|
|
1361
|
+
// Fall through — sciFiWorldReveal will fall back to main-thread computation
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1350
1364
|
} else {
|
|
1351
1365
|
geometry = makeEmptyColumnGeometry(sx, sy, sz, sectionHeight, false)
|
|
1352
1366
|
// Still attach block entity metadata so the main thread sees
|
package/src/three/panorama.ts
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
//@ts-nocheck
|
|
2
|
-
import { join } from 'path'
|
|
3
|
-
import * as THREE from 'three'
|
|
4
|
-
import { getSyncWorld } from '../playground/shared'
|
|
5
|
-
import { Vec3 } from 'vec3'
|
|
6
|
-
import * as tweenJs from '@tweenjs/tween.js'
|
|
7
|
-
import type { GraphicsInitOptions } from '../graphicsBackend/types'
|
|
8
|
-
import { WorldRendererCommon } from '../lib/worldrendererCommon'
|
|
9
|
-
import { defaultWorldRendererConfig, getDefaultRendererState } from '../graphicsBackend/config'
|
|
10
|
-
import { ResourcesManager, ResourcesManagerTransferred } from '../resourcesManager/resourcesManager'
|
|
11
|
-
import { getInitialPlayerStateRenderer } from '../graphicsBackend/playerState'
|
|
12
|
-
import { loadThreeJsTextureFromUrl, loadThreeJsTextureFromUrlSync } from './threeJsUtils'
|
|
13
|
-
import { WorldRendererThree } from './worldRendererThree'
|
|
14
|
-
import { EntityMesh } from './entity/EntityMesh'
|
|
15
|
-
import { DocumentRenderer } from './documentRenderer'
|
|
16
|
-
import { PANORAMA_VERSION } from './panoramaShared'
|
|
17
|
-
import { WorldView } from '../worldView'
|
|
18
|
-
|
|
19
|
-
const date = new Date()
|
|
20
|
-
const isChristmas = date.getMonth() === 11 && date.getDate() >= 24 && date.getDate() <= 26
|
|
21
|
-
|
|
22
|
-
const panoramaFiles = [
|
|
23
|
-
'panorama_3.webp', // right (+x)
|
|
24
|
-
'panorama_1.webp', // left (-x)
|
|
25
|
-
'panorama_4.webp', // top (+y)
|
|
26
|
-
'panorama_5.webp', // bottom (-y)
|
|
27
|
-
'panorama_0.webp', // front (+z)
|
|
28
|
-
'panorama_2.webp', // back (-z)
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
export class PanoramaRenderer {
|
|
32
|
-
private readonly camera: THREE.PerspectiveCamera
|
|
33
|
-
private scene: THREE.Scene
|
|
34
|
-
private readonly ambientLight: THREE.AmbientLight
|
|
35
|
-
private readonly directionalLight: THREE.DirectionalLight
|
|
36
|
-
private panoramaGroup: THREE.Object3D | null = null
|
|
37
|
-
private time = 0
|
|
38
|
-
private readonly abortController = new AbortController()
|
|
39
|
-
private worldRenderer: WorldRendererCommon | WorldRendererThree | undefined
|
|
40
|
-
public WorldRendererClass = WorldRendererThree
|
|
41
|
-
public startTimes = new Map<THREE.MeshBasicMaterial, number>()
|
|
42
|
-
|
|
43
|
-
constructor(private readonly documentRenderer: DocumentRenderer, private readonly options: GraphicsInitOptions, private readonly doWorldBlocksPanorama = false) {
|
|
44
|
-
this.scene = new THREE.Scene()
|
|
45
|
-
// #324568
|
|
46
|
-
this.scene.background = new THREE.Color(0x32_45_68)
|
|
47
|
-
|
|
48
|
-
// Add ambient light
|
|
49
|
-
this.ambientLight = new THREE.AmbientLight(0xcc_cc_cc)
|
|
50
|
-
this.scene.add(this.ambientLight)
|
|
51
|
-
|
|
52
|
-
// Add directional light
|
|
53
|
-
this.directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5)
|
|
54
|
-
this.directionalLight.position.set(1, 1, 0.5).normalize()
|
|
55
|
-
this.directionalLight.castShadow = true
|
|
56
|
-
this.scene.add(this.directionalLight)
|
|
57
|
-
|
|
58
|
-
this.camera = new THREE.PerspectiveCamera(85, this.documentRenderer.canvas.width / this.documentRenderer.canvas.height, 0.05, 1000)
|
|
59
|
-
this.camera.position.set(0, 0, 0)
|
|
60
|
-
this.camera.rotation.set(0, 0, 0)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async start() {
|
|
64
|
-
if (this.doWorldBlocksPanorama) {
|
|
65
|
-
await this.worldBlocksPanorama()
|
|
66
|
-
} else {
|
|
67
|
-
this.addClassicPanorama()
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this.documentRenderer.render = (sizeChanged = false) => {
|
|
72
|
-
if (sizeChanged) {
|
|
73
|
-
this.camera.aspect = this.documentRenderer.canvas.width / this.documentRenderer.canvas.height
|
|
74
|
-
this.camera.updateProjectionMatrix()
|
|
75
|
-
}
|
|
76
|
-
this.documentRenderer.renderer.render(this.scene, this.camera)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async debugImageInFrontOfCamera() {
|
|
81
|
-
const image = await loadThreeJsTextureFromUrl(join('background', 'panorama_0.webp'))
|
|
82
|
-
const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000), new THREE.MeshBasicMaterial({ map: image }))
|
|
83
|
-
mesh.position.set(0, 0, -500)
|
|
84
|
-
mesh.rotation.set(0, 0, 0)
|
|
85
|
-
this.scene.add(mesh)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
addClassicPanorama() {
|
|
89
|
-
const panorGeo = new THREE.BoxGeometry(1000, 1000, 1000)
|
|
90
|
-
const panorMaterials = [] as THREE.MeshBasicMaterial[]
|
|
91
|
-
const fadeInDuration = 200
|
|
92
|
-
|
|
93
|
-
// void this.debugImageInFrontOfCamera()
|
|
94
|
-
|
|
95
|
-
for (const file of panoramaFiles) {
|
|
96
|
-
const load = async () => {
|
|
97
|
-
const { texture } = loadThreeJsTextureFromUrlSync(join('background', isChristmas ? 'christmas' : '', file))
|
|
98
|
-
|
|
99
|
-
// Instead of using repeat/offset to flip, we'll use the texture matrix
|
|
100
|
-
texture.matrixAutoUpdate = false
|
|
101
|
-
texture.matrix.set(
|
|
102
|
-
-1, 0, 1, 0, 1, 0, 0, 0, 1
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
texture.wrapS = THREE.ClampToEdgeWrapping
|
|
106
|
-
texture.wrapT = THREE.ClampToEdgeWrapping
|
|
107
|
-
texture.minFilter = THREE.LinearFilter
|
|
108
|
-
texture.magFilter = THREE.LinearFilter
|
|
109
|
-
|
|
110
|
-
const material = new THREE.MeshBasicMaterial({
|
|
111
|
-
map: texture,
|
|
112
|
-
transparent: true,
|
|
113
|
-
side: THREE.DoubleSide,
|
|
114
|
-
depthWrite: false,
|
|
115
|
-
opacity: 0 // Start with 0 opacity
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
// Start fade-in when texture is loaded
|
|
119
|
-
this.startTimes.set(material, Date.now())
|
|
120
|
-
panorMaterials.push(material)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
void load()
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const panoramaBox = new THREE.Mesh(panorGeo, panorMaterials)
|
|
127
|
-
panoramaBox.onBeforeRender = () => {
|
|
128
|
-
this.time += 0.01
|
|
129
|
-
panoramaBox.rotation.y = Math.PI + this.time * 0.01
|
|
130
|
-
panoramaBox.rotation.z = Math.sin(-this.time * 0.001) * 0.001
|
|
131
|
-
|
|
132
|
-
// Time-based fade in animation for each material
|
|
133
|
-
for (const material of panorMaterials) {
|
|
134
|
-
const startTime = this.startTimes.get(material)
|
|
135
|
-
if (startTime) {
|
|
136
|
-
const elapsed = Date.now() - startTime
|
|
137
|
-
const progress = Math.min(1, elapsed / fadeInDuration)
|
|
138
|
-
material.opacity = progress
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const group = new THREE.Object3D()
|
|
144
|
-
group.add(panoramaBox)
|
|
145
|
-
|
|
146
|
-
if (!isChristmas) {
|
|
147
|
-
// Add entities
|
|
148
|
-
for (let i = 0; i < 20; i++) {
|
|
149
|
-
const m = new EntityMesh('1.16.4', 'squid').mesh
|
|
150
|
-
m.position.set(Math.random() * 30 - 15, Math.random() * 20 - 10, Math.random() * 10 - 17)
|
|
151
|
-
m.rotation.set(0, Math.PI + Math.random(), -Math.PI / 4, 'ZYX')
|
|
152
|
-
const v = Math.random() * 0.01
|
|
153
|
-
m.children[0].onBeforeRender = () => {
|
|
154
|
-
m.rotation.y += v
|
|
155
|
-
m.rotation.z = Math.cos(panoramaBox.rotation.y * 3) * Math.PI / 4 - Math.PI / 2
|
|
156
|
-
}
|
|
157
|
-
group.add(m)
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
this.scene.add(group)
|
|
162
|
-
this.panoramaGroup = group
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async worldBlocksPanorama() {
|
|
166
|
-
const version = PANORAMA_VERSION
|
|
167
|
-
|
|
168
|
-
const fullResourceManager = new ResourcesManager()
|
|
169
|
-
|
|
170
|
-
fullResourceManager.currentConfig = { version, noInventoryGui: true, }
|
|
171
|
-
await fullResourceManager.updateAssetsData?.({})
|
|
172
|
-
if (this.abortController.signal.aborted) return
|
|
173
|
-
console.time('load panorama scene')
|
|
174
|
-
const world = getSyncWorld(version)
|
|
175
|
-
const PrismarineBlock = require('prismarine-block')
|
|
176
|
-
const Block = PrismarineBlock(version)
|
|
177
|
-
const mcData = (globalThis as any).mcData
|
|
178
|
-
const fullBlocks = mcData.blocksArray.filter(block => {
|
|
179
|
-
// if (block.name.includes('leaves')) return false
|
|
180
|
-
if (/* !block.name.includes('wool') && */!block.name.includes('stained_glass')/* && !block.name.includes('terracotta') */) return false
|
|
181
|
-
const b = Block.fromStateId(block.defaultState, 0)
|
|
182
|
-
if (b.shapes?.length !== 1) return false
|
|
183
|
-
const shape = b.shapes[0]
|
|
184
|
-
return shape[0] === 0 && shape[1] === 0 && shape[2] === 0 && shape[3] === 1 && shape[4] === 1 && shape[5] === 1
|
|
185
|
-
})
|
|
186
|
-
const Z = -15
|
|
187
|
-
const sizeX = 100
|
|
188
|
-
const sizeY = 100
|
|
189
|
-
for (let x = -sizeX; x < sizeX; x++) {
|
|
190
|
-
for (let y = -sizeY; y < sizeY; y++) {
|
|
191
|
-
const block = fullBlocks[Math.floor(Math.random() * fullBlocks.length)]
|
|
192
|
-
world.setBlockStateId(new Vec3(x, y, Z), block.defaultState)
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
this.camera.updateProjectionMatrix()
|
|
196
|
-
this.camera.position.set(0.5, sizeY / 2 + 0.5, 0.5)
|
|
197
|
-
this.camera.rotation.set(0, 0, 0)
|
|
198
|
-
const initPos = new Vec3(...this.camera.position.toArray())
|
|
199
|
-
const worldView = new WorldView(world, 2, initPos)
|
|
200
|
-
// worldView.addWaitTime = 0
|
|
201
|
-
if (this.abortController.signal.aborted) return
|
|
202
|
-
|
|
203
|
-
this.worldRenderer = new this.WorldRendererClass(
|
|
204
|
-
this.documentRenderer.renderer,
|
|
205
|
-
this.options,
|
|
206
|
-
{
|
|
207
|
-
version,
|
|
208
|
-
worldView,
|
|
209
|
-
inWorldRenderingConfig: defaultWorldRendererConfig,
|
|
210
|
-
playerStateReactive: getInitialPlayerStateRenderer().reactive,
|
|
211
|
-
rendererState: getDefaultRendererState().reactive,
|
|
212
|
-
nonReactiveState: getDefaultRendererState().nonReactive,
|
|
213
|
-
resourcesManager: fullResourceManager as ResourcesManagerTransferred // todo use guard instead
|
|
214
|
-
}
|
|
215
|
-
)
|
|
216
|
-
if (this.worldRenderer instanceof WorldRendererThree) {
|
|
217
|
-
this.scene = this.worldRenderer.realScene
|
|
218
|
-
}
|
|
219
|
-
void worldView.init(initPos)
|
|
220
|
-
|
|
221
|
-
await this.worldRenderer.waitForChunksToRender()
|
|
222
|
-
if (this.abortController.signal.aborted) return
|
|
223
|
-
// add small camera rotation to side on mouse move depending on absolute position of the cursor
|
|
224
|
-
const { camera } = this
|
|
225
|
-
const initX = camera.position.x
|
|
226
|
-
const initY = camera.position.y
|
|
227
|
-
let prevTwin: tweenJs.Tween<THREE.Vector3> | undefined
|
|
228
|
-
document.body.addEventListener('pointermove', (e) => {
|
|
229
|
-
if (e.pointerType !== 'mouse') return
|
|
230
|
-
const pos = new THREE.Vector2(e.clientX, e.clientY)
|
|
231
|
-
const SCALE = 0.2
|
|
232
|
-
/* -0.5 - 0.5 */
|
|
233
|
-
const xRel = pos.x / window.innerWidth - 0.5
|
|
234
|
-
const yRel = -(pos.y / window.innerHeight - 0.5)
|
|
235
|
-
prevTwin?.stop()
|
|
236
|
-
const to = {
|
|
237
|
-
x: initX + (xRel * SCALE),
|
|
238
|
-
y: initY + (yRel * SCALE)
|
|
239
|
-
}
|
|
240
|
-
prevTwin = new tweenJs.Tween(camera.position).to(to, 0) // todo use the number depending on diff // todo use the number depending on diff
|
|
241
|
-
// prevTwin.easing(tweenJs.Easing.Exponential.InOut)
|
|
242
|
-
prevTwin.start()
|
|
243
|
-
camera.updateProjectionMatrix()
|
|
244
|
-
}, {
|
|
245
|
-
signal: this.abortController.signal
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
console.timeEnd('load panorama scene')
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
dispose() {
|
|
252
|
-
this.scene.clear()
|
|
253
|
-
this.worldRenderer?.destroy()
|
|
254
|
-
this.abortController.abort()
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// export class ClassicPanoramaRenderer {
|
|
259
|
-
// panoramaGroup: THREE.Object3D
|
|
260
|
-
|
|
261
|
-
// constructor (private readonly backgroundFiles: string[], onRender: Array<(sizeChanged: boolean) => void>, addSquids = true) {
|
|
262
|
-
// const panorGeo = new THREE.BoxGeometry(1000, 1000, 1000)
|
|
263
|
-
// const loader = new THREE.TextureLoader()
|
|
264
|
-
// const panorMaterials = [] as THREE.MeshBasicMaterial[]
|
|
265
|
-
|
|
266
|
-
// for (const file of this.backgroundFiles) {
|
|
267
|
-
// const texture = loader.load(file)
|
|
268
|
-
|
|
269
|
-
// // Instead of using repeat/offset to flip, we'll use the texture matrix
|
|
270
|
-
// texture.matrixAutoUpdate = false
|
|
271
|
-
// texture.matrix.set(
|
|
272
|
-
// -1, 0, 1, 0, 1, 0, 0, 0, 1
|
|
273
|
-
// )
|
|
274
|
-
|
|
275
|
-
// texture.wrapS = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping
|
|
276
|
-
// texture.wrapT = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping
|
|
277
|
-
// texture.minFilter = THREE.LinearFilter
|
|
278
|
-
// texture.magFilter = THREE.LinearFilter
|
|
279
|
-
|
|
280
|
-
// panorMaterials.push(new THREE.MeshBasicMaterial({
|
|
281
|
-
// map: texture,
|
|
282
|
-
// transparent: true,
|
|
283
|
-
// side: THREE.DoubleSide,
|
|
284
|
-
// depthWrite: false,
|
|
285
|
-
// }))
|
|
286
|
-
// }
|
|
287
|
-
|
|
288
|
-
// const panoramaBox = new THREE.Mesh(panorGeo, panorMaterials)
|
|
289
|
-
// panoramaBox.onBeforeRender = () => {
|
|
290
|
-
// }
|
|
291
|
-
|
|
292
|
-
// const group = new THREE.Object3D()
|
|
293
|
-
// group.add(panoramaBox)
|
|
294
|
-
|
|
295
|
-
// if (addSquids) {
|
|
296
|
-
// // Add squids
|
|
297
|
-
// for (let i = 0; i < 20; i++) {
|
|
298
|
-
// const m = new EntityMesh('1.16.4', 'squid').mesh
|
|
299
|
-
// m.position.set(Math.random() * 30 - 15, Math.random() * 20 - 10, Math.random() * 10 - 17)
|
|
300
|
-
// m.rotation.set(0, Math.PI + Math.random(), -Math.PI / 4, 'ZYX')
|
|
301
|
-
// const v = Math.random() * 0.01
|
|
302
|
-
// onRender.push(() => {
|
|
303
|
-
// m.rotation.y += v
|
|
304
|
-
// m.rotation.z = Math.cos(panoramaBox.rotation.y * 3) * Math.PI / 4 - Math.PI / 2
|
|
305
|
-
// })
|
|
306
|
-
// group.add(m)
|
|
307
|
-
// }
|
|
308
|
-
// }
|
|
309
|
-
|
|
310
|
-
// this.panoramaGroup = group
|
|
311
|
-
// }
|
|
312
|
-
// }
|