okgeometry-api 1.26.1 → 1.27.0
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/Arc.js +1 -1
- package/dist/Arc.js.map +1 -1
- package/dist/Brep.js +1 -1
- package/dist/Brep.js.map +1 -1
- package/dist/Circle.js +1 -1
- package/dist/Circle.js.map +1 -1
- package/dist/Line.js +1 -1
- package/dist/Line.js.map +1 -1
- package/dist/Mesh.d.ts +41 -0
- package/dist/Mesh.d.ts.map +1 -1
- package/dist/Mesh.js +235 -21
- package/dist/Mesh.js.map +1 -1
- package/dist/MeshSurface.js +1 -1
- package/dist/MeshSurface.js.map +1 -1
- package/dist/NurbsCurve.js +1 -1
- package/dist/NurbsCurve.js.map +1 -1
- package/dist/NurbsSurface.js +1 -1
- package/dist/NurbsSurface.js.map +1 -1
- package/dist/PolyCurve.js +1 -1
- package/dist/PolyCurve.js.map +1 -1
- package/dist/Polyline.js +1 -1
- package/dist/Polyline.js.map +1 -1
- package/dist/Ray.js +1 -1
- package/dist/Ray.js.map +1 -1
- package/dist/SculptSession.js +1 -1
- package/dist/SculptSession.js.map +1 -1
- package/dist/engine-threaded.d.ts +2 -0
- package/dist/engine-threaded.d.ts.map +1 -0
- package/dist/engine-threaded.js +33 -0
- package/dist/engine-threaded.js.map +1 -0
- package/dist/engine.d.ts +21 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +42 -0
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mesh-boolean.pool.d.ts +23 -1
- package/dist/mesh-boolean.pool.d.ts.map +1 -1
- package/dist/mesh-boolean.pool.js +97 -12
- package/dist/mesh-boolean.pool.js.map +1 -1
- package/dist/mesh-boolean.protocol.d.ts +21 -1
- package/dist/mesh-boolean.protocol.d.ts.map +1 -1
- package/dist/mesh-boolean.protocol.js.map +1 -1
- package/dist/mesh-boolean.worker.d.ts.map +1 -1
- package/dist/mesh-boolean.worker.js +94 -1
- package/dist/mesh-boolean.worker.js.map +1 -1
- package/dist/wasm-active.d.ts +20 -0
- package/dist/wasm-active.d.ts.map +1 -0
- package/dist/wasm-active.js +26 -0
- package/dist/wasm-active.js.map +1 -0
- package/dist/wasm-base64-threaded.d.ts +2 -0
- package/dist/wasm-base64-threaded.d.ts.map +1 -0
- package/dist/wasm-base64-threaded.js +3 -0
- package/dist/wasm-base64-threaded.js.map +1 -0
- package/dist/wasm-base64.d.ts +1 -1
- package/dist/wasm-base64.d.ts.map +1 -1
- package/dist/wasm-base64.js +1 -1
- package/dist/wasm-base64.js.map +1 -1
- package/dist/wasm-bindings-threaded.d.ts +2664 -0
- package/dist/wasm-bindings-threaded.d.ts.map +1 -0
- package/dist/wasm-bindings-threaded.js +5008 -0
- package/dist/wasm-bindings-threaded.js.map +1 -0
- package/dist/wasm-bindings.d.ts +130 -0
- package/dist/wasm-bindings.d.ts.map +1 -1
- package/dist/wasm-bindings.js +208 -0
- package/dist/wasm-bindings.js.map +1 -1
- package/dist/workerHelpers-threaded.d.ts +2 -0
- package/dist/workerHelpers-threaded.d.ts.map +1 -0
- package/dist/workerHelpers-threaded.js +100 -0
- package/dist/workerHelpers-threaded.js.map +1 -0
- package/package.json +8 -3
- package/src/Arc.ts +117 -117
- package/src/Brep.ts +1 -1
- package/src/Circle.ts +166 -166
- package/src/Line.ts +171 -171
- package/src/Mesh.ts +300 -45
- package/src/MeshSurface.ts +1 -1
- package/src/NurbsCurve.ts +655 -655
- package/src/NurbsSurface.ts +721 -721
- package/src/PolyCurve.ts +203 -203
- package/src/Polyline.ts +316 -316
- package/src/Ray.ts +90 -90
- package/src/SculptSession.ts +377 -377
- package/src/engine-threaded.ts +39 -0
- package/src/engine.ts +46 -0
- package/src/index.ts +1 -1
- package/src/mesh-boolean.pool.ts +208 -86
- package/src/mesh-boolean.protocol.ts +44 -1
- package/src/mesh-boolean.worker.ts +170 -56
- package/src/wasm-active.ts +31 -0
- package/src/wasm-base64-threaded.ts +2 -0
- package/src/wasm-base64.ts +1 -1
- package/src/wasm-bindings-threaded.d.ts +1989 -0
- package/src/wasm-bindings-threaded.js +5235 -0
- package/src/wasm-bindings.d.ts +104 -0
- package/src/wasm-bindings.js +225 -0
- package/src/workerHelpers-threaded.js +107 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { init, isInitialized } from "./engine.js";
|
|
2
|
-
import { Mesh } from "./Mesh.js";
|
|
2
|
+
import { Mesh } from "./Mesh.js";
|
|
3
|
+
import { Point } from "./Point.js";
|
|
3
4
|
import type {
|
|
4
5
|
MeshBooleanErrorPayload,
|
|
5
6
|
MeshBooleanWorkerErrorResponse,
|
|
@@ -33,8 +34,8 @@ function isCancelled(jobId: number, cancelView: Int32Array | undefined): boolean
|
|
|
33
34
|
return cancelledJobs.has(jobId) || readCancelRequested(cancelView);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
workerGlobal.__okgeometry_boolean_should_cancel = () =>
|
|
37
|
-
readCancelRequested(workerGlobal.__okgeometryBooleanCancelFlag ?? undefined);
|
|
37
|
+
workerGlobal.__okgeometry_boolean_should_cancel = () =>
|
|
38
|
+
readCancelRequested(workerGlobal.__okgeometryBooleanCancelFlag ?? undefined);
|
|
38
39
|
|
|
39
40
|
function toErrorMessage(error: unknown): string {
|
|
40
41
|
if (error instanceof Error) return error.message;
|
|
@@ -46,25 +47,97 @@ function makeError(code: MeshBooleanErrorPayload["code"], message: string, detai
|
|
|
46
47
|
return { code, message, details };
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
function postError(jobId: number, payload: MeshBooleanErrorPayload): void {
|
|
50
|
-
const response: MeshBooleanWorkerErrorResponse = {
|
|
51
|
-
kind: "mesh-boolean-result",
|
|
52
|
-
jobId,
|
|
53
|
-
ok: false,
|
|
54
|
-
error: payload,
|
|
55
|
-
};
|
|
56
|
-
workerScope.postMessage(response);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function postSuccess(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
function postError(jobId: number, payload: MeshBooleanErrorPayload): void {
|
|
51
|
+
const response: MeshBooleanWorkerErrorResponse = {
|
|
52
|
+
kind: "mesh-boolean-result",
|
|
53
|
+
jobId,
|
|
54
|
+
ok: false,
|
|
55
|
+
error: payload,
|
|
56
|
+
};
|
|
57
|
+
workerScope.postMessage(response);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function postSuccess(
|
|
61
|
+
jobId: number,
|
|
62
|
+
buffer: ArrayBuffer,
|
|
63
|
+
meta?: Record<string, string | number | boolean>,
|
|
64
|
+
): void {
|
|
65
|
+
const response: MeshBooleanWorkerSuccessResponse = {
|
|
66
|
+
kind: "mesh-boolean-result",
|
|
67
|
+
jobId,
|
|
68
|
+
ok: true,
|
|
69
|
+
buffer,
|
|
70
|
+
meta,
|
|
71
|
+
};
|
|
72
|
+
workerScope.postMessage(response, [buffer]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Heavy kernel jobs (KERNEL-PERF-ARC lever 4) — see protocol for shapes. */
|
|
76
|
+
function runHeavyOperation(message: {
|
|
77
|
+
operation: string;
|
|
78
|
+
buffers: ArrayBuffer[];
|
|
79
|
+
trusted?: boolean[];
|
|
80
|
+
params?: { resolution?: number; iso?: number; distance?: number };
|
|
81
|
+
options: { allowUnsafe?: boolean; limits?: unknown; debugForceFaceID?: boolean };
|
|
82
|
+
}): { buffer: ArrayBuffer; meta?: Record<string, string | number | boolean> } {
|
|
83
|
+
const meshes = () =>
|
|
84
|
+
message.buffers.map((buf, i) =>
|
|
85
|
+
Mesh.fromBuffer(new Float64Array(buf), {
|
|
86
|
+
trustedBooleanInput: message.trusted?.[i],
|
|
87
|
+
}),
|
|
88
|
+
);
|
|
89
|
+
const options = {
|
|
90
|
+
allowUnsafe: message.options.allowUnsafe ?? true,
|
|
91
|
+
limits: message.options.limits as never,
|
|
92
|
+
debugForceFaceID: message.options.debugForceFaceID,
|
|
93
|
+
};
|
|
94
|
+
const params = message.params ?? {};
|
|
95
|
+
|
|
96
|
+
switch (message.operation) {
|
|
97
|
+
case "unionAll": {
|
|
98
|
+
const result = Mesh.unionAll(meshes(), options);
|
|
99
|
+
return { buffer: new Float64Array(result.rawBuffer).buffer };
|
|
100
|
+
}
|
|
101
|
+
case "differenceAll": {
|
|
102
|
+
const [host, ...cutters] = meshes();
|
|
103
|
+
const result = host.subtractAll(cutters, options);
|
|
104
|
+
return { buffer: new Float64Array(result.rawBuffer).buffer };
|
|
105
|
+
}
|
|
106
|
+
case "makeWatertight": {
|
|
107
|
+
const [mesh] = meshes();
|
|
108
|
+
const r = mesh.makeWatertight({
|
|
109
|
+
resolution: params.resolution,
|
|
110
|
+
iso: params.iso,
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
buffer: new Float64Array(r.mesh.rawBuffer).buffer,
|
|
114
|
+
meta: { method: r.method, effectiveResolution: r.effectiveResolution },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
case "voxelRemesh": {
|
|
118
|
+
const [mesh] = meshes();
|
|
119
|
+
const result = mesh.voxelRemesh(params.resolution ?? 0, params.iso ?? 0.5);
|
|
120
|
+
return { buffer: new Float64Array(result.rawBuffer).buffer };
|
|
121
|
+
}
|
|
122
|
+
case "chamferEdges": {
|
|
123
|
+
const mesh = Mesh.fromBuffer(new Float64Array(message.buffers[0]), {
|
|
124
|
+
trustedBooleanInput: message.trusted?.[0],
|
|
125
|
+
});
|
|
126
|
+
const flat = new Float64Array(message.buffers[1]);
|
|
127
|
+
const edges: Array<{ a: Point; b: Point }> = [];
|
|
128
|
+
for (let i = 0; i + 5 < flat.length; i += 6) {
|
|
129
|
+
edges.push({
|
|
130
|
+
a: new Point(flat[i], flat[i + 1], flat[i + 2]),
|
|
131
|
+
b: new Point(flat[i + 3], flat[i + 4], flat[i + 5]),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const result = mesh.chamferEdges(edges, params.distance ?? 0);
|
|
135
|
+
return { buffer: new Float64Array(result.rawBuffer).buffer };
|
|
136
|
+
}
|
|
137
|
+
default:
|
|
138
|
+
throw new Error(`Unknown heavy operation: ${message.operation}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
68
141
|
|
|
69
142
|
async function ensureWorkerInit(): Promise<void> {
|
|
70
143
|
if (isInitialized()) return;
|
|
@@ -82,25 +155,66 @@ workerScope.addEventListener("message", async (event: MessageEvent<MeshBooleanWo
|
|
|
82
155
|
cancelledJobs.add(message.jobId);
|
|
83
156
|
return;
|
|
84
157
|
}
|
|
85
|
-
|
|
86
|
-
if (message.kind
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
158
|
+
|
|
159
|
+
if (message.kind === "mesh-heavy-request") {
|
|
160
|
+
const jobId = message.jobId;
|
|
161
|
+
const cancelView = message.cancelBuffer ? new Int32Array(message.cancelBuffer) : undefined;
|
|
162
|
+
if (isCancelled(jobId, cancelView)) {
|
|
163
|
+
postError(jobId, makeError("worker_aborted", `${message.operation} aborted.`));
|
|
164
|
+
cancelledJobs.delete(jobId);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
await ensureWorkerInit();
|
|
169
|
+
if (isCancelled(jobId, cancelView)) {
|
|
170
|
+
postError(jobId, makeError("worker_aborted", `${message.operation} aborted.`));
|
|
171
|
+
cancelledJobs.delete(jobId);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
workerGlobal.__okgeometryBooleanCancelFlag = cancelView ?? null;
|
|
175
|
+
const { buffer, meta } = runHeavyOperation(message);
|
|
176
|
+
if (isCancelled(jobId, cancelView)) {
|
|
177
|
+
postError(jobId, makeError("worker_aborted", `${message.operation} aborted.`));
|
|
178
|
+
cancelledJobs.delete(jobId);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
postSuccess(jobId, buffer, meta);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
const details = toErrorMessage(error);
|
|
184
|
+
const cancelled = isCancelled(jobId, cancelView) || details.toLowerCase().includes("cancel");
|
|
185
|
+
postError(
|
|
186
|
+
jobId,
|
|
187
|
+
makeError(
|
|
188
|
+
cancelled ? "worker_aborted" : "kernel_error",
|
|
189
|
+
cancelled ? `${message.operation} aborted.` : `${message.operation} failed.`,
|
|
190
|
+
cancelled ? undefined : details,
|
|
191
|
+
),
|
|
192
|
+
);
|
|
193
|
+
} finally {
|
|
194
|
+
workerGlobal.__okgeometryBooleanCancelFlag = null;
|
|
195
|
+
cancelledJobs.delete(jobId);
|
|
196
|
+
}
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (message.kind !== "mesh-boolean-request") return;
|
|
201
|
+
const jobId = message.jobId;
|
|
202
|
+
const cancelView = message.cancelBuffer ? new Int32Array(message.cancelBuffer) : undefined;
|
|
203
|
+
|
|
204
|
+
if (isCancelled(jobId, cancelView)) {
|
|
205
|
+
postError(jobId, makeError("worker_aborted", `Boolean ${message.operation} aborted.`));
|
|
206
|
+
cancelledJobs.delete(jobId);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
95
209
|
|
|
96
210
|
try {
|
|
97
|
-
await ensureWorkerInit();
|
|
98
|
-
|
|
99
|
-
if (isCancelled(jobId, cancelView)) {
|
|
100
|
-
postError(jobId, makeError("worker_aborted", `Boolean ${message.operation} aborted.`));
|
|
101
|
-
cancelledJobs.delete(jobId);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
211
|
+
await ensureWorkerInit();
|
|
212
|
+
|
|
213
|
+
if (isCancelled(jobId, cancelView)) {
|
|
214
|
+
postError(jobId, makeError("worker_aborted", `Boolean ${message.operation} aborted.`));
|
|
215
|
+
cancelledJobs.delete(jobId);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
104
218
|
|
|
105
219
|
workerGlobal.__okgeometryBooleanCancelFlag = cancelView ?? null;
|
|
106
220
|
|
|
@@ -124,23 +238,23 @@ workerScope.addEventListener("message", async (event: MessageEvent<MeshBooleanWo
|
|
|
124
238
|
} else {
|
|
125
239
|
result = meshA.intersect(meshB, options);
|
|
126
240
|
}
|
|
127
|
-
|
|
128
|
-
if (isCancelled(jobId, cancelView)) {
|
|
129
|
-
postError(jobId, makeError("worker_aborted", `Boolean ${message.operation} aborted.`));
|
|
130
|
-
cancelledJobs.delete(jobId);
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const payload = new Float64Array(result.rawBuffer);
|
|
135
|
-
postSuccess(jobId, payload.buffer);
|
|
136
|
-
} catch (error) {
|
|
137
|
-
const details = toErrorMessage(error);
|
|
138
|
-
const cancelled = isCancelled(jobId, cancelView) || details.toLowerCase().includes("cancel");
|
|
139
|
-
postError(
|
|
140
|
-
jobId,
|
|
141
|
-
makeError(
|
|
142
|
-
cancelled ? "worker_aborted" : "kernel_error",
|
|
143
|
-
cancelled ? `Boolean ${message.operation} aborted.` : `Boolean ${message.operation} failed.`,
|
|
241
|
+
|
|
242
|
+
if (isCancelled(jobId, cancelView)) {
|
|
243
|
+
postError(jobId, makeError("worker_aborted", `Boolean ${message.operation} aborted.`));
|
|
244
|
+
cancelledJobs.delete(jobId);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const payload = new Float64Array(result.rawBuffer);
|
|
249
|
+
postSuccess(jobId, payload.buffer);
|
|
250
|
+
} catch (error) {
|
|
251
|
+
const details = toErrorMessage(error);
|
|
252
|
+
const cancelled = isCancelled(jobId, cancelView) || details.toLowerCase().includes("cancel");
|
|
253
|
+
postError(
|
|
254
|
+
jobId,
|
|
255
|
+
makeError(
|
|
256
|
+
cancelled ? "worker_aborted" : "kernel_error",
|
|
257
|
+
cancelled ? `Boolean ${message.operation} aborted.` : `Boolean ${message.operation} failed.`,
|
|
144
258
|
cancelled ? undefined : details,
|
|
145
259
|
),
|
|
146
260
|
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mutable indirection over the active wasm bindings module
|
|
3
|
+
* (KERNEL-PERF-ARC lever 3).
|
|
4
|
+
*
|
|
5
|
+
* The engine ships two artifacts with an identical export surface: the
|
|
6
|
+
* standard single-thread build and an optional rayon-threaded build
|
|
7
|
+
* (atomics + shared memory) loaded only on cross-origin-isolated pages.
|
|
8
|
+
* All geometry classes call through `wasm` here, which resolves to the
|
|
9
|
+
* active module at call time; `initThreads()` swaps the module BEFORE any
|
|
10
|
+
* geometry exists (enforced in engine.ts), so per-instance state (stored
|
|
11
|
+
* meshes, sculpt sessions) never spans instances.
|
|
12
|
+
*/
|
|
13
|
+
import * as standard from "./wasm-bindings.js";
|
|
14
|
+
|
|
15
|
+
type WasmModule = typeof standard;
|
|
16
|
+
|
|
17
|
+
let active: WasmModule = standard;
|
|
18
|
+
|
|
19
|
+
export function setActiveWasmModule(module: WasmModule): void {
|
|
20
|
+
active = module;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getActiveWasmModule(): WasmModule {
|
|
24
|
+
return active;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Property access resolves through the ACTIVE module at call time. */
|
|
28
|
+
export const wasm: WasmModule = new Proxy(Object.create(null) as WasmModule, {
|
|
29
|
+
get: (_target, key) => (active as unknown as Record<PropertyKey, unknown>)[key],
|
|
30
|
+
has: (_target, key) => key in (active as object),
|
|
31
|
+
});
|