minecraft-renderer 0.1.42 → 0.1.43

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minecraft-renderer",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "The most Modular Minecraft world renderer with Three.js WebGL backend",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -628,6 +628,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
628
628
  worldMinY: this.worldMinYRender,
629
629
  worldMaxY: this.worldMinYRender + this.worldSizeParams.worldHeight,
630
630
  disableConversionCache: this.worldRendererConfig.disableMesherConversionCache,
631
+ computeWireframeEdges: this.worldRendererConfig.futuristicReveal === true,
631
632
  }
632
633
  }
633
634
 
@@ -1,7 +1,7 @@
1
1
  //@ts-nocheck
2
2
  import { Vec3 } from 'vec3'
3
3
  import { World } from '../mesher-shared/world'
4
- import { getSectionGeometry, setBlockStatesData as setMesherData } from '../mesher-shared/models'
4
+ import { getSectionGeometry, setBlockStatesData as setMesherData, computeWireframeEdgesJS } from '../mesher-shared/models'
5
5
  import { BlockStateModelInfo } from '../mesher-shared/shared'
6
6
  import { handleGetHeightmap, EMPTY_COLUMN_HEIGHTMAP_SENTINEL } from '../mesher-shared/computeHeightmap'
7
7
 
@@ -208,7 +208,16 @@ setInterval(() => {
208
208
  if (chunk?.getSection(new Vec3(x, y, z))) {
209
209
  const start = performance.now()
210
210
  const geometry = getSectionGeometry(x, y, z, world)
211
+ if (geometry.positions.length > 0 && geometry.indices.length > 0 && world.config.computeWireframeEdges) {
212
+ const wireframeF32 = computeWireframeEdgesJS(geometry.positions as number[], geometry.indices as number[])
213
+ if (wireframeF32.length > 0) {
214
+ geometry.wireframePositions = wireframeF32
215
+ }
216
+ }
211
217
  const transferable = [geometry.positions?.buffer, geometry.normals?.buffer, geometry.colors?.buffer, geometry.uvs?.buffer].filter(Boolean)
218
+ if (geometry.wireframePositions) {
219
+ transferable.push(geometry.wireframePositions.buffer)
220
+ }
212
221
  //@ts-expect-error
213
222
  postMessage({ type: 'geometry', key, geometry, workerIndex }, transferable)
214
223
  processTime = performance.now() - start
@@ -794,3 +794,44 @@ export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTil
794
794
  }
795
795
  }
796
796
  }
797
+
798
+ export function computeWireframeEdgesJS(positions: Float32Array | number[], indices: Uint32Array | Uint16Array | number[]): Float32Array {
799
+ const pos = positions instanceof Float32Array ? positions : new Float32Array(positions as number[])
800
+ const idx = indices instanceof Uint32Array ? indices : (indices instanceof Uint16Array ? new Uint32Array(indices) : new Uint32Array(indices as number[]))
801
+
802
+ const linePositions: number[] = []
803
+ const edgeSet = new Set<number>()
804
+
805
+ for (let i = 0; i < idx.length; i += 3) {
806
+ const i0 = idx[i]!
807
+ const i1 = idx[i + 1]!
808
+ const i2 = idx[i + 2]!
809
+
810
+ addEdgeJS(pos, i0, i1, linePositions, edgeSet)
811
+ addEdgeJS(pos, i1, i2, linePositions, edgeSet)
812
+ addEdgeJS(pos, i2, i0, linePositions, edgeSet)
813
+ }
814
+
815
+ return new Float32Array(linePositions)
816
+ }
817
+
818
+ function addEdgeJS(
819
+ positions: Float32Array,
820
+ i0: number,
821
+ i1: number,
822
+ linePositions: number[],
823
+ edgeSet: Set<number>
824
+ ): void {
825
+ const minI = i0 < i1 ? i0 : i1
826
+ const maxI = i0 < i1 ? i1 : i0
827
+ // Pack two indices into a single number (safe while indices < 2^24 — far above per-section vertex counts).
828
+ const key = minI * 0x1000000 + maxI
829
+
830
+ if (edgeSet.has(key)) return
831
+ edgeSet.add(key)
832
+
833
+ linePositions.push(
834
+ positions[i0 * 3]!, positions[i0 * 3 + 1]!, positions[i0 * 3 + 2]!,
835
+ positions[i1 * 3]!, positions[i1 * 3 + 1]!, positions[i1 * 3 + 2]!
836
+ )
837
+ }
@@ -19,6 +19,7 @@ export const defaultMesherConfig = {
19
19
  clipWorldBelowY: undefined as undefined | number,
20
20
  disableBlockEntityTextures: false,
21
21
  disableConversionCache: false,
22
+ computeWireframeEdges: false,
22
23
  }
23
24
 
24
25
  export type CustomBlockModels = {
@@ -60,6 +61,7 @@ export type MesherGeometryOutput = {
60
61
  // isFull: boolean
61
62
  hadErrors: boolean
62
63
  blocksCount: number
64
+ wireframePositions?: Float32Array
63
65
  customBlockModels?: CustomBlockModels
64
66
  }
65
67
 
@@ -433,6 +433,12 @@ export class SciFiWorldRevealModule implements RendererModuleController {
433
433
  * Create wireframe geometry from mesh geometry
434
434
  */
435
435
  private createWireframeGeometry(geometry: MesherGeometryOutput): THREE.BufferGeometry {
436
+ if (geometry.wireframePositions && geometry.wireframePositions.length > 0) {
437
+ const wireframeGeom = new THREE.BufferGeometry()
438
+ wireframeGeom.setAttribute('position', new THREE.Float32BufferAttribute(geometry.wireframePositions, 3))
439
+ return wireframeGeom
440
+ }
441
+
436
442
  const positions = geometry.positions as Float32Array
437
443
  const indices = geometry.indices as Uint32Array | Uint16Array
438
444
 
@@ -909,7 +909,7 @@ export class WorldRendererThree extends WorldRendererCommon {
909
909
  const yOffset = this.playerStateReactive.eyeHeight
910
910
 
911
911
  this.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch)
912
- this.media.tryIntersectMedia()
912
+ // this.media.tryIntersectMedia()
913
913
  this.updateCameraSectionPos()
914
914
  }
915
915
 
@@ -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;
@@ -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