nucleation 0.10.20 → 0.10.22

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/BlockPos.mjs CHANGED
@@ -108,6 +108,7 @@ export class BlockPos {
108
108
  // This method does not attempt to handle any dependencies between lifetimes, the caller
109
109
  // should handle this when constructing edge arrays.
110
110
  static _fromFFI(internalConstructor, ptr) {
111
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
111
112
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
112
113
  throw new Error("BlockPos._fromFFI is not meant to be called externally. Please use the default constructor.");
113
114
  }
package/Dimensions.mjs CHANGED
@@ -108,6 +108,7 @@ export class Dimensions {
108
108
  // This method does not attempt to handle any dependencies between lifetimes, the caller
109
109
  // should handle this when constructing edge arrays.
110
110
  static _fromFFI(internalConstructor, ptr) {
111
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
111
112
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
112
113
  throw new Error("Dimensions._fromFFI is not meant to be called externally. Please use the default constructor.");
113
114
  }
package/FieldRange.mjs CHANGED
@@ -89,6 +89,7 @@ export class FieldRange {
89
89
  // This method does not attempt to handle any dependencies between lifetimes, the caller
90
90
  // should handle this when constructing edge arrays.
91
91
  static _fromFFI(internalConstructor, ptr) {
92
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
92
93
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
93
94
  throw new Error("FieldRange._fromFFI is not meant to be called externally. Please use the default constructor.");
94
95
  }
package/ItemScale.mjs CHANGED
@@ -111,6 +111,7 @@ export class ItemScale {
111
111
  // This method does not attempt to handle any dependencies between lifetimes, the caller
112
112
  // should handle this when constructing edge arrays.
113
113
  static _fromFFI(internalConstructor, ptr) {
114
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
114
115
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
115
116
  throw new Error("ItemScale._fromFFI is not meant to be called externally. Please use the default constructor.");
116
117
  }
package/MeshBounds.mjs CHANGED
@@ -153,6 +153,7 @@ export class MeshBounds {
153
153
  // This method does not attempt to handle any dependencies between lifetimes, the caller
154
154
  // should handle this when constructing edge arrays.
155
155
  static _fromFFI(internalConstructor, ptr) {
156
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
156
157
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
157
158
  throw new Error("MeshBounds._fromFFI is not meant to be called externally. Please use the default constructor.");
158
159
  }
package/MeshProgress.mjs CHANGED
@@ -112,6 +112,7 @@ export class MeshProgress {
112
112
  // This method does not attempt to handle any dependencies between lifetimes, the caller
113
113
  // should handle this when constructing edge arrays.
114
114
  static _fromFFI(internalConstructor, ptr) {
115
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
115
116
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
116
117
  throw new Error("MeshProgress._fromFFI is not meant to be called externally. Please use the default constructor.");
117
118
  }
package/Palette.d.mts CHANGED
@@ -17,6 +17,18 @@ export class Palette {
17
17
  constructor();
18
18
 
19
19
 
20
+ /**
21
+ * Opaque building blocks and full glass blocks, for material-aware imports.
22
+ */
23
+ static materials(): Palette;
24
+
25
+ /**
26
+ * Keep only opaque blocks (`false`) or full glass blocks (`true`).
27
+ * Includes/excludes remain respected. Returns an empty palette when
28
+ * no suitable block exists; check `len()` before matching colours.
29
+ */
30
+ forMaterial(translucent: boolean): Palette;
31
+
20
32
  /**
21
33
  * Every block blockpedia knows a color for (the default palette
22
34
  * brushes use when none is set).
package/Palette.d.ts CHANGED
@@ -17,6 +17,18 @@ export class Palette {
17
17
  constructor();
18
18
 
19
19
 
20
+ /**
21
+ * Opaque building blocks and full glass blocks, for material-aware imports.
22
+ */
23
+ static materials(): Palette;
24
+
25
+ /**
26
+ * Keep only opaque blocks (`false`) or full glass blocks (`true`).
27
+ * Includes/excludes remain respected. Returns an empty palette when
28
+ * no suitable block exists; check `len()` before matching colours.
29
+ */
30
+ forMaterial(translucent: boolean): Palette;
31
+
20
32
  /**
21
33
  * Every block blockpedia knows a color for (the default palette
22
34
  * brushes use when none is set).
package/Palette.mjs CHANGED
@@ -42,6 +42,40 @@ export class Palette {
42
42
  }
43
43
 
44
44
 
45
+ /**
46
+ * Opaque building blocks and full glass blocks, for material-aware imports.
47
+ */
48
+ static materials() {
49
+
50
+ const result = wasm.Palette_materials();
51
+
52
+ try {
53
+ return new Palette(diplomatRuntime.internalConstructor, result, []);
54
+ }
55
+
56
+ finally {
57
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Keep only opaque blocks (`false`) or full glass blocks (`true`).
63
+ * Includes/excludes remain respected. Returns an empty palette when
64
+ * no suitable block exists; check `len()` before matching colours.
65
+ */
66
+ forMaterial(translucent) {
67
+
68
+ const result = wasm.Palette_for_material(this.ffiValue, translucent);
69
+
70
+ try {
71
+ return new Palette(diplomatRuntime.internalConstructor, result, []);
72
+ }
73
+
74
+ finally {
75
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
76
+ }
77
+ }
78
+
45
79
  /**
46
80
  * Every block blockpedia knows a color for (the default palette
47
81
  * brushes use when none is set).
package/RegionBounds.mjs CHANGED
@@ -154,6 +154,7 @@ export class RegionBounds {
154
154
  // This method does not attempt to handle any dependencies between lifetimes, the caller
155
155
  // should handle this when constructing edge arrays.
156
156
  static _fromFFI(internalConstructor, ptr) {
157
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
157
158
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
158
159
  throw new Error("RegionBounds._fromFFI is not meant to be called externally. Please use the default constructor.");
159
160
  }
package/Schematic.d.mts CHANGED
@@ -492,6 +492,15 @@ export class Schematic {
492
492
  */
493
493
  getChunkBlocksJson(offsetX: number, offsetY: number, offsetZ: number, width: number, height: number, length: number): string;
494
494
 
495
+ /**
496
+ * Non-air blocks inside a bounded box, retaining block-state properties.
497
+ * Visits only intersecting region cells, not the whole schematic. Bounds
498
+ * and arithmetic are checked; queries may scan at most 1,048,576 cells
499
+ * (including region overlaps) and emit at most 32 MiB of JSON. Renderers
500
+ * should request 16³ sections. Coordinates may be negative.
501
+ */
502
+ getChunkNonAirBlocksJson(offsetX: number, offsetY: number, offsetZ: number, width: number, height: number, length: number): string;
503
+
495
504
  /**
496
505
  * Split the schematic into chunks (default bottom-up strategy). Writes a
497
506
  * JSON array of `{"chunk_x", "chunk_y", "chunk_z", "blocks": [...]}` where
package/Schematic.d.ts CHANGED
@@ -492,6 +492,15 @@ export class Schematic {
492
492
  */
493
493
  getChunkBlocksJson(offsetX: number, offsetY: number, offsetZ: number, width: number, height: number, length: number): string;
494
494
 
495
+ /**
496
+ * Non-air blocks inside a bounded box, retaining block-state properties.
497
+ * Visits only intersecting region cells, not the whole schematic. Bounds
498
+ * and arithmetic are checked; queries may scan at most 1,048,576 cells
499
+ * (including region overlaps) and emit at most 32 MiB of JSON. Renderers
500
+ * should request 16³ sections. Coordinates may be negative.
501
+ */
502
+ getChunkNonAirBlocksJson(offsetX: number, offsetY: number, offsetZ: number, width: number, height: number, length: number): string;
503
+
495
504
  /**
496
505
  * Split the schematic into chunks (default bottom-up strategy). Writes a
497
506
  * JSON array of `{"chunk_x", "chunk_y", "chunk_z", "blocks": [...]}` where
package/Schematic.mjs CHANGED
@@ -1929,6 +1929,36 @@ export class Schematic {
1929
1929
  }
1930
1930
  }
1931
1931
 
1932
+ /**
1933
+ * Non-air blocks inside a bounded box, retaining block-state properties.
1934
+ * Visits only intersecting region cells, not the whole schematic. Bounds
1935
+ * and arithmetic are checked; queries may scan at most 1,048,576 cells
1936
+ * (including region overlaps) and emit at most 32 MiB of JSON. Renderers
1937
+ * should request 16³ sections. Coordinates may be negative.
1938
+ */
1939
+ getChunkNonAirBlocksJson(offsetX, offsetY, offsetZ, width, height, length) {
1940
+ const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true);
1941
+
1942
+ const write = new diplomatRuntime.DiplomatWriteBuf(wasm);
1943
+
1944
+
1945
+ const result = wasm.Schematic_get_chunk_non_air_blocks_json(diplomatReceive.buffer, this.ffiValue, offsetX, offsetY, offsetZ, width, height, length, write.buffer);
1946
+
1947
+ try {
1948
+ if (!diplomatReceive.resultFlag) {
1949
+ const cause = new NucleationError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer));
1950
+ throw new globalThis.Error('NucleationError.' + cause.value, { cause });
1951
+ }
1952
+ return write.readString8();
1953
+ }
1954
+
1955
+ finally {
1956
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
1957
+ diplomatReceive.free();
1958
+ write.free();
1959
+ }
1960
+ }
1961
+
1932
1962
  /**
1933
1963
  * Split the schematic into chunks (default bottom-up strategy). Writes a
1934
1964
  * JSON array of `{"chunk_x", "chunk_y", "chunk_z", "blocks": [...]}` where
package/SdfBounds.mjs CHANGED
@@ -133,6 +133,7 @@ export class SdfBounds {
133
133
  // This method does not attempt to handle any dependencies between lifetimes, the caller
134
134
  // should handle this when constructing edge arrays.
135
135
  static _fromFFI(internalConstructor, ptr) {
136
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
136
137
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
137
138
  throw new Error("SdfBounds._fromFFI is not meant to be called externally. Please use the default constructor.");
138
139
  }
package/SdfNormal.mjs CHANGED
@@ -100,6 +100,7 @@ export class SdfNormal {
100
100
  // This method does not attempt to handle any dependencies between lifetimes, the caller
101
101
  // should handle this when constructing edge arrays.
102
102
  static _fromFFI(internalConstructor, ptr) {
103
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
103
104
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
104
105
  throw new Error("SdfNormal._fromFFI is not meant to be called externally. Please use the default constructor.");
105
106
  }
package/TextureInfo.mjs CHANGED
@@ -125,6 +125,7 @@ export class TextureInfo {
125
125
  // This method does not attempt to handle any dependencies between lifetimes, the caller
126
126
  // should handle this when constructing edge arrays.
127
127
  static _fromFFI(internalConstructor, ptr) {
128
+ ptr >>>= 0; // unsigned wasm32 address; field values retain their signedness.
128
129
  if (internalConstructor !== diplomatRuntime.internalConstructor) {
129
130
  throw new Error("TextureInfo._fromFFI is not meant to be called externally. Please use the default constructor.");
130
131
  }
@@ -0,0 +1,34 @@
1
+ // generated by diplomat-tool
2
+ import type { NucleationError } from "./NucleationError.mjs"
3
+ import type { Palette } from "./Palette.mjs"
4
+ import type { Schematic } from "./Schematic.mjs"
5
+ import type { pointer, codepoint } from "./diplomat-runtime.d.ts";
6
+
7
+
8
+
9
+ /**
10
+ * A parsed GLB/OBJ, reusable for size estimates and configured imports.
11
+ */
12
+ export class VoxelModel {
13
+ /** @internal */
14
+ get ffiValue(): pointer;
15
+ /** @internal */
16
+ constructor();
17
+
18
+
19
+ /**
20
+ * Return {dimensions:[width,height,depth],volume} or {error:message}.
21
+ * Options: target_size, axis (longest/x/y/z), hollow, optional lighting
22
+ * {direction:[x,y,z],strength:0..1}, optional untextured_block.
23
+ * Estimates preserve proportions and run before voxel-grid allocation.
24
+ */
25
+ planJson(optionsJson: string): string;
26
+
27
+ /**
28
+ * Import using plan_json's options. Anchored at (0,0,0), with exact
29
+ * axis-based uniform scaling. Hollow uses a sparse surface raster;
30
+ * lighting darkens sampled texture colours before palette matching.
31
+ * Rejects oversized/over-complex output with InvalidArgument.
32
+ */
33
+ toSchematic(optionsJson: string, palette: Palette, name: string): Schematic;
34
+ }
@@ -0,0 +1,34 @@
1
+ // generated by diplomat-tool
2
+ import type { NucleationError } from "./NucleationError.mjs"
3
+ import type { Palette } from "./Palette.mjs"
4
+ import type { Schematic } from "./Schematic.mjs"
5
+ import type { pointer, codepoint } from "./diplomat-runtime.d.ts";
6
+
7
+
8
+
9
+ /**
10
+ * A parsed GLB/OBJ, reusable for size estimates and configured imports.
11
+ */
12
+ export class VoxelModel {
13
+ /** @internal */
14
+ get ffiValue(): pointer;
15
+ /** @internal */
16
+ constructor();
17
+
18
+
19
+ /**
20
+ * Return {dimensions:[width,height,depth],volume} or {error:message}.
21
+ * Options: target_size, axis (longest/x/y/z), hollow, optional lighting
22
+ * {direction:[x,y,z],strength:0..1}, optional untextured_block.
23
+ * Estimates preserve proportions and run before voxel-grid allocation.
24
+ */
25
+ planJson(optionsJson: string): string;
26
+
27
+ /**
28
+ * Import using plan_json's options. Anchored at (0,0,0), with exact
29
+ * axis-based uniform scaling. Hollow uses a sparse surface raster;
30
+ * lighting darkens sampled texture colours before palette matching.
31
+ * Rejects oversized/over-complex output with InvalidArgument.
32
+ */
33
+ toSchematic(optionsJson: string, palette: Palette, name: string): Schematic;
34
+ }
package/VoxelModel.mjs ADDED
@@ -0,0 +1,113 @@
1
+ // generated by diplomat-tool
2
+ import { NucleationError } from "./NucleationError.mjs"
3
+ import { Palette } from "./Palette.mjs"
4
+ import { Schematic } from "./Schematic.mjs"
5
+ import wasm from "./diplomat-wasm.mjs";
6
+ import * as diplomatRuntime from "./diplomat-runtime.mjs";
7
+
8
+ const VoxelModel_box_destroy_registry = new FinalizationRegistry((ptr) => {
9
+ wasm.VoxelModel_destroy(ptr);
10
+ });
11
+
12
+ /**
13
+ * A parsed GLB/OBJ, reusable for size estimates and configured imports.
14
+ */
15
+ export class VoxelModel {
16
+ // Internal ptr reference:
17
+ #ptr = null;
18
+
19
+ // Lifetimes are only to keep dependencies alive.
20
+ // Since JS won't garbage collect until there are no incoming edges.
21
+ #selfEdge = [];
22
+
23
+ #internalConstructor(symbol, ptr, selfEdge) {
24
+ if (symbol !== diplomatRuntime.internalConstructor) {
25
+ console.error("VoxelModel is an Opaque type. You cannot call its constructor.");
26
+ return;
27
+ }
28
+ this.#ptr = ptr;
29
+ this.#selfEdge = selfEdge;
30
+
31
+ // Are we being borrowed? If not, we can register.
32
+ if (this.#selfEdge.length === 0) {
33
+ VoxelModel_box_destroy_registry.register(this, this.#ptr);
34
+ }
35
+
36
+ return this;
37
+ }
38
+ /** @internal */
39
+ get ffiValue() {
40
+ return this.#ptr;
41
+ }
42
+
43
+
44
+ /**
45
+ * Return {dimensions:[width,height,depth],volume} or {error:message}.
46
+ * Options: target_size, axis (longest/x/y/z), hollow, optional lighting
47
+ * {direction:[x,y,z],strength:0..1}, optional untextured_block.
48
+ * Estimates preserve proportions and run before voxel-grid allocation.
49
+ */
50
+ planJson(optionsJson) {
51
+ let functionCleanupArena = new diplomatRuntime.CleanupArena();
52
+
53
+ const optionsJsonSlice = functionCleanupArena.alloc(diplomatRuntime.DiplomatBuf.sliceWrapper(wasm, diplomatRuntime.DiplomatBuf.str8(wasm, optionsJson)));
54
+ const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true);
55
+
56
+ const write = new diplomatRuntime.DiplomatWriteBuf(wasm);
57
+
58
+
59
+ const result = wasm.VoxelModel_plan_json(diplomatReceive.buffer, this.ffiValue, optionsJsonSlice.ptr, write.buffer);
60
+
61
+ try {
62
+ if (!diplomatReceive.resultFlag) {
63
+ const cause = new NucleationError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer));
64
+ throw new globalThis.Error('NucleationError.' + cause.value, { cause });
65
+ }
66
+ return write.readString8();
67
+ }
68
+
69
+ finally {
70
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
71
+ functionCleanupArena.free();
72
+
73
+ diplomatReceive.free();
74
+ write.free();
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Import using plan_json's options. Anchored at (0,0,0), with exact
80
+ * axis-based uniform scaling. Hollow uses a sparse surface raster;
81
+ * lighting darkens sampled texture colours before palette matching.
82
+ * Rejects oversized/over-complex output with InvalidArgument.
83
+ */
84
+ toSchematic(optionsJson, palette, name) {
85
+ let functionCleanupArena = new diplomatRuntime.CleanupArena();
86
+
87
+ const optionsJsonSlice = functionCleanupArena.alloc(diplomatRuntime.DiplomatBuf.sliceWrapper(wasm, diplomatRuntime.DiplomatBuf.str8(wasm, optionsJson)));
88
+ const nameSlice = functionCleanupArena.alloc(diplomatRuntime.DiplomatBuf.sliceWrapper(wasm, diplomatRuntime.DiplomatBuf.str8(wasm, name)));
89
+ const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true);
90
+
91
+
92
+ const result = wasm.VoxelModel_to_schematic(diplomatReceive.buffer, this.ffiValue, optionsJsonSlice.ptr, palette.ffiValue, nameSlice.ptr);
93
+
94
+ try {
95
+ if (!diplomatReceive.resultFlag) {
96
+ const cause = new NucleationError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer));
97
+ throw new globalThis.Error('NucleationError.' + cause.value, { cause });
98
+ }
99
+ return new Schematic(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []);
100
+ }
101
+
102
+ finally {
103
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
104
+ functionCleanupArena.free();
105
+
106
+ diplomatReceive.free();
107
+ }
108
+ }
109
+
110
+ constructor(symbol, ptr, selfEdge) {
111
+ return this.#internalConstructor(...arguments)
112
+ }
113
+ }
package/Voxelizer.d.mts CHANGED
@@ -3,6 +3,7 @@ import type { NucleationError } from "./NucleationError.mjs"
3
3
  import type { Palette } from "./Palette.mjs"
4
4
  import type { Schematic } from "./Schematic.mjs"
5
5
  import type { Shape } from "./Shape.mjs"
6
+ import type { VoxelModel } from "./VoxelModel.mjs"
6
7
  import type { pointer, codepoint } from "./diplomat-runtime.d.ts";
7
8
 
8
9
 
@@ -18,6 +19,27 @@ export class Voxelizer {
18
19
  constructor();
19
20
 
20
21
 
22
+ /**
23
+ * Reason the last configured model import failed; cleared on success.
24
+ */
25
+ static lastErrorDetail(): string;
26
+
27
+ /**
28
+ * PHP-friendly GLB input: avoids expanding every byte into a boxed
29
+ * integer array before copying it over FFI.
30
+ */
31
+ static loadGlbBase64(data: string): VoxelModel;
32
+
33
+ /**
34
+ * Parse a GLB once for axis-based size estimates and lit voxelization.
35
+ */
36
+ static loadGlb(data: Array<number>): VoxelModel;
37
+
38
+ /**
39
+ * Parse an OBJ once for axis-based size estimates and lit voxelization.
40
+ */
41
+ static loadObj(text: string): VoxelModel;
42
+
21
43
  /**
22
44
  * Load a binary glTF (`.glb`, embedded buffers/images) and voxelize
23
45
  * it into a fillable Shape: the model is uniformly scaled so its
package/Voxelizer.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { NucleationError } from "./NucleationError.mjs"
3
3
  import type { Palette } from "./Palette.mjs"
4
4
  import type { Schematic } from "./Schematic.mjs"
5
5
  import type { Shape } from "./Shape.mjs"
6
+ import type { VoxelModel } from "./VoxelModel.mjs"
6
7
  import type { pointer, codepoint } from "./diplomat-runtime.d.ts";
7
8
 
8
9
 
@@ -18,6 +19,27 @@ export class Voxelizer {
18
19
  constructor();
19
20
 
20
21
 
22
+ /**
23
+ * Reason the last configured model import failed; cleared on success.
24
+ */
25
+ static lastErrorDetail(): string;
26
+
27
+ /**
28
+ * PHP-friendly GLB input: avoids expanding every byte into a boxed
29
+ * integer array before copying it over FFI.
30
+ */
31
+ static loadGlbBase64(data: string): VoxelModel;
32
+
33
+ /**
34
+ * Parse a GLB once for axis-based size estimates and lit voxelization.
35
+ */
36
+ static loadGlb(data: Array<number>): VoxelModel;
37
+
38
+ /**
39
+ * Parse an OBJ once for axis-based size estimates and lit voxelization.
40
+ */
41
+ static loadObj(text: string): VoxelModel;
42
+
21
43
  /**
22
44
  * Load a binary glTF (`.glb`, embedded buffers/images) and voxelize
23
45
  * it into a fillable Shape: the model is uniformly scaled so its
package/Voxelizer.mjs CHANGED
@@ -3,6 +3,7 @@ import { NucleationError } from "./NucleationError.mjs"
3
3
  import { Palette } from "./Palette.mjs"
4
4
  import { Schematic } from "./Schematic.mjs"
5
5
  import { Shape } from "./Shape.mjs"
6
+ import { VoxelModel } from "./VoxelModel.mjs"
6
7
  import wasm from "./diplomat-wasm.mjs";
7
8
  import * as diplomatRuntime from "./diplomat-runtime.mjs";
8
9
 
@@ -43,6 +44,109 @@ export class Voxelizer {
43
44
  }
44
45
 
45
46
 
47
+ /**
48
+ * Reason the last configured model import failed; cleared on success.
49
+ */
50
+ static lastErrorDetail() {
51
+ const write = new diplomatRuntime.DiplomatWriteBuf(wasm);
52
+
53
+ wasm.Voxelizer_last_error_detail(write.buffer);
54
+
55
+ try {
56
+ return write.readString8();
57
+ }
58
+
59
+ finally {
60
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
61
+ write.free();
62
+ }
63
+ }
64
+
65
+ /**
66
+ * PHP-friendly GLB input: avoids expanding every byte into a boxed
67
+ * integer array before copying it over FFI.
68
+ */
69
+ static loadGlbBase64(data) {
70
+ let functionCleanupArena = new diplomatRuntime.CleanupArena();
71
+
72
+ const dataSlice = functionCleanupArena.alloc(diplomatRuntime.DiplomatBuf.sliceWrapper(wasm, diplomatRuntime.DiplomatBuf.str8(wasm, data)));
73
+ const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true);
74
+
75
+
76
+ const result = wasm.Voxelizer_load_glb_base64(diplomatReceive.buffer, dataSlice.ptr);
77
+
78
+ try {
79
+ if (!diplomatReceive.resultFlag) {
80
+ const cause = new NucleationError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer));
81
+ throw new globalThis.Error('NucleationError.' + cause.value, { cause });
82
+ }
83
+ return new VoxelModel(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []);
84
+ }
85
+
86
+ finally {
87
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
88
+ functionCleanupArena.free();
89
+
90
+ diplomatReceive.free();
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Parse a GLB once for axis-based size estimates and lit voxelization.
96
+ */
97
+ static loadGlb(data) {
98
+ let functionCleanupArena = new diplomatRuntime.CleanupArena();
99
+
100
+ const dataSlice = functionCleanupArena.alloc(diplomatRuntime.DiplomatBuf.sliceWrapper(wasm, diplomatRuntime.DiplomatBuf.slice(wasm, data, "u8")));
101
+ const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true);
102
+
103
+
104
+ const result = wasm.Voxelizer_load_glb(diplomatReceive.buffer, dataSlice.ptr);
105
+
106
+ try {
107
+ if (!diplomatReceive.resultFlag) {
108
+ const cause = new NucleationError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer));
109
+ throw new globalThis.Error('NucleationError.' + cause.value, { cause });
110
+ }
111
+ return new VoxelModel(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []);
112
+ }
113
+
114
+ finally {
115
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
116
+ functionCleanupArena.free();
117
+
118
+ diplomatReceive.free();
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Parse an OBJ once for axis-based size estimates and lit voxelization.
124
+ */
125
+ static loadObj(text) {
126
+ let functionCleanupArena = new diplomatRuntime.CleanupArena();
127
+
128
+ const textSlice = functionCleanupArena.alloc(diplomatRuntime.DiplomatBuf.sliceWrapper(wasm, diplomatRuntime.DiplomatBuf.str8(wasm, text)));
129
+ const diplomatReceive = new diplomatRuntime.DiplomatReceiveBuf(wasm, 5, 4, true);
130
+
131
+
132
+ const result = wasm.Voxelizer_load_obj(diplomatReceive.buffer, textSlice.ptr);
133
+
134
+ try {
135
+ if (!diplomatReceive.resultFlag) {
136
+ const cause = new NucleationError(diplomatRuntime.internalConstructor, diplomatRuntime.enumDiscriminant(wasm, diplomatReceive.buffer));
137
+ throw new globalThis.Error('NucleationError.' + cause.value, { cause });
138
+ }
139
+ return new VoxelModel(diplomatRuntime.internalConstructor, diplomatRuntime.ptrRead(wasm, diplomatReceive.buffer), []);
140
+ }
141
+
142
+ finally {
143
+ diplomatRuntime.FUNCTION_PARAM_ALLOC.clean();
144
+ functionCleanupArena.free();
145
+
146
+ diplomatReceive.free();
147
+ }
148
+ }
149
+
46
150
  /**
47
151
  * Load a binary glTF (`.glb`, embedded buffers/images) and voxelize
48
152
  * it into a fillable Shape: the model is uniformly scaled so its
@@ -8,11 +8,13 @@ export const internalConstructor = Symbol("constructor");
8
8
  export const exposeConstructor = Symbol("exposeConstructor");
9
9
 
10
10
  export function readString8(wasm, ptr, len) {
11
+ ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
11
12
  const buf = new Uint8Array(wasm.memory.buffer, ptr, len);
12
13
  return (new TextDecoder("utf-8")).decode(buf)
13
14
  }
14
15
 
15
16
  export function readString16(wasm, ptr, len) {
17
+ ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
16
18
  const buf = new Uint16Array(wasm.memory.buffer, ptr, len);
17
19
  return String.fromCharCode.apply(null, buf)
18
20
  }
@@ -48,6 +50,7 @@ export function withDiplomatWrite(wasm, callback) {
48
50
  * @returns {number} The underlying pointer.
49
51
  */
50
52
  export function ptrRead(wasm, ptr) {
53
+ ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
51
54
  return (new Uint32Array(wasm.memory.buffer, ptr, 1))[0];
52
55
  }
53
56
 
@@ -55,6 +58,7 @@ export function ptrRead(wasm, ptr) {
55
58
  * Get the flag of a result type.
56
59
  */
57
60
  export function resultFlag(wasm, ptr, offset) {
61
+ ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
58
62
  return (new Uint8Array(wasm.memory.buffer, ptr + offset, 1))[0];
59
63
  }
60
64
 
@@ -62,6 +66,7 @@ export function resultFlag(wasm, ptr, offset) {
62
66
  * Get the discriminant of a Rust enum.
63
67
  */
64
68
  export function enumDiscriminant(wasm, ptr) {
69
+ ptr >>>= 0; // wasm32 addresses are unsigned, including above 2 GiB.
65
70
  return (new Int32Array(wasm.memory.buffer, ptr, 1))[0]
66
71
  }
67
72
 
@@ -83,7 +88,7 @@ export function maybePaddingFields(needsPaddingFields, paddingCount) {
83
88
  * (which is a `TypedArray` variant like `Uint8Array` or `Int16Array`)
84
89
  */
85
90
  export function writeToArrayBuffer(arrayBuffer, offset, value, typedArrayKind) {
86
- let buffer = new typedArrayKind(arrayBuffer, offset);
91
+ let buffer = new typedArrayKind(arrayBuffer, offset < 0 ? offset >>> 0 : offset);
87
92
  buffer[0] = value;
88
93
  }
89
94
 
@@ -223,7 +228,7 @@ export class DiplomatBuf {
223
228
  }
224
229
  }
225
230
 
226
- const ptr = wasm.diplomat_alloc(utf8Length, 1);
231
+ const ptr = wasm.diplomat_alloc(utf8Length, 1) >>> 0;
227
232
 
228
233
  const result = (new TextEncoder()).encodeInto(string, new Uint8Array(wasm.memory.buffer, ptr, utf8Length));
229
234
  console.assert(string.length === result.read && utf8Length === result.written, "UTF-8 write error");
@@ -233,7 +238,7 @@ export class DiplomatBuf {
233
238
 
234
239
  static str16 = (wasm, string) => {
235
240
  const byteLength = string.length * 2;
236
- const ptr = wasm.diplomat_alloc(byteLength, 2);
241
+ const ptr = wasm.diplomat_alloc(byteLength, 2) >>> 0;
237
242
 
238
243
  const destination = new Uint16Array(wasm.memory.buffer, ptr, string.length);
239
244
  for (let i = 0; i < string.length; i++) {
@@ -244,7 +249,7 @@ export class DiplomatBuf {
244
249
  }
245
250
 
246
251
  static sliceWrapper = (wasm, buf) => {
247
- const ptr = wasm.diplomat_alloc(8, 4);
252
+ const ptr = wasm.diplomat_alloc(8, 4) >>> 0;
248
253
  let dst = new Uint32Array(wasm.memory.buffer, ptr, 2);
249
254
 
250
255
  dst[0] = buf.ptr;
@@ -262,7 +267,7 @@ export class DiplomatBuf {
262
267
  4;
263
268
 
264
269
  const byteLength = list.length * elementSize;
265
- const ptr = wasm.diplomat_alloc(byteLength, elementSize);
270
+ const ptr = wasm.diplomat_alloc(byteLength, elementSize) >>> 0;
266
271
 
267
272
  /**
268
273
  * Create an array view of the buffer. This gives us the `set` method which correctly handles untyped values
@@ -288,15 +293,15 @@ export class DiplomatBuf {
288
293
 
289
294
  const byteLength = strings.length * 4 * 2;
290
295
 
291
- const ptr = wasm.diplomat_alloc(byteLength, 4);
296
+ const ptr = wasm.diplomat_alloc(byteLength, 4) >>> 0;
292
297
 
293
- const destination = new Uint32Array(wasm.memory.buffer, ptr, byteLength);
294
298
 
295
299
  const stringsAlloc = [];
296
300
 
297
301
  for (let i = 0; i < strings.length; i++) {
298
302
  stringsAlloc.push(encodeStr(wasm, strings[i]));
299
303
 
304
+ const destination = new Uint32Array(wasm.memory.buffer, ptr, strings.length * 2);
300
305
  destination[2 * i] = stringsAlloc[i].ptr;
301
306
  destination[(2 * i) + 1] = stringsAlloc[i].size;
302
307
  }
@@ -310,7 +315,7 @@ export class DiplomatBuf {
310
315
  }
311
316
 
312
317
  static struct = (wasm, size, align) => {
313
- const ptr = wasm.diplomat_alloc(size, align);
318
+ const ptr = wasm.diplomat_alloc(size, align) >>> 0;
314
319
 
315
320
  return new DiplomatBuf(ptr, size, () => {
316
321
  wasm.diplomat_free(ptr, size, align);
@@ -325,7 +330,7 @@ export class DiplomatBuf {
325
330
  free;
326
331
 
327
332
  constructor(ptr, size, free) {
328
- this.ptr = ptr;
333
+ this.ptr = ptr >>> 0;
329
334
  this.size = size;
330
335
  this.free = free;
331
336
  this.leak = () => { };
@@ -357,7 +362,7 @@ export class DiplomatWriteBuf {
357
362
 
358
363
  constructor(wasm) {
359
364
  this.#wasm = wasm;
360
- this.#buffer = this.#wasm.diplomat_buffer_write_create(0);
365
+ this.#buffer = this.#wasm.diplomat_buffer_write_create(0) >>> 0;
361
366
 
362
367
  this.leak = () => { };
363
368
  }
@@ -409,7 +414,7 @@ export class DiplomatSlice {
409
414
  constructor(wasm, buffer, bufferType, lifetimeEdges) {
410
415
  this.#wasm = wasm;
411
416
 
412
- const [ptr, size] = new Uint32Array(this.#wasm.memory.buffer, buffer, 2);
417
+ const [ptr, size] = new Uint32Array(this.#wasm.memory.buffer, buffer >>> 0, 2);
413
418
 
414
419
  this.#buffer = new bufferType(this.#wasm.memory.buffer, ptr, size);
415
420
  this.#bufferType = bufferType;
@@ -432,7 +437,7 @@ export class DiplomatSlice {
432
437
 
433
438
  export class DiplomatSlicePrimitive extends DiplomatSlice {
434
439
  constructor(wasm, buffer, sliceType, lifetimeEdges) {
435
- const [ptr, size] = new Uint32Array(wasm.memory.buffer, buffer, 2);
440
+ const [ptr, size] = new Uint32Array(wasm.memory.buffer, buffer >>> 0, 2);
436
441
 
437
442
  let arrayType;
438
443
  switch (sliceType) {
@@ -552,7 +557,7 @@ export class DiplomatReceiveBuf {
552
557
 
553
558
  this.#hasResult = hasResult;
554
559
 
555
- this.#buffer = this.#wasm.diplomat_alloc(this.#size, this.#align);
560
+ this.#buffer = this.#wasm.diplomat_alloc(this.#size, this.#align) >>> 0;
556
561
 
557
562
  this.leak = () => { };
558
563
  }
@@ -736,7 +741,7 @@ export class FunctionParamAllocator {
736
741
 
737
742
  this.#capacity = capacity;
738
743
  // FunctionParamAllocator is global, so this will be freed when the webpage closes:
739
- this.#ptr = wasm.diplomat_alloc(this.#capacity, 1);
744
+ this.#ptr = wasm.diplomat_alloc(this.#capacity, 1) >>> 0;
740
745
  }
741
746
 
742
747
  /**
package/index.d.mts CHANGED
@@ -142,6 +142,8 @@ export { Store } from "./Store.mjs"
142
142
 
143
143
  export { StoreIo } from "./StoreIo.mjs"
144
144
 
145
+ export { VoxelModel } from "./VoxelModel.mjs"
146
+
145
147
  export { Voxelizer } from "./Voxelizer.mjs"
146
148
 
147
149
  export { CellularSdfConfig } from "./CellularSdfConfig.mjs"
package/index.d.ts CHANGED
@@ -142,6 +142,8 @@ export { Store } from "./Store.mjs"
142
142
 
143
143
  export { StoreIo } from "./StoreIo.mjs"
144
144
 
145
+ export { VoxelModel } from "./VoxelModel.mjs"
146
+
145
147
  export { Voxelizer } from "./Voxelizer.mjs"
146
148
 
147
149
  export { CellularSdfConfig } from "./CellularSdfConfig.mjs"
package/index.mjs CHANGED
@@ -140,6 +140,8 @@ export { Store } from "./Store.mjs"
140
140
 
141
141
  export { StoreIo } from "./StoreIo.mjs"
142
142
 
143
+ export { VoxelModel } from "./VoxelModel.mjs"
144
+
143
145
  export { Voxelizer } from "./Voxelizer.mjs"
144
146
 
145
147
  export { CellularSdfConfig } from "./CellularSdfConfig.mjs"
package/nucleation.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nucleation",
3
- "version": "0.10.20",
3
+ "version": "0.10.22",
4
4
  "description": "A high-performance Minecraft schematic parser and utility library",
5
5
  "type": "module",
6
6
  "main": "index.mjs",