@aura3d/assets 2.0.3 → 3.0.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/GLTFAnimationRuntime.d.ts +95 -2
- package/dist/GLTFAnimationRuntime.d.ts.map +1 -1
- package/dist/GLTFAnimationRuntime.js +328 -3
- package/dist/GLTFAnimationRuntime.js.map +1 -1
- package/dist/GLTFExtensionSupport.js +2 -2
- package/dist/GLTFExtensionSupport.js.map +1 -1
- package/dist/GLTFLoader.d.ts +360 -1
- package/dist/GLTFLoader.d.ts.map +1 -1
- package/dist/GLTFLoader.js +197 -1
- package/dist/GLTFLoader.js.map +1 -1
- package/dist/KTX2BasisTextureTranscoder.d.ts +39 -0
- package/dist/KTX2BasisTextureTranscoder.d.ts.map +1 -1
- package/dist/KTX2BasisTextureTranscoder.js +70 -0
- package/dist/KTX2BasisTextureTranscoder.js.map +1 -1
- package/dist/TexturePipeline.d.ts +20 -0
- package/dist/TexturePipeline.d.ts.map +1 -1
- package/dist/TexturePipeline.js +20 -0
- package/dist/TexturePipeline.js.map +1 -1
- package/dist/TextureStreaming.d.ts +30 -0
- package/dist/TextureStreaming.d.ts.map +1 -1
- package/dist/TextureStreaming.js +53 -0
- package/dist/TextureStreaming.js.map +1 -1
- package/dist/browser-index.d.ts +7 -3
- package/dist/browser-index.d.ts.map +1 -1
- package/dist/browser-index.js +3 -1
- package/dist/browser-index.js.map +1 -1
- package/dist/gltf-runtime.d.ts +1 -1
- package/dist/gltf-runtime.d.ts.map +1 -1
- package/dist/gltf-runtime.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/loaders/HDRLoader.d.ts +40 -0
- package/dist/loaders/HDRLoader.d.ts.map +1 -1
- package/dist/loaders/HDRLoader.js +158 -0
- package/dist/loaders/HDRLoader.js.map +1 -1
- package/package.json +4 -4
package/dist/GLTFLoader.js
CHANGED
|
@@ -986,6 +986,40 @@ function resolveTextureInfo(textures, info, label) {
|
|
|
986
986
|
function usesGLTFExtension(json, extension) {
|
|
987
987
|
return Boolean(json.extensionsRequired?.includes(extension) || json.extensionsUsed?.includes(extension));
|
|
988
988
|
}
|
|
989
|
+
/**
|
|
990
|
+
* Save step: validate a variant switch against the loaded variant list and produce the
|
|
991
|
+
* persisted scene-state JSON value. Throws naming the variant when it is not defined —
|
|
992
|
+
* no silent no-ops.
|
|
993
|
+
*/
|
|
994
|
+
export function serializeMaterialVariantSelection(selectedVariant, materialVariants) {
|
|
995
|
+
if (selectedVariant !== undefined) {
|
|
996
|
+
validateSceneMaterialVariant(materialVariants, selectedVariant);
|
|
997
|
+
}
|
|
998
|
+
return selectedVariant === undefined
|
|
999
|
+
? { schemaVersion: "gltf-material-variant-state" }
|
|
1000
|
+
: { schemaVersion: "gltf-material-variant-state", selectedVariant };
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Reload step: parse persisted scene-state JSON back into a selection the loader's scene
|
|
1004
|
+
* options (`selectedVariant`) accept. Throws on schema mismatch or unknown variant names.
|
|
1005
|
+
*/
|
|
1006
|
+
export function parseMaterialVariantSelection(state, materialVariants) {
|
|
1007
|
+
if (typeof state !== "object" || state === null) {
|
|
1008
|
+
throw new Error("glTF material variant scene state must be an object.");
|
|
1009
|
+
}
|
|
1010
|
+
const record = state;
|
|
1011
|
+
if (record.schemaVersion !== "gltf-material-variant-state") {
|
|
1012
|
+
throw new Error("glTF material variant scene state has an unsupported schemaVersion.");
|
|
1013
|
+
}
|
|
1014
|
+
const selectedVariant = record.selectedVariant;
|
|
1015
|
+
if (selectedVariant === undefined)
|
|
1016
|
+
return undefined;
|
|
1017
|
+
if (typeof selectedVariant !== "string") {
|
|
1018
|
+
throw new Error("glTF material variant scene state selectedVariant must be a string.");
|
|
1019
|
+
}
|
|
1020
|
+
validateSceneMaterialVariant(materialVariants, selectedVariant);
|
|
1021
|
+
return selectedVariant;
|
|
1022
|
+
}
|
|
989
1023
|
function usesGLTFMeshoptExtension(json) {
|
|
990
1024
|
return GLTF_MESHOPT_EXTENSION_NAMES.some((extension) => usesGLTFExtension(json, extension));
|
|
991
1025
|
}
|
|
@@ -1574,7 +1608,22 @@ function createAnimationClips(json, buffers, accessorCache) {
|
|
|
1574
1608
|
throw new Error(`glTF animation ${animationIndex} channel ${channelIndex} references missing sampler ${channel.sampler}`);
|
|
1575
1609
|
}
|
|
1576
1610
|
if (isOptionalAnimationPointerChannel(json, channel)) {
|
|
1577
|
-
|
|
1611
|
+
const pointer = channel.target.extensions?.KHR_animation_pointer?.pointer ?? "";
|
|
1612
|
+
const resolved = resolveAnimationPointerBinding(json, pointer);
|
|
1613
|
+
if (!resolved) {
|
|
1614
|
+
// Unsupported pointer shape: preserve the previous diagnose-and-drop behavior
|
|
1615
|
+
// rather than failing the whole asset. Supported shapes are bound below.
|
|
1616
|
+
return [];
|
|
1617
|
+
}
|
|
1618
|
+
const interpolation = resolveAnimationInterpolation(sampler.interpolation, animationIndex, channelIndex);
|
|
1619
|
+
const times = readAccessor(json, buffers, sampler.input, accessorCache).map((row) => row[0] ?? 0);
|
|
1620
|
+
const output = readAccessor(json, buffers, sampler.output, accessorCache);
|
|
1621
|
+
const values = animationPointerKeyframesForSampler(resolved.valueType, times, output, interpolation, animationIndex, channelIndex);
|
|
1622
|
+
return [new AnimationTrack({
|
|
1623
|
+
target: resolved.target,
|
|
1624
|
+
valueType: resolved.valueType,
|
|
1625
|
+
keyframes: values
|
|
1626
|
+
})];
|
|
1578
1627
|
}
|
|
1579
1628
|
if (channel.target.node === undefined || !json.nodes?.[channel.target.node]) {
|
|
1580
1629
|
throw new Error(`glTF animation ${animationIndex} channel ${channelIndex} references missing target node ${channel.target.node ?? "undefined"}`);
|
|
@@ -1600,6 +1649,153 @@ function isOptionalAnimationPointerChannel(json, channel) {
|
|
|
1600
1649
|
json.extensionsRequired?.includes("KHR_animation_pointer") !== true &&
|
|
1601
1650
|
typeof channel.target.extensions?.KHR_animation_pointer?.pointer === "string";
|
|
1602
1651
|
}
|
|
1652
|
+
export function resolveAnimationPointerBinding(json, pointer) {
|
|
1653
|
+
const segments = pointer.split("/").filter((segment) => segment.length > 0);
|
|
1654
|
+
if (segments.length < 3)
|
|
1655
|
+
return undefined;
|
|
1656
|
+
// Full extension-object form first: it carries no bare index in segment 2.
|
|
1657
|
+
if (segments[0] === "extensions" && segments[1] === "KHR_lights_punctual" && segments[2] === "lights") {
|
|
1658
|
+
return resolvePunctualLightPointer(json, pointer, segments.slice(3));
|
|
1659
|
+
}
|
|
1660
|
+
const [root, indexRaw, ...rest] = segments;
|
|
1661
|
+
const index = Number(indexRaw);
|
|
1662
|
+
if (!Number.isInteger(index) || index < 0)
|
|
1663
|
+
return undefined;
|
|
1664
|
+
if (root === "nodes") {
|
|
1665
|
+
const node = json.nodes?.[index];
|
|
1666
|
+
if (!node)
|
|
1667
|
+
return undefined;
|
|
1668
|
+
const name = typeof node.name === "string" && node.name.trim().length > 0 ? node.name : `node-${index}`;
|
|
1669
|
+
const [leaf] = rest;
|
|
1670
|
+
if (leaf === "translation" || leaf === "scale") {
|
|
1671
|
+
return { pointer, target: `${name}.${leaf}`, valueType: "vector3" };
|
|
1672
|
+
}
|
|
1673
|
+
if (leaf === "rotation") {
|
|
1674
|
+
return { pointer, target: `${name}.${leaf}`, valueType: "quaternion" };
|
|
1675
|
+
}
|
|
1676
|
+
if (leaf === "weights" && rest.length === 1) {
|
|
1677
|
+
return { pointer, target: `${name}.weights`, valueType: "number-array" };
|
|
1678
|
+
}
|
|
1679
|
+
return undefined;
|
|
1680
|
+
}
|
|
1681
|
+
if (root === "meshes") {
|
|
1682
|
+
const mesh = json.meshes?.[index];
|
|
1683
|
+
if (!mesh)
|
|
1684
|
+
return undefined;
|
|
1685
|
+
const meshName = typeof mesh.name === "string" && (mesh.name?.trim().length ?? 0) > 0
|
|
1686
|
+
? mesh.name
|
|
1687
|
+
: `mesh-${index}`;
|
|
1688
|
+
if (rest.length === 1 && rest[0] === "weights") {
|
|
1689
|
+
return { pointer, target: `${meshName}.weights`, valueType: "number-array" };
|
|
1690
|
+
}
|
|
1691
|
+
return undefined;
|
|
1692
|
+
}
|
|
1693
|
+
if (root === "materials") {
|
|
1694
|
+
const material = json.materials?.[index];
|
|
1695
|
+
if (!material)
|
|
1696
|
+
return undefined;
|
|
1697
|
+
const materialName = typeof material.name === "string" && material.name.trim().length > 0 ? material.name : `material-${index}`;
|
|
1698
|
+
if (rest.length === 0)
|
|
1699
|
+
return undefined;
|
|
1700
|
+
const leaf = rest[rest.length - 1] ?? "";
|
|
1701
|
+
return { pointer, target: `material:${materialName}.${rest.join(".")}`, valueType: pointerLeafValueType(leaf) };
|
|
1702
|
+
}
|
|
1703
|
+
if (root === "lights") {
|
|
1704
|
+
return resolvePunctualLightPointer(json, pointer, segments.slice(1));
|
|
1705
|
+
}
|
|
1706
|
+
return undefined;
|
|
1707
|
+
}
|
|
1708
|
+
function resolvePunctualLightPointer(json, pointer, lightSegments) {
|
|
1709
|
+
const [lightIndexRaw, ...lightRest] = lightSegments;
|
|
1710
|
+
const lightIndex = Number(lightIndexRaw);
|
|
1711
|
+
if (!Number.isInteger(lightIndex) || lightIndex < 0 || lightRest.length === 0)
|
|
1712
|
+
return undefined;
|
|
1713
|
+
const light = json.extensions?.KHR_lights_punctual?.lights?.[lightIndex];
|
|
1714
|
+
if (!light)
|
|
1715
|
+
return undefined;
|
|
1716
|
+
const lightName = typeof light.name === "string" && light.name.trim().length > 0 ? light.name : `light-${lightIndex}`;
|
|
1717
|
+
const leaf = lightRest[lightRest.length - 1] ?? "";
|
|
1718
|
+
if (leaf !== "intensity" && leaf !== "color" && leaf !== "range")
|
|
1719
|
+
return undefined;
|
|
1720
|
+
return { pointer, target: `light:${lightName}.${lightRest.join(".")}`, valueType: leaf === "color" ? "vector3" : "scalar" };
|
|
1721
|
+
}
|
|
1722
|
+
const POINTER_SCALAR_LEAVES = new Set([
|
|
1723
|
+
"intensity",
|
|
1724
|
+
"range",
|
|
1725
|
+
"alphaCutoff",
|
|
1726
|
+
"metallicFactor",
|
|
1727
|
+
"roughnessFactor",
|
|
1728
|
+
"normalScale",
|
|
1729
|
+
"occlusionStrength",
|
|
1730
|
+
"emissiveStrength",
|
|
1731
|
+
"clearcoatFactor",
|
|
1732
|
+
"clearcoatRoughnessFactor",
|
|
1733
|
+
"transmissionFactor",
|
|
1734
|
+
"thicknessFactor",
|
|
1735
|
+
"attenuationDistance",
|
|
1736
|
+
"ior",
|
|
1737
|
+
"specularFactor",
|
|
1738
|
+
"sheenRoughnessFactor",
|
|
1739
|
+
"iridescenceFactor",
|
|
1740
|
+
"iridescenceIor",
|
|
1741
|
+
"dispersion"
|
|
1742
|
+
]);
|
|
1743
|
+
const POINTER_VEC3_LEAVES = new Set([
|
|
1744
|
+
"translation",
|
|
1745
|
+
"scale",
|
|
1746
|
+
"color",
|
|
1747
|
+
"emissiveFactor",
|
|
1748
|
+
"attenuationColor",
|
|
1749
|
+
"specularColorFactor",
|
|
1750
|
+
"sheenColorFactor"
|
|
1751
|
+
]);
|
|
1752
|
+
function pointerLeafValueType(leaf) {
|
|
1753
|
+
if (POINTER_SCALAR_LEAVES.has(leaf))
|
|
1754
|
+
return "scalar";
|
|
1755
|
+
if (POINTER_VEC3_LEAVES.has(leaf))
|
|
1756
|
+
return "vector3";
|
|
1757
|
+
if (leaf === "rotation")
|
|
1758
|
+
return "quaternion";
|
|
1759
|
+
// baseColorFactor (vec4), packed factors, and unknown leaves interpolate elementwise.
|
|
1760
|
+
return "number-array";
|
|
1761
|
+
}
|
|
1762
|
+
function animationPointerKeyframesForSampler(valueType, times, output, interpolation, animationIndex, channelIndex) {
|
|
1763
|
+
const convert = (row) => {
|
|
1764
|
+
if (valueType === "scalar")
|
|
1765
|
+
return row[0] ?? 0;
|
|
1766
|
+
if (valueType === "vector3")
|
|
1767
|
+
return toVec3(row);
|
|
1768
|
+
if (valueType === "quaternion")
|
|
1769
|
+
return toQuat(row);
|
|
1770
|
+
return [...row];
|
|
1771
|
+
};
|
|
1772
|
+
if (interpolation !== "CUBICSPLINE") {
|
|
1773
|
+
if (times.length !== output.length) {
|
|
1774
|
+
throw new Error(`glTF animation ${animationIndex} channel ${channelIndex} input/output count mismatch`);
|
|
1775
|
+
}
|
|
1776
|
+
const samples = sanitizeAnimationSamples(times, output, 1);
|
|
1777
|
+
const mode = interpolation === "STEP" ? "step" : "linear";
|
|
1778
|
+
return samples.times.map((time, index) => ({
|
|
1779
|
+
time,
|
|
1780
|
+
value: convert(samples.output[index]),
|
|
1781
|
+
interpolation: mode
|
|
1782
|
+
}));
|
|
1783
|
+
}
|
|
1784
|
+
if (output.length !== times.length * 3) {
|
|
1785
|
+
throw new Error(`glTF animation ${animationIndex} channel ${channelIndex} CUBICSPLINE output count must be three times input count`);
|
|
1786
|
+
}
|
|
1787
|
+
const samples = sanitizeAnimationSamples(times, output, 3);
|
|
1788
|
+
return samples.times.map((time, index) => {
|
|
1789
|
+
const offset = index * 3;
|
|
1790
|
+
return {
|
|
1791
|
+
time,
|
|
1792
|
+
inTangent: convert(samples.output[offset]),
|
|
1793
|
+
value: convert(samples.output[offset + 1]),
|
|
1794
|
+
outTangent: convert(samples.output[offset + 2]),
|
|
1795
|
+
interpolation: "cubicspline"
|
|
1796
|
+
};
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1603
1799
|
function resolveAnimationInterpolation(value, animationIndex, channelIndex) {
|
|
1604
1800
|
if (value === undefined || value === "LINEAR" || value === "STEP" || value === "CUBICSPLINE") {
|
|
1605
1801
|
return value ?? "LINEAR";
|