@luma.gl/gltf 9.3.0-alpha.2 → 9.3.0-alpha.6
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/dist.dev.js +403 -220
- package/dist/dist.min.js +98 -46
- package/dist/gltf/animations/animations.d.ts +16 -4
- package/dist/gltf/animations/animations.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.d.ts +4 -3
- package/dist/gltf/animations/interpolate.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.js +27 -36
- package/dist/gltf/animations/interpolate.js.map +1 -1
- package/dist/gltf/create-gltf-model.d.ts +6 -0
- package/dist/gltf/create-gltf-model.d.ts.map +1 -1
- package/dist/gltf/create-gltf-model.js +96 -44
- package/dist/gltf/create-gltf-model.js.map +1 -1
- package/dist/gltf/create-scenegraph-from-gltf.d.ts +15 -1
- package/dist/gltf/create-scenegraph-from-gltf.d.ts.map +1 -1
- package/dist/gltf/create-scenegraph-from-gltf.js +12 -6
- package/dist/gltf/create-scenegraph-from-gltf.js.map +1 -1
- package/dist/gltf/gltf-animator.d.ts +26 -0
- package/dist/gltf/gltf-animator.d.ts.map +1 -1
- package/dist/gltf/gltf-animator.js +22 -19
- package/dist/gltf/gltf-animator.js.map +1 -1
- package/dist/index.cjs +384 -210
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/parsers/parse-gltf-animations.d.ts +1 -0
- package/dist/parsers/parse-gltf-animations.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-animations.js +46 -23
- package/dist/parsers/parse-gltf-animations.js.map +1 -1
- package/dist/parsers/parse-gltf-lights.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-lights.js +40 -12
- package/dist/parsers/parse-gltf-lights.js.map +1 -1
- package/dist/parsers/parse-gltf.d.ts +16 -1
- package/dist/parsers/parse-gltf.d.ts.map +1 -1
- package/dist/parsers/parse-gltf.js +65 -57
- package/dist/parsers/parse-gltf.js.map +1 -1
- package/dist/parsers/parse-pbr-material.d.ts +46 -1
- package/dist/parsers/parse-pbr-material.d.ts.map +1 -1
- package/dist/parsers/parse-pbr-material.js +142 -13
- package/dist/parsers/parse-pbr-material.js.map +1 -1
- package/dist/pbr/pbr-environment.d.ts +6 -0
- package/dist/pbr/pbr-environment.d.ts.map +1 -1
- package/dist/pbr/pbr-environment.js +1 -0
- package/dist/pbr/pbr-environment.js.map +1 -1
- package/dist/pbr/pbr-material.d.ts +5 -0
- package/dist/pbr/pbr-material.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts +12 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.js +3 -0
- package/dist/webgl-to-webgpu/convert-webgl-attribute.js.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts +6 -0
- package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-sampler.js +4 -0
- package/dist/webgl-to-webgpu/convert-webgl-sampler.js.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts +2 -0
- package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-topology.js +2 -0
- package/dist/webgl-to-webgpu/convert-webgl-topology.js.map +1 -1
- package/package.json +5 -5
- package/src/gltf/animations/animations.ts +17 -5
- package/src/gltf/animations/interpolate.ts +49 -68
- package/src/gltf/create-gltf-model.ts +101 -43
- package/src/gltf/create-scenegraph-from-gltf.ts +39 -11
- package/src/gltf/gltf-animator.ts +34 -25
- package/src/index.ts +1 -2
- package/src/parsers/parse-gltf-animations.ts +63 -26
- package/src/parsers/parse-gltf-lights.ts +51 -13
- package/src/parsers/parse-gltf.ts +90 -77
- package/src/parsers/parse-pbr-material.ts +210 -15
- package/src/pbr/pbr-environment.ts +10 -0
- package/src/pbr/pbr-material.ts +5 -0
- package/src/webgl-to-webgpu/convert-webgl-attribute.ts +12 -1
- package/src/webgl-to-webgpu/convert-webgl-sampler.ts +9 -0
- package/src/webgl-to-webgpu/convert-webgl-topology.ts +2 -0
- package/dist/utils/deep-copy.d.ts +0 -3
- package/dist/utils/deep-copy.d.ts.map +0 -1
- package/dist/utils/deep-copy.js +0 -21
- package/dist/utils/deep-copy.js.map +0 -1
- package/src/utils/deep-copy.ts +0 -22
package/dist/dist.dev.js
CHANGED
|
@@ -122,7 +122,7 @@ var __exports__ = (() => {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// ../../node_modules/@loaders.gl/images/dist/lib/utils/version.js
|
|
125
|
-
var VERSION = true ? "4.
|
|
125
|
+
var VERSION = true ? "4.4.0-alpha.18" : "latest";
|
|
126
126
|
|
|
127
127
|
// ../../node_modules/@loaders.gl/images/dist/lib/category-api/image-type.js
|
|
128
128
|
var parseImageNode = globalThis.loaders?.parseImageNode;
|
|
@@ -263,7 +263,6 @@ var __exports__ = (() => {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
// ../../node_modules/@loaders.gl/images/dist/lib/parsers/parse-to-image-bitmap.js
|
|
266
|
-
var EMPTY_OBJECT = {};
|
|
267
266
|
var imagebitmapOptionsSupported = true;
|
|
268
267
|
async function parseToImageBitmap(arrayBuffer, options, url) {
|
|
269
268
|
let blob;
|
|
@@ -291,8 +290,13 @@ var __exports__ = (() => {
|
|
|
291
290
|
return await createImageBitmap(blob);
|
|
292
291
|
}
|
|
293
292
|
function isEmptyObject(object) {
|
|
294
|
-
|
|
295
|
-
return
|
|
293
|
+
if (!object) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
for (const key in object) {
|
|
297
|
+
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
296
300
|
}
|
|
297
301
|
return true;
|
|
298
302
|
}
|
|
@@ -681,8 +685,8 @@ var __exports__ = (() => {
|
|
|
681
685
|
}
|
|
682
686
|
|
|
683
687
|
// src/parsers/parse-pbr-material.ts
|
|
684
|
-
var import_constants2 = __toESM(require_constants(), 1);
|
|
685
688
|
var import_core = __toESM(require_core(), 1);
|
|
689
|
+
var import_constants2 = __toESM(require_constants(), 1);
|
|
686
690
|
|
|
687
691
|
// src/webgl-to-webgpu/convert-webgl-sampler.ts
|
|
688
692
|
var import_constants = __toESM(require_constants(), 1);
|
|
@@ -774,6 +778,10 @@ var __exports__ = (() => {
|
|
|
774
778
|
parsedMaterial.defines["HAS_TANGENTS"] = true;
|
|
775
779
|
if (attributes["TEXCOORD_0"])
|
|
776
780
|
parsedMaterial.defines["HAS_UV"] = true;
|
|
781
|
+
if (attributes["JOINTS_0"] && attributes["WEIGHTS_0"])
|
|
782
|
+
parsedMaterial.defines["HAS_SKIN"] = true;
|
|
783
|
+
if (attributes["COLOR_0"])
|
|
784
|
+
parsedMaterial.defines["HAS_COLORS"] = true;
|
|
777
785
|
if (options?.imageBasedLightingEnvironment)
|
|
778
786
|
parsedMaterial.defines["USE_IBL"] = true;
|
|
779
787
|
if (options?.lights)
|
|
@@ -871,29 +879,133 @@ var __exports__ = (() => {
|
|
|
871
879
|
}
|
|
872
880
|
function addTexture(device, gltfTexture, uniformName, define, parsedMaterial) {
|
|
873
881
|
const image = gltfTexture.texture.source.image;
|
|
874
|
-
let textureOptions;
|
|
875
|
-
if (image.compressed) {
|
|
876
|
-
textureOptions = image;
|
|
877
|
-
} else {
|
|
878
|
-
textureOptions = { data: image };
|
|
879
|
-
}
|
|
880
882
|
const gltfSampler = {
|
|
881
883
|
wrapS: 10497,
|
|
882
884
|
// default REPEAT S (U) wrapping mode.
|
|
883
885
|
wrapT: 10497,
|
|
884
886
|
// default REPEAT T (V) wrapping mode.
|
|
887
|
+
minFilter: 9729,
|
|
888
|
+
// default LINEAR filtering
|
|
889
|
+
magFilter: 9729,
|
|
890
|
+
// default LINEAR filtering
|
|
885
891
|
...gltfTexture?.texture?.sampler
|
|
886
892
|
};
|
|
887
|
-
const
|
|
893
|
+
const baseOptions = {
|
|
888
894
|
id: gltfTexture.uniformName || gltfTexture.id,
|
|
889
|
-
sampler: convertSampler(gltfSampler)
|
|
890
|
-
|
|
891
|
-
|
|
895
|
+
sampler: convertSampler(gltfSampler)
|
|
896
|
+
};
|
|
897
|
+
let texture;
|
|
898
|
+
if (image.compressed) {
|
|
899
|
+
texture = createCompressedTexture(device, image, baseOptions);
|
|
900
|
+
} else {
|
|
901
|
+
const { width, height } = device.getExternalImageSize(image);
|
|
902
|
+
texture = device.createTexture({
|
|
903
|
+
...baseOptions,
|
|
904
|
+
width,
|
|
905
|
+
height,
|
|
906
|
+
data: image
|
|
907
|
+
});
|
|
908
|
+
}
|
|
892
909
|
parsedMaterial.bindings[uniformName] = texture;
|
|
893
910
|
if (define)
|
|
894
911
|
parsedMaterial.defines[define] = true;
|
|
895
912
|
parsedMaterial.generatedTextures.push(texture);
|
|
896
913
|
}
|
|
914
|
+
function createCompressedTextureFallback(device, baseOptions) {
|
|
915
|
+
return device.createTexture({
|
|
916
|
+
...baseOptions,
|
|
917
|
+
format: "rgba8unorm",
|
|
918
|
+
width: 1,
|
|
919
|
+
height: 1,
|
|
920
|
+
mipLevels: 1
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
function resolveCompressedTextureFormat(level) {
|
|
924
|
+
return level.textureFormat;
|
|
925
|
+
}
|
|
926
|
+
function getMaxCompressedMipLevels(baseWidth, baseHeight, format) {
|
|
927
|
+
const { blockWidth = 1, blockHeight = 1 } = import_core.textureFormatDecoder.getInfo(format);
|
|
928
|
+
let count = 1;
|
|
929
|
+
for (let i = 1; ; i++) {
|
|
930
|
+
const w = Math.max(1, baseWidth >> i);
|
|
931
|
+
const h = Math.max(1, baseHeight >> i);
|
|
932
|
+
if (w < blockWidth || h < blockHeight)
|
|
933
|
+
break;
|
|
934
|
+
count++;
|
|
935
|
+
}
|
|
936
|
+
return count;
|
|
937
|
+
}
|
|
938
|
+
function createCompressedTexture(device, image, baseOptions) {
|
|
939
|
+
let levels;
|
|
940
|
+
if (Array.isArray(image.data) && image.data[0]?.data) {
|
|
941
|
+
levels = image.data;
|
|
942
|
+
} else if ("mipmaps" in image && Array.isArray(image.mipmaps)) {
|
|
943
|
+
levels = image.mipmaps;
|
|
944
|
+
} else {
|
|
945
|
+
levels = [];
|
|
946
|
+
}
|
|
947
|
+
if (levels.length === 0 || !levels[0]?.data) {
|
|
948
|
+
import_core.log.warn(
|
|
949
|
+
"createCompressedTexture: compressed image has no valid mip levels, creating fallback"
|
|
950
|
+
)();
|
|
951
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
952
|
+
}
|
|
953
|
+
const baseLevel = levels[0];
|
|
954
|
+
const baseWidth = baseLevel.width ?? image.width ?? 0;
|
|
955
|
+
const baseHeight = baseLevel.height ?? image.height ?? 0;
|
|
956
|
+
if (baseWidth <= 0 || baseHeight <= 0) {
|
|
957
|
+
import_core.log.warn("createCompressedTexture: base level has invalid dimensions, creating fallback")();
|
|
958
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
959
|
+
}
|
|
960
|
+
const format = resolveCompressedTextureFormat(baseLevel);
|
|
961
|
+
if (!format) {
|
|
962
|
+
import_core.log.warn("createCompressedTexture: compressed image has no textureFormat, creating fallback")();
|
|
963
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
964
|
+
}
|
|
965
|
+
const maxMipLevels = getMaxCompressedMipLevels(baseWidth, baseHeight, format);
|
|
966
|
+
const levelLimit = Math.min(levels.length, maxMipLevels);
|
|
967
|
+
let validLevelCount = 1;
|
|
968
|
+
for (let i = 1; i < levelLimit; i++) {
|
|
969
|
+
const level = levels[i];
|
|
970
|
+
if (!level.data || level.width <= 0 || level.height <= 0) {
|
|
971
|
+
import_core.log.warn(`createCompressedTexture: mip level ${i} has invalid data/dimensions, truncating`)();
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
const levelFormat = resolveCompressedTextureFormat(level);
|
|
975
|
+
if (levelFormat && levelFormat !== format) {
|
|
976
|
+
import_core.log.warn(
|
|
977
|
+
`createCompressedTexture: mip level ${i} format '${levelFormat}' differs from base '${format}', truncating`
|
|
978
|
+
)();
|
|
979
|
+
break;
|
|
980
|
+
}
|
|
981
|
+
const expectedW = Math.max(1, baseWidth >> i);
|
|
982
|
+
const expectedH = Math.max(1, baseHeight >> i);
|
|
983
|
+
if (level.width !== expectedW || level.height !== expectedH) {
|
|
984
|
+
import_core.log.warn(
|
|
985
|
+
`createCompressedTexture: mip level ${i} dimensions ${level.width}x${level.height} don't match expected ${expectedW}x${expectedH}, truncating`
|
|
986
|
+
)();
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
989
|
+
validLevelCount++;
|
|
990
|
+
}
|
|
991
|
+
const texture = device.createTexture({
|
|
992
|
+
...baseOptions,
|
|
993
|
+
format,
|
|
994
|
+
usage: import_core.Texture.TEXTURE | import_core.Texture.COPY_DST,
|
|
995
|
+
width: baseWidth,
|
|
996
|
+
height: baseHeight,
|
|
997
|
+
mipLevels: validLevelCount,
|
|
998
|
+
data: baseLevel.data
|
|
999
|
+
});
|
|
1000
|
+
for (let i = 1; i < validLevelCount; i++) {
|
|
1001
|
+
texture.writeData(levels[i].data, {
|
|
1002
|
+
width: levels[i].width,
|
|
1003
|
+
height: levels[i].height,
|
|
1004
|
+
mipLevel: i
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
return texture;
|
|
1008
|
+
}
|
|
897
1009
|
|
|
898
1010
|
// ../../node_modules/@math.gl/core/dist/lib/common.js
|
|
899
1011
|
var RADIANS_TO_DEGREES = 1 / Math.PI * 180;
|
|
@@ -3468,17 +3580,20 @@ var __exports__ = (() => {
|
|
|
3468
3580
|
|
|
3469
3581
|
// src/parsers/parse-gltf-lights.ts
|
|
3470
3582
|
function parseGLTFLights(gltf) {
|
|
3471
|
-
const lightDefs =
|
|
3583
|
+
const lightDefs = (
|
|
3584
|
+
// `postProcessGLTF()` moves KHR_lights_punctual into `gltf.lights`.
|
|
3585
|
+
gltf.lights || gltf.extensions?.["KHR_lights_punctual"]?.["lights"]
|
|
3586
|
+
);
|
|
3472
3587
|
if (!lightDefs || !Array.isArray(lightDefs) || lightDefs.length === 0) {
|
|
3473
3588
|
return [];
|
|
3474
3589
|
}
|
|
3475
3590
|
const lights = [];
|
|
3476
3591
|
for (const node of gltf.nodes || []) {
|
|
3477
|
-
const
|
|
3478
|
-
if (
|
|
3592
|
+
const lightIndex = node.light ?? node.extensions?.KHR_lights_punctual?.light;
|
|
3593
|
+
if (typeof lightIndex !== "number") {
|
|
3479
3594
|
continue;
|
|
3480
3595
|
}
|
|
3481
|
-
const gltfLight = lightDefs[
|
|
3596
|
+
const gltfLight = lightDefs[lightIndex];
|
|
3482
3597
|
if (!gltfLight) {
|
|
3483
3598
|
continue;
|
|
3484
3599
|
}
|
|
@@ -3502,7 +3617,7 @@ var __exports__ = (() => {
|
|
|
3502
3617
|
return lights;
|
|
3503
3618
|
}
|
|
3504
3619
|
function parsePointLight(node, color, intensity, range) {
|
|
3505
|
-
const position = node
|
|
3620
|
+
const position = getNodePosition(node);
|
|
3506
3621
|
let attenuation = [1, 0, 0];
|
|
3507
3622
|
if (range !== void 0 && range > 0) {
|
|
3508
3623
|
attenuation = [1, 0, 1 / (range * range)];
|
|
@@ -3516,11 +3631,7 @@ var __exports__ = (() => {
|
|
|
3516
3631
|
};
|
|
3517
3632
|
}
|
|
3518
3633
|
function parseDirectionalLight(node, color, intensity) {
|
|
3519
|
-
|
|
3520
|
-
if (node.rotation) {
|
|
3521
|
-
const orientation = new Matrix4().fromQuaternion(node.rotation);
|
|
3522
|
-
direction = orientation.transformDirection([0, 0, -1]);
|
|
3523
|
-
}
|
|
3634
|
+
const direction = getNodeDirection(node);
|
|
3524
3635
|
return {
|
|
3525
3636
|
type: "directional",
|
|
3526
3637
|
direction,
|
|
@@ -3528,6 +3639,24 @@ var __exports__ = (() => {
|
|
|
3528
3639
|
intensity
|
|
3529
3640
|
};
|
|
3530
3641
|
}
|
|
3642
|
+
function getNodePosition(node) {
|
|
3643
|
+
if (node.matrix) {
|
|
3644
|
+
return new Matrix4(node.matrix).transformAsPoint([0, 0, 0]);
|
|
3645
|
+
}
|
|
3646
|
+
if (node.translation) {
|
|
3647
|
+
return [...node.translation];
|
|
3648
|
+
}
|
|
3649
|
+
return [0, 0, 0];
|
|
3650
|
+
}
|
|
3651
|
+
function getNodeDirection(node) {
|
|
3652
|
+
if (node.matrix) {
|
|
3653
|
+
return new Matrix4(node.matrix).transformDirection([0, 0, -1]);
|
|
3654
|
+
}
|
|
3655
|
+
if (node.rotation) {
|
|
3656
|
+
return new Matrix4().fromQuaternion(node.rotation).transformDirection([0, 0, -1]);
|
|
3657
|
+
}
|
|
3658
|
+
return [0, 0, -1];
|
|
3659
|
+
}
|
|
3531
3660
|
|
|
3532
3661
|
// src/parsers/parse-gltf.ts
|
|
3533
3662
|
var import_engine3 = __toESM(require_engine(), 1);
|
|
@@ -3557,50 +3686,88 @@ var __exports__ = (() => {
|
|
|
3557
3686
|
var SHADER = (
|
|
3558
3687
|
/* WGSL */
|
|
3559
3688
|
`
|
|
3560
|
-
|
|
3689
|
+
struct VertexInputs {
|
|
3690
|
+
@location(0) positions: vec3f,
|
|
3691
|
+
#ifdef HAS_NORMALS
|
|
3692
|
+
@location(1) normals: vec3f,
|
|
3693
|
+
#endif
|
|
3694
|
+
#ifdef HAS_TANGENTS
|
|
3695
|
+
@location(2) TANGENT: vec4f,
|
|
3696
|
+
#endif
|
|
3697
|
+
#ifdef HAS_UV
|
|
3698
|
+
@location(3) texCoords: vec2f,
|
|
3699
|
+
#endif
|
|
3700
|
+
#ifdef HAS_SKIN
|
|
3701
|
+
@location(4) JOINTS_0: vec4u,
|
|
3702
|
+
@location(5) WEIGHTS_0: vec4f,
|
|
3703
|
+
#endif
|
|
3704
|
+
};
|
|
3561
3705
|
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
// in vec2 TEXCOORD_0;
|
|
3572
|
-
in vec2 texCoords;
|
|
3573
|
-
#endif
|
|
3706
|
+
struct FragmentInputs {
|
|
3707
|
+
@builtin(position) position: vec4f,
|
|
3708
|
+
@location(0) pbrPosition: vec3f,
|
|
3709
|
+
@location(1) pbrUV: vec2f,
|
|
3710
|
+
@location(2) pbrNormal: vec3f,
|
|
3711
|
+
#ifdef HAS_TANGENTS
|
|
3712
|
+
@location(3) pbrTangent: vec4f,
|
|
3713
|
+
#endif
|
|
3714
|
+
};
|
|
3574
3715
|
|
|
3575
3716
|
@vertex
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3717
|
+
fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
3718
|
+
var outputs: FragmentInputs;
|
|
3719
|
+
var position = vec4f(inputs.positions, 1.0);
|
|
3720
|
+
var normal = vec3f(0.0, 0.0, 1.0);
|
|
3721
|
+
var tangent = vec4f(1.0, 0.0, 0.0, 1.0);
|
|
3722
|
+
var uv = vec2f(0.0, 0.0);
|
|
3580
3723
|
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3724
|
+
#ifdef HAS_NORMALS
|
|
3725
|
+
normal = inputs.normals;
|
|
3726
|
+
#endif
|
|
3727
|
+
#ifdef HAS_UV
|
|
3728
|
+
uv = inputs.texCoords;
|
|
3729
|
+
#endif
|
|
3730
|
+
#ifdef HAS_TANGENTS
|
|
3731
|
+
tangent = inputs.TANGENT;
|
|
3732
|
+
#endif
|
|
3733
|
+
#ifdef HAS_SKIN
|
|
3734
|
+
let skinMatrix = getSkinMatrix(inputs.WEIGHTS_0, inputs.JOINTS_0);
|
|
3735
|
+
position = skinMatrix * position;
|
|
3736
|
+
normal = normalize((skinMatrix * vec4f(normal, 0.0)).xyz);
|
|
3737
|
+
#ifdef HAS_TANGENTS
|
|
3738
|
+
tangent = vec4f(normalize((skinMatrix * vec4f(tangent.xyz, 0.0)).xyz), tangent.w);
|
|
3739
|
+
#endif
|
|
3740
|
+
#endif
|
|
3584
3741
|
|
|
3585
|
-
|
|
3586
|
-
_TANGENT = TANGENT;
|
|
3587
|
-
#endif
|
|
3742
|
+
let worldPosition = pbrProjection.modelMatrix * position;
|
|
3588
3743
|
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3744
|
+
#ifdef HAS_NORMALS
|
|
3745
|
+
normal = normalize((pbrProjection.normalMatrix * vec4f(normal, 0.0)).xyz);
|
|
3746
|
+
#endif
|
|
3747
|
+
#ifdef HAS_TANGENTS
|
|
3748
|
+
let worldTangent = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);
|
|
3749
|
+
outputs.pbrTangent = vec4f(worldTangent, tangent.w);
|
|
3750
|
+
#endif
|
|
3592
3751
|
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3752
|
+
outputs.position = pbrProjection.modelViewProjectionMatrix * position;
|
|
3753
|
+
outputs.pbrPosition = worldPosition.xyz / worldPosition.w;
|
|
3754
|
+
outputs.pbrUV = uv;
|
|
3755
|
+
outputs.pbrNormal = normal;
|
|
3756
|
+
return outputs;
|
|
3757
|
+
}
|
|
3596
3758
|
|
|
3597
3759
|
@fragment
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3760
|
+
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
3761
|
+
fragmentInputs.pbr_vPosition = inputs.pbrPosition;
|
|
3762
|
+
fragmentInputs.pbr_vUV = inputs.pbrUV;
|
|
3763
|
+
fragmentInputs.pbr_vNormal = inputs.pbrNormal;
|
|
3764
|
+
#ifdef HAS_TANGENTS
|
|
3765
|
+
let tangent = normalize(inputs.pbrTangent.xyz);
|
|
3766
|
+
let bitangent = normalize(cross(inputs.pbrNormal, tangent)) * inputs.pbrTangent.w;
|
|
3767
|
+
fragmentInputs.pbr_vTBN = mat3x3f(tangent, bitangent, inputs.pbrNormal);
|
|
3768
|
+
#endif
|
|
3769
|
+
return pbr_filterColor(vec4f(1.0));
|
|
3770
|
+
}
|
|
3604
3771
|
`
|
|
3605
3772
|
);
|
|
3606
3773
|
var vs = (
|
|
@@ -3624,6 +3791,11 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3624
3791
|
in vec2 texCoords;
|
|
3625
3792
|
#endif
|
|
3626
3793
|
|
|
3794
|
+
#ifdef HAS_SKIN
|
|
3795
|
+
in uvec4 JOINTS_0;
|
|
3796
|
+
in vec4 WEIGHTS_0;
|
|
3797
|
+
#endif
|
|
3798
|
+
|
|
3627
3799
|
void main(void) {
|
|
3628
3800
|
vec4 _NORMAL = vec4(0.);
|
|
3629
3801
|
vec4 _TANGENT = vec4(0.);
|
|
@@ -3641,8 +3813,17 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3641
3813
|
_TEXCOORD_0 = texCoords;
|
|
3642
3814
|
#endif
|
|
3643
3815
|
|
|
3644
|
-
|
|
3645
|
-
|
|
3816
|
+
vec4 pos = positions;
|
|
3817
|
+
|
|
3818
|
+
#ifdef HAS_SKIN
|
|
3819
|
+
mat4 skinMat = getSkinMatrix(WEIGHTS_0, JOINTS_0);
|
|
3820
|
+
pos = skinMat * pos;
|
|
3821
|
+
_NORMAL = skinMat * _NORMAL;
|
|
3822
|
+
_TANGENT = vec4((skinMat * vec4(_TANGENT.xyz, 0.)).xyz, _TANGENT.w);
|
|
3823
|
+
#endif
|
|
3824
|
+
|
|
3825
|
+
pbr_setPositionNormalTangentUV(pos, _NORMAL, _TANGENT, _TEXCOORD_0);
|
|
3826
|
+
gl_Position = pbrProjection.modelViewProjectionMatrix * pos;
|
|
3646
3827
|
}
|
|
3647
3828
|
`
|
|
3648
3829
|
);
|
|
@@ -3675,7 +3856,7 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3675
3856
|
geometry,
|
|
3676
3857
|
topology: geometry.topology,
|
|
3677
3858
|
vertexCount,
|
|
3678
|
-
modules: [import_shadertools.pbrMaterial],
|
|
3859
|
+
modules: [import_shadertools.pbrMaterial, import_shadertools.skin],
|
|
3679
3860
|
...modelOptions,
|
|
3680
3861
|
defines: { ...parsedPPBRMaterial.defines, ...modelOptions.defines },
|
|
3681
3862
|
parameters: { ...parameters, ...parsedPPBRMaterial.parameters, ...modelOptions.parameters }
|
|
@@ -3699,69 +3880,73 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3699
3880
|
lights: true,
|
|
3700
3881
|
useTangents: false
|
|
3701
3882
|
};
|
|
3702
|
-
function parseGLTF(device, gltf,
|
|
3703
|
-
const
|
|
3704
|
-
const
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
}
|
|
3709
|
-
function createScene(device, gltfScene, gltfNodes, options) {
|
|
3710
|
-
const gltfSceneNodes = gltfScene.nodes || [];
|
|
3711
|
-
const nodes = gltfSceneNodes.map((node) => createNode(device, node, gltfNodes, options));
|
|
3712
|
-
const sceneNode = new import_engine3.GroupNode({
|
|
3713
|
-
id: gltfScene.name || gltfScene.id,
|
|
3714
|
-
children: nodes
|
|
3883
|
+
function parseGLTF(device, gltf, options = {}) {
|
|
3884
|
+
const combinedOptions = { ...defaultOptions, ...options };
|
|
3885
|
+
const gltfMeshIdToNodeMap = /* @__PURE__ */ new Map();
|
|
3886
|
+
gltf.meshes.forEach((gltfMesh, idx) => {
|
|
3887
|
+
const newMesh = createNodeForGLTFMesh(device, gltfMesh, combinedOptions);
|
|
3888
|
+
gltfMeshIdToNodeMap.set(gltfMesh.id, newMesh);
|
|
3715
3889
|
});
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3890
|
+
const gltfNodeIndexToNodeMap = /* @__PURE__ */ new Map();
|
|
3891
|
+
const gltfNodeIdToNodeMap = /* @__PURE__ */ new Map();
|
|
3892
|
+
gltf.nodes.forEach((gltfNode, idx) => {
|
|
3893
|
+
const newNode = createNodeForGLTFNode(device, gltfNode, combinedOptions);
|
|
3894
|
+
gltfNodeIndexToNodeMap.set(idx, newNode);
|
|
3895
|
+
gltfNodeIdToNodeMap.set(gltfNode.id, newNode);
|
|
3896
|
+
});
|
|
3897
|
+
gltf.nodes.forEach((gltfNode, idx) => {
|
|
3898
|
+
gltfNodeIndexToNodeMap.get(idx).add(
|
|
3899
|
+
(gltfNode.children ?? []).map(({ id }) => {
|
|
3900
|
+
const child = gltfNodeIdToNodeMap.get(id);
|
|
3901
|
+
if (!child)
|
|
3902
|
+
throw new Error(`Cannot find child ${id} of node ${idx}`);
|
|
3903
|
+
return child;
|
|
3904
|
+
})
|
|
3905
|
+
);
|
|
3722
3906
|
if (gltfNode.mesh) {
|
|
3723
|
-
|
|
3907
|
+
const mesh = gltfMeshIdToNodeMap.get(gltfNode.mesh.id);
|
|
3908
|
+
if (!mesh) {
|
|
3909
|
+
throw new Error(`Cannot find mesh child ${gltfNode.mesh.id} of node ${idx}`);
|
|
3910
|
+
}
|
|
3911
|
+
gltfNodeIndexToNodeMap.get(idx).add(mesh);
|
|
3724
3912
|
}
|
|
3725
|
-
|
|
3726
|
-
|
|
3913
|
+
});
|
|
3914
|
+
const scenes = gltf.scenes.map((gltfScene) => {
|
|
3915
|
+
const children = (gltfScene.nodes || []).map(({ id }) => {
|
|
3916
|
+
const child = gltfNodeIdToNodeMap.get(id);
|
|
3917
|
+
if (!child)
|
|
3918
|
+
throw new Error(`Cannot find child ${id} of scene ${gltfScene.name || gltfScene.id}`);
|
|
3919
|
+
return child;
|
|
3920
|
+
});
|
|
3921
|
+
return new import_engine3.GroupNode({
|
|
3922
|
+
id: gltfScene.name || gltfScene.id,
|
|
3727
3923
|
children
|
|
3728
3924
|
});
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
node.matrix.scale(gltfNode.scale);
|
|
3742
|
-
}
|
|
3743
|
-
}
|
|
3744
|
-
gltfNode._node = node;
|
|
3745
|
-
}
|
|
3746
|
-
const topLevelNode = gltfNodes.find((node) => node.id === gltfNode.id);
|
|
3747
|
-
topLevelNode._node = gltfNode._node;
|
|
3748
|
-
return gltfNode._node;
|
|
3925
|
+
});
|
|
3926
|
+
return { scenes, gltfMeshIdToNodeMap, gltfNodeIdToNodeMap, gltfNodeIndexToNodeMap };
|
|
3927
|
+
}
|
|
3928
|
+
function createNodeForGLTFNode(device, gltfNode, options) {
|
|
3929
|
+
return new import_engine3.GroupNode({
|
|
3930
|
+
id: gltfNode.name || gltfNode.id,
|
|
3931
|
+
children: [],
|
|
3932
|
+
matrix: gltfNode.matrix,
|
|
3933
|
+
position: gltfNode.translation,
|
|
3934
|
+
rotation: gltfNode.rotation,
|
|
3935
|
+
scale: gltfNode.scale
|
|
3936
|
+
});
|
|
3749
3937
|
}
|
|
3750
|
-
function
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
gltfMesh._mesh = mesh;
|
|
3761
|
-
}
|
|
3762
|
-
return gltfMesh._mesh;
|
|
3938
|
+
function createNodeForGLTFMesh(device, gltfMesh, options) {
|
|
3939
|
+
const gltfPrimitives = gltfMesh.primitives || [];
|
|
3940
|
+
const primitives = gltfPrimitives.map(
|
|
3941
|
+
(gltfPrimitive, i) => createNodeForGLTFPrimitive(device, gltfPrimitive, i, gltfMesh, options)
|
|
3942
|
+
);
|
|
3943
|
+
const mesh = new import_engine3.GroupNode({
|
|
3944
|
+
id: gltfMesh.name || gltfMesh.id,
|
|
3945
|
+
children: primitives
|
|
3946
|
+
});
|
|
3947
|
+
return mesh;
|
|
3763
3948
|
}
|
|
3764
|
-
function
|
|
3949
|
+
function createNodeForGLTFPrimitive(device, gltfPrimitive, i, gltfMesh, options) {
|
|
3765
3950
|
const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`;
|
|
3766
3951
|
const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4);
|
|
3767
3952
|
const vertexCount = gltfPrimitive.indices ? gltfPrimitive.indices.count : getVertexCount(gltfPrimitive.attributes);
|
|
@@ -3800,31 +3985,28 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3800
3985
|
}
|
|
3801
3986
|
|
|
3802
3987
|
// src/gltf/gltf-animator.ts
|
|
3803
|
-
var
|
|
3988
|
+
var import_core6 = __toESM(require_core(), 1);
|
|
3804
3989
|
|
|
3805
3990
|
// src/gltf/animations/interpolate.ts
|
|
3806
|
-
var
|
|
3807
|
-
|
|
3991
|
+
var import_core4 = __toESM(require_core(), 1);
|
|
3992
|
+
function updateTargetPath(target, path, newValue) {
|
|
3993
|
+
switch (path) {
|
|
3994
|
+
case "translation":
|
|
3995
|
+
return target.setPosition(newValue).updateMatrix();
|
|
3996
|
+
case "rotation":
|
|
3997
|
+
return target.setRotation(newValue).updateMatrix();
|
|
3998
|
+
case "scale":
|
|
3999
|
+
return target.setScale(newValue).updateMatrix();
|
|
4000
|
+
default:
|
|
4001
|
+
import_core4.log.warn(`Bad animation path ${path}`)();
|
|
4002
|
+
return null;
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
3808
4005
|
function interpolate(time, { input, interpolation, output }, target, path) {
|
|
3809
4006
|
const maxTime = input[input.length - 1];
|
|
3810
4007
|
const animationTime = time % maxTime;
|
|
3811
4008
|
const nextIndex = input.findIndex((t) => t >= animationTime);
|
|
3812
4009
|
const previousIndex = Math.max(0, nextIndex - 1);
|
|
3813
|
-
if (!Array.isArray(target[path])) {
|
|
3814
|
-
switch (path) {
|
|
3815
|
-
case "translation":
|
|
3816
|
-
target[path] = [0, 0, 0];
|
|
3817
|
-
break;
|
|
3818
|
-
case "rotation":
|
|
3819
|
-
target[path] = [0, 0, 0, 1];
|
|
3820
|
-
break;
|
|
3821
|
-
case "scale":
|
|
3822
|
-
target[path] = [1, 1, 1];
|
|
3823
|
-
break;
|
|
3824
|
-
default:
|
|
3825
|
-
import_core5.log.warn(`Bad animation path ${path}`)();
|
|
3826
|
-
}
|
|
3827
|
-
}
|
|
3828
4010
|
const previousTime = input[previousIndex];
|
|
3829
4011
|
const nextTime = input[nextIndex];
|
|
3830
4012
|
switch (interpolation) {
|
|
@@ -3834,13 +4016,7 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3834
4016
|
case "LINEAR":
|
|
3835
4017
|
if (nextTime > previousTime) {
|
|
3836
4018
|
const ratio = (animationTime - previousTime) / (nextTime - previousTime);
|
|
3837
|
-
linearInterpolate(
|
|
3838
|
-
target,
|
|
3839
|
-
path,
|
|
3840
|
-
output[previousIndex],
|
|
3841
|
-
output[nextIndex],
|
|
3842
|
-
ratio
|
|
3843
|
-
);
|
|
4019
|
+
linearInterpolate(target, path, output[previousIndex], output[nextIndex], ratio);
|
|
3844
4020
|
}
|
|
3845
4021
|
break;
|
|
3846
4022
|
case "CUBICSPLINE":
|
|
@@ -3855,23 +4031,19 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3855
4031
|
}
|
|
3856
4032
|
break;
|
|
3857
4033
|
default:
|
|
3858
|
-
|
|
4034
|
+
import_core4.log.warn(`Interpolation ${interpolation} not supported`)();
|
|
3859
4035
|
break;
|
|
3860
4036
|
}
|
|
3861
4037
|
}
|
|
3862
4038
|
function linearInterpolate(target, path, start, stop, ratio) {
|
|
3863
|
-
if (!target[path]) {
|
|
3864
|
-
throw new Error();
|
|
3865
|
-
}
|
|
3866
4039
|
if (path === "rotation") {
|
|
3867
|
-
|
|
3868
|
-
for (let i = 0; i < scratchQuaternion.length; i++) {
|
|
3869
|
-
target[path][i] = scratchQuaternion[i];
|
|
3870
|
-
}
|
|
4040
|
+
updateTargetPath(target, path, new Quaternion().slerp({ start, target: stop, ratio }));
|
|
3871
4041
|
} else {
|
|
4042
|
+
const newVal = [];
|
|
3872
4043
|
for (let i = 0; i < start.length; i++) {
|
|
3873
|
-
|
|
4044
|
+
newVal[i] = ratio * stop[i] + (1 - ratio) * start[i];
|
|
3874
4045
|
}
|
|
4046
|
+
updateTargetPath(target, path, newVal);
|
|
3875
4047
|
}
|
|
3876
4048
|
}
|
|
3877
4049
|
function cubicsplineInterpolate(target, path, {
|
|
@@ -3882,83 +4054,80 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3882
4054
|
tDiff,
|
|
3883
4055
|
ratio: t
|
|
3884
4056
|
}) {
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
}
|
|
3888
|
-
for (let i = 0; i < target[path].length; i++) {
|
|
4057
|
+
const newVal = [];
|
|
4058
|
+
for (let i = 0; i < p0.length; i++) {
|
|
3889
4059
|
const m0 = outTangent0[i] * tDiff;
|
|
3890
4060
|
const m1 = inTangent1[i] * tDiff;
|
|
3891
|
-
|
|
4061
|
+
newVal[i] = (2 * Math.pow(t, 3) - 3 * Math.pow(t, 2) + 1) * p0[i] + (Math.pow(t, 3) - 2 * Math.pow(t, 2) + t) * m0 + (-2 * Math.pow(t, 3) + 3 * Math.pow(t, 2)) * p1[i] + (Math.pow(t, 3) - Math.pow(t, 2)) * m1;
|
|
3892
4062
|
}
|
|
4063
|
+
updateTargetPath(target, path, newVal);
|
|
3893
4064
|
}
|
|
3894
4065
|
function stepInterpolate(target, path, value) {
|
|
3895
|
-
|
|
3896
|
-
throw new Error();
|
|
3897
|
-
}
|
|
3898
|
-
for (let i = 0; i < value.length; i++) {
|
|
3899
|
-
target[path][i] = value[i];
|
|
3900
|
-
}
|
|
4066
|
+
updateTargetPath(target, path, value);
|
|
3901
4067
|
}
|
|
3902
4068
|
|
|
3903
4069
|
// src/gltf/gltf-animator.ts
|
|
3904
4070
|
var GLTFSingleAnimator = class {
|
|
4071
|
+
/** Animation definition being played. */
|
|
3905
4072
|
animation;
|
|
4073
|
+
/** Target scenegraph lookup table. */
|
|
4074
|
+
gltfNodeIdToNodeMap;
|
|
4075
|
+
/** Playback start time in seconds. */
|
|
3906
4076
|
startTime = 0;
|
|
4077
|
+
/** Whether playback is currently enabled. */
|
|
3907
4078
|
playing = true;
|
|
4079
|
+
/** Playback speed multiplier. */
|
|
3908
4080
|
speed = 1;
|
|
4081
|
+
/** Creates a single-animation controller. */
|
|
3909
4082
|
constructor(props) {
|
|
3910
4083
|
this.animation = props.animation;
|
|
4084
|
+
this.gltfNodeIdToNodeMap = props.gltfNodeIdToNodeMap;
|
|
3911
4085
|
this.animation.name ||= "unnamed";
|
|
3912
4086
|
Object.assign(this, props);
|
|
3913
4087
|
}
|
|
4088
|
+
/** Advances the animation to the supplied wall-clock time in milliseconds. */
|
|
3914
4089
|
setTime(timeMs) {
|
|
3915
4090
|
if (!this.playing) {
|
|
3916
4091
|
return;
|
|
3917
4092
|
}
|
|
3918
4093
|
const absTime = timeMs / 1e3;
|
|
3919
4094
|
const time = (absTime - this.startTime) * this.speed;
|
|
3920
|
-
this.animation.channels.forEach(({ sampler,
|
|
3921
|
-
|
|
3922
|
-
|
|
4095
|
+
this.animation.channels.forEach(({ sampler, targetNodeId, path }) => {
|
|
4096
|
+
const targetNode = this.gltfNodeIdToNodeMap.get(targetNodeId);
|
|
4097
|
+
if (!targetNode) {
|
|
4098
|
+
throw new Error(`Cannot find animation target node ${targetNodeId}`);
|
|
4099
|
+
}
|
|
4100
|
+
interpolate(time, sampler, targetNode, path);
|
|
3923
4101
|
});
|
|
3924
4102
|
}
|
|
3925
4103
|
};
|
|
3926
4104
|
var GLTFAnimator = class {
|
|
4105
|
+
/** Individual animation controllers. */
|
|
3927
4106
|
animations;
|
|
4107
|
+
/** Creates an animator for the supplied glTF scenegraph. */
|
|
3928
4108
|
constructor(props) {
|
|
3929
4109
|
this.animations = props.animations.map((animation, index) => {
|
|
3930
4110
|
const name = animation.name || `Animation-${index}`;
|
|
3931
4111
|
return new GLTFSingleAnimator({
|
|
4112
|
+
gltfNodeIdToNodeMap: props.gltfNodeIdToNodeMap,
|
|
3932
4113
|
animation: { name, channels: animation.channels }
|
|
3933
4114
|
});
|
|
3934
4115
|
});
|
|
3935
4116
|
}
|
|
3936
4117
|
/** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */
|
|
3937
4118
|
animate(time) {
|
|
3938
|
-
|
|
4119
|
+
import_core6.log.warn("GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead")();
|
|
3939
4120
|
this.setTime(time);
|
|
3940
4121
|
}
|
|
4122
|
+
/** Advances every animation to the supplied wall-clock time in milliseconds. */
|
|
3941
4123
|
setTime(time) {
|
|
3942
4124
|
this.animations.forEach((animation) => animation.setTime(time));
|
|
3943
4125
|
}
|
|
4126
|
+
/** Returns the per-animation controllers managed by this animator. */
|
|
3944
4127
|
getAnimations() {
|
|
3945
4128
|
return this.animations;
|
|
3946
4129
|
}
|
|
3947
4130
|
};
|
|
3948
|
-
var scratchMatrix = new Matrix4();
|
|
3949
|
-
function applyTranslationRotationScale(gltfNode, node) {
|
|
3950
|
-
node.matrix.identity();
|
|
3951
|
-
if (gltfNode.translation) {
|
|
3952
|
-
node.matrix.translate(gltfNode.translation);
|
|
3953
|
-
}
|
|
3954
|
-
if (gltfNode.rotation) {
|
|
3955
|
-
const rotationMatrix = scratchMatrix.fromQuaternion(gltfNode.rotation);
|
|
3956
|
-
node.matrix.multiplyRight(rotationMatrix);
|
|
3957
|
-
}
|
|
3958
|
-
if (gltfNode.scale) {
|
|
3959
|
-
node.matrix.scale(gltfNode.scale);
|
|
3960
|
-
}
|
|
3961
|
-
}
|
|
3962
4131
|
|
|
3963
4132
|
// src/webgl-to-webgpu/convert-webgl-attribute.ts
|
|
3964
4133
|
var ATTRIBUTE_TYPE_TO_COMPONENTS = {
|
|
@@ -3990,65 +4159,79 @@ layout(0) positions: vec4; // in vec4 POSITION;
|
|
|
3990
4159
|
// src/parsers/parse-gltf-animations.ts
|
|
3991
4160
|
function parseGLTFAnimations(gltf) {
|
|
3992
4161
|
const gltfAnimations = gltf.animations || [];
|
|
4162
|
+
const accessorCache1D = /* @__PURE__ */ new Map();
|
|
4163
|
+
const accessorCache2D = /* @__PURE__ */ new Map();
|
|
3993
4164
|
return gltfAnimations.map((animation, index) => {
|
|
3994
4165
|
const name = animation.name || `Animation-${index}`;
|
|
3995
4166
|
const samplers = animation.samplers.map(
|
|
3996
4167
|
({ input, interpolation = "LINEAR", output }) => ({
|
|
3997
|
-
input:
|
|
4168
|
+
input: accessorToJsArray1D(gltf.accessors[input], accessorCache1D),
|
|
3998
4169
|
interpolation,
|
|
3999
|
-
output:
|
|
4170
|
+
output: accessorToJsArray2D(gltf.accessors[output], accessorCache2D)
|
|
4000
4171
|
})
|
|
4001
4172
|
);
|
|
4002
|
-
const channels = animation.channels.map(({ sampler, target }) =>
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4173
|
+
const channels = animation.channels.map(({ sampler, target }) => {
|
|
4174
|
+
const targetNode = gltf.nodes[target.node ?? 0];
|
|
4175
|
+
if (!targetNode) {
|
|
4176
|
+
throw new Error(`Cannot find animation target ${target.node}`);
|
|
4177
|
+
}
|
|
4178
|
+
return {
|
|
4179
|
+
sampler: samplers[sampler],
|
|
4180
|
+
targetNodeId: targetNode.id,
|
|
4181
|
+
path: target.path
|
|
4182
|
+
};
|
|
4183
|
+
});
|
|
4007
4184
|
return { name, channels };
|
|
4008
4185
|
});
|
|
4009
4186
|
}
|
|
4010
|
-
function
|
|
4011
|
-
if (
|
|
4012
|
-
|
|
4013
|
-
if (components === 1) {
|
|
4014
|
-
accessor._animation = Array.from(array);
|
|
4015
|
-
} else {
|
|
4016
|
-
const slicedArray = [];
|
|
4017
|
-
for (let i = 0; i < array.length; i += components) {
|
|
4018
|
-
slicedArray.push(Array.from(array.slice(i, i + components)));
|
|
4019
|
-
}
|
|
4020
|
-
accessor._animation = slicedArray;
|
|
4021
|
-
}
|
|
4187
|
+
function accessorToJsArray1D(accessor, accessorCache) {
|
|
4188
|
+
if (accessorCache.has(accessor)) {
|
|
4189
|
+
return accessorCache.get(accessor);
|
|
4022
4190
|
}
|
|
4023
|
-
|
|
4191
|
+
const { typedArray: array, components } = accessorToTypedArray(accessor);
|
|
4192
|
+
assert3(components === 1, "accessorToJsArray1D must have exactly 1 component");
|
|
4193
|
+
const result = Array.from(array);
|
|
4194
|
+
accessorCache.set(accessor, result);
|
|
4195
|
+
return result;
|
|
4024
4196
|
}
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
if (ArrayBuffer.isView(object) || object instanceof ArrayBuffer || object instanceof ImageBitmap) {
|
|
4029
|
-
return object;
|
|
4197
|
+
function accessorToJsArray2D(accessor, accessorCache) {
|
|
4198
|
+
if (accessorCache.has(accessor)) {
|
|
4199
|
+
return accessorCache.get(accessor);
|
|
4030
4200
|
}
|
|
4031
|
-
|
|
4032
|
-
|
|
4201
|
+
const { typedArray: array, components } = accessorToTypedArray(accessor);
|
|
4202
|
+
assert3(components > 1, "accessorToJsArray2D must have more than 1 component");
|
|
4203
|
+
const result = [];
|
|
4204
|
+
for (let i = 0; i < array.length; i += components) {
|
|
4205
|
+
result.push(Array.from(array.slice(i, i + components)));
|
|
4033
4206
|
}
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4207
|
+
accessorCache.set(accessor, result);
|
|
4208
|
+
return result;
|
|
4209
|
+
}
|
|
4210
|
+
function assert3(condition, message) {
|
|
4211
|
+
if (!condition) {
|
|
4212
|
+
throw new Error(message);
|
|
4040
4213
|
}
|
|
4041
|
-
return object;
|
|
4042
4214
|
}
|
|
4043
4215
|
|
|
4044
4216
|
// src/gltf/create-scenegraph-from-gltf.ts
|
|
4045
4217
|
function createScenegraphsFromGLTF(device, gltf, options) {
|
|
4046
|
-
|
|
4047
|
-
|
|
4218
|
+
const { scenes, gltfMeshIdToNodeMap, gltfNodeIdToNodeMap, gltfNodeIndexToNodeMap } = parseGLTF(
|
|
4219
|
+
device,
|
|
4220
|
+
gltf,
|
|
4221
|
+
options
|
|
4222
|
+
);
|
|
4048
4223
|
const animations = parseGLTFAnimations(gltf);
|
|
4049
|
-
const animator = new GLTFAnimator({ animations });
|
|
4224
|
+
const animator = new GLTFAnimator({ animations, gltfNodeIdToNodeMap });
|
|
4050
4225
|
const lights = parseGLTFLights(gltf);
|
|
4051
|
-
return {
|
|
4226
|
+
return {
|
|
4227
|
+
scenes,
|
|
4228
|
+
animator,
|
|
4229
|
+
lights,
|
|
4230
|
+
gltfMeshIdToNodeMap,
|
|
4231
|
+
gltfNodeIdToNodeMap,
|
|
4232
|
+
gltfNodeIndexToNodeMap,
|
|
4233
|
+
gltf
|
|
4234
|
+
};
|
|
4052
4235
|
}
|
|
4053
4236
|
return __toCommonJS(bundle_exports);
|
|
4054
4237
|
})();
|