@vizij/render 0.1.0 → 0.1.2
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/README.md +12 -8
- package/dist/index.d.mts +42 -2
- package/dist/index.d.ts +42 -2
- package/dist/index.js +663 -131
- package/dist/index.mjs +654 -121
- package/package.json +18 -17
- package/LICENSE +0 -201
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ __export(index_exports, {
|
|
|
45
45
|
loadGLTFFromBlobWithBundle: () => loadGLTFFromBlobWithBundle,
|
|
46
46
|
loadGLTFWithBundle: () => loadGLTFWithBundle,
|
|
47
47
|
loadGltfFromBlob: () => loadGltfFromBlob,
|
|
48
|
+
parseGlbJsonChunk: () => parseGlbJsonChunk,
|
|
48
49
|
useDefaultVizijStore: () => useDefaultVizijStore,
|
|
49
50
|
useFeatures: () => useFeatures,
|
|
50
51
|
useVizijStore: () => useVizijStore,
|
|
@@ -1005,6 +1006,48 @@ function InnerRenderedShape({
|
|
|
1005
1006
|
);
|
|
1006
1007
|
}
|
|
1007
1008
|
},
|
|
1009
|
+
roughness: (value) => {
|
|
1010
|
+
const standard = material.current;
|
|
1011
|
+
if (standard?.roughness !== void 0 && (0, import_utils5.instanceOfRawNumber)(value)) {
|
|
1012
|
+
standard.roughness = value;
|
|
1013
|
+
standard.needsUpdate = true;
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
1016
|
+
metalness: (value) => {
|
|
1017
|
+
const standard = material.current;
|
|
1018
|
+
if (standard?.metalness !== void 0 && (0, import_utils5.instanceOfRawNumber)(value)) {
|
|
1019
|
+
standard.metalness = value;
|
|
1020
|
+
standard.needsUpdate = true;
|
|
1021
|
+
}
|
|
1022
|
+
},
|
|
1023
|
+
shininess: (value) => {
|
|
1024
|
+
const phong = material.current;
|
|
1025
|
+
if (phong?.shininess !== void 0 && (0, import_utils5.instanceOfRawNumber)(value)) {
|
|
1026
|
+
phong.shininess = value;
|
|
1027
|
+
phong.needsUpdate = true;
|
|
1028
|
+
}
|
|
1029
|
+
},
|
|
1030
|
+
emissive: (value) => {
|
|
1031
|
+
const standard = material.current;
|
|
1032
|
+
if (standard?.emissive && (0, import_utils5.instanceOfRawRGB)(value)) {
|
|
1033
|
+
standard.emissive.setRGB(value.r, value.g, value.b);
|
|
1034
|
+
standard.needsUpdate = true;
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
1037
|
+
emissiveIntensity: (value) => {
|
|
1038
|
+
const standard = material.current;
|
|
1039
|
+
if (standard?.emissiveIntensity !== void 0 && (0, import_utils5.instanceOfRawNumber)(value)) {
|
|
1040
|
+
standard.emissiveIntensity = value;
|
|
1041
|
+
standard.needsUpdate = true;
|
|
1042
|
+
}
|
|
1043
|
+
},
|
|
1044
|
+
specular: (value) => {
|
|
1045
|
+
const phong = material.current;
|
|
1046
|
+
if (phong?.specular && (0, import_utils5.instanceOfRawRGB)(value)) {
|
|
1047
|
+
phong.specular.setRGB(value.r, value.g, value.b);
|
|
1048
|
+
phong.needsUpdate = true;
|
|
1049
|
+
}
|
|
1050
|
+
},
|
|
1008
1051
|
...morphTargetSettings[2]
|
|
1009
1052
|
},
|
|
1010
1053
|
shape
|
|
@@ -1125,7 +1168,10 @@ var MATERIAL_FEATURE_KEYS = [
|
|
|
1125
1168
|
"opacity",
|
|
1126
1169
|
"roughness",
|
|
1127
1170
|
"metalness",
|
|
1128
|
-
"shininess"
|
|
1171
|
+
"shininess",
|
|
1172
|
+
"emissive",
|
|
1173
|
+
"emissiveIntensity",
|
|
1174
|
+
"specular"
|
|
1129
1175
|
];
|
|
1130
1176
|
var MATERIAL_NAME_SUFFIXES = [
|
|
1131
1177
|
" color",
|
|
@@ -1134,7 +1180,10 @@ var MATERIAL_NAME_SUFFIXES = [
|
|
|
1134
1180
|
" opacity",
|
|
1135
1181
|
" roughness",
|
|
1136
1182
|
" metalness",
|
|
1137
|
-
" shininess"
|
|
1183
|
+
" shininess",
|
|
1184
|
+
" emissive intensity",
|
|
1185
|
+
" emissive",
|
|
1186
|
+
" specular"
|
|
1138
1187
|
];
|
|
1139
1188
|
function deriveMaterialName(shape, values) {
|
|
1140
1189
|
for (const key of MATERIAL_FEATURE_KEYS) {
|
|
@@ -1241,19 +1290,20 @@ var import_zustand2 = require("zustand");
|
|
|
1241
1290
|
var import_middleware = require("zustand/middleware");
|
|
1242
1291
|
var import_immer = require("immer");
|
|
1243
1292
|
var THREE3 = __toESM(require("three"));
|
|
1244
|
-
var
|
|
1293
|
+
var import_utils8 = require("@vizij/utils");
|
|
1245
1294
|
|
|
1246
1295
|
// src/actions/create-new-element.ts
|
|
1247
1296
|
var import_react9 = require("react");
|
|
1248
1297
|
var import_lodash3 = require("lodash");
|
|
1249
1298
|
|
|
1250
1299
|
// src/functions/create-world-element.ts
|
|
1300
|
+
var import_utils6 = require("@vizij/utils");
|
|
1251
1301
|
function createDefaultGroup(partialBody) {
|
|
1252
1302
|
const translation = partialBody.features?.translation || { animated: false, value: { x: 0, y: 0 } };
|
|
1253
1303
|
const rotation = partialBody.features?.rotation || { animated: false, value: { x: 0, y: 0, z: 0 } };
|
|
1254
1304
|
const scale = partialBody.features?.scale || { animated: false, value: { x: 1, y: 1, z: 1 } };
|
|
1255
1305
|
return {
|
|
1256
|
-
id: partialBody.id ||
|
|
1306
|
+
id: partialBody.id || (0, import_utils6.createBrowserSafeId)(),
|
|
1257
1307
|
name: partialBody.name || "new-body",
|
|
1258
1308
|
type: partialBody.type || "group",
|
|
1259
1309
|
tags: partialBody.tags || [],
|
|
@@ -1314,7 +1364,32 @@ function removeFromTree(state, nodesToRemove) {
|
|
|
1314
1364
|
});
|
|
1315
1365
|
}
|
|
1316
1366
|
|
|
1367
|
+
// src/memoryInvestigation.ts
|
|
1368
|
+
function getGlobalMemoryInvestigation() {
|
|
1369
|
+
return globalThis;
|
|
1370
|
+
}
|
|
1371
|
+
function updateRenderState(updater) {
|
|
1372
|
+
const globalObj = getGlobalMemoryInvestigation();
|
|
1373
|
+
if (!globalObj.__VIZIJ_MEMORY_INVESTIGATION__?.enabled) {
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
if (!globalObj.__vizijMemoryDebugState) {
|
|
1377
|
+
globalObj.__vizijMemoryDebugState = {};
|
|
1378
|
+
}
|
|
1379
|
+
if (!globalObj.__vizijMemoryDebugState.render) {
|
|
1380
|
+
globalObj.__vizijMemoryDebugState.render = {};
|
|
1381
|
+
}
|
|
1382
|
+
updater(globalObj.__vizijMemoryDebugState.render);
|
|
1383
|
+
}
|
|
1384
|
+
function recordRenderCounter(key, delta = 1) {
|
|
1385
|
+
updateRenderState((renderState) => {
|
|
1386
|
+
const current = typeof renderState[key] === "number" ? Number(renderState[key]) : 0;
|
|
1387
|
+
renderState[key] = current + delta;
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1317
1391
|
// src/functions/create-animatable.ts
|
|
1392
|
+
var import_utils7 = require("@vizij/utils");
|
|
1318
1393
|
function createAnimatable(value) {
|
|
1319
1394
|
if (!value.type) {
|
|
1320
1395
|
return null;
|
|
@@ -1324,7 +1399,7 @@ function createAnimatable(value) {
|
|
|
1324
1399
|
}
|
|
1325
1400
|
if (value.type === "euler") {
|
|
1326
1401
|
const newAnimatable = {
|
|
1327
|
-
id: value.id ??
|
|
1402
|
+
id: value.id ?? (0, import_utils7.createBrowserSafeId)(),
|
|
1328
1403
|
name: `${value.name} Rotation`,
|
|
1329
1404
|
type: value.type,
|
|
1330
1405
|
default: value.default ?? { x: 0, y: 0, z: 0 },
|
|
@@ -1341,7 +1416,7 @@ function createAnimatable(value) {
|
|
|
1341
1416
|
return newAnimatable;
|
|
1342
1417
|
} else if (value.type === "vector3") {
|
|
1343
1418
|
const newAnimatable = {
|
|
1344
|
-
id: value.id ??
|
|
1419
|
+
id: value.id ?? (0, import_utils7.createBrowserSafeId)(),
|
|
1345
1420
|
name: `${value.name} Vector3`,
|
|
1346
1421
|
type: value.type,
|
|
1347
1422
|
default: value.default ?? { x: 0, y: 0, z: 0 },
|
|
@@ -1358,7 +1433,7 @@ function createAnimatable(value) {
|
|
|
1358
1433
|
return newAnimatable;
|
|
1359
1434
|
} else if (value.type === "string") {
|
|
1360
1435
|
const newAnimatable = {
|
|
1361
|
-
id: value.id ??
|
|
1436
|
+
id: value.id ?? (0, import_utils7.createBrowserSafeId)(),
|
|
1362
1437
|
name: value.name,
|
|
1363
1438
|
type: value.type,
|
|
1364
1439
|
default: value.default ?? "Hello World",
|
|
@@ -1371,7 +1446,7 @@ function createAnimatable(value) {
|
|
|
1371
1446
|
return newAnimatable;
|
|
1372
1447
|
} else if (value.type === "number") {
|
|
1373
1448
|
const newAnimatable = {
|
|
1374
|
-
id: value.id ??
|
|
1449
|
+
id: value.id ?? (0, import_utils7.createBrowserSafeId)(),
|
|
1375
1450
|
name: value.name,
|
|
1376
1451
|
type: value.type,
|
|
1377
1452
|
default: value.default ?? 0,
|
|
@@ -1384,7 +1459,7 @@ function createAnimatable(value) {
|
|
|
1384
1459
|
return newAnimatable;
|
|
1385
1460
|
} else if (value.type === "boolean") {
|
|
1386
1461
|
const newAnimatable = {
|
|
1387
|
-
id: value.id ??
|
|
1462
|
+
id: value.id ?? (0, import_utils7.createBrowserSafeId)(),
|
|
1388
1463
|
name: value.name,
|
|
1389
1464
|
type: value.type,
|
|
1390
1465
|
default: value.default ?? false,
|
|
@@ -1397,7 +1472,7 @@ function createAnimatable(value) {
|
|
|
1397
1472
|
return newAnimatable;
|
|
1398
1473
|
} else if (value.type === "rgb") {
|
|
1399
1474
|
const newAnimatable = {
|
|
1400
|
-
id: value.id ??
|
|
1475
|
+
id: value.id ?? (0, import_utils7.createBrowserSafeId)(),
|
|
1401
1476
|
name: value.name,
|
|
1402
1477
|
type: value.type,
|
|
1403
1478
|
default: value.default ?? { r: 0, g: 0, b: 0 },
|
|
@@ -1414,7 +1489,7 @@ function createAnimatable(value) {
|
|
|
1414
1489
|
return newAnimatable;
|
|
1415
1490
|
} else if (value.type === "hsl") {
|
|
1416
1491
|
const newAnimatable = {
|
|
1417
|
-
id: value.id ??
|
|
1492
|
+
id: value.id ?? (0, import_utils7.createBrowserSafeId)(),
|
|
1418
1493
|
name: value.name,
|
|
1419
1494
|
type: value.type,
|
|
1420
1495
|
default: value.default ?? { h: 0, s: 0, l: 0 },
|
|
@@ -1434,6 +1509,35 @@ function createAnimatable(value) {
|
|
|
1434
1509
|
}
|
|
1435
1510
|
createAnimatable({ type: "euler", name: "Rotation" });
|
|
1436
1511
|
|
|
1512
|
+
// src/functions/exportable-bodies.ts
|
|
1513
|
+
function asGroupEntries(world) {
|
|
1514
|
+
return Object.values(world).filter((entry) => entry.type === "group");
|
|
1515
|
+
}
|
|
1516
|
+
function selectExportableGroupEntries(world, filterIds) {
|
|
1517
|
+
const groupEntries = asGroupEntries(world);
|
|
1518
|
+
const filterSet = Array.isArray(filterIds) && filterIds.length > 0 ? new Set(filterIds) : null;
|
|
1519
|
+
if (filterSet) {
|
|
1520
|
+
return groupEntries.filter((entry) => filterSet.has(entry.id));
|
|
1521
|
+
}
|
|
1522
|
+
const rootBoundsGroups = groupEntries.filter(
|
|
1523
|
+
(entry) => Boolean(entry.rootBounds)
|
|
1524
|
+
);
|
|
1525
|
+
if (rootBoundsGroups.length > 0) {
|
|
1526
|
+
return rootBoundsGroups;
|
|
1527
|
+
}
|
|
1528
|
+
const explicitRootGroups = groupEntries.filter(
|
|
1529
|
+
(entry) => entry.root === true
|
|
1530
|
+
);
|
|
1531
|
+
if (explicitRootGroups.length > 0) {
|
|
1532
|
+
return explicitRootGroups;
|
|
1533
|
+
}
|
|
1534
|
+
const topLevelGroups = groupEntries.filter((entry) => !entry.parent);
|
|
1535
|
+
if (topLevelGroups.length > 0) {
|
|
1536
|
+
return topLevelGroups;
|
|
1537
|
+
}
|
|
1538
|
+
return groupEntries;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1437
1541
|
// src/store.ts
|
|
1438
1542
|
THREE3.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
1439
1543
|
(0, import_immer.enableMapSet)();
|
|
@@ -1509,23 +1613,17 @@ var VizijSlice = (set, get) => ({
|
|
|
1509
1613
|
},
|
|
1510
1614
|
getExportableBodies: (filterIds) => {
|
|
1511
1615
|
const worldData = get().world;
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
const
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
const firstNs = Object.keys(entry.refs)[0];
|
|
1524
|
-
const refGroup = entry.refs[firstNs].current;
|
|
1525
|
-
return refGroup;
|
|
1526
|
-
});
|
|
1527
|
-
return bodies;
|
|
1528
|
-
}
|
|
1616
|
+
const candidateGroups = selectExportableGroupEntries(
|
|
1617
|
+
worldData,
|
|
1618
|
+
filterIds
|
|
1619
|
+
);
|
|
1620
|
+
return candidateGroups.flatMap((entry) => {
|
|
1621
|
+
const refs = Object.values(
|
|
1622
|
+
entry.refs ?? {}
|
|
1623
|
+
);
|
|
1624
|
+
const resolved = refs.find((ref) => ref?.current)?.current ?? null;
|
|
1625
|
+
return resolved ? [resolved] : [];
|
|
1626
|
+
});
|
|
1529
1627
|
},
|
|
1530
1628
|
setGeometry: (id, geometry) => {
|
|
1531
1629
|
set(
|
|
@@ -1537,7 +1635,7 @@ var VizijSlice = (set, get) => ({
|
|
|
1537
1635
|
setValue: (id, namespace, value) => {
|
|
1538
1636
|
set(
|
|
1539
1637
|
(0, import_immer.produce)((state) => {
|
|
1540
|
-
const lookupId = (0,
|
|
1638
|
+
const lookupId = (0, import_utils8.getLookup)(namespace, id);
|
|
1541
1639
|
if (typeof value === "function") {
|
|
1542
1640
|
const current = state.values.get(lookupId);
|
|
1543
1641
|
if (current !== void 0) {
|
|
@@ -1566,7 +1664,7 @@ var VizijSlice = (set, get) => ({
|
|
|
1566
1664
|
set(
|
|
1567
1665
|
(0, import_immer.produce)((state) => {
|
|
1568
1666
|
writes.forEach(({ id, namespace, value }) => {
|
|
1569
|
-
const lookupId = (0,
|
|
1667
|
+
const lookupId = (0, import_utils8.getLookup)(namespace, id);
|
|
1570
1668
|
state.values.set(lookupId, value);
|
|
1571
1669
|
});
|
|
1572
1670
|
})
|
|
@@ -1697,8 +1795,8 @@ var VizijSlice = (set, get) => ({
|
|
|
1697
1795
|
setSlot: (parentId, parentNamespace, childId, childNamespace) => {
|
|
1698
1796
|
set(
|
|
1699
1797
|
(0, import_immer.produce)((state) => {
|
|
1700
|
-
const parentLookupId = (0,
|
|
1701
|
-
const childLookupId = (0,
|
|
1798
|
+
const parentLookupId = (0, import_utils8.getLookup)(parentNamespace, parentId);
|
|
1799
|
+
const childLookupId = (0, import_utils8.getLookup)(childNamespace, childId);
|
|
1702
1800
|
state.slotConfig[parentLookupId] = childLookupId;
|
|
1703
1801
|
})
|
|
1704
1802
|
);
|
|
@@ -1717,12 +1815,13 @@ var VizijSlice = (set, get) => ({
|
|
|
1717
1815
|
clearSlot: (parentId, parentNamespace) => {
|
|
1718
1816
|
set(
|
|
1719
1817
|
(0, import_immer.produce)((state) => {
|
|
1720
|
-
const parentLookupId = (0,
|
|
1818
|
+
const parentLookupId = (0, import_utils8.getLookup)(parentNamespace, parentId);
|
|
1721
1819
|
delete state.slotConfig[parentLookupId];
|
|
1722
1820
|
})
|
|
1723
1821
|
);
|
|
1724
1822
|
},
|
|
1725
1823
|
setVizij: (scene, animatables) => {
|
|
1824
|
+
recordRenderCounter("rootReplacementCount");
|
|
1726
1825
|
set({
|
|
1727
1826
|
world: scene,
|
|
1728
1827
|
animatables
|
|
@@ -1730,6 +1829,7 @@ var VizijSlice = (set, get) => ({
|
|
|
1730
1829
|
},
|
|
1731
1830
|
addWorldElements(world, animatables, replace) {
|
|
1732
1831
|
if (replace) {
|
|
1832
|
+
recordRenderCounter("rootReplacementCount");
|
|
1733
1833
|
set({ world, animatables });
|
|
1734
1834
|
} else {
|
|
1735
1835
|
set((state) => ({
|
|
@@ -1774,7 +1874,7 @@ var import_three = require("three");
|
|
|
1774
1874
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1775
1875
|
function SelectionGlowEffect({
|
|
1776
1876
|
enabled = false,
|
|
1777
|
-
color = "#
|
|
1877
|
+
color = "#ff1010",
|
|
1778
1878
|
opacity = 0.9,
|
|
1779
1879
|
thresholdAngle = 2
|
|
1780
1880
|
}) {
|
|
@@ -1880,6 +1980,13 @@ function Vizij({
|
|
|
1880
1980
|
onPointerMissed
|
|
1881
1981
|
}) {
|
|
1882
1982
|
const ctx = (0, import_react11.useContext)(VizijContext);
|
|
1983
|
+
(0, import_react11.useEffect)(() => {
|
|
1984
|
+
recordRenderCounter("canvasMountCount");
|
|
1985
|
+
recordRenderCounter("mountedCanvasCount");
|
|
1986
|
+
return () => {
|
|
1987
|
+
recordRenderCounter("mountedCanvasCount", -1);
|
|
1988
|
+
};
|
|
1989
|
+
}, []);
|
|
1883
1990
|
if (ctx) {
|
|
1884
1991
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1885
1992
|
import_fiber2.Canvas,
|
|
@@ -1948,7 +2055,7 @@ function InnerVizij({
|
|
|
1948
2055
|
makeDefault: true,
|
|
1949
2056
|
position: [0, 0, 100],
|
|
1950
2057
|
near: 0.1,
|
|
1951
|
-
far:
|
|
2058
|
+
far: 1e3
|
|
1952
2059
|
}
|
|
1953
2060
|
),
|
|
1954
2061
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react11.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -2126,6 +2233,7 @@ var import_three5 = require("three");
|
|
|
2126
2233
|
|
|
2127
2234
|
// src/functions/gltf-loading/import-group.ts
|
|
2128
2235
|
var import_three4 = require("three");
|
|
2236
|
+
var import_utils11 = require("@vizij/utils");
|
|
2129
2237
|
|
|
2130
2238
|
// src/functions/util.ts
|
|
2131
2239
|
var import_react15 = require("react");
|
|
@@ -2135,8 +2243,10 @@ function namespaceArrayToRefs(namespaces) {
|
|
|
2135
2243
|
|
|
2136
2244
|
// src/functions/gltf-loading/import-mesh.ts
|
|
2137
2245
|
var import_three3 = require("three");
|
|
2246
|
+
var import_utils10 = require("@vizij/utils");
|
|
2138
2247
|
|
|
2139
2248
|
// src/functions/gltf-loading/import-geometry.ts
|
|
2249
|
+
var import_utils9 = require("@vizij/utils");
|
|
2140
2250
|
function sanitizeMorphKey(name, fallbackIndex, used) {
|
|
2141
2251
|
const baseName = name && name.trim().length > 0 ? name.trim() : `morph_${fallbackIndex + 1}`;
|
|
2142
2252
|
const slug = baseName.toLowerCase().replace(/[^a-z0-9]+/gi, "_").replace(/^_+|_+$/g, "");
|
|
@@ -2160,7 +2270,7 @@ function importGeometry(geometry, mesh) {
|
|
|
2160
2270
|
const usedKeys = /* @__PURE__ */ new Set();
|
|
2161
2271
|
Object.entries(mesh.morphTargetDictionary ?? {}).forEach(
|
|
2162
2272
|
([name, index]) => {
|
|
2163
|
-
const morphId =
|
|
2273
|
+
const morphId = (0, import_utils9.createBrowserSafeId)();
|
|
2164
2274
|
const featureKey = sanitizeMorphKey(name, index, usedKeys);
|
|
2165
2275
|
morphIds.push(featureKey);
|
|
2166
2276
|
features[featureKey] = {
|
|
@@ -2196,7 +2306,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2196
2306
|
let animatables = {};
|
|
2197
2307
|
let newColorLookup = {};
|
|
2198
2308
|
const translationAnimatable = {
|
|
2199
|
-
id:
|
|
2309
|
+
id: (0, import_utils10.createBrowserSafeId)(),
|
|
2200
2310
|
name: `${mesh.name ?? "Mesh"} translation`,
|
|
2201
2311
|
type: "vector3",
|
|
2202
2312
|
default: { x: mesh.position.x, y: mesh.position.y, z: mesh.position.z },
|
|
@@ -2212,7 +2322,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2212
2322
|
[translationAnimatable.id]: translationAnimatable
|
|
2213
2323
|
};
|
|
2214
2324
|
const rotationAnimatable = {
|
|
2215
|
-
id:
|
|
2325
|
+
id: (0, import_utils10.createBrowserSafeId)(),
|
|
2216
2326
|
name: `${mesh.name ?? "Mesh"} rotation`,
|
|
2217
2327
|
type: "euler",
|
|
2218
2328
|
default: { x: mesh.rotation.x, y: mesh.rotation.y, z: mesh.rotation.z },
|
|
@@ -2225,7 +2335,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2225
2335
|
};
|
|
2226
2336
|
animatables = { ...animatables, [rotationAnimatable.id]: rotationAnimatable };
|
|
2227
2337
|
const scaleAnimatable = {
|
|
2228
|
-
id:
|
|
2338
|
+
id: (0, import_utils10.createBrowserSafeId)(),
|
|
2229
2339
|
name: `${mesh.name ?? "Mesh"} scale`,
|
|
2230
2340
|
type: "vector3",
|
|
2231
2341
|
default: { x: mesh.scale.x, y: mesh.scale.y, z: mesh.scale.z },
|
|
@@ -2236,56 +2346,120 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2236
2346
|
}
|
|
2237
2347
|
};
|
|
2238
2348
|
animatables = { ...animatables, [scaleAnimatable.id]: scaleAnimatable };
|
|
2239
|
-
const
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
type: "rgb",
|
|
2250
|
-
default: { r: color.r, g: color.g, b: color.b },
|
|
2251
|
-
constraints: {
|
|
2252
|
-
min: [0, 0, 0],
|
|
2253
|
-
max: [1, 1, 1]
|
|
2254
|
-
},
|
|
2349
|
+
const material = mesh.material;
|
|
2350
|
+
const color = material.color;
|
|
2351
|
+
const colorName = material.name;
|
|
2352
|
+
const label = (suffix) => colorName ? `${colorName} ${suffix}` : `${mesh.name ?? "Mesh"} ${suffix}`;
|
|
2353
|
+
const makeNumberAnimatable = (suffix, value, constraints) => ({
|
|
2354
|
+
id: (0, import_utils10.createBrowserSafeId)(),
|
|
2355
|
+
name: label(suffix),
|
|
2356
|
+
type: "number",
|
|
2357
|
+
default: value,
|
|
2358
|
+
constraints,
|
|
2255
2359
|
pub: {
|
|
2256
2360
|
public: true,
|
|
2257
|
-
output:
|
|
2361
|
+
output: label(suffix)
|
|
2258
2362
|
}
|
|
2259
|
-
};
|
|
2260
|
-
const
|
|
2261
|
-
id:
|
|
2262
|
-
name:
|
|
2263
|
-
type: "
|
|
2264
|
-
default:
|
|
2363
|
+
});
|
|
2364
|
+
const makeColorAnimatable = (suffix, value) => ({
|
|
2365
|
+
id: (0, import_utils10.createBrowserSafeId)(),
|
|
2366
|
+
name: label(suffix),
|
|
2367
|
+
type: "rgb",
|
|
2368
|
+
default: { r: value.r, g: value.g, b: value.b },
|
|
2265
2369
|
constraints: {
|
|
2266
|
-
min: 0,
|
|
2267
|
-
max: 1
|
|
2370
|
+
min: [0, 0, 0],
|
|
2371
|
+
max: [1, 1, 1]
|
|
2268
2372
|
},
|
|
2269
2373
|
pub: {
|
|
2270
2374
|
public: true,
|
|
2271
|
-
output:
|
|
2375
|
+
output: label(suffix)
|
|
2272
2376
|
}
|
|
2377
|
+
});
|
|
2378
|
+
const colorAnimatable = {
|
|
2379
|
+
...makeColorAnimatable("color", color),
|
|
2380
|
+
name: material.name ?? `${mesh.name ?? "Mesh"} color`
|
|
2273
2381
|
};
|
|
2274
|
-
|
|
2275
|
-
|
|
2382
|
+
const opacityAnimatable = makeNumberAnimatable("opacity", material.opacity, {
|
|
2383
|
+
min: 0,
|
|
2384
|
+
max: 1
|
|
2385
|
+
});
|
|
2386
|
+
const materialAnimatables = [
|
|
2387
|
+
colorAnimatable,
|
|
2388
|
+
opacityAnimatable
|
|
2389
|
+
];
|
|
2390
|
+
let roughnessAnimatable;
|
|
2391
|
+
let metalnessAnimatable;
|
|
2392
|
+
let emissiveAnimatable;
|
|
2393
|
+
let emissiveIntensityAnimatable;
|
|
2394
|
+
let shininessAnimatable;
|
|
2395
|
+
let specularAnimatable;
|
|
2396
|
+
if (material.isMeshStandardMaterial) {
|
|
2397
|
+
roughnessAnimatable = makeNumberAnimatable(
|
|
2398
|
+
"roughness",
|
|
2399
|
+
material.roughness,
|
|
2400
|
+
{
|
|
2401
|
+
min: 0,
|
|
2402
|
+
max: 1
|
|
2403
|
+
}
|
|
2404
|
+
);
|
|
2405
|
+
metalnessAnimatable = makeNumberAnimatable(
|
|
2406
|
+
"metalness",
|
|
2407
|
+
material.metalness,
|
|
2408
|
+
{
|
|
2409
|
+
min: 0,
|
|
2410
|
+
max: 1
|
|
2411
|
+
}
|
|
2412
|
+
);
|
|
2413
|
+
emissiveAnimatable = makeColorAnimatable("emissive", material.emissive);
|
|
2414
|
+
emissiveIntensityAnimatable = makeNumberAnimatable(
|
|
2415
|
+
"emissive intensity",
|
|
2416
|
+
material.emissiveIntensity,
|
|
2417
|
+
{ min: 0 }
|
|
2418
|
+
);
|
|
2419
|
+
materialAnimatables.push(
|
|
2420
|
+
roughnessAnimatable,
|
|
2421
|
+
metalnessAnimatable,
|
|
2422
|
+
emissiveAnimatable,
|
|
2423
|
+
emissiveIntensityAnimatable
|
|
2424
|
+
);
|
|
2425
|
+
} else if (mesh.material.isMeshPhongMaterial) {
|
|
2426
|
+
const phong = mesh.material;
|
|
2427
|
+
shininessAnimatable = makeNumberAnimatable("shininess", phong.shininess, {
|
|
2428
|
+
min: 0
|
|
2429
|
+
});
|
|
2430
|
+
emissiveAnimatable = makeColorAnimatable("emissive", phong.emissive);
|
|
2431
|
+
emissiveIntensityAnimatable = makeNumberAnimatable(
|
|
2432
|
+
"emissive intensity",
|
|
2433
|
+
phong.emissiveIntensity,
|
|
2434
|
+
{ min: 0 }
|
|
2435
|
+
);
|
|
2436
|
+
specularAnimatable = makeColorAnimatable("specular", phong.specular);
|
|
2437
|
+
materialAnimatables.push(
|
|
2438
|
+
shininessAnimatable,
|
|
2439
|
+
emissiveAnimatable,
|
|
2440
|
+
emissiveIntensityAnimatable,
|
|
2441
|
+
specularAnimatable
|
|
2442
|
+
);
|
|
2443
|
+
}
|
|
2444
|
+
let materialIds;
|
|
2276
2445
|
if (colorName && colorLookup[colorName]) {
|
|
2277
|
-
|
|
2278
|
-
opacityId = colorLookup[colorName][1];
|
|
2279
|
-
useEmissive = colorLookup[colorName][2];
|
|
2446
|
+
materialIds = colorLookup[colorName];
|
|
2280
2447
|
} else {
|
|
2281
|
-
|
|
2282
|
-
|
|
2448
|
+
materialIds = {
|
|
2449
|
+
color: colorAnimatable.id,
|
|
2450
|
+
opacity: opacityAnimatable.id,
|
|
2451
|
+
roughness: roughnessAnimatable?.id,
|
|
2452
|
+
metalness: metalnessAnimatable?.id,
|
|
2453
|
+
emissive: emissiveAnimatable?.id,
|
|
2454
|
+
emissiveIntensity: emissiveIntensityAnimatable?.id,
|
|
2455
|
+
shininess: shininessAnimatable?.id,
|
|
2456
|
+
specular: specularAnimatable?.id
|
|
2457
|
+
};
|
|
2458
|
+
materialAnimatables.forEach((animatable) => {
|
|
2459
|
+
animatables = { ...animatables, [animatable.id]: animatable };
|
|
2460
|
+
});
|
|
2283
2461
|
if (colorName) {
|
|
2284
|
-
newColorLookup[colorName] =
|
|
2285
|
-
colorAnimatable.id,
|
|
2286
|
-
opacityAnimatable.id,
|
|
2287
|
-
useEmissive
|
|
2288
|
-
];
|
|
2462
|
+
newColorLookup[colorName] = materialIds;
|
|
2289
2463
|
}
|
|
2290
2464
|
}
|
|
2291
2465
|
const [geometryFeatures, geometryAnimatables, morphTargets] = importGeometry(
|
|
@@ -2304,13 +2478,22 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2304
2478
|
world = { ...world, ...newWorldItems };
|
|
2305
2479
|
animatables = { ...animatables, ...newAnimatables };
|
|
2306
2480
|
children.push(childId);
|
|
2481
|
+
} else if (shouldImportAsGroupChild(child)) {
|
|
2482
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child, namespaces, {
|
|
2483
|
+
...colorLookup,
|
|
2484
|
+
...newColorLookup
|
|
2485
|
+
});
|
|
2486
|
+
newColorLookup = { ...newColorLookup, ...newMeshColors };
|
|
2487
|
+
world = { ...world, ...newWorldItems };
|
|
2488
|
+
animatables = { ...animatables, ...newAnimatables };
|
|
2489
|
+
children.push(childId);
|
|
2307
2490
|
}
|
|
2308
2491
|
});
|
|
2309
2492
|
const newShape = {
|
|
2310
2493
|
id: mesh.uuid,
|
|
2311
2494
|
name: mesh.name,
|
|
2312
2495
|
geometry: mesh.geometry,
|
|
2313
|
-
material: getShapeMaterial(mesh
|
|
2496
|
+
material: getShapeMaterial(mesh),
|
|
2314
2497
|
type: "shape",
|
|
2315
2498
|
tags: [],
|
|
2316
2499
|
morphTargets,
|
|
@@ -2318,8 +2501,19 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2318
2501
|
translation: { animated: true, value: translationAnimatable.id },
|
|
2319
2502
|
rotation: { animated: true, value: rotationAnimatable.id },
|
|
2320
2503
|
scale: { animated: true, value: scaleAnimatable.id },
|
|
2321
|
-
color: { animated: true, value:
|
|
2322
|
-
opacity: { animated: true, value:
|
|
2504
|
+
color: { animated: true, value: materialIds.color },
|
|
2505
|
+
opacity: { animated: true, value: materialIds.opacity },
|
|
2506
|
+
...materialIds.roughness ? { roughness: { animated: true, value: materialIds.roughness } } : {},
|
|
2507
|
+
...materialIds.metalness ? { metalness: { animated: true, value: materialIds.metalness } } : {},
|
|
2508
|
+
...materialIds.emissive ? { emissive: { animated: true, value: materialIds.emissive } } : {},
|
|
2509
|
+
...materialIds.emissiveIntensity ? {
|
|
2510
|
+
emissiveIntensity: {
|
|
2511
|
+
animated: true,
|
|
2512
|
+
value: materialIds.emissiveIntensity
|
|
2513
|
+
}
|
|
2514
|
+
} : {},
|
|
2515
|
+
...materialIds.shininess ? { shininess: { animated: true, value: materialIds.shininess } } : {},
|
|
2516
|
+
...materialIds.specular ? { specular: { animated: true, value: materialIds.specular } } : {},
|
|
2323
2517
|
...geometryFeatures
|
|
2324
2518
|
},
|
|
2325
2519
|
children: children.length > 0 ? children : void 0,
|
|
@@ -2328,11 +2522,8 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2328
2522
|
world = { ...world, [newShape.id]: newShape };
|
|
2329
2523
|
return [world, animatables, newShape.id, newColorLookup];
|
|
2330
2524
|
}
|
|
2331
|
-
function getShapeMaterial(mesh
|
|
2525
|
+
function getShapeMaterial(mesh) {
|
|
2332
2526
|
const material = mesh.material;
|
|
2333
|
-
if (useEmissive) {
|
|
2334
|
-
return "basic" /* Basic */;
|
|
2335
|
-
}
|
|
2336
2527
|
if (material.isMeshStandardMaterial) {
|
|
2337
2528
|
return "standard" /* Standard */;
|
|
2338
2529
|
} else if (material.isMeshPhongMaterial) {
|
|
@@ -2347,6 +2538,24 @@ function getShapeMaterial(mesh, useEmissive) {
|
|
|
2347
2538
|
return "standard" /* Standard */;
|
|
2348
2539
|
}
|
|
2349
2540
|
}
|
|
2541
|
+
function shouldImportAsGroupChild(child) {
|
|
2542
|
+
if (!child.isObject3D) {
|
|
2543
|
+
return false;
|
|
2544
|
+
}
|
|
2545
|
+
if (child.isMesh) {
|
|
2546
|
+
return false;
|
|
2547
|
+
}
|
|
2548
|
+
if (child.isCamera) {
|
|
2549
|
+
return false;
|
|
2550
|
+
}
|
|
2551
|
+
if (child.isLight) {
|
|
2552
|
+
return false;
|
|
2553
|
+
}
|
|
2554
|
+
if (child.isBone) {
|
|
2555
|
+
return false;
|
|
2556
|
+
}
|
|
2557
|
+
return true;
|
|
2558
|
+
}
|
|
2350
2559
|
|
|
2351
2560
|
// src/functions/gltf-loading/import-group.ts
|
|
2352
2561
|
import_three4.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
@@ -2356,7 +2565,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2356
2565
|
let newColorLookup = {};
|
|
2357
2566
|
const children = [];
|
|
2358
2567
|
const translationAnimatable = {
|
|
2359
|
-
id:
|
|
2568
|
+
id: (0, import_utils11.createBrowserSafeId)(),
|
|
2360
2569
|
name: `${group.name ?? "Group"} translation`,
|
|
2361
2570
|
type: "vector3",
|
|
2362
2571
|
default: { x: group.position.x, y: group.position.y, z: group.position.z },
|
|
@@ -2372,7 +2581,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2372
2581
|
[translationAnimatable.id]: translationAnimatable
|
|
2373
2582
|
};
|
|
2374
2583
|
const rotationAnimatable = {
|
|
2375
|
-
id:
|
|
2584
|
+
id: (0, import_utils11.createBrowserSafeId)(),
|
|
2376
2585
|
name: `${group.name ?? "Group"} rotation`,
|
|
2377
2586
|
type: "euler",
|
|
2378
2587
|
default: { x: group.rotation.x, y: group.rotation.y, z: group.rotation.z },
|
|
@@ -2385,7 +2594,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2385
2594
|
};
|
|
2386
2595
|
animatables = { ...animatables, [rotationAnimatable.id]: rotationAnimatable };
|
|
2387
2596
|
const scaleAnimatable = {
|
|
2388
|
-
id:
|
|
2597
|
+
id: (0, import_utils11.createBrowserSafeId)(),
|
|
2389
2598
|
name: `${group.name ?? "Group"} scale`,
|
|
2390
2599
|
type: "vector3",
|
|
2391
2600
|
default: { x: group.scale.x, y: group.scale.y, z: group.scale.z },
|
|
@@ -2406,7 +2615,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2406
2615
|
world = { ...world, ...newWorldItems };
|
|
2407
2616
|
animatables = { ...animatables, ...newAnimatables };
|
|
2408
2617
|
children.push(childId);
|
|
2409
|
-
} else if (child
|
|
2618
|
+
} else if (shouldImportAsGroupChild2(child)) {
|
|
2410
2619
|
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child, namespaces, {
|
|
2411
2620
|
...colorLookup,
|
|
2412
2621
|
...newColorLookup
|
|
@@ -2435,6 +2644,24 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2435
2644
|
world = { ...world, [newGroup.id]: newGroup };
|
|
2436
2645
|
return [world, animatables, newGroup.id, newColorLookup];
|
|
2437
2646
|
}
|
|
2647
|
+
function shouldImportAsGroupChild2(child) {
|
|
2648
|
+
if (!child.isObject3D) {
|
|
2649
|
+
return false;
|
|
2650
|
+
}
|
|
2651
|
+
if (child.isMesh) {
|
|
2652
|
+
return false;
|
|
2653
|
+
}
|
|
2654
|
+
if (child.isCamera) {
|
|
2655
|
+
return false;
|
|
2656
|
+
}
|
|
2657
|
+
if (child.isLight) {
|
|
2658
|
+
return false;
|
|
2659
|
+
}
|
|
2660
|
+
if (child.isBone) {
|
|
2661
|
+
return false;
|
|
2662
|
+
}
|
|
2663
|
+
return true;
|
|
2664
|
+
}
|
|
2438
2665
|
|
|
2439
2666
|
// src/functions/gltf-loading/import-scene.ts
|
|
2440
2667
|
import_three5.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
@@ -2560,7 +2787,10 @@ var MATERIAL_NAME_FEATURE_KEYS = [
|
|
|
2560
2787
|
"opacity",
|
|
2561
2788
|
"roughness",
|
|
2562
2789
|
"metalness",
|
|
2563
|
-
"shininess"
|
|
2790
|
+
"shininess",
|
|
2791
|
+
"emissive",
|
|
2792
|
+
"emissiveIntensity",
|
|
2793
|
+
"specular"
|
|
2564
2794
|
];
|
|
2565
2795
|
var MATERIAL_NAME_SUFFIXES2 = [
|
|
2566
2796
|
" color",
|
|
@@ -2569,7 +2799,10 @@ var MATERIAL_NAME_SUFFIXES2 = [
|
|
|
2569
2799
|
" opacity",
|
|
2570
2800
|
" roughness",
|
|
2571
2801
|
" metalness",
|
|
2572
|
-
" shininess"
|
|
2802
|
+
" shininess",
|
|
2803
|
+
" emissive intensity",
|
|
2804
|
+
" emissive",
|
|
2805
|
+
" specular"
|
|
2573
2806
|
];
|
|
2574
2807
|
function applyStoredRenderableNames(object, data) {
|
|
2575
2808
|
if (typeof data.name === "string" && data.name.length > 0) {
|
|
@@ -2708,10 +2941,10 @@ function deriveRootBounds(group) {
|
|
|
2708
2941
|
}
|
|
2709
2942
|
|
|
2710
2943
|
// src/functions/vizij-bundle.ts
|
|
2711
|
-
var
|
|
2944
|
+
var import_utils12 = require("@vizij/utils");
|
|
2712
2945
|
var BUNDLE_KEYS = ["VIZIJ_bundle"];
|
|
2713
2946
|
function cloneBundle(value) {
|
|
2714
|
-
return (0,
|
|
2947
|
+
return (0, import_utils12.cloneDeepSafe)(value);
|
|
2715
2948
|
}
|
|
2716
2949
|
function readExtensionValue(extensionContainer) {
|
|
2717
2950
|
for (const key of BUNDLE_KEYS) {
|
|
@@ -2745,6 +2978,13 @@ function searchParserJsonForBundle(parserJson) {
|
|
|
2745
2978
|
if (!parserJson || typeof parserJson !== "object") {
|
|
2746
2979
|
return null;
|
|
2747
2980
|
}
|
|
2981
|
+
const rootExtensions = parserJson && typeof parserJson === "object" ? parserJson.extensions : null;
|
|
2982
|
+
if (rootExtensions && typeof rootExtensions === "object") {
|
|
2983
|
+
const match = readExtensionValue(rootExtensions);
|
|
2984
|
+
if (match) {
|
|
2985
|
+
return cloneBundle(match.value);
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2748
2988
|
const nodes = Array.isArray(parserJson.nodes) ? parserJson.nodes : [];
|
|
2749
2989
|
for (const node of nodes) {
|
|
2750
2990
|
const extensions = node && typeof node === "object" ? node.extensions : null;
|
|
@@ -2782,12 +3022,29 @@ function applyVizijBundle(object, bundle) {
|
|
|
2782
3022
|
const userData = object.userData && typeof object.userData === "object" ? object.userData : {};
|
|
2783
3023
|
const originalExtensions = userData.gltfExtensions;
|
|
2784
3024
|
let applied = false;
|
|
3025
|
+
const staleCarriers = [];
|
|
2785
3026
|
if (bundle) {
|
|
2786
3027
|
userData.gltfExtensions = {
|
|
2787
3028
|
...originalExtensions ?? {},
|
|
2788
3029
|
VIZIJ_bundle: bundle
|
|
2789
3030
|
};
|
|
2790
3031
|
object.userData = userData;
|
|
3032
|
+
object.traverse((node) => {
|
|
3033
|
+
if (node === object) {
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
const extensions = node.userData?.gltfExtensions;
|
|
3037
|
+
if (!extensions || !(BUNDLE_KEYS[0] in extensions)) {
|
|
3038
|
+
return;
|
|
3039
|
+
}
|
|
3040
|
+
staleCarriers.push({ node, extensions });
|
|
3041
|
+
const { [BUNDLE_KEYS[0]]: _stale, ...rest } = extensions;
|
|
3042
|
+
if (Object.keys(rest).length > 0) {
|
|
3043
|
+
node.userData.gltfExtensions = rest;
|
|
3044
|
+
} else {
|
|
3045
|
+
delete node.userData.gltfExtensions;
|
|
3046
|
+
}
|
|
3047
|
+
});
|
|
2791
3048
|
applied = true;
|
|
2792
3049
|
}
|
|
2793
3050
|
return () => {
|
|
@@ -2804,12 +3061,16 @@ function applyVizijBundle(object, bundle) {
|
|
|
2804
3061
|
delete object.userData;
|
|
2805
3062
|
}
|
|
2806
3063
|
}
|
|
3064
|
+
for (const { node, extensions } of staleCarriers) {
|
|
3065
|
+
node.userData.gltfExtensions = extensions;
|
|
3066
|
+
}
|
|
3067
|
+
staleCarriers.length = 0;
|
|
2807
3068
|
applied = false;
|
|
2808
3069
|
};
|
|
2809
3070
|
}
|
|
2810
3071
|
|
|
2811
3072
|
// src/functions/gltf-loading/extract-animations.ts
|
|
2812
|
-
var
|
|
3073
|
+
var import_utils13 = require("@vizij/utils");
|
|
2813
3074
|
var CHANNEL_PATH_TO_TRACK_PROPERTY = {
|
|
2814
3075
|
translation: "position",
|
|
2815
3076
|
rotation: "quaternion",
|
|
@@ -2825,7 +3086,7 @@ function clonePlainObject(value) {
|
|
|
2825
3086
|
if (!value) {
|
|
2826
3087
|
return void 0;
|
|
2827
3088
|
}
|
|
2828
|
-
return (0,
|
|
3089
|
+
return (0, import_utils13.cloneDeepSafe)(value);
|
|
2829
3090
|
}
|
|
2830
3091
|
function inferValueSize(valueType) {
|
|
2831
3092
|
switch (valueType) {
|
|
@@ -3180,24 +3441,87 @@ function extractVizijAnimations(parserJson, clips) {
|
|
|
3180
3441
|
|
|
3181
3442
|
// src/functions/load-gltf.ts
|
|
3182
3443
|
THREE5.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
3444
|
+
var GLB_MAGIC = 1179937895;
|
|
3445
|
+
var GLB_VERSION = 2;
|
|
3446
|
+
var GLB_HEADER_BYTES = 12;
|
|
3447
|
+
var GLB_CHUNK_HEADER_BYTES = 8;
|
|
3448
|
+
var GLB_JSON_CHUNK_TYPE = 1313821514;
|
|
3183
3449
|
var EmptyModelError = class extends Error {
|
|
3184
3450
|
constructor(message) {
|
|
3185
3451
|
super(message);
|
|
3186
3452
|
this.name = "EmptyModelError";
|
|
3187
3453
|
}
|
|
3188
3454
|
};
|
|
3455
|
+
function parseGlbJsonChunk(buffer) {
|
|
3456
|
+
if (buffer.byteLength < GLB_HEADER_BYTES + GLB_CHUNK_HEADER_BYTES) {
|
|
3457
|
+
return void 0;
|
|
3458
|
+
}
|
|
3459
|
+
const view = new DataView(buffer);
|
|
3460
|
+
const magic = view.getUint32(0, true);
|
|
3461
|
+
const version = view.getUint32(4, true);
|
|
3462
|
+
if (magic !== GLB_MAGIC || version !== GLB_VERSION) {
|
|
3463
|
+
return void 0;
|
|
3464
|
+
}
|
|
3465
|
+
const chunkLength = view.getUint32(GLB_HEADER_BYTES, true);
|
|
3466
|
+
const chunkType = view.getUint32(GLB_HEADER_BYTES + 4, true);
|
|
3467
|
+
if (chunkType !== GLB_JSON_CHUNK_TYPE) {
|
|
3468
|
+
return void 0;
|
|
3469
|
+
}
|
|
3470
|
+
const chunkStart = GLB_HEADER_BYTES + GLB_CHUNK_HEADER_BYTES;
|
|
3471
|
+
const chunkEnd = chunkStart + chunkLength;
|
|
3472
|
+
if (chunkEnd > buffer.byteLength) {
|
|
3473
|
+
return void 0;
|
|
3474
|
+
}
|
|
3475
|
+
try {
|
|
3476
|
+
const chunkBytes = new Uint8Array(buffer, chunkStart, chunkLength);
|
|
3477
|
+
const jsonText = new TextDecoder().decode(chunkBytes);
|
|
3478
|
+
return JSON.parse(jsonText);
|
|
3479
|
+
} catch {
|
|
3480
|
+
return void 0;
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
async function resolveParserJson(parserJson, fallback) {
|
|
3484
|
+
if (parserJson && typeof parserJson === "object") {
|
|
3485
|
+
return parserJson;
|
|
3486
|
+
}
|
|
3487
|
+
if (fallback.arrayBuffer) {
|
|
3488
|
+
const fromArrayBuffer = parseGlbJsonChunk(fallback.arrayBuffer);
|
|
3489
|
+
if (fromArrayBuffer && typeof fromArrayBuffer === "object") {
|
|
3490
|
+
return fromArrayBuffer;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
if (fallback.blob) {
|
|
3494
|
+
try {
|
|
3495
|
+
const blobBuffer = typeof fallback.blob.arrayBuffer === "function" ? await fallback.blob.arrayBuffer() : await new Response(fallback.blob).arrayBuffer();
|
|
3496
|
+
const fromBlob = parseGlbJsonChunk(blobBuffer);
|
|
3497
|
+
if (fromBlob && typeof fromBlob === "object") {
|
|
3498
|
+
return fromBlob;
|
|
3499
|
+
}
|
|
3500
|
+
} catch {
|
|
3501
|
+
}
|
|
3502
|
+
}
|
|
3503
|
+
if (fallback.url && typeof fetch === "function") {
|
|
3504
|
+
try {
|
|
3505
|
+
const response = await fetch(fallback.url);
|
|
3506
|
+
if (response.ok) {
|
|
3507
|
+
const binary = await response.arrayBuffer();
|
|
3508
|
+
const fromUrl = parseGlbJsonChunk(binary);
|
|
3509
|
+
if (fromUrl && typeof fromUrl === "object") {
|
|
3510
|
+
return fromUrl;
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
} catch {
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
return parserJson;
|
|
3517
|
+
}
|
|
3189
3518
|
async function loadGLTF(url, namespaces, aggressiveImport = false, rootBounds) {
|
|
3190
|
-
const
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3194
|
-
const asset = parseScene(
|
|
3195
|
-
modelData.scene,
|
|
3196
|
-
actualizedNamespaces,
|
|
3519
|
+
const asset = await loadGLTFWithBundleInternal(
|
|
3520
|
+
url,
|
|
3521
|
+
namespaces,
|
|
3197
3522
|
aggressiveImport,
|
|
3198
3523
|
rootBounds,
|
|
3199
|
-
|
|
3200
|
-
modelData.animations
|
|
3524
|
+
"url"
|
|
3201
3525
|
);
|
|
3202
3526
|
return [asset.world, asset.animatables, asset.animations];
|
|
3203
3527
|
}
|
|
@@ -3206,11 +3530,13 @@ async function loadGLTFFromBlob(blob, namespaces, aggressiveImport = false, root
|
|
|
3206
3530
|
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
3207
3531
|
const objectUrl = URL.createObjectURL(blob);
|
|
3208
3532
|
try {
|
|
3209
|
-
const asset = await
|
|
3533
|
+
const asset = await loadGLTFWithBundleInternal(
|
|
3210
3534
|
objectUrl,
|
|
3211
3535
|
actualizedNamespaces,
|
|
3212
3536
|
aggressiveImport,
|
|
3213
|
-
rootBounds
|
|
3537
|
+
rootBounds,
|
|
3538
|
+
"blob",
|
|
3539
|
+
{ blob }
|
|
3214
3540
|
);
|
|
3215
3541
|
return [asset.world, asset.animatables, asset.animations];
|
|
3216
3542
|
} finally {
|
|
@@ -3219,19 +3545,22 @@ async function loadGLTFFromBlob(blob, namespaces, aggressiveImport = false, root
|
|
|
3219
3545
|
}
|
|
3220
3546
|
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
3221
3547
|
return new Promise((resolve, reject) => {
|
|
3222
|
-
const loader =
|
|
3223
|
-
loader.setDRACOLoader(new import_three_stdlib.DRACOLoader());
|
|
3548
|
+
const loader = createTrackedGLTFLoader();
|
|
3224
3549
|
loader.parse(
|
|
3225
3550
|
arrayBuffer,
|
|
3226
3551
|
"",
|
|
3227
|
-
(gltf) => {
|
|
3552
|
+
async (gltf) => {
|
|
3228
3553
|
try {
|
|
3554
|
+
const parserJson = await resolveParserJson(
|
|
3555
|
+
gltf?.parser?.json,
|
|
3556
|
+
{ arrayBuffer }
|
|
3557
|
+
);
|
|
3229
3558
|
const asset = parseScene(
|
|
3230
3559
|
gltf.scene,
|
|
3231
3560
|
actualizedNamespaces,
|
|
3232
3561
|
aggressiveImport,
|
|
3233
3562
|
rootBounds,
|
|
3234
|
-
|
|
3563
|
+
parserJson,
|
|
3235
3564
|
gltf.animations
|
|
3236
3565
|
);
|
|
3237
3566
|
resolve([asset.world, asset.animatables, asset.animations]);
|
|
@@ -3258,32 +3587,59 @@ function parseScene(scene, namespaces, aggressiveImport, rootBounds, parserJson,
|
|
|
3258
3587
|
);
|
|
3259
3588
|
const bundle = extractVizijBundle(scene, parserJson);
|
|
3260
3589
|
const animations = extractVizijAnimations(parserJson, clips);
|
|
3261
|
-
return { world, animatables, bundle, animations };
|
|
3590
|
+
return { world, animatables, bundle, animations, scene };
|
|
3262
3591
|
}
|
|
3263
|
-
|
|
3592
|
+
function createTrackedGLTFLoader() {
|
|
3593
|
+
recordRenderCounter("gltfLoadCount");
|
|
3594
|
+
recordRenderCounter("dracoLoaderCreationCount");
|
|
3264
3595
|
const modelLoader = new import_three_stdlib.GLTFLoader();
|
|
3265
3596
|
modelLoader.setDRACOLoader(new import_three_stdlib.DRACOLoader());
|
|
3597
|
+
return modelLoader;
|
|
3598
|
+
}
|
|
3599
|
+
async function loadGLTFWithBundleInternal(url, namespaces, aggressiveImport = false, rootBounds, sourceKind = "url", parserJsonFallback) {
|
|
3600
|
+
if (sourceKind === "url") {
|
|
3601
|
+
recordRenderCounter("gltfUrlLoadCount");
|
|
3602
|
+
} else {
|
|
3603
|
+
recordRenderCounter("gltfBlobLoadCount");
|
|
3604
|
+
}
|
|
3605
|
+
const modelLoader = createTrackedGLTFLoader();
|
|
3266
3606
|
const modelData = await modelLoader.loadAsync(url);
|
|
3607
|
+
const parserJson = await resolveParserJson(modelData?.parser?.json, {
|
|
3608
|
+
url,
|
|
3609
|
+
...parserJsonFallback
|
|
3610
|
+
});
|
|
3267
3611
|
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3268
3612
|
return parseScene(
|
|
3269
3613
|
modelData.scene,
|
|
3270
3614
|
actualizedNamespaces,
|
|
3271
3615
|
aggressiveImport,
|
|
3272
3616
|
rootBounds,
|
|
3273
|
-
|
|
3617
|
+
parserJson,
|
|
3274
3618
|
modelData.animations
|
|
3275
3619
|
);
|
|
3276
3620
|
}
|
|
3621
|
+
async function loadGLTFWithBundle(url, namespaces, aggressiveImport = false, rootBounds, parserJsonFallback) {
|
|
3622
|
+
return loadGLTFWithBundleInternal(
|
|
3623
|
+
url,
|
|
3624
|
+
namespaces,
|
|
3625
|
+
aggressiveImport,
|
|
3626
|
+
rootBounds,
|
|
3627
|
+
"url",
|
|
3628
|
+
parserJsonFallback
|
|
3629
|
+
);
|
|
3630
|
+
}
|
|
3277
3631
|
async function loadGLTFFromBlobWithBundle(blob, namespaces, aggressiveImport = false, rootBounds) {
|
|
3278
3632
|
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3279
3633
|
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
3280
3634
|
const objectUrl = URL.createObjectURL(blob);
|
|
3281
3635
|
try {
|
|
3282
|
-
return await
|
|
3636
|
+
return await loadGLTFWithBundleInternal(
|
|
3283
3637
|
objectUrl,
|
|
3284
3638
|
actualizedNamespaces,
|
|
3285
3639
|
aggressiveImport,
|
|
3286
|
-
rootBounds
|
|
3640
|
+
rootBounds,
|
|
3641
|
+
"blob",
|
|
3642
|
+
{ blob }
|
|
3287
3643
|
);
|
|
3288
3644
|
} finally {
|
|
3289
3645
|
URL.revokeObjectURL(objectUrl);
|
|
@@ -3291,19 +3647,22 @@ async function loadGLTFFromBlobWithBundle(blob, namespaces, aggressiveImport = f
|
|
|
3291
3647
|
}
|
|
3292
3648
|
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
3293
3649
|
return new Promise((resolve, reject) => {
|
|
3294
|
-
const loader =
|
|
3295
|
-
loader.setDRACOLoader(new import_three_stdlib.DRACOLoader());
|
|
3650
|
+
const loader = createTrackedGLTFLoader();
|
|
3296
3651
|
loader.parse(
|
|
3297
3652
|
arrayBuffer,
|
|
3298
3653
|
"",
|
|
3299
|
-
(gltf) => {
|
|
3654
|
+
async (gltf) => {
|
|
3300
3655
|
try {
|
|
3656
|
+
const parserJson = await resolveParserJson(
|
|
3657
|
+
gltf?.parser?.json,
|
|
3658
|
+
{ arrayBuffer }
|
|
3659
|
+
);
|
|
3301
3660
|
const asset = parseScene(
|
|
3302
3661
|
gltf.scene,
|
|
3303
3662
|
actualizedNamespaces,
|
|
3304
3663
|
aggressiveImport,
|
|
3305
3664
|
rootBounds,
|
|
3306
|
-
|
|
3665
|
+
parserJson,
|
|
3307
3666
|
gltf.animations
|
|
3308
3667
|
);
|
|
3309
3668
|
resolve(asset);
|
|
@@ -3325,6 +3684,9 @@ async function loadGLTFFromBlobWithBundle(blob, namespaces, aggressiveImport = f
|
|
|
3325
3684
|
// src/functions/load-gltf-blob.ts
|
|
3326
3685
|
var import_three_stdlib2 = require("three-stdlib");
|
|
3327
3686
|
var loadGltfFromBlob = (blob, namespaces) => {
|
|
3687
|
+
recordRenderCounter("gltfLoadCount");
|
|
3688
|
+
recordRenderCounter("gltfBlobLoadCount");
|
|
3689
|
+
recordRenderCounter("dracoLoaderCreationCount");
|
|
3328
3690
|
return new Promise((resolve, reject) => {
|
|
3329
3691
|
const loader = new import_three_stdlib2.GLTFLoader();
|
|
3330
3692
|
loader.setDRACOLoader(new import_three_stdlib2.DRACOLoader());
|
|
@@ -3355,6 +3717,160 @@ var loadGltfFromBlob = (blob, namespaces) => {
|
|
|
3355
3717
|
var import_three_stdlib3 = require("three-stdlib");
|
|
3356
3718
|
var THREE6 = __toESM(require("three"));
|
|
3357
3719
|
THREE6.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
3720
|
+
function normalizeExportError(error) {
|
|
3721
|
+
if (error instanceof Error) {
|
|
3722
|
+
return error;
|
|
3723
|
+
}
|
|
3724
|
+
if (typeof error === "string") {
|
|
3725
|
+
return new Error(error);
|
|
3726
|
+
}
|
|
3727
|
+
return new Error("Failed to export scene.");
|
|
3728
|
+
}
|
|
3729
|
+
function triggerBlobDownload(blob, filename) {
|
|
3730
|
+
const url = URL.createObjectURL(blob);
|
|
3731
|
+
const link = document.createElement("a");
|
|
3732
|
+
link.href = url;
|
|
3733
|
+
link.download = filename;
|
|
3734
|
+
link.style.display = "none";
|
|
3735
|
+
document.body.appendChild(link);
|
|
3736
|
+
link.click();
|
|
3737
|
+
document.body.removeChild(link);
|
|
3738
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
3739
|
+
}
|
|
3740
|
+
var GLB_MAGIC2 = 1179937895;
|
|
3741
|
+
var GLB_VERSION2 = 2;
|
|
3742
|
+
var GLB_JSON_CHUNK_TYPE2 = 1313821514;
|
|
3743
|
+
var GLB_HEADER_BYTES2 = 12;
|
|
3744
|
+
var GLB_CHUNK_HEADER_BYTES2 = 8;
|
|
3745
|
+
var GLB_JSON_PADDING_BYTE = 32;
|
|
3746
|
+
function isNearlyEqual(a, b, epsilon = 1e-6) {
|
|
3747
|
+
return Math.abs(a - b) <= epsilon;
|
|
3748
|
+
}
|
|
3749
|
+
function isIdentityTransformNode(node) {
|
|
3750
|
+
const translation = node.translation;
|
|
3751
|
+
if (Array.isArray(translation) && (translation.length !== 3 || !isNearlyEqual(Number(translation[0]), 0) || !isNearlyEqual(Number(translation[1]), 0) || !isNearlyEqual(Number(translation[2]), 0))) {
|
|
3752
|
+
return false;
|
|
3753
|
+
}
|
|
3754
|
+
const rotation = node.rotation;
|
|
3755
|
+
if (Array.isArray(rotation) && (rotation.length !== 4 || !isNearlyEqual(Number(rotation[0]), 0) || !isNearlyEqual(Number(rotation[1]), 0) || !isNearlyEqual(Number(rotation[2]), 0) || !isNearlyEqual(Number(rotation[3]), 1))) {
|
|
3756
|
+
return false;
|
|
3757
|
+
}
|
|
3758
|
+
const scale = node.scale;
|
|
3759
|
+
if (Array.isArray(scale) && (scale.length !== 3 || !isNearlyEqual(Number(scale[0]), 1) || !isNearlyEqual(Number(scale[1]), 1) || !isNearlyEqual(Number(scale[2]), 1))) {
|
|
3760
|
+
return false;
|
|
3761
|
+
}
|
|
3762
|
+
return true;
|
|
3763
|
+
}
|
|
3764
|
+
function isPassThroughWrapperNode(node) {
|
|
3765
|
+
if (!node || typeof node !== "object") {
|
|
3766
|
+
return false;
|
|
3767
|
+
}
|
|
3768
|
+
if (!Array.isArray(node.children) || node.children.length === 0) {
|
|
3769
|
+
return false;
|
|
3770
|
+
}
|
|
3771
|
+
const hasOnlyNumericChildren = node.children.every(
|
|
3772
|
+
(index) => Number.isInteger(index)
|
|
3773
|
+
);
|
|
3774
|
+
if (!hasOnlyNumericChildren) {
|
|
3775
|
+
return false;
|
|
3776
|
+
}
|
|
3777
|
+
if (node.mesh !== void 0 || node.camera !== void 0 || node.skin !== void 0) {
|
|
3778
|
+
return false;
|
|
3779
|
+
}
|
|
3780
|
+
if (node.extensions && typeof node.extensions === "object" && Object.keys(node.extensions).length > 0) {
|
|
3781
|
+
return false;
|
|
3782
|
+
}
|
|
3783
|
+
return isIdentityTransformNode(node);
|
|
3784
|
+
}
|
|
3785
|
+
function normalizeExportedSceneJson(json, fallbackSceneName) {
|
|
3786
|
+
if (!json || typeof json !== "object") {
|
|
3787
|
+
return false;
|
|
3788
|
+
}
|
|
3789
|
+
if (!Array.isArray(json.scenes) || !Array.isArray(json.nodes)) {
|
|
3790
|
+
return false;
|
|
3791
|
+
}
|
|
3792
|
+
const sceneIndexRaw = json.scene;
|
|
3793
|
+
const sceneIndex = typeof sceneIndexRaw === "number" && Number.isInteger(sceneIndexRaw) ? sceneIndexRaw : 0;
|
|
3794
|
+
const sceneDef = json.scenes[sceneIndex];
|
|
3795
|
+
if (!sceneDef || typeof sceneDef !== "object") {
|
|
3796
|
+
return false;
|
|
3797
|
+
}
|
|
3798
|
+
let changed = false;
|
|
3799
|
+
let wrapperNodeName;
|
|
3800
|
+
if (Array.isArray(sceneDef.nodes) && sceneDef.nodes.length === 1) {
|
|
3801
|
+
const wrapperIndex = sceneDef.nodes[0];
|
|
3802
|
+
if (Number.isInteger(wrapperIndex)) {
|
|
3803
|
+
const wrapperNode = json.nodes[wrapperIndex];
|
|
3804
|
+
if (isPassThroughWrapperNode(wrapperNode)) {
|
|
3805
|
+
sceneDef.nodes = [...wrapperNode.children];
|
|
3806
|
+
wrapperNodeName = typeof wrapperNode.name === "string" ? wrapperNode.name : void 0;
|
|
3807
|
+
changed = true;
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
const currentSceneName = typeof sceneDef.name === "string" ? sceneDef.name.trim() : "";
|
|
3812
|
+
if (currentSceneName === "AuxScene") {
|
|
3813
|
+
const nextSceneName = (wrapperNodeName?.trim() || fallbackSceneName?.trim() || "Scene").trim();
|
|
3814
|
+
if (nextSceneName.length > 0 && nextSceneName !== currentSceneName) {
|
|
3815
|
+
sceneDef.name = nextSceneName;
|
|
3816
|
+
changed = true;
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
return changed;
|
|
3820
|
+
}
|
|
3821
|
+
function sanitizeExportedGlb(buffer, fallbackSceneName) {
|
|
3822
|
+
if (buffer.byteLength < GLB_HEADER_BYTES2 + GLB_CHUNK_HEADER_BYTES2) {
|
|
3823
|
+
return buffer;
|
|
3824
|
+
}
|
|
3825
|
+
const originalBytes = new Uint8Array(buffer);
|
|
3826
|
+
const view = new DataView(buffer);
|
|
3827
|
+
const magic = view.getUint32(0, true);
|
|
3828
|
+
const version = view.getUint32(4, true);
|
|
3829
|
+
if (magic !== GLB_MAGIC2 || version !== GLB_VERSION2) {
|
|
3830
|
+
return buffer;
|
|
3831
|
+
}
|
|
3832
|
+
const jsonChunkLength = view.getUint32(GLB_HEADER_BYTES2, true);
|
|
3833
|
+
const jsonChunkType = view.getUint32(GLB_HEADER_BYTES2 + 4, true);
|
|
3834
|
+
if (jsonChunkType !== GLB_JSON_CHUNK_TYPE2) {
|
|
3835
|
+
return buffer;
|
|
3836
|
+
}
|
|
3837
|
+
const jsonChunkStart = GLB_HEADER_BYTES2 + GLB_CHUNK_HEADER_BYTES2;
|
|
3838
|
+
const jsonChunkEnd = jsonChunkStart + jsonChunkLength;
|
|
3839
|
+
if (jsonChunkEnd > originalBytes.length) {
|
|
3840
|
+
return buffer;
|
|
3841
|
+
}
|
|
3842
|
+
let jsonPayload;
|
|
3843
|
+
try {
|
|
3844
|
+
const jsonText = new TextDecoder().decode(
|
|
3845
|
+
originalBytes.slice(jsonChunkStart, jsonChunkEnd)
|
|
3846
|
+
);
|
|
3847
|
+
jsonPayload = JSON.parse(jsonText);
|
|
3848
|
+
} catch {
|
|
3849
|
+
return buffer;
|
|
3850
|
+
}
|
|
3851
|
+
const changed = normalizeExportedSceneJson(jsonPayload, fallbackSceneName);
|
|
3852
|
+
if (!changed) {
|
|
3853
|
+
return buffer;
|
|
3854
|
+
}
|
|
3855
|
+
const encodedJson = new TextEncoder().encode(JSON.stringify(jsonPayload));
|
|
3856
|
+
const paddedJsonLength = encodedJson.length + 3 & ~3;
|
|
3857
|
+
const paddedJson = new Uint8Array(paddedJsonLength);
|
|
3858
|
+
paddedJson.fill(GLB_JSON_PADDING_BYTE);
|
|
3859
|
+
paddedJson.set(encodedJson);
|
|
3860
|
+
const remainingChunks = originalBytes.slice(jsonChunkEnd);
|
|
3861
|
+
const totalLength = GLB_HEADER_BYTES2 + GLB_CHUNK_HEADER_BYTES2 + paddedJsonLength + remainingChunks.length;
|
|
3862
|
+
const sanitized = new ArrayBuffer(totalLength);
|
|
3863
|
+
const sanitizedBytes = new Uint8Array(sanitized);
|
|
3864
|
+
const sanitizedView = new DataView(sanitized);
|
|
3865
|
+
sanitizedView.setUint32(0, GLB_MAGIC2, true);
|
|
3866
|
+
sanitizedView.setUint32(4, GLB_VERSION2, true);
|
|
3867
|
+
sanitizedView.setUint32(8, totalLength, true);
|
|
3868
|
+
sanitizedView.setUint32(GLB_HEADER_BYTES2, paddedJsonLength, true);
|
|
3869
|
+
sanitizedView.setUint32(GLB_HEADER_BYTES2 + 4, GLB_JSON_CHUNK_TYPE2, true);
|
|
3870
|
+
sanitizedBytes.set(paddedJson, jsonChunkStart);
|
|
3871
|
+
sanitizedBytes.set(remainingChunks, jsonChunkStart + paddedJsonLength);
|
|
3872
|
+
return sanitized;
|
|
3873
|
+
}
|
|
3358
3874
|
function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
3359
3875
|
const options = typeof fileNameOrOptions === "string" ? { fileName: fileNameOrOptions } : fileNameOrOptions ?? {};
|
|
3360
3876
|
const fileName = options.fileName ?? "scene.glb";
|
|
@@ -3369,7 +3885,15 @@ function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
|
3369
3885
|
}
|
|
3370
3886
|
}
|
|
3371
3887
|
}));
|
|
3372
|
-
const
|
|
3888
|
+
const sourceRoot = data;
|
|
3889
|
+
const exportRoot = sourceRoot instanceof THREE6.Scene ? sourceRoot : sourceRoot.clone(true);
|
|
3890
|
+
const exportTarget = exportRoot instanceof THREE6.Scene ? exportRoot : (() => {
|
|
3891
|
+
const scene = new THREE6.Scene();
|
|
3892
|
+
scene.name = data.name?.trim() || "Scene";
|
|
3893
|
+
scene.add(exportRoot);
|
|
3894
|
+
return scene;
|
|
3895
|
+
})();
|
|
3896
|
+
const detachBundle = shouldAttachBundle && options.bundle ? applyVizijBundle(exportRoot, options.bundle) : () => {
|
|
3373
3897
|
};
|
|
3374
3898
|
const binary = options.binary ?? true;
|
|
3375
3899
|
const exporterOptions = {
|
|
@@ -3383,33 +3907,40 @@ function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
|
3383
3907
|
}
|
|
3384
3908
|
try {
|
|
3385
3909
|
exporter.parse(
|
|
3386
|
-
|
|
3910
|
+
exportTarget,
|
|
3387
3911
|
(gltf) => {
|
|
3388
3912
|
detachBundle();
|
|
3389
3913
|
if (!(gltf instanceof ArrayBuffer)) {
|
|
3390
|
-
|
|
3914
|
+
const error = new Error("Failed to export scene.");
|
|
3915
|
+
options.onError?.(error);
|
|
3916
|
+
return;
|
|
3391
3917
|
}
|
|
3392
|
-
const
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
type: "application/octet-stream"
|
|
3396
|
-
})
|
|
3918
|
+
const sanitizedGltf = sanitizeExportedGlb(
|
|
3919
|
+
gltf,
|
|
3920
|
+
data.name?.trim() || void 0
|
|
3397
3921
|
);
|
|
3398
3922
|
const trimmed = fileName.trim();
|
|
3399
3923
|
const safeFileName = trimmed.length > 0 ? trimmed : "scene.glb";
|
|
3400
3924
|
const downloadName = safeFileName.toLowerCase().endsWith(".glb") ? safeFileName : `${safeFileName}.glb`;
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3925
|
+
triggerBlobDownload(
|
|
3926
|
+
new Blob([sanitizedGltf], {
|
|
3927
|
+
type: "application/octet-stream"
|
|
3928
|
+
}),
|
|
3929
|
+
downloadName
|
|
3930
|
+
);
|
|
3931
|
+
options.onComplete?.();
|
|
3404
3932
|
},
|
|
3405
|
-
() => {
|
|
3933
|
+
(error) => {
|
|
3406
3934
|
detachBundle();
|
|
3935
|
+
options.onError?.(normalizeExportError(error));
|
|
3407
3936
|
},
|
|
3408
3937
|
exporterOptions
|
|
3409
3938
|
);
|
|
3410
3939
|
} catch (error) {
|
|
3411
3940
|
detachBundle();
|
|
3412
|
-
|
|
3941
|
+
const normalizedError = normalizeExportError(error);
|
|
3942
|
+
options.onError?.(normalizedError);
|
|
3943
|
+
throw normalizedError;
|
|
3413
3944
|
}
|
|
3414
3945
|
}
|
|
3415
3946
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -3429,6 +3960,7 @@ function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
|
3429
3960
|
loadGLTFFromBlobWithBundle,
|
|
3430
3961
|
loadGLTFWithBundle,
|
|
3431
3962
|
loadGltfFromBlob,
|
|
3963
|
+
parseGlbJsonChunk,
|
|
3432
3964
|
useDefaultVizijStore,
|
|
3433
3965
|
useFeatures,
|
|
3434
3966
|
useVizijStore,
|