@luma.gl/gltf 9.3.0-alpha.8 → 9.3.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/dist.dev.js +4396 -3081
- package/dist/dist.min.js +33 -14
- package/dist/gltf/animations/animations.d.ts +43 -3
- package/dist/gltf/animations/animations.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.d.ts +2 -0
- package/dist/gltf/animations/interpolate.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.js +27 -22
- package/dist/gltf/animations/interpolate.js.map +1 -1
- package/dist/gltf/create-gltf-model.d.ts.map +1 -1
- package/dist/gltf/create-gltf-model.js +29 -10
- package/dist/gltf/create-gltf-model.js.map +1 -1
- package/dist/gltf/create-scenegraph-from-gltf.js +2 -2
- package/dist/gltf/create-scenegraph-from-gltf.js.map +1 -1
- package/dist/gltf/gltf-animator.d.ts +12 -1
- package/dist/gltf/gltf-animator.d.ts.map +1 -1
- package/dist/gltf/gltf-animator.js +98 -6
- package/dist/gltf/gltf-animator.js.map +1 -1
- package/dist/gltf/gltf-extension-support.d.ts +3 -0
- package/dist/gltf/gltf-extension-support.d.ts.map +1 -1
- package/dist/gltf/gltf-extension-support.js +10 -5
- package/dist/gltf/gltf-extension-support.js.map +1 -1
- package/dist/index.cjs +763 -272
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/parsers/parse-gltf-animations.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-animations.js +319 -18
- package/dist/parsers/parse-gltf-animations.js.map +1 -1
- package/dist/parsers/parse-gltf-lights.d.ts +6 -2
- package/dist/parsers/parse-gltf-lights.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-lights.js +9 -6
- package/dist/parsers/parse-gltf-lights.js.map +1 -1
- package/dist/parsers/parse-gltf.d.ts +2 -0
- package/dist/parsers/parse-gltf.d.ts.map +1 -1
- package/dist/parsers/parse-gltf.js +21 -7
- package/dist/parsers/parse-gltf.js.map +1 -1
- package/dist/parsers/parse-pbr-material.d.ts.map +1 -1
- package/dist/parsers/parse-pbr-material.js +114 -81
- package/dist/parsers/parse-pbr-material.js.map +1 -1
- package/dist/pbr/pbr-environment.d.ts.map +1 -1
- package/dist/pbr/pbr-environment.js +7 -3
- package/dist/pbr/pbr-environment.js.map +1 -1
- package/dist/pbr/texture-transform.d.ts +24 -0
- package/dist/pbr/texture-transform.d.ts.map +1 -0
- package/dist/pbr/texture-transform.js +98 -0
- package/dist/pbr/texture-transform.js.map +1 -0
- package/dist/webgl-to-webgpu/convert-webgl-topology.js +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-topology.js.map +1 -1
- package/package.json +5 -5
- package/src/gltf/animations/animations.ts +73 -3
- package/src/gltf/animations/interpolate.ts +50 -43
- package/src/gltf/create-gltf-model.ts +29 -10
- package/src/gltf/create-scenegraph-from-gltf.ts +2 -2
- package/src/gltf/gltf-animator.ts +177 -8
- package/src/gltf/gltf-extension-support.ts +17 -5
- package/src/index.ts +1 -1
- package/src/parsers/parse-gltf-animations.ts +461 -21
- package/src/parsers/parse-gltf-lights.ts +27 -8
- package/src/parsers/parse-gltf.ts +23 -7
- package/src/parsers/parse-pbr-material.ts +184 -79
- package/src/pbr/pbr-environment.ts +10 -3
- package/src/pbr/texture-transform.ts +263 -0
- package/src/webgl-to-webgpu/convert-webgl-topology.ts +1 -1
package/dist/index.cjs
CHANGED
|
@@ -43,11 +43,11 @@ function loadPBREnvironment(device, props) {
|
|
|
43
43
|
magFilter: "linear"
|
|
44
44
|
},
|
|
45
45
|
// Texture accepts a promise that returns an image as data (Async Textures)
|
|
46
|
-
data: (0, import_textures.loadImageTexture)(props.brdfLutUrl)
|
|
46
|
+
data: (0, import_textures.loadImageTexture)(resolveTextureUrl(props.brdfLutUrl))
|
|
47
47
|
});
|
|
48
48
|
const diffuseEnvSampler = makeCube(device, {
|
|
49
49
|
id: "DiffuseEnvSampler",
|
|
50
|
-
getTextureForFace: (face) => (0, import_textures.loadImageTexture)(props.getTexUrl("diffuse", FACES.indexOf(face), 0)),
|
|
50
|
+
getTextureForFace: (face) => (0, import_textures.loadImageTexture)(resolveTextureUrl(props.getTexUrl("diffuse", FACES.indexOf(face), 0))),
|
|
51
51
|
sampler: {
|
|
52
52
|
addressModeU: "clamp-to-edge",
|
|
53
53
|
addressModeV: "clamp-to-edge",
|
|
@@ -61,7 +61,7 @@ function loadPBREnvironment(device, props) {
|
|
|
61
61
|
const imageArray = [];
|
|
62
62
|
const direction = FACES.indexOf(face);
|
|
63
63
|
for (let lod = 0; lod < specularMipLevels; lod++) {
|
|
64
|
-
imageArray.push((0, import_textures.loadImageTexture)(props.getTexUrl("specular", direction, lod)));
|
|
64
|
+
imageArray.push((0, import_textures.loadImageTexture)(resolveTextureUrl(props.getTexUrl("specular", direction, lod))));
|
|
65
65
|
}
|
|
66
66
|
return Promise.all(imageArray);
|
|
67
67
|
},
|
|
@@ -80,6 +80,11 @@ function loadPBREnvironment(device, props) {
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
var FACES = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
|
|
83
|
+
function resolveTextureUrl(url) {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
const baseUrl = ((_a = globalThis.document) == null ? void 0 : _a.baseURI) ?? ((_b = globalThis.location) == null ? void 0 : _b.href);
|
|
86
|
+
return baseUrl ? new URL(url, baseUrl).toString() : url;
|
|
87
|
+
}
|
|
83
88
|
function makeCube(device, { id, getTextureForFace, sampler }) {
|
|
84
89
|
const data = Promise.all(FACES.map((face) => getTextureForFace(face))).then((faceDataArray) => {
|
|
85
90
|
const cubeData = {};
|
|
@@ -98,7 +103,7 @@ function makeCube(device, { id, getTextureForFace, sampler }) {
|
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
// dist/parsers/parse-pbr-material.js
|
|
101
|
-
var
|
|
106
|
+
var import_core2 = require("@luma.gl/core");
|
|
102
107
|
|
|
103
108
|
// dist/webgl-to-webgpu/gltf-webgl-constants.js
|
|
104
109
|
var GLEnum;
|
|
@@ -179,6 +184,87 @@ function convertSamplerMinFilter(mode) {
|
|
|
179
184
|
}
|
|
180
185
|
}
|
|
181
186
|
|
|
187
|
+
// dist/pbr/texture-transform.js
|
|
188
|
+
var import_core = require("@math.gl/core");
|
|
189
|
+
var TEXTURE_TRANSFORM_SLOT_DEFINITIONS = [
|
|
190
|
+
createTextureTransformSlotDefinition("baseColor", "pbr_baseColorSampler", "baseColorTexture", [
|
|
191
|
+
"pbrMetallicRoughness",
|
|
192
|
+
"baseColorTexture"
|
|
193
|
+
]),
|
|
194
|
+
createTextureTransformSlotDefinition("metallicRoughness", "pbr_metallicRoughnessSampler", "metallicRoughnessTexture", ["pbrMetallicRoughness", "metallicRoughnessTexture"]),
|
|
195
|
+
createTextureTransformSlotDefinition("normal", "pbr_normalSampler", "normalTexture", [
|
|
196
|
+
"normalTexture"
|
|
197
|
+
]),
|
|
198
|
+
createTextureTransformSlotDefinition("occlusion", "pbr_occlusionSampler", "occlusionTexture", [
|
|
199
|
+
"occlusionTexture"
|
|
200
|
+
]),
|
|
201
|
+
createTextureTransformSlotDefinition("emissive", "pbr_emissiveSampler", "emissiveTexture", [
|
|
202
|
+
"emissiveTexture"
|
|
203
|
+
]),
|
|
204
|
+
createTextureTransformSlotDefinition("specularColor", "pbr_specularColorSampler", "KHR_materials_specular.specularColorTexture", ["extensions", "KHR_materials_specular", "specularColorTexture"]),
|
|
205
|
+
createTextureTransformSlotDefinition("specularIntensity", "pbr_specularIntensitySampler", "KHR_materials_specular.specularTexture", ["extensions", "KHR_materials_specular", "specularTexture"]),
|
|
206
|
+
createTextureTransformSlotDefinition("transmission", "pbr_transmissionSampler", "KHR_materials_transmission.transmissionTexture", ["extensions", "KHR_materials_transmission", "transmissionTexture"]),
|
|
207
|
+
createTextureTransformSlotDefinition("thickness", "pbr_thicknessSampler", "KHR_materials_volume.thicknessTexture", ["extensions", "KHR_materials_volume", "thicknessTexture"]),
|
|
208
|
+
createTextureTransformSlotDefinition("clearcoat", "pbr_clearcoatSampler", "KHR_materials_clearcoat.clearcoatTexture", ["extensions", "KHR_materials_clearcoat", "clearcoatTexture"]),
|
|
209
|
+
createTextureTransformSlotDefinition("clearcoatRoughness", "pbr_clearcoatRoughnessSampler", "KHR_materials_clearcoat.clearcoatRoughnessTexture", ["extensions", "KHR_materials_clearcoat", "clearcoatRoughnessTexture"]),
|
|
210
|
+
createTextureTransformSlotDefinition("clearcoatNormal", "pbr_clearcoatNormalSampler", "KHR_materials_clearcoat.clearcoatNormalTexture", ["extensions", "KHR_materials_clearcoat", "clearcoatNormalTexture"]),
|
|
211
|
+
createTextureTransformSlotDefinition("sheenColor", "pbr_sheenColorSampler", "KHR_materials_sheen.sheenColorTexture", ["extensions", "KHR_materials_sheen", "sheenColorTexture"]),
|
|
212
|
+
createTextureTransformSlotDefinition("sheenRoughness", "pbr_sheenRoughnessSampler", "KHR_materials_sheen.sheenRoughnessTexture", ["extensions", "KHR_materials_sheen", "sheenRoughnessTexture"]),
|
|
213
|
+
createTextureTransformSlotDefinition("iridescence", "pbr_iridescenceSampler", "KHR_materials_iridescence.iridescenceTexture", ["extensions", "KHR_materials_iridescence", "iridescenceTexture"]),
|
|
214
|
+
createTextureTransformSlotDefinition("iridescenceThickness", "pbr_iridescenceThicknessSampler", "KHR_materials_iridescence.iridescenceThicknessTexture", ["extensions", "KHR_materials_iridescence", "iridescenceThicknessTexture"]),
|
|
215
|
+
createTextureTransformSlotDefinition("anisotropy", "pbr_anisotropySampler", "KHR_materials_anisotropy.anisotropyTexture", ["extensions", "KHR_materials_anisotropy", "anisotropyTexture"])
|
|
216
|
+
];
|
|
217
|
+
var TEXTURE_TRANSFORM_SLOT_DEFINITION_MAP = new Map(TEXTURE_TRANSFORM_SLOT_DEFINITIONS.map((definition) => [definition.slot, definition]));
|
|
218
|
+
function createTextureTransformSlotDefinition(slot, binding, displayName, pathSegments) {
|
|
219
|
+
return {
|
|
220
|
+
slot,
|
|
221
|
+
binding,
|
|
222
|
+
displayName,
|
|
223
|
+
pathSegments,
|
|
224
|
+
uvSetUniform: `${slot}UVSet`,
|
|
225
|
+
uvTransformUniform: `${slot}UVTransform`
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function getTextureTransformSlotDefinitions() {
|
|
229
|
+
return TEXTURE_TRANSFORM_SLOT_DEFINITIONS;
|
|
230
|
+
}
|
|
231
|
+
function getTextureTransformSlotDefinition(slot) {
|
|
232
|
+
const definition = TEXTURE_TRANSFORM_SLOT_DEFINITION_MAP.get(slot);
|
|
233
|
+
if (!definition) {
|
|
234
|
+
throw new Error(`Unknown PBR texture transform slot ${slot}`);
|
|
235
|
+
}
|
|
236
|
+
return definition;
|
|
237
|
+
}
|
|
238
|
+
function resolveTextureTransform(textureInfo) {
|
|
239
|
+
var _a;
|
|
240
|
+
const extensionTextureTransform = (_a = textureInfo == null ? void 0 : textureInfo["extensions"]) == null ? void 0 : _a["KHR_texture_transform"];
|
|
241
|
+
return {
|
|
242
|
+
offset: (extensionTextureTransform == null ? void 0 : extensionTextureTransform.offset) ? [extensionTextureTransform.offset[0], extensionTextureTransform.offset[1]] : [0, 0],
|
|
243
|
+
rotation: (extensionTextureTransform == null ? void 0 : extensionTextureTransform.rotation) ?? 0,
|
|
244
|
+
scale: (extensionTextureTransform == null ? void 0 : extensionTextureTransform.scale) ? [extensionTextureTransform.scale[0], extensionTextureTransform.scale[1]] : [1, 1]
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function resolveTextureCoordinateSet(textureInfo) {
|
|
248
|
+
var _a;
|
|
249
|
+
const extensionTextureTransform = (_a = textureInfo == null ? void 0 : textureInfo["extensions"]) == null ? void 0 : _a["KHR_texture_transform"];
|
|
250
|
+
return (extensionTextureTransform == null ? void 0 : extensionTextureTransform["texCoord"]) ?? (textureInfo == null ? void 0 : textureInfo["texCoord"]) ?? 0;
|
|
251
|
+
}
|
|
252
|
+
function resolveTextureTransformSlot(pointerSegments) {
|
|
253
|
+
return TEXTURE_TRANSFORM_SLOT_DEFINITIONS.find((definition) => definition.pathSegments.length === pointerSegments.length && definition.pathSegments.every((segment, index) => pointerSegments[index] === segment)) || null;
|
|
254
|
+
}
|
|
255
|
+
function getTextureTransformMatrix(transform) {
|
|
256
|
+
const translationMatrix = new import_core.Matrix3().set(1, 0, 0, 0, 1, 0, transform.offset[0], transform.offset[1], 1);
|
|
257
|
+
const rotationMatrix = new import_core.Matrix3().set(Math.cos(transform.rotation), Math.sin(transform.rotation), 0, -Math.sin(transform.rotation), Math.cos(transform.rotation), 0, 0, 0, 1);
|
|
258
|
+
const scaleMatrix = new import_core.Matrix3().set(transform.scale[0], 0, 0, 0, transform.scale[1], 0, 0, 0, 1);
|
|
259
|
+
return Array.from(translationMatrix.multiplyRight(rotationMatrix).multiplyRight(scaleMatrix));
|
|
260
|
+
}
|
|
261
|
+
function getTextureTransformDeltaMatrix(baseTransform, currentTransform) {
|
|
262
|
+
const baseMatrix = new import_core.Matrix3(getTextureTransformMatrix(baseTransform));
|
|
263
|
+
const currentMatrix = new import_core.Matrix3(getTextureTransformMatrix(currentTransform));
|
|
264
|
+
const inverseBaseMatrix = new import_core.Matrix3(baseMatrix).invert();
|
|
265
|
+
return Array.from(currentMatrix.multiplyRight(inverseBaseMatrix));
|
|
266
|
+
}
|
|
267
|
+
|
|
182
268
|
// dist/parsers/parse-pbr-material.js
|
|
183
269
|
function parsePBRMaterial(device, material, attributes, options) {
|
|
184
270
|
const parsedMaterial = {
|
|
@@ -219,6 +305,8 @@ function parsePBRMaterial(device, material, attributes, options) {
|
|
|
219
305
|
parsedMaterial.defines["HAS_TANGENTS"] = true;
|
|
220
306
|
if (attributes["TEXCOORD_0"])
|
|
221
307
|
parsedMaterial.defines["HAS_UV"] = true;
|
|
308
|
+
if (attributes["TEXCOORD_1"])
|
|
309
|
+
parsedMaterial.defines["HAS_UV_1"] = true;
|
|
222
310
|
if (attributes["JOINTS_0"] && attributes["WEIGHTS_0"])
|
|
223
311
|
parsedMaterial.defines["HAS_SKIN"] = true;
|
|
224
312
|
if (attributes["COLOR_0"])
|
|
@@ -231,75 +319,55 @@ function parsePBRMaterial(device, material, attributes, options) {
|
|
|
231
319
|
if (options.validateAttributes !== false) {
|
|
232
320
|
warnOnMissingExpectedAttributes(material, attributes);
|
|
233
321
|
}
|
|
234
|
-
parseMaterial(device, material, parsedMaterial, options.gltf);
|
|
322
|
+
parseMaterial(device, material, parsedMaterial, attributes, options.gltf);
|
|
235
323
|
}
|
|
236
324
|
return parsedMaterial;
|
|
237
325
|
}
|
|
238
326
|
function warnOnMissingExpectedAttributes(material, attributes) {
|
|
239
327
|
var _a;
|
|
240
|
-
const uvDependentTextureSlots = getUvDependentTextureSlots(material);
|
|
328
|
+
const uvDependentTextureSlots = getUvDependentTextureSlots(material, 0);
|
|
241
329
|
if (uvDependentTextureSlots.length > 0 && !attributes["TEXCOORD_0"]) {
|
|
242
|
-
|
|
330
|
+
import_core2.log.warn(`glTF material uses ${uvDependentTextureSlots.join(", ")} but primitive is missing TEXCOORD_0; textured shading will sample the default UV coordinates`)();
|
|
331
|
+
}
|
|
332
|
+
const uv1DependentTextureSlots = getUvDependentTextureSlots(material, 1);
|
|
333
|
+
if (uv1DependentTextureSlots.length > 0 && !attributes["TEXCOORD_1"]) {
|
|
334
|
+
import_core2.log.warn(`glTF material uses ${uv1DependentTextureSlots.join(", ")} with TEXCOORD_1 but primitive is missing TEXCOORD_1; those textures will be skipped`)();
|
|
243
335
|
}
|
|
244
336
|
const isUnlitMaterial = Boolean(material.unlit || ((_a = material.extensions) == null ? void 0 : _a.KHR_materials_unlit));
|
|
245
337
|
if (isUnlitMaterial || attributes["NORMAL"]) {
|
|
246
338
|
return;
|
|
247
339
|
}
|
|
248
340
|
const missingNormalReason = material.normalTexture ? "lit PBR shading with normalTexture" : "lit PBR shading";
|
|
249
|
-
|
|
341
|
+
import_core2.log.warn(`glTF primitive is missing NORMAL while using ${missingNormalReason}; shading will fall back to geometric normals`)();
|
|
250
342
|
}
|
|
251
|
-
function getUvDependentTextureSlots(material) {
|
|
252
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
|
|
343
|
+
function getUvDependentTextureSlots(material, textureCoordinateSet) {
|
|
253
344
|
const uvDependentTextureSlots = [];
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
if (material.occlusionTexture) {
|
|
264
|
-
uvDependentTextureSlots.push("occlusionTexture");
|
|
265
|
-
}
|
|
266
|
-
if (material.emissiveTexture) {
|
|
267
|
-
uvDependentTextureSlots.push("emissiveTexture");
|
|
268
|
-
}
|
|
269
|
-
if ((_d = (_c = material.extensions) == null ? void 0 : _c.KHR_materials_specular) == null ? void 0 : _d.specularTexture) {
|
|
270
|
-
uvDependentTextureSlots.push("KHR_materials_specular.specularTexture");
|
|
271
|
-
}
|
|
272
|
-
if ((_f = (_e = material.extensions) == null ? void 0 : _e.KHR_materials_specular) == null ? void 0 : _f.specularColorTexture) {
|
|
273
|
-
uvDependentTextureSlots.push("KHR_materials_specular.specularColorTexture");
|
|
274
|
-
}
|
|
275
|
-
if ((_h = (_g = material.extensions) == null ? void 0 : _g.KHR_materials_transmission) == null ? void 0 : _h.transmissionTexture) {
|
|
276
|
-
uvDependentTextureSlots.push("KHR_materials_transmission.transmissionTexture");
|
|
277
|
-
}
|
|
278
|
-
if ((_j = (_i = material.extensions) == null ? void 0 : _i.KHR_materials_clearcoat) == null ? void 0 : _j.clearcoatTexture) {
|
|
279
|
-
uvDependentTextureSlots.push("KHR_materials_clearcoat.clearcoatTexture");
|
|
280
|
-
}
|
|
281
|
-
if ((_l = (_k = material.extensions) == null ? void 0 : _k.KHR_materials_clearcoat) == null ? void 0 : _l.clearcoatRoughnessTexture) {
|
|
282
|
-
uvDependentTextureSlots.push("KHR_materials_clearcoat.clearcoatRoughnessTexture");
|
|
283
|
-
}
|
|
284
|
-
if ((_n = (_m = material.extensions) == null ? void 0 : _m.KHR_materials_sheen) == null ? void 0 : _n.sheenColorTexture) {
|
|
285
|
-
uvDependentTextureSlots.push("KHR_materials_sheen.sheenColorTexture");
|
|
286
|
-
}
|
|
287
|
-
if ((_p = (_o = material.extensions) == null ? void 0 : _o.KHR_materials_sheen) == null ? void 0 : _p.sheenRoughnessTexture) {
|
|
288
|
-
uvDependentTextureSlots.push("KHR_materials_sheen.sheenRoughnessTexture");
|
|
289
|
-
}
|
|
290
|
-
if ((_r = (_q = material.extensions) == null ? void 0 : _q.KHR_materials_iridescence) == null ? void 0 : _r.iridescenceTexture) {
|
|
291
|
-
uvDependentTextureSlots.push("KHR_materials_iridescence.iridescenceTexture");
|
|
292
|
-
}
|
|
293
|
-
if ((_t = (_s = material.extensions) == null ? void 0 : _s.KHR_materials_anisotropy) == null ? void 0 : _t.anisotropyTexture) {
|
|
294
|
-
uvDependentTextureSlots.push("KHR_materials_anisotropy.anisotropyTexture");
|
|
345
|
+
for (const slotDefinition of getTextureTransformSlotDefinitions()) {
|
|
346
|
+
const textureInfo = getNestedTextureInfo(material, slotDefinition.pathSegments);
|
|
347
|
+
if (!textureInfo) {
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
if (resolveTextureCoordinateSet(textureInfo) === textureCoordinateSet) {
|
|
351
|
+
uvDependentTextureSlots.push(slotDefinition.displayName);
|
|
352
|
+
}
|
|
295
353
|
}
|
|
296
354
|
return uvDependentTextureSlots;
|
|
297
355
|
}
|
|
298
|
-
function
|
|
356
|
+
function getNestedTextureInfo(material, pathSegments) {
|
|
357
|
+
let value = material;
|
|
358
|
+
for (const pathSegment of pathSegments) {
|
|
359
|
+
value = value == null ? void 0 : value[pathSegment];
|
|
360
|
+
if (!value) {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return value;
|
|
365
|
+
}
|
|
366
|
+
function parseMaterial(device, material, parsedMaterial, attributes, gltf) {
|
|
299
367
|
var _a;
|
|
300
368
|
parsedMaterial.uniforms.unlit = Boolean(material.unlit || ((_a = material.extensions) == null ? void 0 : _a.KHR_materials_unlit));
|
|
301
369
|
if (material.pbrMetallicRoughness) {
|
|
302
|
-
parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial, gltf);
|
|
370
|
+
parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial, attributes, gltf);
|
|
303
371
|
}
|
|
304
372
|
if (material.normalTexture) {
|
|
305
373
|
addTexture(device, material.normalTexture, "pbr_normalSampler", parsedMaterial, {
|
|
@@ -307,7 +375,9 @@ function parseMaterial(device, material, parsedMaterial, gltf) {
|
|
|
307
375
|
define: "HAS_NORMALMAP",
|
|
308
376
|
enabledUniformName: "normalMapEnabled"
|
|
309
377
|
},
|
|
310
|
-
gltf
|
|
378
|
+
gltf,
|
|
379
|
+
attributes,
|
|
380
|
+
textureTransformSlot: "normal"
|
|
311
381
|
});
|
|
312
382
|
const { scale = 1 } = material.normalTexture;
|
|
313
383
|
parsedMaterial.uniforms.normalScale = scale;
|
|
@@ -318,7 +388,9 @@ function parseMaterial(device, material, parsedMaterial, gltf) {
|
|
|
318
388
|
define: "HAS_OCCLUSIONMAP",
|
|
319
389
|
enabledUniformName: "occlusionMapEnabled"
|
|
320
390
|
},
|
|
321
|
-
gltf
|
|
391
|
+
gltf,
|
|
392
|
+
attributes,
|
|
393
|
+
textureTransformSlot: "occlusion"
|
|
322
394
|
});
|
|
323
395
|
const { strength = 1 } = material.occlusionTexture;
|
|
324
396
|
parsedMaterial.uniforms.occlusionStrength = strength;
|
|
@@ -330,10 +402,12 @@ function parseMaterial(device, material, parsedMaterial, gltf) {
|
|
|
330
402
|
define: "HAS_EMISSIVEMAP",
|
|
331
403
|
enabledUniformName: "emissiveMapEnabled"
|
|
332
404
|
},
|
|
333
|
-
gltf
|
|
405
|
+
gltf,
|
|
406
|
+
attributes,
|
|
407
|
+
textureTransformSlot: "emissive"
|
|
334
408
|
});
|
|
335
409
|
}
|
|
336
|
-
parseMaterialExtensions(device, material.extensions, parsedMaterial, gltf);
|
|
410
|
+
parseMaterialExtensions(device, material.extensions, parsedMaterial, gltf, attributes);
|
|
337
411
|
switch (material.alphaMode || "OPAQUE") {
|
|
338
412
|
case "OPAQUE":
|
|
339
413
|
break;
|
|
@@ -345,7 +419,7 @@ function parseMaterial(device, material, parsedMaterial, gltf) {
|
|
|
345
419
|
break;
|
|
346
420
|
}
|
|
347
421
|
case "BLEND":
|
|
348
|
-
|
|
422
|
+
import_core2.log.warn("glTF BLEND alphaMode might not work well because it requires mesh sorting")();
|
|
349
423
|
applyAlphaBlendParameters(parsedMaterial);
|
|
350
424
|
break;
|
|
351
425
|
}
|
|
@@ -386,14 +460,16 @@ function applyTransmissionBlendApproximation(parsedMaterial) {
|
|
|
386
460
|
GLEnum.ONE_MINUS_SRC_ALPHA
|
|
387
461
|
];
|
|
388
462
|
}
|
|
389
|
-
function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial, gltf) {
|
|
463
|
+
function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial, attributes, gltf) {
|
|
390
464
|
if (pbrMetallicRoughness.baseColorTexture) {
|
|
391
465
|
addTexture(device, pbrMetallicRoughness.baseColorTexture, "pbr_baseColorSampler", parsedMaterial, {
|
|
392
466
|
featureOptions: {
|
|
393
467
|
define: "HAS_BASECOLORMAP",
|
|
394
468
|
enabledUniformName: "baseColorMapEnabled"
|
|
395
469
|
},
|
|
396
|
-
gltf
|
|
470
|
+
gltf,
|
|
471
|
+
attributes,
|
|
472
|
+
textureTransformSlot: "baseColor"
|
|
397
473
|
});
|
|
398
474
|
}
|
|
399
475
|
parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
|
|
@@ -403,33 +479,35 @@ function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial,
|
|
|
403
479
|
define: "HAS_METALROUGHNESSMAP",
|
|
404
480
|
enabledUniformName: "metallicRoughnessMapEnabled"
|
|
405
481
|
},
|
|
406
|
-
gltf
|
|
482
|
+
gltf,
|
|
483
|
+
attributes,
|
|
484
|
+
textureTransformSlot: "metallicRoughness"
|
|
407
485
|
});
|
|
408
486
|
}
|
|
409
487
|
const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
|
|
410
488
|
parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
|
|
411
489
|
}
|
|
412
|
-
function parseMaterialExtensions(device, extensions, parsedMaterial, gltf) {
|
|
490
|
+
function parseMaterialExtensions(device, extensions, parsedMaterial, gltf, attributes = {}) {
|
|
413
491
|
if (!extensions) {
|
|
414
492
|
return;
|
|
415
493
|
}
|
|
416
494
|
if (hasMaterialExtensionShading(extensions)) {
|
|
417
495
|
parsedMaterial.defines["USE_MATERIAL_EXTENSIONS"] = true;
|
|
418
496
|
}
|
|
419
|
-
parseSpecularExtension(device, extensions.KHR_materials_specular, parsedMaterial, gltf);
|
|
497
|
+
parseSpecularExtension(device, extensions.KHR_materials_specular, parsedMaterial, gltf, attributes);
|
|
420
498
|
parseIorExtension(extensions.KHR_materials_ior, parsedMaterial);
|
|
421
|
-
parseTransmissionExtension(device, extensions.KHR_materials_transmission, parsedMaterial, gltf);
|
|
422
|
-
parseVolumeExtension(device, extensions.KHR_materials_volume, parsedMaterial, gltf);
|
|
423
|
-
parseClearcoatExtension(device, extensions.KHR_materials_clearcoat, parsedMaterial, gltf);
|
|
424
|
-
parseSheenExtension(device, extensions.KHR_materials_sheen, parsedMaterial, gltf);
|
|
425
|
-
parseIridescenceExtension(device, extensions.KHR_materials_iridescence, parsedMaterial, gltf);
|
|
426
|
-
parseAnisotropyExtension(device, extensions.KHR_materials_anisotropy, parsedMaterial, gltf);
|
|
499
|
+
parseTransmissionExtension(device, extensions.KHR_materials_transmission, parsedMaterial, gltf, attributes);
|
|
500
|
+
parseVolumeExtension(device, extensions.KHR_materials_volume, parsedMaterial, gltf, attributes);
|
|
501
|
+
parseClearcoatExtension(device, extensions.KHR_materials_clearcoat, parsedMaterial, gltf, attributes);
|
|
502
|
+
parseSheenExtension(device, extensions.KHR_materials_sheen, parsedMaterial, gltf, attributes);
|
|
503
|
+
parseIridescenceExtension(device, extensions.KHR_materials_iridescence, parsedMaterial, gltf, attributes);
|
|
504
|
+
parseAnisotropyExtension(device, extensions.KHR_materials_anisotropy, parsedMaterial, gltf, attributes);
|
|
427
505
|
parseEmissiveStrengthExtension(extensions.KHR_materials_emissive_strength, parsedMaterial);
|
|
428
506
|
}
|
|
429
507
|
function hasMaterialExtensionShading(extensions) {
|
|
430
508
|
return Boolean(extensions.KHR_materials_specular || extensions.KHR_materials_ior || extensions.KHR_materials_transmission || extensions.KHR_materials_volume || extensions.KHR_materials_clearcoat || extensions.KHR_materials_sheen || extensions.KHR_materials_iridescence || extensions.KHR_materials_anisotropy);
|
|
431
509
|
}
|
|
432
|
-
function parseSpecularExtension(device, extension, parsedMaterial, gltf) {
|
|
510
|
+
function parseSpecularExtension(device, extension, parsedMaterial, gltf, attributes = {}) {
|
|
433
511
|
if (!extension) {
|
|
434
512
|
return;
|
|
435
513
|
}
|
|
@@ -445,7 +523,9 @@ function parseSpecularExtension(device, extension, parsedMaterial, gltf) {
|
|
|
445
523
|
define: "HAS_SPECULARCOLORMAP",
|
|
446
524
|
enabledUniformName: "specularColorMapEnabled"
|
|
447
525
|
},
|
|
448
|
-
gltf
|
|
526
|
+
gltf,
|
|
527
|
+
attributes,
|
|
528
|
+
textureTransformSlot: "specularColor"
|
|
449
529
|
});
|
|
450
530
|
}
|
|
451
531
|
if (extension.specularTexture) {
|
|
@@ -454,7 +534,9 @@ function parseSpecularExtension(device, extension, parsedMaterial, gltf) {
|
|
|
454
534
|
define: "HAS_SPECULARINTENSITYMAP",
|
|
455
535
|
enabledUniformName: "specularIntensityMapEnabled"
|
|
456
536
|
},
|
|
457
|
-
gltf
|
|
537
|
+
gltf,
|
|
538
|
+
attributes,
|
|
539
|
+
textureTransformSlot: "specularIntensity"
|
|
458
540
|
});
|
|
459
541
|
}
|
|
460
542
|
}
|
|
@@ -463,7 +545,7 @@ function parseIorExtension(extension, parsedMaterial) {
|
|
|
463
545
|
parsedMaterial.uniforms.ior = extension.ior;
|
|
464
546
|
}
|
|
465
547
|
}
|
|
466
|
-
function parseTransmissionExtension(device, extension, parsedMaterial, gltf) {
|
|
548
|
+
function parseTransmissionExtension(device, extension, parsedMaterial, gltf, attributes = {}) {
|
|
467
549
|
if (!extension) {
|
|
468
550
|
return;
|
|
469
551
|
}
|
|
@@ -476,15 +558,17 @@ function parseTransmissionExtension(device, extension, parsedMaterial, gltf) {
|
|
|
476
558
|
define: "HAS_TRANSMISSIONMAP",
|
|
477
559
|
enabledUniformName: "transmissionMapEnabled"
|
|
478
560
|
},
|
|
479
|
-
gltf
|
|
561
|
+
gltf,
|
|
562
|
+
attributes,
|
|
563
|
+
textureTransformSlot: "transmission"
|
|
480
564
|
});
|
|
481
565
|
}
|
|
482
566
|
if ((extension.transmissionFactor ?? 0) > 0 || extension.transmissionTexture) {
|
|
483
|
-
|
|
567
|
+
import_core2.log.warn("KHR_materials_transmission uses a premultiplied-alpha blending approximation and may require mesh sorting")();
|
|
484
568
|
applyTransmissionBlendApproximation(parsedMaterial);
|
|
485
569
|
}
|
|
486
570
|
}
|
|
487
|
-
function parseVolumeExtension(device, extension, parsedMaterial, gltf) {
|
|
571
|
+
function parseVolumeExtension(device, extension, parsedMaterial, gltf, attributes = {}) {
|
|
488
572
|
if (!extension) {
|
|
489
573
|
return;
|
|
490
574
|
}
|
|
@@ -496,7 +580,9 @@ function parseVolumeExtension(device, extension, parsedMaterial, gltf) {
|
|
|
496
580
|
featureOptions: {
|
|
497
581
|
define: "HAS_THICKNESSMAP"
|
|
498
582
|
},
|
|
499
|
-
gltf
|
|
583
|
+
gltf,
|
|
584
|
+
attributes,
|
|
585
|
+
textureTransformSlot: "thickness"
|
|
500
586
|
});
|
|
501
587
|
}
|
|
502
588
|
if (extension.attenuationDistance !== void 0) {
|
|
@@ -506,7 +592,7 @@ function parseVolumeExtension(device, extension, parsedMaterial, gltf) {
|
|
|
506
592
|
parsedMaterial.uniforms.attenuationColor = extension.attenuationColor;
|
|
507
593
|
}
|
|
508
594
|
}
|
|
509
|
-
function parseClearcoatExtension(device, extension, parsedMaterial, gltf) {
|
|
595
|
+
function parseClearcoatExtension(device, extension, parsedMaterial, gltf, attributes = {}) {
|
|
510
596
|
if (!extension) {
|
|
511
597
|
return;
|
|
512
598
|
}
|
|
@@ -522,7 +608,9 @@ function parseClearcoatExtension(device, extension, parsedMaterial, gltf) {
|
|
|
522
608
|
define: "HAS_CLEARCOATMAP",
|
|
523
609
|
enabledUniformName: "clearcoatMapEnabled"
|
|
524
610
|
},
|
|
525
|
-
gltf
|
|
611
|
+
gltf,
|
|
612
|
+
attributes,
|
|
613
|
+
textureTransformSlot: "clearcoat"
|
|
526
614
|
});
|
|
527
615
|
}
|
|
528
616
|
if (extension.clearcoatRoughnessTexture) {
|
|
@@ -531,7 +619,9 @@ function parseClearcoatExtension(device, extension, parsedMaterial, gltf) {
|
|
|
531
619
|
define: "HAS_CLEARCOATROUGHNESSMAP",
|
|
532
620
|
enabledUniformName: "clearcoatRoughnessMapEnabled"
|
|
533
621
|
},
|
|
534
|
-
gltf
|
|
622
|
+
gltf,
|
|
623
|
+
attributes,
|
|
624
|
+
textureTransformSlot: "clearcoatRoughness"
|
|
535
625
|
});
|
|
536
626
|
}
|
|
537
627
|
if (extension.clearcoatNormalTexture) {
|
|
@@ -539,11 +629,13 @@ function parseClearcoatExtension(device, extension, parsedMaterial, gltf) {
|
|
|
539
629
|
featureOptions: {
|
|
540
630
|
define: "HAS_CLEARCOATNORMALMAP"
|
|
541
631
|
},
|
|
542
|
-
gltf
|
|
632
|
+
gltf,
|
|
633
|
+
attributes,
|
|
634
|
+
textureTransformSlot: "clearcoatNormal"
|
|
543
635
|
});
|
|
544
636
|
}
|
|
545
637
|
}
|
|
546
|
-
function parseSheenExtension(device, extension, parsedMaterial, gltf) {
|
|
638
|
+
function parseSheenExtension(device, extension, parsedMaterial, gltf, attributes = {}) {
|
|
547
639
|
if (!extension) {
|
|
548
640
|
return;
|
|
549
641
|
}
|
|
@@ -559,7 +651,9 @@ function parseSheenExtension(device, extension, parsedMaterial, gltf) {
|
|
|
559
651
|
define: "HAS_SHEENCOLORMAP",
|
|
560
652
|
enabledUniformName: "sheenColorMapEnabled"
|
|
561
653
|
},
|
|
562
|
-
gltf
|
|
654
|
+
gltf,
|
|
655
|
+
attributes,
|
|
656
|
+
textureTransformSlot: "sheenColor"
|
|
563
657
|
});
|
|
564
658
|
}
|
|
565
659
|
if (extension.sheenRoughnessTexture) {
|
|
@@ -568,11 +662,13 @@ function parseSheenExtension(device, extension, parsedMaterial, gltf) {
|
|
|
568
662
|
define: "HAS_SHEENROUGHNESSMAP",
|
|
569
663
|
enabledUniformName: "sheenRoughnessMapEnabled"
|
|
570
664
|
},
|
|
571
|
-
gltf
|
|
665
|
+
gltf,
|
|
666
|
+
attributes,
|
|
667
|
+
textureTransformSlot: "sheenRoughness"
|
|
572
668
|
});
|
|
573
669
|
}
|
|
574
670
|
}
|
|
575
|
-
function parseIridescenceExtension(device, extension, parsedMaterial, gltf) {
|
|
671
|
+
function parseIridescenceExtension(device, extension, parsedMaterial, gltf, attributes = {}) {
|
|
576
672
|
if (!extension) {
|
|
577
673
|
return;
|
|
578
674
|
}
|
|
@@ -594,7 +690,9 @@ function parseIridescenceExtension(device, extension, parsedMaterial, gltf) {
|
|
|
594
690
|
define: "HAS_IRIDESCENCEMAP",
|
|
595
691
|
enabledUniformName: "iridescenceMapEnabled"
|
|
596
692
|
},
|
|
597
|
-
gltf
|
|
693
|
+
gltf,
|
|
694
|
+
attributes,
|
|
695
|
+
textureTransformSlot: "iridescence"
|
|
598
696
|
});
|
|
599
697
|
}
|
|
600
698
|
if (extension.iridescenceThicknessTexture) {
|
|
@@ -602,11 +700,13 @@ function parseIridescenceExtension(device, extension, parsedMaterial, gltf) {
|
|
|
602
700
|
featureOptions: {
|
|
603
701
|
define: "HAS_IRIDESCENCETHICKNESSMAP"
|
|
604
702
|
},
|
|
605
|
-
gltf
|
|
703
|
+
gltf,
|
|
704
|
+
attributes,
|
|
705
|
+
textureTransformSlot: "iridescenceThickness"
|
|
606
706
|
});
|
|
607
707
|
}
|
|
608
708
|
}
|
|
609
|
-
function parseAnisotropyExtension(device, extension, parsedMaterial, gltf) {
|
|
709
|
+
function parseAnisotropyExtension(device, extension, parsedMaterial, gltf, attributes = {}) {
|
|
610
710
|
if (!extension) {
|
|
611
711
|
return;
|
|
612
712
|
}
|
|
@@ -622,7 +722,9 @@ function parseAnisotropyExtension(device, extension, parsedMaterial, gltf) {
|
|
|
622
722
|
define: "HAS_ANISOTROPYMAP",
|
|
623
723
|
enabledUniformName: "anisotropyMapEnabled"
|
|
624
724
|
},
|
|
625
|
-
gltf
|
|
725
|
+
gltf,
|
|
726
|
+
attributes,
|
|
727
|
+
textureTransformSlot: "anisotropy"
|
|
626
728
|
});
|
|
627
729
|
}
|
|
628
730
|
}
|
|
@@ -633,12 +735,21 @@ function parseEmissiveStrengthExtension(extension, parsedMaterial) {
|
|
|
633
735
|
}
|
|
634
736
|
function addTexture(device, gltfTexture, uniformName, parsedMaterial, textureParseOptions = {}) {
|
|
635
737
|
var _a, _b, _c;
|
|
636
|
-
const { featureOptions = {}, gltf } = textureParseOptions;
|
|
738
|
+
const { featureOptions = {}, gltf, attributes = {}, textureTransformSlot } = textureParseOptions;
|
|
637
739
|
const { define, enabledUniformName } = featureOptions;
|
|
740
|
+
const textureCoordinateSet = resolveTextureCoordinateSet(gltfTexture);
|
|
741
|
+
if (textureCoordinateSet > 1) {
|
|
742
|
+
import_core2.log.warn(`Skipping ${String(uniformName)} because ${textureCoordinateSet} is not supported; only TEXCOORD_0 and TEXCOORD_1 are currently available`)();
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
if (textureCoordinateSet === 1 && !attributes["TEXCOORD_1"]) {
|
|
746
|
+
import_core2.log.warn(`Skipping ${String(uniformName)} because it requires TEXCOORD_1 but the primitive does not provide TEXCOORD_1`)();
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
638
749
|
const resolvedTextureInfo = resolveTextureInfo(gltfTexture, gltf);
|
|
639
750
|
const image = (_b = (_a = resolvedTextureInfo.texture) == null ? void 0 : _a.source) == null ? void 0 : _b.image;
|
|
640
751
|
if (!image) {
|
|
641
|
-
|
|
752
|
+
import_core2.log.warn(`Skipping unresolved glTF texture for ${String(uniformName)}`)();
|
|
642
753
|
return;
|
|
643
754
|
}
|
|
644
755
|
const gltfSampler = {
|
|
@@ -674,6 +785,11 @@ function addTexture(device, gltfTexture, uniformName, parsedMaterial, texturePar
|
|
|
674
785
|
if (enabledUniformName) {
|
|
675
786
|
parsedMaterial.uniforms[enabledUniformName] = true;
|
|
676
787
|
}
|
|
788
|
+
if (textureTransformSlot) {
|
|
789
|
+
const textureTransformSlotDefinition = getTextureTransformSlotDefinition(textureTransformSlot);
|
|
790
|
+
parsedMaterial.uniforms[textureTransformSlotDefinition.uvSetUniform] = textureCoordinateSet;
|
|
791
|
+
parsedMaterial.uniforms[textureTransformSlotDefinition.uvTransformUniform] = getTextureTransformMatrix(resolveTextureTransform(gltfTexture));
|
|
792
|
+
}
|
|
677
793
|
parsedMaterial.generatedTextures.push(texture);
|
|
678
794
|
}
|
|
679
795
|
function resolveTextureInfo(gltfTexture, gltf) {
|
|
@@ -712,7 +828,7 @@ function resolveCompressedTextureFormat(level) {
|
|
|
712
828
|
return level.textureFormat;
|
|
713
829
|
}
|
|
714
830
|
function getMaxCompressedMipLevels(baseWidth, baseHeight, format) {
|
|
715
|
-
const { blockWidth = 1, blockHeight = 1 } =
|
|
831
|
+
const { blockWidth = 1, blockHeight = 1 } = import_core2.textureFormatDecoder.getInfo(format);
|
|
716
832
|
let count = 1;
|
|
717
833
|
for (let i = 1; ; i++) {
|
|
718
834
|
const w = Math.max(1, baseWidth >> i);
|
|
@@ -734,19 +850,19 @@ function createCompressedTexture(device, image, baseOptions) {
|
|
|
734
850
|
levels = [];
|
|
735
851
|
}
|
|
736
852
|
if (levels.length === 0 || !((_b = levels[0]) == null ? void 0 : _b.data)) {
|
|
737
|
-
|
|
853
|
+
import_core2.log.warn("createCompressedTexture: compressed image has no valid mip levels, creating fallback")();
|
|
738
854
|
return createCompressedTextureFallback(device, baseOptions);
|
|
739
855
|
}
|
|
740
856
|
const baseLevel = levels[0];
|
|
741
857
|
const baseWidth = baseLevel.width ?? image.width ?? 0;
|
|
742
858
|
const baseHeight = baseLevel.height ?? image.height ?? 0;
|
|
743
859
|
if (baseWidth <= 0 || baseHeight <= 0) {
|
|
744
|
-
|
|
860
|
+
import_core2.log.warn("createCompressedTexture: base level has invalid dimensions, creating fallback")();
|
|
745
861
|
return createCompressedTextureFallback(device, baseOptions);
|
|
746
862
|
}
|
|
747
863
|
const format = resolveCompressedTextureFormat(baseLevel);
|
|
748
864
|
if (!format) {
|
|
749
|
-
|
|
865
|
+
import_core2.log.warn("createCompressedTexture: compressed image has no textureFormat, creating fallback")();
|
|
750
866
|
return createCompressedTextureFallback(device, baseOptions);
|
|
751
867
|
}
|
|
752
868
|
const maxMipLevels = getMaxCompressedMipLevels(baseWidth, baseHeight, format);
|
|
@@ -755,18 +871,18 @@ function createCompressedTexture(device, image, baseOptions) {
|
|
|
755
871
|
for (let i = 1; i < levelLimit; i++) {
|
|
756
872
|
const level = levels[i];
|
|
757
873
|
if (!level.data || level.width <= 0 || level.height <= 0) {
|
|
758
|
-
|
|
874
|
+
import_core2.log.warn(`createCompressedTexture: mip level ${i} has invalid data/dimensions, truncating`)();
|
|
759
875
|
break;
|
|
760
876
|
}
|
|
761
877
|
const levelFormat = resolveCompressedTextureFormat(level);
|
|
762
878
|
if (levelFormat && levelFormat !== format) {
|
|
763
|
-
|
|
879
|
+
import_core2.log.warn(`createCompressedTexture: mip level ${i} format '${levelFormat}' differs from base '${format}', truncating`)();
|
|
764
880
|
break;
|
|
765
881
|
}
|
|
766
882
|
const expectedW = Math.max(1, baseWidth >> i);
|
|
767
883
|
const expectedH = Math.max(1, baseHeight >> i);
|
|
768
884
|
if (level.width !== expectedW || level.height !== expectedH) {
|
|
769
|
-
|
|
885
|
+
import_core2.log.warn(`createCompressedTexture: mip level ${i} dimensions ${level.width}x${level.height} don't match expected ${expectedW}x${expectedH}, truncating`)();
|
|
770
886
|
break;
|
|
771
887
|
}
|
|
772
888
|
validLevelCount++;
|
|
@@ -774,7 +890,7 @@ function createCompressedTexture(device, image, baseOptions) {
|
|
|
774
890
|
const texture = device.createTexture({
|
|
775
891
|
...baseOptions,
|
|
776
892
|
format,
|
|
777
|
-
usage:
|
|
893
|
+
usage: import_core2.Texture.TEXTURE | import_core2.Texture.COPY_DST,
|
|
778
894
|
width: baseWidth,
|
|
779
895
|
height: baseHeight,
|
|
780
896
|
mipLevels: validLevelCount,
|
|
@@ -791,9 +907,9 @@ function createCompressedTexture(device, image, baseOptions) {
|
|
|
791
907
|
}
|
|
792
908
|
|
|
793
909
|
// dist/parsers/parse-gltf-lights.js
|
|
794
|
-
var
|
|
795
|
-
var
|
|
796
|
-
function parseGLTFLights(gltf) {
|
|
910
|
+
var import_core3 = require("@math.gl/core");
|
|
911
|
+
var import_shadertools = require("@luma.gl/shadertools");
|
|
912
|
+
function parseGLTFLights(gltf, options = {}) {
|
|
797
913
|
var _a, _b, _c, _d;
|
|
798
914
|
const lightDefs = (
|
|
799
915
|
// `postProcessGLTF()` moves KHR_lights_punctual into `gltf.lights`.
|
|
@@ -814,7 +930,7 @@ function parseGLTFLights(gltf) {
|
|
|
814
930
|
if (!gltfLight) {
|
|
815
931
|
continue;
|
|
816
932
|
}
|
|
817
|
-
const color = normalizeGLTFLightColor(gltfLight.color || [1, 1, 1]);
|
|
933
|
+
const color = normalizeGLTFLightColor(gltfLight.color || [1, 1, 1], options.useByteColors ?? true);
|
|
818
934
|
const intensity = gltfLight.intensity ?? 1;
|
|
819
935
|
const range = gltfLight.range;
|
|
820
936
|
const worldMatrix = getNodeWorldMatrix(node, parentNodeById, worldMatrixByNodeId);
|
|
@@ -834,8 +950,11 @@ function parseGLTFLights(gltf) {
|
|
|
834
950
|
}
|
|
835
951
|
return lights;
|
|
836
952
|
}
|
|
837
|
-
function normalizeGLTFLightColor(color) {
|
|
838
|
-
|
|
953
|
+
function normalizeGLTFLightColor(color, useByteColors) {
|
|
954
|
+
if (useByteColors) {
|
|
955
|
+
return color.map((component) => component * 255);
|
|
956
|
+
}
|
|
957
|
+
return (0, import_shadertools.normalizeByteColor3)(color, false);
|
|
839
958
|
}
|
|
840
959
|
function parsePointLight(worldMatrix, color, intensity, range) {
|
|
841
960
|
const position = getLightPosition(worldMatrix);
|
|
@@ -894,20 +1013,20 @@ function getNodeWorldMatrix(node, parentNodeById, worldMatrixByNodeId) {
|
|
|
894
1013
|
}
|
|
895
1014
|
const localMatrix = getNodeLocalMatrix(node);
|
|
896
1015
|
const parentNode = parentNodeById.get(node.id);
|
|
897
|
-
const worldMatrix = parentNode ? new
|
|
1016
|
+
const worldMatrix = parentNode ? new import_core3.Matrix4(getNodeWorldMatrix(parentNode, parentNodeById, worldMatrixByNodeId)).multiplyRight(localMatrix) : localMatrix;
|
|
898
1017
|
worldMatrixByNodeId.set(node.id, worldMatrix);
|
|
899
1018
|
return worldMatrix;
|
|
900
1019
|
}
|
|
901
1020
|
function getNodeLocalMatrix(node) {
|
|
902
1021
|
if (node.matrix) {
|
|
903
|
-
return new
|
|
1022
|
+
return new import_core3.Matrix4(node.matrix);
|
|
904
1023
|
}
|
|
905
|
-
const matrix = new
|
|
1024
|
+
const matrix = new import_core3.Matrix4();
|
|
906
1025
|
if (node.translation) {
|
|
907
1026
|
matrix.translate(node.translation);
|
|
908
1027
|
}
|
|
909
1028
|
if (node.rotation) {
|
|
910
|
-
matrix.multiplyRight(new
|
|
1029
|
+
matrix.multiplyRight(new import_core3.Matrix4().fromQuaternion(node.rotation));
|
|
911
1030
|
}
|
|
912
1031
|
if (node.scale) {
|
|
913
1032
|
matrix.scale(node.scale);
|
|
@@ -923,7 +1042,7 @@ function getLightDirection(worldMatrix) {
|
|
|
923
1042
|
|
|
924
1043
|
// dist/parsers/parse-gltf.js
|
|
925
1044
|
var import_engine4 = require("@luma.gl/engine");
|
|
926
|
-
var
|
|
1045
|
+
var import_shadertools3 = require("@luma.gl/shadertools");
|
|
927
1046
|
|
|
928
1047
|
// dist/webgl-to-webgpu/convert-webgl-topology.js
|
|
929
1048
|
function convertGLDrawModeToTopology(drawMode) {
|
|
@@ -944,9 +1063,9 @@ function convertGLDrawModeToTopology(drawMode) {
|
|
|
944
1063
|
}
|
|
945
1064
|
|
|
946
1065
|
// dist/gltf/create-gltf-model.js
|
|
947
|
-
var
|
|
1066
|
+
var import_core4 = require("@luma.gl/core");
|
|
948
1067
|
var import_engine2 = require("@luma.gl/engine");
|
|
949
|
-
var
|
|
1068
|
+
var import_shadertools2 = require("@luma.gl/shadertools");
|
|
950
1069
|
var import_engine3 = require("@luma.gl/engine");
|
|
951
1070
|
var SHADER = (
|
|
952
1071
|
/* WGSL */
|
|
@@ -962,19 +1081,23 @@ struct VertexInputs {
|
|
|
962
1081
|
#ifdef HAS_UV
|
|
963
1082
|
@location(3) texCoords: vec2f,
|
|
964
1083
|
#endif
|
|
1084
|
+
#ifdef HAS_UV_1
|
|
1085
|
+
@location(4) texCoords1: vec2f,
|
|
1086
|
+
#endif
|
|
965
1087
|
#ifdef HAS_SKIN
|
|
966
|
-
@location(
|
|
967
|
-
@location(
|
|
1088
|
+
@location(5) JOINTS_0: vec4u,
|
|
1089
|
+
@location(6) WEIGHTS_0: vec4f,
|
|
968
1090
|
#endif
|
|
969
1091
|
};
|
|
970
1092
|
|
|
971
1093
|
struct FragmentInputs {
|
|
972
1094
|
@builtin(position) position: vec4f,
|
|
973
1095
|
@location(0) pbrPosition: vec3f,
|
|
974
|
-
@location(1)
|
|
975
|
-
@location(2)
|
|
1096
|
+
@location(1) pbrUV0: vec2f,
|
|
1097
|
+
@location(2) pbrUV1: vec2f,
|
|
1098
|
+
@location(3) pbrNormal: vec3f,
|
|
976
1099
|
#ifdef HAS_TANGENTS
|
|
977
|
-
@location(
|
|
1100
|
+
@location(4) pbrTangent: vec4f,
|
|
978
1101
|
#endif
|
|
979
1102
|
};
|
|
980
1103
|
|
|
@@ -984,13 +1107,17 @@ fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
|
984
1107
|
var position = vec4f(inputs.positions, 1.0);
|
|
985
1108
|
var normal = vec3f(0.0, 0.0, 1.0);
|
|
986
1109
|
var tangent = vec4f(1.0, 0.0, 0.0, 1.0);
|
|
987
|
-
var
|
|
1110
|
+
var uv0 = vec2f(0.0, 0.0);
|
|
1111
|
+
var uv1 = vec2f(0.0, 0.0);
|
|
988
1112
|
|
|
989
1113
|
#ifdef HAS_NORMALS
|
|
990
1114
|
normal = inputs.normals;
|
|
991
1115
|
#endif
|
|
992
1116
|
#ifdef HAS_UV
|
|
993
|
-
|
|
1117
|
+
uv0 = inputs.texCoords;
|
|
1118
|
+
#endif
|
|
1119
|
+
#ifdef HAS_UV_1
|
|
1120
|
+
uv1 = inputs.texCoords1;
|
|
994
1121
|
#endif
|
|
995
1122
|
#ifdef HAS_TANGENTS
|
|
996
1123
|
tangent = inputs.TANGENT;
|
|
@@ -1016,7 +1143,8 @@ fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
|
1016
1143
|
|
|
1017
1144
|
outputs.position = pbrProjection.modelViewProjectionMatrix * position;
|
|
1018
1145
|
outputs.pbrPosition = worldPosition.xyz / worldPosition.w;
|
|
1019
|
-
outputs.
|
|
1146
|
+
outputs.pbrUV0 = uv0;
|
|
1147
|
+
outputs.pbrUV1 = uv1;
|
|
1020
1148
|
outputs.pbrNormal = normal;
|
|
1021
1149
|
return outputs;
|
|
1022
1150
|
}
|
|
@@ -1024,7 +1152,8 @@ fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
|
1024
1152
|
@fragment
|
|
1025
1153
|
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
1026
1154
|
fragmentInputs.pbr_vPosition = inputs.pbrPosition;
|
|
1027
|
-
fragmentInputs.
|
|
1155
|
+
fragmentInputs.pbr_vUV0 = inputs.pbrUV0;
|
|
1156
|
+
fragmentInputs.pbr_vUV1 = inputs.pbrUV1;
|
|
1028
1157
|
fragmentInputs.pbr_vNormal = inputs.pbrNormal;
|
|
1029
1158
|
#ifdef HAS_TANGENTS
|
|
1030
1159
|
let tangent = normalize(inputs.pbrTangent.xyz);
|
|
@@ -1056,6 +1185,10 @@ var vs = (
|
|
|
1056
1185
|
in vec2 texCoords;
|
|
1057
1186
|
#endif
|
|
1058
1187
|
|
|
1188
|
+
#ifdef HAS_UV_1
|
|
1189
|
+
in vec2 texCoords1;
|
|
1190
|
+
#endif
|
|
1191
|
+
|
|
1059
1192
|
#ifdef HAS_SKIN
|
|
1060
1193
|
in uvec4 JOINTS_0;
|
|
1061
1194
|
in vec4 WEIGHTS_0;
|
|
@@ -1065,6 +1198,7 @@ var vs = (
|
|
|
1065
1198
|
vec4 _NORMAL = vec4(0.);
|
|
1066
1199
|
vec4 _TANGENT = vec4(0.);
|
|
1067
1200
|
vec2 _TEXCOORD_0 = vec2(0.);
|
|
1201
|
+
vec2 _TEXCOORD_1 = vec2(0.);
|
|
1068
1202
|
|
|
1069
1203
|
#ifdef HAS_NORMALS
|
|
1070
1204
|
_NORMAL = normals;
|
|
@@ -1078,6 +1212,10 @@ var vs = (
|
|
|
1078
1212
|
_TEXCOORD_0 = texCoords;
|
|
1079
1213
|
#endif
|
|
1080
1214
|
|
|
1215
|
+
#ifdef HAS_UV_1
|
|
1216
|
+
_TEXCOORD_1 = texCoords1;
|
|
1217
|
+
#endif
|
|
1218
|
+
|
|
1081
1219
|
vec4 pos = positions;
|
|
1082
1220
|
|
|
1083
1221
|
#ifdef HAS_SKIN
|
|
@@ -1087,7 +1225,7 @@ var vs = (
|
|
|
1087
1225
|
_TANGENT = vec4((skinMat * vec4(_TANGENT.xyz, 0.)).xyz, _TANGENT.w);
|
|
1088
1226
|
#endif
|
|
1089
1227
|
|
|
1090
|
-
pbr_setPositionNormalTangentUV(pos, _NORMAL, _TANGENT, _TEXCOORD_0);
|
|
1228
|
+
pbr_setPositionNormalTangentUV(pos, _NORMAL, _TANGENT, _TEXCOORD_0, _TEXCOORD_1);
|
|
1091
1229
|
gl_Position = pbrProjection.modelViewProjectionMatrix * pos;
|
|
1092
1230
|
}
|
|
1093
1231
|
`
|
|
@@ -1104,7 +1242,7 @@ var fs = (
|
|
|
1104
1242
|
`
|
|
1105
1243
|
);
|
|
1106
1244
|
function createGLTFMaterial(device, options) {
|
|
1107
|
-
const materialFactory = options.materialFactory || new import_engine3.MaterialFactory(device, { modules: [
|
|
1245
|
+
const materialFactory = options.materialFactory || new import_engine3.MaterialFactory(device, { modules: [import_shadertools2.pbrMaterial] });
|
|
1108
1246
|
const pbrMaterialProps = { ...options.parsedPPBRMaterial.uniforms };
|
|
1109
1247
|
delete pbrMaterialProps.camera;
|
|
1110
1248
|
const materialBindings = Object.fromEntries(Object.entries({
|
|
@@ -1120,7 +1258,7 @@ function createGLTFMaterial(device, options) {
|
|
|
1120
1258
|
}
|
|
1121
1259
|
function createGLTFModel(device, options) {
|
|
1122
1260
|
const { id, geometry, parsedPPBRMaterial, vertexCount, modelOptions = {} } = options;
|
|
1123
|
-
|
|
1261
|
+
import_core4.log.info(4, "createGLTFModel defines: ", parsedPPBRMaterial.defines)();
|
|
1124
1262
|
const managedResources = [];
|
|
1125
1263
|
const parameters = {
|
|
1126
1264
|
depthWriteEnabled: true,
|
|
@@ -1136,7 +1274,7 @@ function createGLTFModel(device, options) {
|
|
|
1136
1274
|
geometry,
|
|
1137
1275
|
topology: geometry.topology,
|
|
1138
1276
|
vertexCount,
|
|
1139
|
-
modules: [
|
|
1277
|
+
modules: [import_shadertools2.pbrMaterial, import_shadertools2.skin],
|
|
1140
1278
|
...modelOptions,
|
|
1141
1279
|
defines: { ...parsedPPBRMaterial.defines, ...modelOptions.defines },
|
|
1142
1280
|
parameters: { ...parameters, ...parsedPPBRMaterial.parameters, ...modelOptions.parameters }
|
|
@@ -1158,7 +1296,7 @@ function createGLTFModel(device, options) {
|
|
|
1158
1296
|
return new import_engine3.ModelNode({ managedResources, model });
|
|
1159
1297
|
}
|
|
1160
1298
|
function isMaterialBindingResource(value) {
|
|
1161
|
-
return value instanceof
|
|
1299
|
+
return value instanceof import_core4.Buffer || value instanceof import_engine2.DynamicTexture || value instanceof import_core4.Sampler || value instanceof import_core4.Texture || value instanceof import_core4.TextureView;
|
|
1162
1300
|
}
|
|
1163
1301
|
function getSceneShaderInputProps(modules, material, shaderInputValues) {
|
|
1164
1302
|
const propertyToModuleNameMap = /* @__PURE__ */ new Map();
|
|
@@ -1191,11 +1329,12 @@ var defaultOptions = {
|
|
|
1191
1329
|
pbrDebug: false,
|
|
1192
1330
|
imageBasedLightingEnvironment: void 0,
|
|
1193
1331
|
lights: true,
|
|
1194
|
-
useTangents: false
|
|
1332
|
+
useTangents: false,
|
|
1333
|
+
useByteColors: true
|
|
1195
1334
|
};
|
|
1196
1335
|
function parseGLTF(device, gltf, options = {}) {
|
|
1197
1336
|
const combinedOptions = { ...defaultOptions, ...options };
|
|
1198
|
-
const materialFactory = new import_engine4.MaterialFactory(device, { modules: [
|
|
1337
|
+
const materialFactory = new import_engine4.MaterialFactory(device, { modules: [import_shadertools3.pbrMaterial] });
|
|
1199
1338
|
const materials = (gltf.materials || []).map((gltfMaterial, materialIndex) => createGLTFMaterial(device, {
|
|
1200
1339
|
id: getGLTFMaterialId(gltfMaterial, materialIndex),
|
|
1201
1340
|
parsedPPBRMaterial: parsePBRMaterial(device, gltfMaterial, {}, {
|
|
@@ -1279,7 +1418,7 @@ function createNodeForGLTFMesh(device, gltfMesh, gltf, gltfMaterialIdToMaterialM
|
|
|
1279
1418
|
}
|
|
1280
1419
|
function createNodeForGLTFPrimitive({ device, gltfPrimitive, primitiveIndex, gltfMesh, gltf, gltfMaterialIdToMaterialMap, options }) {
|
|
1281
1420
|
const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${primitiveIndex}`;
|
|
1282
|
-
const topology = convertGLDrawModeToTopology(gltfPrimitive.mode
|
|
1421
|
+
const topology = convertGLDrawModeToTopology(gltfPrimitive.mode ?? 4);
|
|
1283
1422
|
const vertexCount = gltfPrimitive.indices ? gltfPrimitive.indices.count : getVertexCount(gltfPrimitive.attributes);
|
|
1284
1423
|
const geometry = createGeometry(id, gltfPrimitive, topology);
|
|
1285
1424
|
const parsedPPBRMaterial = parsePBRMaterial(device, gltfPrimitive.material, geometry.attributes, {
|
|
@@ -1288,7 +1427,7 @@ function createNodeForGLTFPrimitive({ device, gltfPrimitive, primitiveIndex, glt
|
|
|
1288
1427
|
});
|
|
1289
1428
|
const modelNode = createGLTFModel(device, {
|
|
1290
1429
|
id,
|
|
1291
|
-
geometry
|
|
1430
|
+
geometry,
|
|
1292
1431
|
material: gltfPrimitive.material ? gltfMaterialIdToMaterialMap.get(gltfPrimitive.material.id) || null : null,
|
|
1293
1432
|
parsedPPBRMaterial,
|
|
1294
1433
|
modelOptions: options.modelOptions,
|
|
@@ -1298,18 +1437,32 @@ function createNodeForGLTFPrimitive({ device, gltfPrimitive, primitiveIndex, glt
|
|
|
1298
1437
|
return modelNode;
|
|
1299
1438
|
}
|
|
1300
1439
|
function getVertexCount(attributes) {
|
|
1301
|
-
|
|
1440
|
+
let vertexCount = Infinity;
|
|
1441
|
+
for (const attribute of Object.values(attributes)) {
|
|
1442
|
+
if (attribute) {
|
|
1443
|
+
const { value, size, components } = attribute;
|
|
1444
|
+
const attributeSize = size ?? components;
|
|
1445
|
+
if ((value == null ? void 0 : value.length) !== void 0 && attributeSize >= 1) {
|
|
1446
|
+
vertexCount = Math.min(vertexCount, value.length / attributeSize);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
if (!Number.isFinite(vertexCount)) {
|
|
1451
|
+
throw new Error("Could not determine vertex count from attributes");
|
|
1452
|
+
}
|
|
1453
|
+
return vertexCount;
|
|
1302
1454
|
}
|
|
1303
1455
|
function createGeometry(id, gltfPrimitive, topology) {
|
|
1456
|
+
var _a;
|
|
1304
1457
|
const attributes = {};
|
|
1305
1458
|
for (const [attributeName, attribute] of Object.entries(gltfPrimitive.attributes)) {
|
|
1306
|
-
const { components, size, value } = attribute;
|
|
1307
|
-
attributes[attributeName] = { size: size ?? components, value };
|
|
1459
|
+
const { components, size, value, normalized } = attribute;
|
|
1460
|
+
attributes[attributeName] = { size: size ?? components, value, normalized };
|
|
1308
1461
|
}
|
|
1309
1462
|
return new import_engine4.Geometry({
|
|
1310
1463
|
id,
|
|
1311
1464
|
topology,
|
|
1312
|
-
indices: gltfPrimitive.indices.value,
|
|
1465
|
+
indices: (_a = gltfPrimitive.indices) == null ? void 0 : _a.value,
|
|
1313
1466
|
attributes
|
|
1314
1467
|
});
|
|
1315
1468
|
}
|
|
@@ -1318,11 +1471,11 @@ function getGLTFMaterialId(gltfMaterial, materialIndex) {
|
|
|
1318
1471
|
}
|
|
1319
1472
|
|
|
1320
1473
|
// dist/gltf/gltf-animator.js
|
|
1321
|
-
var
|
|
1474
|
+
var import_core7 = require("@luma.gl/core");
|
|
1322
1475
|
|
|
1323
1476
|
// dist/gltf/animations/interpolate.js
|
|
1324
|
-
var
|
|
1325
|
-
var
|
|
1477
|
+
var import_core5 = require("@luma.gl/core");
|
|
1478
|
+
var import_core6 = require("@math.gl/core");
|
|
1326
1479
|
function updateTargetPath(target, path, newValue) {
|
|
1327
1480
|
switch (path) {
|
|
1328
1481
|
case "translation":
|
|
@@ -1332,27 +1485,38 @@ function updateTargetPath(target, path, newValue) {
|
|
|
1332
1485
|
case "scale":
|
|
1333
1486
|
return target.setScale(newValue).updateMatrix();
|
|
1334
1487
|
default:
|
|
1335
|
-
|
|
1488
|
+
import_core5.log.warn(`Bad animation path ${path}`)();
|
|
1336
1489
|
return null;
|
|
1337
1490
|
}
|
|
1338
1491
|
}
|
|
1339
1492
|
function interpolate(time, { input, interpolation, output }, target, path) {
|
|
1493
|
+
const value = evaluateSampler(time, { input, interpolation, output }, path);
|
|
1494
|
+
if (value) {
|
|
1495
|
+
updateTargetPath(target, path, value);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
function evaluateSampler(time, { input, interpolation, output }, path) {
|
|
1340
1499
|
const maxTime = input[input.length - 1];
|
|
1500
|
+
if (!Number.isFinite(maxTime) || maxTime <= 0) {
|
|
1501
|
+
return output[0] || null;
|
|
1502
|
+
}
|
|
1341
1503
|
const animationTime = time % maxTime;
|
|
1342
1504
|
const nextIndex = input.findIndex((t) => t >= animationTime);
|
|
1505
|
+
if (nextIndex < 0) {
|
|
1506
|
+
return output[output.length - 1] || null;
|
|
1507
|
+
}
|
|
1343
1508
|
const previousIndex = Math.max(0, nextIndex - 1);
|
|
1344
1509
|
const previousTime = input[previousIndex];
|
|
1345
1510
|
const nextTime = input[nextIndex];
|
|
1346
1511
|
switch (interpolation) {
|
|
1347
1512
|
case "STEP":
|
|
1348
|
-
|
|
1349
|
-
break;
|
|
1513
|
+
return output[previousIndex];
|
|
1350
1514
|
case "LINEAR":
|
|
1351
1515
|
if (nextTime > previousTime) {
|
|
1352
1516
|
const ratio = (animationTime - previousTime) / (nextTime - previousTime);
|
|
1353
|
-
linearInterpolate(
|
|
1517
|
+
return linearInterpolate(path, output[previousIndex], output[nextIndex], ratio);
|
|
1354
1518
|
}
|
|
1355
|
-
|
|
1519
|
+
return output[previousIndex] || null;
|
|
1356
1520
|
case "CUBICSPLINE":
|
|
1357
1521
|
if (nextTime > previousTime) {
|
|
1358
1522
|
const ratio = (animationTime - previousTime) / (nextTime - previousTime);
|
|
@@ -1361,36 +1525,32 @@ function interpolate(time, { input, interpolation, output }, target, path) {
|
|
|
1361
1525
|
const outTangent0 = output[3 * previousIndex + 2];
|
|
1362
1526
|
const inTangent1 = output[3 * nextIndex + 0];
|
|
1363
1527
|
const p1 = output[3 * nextIndex + 1];
|
|
1364
|
-
cubicsplineInterpolate(
|
|
1528
|
+
return cubicsplineInterpolate({ p0, outTangent0, inTangent1, p1, tDiff, ratio });
|
|
1365
1529
|
}
|
|
1366
|
-
|
|
1530
|
+
return output[3 * previousIndex + 1] || null;
|
|
1367
1531
|
default:
|
|
1368
|
-
|
|
1369
|
-
|
|
1532
|
+
import_core5.log.warn(`Interpolation ${interpolation} not supported`)();
|
|
1533
|
+
return null;
|
|
1370
1534
|
}
|
|
1371
1535
|
}
|
|
1372
|
-
function linearInterpolate(
|
|
1536
|
+
function linearInterpolate(path, start, stop, ratio) {
|
|
1373
1537
|
if (path === "rotation") {
|
|
1374
|
-
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
}
|
|
1380
|
-
updateTargetPath(target, path, newVal);
|
|
1538
|
+
return new import_core6.Quaternion().slerp({ start, target: stop, ratio });
|
|
1539
|
+
}
|
|
1540
|
+
const newVal = [];
|
|
1541
|
+
for (let i = 0; i < start.length; i++) {
|
|
1542
|
+
newVal[i] = ratio * stop[i] + (1 - ratio) * start[i];
|
|
1381
1543
|
}
|
|
1544
|
+
return newVal;
|
|
1382
1545
|
}
|
|
1383
|
-
function cubicsplineInterpolate(
|
|
1546
|
+
function cubicsplineInterpolate({ p0, outTangent0, inTangent1, p1, tDiff, ratio: t }) {
|
|
1384
1547
|
const newVal = [];
|
|
1385
1548
|
for (let i = 0; i < p0.length; i++) {
|
|
1386
1549
|
const m0 = outTangent0[i] * tDiff;
|
|
1387
1550
|
const m1 = inTangent1[i] * tDiff;
|
|
1388
1551
|
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;
|
|
1389
1552
|
}
|
|
1390
|
-
|
|
1391
|
-
}
|
|
1392
|
-
function stepInterpolate(target, path, value) {
|
|
1393
|
-
updateTargetPath(target, path, value);
|
|
1553
|
+
return newVal;
|
|
1394
1554
|
}
|
|
1395
1555
|
|
|
1396
1556
|
// dist/gltf/gltf-animator.js
|
|
@@ -1399,18 +1559,26 @@ var GLTFSingleAnimator = class {
|
|
|
1399
1559
|
animation;
|
|
1400
1560
|
/** Target scenegraph lookup table. */
|
|
1401
1561
|
gltfNodeIdToNodeMap;
|
|
1562
|
+
/** Materials aligned with the source glTF materials array. */
|
|
1563
|
+
materials;
|
|
1402
1564
|
/** Playback start time in seconds. */
|
|
1403
1565
|
startTime = 0;
|
|
1404
1566
|
/** Whether playback is currently enabled. */
|
|
1405
1567
|
playing = true;
|
|
1406
1568
|
/** Playback speed multiplier. */
|
|
1407
1569
|
speed = 1;
|
|
1570
|
+
/** Mutable runtime texture-transform state for animated material slots. */
|
|
1571
|
+
materialTextureTransformState = /* @__PURE__ */ new Map();
|
|
1408
1572
|
/** Creates a single-animation controller. */
|
|
1409
1573
|
constructor(props) {
|
|
1410
1574
|
this.animation = props.animation;
|
|
1411
1575
|
this.gltfNodeIdToNodeMap = props.gltfNodeIdToNodeMap;
|
|
1576
|
+
this.materials = props.materials || [];
|
|
1412
1577
|
this.animation.name ||= "unnamed";
|
|
1413
1578
|
Object.assign(this, props);
|
|
1579
|
+
if (this.animation.channels.some((channel) => channel.type !== "node") && !this.materials.length) {
|
|
1580
|
+
throw new Error(`Animation ${this.animation.name} targets materials, but GLTFAnimator was created without a materials array`);
|
|
1581
|
+
}
|
|
1414
1582
|
}
|
|
1415
1583
|
/** Advances the animation to the supplied wall-clock time in milliseconds. */
|
|
1416
1584
|
setTime(timeMs) {
|
|
@@ -1419,12 +1587,28 @@ var GLTFSingleAnimator = class {
|
|
|
1419
1587
|
}
|
|
1420
1588
|
const absTime = timeMs / 1e3;
|
|
1421
1589
|
const time = (absTime - this.startTime) * this.speed;
|
|
1422
|
-
this.animation.channels.forEach((
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1590
|
+
this.animation.channels.forEach((channel) => {
|
|
1591
|
+
if (channel.type === "node") {
|
|
1592
|
+
const { sampler, targetNodeId, path } = channel;
|
|
1593
|
+
const targetNode = this.gltfNodeIdToNodeMap.get(targetNodeId);
|
|
1594
|
+
if (!targetNode) {
|
|
1595
|
+
throw new Error(`Cannot find animation target node ${targetNodeId}`);
|
|
1596
|
+
}
|
|
1597
|
+
interpolate(time, sampler, targetNode, path);
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
const material = this.materials[channel.targetMaterialIndex];
|
|
1601
|
+
if (!material) {
|
|
1602
|
+
throw new Error(`Cannot find animation target material ${channel.targetMaterialIndex} for ${channel.pointer}`);
|
|
1603
|
+
}
|
|
1604
|
+
const value = evaluateSampler(time, channel.sampler);
|
|
1605
|
+
if (value) {
|
|
1606
|
+
if (channel.type === "material") {
|
|
1607
|
+
applyMaterialAnimationValue(material, channel, value);
|
|
1608
|
+
} else {
|
|
1609
|
+
applyTextureTransformAnimationValue(material, channel, value, this.materialTextureTransformState);
|
|
1610
|
+
}
|
|
1426
1611
|
}
|
|
1427
|
-
interpolate(time, sampler, targetNode, path);
|
|
1428
1612
|
});
|
|
1429
1613
|
}
|
|
1430
1614
|
};
|
|
@@ -1437,13 +1621,14 @@ var GLTFAnimator = class {
|
|
|
1437
1621
|
const name = animation.name || `Animation-${index}`;
|
|
1438
1622
|
return new GLTFSingleAnimator({
|
|
1439
1623
|
gltfNodeIdToNodeMap: props.gltfNodeIdToNodeMap,
|
|
1624
|
+
materials: props.materials,
|
|
1440
1625
|
animation: { name, channels: animation.channels }
|
|
1441
1626
|
});
|
|
1442
1627
|
});
|
|
1443
1628
|
}
|
|
1444
1629
|
/** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */
|
|
1445
1630
|
animate(time) {
|
|
1446
|
-
|
|
1631
|
+
import_core7.log.warn("GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead")();
|
|
1447
1632
|
this.setTime(time);
|
|
1448
1633
|
}
|
|
1449
1634
|
/** Advances every animation to the supplied wall-clock time in milliseconds. */
|
|
@@ -1455,114 +1640,71 @@ var GLTFAnimator = class {
|
|
|
1455
1640
|
return this.animations;
|
|
1456
1641
|
}
|
|
1457
1642
|
};
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
VEC2: 2,
|
|
1466
|
-
VEC3: 3,
|
|
1467
|
-
VEC4: 4,
|
|
1468
|
-
MAT2: 4,
|
|
1469
|
-
MAT3: 9,
|
|
1470
|
-
MAT4: 16
|
|
1471
|
-
};
|
|
1472
|
-
var ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = {
|
|
1473
|
-
5120: Int8Array,
|
|
1474
|
-
5121: Uint8Array,
|
|
1475
|
-
5122: Int16Array,
|
|
1476
|
-
5123: Uint16Array,
|
|
1477
|
-
5125: Uint32Array,
|
|
1478
|
-
5126: Float32Array
|
|
1479
|
-
};
|
|
1480
|
-
function accessorToTypedArray(accessor) {
|
|
1481
|
-
var _a;
|
|
1482
|
-
const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];
|
|
1483
|
-
const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];
|
|
1484
|
-
const length = components * accessor.count;
|
|
1485
|
-
const { buffer, byteOffset = 0 } = ((_a = accessor.bufferView) == null ? void 0 : _a.data) ?? {};
|
|
1486
|
-
const typedArray = new ArrayType(buffer, byteOffset + (accessor.byteOffset || 0), length);
|
|
1487
|
-
return { typedArray, components };
|
|
1643
|
+
function applyMaterialAnimationValue(material, channel, value) {
|
|
1644
|
+
const pbrMaterial3 = channel.component !== void 0 ? {
|
|
1645
|
+
[channel.property]: updateMaterialArrayComponent(getCurrentMaterialValue(material, channel.property), channel.component, value[0])
|
|
1646
|
+
} : {
|
|
1647
|
+
[channel.property]: value.length === 1 ? value[0] : value
|
|
1648
|
+
};
|
|
1649
|
+
material.setProps({ pbrMaterial: pbrMaterial3 });
|
|
1488
1650
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
const
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1651
|
+
function getCurrentMaterialValue(material, property) {
|
|
1652
|
+
var _a;
|
|
1653
|
+
const uniformValues = material.shaderInputs.getUniformValues();
|
|
1654
|
+
const currentValue = (_a = uniformValues["pbrMaterial"]) == null ? void 0 : _a[property];
|
|
1655
|
+
return Array.isArray(currentValue) ? [...currentValue] : [];
|
|
1656
|
+
}
|
|
1657
|
+
function updateMaterialArrayComponent(currentValue, component, nextValue) {
|
|
1658
|
+
const updatedValue = [...currentValue];
|
|
1659
|
+
updatedValue[component] = nextValue;
|
|
1660
|
+
return updatedValue;
|
|
1661
|
+
}
|
|
1662
|
+
function applyTextureTransformAnimationValue(material, channel, value, materialTextureTransformState) {
|
|
1663
|
+
const slotDefinition = getTextureTransformSlotDefinition(channel.textureSlot);
|
|
1664
|
+
const currentTransform = getCurrentTextureTransform(materialTextureTransformState, material, channel);
|
|
1665
|
+
switch (channel.path) {
|
|
1666
|
+
case "offset":
|
|
1667
|
+
if (channel.component !== void 0) {
|
|
1668
|
+
currentTransform.offset[channel.component] = value[0];
|
|
1669
|
+
} else {
|
|
1670
|
+
currentTransform.offset = [value[0], value[1]];
|
|
1506
1671
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
interpolation,
|
|
1517
|
-
output: accessorToJsArray2D(gltf.accessors[output], accessorCache2D)
|
|
1518
|
-
};
|
|
1519
|
-
samplerCache.set(sampler, parsedSampler);
|
|
1672
|
+
break;
|
|
1673
|
+
case "rotation":
|
|
1674
|
+
currentTransform.rotation = value[0];
|
|
1675
|
+
break;
|
|
1676
|
+
case "scale":
|
|
1677
|
+
if (channel.component !== void 0) {
|
|
1678
|
+
currentTransform.scale[channel.component] = value[0];
|
|
1679
|
+
} else {
|
|
1680
|
+
currentTransform.scale = [value[0], value[1]];
|
|
1520
1681
|
}
|
|
1521
|
-
|
|
1522
|
-
sampler: parsedSampler,
|
|
1523
|
-
targetNodeId: targetNode.id,
|
|
1524
|
-
path
|
|
1525
|
-
};
|
|
1526
|
-
});
|
|
1527
|
-
return channels.length ? [{ name, channels }] : [];
|
|
1528
|
-
});
|
|
1529
|
-
}
|
|
1530
|
-
function getSupportedAnimationPath(path) {
|
|
1531
|
-
if (path === "pointer") {
|
|
1532
|
-
import_core7.log.warn("KHR_animation_pointer channels are not supported and will be skipped")();
|
|
1533
|
-
return null;
|
|
1534
|
-
}
|
|
1535
|
-
return path;
|
|
1536
|
-
}
|
|
1537
|
-
function accessorToJsArray1D(accessor, accessorCache) {
|
|
1538
|
-
if (accessorCache.has(accessor)) {
|
|
1539
|
-
return accessorCache.get(accessor);
|
|
1540
|
-
}
|
|
1541
|
-
const { typedArray: array, components } = accessorToTypedArray(accessor);
|
|
1542
|
-
assert(components === 1, "accessorToJsArray1D must have exactly 1 component");
|
|
1543
|
-
const result = Array.from(array);
|
|
1544
|
-
accessorCache.set(accessor, result);
|
|
1545
|
-
return result;
|
|
1546
|
-
}
|
|
1547
|
-
function accessorToJsArray2D(accessor, accessorCache) {
|
|
1548
|
-
if (accessorCache.has(accessor)) {
|
|
1549
|
-
return accessorCache.get(accessor);
|
|
1550
|
-
}
|
|
1551
|
-
const { typedArray: array, components } = accessorToTypedArray(accessor);
|
|
1552
|
-
assert(components >= 1, "accessorToJsArray2D must have at least 1 component");
|
|
1553
|
-
const result = [];
|
|
1554
|
-
for (let i = 0; i < array.length; i += components) {
|
|
1555
|
-
result.push(Array.from(array.slice(i, i + components)));
|
|
1682
|
+
break;
|
|
1556
1683
|
}
|
|
1557
|
-
|
|
1558
|
-
|
|
1684
|
+
material.setProps({
|
|
1685
|
+
pbrMaterial: {
|
|
1686
|
+
[slotDefinition.uvTransformUniform]: getTextureTransformDeltaMatrix(channel.baseTransform, currentTransform)
|
|
1687
|
+
}
|
|
1688
|
+
});
|
|
1559
1689
|
}
|
|
1560
|
-
function
|
|
1561
|
-
|
|
1562
|
-
|
|
1690
|
+
function getCurrentTextureTransform(materialTextureTransformState, material, channel) {
|
|
1691
|
+
const materialState = materialTextureTransformState.get(material) || {};
|
|
1692
|
+
let textureTransformState = materialState[channel.textureSlot];
|
|
1693
|
+
if (!textureTransformState) {
|
|
1694
|
+
textureTransformState = {
|
|
1695
|
+
offset: [...channel.baseTransform.offset],
|
|
1696
|
+
rotation: channel.baseTransform.rotation,
|
|
1697
|
+
scale: [...channel.baseTransform.scale]
|
|
1698
|
+
};
|
|
1699
|
+
materialState[channel.textureSlot] = textureTransformState;
|
|
1700
|
+
materialTextureTransformState.set(material, materialState);
|
|
1563
1701
|
}
|
|
1702
|
+
return textureTransformState;
|
|
1564
1703
|
}
|
|
1565
1704
|
|
|
1705
|
+
// dist/parsers/parse-gltf-animations.js
|
|
1706
|
+
var import_core8 = require("@luma.gl/core");
|
|
1707
|
+
|
|
1566
1708
|
// dist/gltf/gltf-extension-support.js
|
|
1567
1709
|
var UNKNOWN_EXTENSION_SUPPORT = {
|
|
1568
1710
|
supportLevel: "none",
|
|
@@ -1658,8 +1800,8 @@ var GLTF_EXTENSION_SUPPORT_REGISTRY = {
|
|
|
1658
1800
|
comment: "Node-visibility animations and toggles are not mapped onto runtime scenegraph state."
|
|
1659
1801
|
},
|
|
1660
1802
|
KHR_animation_pointer: {
|
|
1661
|
-
supportLevel: "
|
|
1662
|
-
comment: "
|
|
1803
|
+
supportLevel: "parsed-and-wired",
|
|
1804
|
+
comment: "Selected node TRS, material factor, and KHR_texture_transform offset/rotation/scale pointers are wired to runtime updates; unsupported targets are skipped."
|
|
1663
1805
|
},
|
|
1664
1806
|
KHR_materials_diffuse_transmission: {
|
|
1665
1807
|
supportLevel: "none",
|
|
@@ -1702,7 +1844,7 @@ function getGLTFExtensionSupport(gltf) {
|
|
|
1702
1844
|
extensionName,
|
|
1703
1845
|
{
|
|
1704
1846
|
extensionName,
|
|
1705
|
-
supported: extensionSupportDefinition.supportLevel === "built-in",
|
|
1847
|
+
supported: extensionSupportDefinition.supportLevel === "built-in" || extensionSupportDefinition.supportLevel === "parsed-and-wired",
|
|
1706
1848
|
supportLevel: extensionSupportDefinition.supportLevel,
|
|
1707
1849
|
comment: extensionSupportDefinition.comment
|
|
1708
1850
|
}
|
|
@@ -1710,6 +1852,9 @@ function getGLTFExtensionSupport(gltf) {
|
|
|
1710
1852
|
});
|
|
1711
1853
|
return new Map(extensionSupportEntries);
|
|
1712
1854
|
}
|
|
1855
|
+
function getRegisteredGLTFExtensionSupport(extensionName) {
|
|
1856
|
+
return GLTF_EXTENSION_SUPPORT_REGISTRY[extensionName] || null;
|
|
1857
|
+
}
|
|
1713
1858
|
function collectGLTFExtensionNames(gltf) {
|
|
1714
1859
|
var _a;
|
|
1715
1860
|
const gltfWithRemovedExtensions = gltf;
|
|
@@ -1718,10 +1863,10 @@ function collectGLTFExtensionNames(gltf) {
|
|
|
1718
1863
|
addExtensionNames(extensionNames, gltf.extensionsRequired);
|
|
1719
1864
|
addExtensionNames(extensionNames, gltfWithRemovedExtensions.extensionsRemoved);
|
|
1720
1865
|
addExtensionNames(extensionNames, Object.keys(gltf.extensions || {}));
|
|
1721
|
-
if (((_a = gltfWithRemovedExtensions.lights) == null ? void 0 : _a.length) || gltf.nodes.some((node) => "light" in node)) {
|
|
1866
|
+
if (((_a = gltfWithRemovedExtensions.lights) == null ? void 0 : _a.length) || (gltf.nodes || []).some((node) => "light" in node)) {
|
|
1722
1867
|
extensionNames.add("KHR_lights_punctual");
|
|
1723
1868
|
}
|
|
1724
|
-
if (gltf.materials.some((material) => {
|
|
1869
|
+
if ((gltf.materials || []).some((material) => {
|
|
1725
1870
|
var _a2;
|
|
1726
1871
|
const gltfMaterial = material;
|
|
1727
1872
|
return gltfMaterial.unlit || ((_a2 = gltfMaterial.extensions) == null ? void 0 : _a2.KHR_materials_unlit);
|
|
@@ -1736,12 +1881,358 @@ function addExtensionNames(extensionNames, newExtensionNames = []) {
|
|
|
1736
1881
|
}
|
|
1737
1882
|
}
|
|
1738
1883
|
|
|
1884
|
+
// dist/webgl-to-webgpu/convert-webgl-attribute.js
|
|
1885
|
+
var ATTRIBUTE_TYPE_TO_COMPONENTS = {
|
|
1886
|
+
SCALAR: 1,
|
|
1887
|
+
VEC2: 2,
|
|
1888
|
+
VEC3: 3,
|
|
1889
|
+
VEC4: 4,
|
|
1890
|
+
MAT2: 4,
|
|
1891
|
+
MAT3: 9,
|
|
1892
|
+
MAT4: 16
|
|
1893
|
+
};
|
|
1894
|
+
var ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = {
|
|
1895
|
+
5120: Int8Array,
|
|
1896
|
+
5121: Uint8Array,
|
|
1897
|
+
5122: Int16Array,
|
|
1898
|
+
5123: Uint16Array,
|
|
1899
|
+
5125: Uint32Array,
|
|
1900
|
+
5126: Float32Array
|
|
1901
|
+
};
|
|
1902
|
+
function accessorToTypedArray(accessor) {
|
|
1903
|
+
var _a;
|
|
1904
|
+
const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];
|
|
1905
|
+
const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];
|
|
1906
|
+
const length = components * accessor.count;
|
|
1907
|
+
const { buffer, byteOffset = 0 } = ((_a = accessor.bufferView) == null ? void 0 : _a.data) ?? {};
|
|
1908
|
+
const typedArray = new ArrayType(buffer, byteOffset + (accessor.byteOffset || 0), length);
|
|
1909
|
+
return { typedArray, components };
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
// dist/parsers/parse-gltf-animations.js
|
|
1913
|
+
function parseGLTFAnimations(gltf) {
|
|
1914
|
+
const gltfAnimations = gltf.animations || [];
|
|
1915
|
+
const accessorCache1D = /* @__PURE__ */ new Map();
|
|
1916
|
+
const accessorCache2D = /* @__PURE__ */ new Map();
|
|
1917
|
+
return gltfAnimations.flatMap((animation, index) => {
|
|
1918
|
+
const name = animation.name || `Animation-${index}`;
|
|
1919
|
+
const samplerCache = /* @__PURE__ */ new Map();
|
|
1920
|
+
const channels = animation.channels.flatMap(({ sampler, target }) => {
|
|
1921
|
+
let parsedSampler = samplerCache.get(sampler);
|
|
1922
|
+
if (!parsedSampler) {
|
|
1923
|
+
const gltfSampler = animation.samplers[sampler];
|
|
1924
|
+
if (!gltfSampler) {
|
|
1925
|
+
throw new Error(`Cannot find animation sampler ${sampler}`);
|
|
1926
|
+
}
|
|
1927
|
+
const { input, interpolation = "LINEAR", output } = gltfSampler;
|
|
1928
|
+
parsedSampler = {
|
|
1929
|
+
input: accessorToJsArray1D(gltf.accessors[input], accessorCache1D),
|
|
1930
|
+
interpolation,
|
|
1931
|
+
output: accessorToJsArray2D(gltf.accessors[output], accessorCache2D)
|
|
1932
|
+
};
|
|
1933
|
+
samplerCache.set(sampler, parsedSampler);
|
|
1934
|
+
}
|
|
1935
|
+
const parsedChannel = parseAnimationChannel(gltf, target, parsedSampler);
|
|
1936
|
+
return parsedChannel ? [parsedChannel] : [];
|
|
1937
|
+
});
|
|
1938
|
+
return channels.length ? [{ name, channels }] : [];
|
|
1939
|
+
});
|
|
1940
|
+
}
|
|
1941
|
+
function parseAnimationChannel(gltf, target, sampler) {
|
|
1942
|
+
if (target.path === "pointer") {
|
|
1943
|
+
return parseAnimationPointerChannel(gltf, target, sampler);
|
|
1944
|
+
}
|
|
1945
|
+
const path = getNodeAnimationPath(target.path);
|
|
1946
|
+
if (!path) {
|
|
1947
|
+
return null;
|
|
1948
|
+
}
|
|
1949
|
+
const targetNode = gltf.nodes[target.node ?? 0];
|
|
1950
|
+
if (!targetNode) {
|
|
1951
|
+
throw new Error(`Cannot find animation target ${target.node}`);
|
|
1952
|
+
}
|
|
1953
|
+
return {
|
|
1954
|
+
type: "node",
|
|
1955
|
+
sampler,
|
|
1956
|
+
targetNodeId: targetNode.id,
|
|
1957
|
+
path
|
|
1958
|
+
};
|
|
1959
|
+
}
|
|
1960
|
+
function parseAnimationPointerChannel(gltf, target, sampler) {
|
|
1961
|
+
var _a, _b;
|
|
1962
|
+
const pointer = (_b = (_a = target.extensions) == null ? void 0 : _a["KHR_animation_pointer"]) == null ? void 0 : _b.pointer;
|
|
1963
|
+
if (typeof pointer !== "string" || !pointer.startsWith("/")) {
|
|
1964
|
+
import_core8.log.warn("KHR_animation_pointer channel is missing a valid JSON pointer and will be skipped")();
|
|
1965
|
+
return null;
|
|
1966
|
+
}
|
|
1967
|
+
const pointerSegments = splitJsonPointer(pointer);
|
|
1968
|
+
switch (pointerSegments[0]) {
|
|
1969
|
+
case "nodes":
|
|
1970
|
+
return parseNodePointerAnimationChannel(gltf, pointerSegments, sampler, pointer);
|
|
1971
|
+
case "materials":
|
|
1972
|
+
return parseMaterialPointerAnimationChannel(gltf, pointerSegments, sampler, pointer);
|
|
1973
|
+
default:
|
|
1974
|
+
warnUnsupportedAnimationPointer(pointer, `top-level target "${pointerSegments[0]}" has no runtime animation mapping`);
|
|
1975
|
+
return null;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
function parseNodePointerAnimationChannel(gltf, pointerSegments, sampler, pointer) {
|
|
1979
|
+
if (pointerSegments.length !== 3) {
|
|
1980
|
+
warnUnsupportedAnimationPointer(pointer, "node pointers must use /nodes/{index}/{translation|rotation|scale|weights}");
|
|
1981
|
+
return null;
|
|
1982
|
+
}
|
|
1983
|
+
const nodeIndex = Number(pointerSegments[1]);
|
|
1984
|
+
const targetNode = gltf.nodes[nodeIndex];
|
|
1985
|
+
if (!Number.isInteger(nodeIndex) || !targetNode) {
|
|
1986
|
+
import_core8.log.warn(`KHR_animation_pointer target ${pointer} references a missing node and will be skipped`)();
|
|
1987
|
+
return null;
|
|
1988
|
+
}
|
|
1989
|
+
const path = getNodeAnimationPath(pointerSegments[2]);
|
|
1990
|
+
if (!path) {
|
|
1991
|
+
warnUnsupportedAnimationPointer(pointer, `node property "${pointerSegments[2]}" has no runtime animation mapping`);
|
|
1992
|
+
return null;
|
|
1993
|
+
}
|
|
1994
|
+
if (path === "weights") {
|
|
1995
|
+
import_core8.log.warn(`KHR_animation_pointer target ${pointer} will be skipped because morph weights are not implemented in GLTFAnimator`)();
|
|
1996
|
+
return null;
|
|
1997
|
+
}
|
|
1998
|
+
return {
|
|
1999
|
+
type: "node",
|
|
2000
|
+
sampler,
|
|
2001
|
+
targetNodeId: targetNode.id,
|
|
2002
|
+
path
|
|
2003
|
+
};
|
|
2004
|
+
}
|
|
2005
|
+
function parseMaterialPointerAnimationChannel(gltf, pointerSegments, sampler, pointer) {
|
|
2006
|
+
if (pointerSegments.length < 3) {
|
|
2007
|
+
warnUnsupportedAnimationPointer(pointer, "material pointers must include a material index and target property path");
|
|
2008
|
+
return null;
|
|
2009
|
+
}
|
|
2010
|
+
const materialIndex = Number(pointerSegments[1]);
|
|
2011
|
+
const material = gltf.materials[materialIndex];
|
|
2012
|
+
if (!Number.isInteger(materialIndex) || !material) {
|
|
2013
|
+
import_core8.log.warn(`KHR_animation_pointer target ${pointer} references a missing material and will be skipped`)();
|
|
2014
|
+
return null;
|
|
2015
|
+
}
|
|
2016
|
+
const materialTarget = resolveMaterialAnimationTarget(material, pointerSegments.slice(2));
|
|
2017
|
+
if ("reason" in materialTarget) {
|
|
2018
|
+
warnUnsupportedAnimationPointer(pointer, materialTarget.reason);
|
|
2019
|
+
return null;
|
|
2020
|
+
}
|
|
2021
|
+
return {
|
|
2022
|
+
sampler,
|
|
2023
|
+
pointer,
|
|
2024
|
+
targetMaterialIndex: materialIndex,
|
|
2025
|
+
...materialTarget
|
|
2026
|
+
};
|
|
2027
|
+
}
|
|
2028
|
+
function getNodeAnimationPath(path) {
|
|
2029
|
+
switch (path) {
|
|
2030
|
+
case "translation":
|
|
2031
|
+
case "rotation":
|
|
2032
|
+
case "scale":
|
|
2033
|
+
case "weights":
|
|
2034
|
+
return path;
|
|
2035
|
+
default:
|
|
2036
|
+
return null;
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
function resolveMaterialAnimationTarget(material, pointerSegments) {
|
|
2040
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
2041
|
+
const textureTransformTarget = resolveTextureTransformAnimationTarget(material, pointerSegments);
|
|
2042
|
+
if (!("reason" in textureTransformTarget)) {
|
|
2043
|
+
return textureTransformTarget;
|
|
2044
|
+
}
|
|
2045
|
+
if (textureTransformTarget.reason !== "not-a-texture-transform-target") {
|
|
2046
|
+
return textureTransformTarget;
|
|
2047
|
+
}
|
|
2048
|
+
const pointerPath = pointerSegments.join("/");
|
|
2049
|
+
switch (pointerPath) {
|
|
2050
|
+
case "pbrMetallicRoughness/baseColorFactor":
|
|
2051
|
+
return material["pbrMetallicRoughness"] ? { type: "material", property: "baseColorFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2052
|
+
case "pbrMetallicRoughness/metallicFactor":
|
|
2053
|
+
return material["pbrMetallicRoughness"] ? { type: "material", property: "metallicRoughnessValues", component: 0 } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2054
|
+
case "pbrMetallicRoughness/roughnessFactor":
|
|
2055
|
+
return material["pbrMetallicRoughness"] ? { type: "material", property: "metallicRoughnessValues", component: 1 } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2056
|
+
case "normalTexture/scale":
|
|
2057
|
+
return material["normalTexture"] ? { type: "material", property: "normalScale" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2058
|
+
case "occlusionTexture/strength":
|
|
2059
|
+
return material["occlusionTexture"] ? { type: "material", property: "occlusionStrength" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2060
|
+
case "emissiveFactor":
|
|
2061
|
+
return { type: "material", property: "emissiveFactor" };
|
|
2062
|
+
case "alphaCutoff":
|
|
2063
|
+
return { type: "material", property: "alphaCutoff" };
|
|
2064
|
+
case "extensions/KHR_materials_specular/specularFactor":
|
|
2065
|
+
return ((_a = material["extensions"]) == null ? void 0 : _a["KHR_materials_specular"]) ? { type: "material", property: "specularIntensityFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2066
|
+
case "extensions/KHR_materials_specular/specularColorFactor":
|
|
2067
|
+
return ((_b = material["extensions"]) == null ? void 0 : _b["KHR_materials_specular"]) ? { type: "material", property: "specularColorFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2068
|
+
case "extensions/KHR_materials_ior/ior":
|
|
2069
|
+
return ((_c = material["extensions"]) == null ? void 0 : _c["KHR_materials_ior"]) ? { type: "material", property: "ior" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2070
|
+
case "extensions/KHR_materials_transmission/transmissionFactor":
|
|
2071
|
+
return ((_d = material["extensions"]) == null ? void 0 : _d["KHR_materials_transmission"]) ? { type: "material", property: "transmissionFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2072
|
+
case "extensions/KHR_materials_volume/thicknessFactor":
|
|
2073
|
+
return ((_e = material["extensions"]) == null ? void 0 : _e["KHR_materials_volume"]) ? { type: "material", property: "thicknessFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2074
|
+
case "extensions/KHR_materials_volume/attenuationDistance":
|
|
2075
|
+
return ((_f = material["extensions"]) == null ? void 0 : _f["KHR_materials_volume"]) ? { type: "material", property: "attenuationDistance" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2076
|
+
case "extensions/KHR_materials_volume/attenuationColor":
|
|
2077
|
+
return ((_g = material["extensions"]) == null ? void 0 : _g["KHR_materials_volume"]) ? { type: "material", property: "attenuationColor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2078
|
+
case "extensions/KHR_materials_clearcoat/clearcoatFactor":
|
|
2079
|
+
return ((_h = material["extensions"]) == null ? void 0 : _h["KHR_materials_clearcoat"]) ? { type: "material", property: "clearcoatFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2080
|
+
case "extensions/KHR_materials_clearcoat/clearcoatRoughnessFactor":
|
|
2081
|
+
return ((_i = material["extensions"]) == null ? void 0 : _i["KHR_materials_clearcoat"]) ? { type: "material", property: "clearcoatRoughnessFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2082
|
+
case "extensions/KHR_materials_sheen/sheenColorFactor":
|
|
2083
|
+
return ((_j = material["extensions"]) == null ? void 0 : _j["KHR_materials_sheen"]) ? { type: "material", property: "sheenColorFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2084
|
+
case "extensions/KHR_materials_sheen/sheenRoughnessFactor":
|
|
2085
|
+
return ((_k = material["extensions"]) == null ? void 0 : _k["KHR_materials_sheen"]) ? { type: "material", property: "sheenRoughnessFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2086
|
+
case "extensions/KHR_materials_iridescence/iridescenceFactor":
|
|
2087
|
+
return ((_l = material["extensions"]) == null ? void 0 : _l["KHR_materials_iridescence"]) ? { type: "material", property: "iridescenceFactor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2088
|
+
case "extensions/KHR_materials_iridescence/iridescenceIor":
|
|
2089
|
+
return ((_m = material["extensions"]) == null ? void 0 : _m["KHR_materials_iridescence"]) ? { type: "material", property: "iridescenceIor" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2090
|
+
case "extensions/KHR_materials_iridescence/iridescenceThicknessMinimum":
|
|
2091
|
+
return ((_n = material["extensions"]) == null ? void 0 : _n["KHR_materials_iridescence"]) ? { type: "material", property: "iridescenceThicknessRange", component: 0 } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2092
|
+
case "extensions/KHR_materials_iridescence/iridescenceThicknessMaximum":
|
|
2093
|
+
return ((_o = material["extensions"]) == null ? void 0 : _o["KHR_materials_iridescence"]) ? { type: "material", property: "iridescenceThicknessRange", component: 1 } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2094
|
+
case "extensions/KHR_materials_anisotropy/anisotropyStrength":
|
|
2095
|
+
return ((_p = material["extensions"]) == null ? void 0 : _p["KHR_materials_anisotropy"]) ? { type: "material", property: "anisotropyStrength" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2096
|
+
case "extensions/KHR_materials_anisotropy/anisotropyRotation":
|
|
2097
|
+
return ((_q = material["extensions"]) == null ? void 0 : _q["KHR_materials_anisotropy"]) ? { type: "material", property: "anisotropyRotation" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2098
|
+
case "extensions/KHR_materials_emissive_strength/emissiveStrength":
|
|
2099
|
+
return ((_r = material["extensions"]) == null ? void 0 : _r["KHR_materials_emissive_strength"]) ? { type: "material", property: "emissiveStrength" } : { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2100
|
+
default:
|
|
2101
|
+
return { reason: getUnsupportedMaterialPointerReason(pointerSegments) };
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
function resolveTextureTransformAnimationTarget(material, pointerSegments) {
|
|
2105
|
+
const extensionIndex = pointerSegments.lastIndexOf("extensions");
|
|
2106
|
+
if (extensionIndex < 0 || pointerSegments[extensionIndex + 1] !== "KHR_texture_transform" || extensionIndex < 1) {
|
|
2107
|
+
return { reason: "not-a-texture-transform-target" };
|
|
2108
|
+
}
|
|
2109
|
+
const textureSlotDefinition = resolveTextureTransformSlot(pointerSegments.slice(0, extensionIndex));
|
|
2110
|
+
if (!textureSlotDefinition) {
|
|
2111
|
+
return {
|
|
2112
|
+
reason: getUnsupportedTextureTransformSlotReason(pointerSegments.slice(0, extensionIndex))
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
const textureInfo = getNestedMaterialValue(material, textureSlotDefinition.pathSegments);
|
|
2116
|
+
if (!textureInfo) {
|
|
2117
|
+
return {
|
|
2118
|
+
reason: `texture-transform target "${pointerSegments.slice(0, extensionIndex).join("/")}" does not exist on the referenced material`
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
const textureTransformPath = pointerSegments[extensionIndex + 2];
|
|
2122
|
+
if (textureTransformPath === "texCoord") {
|
|
2123
|
+
return {
|
|
2124
|
+
reason: "animated KHR_texture_transform.texCoord is unsupported because texCoord selection is structural, not a runtime float/vector update"
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
if (textureTransformPath !== "offset" && textureTransformPath !== "rotation" && textureTransformPath !== "scale") {
|
|
2128
|
+
return {
|
|
2129
|
+
reason: `KHR_texture_transform property "${textureTransformPath}" is not animatable; supported properties are offset, rotation, and scale`
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
const componentSegment = pointerSegments[extensionIndex + 3];
|
|
2133
|
+
if (pointerSegments.length > extensionIndex + 4) {
|
|
2134
|
+
return {
|
|
2135
|
+
reason: `KHR_texture_transform.${textureTransformPath} does not support nested property paths`
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
let component;
|
|
2139
|
+
if (componentSegment !== void 0) {
|
|
2140
|
+
component = Number(componentSegment);
|
|
2141
|
+
if (textureTransformPath === "rotation") {
|
|
2142
|
+
return {
|
|
2143
|
+
reason: "KHR_texture_transform.rotation does not support component indices"
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
if (!Number.isInteger(component) || component < 0 || component > 1) {
|
|
2147
|
+
return {
|
|
2148
|
+
reason: `KHR_texture_transform.${textureTransformPath} component index "${componentSegment}" is invalid; only 0 and 1 are supported`
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
return {
|
|
2153
|
+
type: "textureTransform",
|
|
2154
|
+
textureSlot: textureSlotDefinition.slot,
|
|
2155
|
+
path: textureTransformPath,
|
|
2156
|
+
component,
|
|
2157
|
+
baseTransform: resolveTextureTransform(textureInfo)
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
function getNestedMaterialValue(material, pathSegments) {
|
|
2161
|
+
let value = material;
|
|
2162
|
+
for (const pathSegment of pathSegments) {
|
|
2163
|
+
value = value == null ? void 0 : value[pathSegment];
|
|
2164
|
+
if (!value) {
|
|
2165
|
+
return null;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
return value;
|
|
2169
|
+
}
|
|
2170
|
+
function splitJsonPointer(pointer) {
|
|
2171
|
+
return pointer.slice(1).split("/").map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
2172
|
+
}
|
|
2173
|
+
function getUnsupportedMaterialPointerReason(pointerSegments) {
|
|
2174
|
+
const extensionName = getPointerExtensionName(pointerSegments);
|
|
2175
|
+
if (extensionName) {
|
|
2176
|
+
const extensionSupport = getRegisteredGLTFExtensionSupport(extensionName);
|
|
2177
|
+
if ((extensionSupport == null ? void 0 : extensionSupport.supportLevel) === "none") {
|
|
2178
|
+
return `${extensionName} is referenced by this pointer, but ${extensionSupport.comment.charAt(0).toLowerCase()}${extensionSupport.comment.slice(1)}`;
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
return `no runtime target exists for material property "${pointerSegments.join("/")}"`;
|
|
2182
|
+
}
|
|
2183
|
+
function getUnsupportedTextureTransformSlotReason(pointerSegments) {
|
|
2184
|
+
const extensionName = getPointerExtensionName(pointerSegments);
|
|
2185
|
+
if (extensionName) {
|
|
2186
|
+
const extensionSupport = getRegisteredGLTFExtensionSupport(extensionName);
|
|
2187
|
+
if ((extensionSupport == null ? void 0 : extensionSupport.supportLevel) === "none") {
|
|
2188
|
+
return `${extensionName} is referenced by this pointer, but ${extensionSupport.comment.charAt(0).toLowerCase()}${extensionSupport.comment.slice(1)}`;
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
return `texture-transform target "${pointerSegments.join("/")}" has no runtime texture-slot mapping`;
|
|
2192
|
+
}
|
|
2193
|
+
function getPointerExtensionName(pointerSegments) {
|
|
2194
|
+
const extensionIndex = pointerSegments.indexOf("extensions");
|
|
2195
|
+
const extensionName = pointerSegments[extensionIndex + 1];
|
|
2196
|
+
return extensionIndex >= 0 && extensionName ? extensionName : null;
|
|
2197
|
+
}
|
|
2198
|
+
function warnUnsupportedAnimationPointer(pointer, reason) {
|
|
2199
|
+
import_core8.log.warn(`KHR_animation_pointer target ${pointer} will be skipped because ${reason}`)();
|
|
2200
|
+
}
|
|
2201
|
+
function accessorToJsArray1D(accessor, accessorCache) {
|
|
2202
|
+
if (accessorCache.has(accessor)) {
|
|
2203
|
+
return accessorCache.get(accessor);
|
|
2204
|
+
}
|
|
2205
|
+
const { typedArray: array, components } = accessorToTypedArray(accessor);
|
|
2206
|
+
assert(components === 1, "accessorToJsArray1D must have exactly 1 component");
|
|
2207
|
+
const result = Array.from(array);
|
|
2208
|
+
accessorCache.set(accessor, result);
|
|
2209
|
+
return result;
|
|
2210
|
+
}
|
|
2211
|
+
function accessorToJsArray2D(accessor, accessorCache) {
|
|
2212
|
+
if (accessorCache.has(accessor)) {
|
|
2213
|
+
return accessorCache.get(accessor);
|
|
2214
|
+
}
|
|
2215
|
+
const { typedArray: array, components } = accessorToTypedArray(accessor);
|
|
2216
|
+
assert(components >= 1, "accessorToJsArray2D must have at least 1 component");
|
|
2217
|
+
const result = [];
|
|
2218
|
+
for (let i = 0; i < array.length; i += components) {
|
|
2219
|
+
result.push(Array.from(array.slice(i, i + components)));
|
|
2220
|
+
}
|
|
2221
|
+
accessorCache.set(accessor, result);
|
|
2222
|
+
return result;
|
|
2223
|
+
}
|
|
2224
|
+
function assert(condition, message) {
|
|
2225
|
+
if (!condition) {
|
|
2226
|
+
throw new Error(message);
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
|
|
1739
2230
|
// dist/gltf/create-scenegraph-from-gltf.js
|
|
1740
2231
|
function createScenegraphsFromGLTF(device, gltf, options) {
|
|
1741
2232
|
const { scenes, materials, gltfMeshIdToNodeMap, gltfNodeIdToNodeMap, gltfNodeIndexToNodeMap } = parseGLTF(device, gltf, options);
|
|
1742
2233
|
const animations = parseGLTFAnimations(gltf);
|
|
1743
|
-
const animator = new GLTFAnimator({ animations, gltfNodeIdToNodeMap });
|
|
1744
|
-
const lights = parseGLTFLights(gltf);
|
|
2234
|
+
const animator = new GLTFAnimator({ animations, gltfNodeIdToNodeMap, materials });
|
|
2235
|
+
const lights = parseGLTFLights(gltf, { useByteColors: (options == null ? void 0 : options.useByteColors) ?? true });
|
|
1745
2236
|
const extensionSupport = getGLTFExtensionSupport(gltf);
|
|
1746
2237
|
const sceneBounds = scenes.map((scene) => getScenegraphBounds(scene.getBounds()));
|
|
1747
2238
|
const modelBounds = getCombinedScenegraphBounds(sceneBounds);
|