@shopware-ag/dive
Version:
Shopware Spatial Framework
516 lines (515 loc) • 15.1 kB
JavaScript
var k = Object.defineProperty;
var F = (_, r, s) => r in _ ? k(_, r, { enumerable: !0, configurable: !0, writable: !0, value: s }) : _[r] = s;
var h = (_, r, s) => F(_, typeof r != "symbol" ? r + "" : r, s);
import { GLTFLoader as x } from "three/examples/jsm/loaders/GLTFLoader.js";
import { USDLoader as G } from "three/examples/jsm/loaders/USDLoader.js";
import { S as B } from "./FileTypes-Ck6z0LqE.mjs";
import { Group as C, BufferGeometry as W, BufferAttribute as O, MeshStandardMaterial as v, Mesh as j } from "three/webgpu";
import "three/examples/jsm/loaders/HDRLoader.js";
import "three/tsl";
import { g as H, i as z } from "./isFileTypeSupported-DPjSWSnx.mjs";
import { F as P, P as M } from "./parse-error-DfOPyLWM.mjs";
import { DRACOLoader as Y } from "three/examples/jsm/loaders/DRACOLoader.js";
import { A as S } from "./AssetCache-w3B0LIUw.mjs";
function J() {
let _, r;
onmessage = function(e) {
const n = e.data;
switch (n.type) {
case "init":
_ = n.decoderConfig, r = new Promise(function(i) {
_.onModuleLoaded = function(f) {
i({ draco: f });
}, DracoDecoderModule(_);
});
break;
case "decode":
const c = n.buffer, d = n.taskConfig;
r.then((i) => {
const f = i.draco, a = new f.Decoder();
try {
const l = s(
f,
a,
new Int8Array(c),
d
), p = l.attributes.map(
(m) => m.array.buffer
);
l.index && p.push(l.index.array.buffer), self.postMessage(
{ type: "decode", id: n.id, geometry: l },
p
);
} catch (l) {
console.error(l), self.postMessage({
type: "error",
id: n.id,
error: l.message
});
} finally {
f.destroy(a);
}
});
break;
}
};
function s(e, n, c, d) {
const i = d.attributeIDs, f = d.attributeTypes;
let a, l;
const p = n.GetEncodedGeometryType(c);
if (p === e.TRIANGULAR_MESH)
a = new e.Mesh(), l = n.DecodeArrayToMesh(
c,
c.byteLength,
a
);
else if (p === e.POINT_CLOUD)
a = new e.PointCloud(), l = n.DecodeArrayToPointCloud(
c,
c.byteLength,
a
);
else
throw new Error("THREE.DRACOLoader: Unexpected geometry type.");
if (!l.ok() || a.ptr === 0)
throw new Error(
"THREE.DRACOLoader: Decoding failed: " + l.error_msg()
);
const m = { index: null, attributes: [] };
for (const g in i) {
const E = self[f[g]];
let w, A;
if (d.useUniqueIDs)
A = i[g], w = n.GetAttributeByUniqueId(
a,
A
);
else {
if (A = n.GetAttributeId(
a,
e[i[g]]
), A === -1) continue;
w = n.GetAttribute(a, A);
}
const y = o(
e,
n,
a,
g,
E,
w
);
g === "color" && (y.vertexColorSpace = d.vertexColorSpace), m.attributes.push(y);
}
return p === e.TRIANGULAR_MESH && (m.index = t(e, n, a)), e.destroy(a), m;
}
function t(e, n, c) {
const i = c.num_faces() * 3, f = i * 4, a = e._malloc(f);
n.GetTrianglesUInt32Array(c, f, a);
const l = new Uint32Array(
e.HEAPF32.buffer,
a,
i
).slice();
return e._free(a), { array: l, itemSize: 1 };
}
function o(e, n, c, d, i, f) {
const a = c.num_points(), l = f.num_components(), p = u(e, i), m = l * i.BYTES_PER_ELEMENT, g = Math.ceil(m / 4) * 4, E = g / i.BYTES_PER_ELEMENT, w = a * m, A = a * g, y = e._malloc(w);
n.GetAttributeDataArrayForAllPoints(
c,
f,
p,
w,
y
);
const R = new i(
e.HEAPF32.buffer,
y,
w / i.BYTES_PER_ELEMENT
);
let D;
if (m === g)
D = R.slice();
else {
D = new i(
A / i.BYTES_PER_ELEMENT
);
let I = 0;
for (let T = 0, N = R.length; T < N; T += l) {
for (let L = 0; L < l; L++)
D[I + L] = R[T + L];
I += E;
}
}
return e._free(y), {
name: d,
count: a,
itemSize: l,
array: D,
stride: E
};
}
function u(e, n) {
switch (n) {
case Float32Array:
return e.DT_FLOAT32;
case Int8Array:
return e.DT_INT8;
case Int16Array:
return e.DT_INT16;
case Int32Array:
return e.DT_INT32;
case Uint8Array:
return e.DT_UINT8;
case Uint16Array:
return e.DT_UINT16;
case Uint32Array:
return e.DT_UINT32;
}
}
}
const b = {
LOAD_DRACO_JS_DECODER: async () => (await import("three/examples/jsm/libs/draco/draco_decoder.js?raw")).default,
LOAD_DRACO_WASM_WRAPPER: async () => (await import("three/examples/jsm/libs/draco/draco_wasm_wrapper.js?raw")).default,
LOAD_DRACO_WASM_DECODER: async () => {
const _ = (await import("three/examples/jsm/libs/draco/draco_decoder.wasm?url")).default;
return await (await fetch(_)).arrayBuffer();
}
};
class $ extends Y {
constructor() {
super(...arguments);
h(this, "decoderPending", null);
h(this, "decoderConfig", {
type: "js",
wasmBinary: null
});
h(this, "workerSourceURL", "");
}
async _initDecoder() {
if (this.decoderPending) return this.decoderPending;
const s = typeof WebAssembly != "object" || this.decoderConfig.type === "js", t = [];
return s ? t.push(
b.LOAD_DRACO_JS_DECODER()
) : (t.push(
b.LOAD_DRACO_WASM_WRAPPER()
), t.push(
b.LOAD_DRACO_WASM_DECODER()
)), this.decoderPending = Promise.all(t).then(
(o) => {
const u = o[0];
s || (this.decoderConfig.wasmBinary = o[1]);
const e = J.toString(), n = [
"/* draco decoder */",
u,
"",
"/* worker */",
e.substring(e.indexOf("{") + 1, e.lastIndexOf("}"))
].join(`
`);
this.workerSourceURL = URL.createObjectURL(new Blob([n]));
}
), this.decoderPending;
}
}
function q() {
let _ = null, r = null;
const s = [
[
/'CONFIG_CONTROL_DESIGN'\s*\)/g,
"'AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF')"
],
[
/'AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF\.\s*\{[\s\S]*?\}\s*'/g,
"'AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF'"
]
];
function t() {
return _ || (_ = occtimportjs({
// eslint-disable-line no-undef
locateFile: function() {
return r;
}
})), _;
}
function o(e) {
for (var n = new TextDecoder("utf-8", { fatal: !1 }), c = new TextEncoder(), d = n.decode(e), i = 0; i < s.length; i++) {
var f = s[i][0], a = s[i][1];
d = d.replace(f, a);
}
return new Uint8Array(c.encode(d));
}
function u(e, n) {
var c = o(n);
try {
var d = e.ReadStepFile(c, null);
if (d.success && d.root) return d;
} catch {
}
try {
return e.ReadStepFile(n, null);
} catch {
return {
success: !1,
root: { meshes: [], children: [] },
meshes: []
};
}
}
onmessage = async function(e) {
var n = e.data;
switch (n.type) {
case "init":
r = n.wasmUrl;
break;
case "parse":
try {
var c = await t(), d = new Uint8Array(n.buffer), i = n.fileType, f;
if (i === "step" || i === "stp" ? f = u(c, d) : f = c.ReadIgesFile(d, null), !f.success || !f.root) {
self.postMessage({
type: "error",
id: n.id,
error: "Failed to parse CAD file"
});
return;
}
self.postMessage({
type: "result",
id: n.id,
result: f
});
} catch (a) {
self.postMessage({
type: "error",
id: n.id,
error: a instanceof Error ? a.message : String(a)
});
}
break;
}
};
}
const U = {
LOAD_OCCT_JS: async () => (await import("./occt-import-js-D-bjjBtk.mjs")).default,
LOAD_OCCT_WASM_URL: async () => (await import("./occt-import-js-ekuHaP1Z.mjs")).default
};
class V {
constructor() {
h(this, "_workerPending", null);
h(this, "_worker", null);
h(this, "_nextId", 0);
h(this, "_pending", /* @__PURE__ */ new Map());
}
/**
* Create (or return existing) blob-URL worker.
* Loads occt-import-js JS as raw text, concatenates with STEPWorker
* function body, and creates a classic (non-module) worker.
*/
_getWorker() {
return this._workerPending ? this._workerPending : (this._workerPending = (async () => {
const [
r,
s
] = await Promise.all([
U.LOAD_OCCT_JS(),
U.LOAD_OCCT_WASM_URL()
]), t = q.toString(), o = [
"/* occt-import-js */",
r,
"",
"/* step worker */",
t.substring(t.indexOf("{") + 1, t.lastIndexOf("}"))
].join(`
`), u = URL.createObjectURL(new Blob([o])), e = new Worker(u), n = new URL(s, window.location.href).href;
return e.postMessage({ type: "init", wasmUrl: n }), e.onmessage = (c) => {
const { type: d, id: i, result: f, error: a } = c.data, l = this._pending.get(i);
if (l)
if (this._pending.delete(i), d === "result")
try {
l.resolve(this._buildScene(f));
} catch (p) {
l.reject(
p instanceof Error ? p : new Error(String(p))
);
}
else
l.reject(new Error(a ?? "Worker error"));
}, e.onerror = (c) => {
for (const [
,
{ reject: d }
] of this._pending)
d(new Error(c.message ?? "Worker error"));
this._pending.clear();
}, this._worker = e, e;
})(), this._workerPending);
}
/**
* Parse STEP or IGES file content and return a Three.js Object3D
*/
async parseAsync(r, s) {
const t = this._nextId++, o = await this._getWorker();
return new Promise((u, e) => {
this._pending.set(t, { resolve: u, reject: e });
const n = r.slice(0);
o.postMessage({ type: "parse", id: t, buffer: n, fileType: s }, [
n
]);
});
}
/**
* Dispose the worker. Call when the loader is no longer needed.
*/
dispose() {
if (this._worker) {
for (const [
,
{ reject: r }
] of this._pending)
r(new Error("STEPLoader disposed"));
this._pending.clear(), this._worker.terminate(), this._worker = null, this._workerPending = null;
}
}
_buildScene(r) {
const s = new C();
return s.name = r.root.name ?? "CAD Model", this._buildNode(r.root, r.meshes, s), s.rotation.x = -Math.PI / 2, s.rotation.z = Math.PI / 2, s;
}
_buildNode(r, s, t) {
const o = new C();
o.name = r.name ?? "Part";
for (const u of r.meshes) {
const e = s[u];
if (e != null && e.attributes) {
const n = this._createMesh(e);
o.add(n);
}
}
for (const u of r.children)
this._buildNode(u, s, o);
t.add(o);
}
_createMesh(r) {
var d, i;
const { position: s, normal: t } = r.attributes, o = r.index ?? r.attributes.index, u = new W();
u.setAttribute(
"position",
new O(new Float32Array(s.array), 3)
), (d = t == null ? void 0 : t.array) != null && d.length ? u.setAttribute(
"normal",
new O(new Float32Array(t.array), 3)
) : u.computeVertexNormals(), (i = o == null ? void 0 : o.array) != null && i.length && u.setIndex(
new O(new Uint32Array(o.array), 1)
);
const e = r.color, n = new v({
metalness: 0.3,
roughness: 0.6
});
e && e.length >= 3 ? n.color.setRGB(e[0], e[1], e[2]) : n.color.setHex(13421772);
const c = new j(u, n);
return c.name = r.name ?? "Mesh", c.castShadow = !0, c.receiveShadow = !0, c;
}
}
class ae {
constructor() {
h(this, "_gltfLoader");
h(this, "_usdLoader");
h(this, "_stepLoader");
const r = new $();
r.setDecoderConfig({ type: "wasm" }), this._gltfLoader = new x(), this._gltfLoader.setDRACOLoader(r), this._usdLoader = new G(), this._stepLoader = new V();
}
async load(r, s) {
let t;
if (s)
t = s;
else if (t = H(r), t.length === 0 && (t = await this._detectFileTypeFromContent(r), t.length === 0))
throw new P(
"No file extension found in URI",
""
);
if (!z(t))
throw new P(
`Unsupported file type: ${t}. Supported types: ${B.join(", ")}`,
t
);
const o = S.read(r);
if (o)
return o.arrayBuffer ? this._parse(o.arrayBuffer, t) : o.promise.then((n) => this._parse(n, t));
const e = await S.create(r).load();
return this._parse(e, t);
}
/**
* Detects file type from content (magic bytes)
* @param uri - The URI to load and detect
* @returns The detected file extension or empty string if detection fails
*/
async _detectFileTypeFromContent(r) {
try {
const s = S.read(r);
let t;
s ? s.arrayBuffer ? t = s.arrayBuffer : t = await s.promise : t = await S.create(r).load();
const o = new Uint8Array(t);
return o.length >= 12 && String.fromCharCode(
o[0],
o[1],
o[2],
o[3]
) === "glTF" ? o[12] === 0 ? "glb" : "gltf" : o.length >= 4 && o[0] === 80 && // 'P'
o[1] === 75 && // 'K'
(o[2] === 3 || o[2] === 5) && (o[3] === 4 || o[3] === 6) ? "usdz" : o.length >= 20 && new TextDecoder("ascii").decode(
o.subarray(0, 20)
).startsWith("ISO-10303-21") ? "step" : o.length >= 80 && o[72] === 83 ? "iges" : "";
} catch {
return "";
}
}
/**
* parse function for the chunk
* @param arrayBuffer - the array buffer to parse, will be provided within the chunk
* @param type - the file type of the array buffer
* @returns the parsed object, will be stored within the chunk
*/
async _parse(r, s) {
try {
switch (s) {
case "glb":
case "gltf": {
const t = await this._gltfLoader.parseAsync(
r,
""
);
return t.scene.animations = t.animations, t.scene;
}
case "usdz": {
const t = this._usdLoader.parse(r);
return t.animations = [], t;
}
case "step":
case "stp": {
const t = await this._stepLoader.parseAsync(
r,
s
);
return t.animations = [], t;
}
case "iges":
case "igs": {
const t = await this._stepLoader.parseAsync(
r,
s
);
return t.animations = [], t;
}
}
} catch (t) {
throw t instanceof Error ? new M(
`Failed to parse ${s} file: ${t.message}`,
t
) : new M(`Failed to parse ${s} file`);
}
}
}
export {
ae as A,
J as D,
$ as a
};