@luma.gl/gltf 9.3.0-alpha.4 → 9.3.0-alpha.8
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 +1305 -327
- package/dist/dist.min.js +98 -46
- package/dist/gltf/animations/animations.d.ts +16 -4
- package/dist/gltf/animations/animations.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.d.ts +4 -3
- package/dist/gltf/animations/interpolate.d.ts.map +1 -1
- package/dist/gltf/animations/interpolate.js +27 -36
- package/dist/gltf/animations/interpolate.js.map +1 -1
- package/dist/gltf/create-gltf-model.d.ts +15 -1
- package/dist/gltf/create-gltf-model.d.ts.map +1 -1
- package/dist/gltf/create-gltf-model.js +154 -48
- package/dist/gltf/create-gltf-model.js.map +1 -1
- package/dist/gltf/create-scenegraph-from-gltf.d.ts +37 -2
- package/dist/gltf/create-scenegraph-from-gltf.d.ts.map +1 -1
- package/dist/gltf/create-scenegraph-from-gltf.js +74 -6
- package/dist/gltf/create-scenegraph-from-gltf.js.map +1 -1
- package/dist/gltf/gltf-animator.d.ts +26 -0
- package/dist/gltf/gltf-animator.d.ts.map +1 -1
- package/dist/gltf/gltf-animator.js +22 -19
- package/dist/gltf/gltf-animator.js.map +1 -1
- package/dist/gltf/gltf-extension-support.d.ts +10 -0
- package/dist/gltf/gltf-extension-support.d.ts.map +1 -0
- package/dist/gltf/gltf-extension-support.js +173 -0
- package/dist/gltf/gltf-extension-support.js.map +1 -0
- package/dist/index.cjs +1247 -294
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/parsers/parse-gltf-animations.d.ts +1 -0
- package/dist/parsers/parse-gltf-animations.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-animations.js +73 -28
- package/dist/parsers/parse-gltf-animations.js.map +1 -1
- package/dist/parsers/parse-gltf-lights.d.ts.map +1 -1
- package/dist/parsers/parse-gltf-lights.js +112 -18
- package/dist/parsers/parse-gltf-lights.js.map +1 -1
- package/dist/parsers/parse-gltf.d.ts +19 -2
- package/dist/parsers/parse-gltf.d.ts.map +1 -1
- package/dist/parsers/parse-gltf.js +101 -61
- package/dist/parsers/parse-gltf.js.map +1 -1
- package/dist/parsers/parse-pbr-material.d.ts +115 -2
- package/dist/parsers/parse-pbr-material.d.ts.map +1 -1
- package/dist/parsers/parse-pbr-material.js +565 -54
- package/dist/parsers/parse-pbr-material.js.map +1 -1
- package/dist/pbr/pbr-environment.d.ts +6 -0
- package/dist/pbr/pbr-environment.d.ts.map +1 -1
- package/dist/pbr/pbr-environment.js +15 -12
- package/dist/pbr/pbr-environment.js.map +1 -1
- package/dist/pbr/pbr-material.d.ts +13 -3
- package/dist/pbr/pbr-material.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts +12 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-attribute.js +3 -0
- package/dist/webgl-to-webgpu/convert-webgl-attribute.js.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts +11 -5
- package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-sampler.js +16 -12
- package/dist/webgl-to-webgpu/convert-webgl-sampler.js.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts +2 -9
- package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts.map +1 -1
- package/dist/webgl-to-webgpu/convert-webgl-topology.js +2 -14
- package/dist/webgl-to-webgpu/convert-webgl-topology.js.map +1 -1
- package/dist/webgl-to-webgpu/gltf-webgl-constants.d.ts +27 -0
- package/dist/webgl-to-webgpu/gltf-webgl-constants.d.ts.map +1 -0
- package/dist/webgl-to-webgpu/gltf-webgl-constants.js +34 -0
- package/dist/webgl-to-webgpu/gltf-webgl-constants.js.map +1 -0
- package/package.json +8 -9
- package/src/gltf/animations/animations.ts +17 -5
- package/src/gltf/animations/interpolate.ts +49 -68
- package/src/gltf/create-gltf-model.ts +214 -48
- package/src/gltf/create-scenegraph-from-gltf.ts +131 -12
- package/src/gltf/gltf-animator.ts +34 -25
- package/src/gltf/gltf-extension-support.ts +214 -0
- package/src/index.ts +10 -2
- package/src/parsers/parse-gltf-animations.ts +94 -33
- package/src/parsers/parse-gltf-lights.ts +147 -20
- package/src/parsers/parse-gltf.ts +170 -90
- package/src/parsers/parse-pbr-material.ts +865 -80
- package/src/pbr/pbr-environment.ts +38 -15
- package/src/pbr/pbr-material.ts +18 -3
- package/src/webgl-to-webgpu/convert-webgl-attribute.ts +12 -1
- package/src/webgl-to-webgpu/convert-webgl-sampler.ts +38 -29
- package/src/webgl-to-webgpu/convert-webgl-topology.ts +2 -14
- package/src/webgl-to-webgpu/gltf-webgl-constants.ts +35 -0
- package/dist/utils/deep-copy.d.ts +0 -3
- package/dist/utils/deep-copy.d.ts.map +0 -1
- package/dist/utils/deep-copy.js +0 -21
- package/dist/utils/deep-copy.js.map +0 -1
- package/src/utils/deep-copy.ts +0 -22
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var dist_exports = {};
|
|
|
22
22
|
__export(dist_exports, {
|
|
23
23
|
GLTFAnimator: () => GLTFAnimator,
|
|
24
24
|
createScenegraphsFromGLTF: () => createScenegraphsFromGLTF,
|
|
25
|
+
getGLTFExtensionSupport: () => getGLTFExtensionSupport,
|
|
25
26
|
loadPBREnvironment: () => loadPBREnvironment,
|
|
26
27
|
parseGLTFLights: () => parseGLTFLights,
|
|
27
28
|
parsePBRMaterial: () => parsePBRMaterial
|
|
@@ -32,6 +33,7 @@ module.exports = __toCommonJS(dist_exports);
|
|
|
32
33
|
var import_engine = require("@luma.gl/engine");
|
|
33
34
|
var import_textures = require("@loaders.gl/textures");
|
|
34
35
|
function loadPBREnvironment(device, props) {
|
|
36
|
+
const specularMipLevels = props.specularMipLevels ?? 1;
|
|
35
37
|
const brdfLutTexture = new import_engine.DynamicTexture(device, {
|
|
36
38
|
id: "brdfLUT",
|
|
37
39
|
sampler: {
|
|
@@ -45,7 +47,7 @@ function loadPBREnvironment(device, props) {
|
|
|
45
47
|
});
|
|
46
48
|
const diffuseEnvSampler = makeCube(device, {
|
|
47
49
|
id: "DiffuseEnvSampler",
|
|
48
|
-
getTextureForFace: (
|
|
50
|
+
getTextureForFace: (face) => (0, import_textures.loadImageTexture)(props.getTexUrl("diffuse", FACES.indexOf(face), 0)),
|
|
49
51
|
sampler: {
|
|
50
52
|
addressModeU: "clamp-to-edge",
|
|
51
53
|
addressModeV: "clamp-to-edge",
|
|
@@ -55,12 +57,13 @@ function loadPBREnvironment(device, props) {
|
|
|
55
57
|
});
|
|
56
58
|
const specularEnvSampler = makeCube(device, {
|
|
57
59
|
id: "SpecularEnvSampler",
|
|
58
|
-
getTextureForFace: (
|
|
60
|
+
getTextureForFace: (face) => {
|
|
59
61
|
const imageArray = [];
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
const direction = FACES.indexOf(face);
|
|
63
|
+
for (let lod = 0; lod < specularMipLevels; lod++) {
|
|
64
|
+
imageArray.push((0, import_textures.loadImageTexture)(props.getTexUrl("specular", direction, lod)));
|
|
62
65
|
}
|
|
63
|
-
return imageArray;
|
|
66
|
+
return Promise.all(imageArray);
|
|
64
67
|
},
|
|
65
68
|
sampler: {
|
|
66
69
|
addressModeU: "clamp-to-edge",
|
|
@@ -76,28 +79,57 @@ function loadPBREnvironment(device, props) {
|
|
|
76
79
|
specularEnvSampler
|
|
77
80
|
};
|
|
78
81
|
}
|
|
79
|
-
var FACES = [
|
|
82
|
+
var FACES = ["+X", "-X", "+Y", "-Y", "+Z", "-Z"];
|
|
80
83
|
function makeCube(device, { id, getTextureForFace, sampler }) {
|
|
81
|
-
const data = {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
const data = Promise.all(FACES.map((face) => getTextureForFace(face))).then((faceDataArray) => {
|
|
85
|
+
const cubeData = {};
|
|
86
|
+
FACES.forEach((face, index) => {
|
|
87
|
+
cubeData[face] = faceDataArray[index];
|
|
88
|
+
});
|
|
89
|
+
return cubeData;
|
|
84
90
|
});
|
|
85
91
|
return new import_engine.DynamicTexture(device, {
|
|
86
92
|
id,
|
|
87
93
|
dimension: "cube",
|
|
88
94
|
mipmaps: false,
|
|
89
95
|
sampler,
|
|
90
|
-
// @ts-expect-error
|
|
91
96
|
data
|
|
92
97
|
});
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
// dist/parsers/parse-pbr-material.js
|
|
96
|
-
var import_constants2 = require("@luma.gl/constants");
|
|
97
101
|
var import_core = require("@luma.gl/core");
|
|
98
102
|
|
|
103
|
+
// dist/webgl-to-webgpu/gltf-webgl-constants.js
|
|
104
|
+
var GLEnum;
|
|
105
|
+
(function(GLEnum2) {
|
|
106
|
+
GLEnum2[GLEnum2["POINTS"] = 0] = "POINTS";
|
|
107
|
+
GLEnum2[GLEnum2["LINES"] = 1] = "LINES";
|
|
108
|
+
GLEnum2[GLEnum2["LINE_LOOP"] = 2] = "LINE_LOOP";
|
|
109
|
+
GLEnum2[GLEnum2["LINE_STRIP"] = 3] = "LINE_STRIP";
|
|
110
|
+
GLEnum2[GLEnum2["TRIANGLES"] = 4] = "TRIANGLES";
|
|
111
|
+
GLEnum2[GLEnum2["TRIANGLE_STRIP"] = 5] = "TRIANGLE_STRIP";
|
|
112
|
+
GLEnum2[GLEnum2["TRIANGLE_FAN"] = 6] = "TRIANGLE_FAN";
|
|
113
|
+
GLEnum2[GLEnum2["ONE"] = 1] = "ONE";
|
|
114
|
+
GLEnum2[GLEnum2["SRC_ALPHA"] = 770] = "SRC_ALPHA";
|
|
115
|
+
GLEnum2[GLEnum2["ONE_MINUS_SRC_ALPHA"] = 771] = "ONE_MINUS_SRC_ALPHA";
|
|
116
|
+
GLEnum2[GLEnum2["FUNC_ADD"] = 32774] = "FUNC_ADD";
|
|
117
|
+
GLEnum2[GLEnum2["LINEAR"] = 9729] = "LINEAR";
|
|
118
|
+
GLEnum2[GLEnum2["NEAREST"] = 9728] = "NEAREST";
|
|
119
|
+
GLEnum2[GLEnum2["NEAREST_MIPMAP_NEAREST"] = 9984] = "NEAREST_MIPMAP_NEAREST";
|
|
120
|
+
GLEnum2[GLEnum2["LINEAR_MIPMAP_NEAREST"] = 9985] = "LINEAR_MIPMAP_NEAREST";
|
|
121
|
+
GLEnum2[GLEnum2["NEAREST_MIPMAP_LINEAR"] = 9986] = "NEAREST_MIPMAP_LINEAR";
|
|
122
|
+
GLEnum2[GLEnum2["LINEAR_MIPMAP_LINEAR"] = 9987] = "LINEAR_MIPMAP_LINEAR";
|
|
123
|
+
GLEnum2[GLEnum2["TEXTURE_MIN_FILTER"] = 10241] = "TEXTURE_MIN_FILTER";
|
|
124
|
+
GLEnum2[GLEnum2["TEXTURE_WRAP_S"] = 10242] = "TEXTURE_WRAP_S";
|
|
125
|
+
GLEnum2[GLEnum2["TEXTURE_WRAP_T"] = 10243] = "TEXTURE_WRAP_T";
|
|
126
|
+
GLEnum2[GLEnum2["REPEAT"] = 10497] = "REPEAT";
|
|
127
|
+
GLEnum2[GLEnum2["CLAMP_TO_EDGE"] = 33071] = "CLAMP_TO_EDGE";
|
|
128
|
+
GLEnum2[GLEnum2["MIRRORED_REPEAT"] = 33648] = "MIRRORED_REPEAT";
|
|
129
|
+
GLEnum2[GLEnum2["UNPACK_FLIP_Y_WEBGL"] = 37440] = "UNPACK_FLIP_Y_WEBGL";
|
|
130
|
+
})(GLEnum || (GLEnum = {}));
|
|
131
|
+
|
|
99
132
|
// dist/webgl-to-webgpu/convert-webgl-sampler.js
|
|
100
|
-
var import_constants = require("@luma.gl/constants");
|
|
101
133
|
function convertSampler(gltfSampler) {
|
|
102
134
|
return {
|
|
103
135
|
addressModeU: convertSamplerWrapMode(gltfSampler.wrapS),
|
|
@@ -108,11 +140,11 @@ function convertSampler(gltfSampler) {
|
|
|
108
140
|
}
|
|
109
141
|
function convertSamplerWrapMode(mode) {
|
|
110
142
|
switch (mode) {
|
|
111
|
-
case
|
|
143
|
+
case GLEnum.CLAMP_TO_EDGE:
|
|
112
144
|
return "clamp-to-edge";
|
|
113
|
-
case
|
|
145
|
+
case GLEnum.REPEAT:
|
|
114
146
|
return "repeat";
|
|
115
|
-
case
|
|
147
|
+
case GLEnum.MIRRORED_REPEAT:
|
|
116
148
|
return "mirror-repeat";
|
|
117
149
|
default:
|
|
118
150
|
return void 0;
|
|
@@ -120,9 +152,9 @@ function convertSamplerWrapMode(mode) {
|
|
|
120
152
|
}
|
|
121
153
|
function convertSamplerMagFilter(mode) {
|
|
122
154
|
switch (mode) {
|
|
123
|
-
case
|
|
155
|
+
case GLEnum.NEAREST:
|
|
124
156
|
return "nearest";
|
|
125
|
-
case
|
|
157
|
+
case GLEnum.LINEAR:
|
|
126
158
|
return "linear";
|
|
127
159
|
default:
|
|
128
160
|
return void 0;
|
|
@@ -130,17 +162,17 @@ function convertSamplerMagFilter(mode) {
|
|
|
130
162
|
}
|
|
131
163
|
function convertSamplerMinFilter(mode) {
|
|
132
164
|
switch (mode) {
|
|
133
|
-
case
|
|
165
|
+
case GLEnum.NEAREST:
|
|
134
166
|
return { minFilter: "nearest" };
|
|
135
|
-
case
|
|
167
|
+
case GLEnum.LINEAR:
|
|
136
168
|
return { minFilter: "linear" };
|
|
137
|
-
case
|
|
169
|
+
case GLEnum.NEAREST_MIPMAP_NEAREST:
|
|
138
170
|
return { minFilter: "nearest", mipmapFilter: "nearest" };
|
|
139
|
-
case
|
|
171
|
+
case GLEnum.LINEAR_MIPMAP_NEAREST:
|
|
140
172
|
return { minFilter: "linear", mipmapFilter: "nearest" };
|
|
141
|
-
case
|
|
173
|
+
case GLEnum.NEAREST_MIPMAP_LINEAR:
|
|
142
174
|
return { minFilter: "nearest", mipmapFilter: "linear" };
|
|
143
|
-
case
|
|
175
|
+
case GLEnum.LINEAR_MIPMAP_LINEAR:
|
|
144
176
|
return { minFilter: "linear", mipmapFilter: "linear" };
|
|
145
177
|
default:
|
|
146
178
|
return {};
|
|
@@ -172,7 +204,8 @@ function parsePBRMaterial(device, material, attributes, options) {
|
|
|
172
204
|
if (imageBasedLightingEnvironment) {
|
|
173
205
|
parsedMaterial.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.diffuseEnvSampler.texture;
|
|
174
206
|
parsedMaterial.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.specularEnvSampler.texture;
|
|
175
|
-
parsedMaterial.bindings.
|
|
207
|
+
parsedMaterial.bindings.pbr_brdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
|
|
208
|
+
parsedMaterial.uniforms.IBLenabled = true;
|
|
176
209
|
parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];
|
|
177
210
|
}
|
|
178
211
|
if (options == null ? void 0 : options.pbrDebug) {
|
|
@@ -186,6 +219,8 @@ function parsePBRMaterial(device, material, attributes, options) {
|
|
|
186
219
|
parsedMaterial.defines["HAS_TANGENTS"] = true;
|
|
187
220
|
if (attributes["TEXCOORD_0"])
|
|
188
221
|
parsedMaterial.defines["HAS_UV"] = true;
|
|
222
|
+
if (attributes["JOINTS_0"] && attributes["WEIGHTS_0"])
|
|
223
|
+
parsedMaterial.defines["HAS_SKIN"] = true;
|
|
189
224
|
if (attributes["COLOR_0"])
|
|
190
225
|
parsedMaterial.defines["HAS_COLORS"] = true;
|
|
191
226
|
if (options == null ? void 0 : options.imageBasedLightingEnvironment)
|
|
@@ -193,74 +228,418 @@ function parsePBRMaterial(device, material, attributes, options) {
|
|
|
193
228
|
if (options == null ? void 0 : options.lights)
|
|
194
229
|
parsedMaterial.defines["USE_LIGHTS"] = true;
|
|
195
230
|
if (material) {
|
|
196
|
-
|
|
231
|
+
if (options.validateAttributes !== false) {
|
|
232
|
+
warnOnMissingExpectedAttributes(material, attributes);
|
|
233
|
+
}
|
|
234
|
+
parseMaterial(device, material, parsedMaterial, options.gltf);
|
|
197
235
|
}
|
|
198
236
|
return parsedMaterial;
|
|
199
237
|
}
|
|
200
|
-
function
|
|
201
|
-
|
|
238
|
+
function warnOnMissingExpectedAttributes(material, attributes) {
|
|
239
|
+
var _a;
|
|
240
|
+
const uvDependentTextureSlots = getUvDependentTextureSlots(material);
|
|
241
|
+
if (uvDependentTextureSlots.length > 0 && !attributes["TEXCOORD_0"]) {
|
|
242
|
+
import_core.log.warn(`glTF material uses ${uvDependentTextureSlots.join(", ")} but primitive is missing TEXCOORD_0; textured shading will sample the default UV coordinates`)();
|
|
243
|
+
}
|
|
244
|
+
const isUnlitMaterial = Boolean(material.unlit || ((_a = material.extensions) == null ? void 0 : _a.KHR_materials_unlit));
|
|
245
|
+
if (isUnlitMaterial || attributes["NORMAL"]) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const missingNormalReason = material.normalTexture ? "lit PBR shading with normalTexture" : "lit PBR shading";
|
|
249
|
+
import_core.log.warn(`glTF primitive is missing NORMAL while using ${missingNormalReason}; shading will fall back to geometric normals`)();
|
|
250
|
+
}
|
|
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;
|
|
253
|
+
const uvDependentTextureSlots = [];
|
|
254
|
+
if ((_a = material.pbrMetallicRoughness) == null ? void 0 : _a.baseColorTexture) {
|
|
255
|
+
uvDependentTextureSlots.push("baseColorTexture");
|
|
256
|
+
}
|
|
257
|
+
if ((_b = material.pbrMetallicRoughness) == null ? void 0 : _b.metallicRoughnessTexture) {
|
|
258
|
+
uvDependentTextureSlots.push("metallicRoughnessTexture");
|
|
259
|
+
}
|
|
260
|
+
if (material.normalTexture) {
|
|
261
|
+
uvDependentTextureSlots.push("normalTexture");
|
|
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");
|
|
295
|
+
}
|
|
296
|
+
return uvDependentTextureSlots;
|
|
297
|
+
}
|
|
298
|
+
function parseMaterial(device, material, parsedMaterial, gltf) {
|
|
299
|
+
var _a;
|
|
300
|
+
parsedMaterial.uniforms.unlit = Boolean(material.unlit || ((_a = material.extensions) == null ? void 0 : _a.KHR_materials_unlit));
|
|
202
301
|
if (material.pbrMetallicRoughness) {
|
|
203
|
-
parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);
|
|
302
|
+
parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial, gltf);
|
|
204
303
|
}
|
|
205
304
|
if (material.normalTexture) {
|
|
206
|
-
addTexture(device, material.normalTexture, "pbr_normalSampler",
|
|
305
|
+
addTexture(device, material.normalTexture, "pbr_normalSampler", parsedMaterial, {
|
|
306
|
+
featureOptions: {
|
|
307
|
+
define: "HAS_NORMALMAP",
|
|
308
|
+
enabledUniformName: "normalMapEnabled"
|
|
309
|
+
},
|
|
310
|
+
gltf
|
|
311
|
+
});
|
|
207
312
|
const { scale = 1 } = material.normalTexture;
|
|
208
313
|
parsedMaterial.uniforms.normalScale = scale;
|
|
209
314
|
}
|
|
210
315
|
if (material.occlusionTexture) {
|
|
211
|
-
addTexture(device, material.occlusionTexture, "pbr_occlusionSampler",
|
|
316
|
+
addTexture(device, material.occlusionTexture, "pbr_occlusionSampler", parsedMaterial, {
|
|
317
|
+
featureOptions: {
|
|
318
|
+
define: "HAS_OCCLUSIONMAP",
|
|
319
|
+
enabledUniformName: "occlusionMapEnabled"
|
|
320
|
+
},
|
|
321
|
+
gltf
|
|
322
|
+
});
|
|
212
323
|
const { strength = 1 } = material.occlusionTexture;
|
|
213
324
|
parsedMaterial.uniforms.occlusionStrength = strength;
|
|
214
325
|
}
|
|
326
|
+
parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
|
|
215
327
|
if (material.emissiveTexture) {
|
|
216
|
-
addTexture(device, material.emissiveTexture, "pbr_emissiveSampler",
|
|
217
|
-
|
|
328
|
+
addTexture(device, material.emissiveTexture, "pbr_emissiveSampler", parsedMaterial, {
|
|
329
|
+
featureOptions: {
|
|
330
|
+
define: "HAS_EMISSIVEMAP",
|
|
331
|
+
enabledUniformName: "emissiveMapEnabled"
|
|
332
|
+
},
|
|
333
|
+
gltf
|
|
334
|
+
});
|
|
218
335
|
}
|
|
219
|
-
|
|
220
|
-
|
|
336
|
+
parseMaterialExtensions(device, material.extensions, parsedMaterial, gltf);
|
|
337
|
+
switch (material.alphaMode || "OPAQUE") {
|
|
338
|
+
case "OPAQUE":
|
|
339
|
+
break;
|
|
340
|
+
case "MASK": {
|
|
221
341
|
const { alphaCutoff = 0.5 } = material;
|
|
222
342
|
parsedMaterial.defines["ALPHA_CUTOFF"] = true;
|
|
343
|
+
parsedMaterial.uniforms.alphaCutoffEnabled = true;
|
|
223
344
|
parsedMaterial.uniforms.alphaCutoff = alphaCutoff;
|
|
224
345
|
break;
|
|
346
|
+
}
|
|
225
347
|
case "BLEND":
|
|
226
348
|
import_core.log.warn("glTF BLEND alphaMode might not work well because it requires mesh sorting")();
|
|
227
|
-
parsedMaterial
|
|
228
|
-
parsedMaterial.parameters.blendColorOperation = "add";
|
|
229
|
-
parsedMaterial.parameters.blendColorSrcFactor = "src-alpha";
|
|
230
|
-
parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
|
|
231
|
-
parsedMaterial.parameters.blendAlphaOperation = "add";
|
|
232
|
-
parsedMaterial.parameters.blendAlphaSrcFactor = "one";
|
|
233
|
-
parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
|
|
234
|
-
parsedMaterial.glParameters["blend"] = true;
|
|
235
|
-
parsedMaterial.glParameters["blendEquation"] = 32774;
|
|
236
|
-
parsedMaterial.glParameters["blendFunc"] = [
|
|
237
|
-
770,
|
|
238
|
-
771,
|
|
239
|
-
1,
|
|
240
|
-
771
|
|
241
|
-
];
|
|
349
|
+
applyAlphaBlendParameters(parsedMaterial);
|
|
242
350
|
break;
|
|
243
351
|
}
|
|
244
352
|
}
|
|
245
|
-
function
|
|
353
|
+
function applyAlphaBlendParameters(parsedMaterial) {
|
|
354
|
+
parsedMaterial.parameters.blend = true;
|
|
355
|
+
parsedMaterial.parameters.blendColorOperation = "add";
|
|
356
|
+
parsedMaterial.parameters.blendColorSrcFactor = "src-alpha";
|
|
357
|
+
parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
|
|
358
|
+
parsedMaterial.parameters.blendAlphaOperation = "add";
|
|
359
|
+
parsedMaterial.parameters.blendAlphaSrcFactor = "one";
|
|
360
|
+
parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
|
|
361
|
+
parsedMaterial.glParameters["blend"] = true;
|
|
362
|
+
parsedMaterial.glParameters["blendEquation"] = GLEnum.FUNC_ADD;
|
|
363
|
+
parsedMaterial.glParameters["blendFunc"] = [
|
|
364
|
+
GLEnum.SRC_ALPHA,
|
|
365
|
+
GLEnum.ONE_MINUS_SRC_ALPHA,
|
|
366
|
+
GLEnum.ONE,
|
|
367
|
+
GLEnum.ONE_MINUS_SRC_ALPHA
|
|
368
|
+
];
|
|
369
|
+
}
|
|
370
|
+
function applyTransmissionBlendApproximation(parsedMaterial) {
|
|
371
|
+
parsedMaterial.parameters.blend = true;
|
|
372
|
+
parsedMaterial.parameters.depthWriteEnabled = false;
|
|
373
|
+
parsedMaterial.parameters.blendColorOperation = "add";
|
|
374
|
+
parsedMaterial.parameters.blendColorSrcFactor = "one";
|
|
375
|
+
parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
|
|
376
|
+
parsedMaterial.parameters.blendAlphaOperation = "add";
|
|
377
|
+
parsedMaterial.parameters.blendAlphaSrcFactor = "one";
|
|
378
|
+
parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
|
|
379
|
+
parsedMaterial.glParameters["blend"] = true;
|
|
380
|
+
parsedMaterial.glParameters["depthMask"] = false;
|
|
381
|
+
parsedMaterial.glParameters["blendEquation"] = GLEnum.FUNC_ADD;
|
|
382
|
+
parsedMaterial.glParameters["blendFunc"] = [
|
|
383
|
+
GLEnum.ONE,
|
|
384
|
+
GLEnum.ONE_MINUS_SRC_ALPHA,
|
|
385
|
+
GLEnum.ONE,
|
|
386
|
+
GLEnum.ONE_MINUS_SRC_ALPHA
|
|
387
|
+
];
|
|
388
|
+
}
|
|
389
|
+
function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial, gltf) {
|
|
246
390
|
if (pbrMetallicRoughness.baseColorTexture) {
|
|
247
|
-
addTexture(device, pbrMetallicRoughness.baseColorTexture, "pbr_baseColorSampler",
|
|
391
|
+
addTexture(device, pbrMetallicRoughness.baseColorTexture, "pbr_baseColorSampler", parsedMaterial, {
|
|
392
|
+
featureOptions: {
|
|
393
|
+
define: "HAS_BASECOLORMAP",
|
|
394
|
+
enabledUniformName: "baseColorMapEnabled"
|
|
395
|
+
},
|
|
396
|
+
gltf
|
|
397
|
+
});
|
|
248
398
|
}
|
|
249
399
|
parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
|
|
250
400
|
if (pbrMetallicRoughness.metallicRoughnessTexture) {
|
|
251
|
-
addTexture(device, pbrMetallicRoughness.metallicRoughnessTexture, "pbr_metallicRoughnessSampler",
|
|
401
|
+
addTexture(device, pbrMetallicRoughness.metallicRoughnessTexture, "pbr_metallicRoughnessSampler", parsedMaterial, {
|
|
402
|
+
featureOptions: {
|
|
403
|
+
define: "HAS_METALROUGHNESSMAP",
|
|
404
|
+
enabledUniformName: "metallicRoughnessMapEnabled"
|
|
405
|
+
},
|
|
406
|
+
gltf
|
|
407
|
+
});
|
|
252
408
|
}
|
|
253
409
|
const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
|
|
254
410
|
parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
|
|
255
411
|
}
|
|
256
|
-
function
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
412
|
+
function parseMaterialExtensions(device, extensions, parsedMaterial, gltf) {
|
|
413
|
+
if (!extensions) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (hasMaterialExtensionShading(extensions)) {
|
|
417
|
+
parsedMaterial.defines["USE_MATERIAL_EXTENSIONS"] = true;
|
|
418
|
+
}
|
|
419
|
+
parseSpecularExtension(device, extensions.KHR_materials_specular, parsedMaterial, gltf);
|
|
420
|
+
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);
|
|
427
|
+
parseEmissiveStrengthExtension(extensions.KHR_materials_emissive_strength, parsedMaterial);
|
|
428
|
+
}
|
|
429
|
+
function hasMaterialExtensionShading(extensions) {
|
|
430
|
+
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
|
+
}
|
|
432
|
+
function parseSpecularExtension(device, extension, parsedMaterial, gltf) {
|
|
433
|
+
if (!extension) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
if (extension.specularColorFactor) {
|
|
437
|
+
parsedMaterial.uniforms.specularColorFactor = extension.specularColorFactor;
|
|
438
|
+
}
|
|
439
|
+
if (extension.specularFactor !== void 0) {
|
|
440
|
+
parsedMaterial.uniforms.specularIntensityFactor = extension.specularFactor;
|
|
441
|
+
}
|
|
442
|
+
if (extension.specularColorTexture) {
|
|
443
|
+
addTexture(device, extension.specularColorTexture, "pbr_specularColorSampler", parsedMaterial, {
|
|
444
|
+
featureOptions: {
|
|
445
|
+
define: "HAS_SPECULARCOLORMAP",
|
|
446
|
+
enabledUniformName: "specularColorMapEnabled"
|
|
447
|
+
},
|
|
448
|
+
gltf
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
if (extension.specularTexture) {
|
|
452
|
+
addTexture(device, extension.specularTexture, "pbr_specularIntensitySampler", parsedMaterial, {
|
|
453
|
+
featureOptions: {
|
|
454
|
+
define: "HAS_SPECULARINTENSITYMAP",
|
|
455
|
+
enabledUniformName: "specularIntensityMapEnabled"
|
|
456
|
+
},
|
|
457
|
+
gltf
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function parseIorExtension(extension, parsedMaterial) {
|
|
462
|
+
if ((extension == null ? void 0 : extension.ior) !== void 0) {
|
|
463
|
+
parsedMaterial.uniforms.ior = extension.ior;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function parseTransmissionExtension(device, extension, parsedMaterial, gltf) {
|
|
467
|
+
if (!extension) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
if (extension.transmissionFactor !== void 0) {
|
|
471
|
+
parsedMaterial.uniforms.transmissionFactor = extension.transmissionFactor;
|
|
472
|
+
}
|
|
473
|
+
if (extension.transmissionTexture) {
|
|
474
|
+
addTexture(device, extension.transmissionTexture, "pbr_transmissionSampler", parsedMaterial, {
|
|
475
|
+
featureOptions: {
|
|
476
|
+
define: "HAS_TRANSMISSIONMAP",
|
|
477
|
+
enabledUniformName: "transmissionMapEnabled"
|
|
478
|
+
},
|
|
479
|
+
gltf
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
if ((extension.transmissionFactor ?? 0) > 0 || extension.transmissionTexture) {
|
|
483
|
+
import_core.log.warn("KHR_materials_transmission uses a premultiplied-alpha blending approximation and may require mesh sorting")();
|
|
484
|
+
applyTransmissionBlendApproximation(parsedMaterial);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
function parseVolumeExtension(device, extension, parsedMaterial, gltf) {
|
|
488
|
+
if (!extension) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (extension.thicknessFactor !== void 0) {
|
|
492
|
+
parsedMaterial.uniforms.thicknessFactor = extension.thicknessFactor;
|
|
493
|
+
}
|
|
494
|
+
if (extension.thicknessTexture) {
|
|
495
|
+
addTexture(device, extension.thicknessTexture, "pbr_thicknessSampler", parsedMaterial, {
|
|
496
|
+
featureOptions: {
|
|
497
|
+
define: "HAS_THICKNESSMAP"
|
|
498
|
+
},
|
|
499
|
+
gltf
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
if (extension.attenuationDistance !== void 0) {
|
|
503
|
+
parsedMaterial.uniforms.attenuationDistance = extension.attenuationDistance;
|
|
504
|
+
}
|
|
505
|
+
if (extension.attenuationColor) {
|
|
506
|
+
parsedMaterial.uniforms.attenuationColor = extension.attenuationColor;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
function parseClearcoatExtension(device, extension, parsedMaterial, gltf) {
|
|
510
|
+
if (!extension) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
if (extension.clearcoatFactor !== void 0) {
|
|
514
|
+
parsedMaterial.uniforms.clearcoatFactor = extension.clearcoatFactor;
|
|
515
|
+
}
|
|
516
|
+
if (extension.clearcoatRoughnessFactor !== void 0) {
|
|
517
|
+
parsedMaterial.uniforms.clearcoatRoughnessFactor = extension.clearcoatRoughnessFactor;
|
|
518
|
+
}
|
|
519
|
+
if (extension.clearcoatTexture) {
|
|
520
|
+
addTexture(device, extension.clearcoatTexture, "pbr_clearcoatSampler", parsedMaterial, {
|
|
521
|
+
featureOptions: {
|
|
522
|
+
define: "HAS_CLEARCOATMAP",
|
|
523
|
+
enabledUniformName: "clearcoatMapEnabled"
|
|
524
|
+
},
|
|
525
|
+
gltf
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
if (extension.clearcoatRoughnessTexture) {
|
|
529
|
+
addTexture(device, extension.clearcoatRoughnessTexture, "pbr_clearcoatRoughnessSampler", parsedMaterial, {
|
|
530
|
+
featureOptions: {
|
|
531
|
+
define: "HAS_CLEARCOATROUGHNESSMAP",
|
|
532
|
+
enabledUniformName: "clearcoatRoughnessMapEnabled"
|
|
533
|
+
},
|
|
534
|
+
gltf
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
if (extension.clearcoatNormalTexture) {
|
|
538
|
+
addTexture(device, extension.clearcoatNormalTexture, "pbr_clearcoatNormalSampler", parsedMaterial, {
|
|
539
|
+
featureOptions: {
|
|
540
|
+
define: "HAS_CLEARCOATNORMALMAP"
|
|
541
|
+
},
|
|
542
|
+
gltf
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function parseSheenExtension(device, extension, parsedMaterial, gltf) {
|
|
547
|
+
if (!extension) {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
if (extension.sheenColorFactor) {
|
|
551
|
+
parsedMaterial.uniforms.sheenColorFactor = extension.sheenColorFactor;
|
|
552
|
+
}
|
|
553
|
+
if (extension.sheenRoughnessFactor !== void 0) {
|
|
554
|
+
parsedMaterial.uniforms.sheenRoughnessFactor = extension.sheenRoughnessFactor;
|
|
555
|
+
}
|
|
556
|
+
if (extension.sheenColorTexture) {
|
|
557
|
+
addTexture(device, extension.sheenColorTexture, "pbr_sheenColorSampler", parsedMaterial, {
|
|
558
|
+
featureOptions: {
|
|
559
|
+
define: "HAS_SHEENCOLORMAP",
|
|
560
|
+
enabledUniformName: "sheenColorMapEnabled"
|
|
561
|
+
},
|
|
562
|
+
gltf
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
if (extension.sheenRoughnessTexture) {
|
|
566
|
+
addTexture(device, extension.sheenRoughnessTexture, "pbr_sheenRoughnessSampler", parsedMaterial, {
|
|
567
|
+
featureOptions: {
|
|
568
|
+
define: "HAS_SHEENROUGHNESSMAP",
|
|
569
|
+
enabledUniformName: "sheenRoughnessMapEnabled"
|
|
570
|
+
},
|
|
571
|
+
gltf
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function parseIridescenceExtension(device, extension, parsedMaterial, gltf) {
|
|
576
|
+
if (!extension) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (extension.iridescenceFactor !== void 0) {
|
|
580
|
+
parsedMaterial.uniforms.iridescenceFactor = extension.iridescenceFactor;
|
|
581
|
+
}
|
|
582
|
+
if (extension.iridescenceIor !== void 0) {
|
|
583
|
+
parsedMaterial.uniforms.iridescenceIor = extension.iridescenceIor;
|
|
584
|
+
}
|
|
585
|
+
if (extension.iridescenceThicknessMinimum !== void 0 || extension.iridescenceThicknessMaximum !== void 0) {
|
|
586
|
+
parsedMaterial.uniforms.iridescenceThicknessRange = [
|
|
587
|
+
extension.iridescenceThicknessMinimum ?? 100,
|
|
588
|
+
extension.iridescenceThicknessMaximum ?? 400
|
|
589
|
+
];
|
|
590
|
+
}
|
|
591
|
+
if (extension.iridescenceTexture) {
|
|
592
|
+
addTexture(device, extension.iridescenceTexture, "pbr_iridescenceSampler", parsedMaterial, {
|
|
593
|
+
featureOptions: {
|
|
594
|
+
define: "HAS_IRIDESCENCEMAP",
|
|
595
|
+
enabledUniformName: "iridescenceMapEnabled"
|
|
596
|
+
},
|
|
597
|
+
gltf
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
if (extension.iridescenceThicknessTexture) {
|
|
601
|
+
addTexture(device, extension.iridescenceThicknessTexture, "pbr_iridescenceThicknessSampler", parsedMaterial, {
|
|
602
|
+
featureOptions: {
|
|
603
|
+
define: "HAS_IRIDESCENCETHICKNESSMAP"
|
|
604
|
+
},
|
|
605
|
+
gltf
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
function parseAnisotropyExtension(device, extension, parsedMaterial, gltf) {
|
|
610
|
+
if (!extension) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (extension.anisotropyStrength !== void 0) {
|
|
614
|
+
parsedMaterial.uniforms.anisotropyStrength = extension.anisotropyStrength;
|
|
615
|
+
}
|
|
616
|
+
if (extension.anisotropyRotation !== void 0) {
|
|
617
|
+
parsedMaterial.uniforms.anisotropyRotation = extension.anisotropyRotation;
|
|
618
|
+
}
|
|
619
|
+
if (extension.anisotropyTexture) {
|
|
620
|
+
addTexture(device, extension.anisotropyTexture, "pbr_anisotropySampler", parsedMaterial, {
|
|
621
|
+
featureOptions: {
|
|
622
|
+
define: "HAS_ANISOTROPYMAP",
|
|
623
|
+
enabledUniformName: "anisotropyMapEnabled"
|
|
624
|
+
},
|
|
625
|
+
gltf
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
function parseEmissiveStrengthExtension(extension, parsedMaterial) {
|
|
630
|
+
if ((extension == null ? void 0 : extension.emissiveStrength) !== void 0) {
|
|
631
|
+
parsedMaterial.uniforms.emissiveStrength = extension.emissiveStrength;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function addTexture(device, gltfTexture, uniformName, parsedMaterial, textureParseOptions = {}) {
|
|
635
|
+
var _a, _b, _c;
|
|
636
|
+
const { featureOptions = {}, gltf } = textureParseOptions;
|
|
637
|
+
const { define, enabledUniformName } = featureOptions;
|
|
638
|
+
const resolvedTextureInfo = resolveTextureInfo(gltfTexture, gltf);
|
|
639
|
+
const image = (_b = (_a = resolvedTextureInfo.texture) == null ? void 0 : _a.source) == null ? void 0 : _b.image;
|
|
640
|
+
if (!image) {
|
|
641
|
+
import_core.log.warn(`Skipping unresolved glTF texture for ${String(uniformName)}`)();
|
|
642
|
+
return;
|
|
264
643
|
}
|
|
265
644
|
const gltfSampler = {
|
|
266
645
|
wrapS: 10497,
|
|
@@ -271,49 +650,183 @@ function addTexture(device, gltfTexture, uniformName, define, parsedMaterial) {
|
|
|
271
650
|
// default LINEAR filtering
|
|
272
651
|
magFilter: 9729,
|
|
273
652
|
// default LINEAR filtering
|
|
274
|
-
...(
|
|
653
|
+
...(_c = resolvedTextureInfo == null ? void 0 : resolvedTextureInfo.texture) == null ? void 0 : _c.sampler
|
|
275
654
|
};
|
|
276
|
-
const
|
|
277
|
-
id:
|
|
278
|
-
sampler: convertSampler(gltfSampler)
|
|
279
|
-
|
|
280
|
-
|
|
655
|
+
const baseOptions = {
|
|
656
|
+
id: resolvedTextureInfo.uniformName || resolvedTextureInfo.id,
|
|
657
|
+
sampler: convertSampler(gltfSampler)
|
|
658
|
+
};
|
|
659
|
+
let texture;
|
|
660
|
+
if (image.compressed) {
|
|
661
|
+
texture = createCompressedTexture(device, image, baseOptions);
|
|
662
|
+
} else {
|
|
663
|
+
const { width, height } = device.getExternalImageSize(image);
|
|
664
|
+
texture = device.createTexture({
|
|
665
|
+
...baseOptions,
|
|
666
|
+
width,
|
|
667
|
+
height,
|
|
668
|
+
data: image
|
|
669
|
+
});
|
|
670
|
+
}
|
|
281
671
|
parsedMaterial.bindings[uniformName] = texture;
|
|
282
672
|
if (define)
|
|
283
673
|
parsedMaterial.defines[define] = true;
|
|
674
|
+
if (enabledUniformName) {
|
|
675
|
+
parsedMaterial.uniforms[enabledUniformName] = true;
|
|
676
|
+
}
|
|
284
677
|
parsedMaterial.generatedTextures.push(texture);
|
|
285
678
|
}
|
|
679
|
+
function resolveTextureInfo(gltfTexture, gltf) {
|
|
680
|
+
if (gltfTexture.texture || gltfTexture.index === void 0 || !(gltf == null ? void 0 : gltf.textures)) {
|
|
681
|
+
return gltfTexture;
|
|
682
|
+
}
|
|
683
|
+
const resolvedTextureEntry = gltf.textures[gltfTexture.index];
|
|
684
|
+
if (!resolvedTextureEntry) {
|
|
685
|
+
return gltfTexture;
|
|
686
|
+
}
|
|
687
|
+
if ("texture" in resolvedTextureEntry && resolvedTextureEntry.texture) {
|
|
688
|
+
return {
|
|
689
|
+
...resolvedTextureEntry,
|
|
690
|
+
...gltfTexture,
|
|
691
|
+
texture: resolvedTextureEntry.texture
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
if (!("source" in resolvedTextureEntry)) {
|
|
695
|
+
return gltfTexture;
|
|
696
|
+
}
|
|
697
|
+
return {
|
|
698
|
+
...gltfTexture,
|
|
699
|
+
texture: resolvedTextureEntry
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
function createCompressedTextureFallback(device, baseOptions) {
|
|
703
|
+
return device.createTexture({
|
|
704
|
+
...baseOptions,
|
|
705
|
+
format: "rgba8unorm",
|
|
706
|
+
width: 1,
|
|
707
|
+
height: 1,
|
|
708
|
+
mipLevels: 1
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
function resolveCompressedTextureFormat(level) {
|
|
712
|
+
return level.textureFormat;
|
|
713
|
+
}
|
|
714
|
+
function getMaxCompressedMipLevels(baseWidth, baseHeight, format) {
|
|
715
|
+
const { blockWidth = 1, blockHeight = 1 } = import_core.textureFormatDecoder.getInfo(format);
|
|
716
|
+
let count = 1;
|
|
717
|
+
for (let i = 1; ; i++) {
|
|
718
|
+
const w = Math.max(1, baseWidth >> i);
|
|
719
|
+
const h = Math.max(1, baseHeight >> i);
|
|
720
|
+
if (w < blockWidth || h < blockHeight)
|
|
721
|
+
break;
|
|
722
|
+
count++;
|
|
723
|
+
}
|
|
724
|
+
return count;
|
|
725
|
+
}
|
|
726
|
+
function createCompressedTexture(device, image, baseOptions) {
|
|
727
|
+
var _a, _b;
|
|
728
|
+
let levels;
|
|
729
|
+
if (Array.isArray(image.data) && ((_a = image.data[0]) == null ? void 0 : _a.data)) {
|
|
730
|
+
levels = image.data;
|
|
731
|
+
} else if ("mipmaps" in image && Array.isArray(image.mipmaps)) {
|
|
732
|
+
levels = image.mipmaps;
|
|
733
|
+
} else {
|
|
734
|
+
levels = [];
|
|
735
|
+
}
|
|
736
|
+
if (levels.length === 0 || !((_b = levels[0]) == null ? void 0 : _b.data)) {
|
|
737
|
+
import_core.log.warn("createCompressedTexture: compressed image has no valid mip levels, creating fallback")();
|
|
738
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
739
|
+
}
|
|
740
|
+
const baseLevel = levels[0];
|
|
741
|
+
const baseWidth = baseLevel.width ?? image.width ?? 0;
|
|
742
|
+
const baseHeight = baseLevel.height ?? image.height ?? 0;
|
|
743
|
+
if (baseWidth <= 0 || baseHeight <= 0) {
|
|
744
|
+
import_core.log.warn("createCompressedTexture: base level has invalid dimensions, creating fallback")();
|
|
745
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
746
|
+
}
|
|
747
|
+
const format = resolveCompressedTextureFormat(baseLevel);
|
|
748
|
+
if (!format) {
|
|
749
|
+
import_core.log.warn("createCompressedTexture: compressed image has no textureFormat, creating fallback")();
|
|
750
|
+
return createCompressedTextureFallback(device, baseOptions);
|
|
751
|
+
}
|
|
752
|
+
const maxMipLevels = getMaxCompressedMipLevels(baseWidth, baseHeight, format);
|
|
753
|
+
const levelLimit = Math.min(levels.length, maxMipLevels);
|
|
754
|
+
let validLevelCount = 1;
|
|
755
|
+
for (let i = 1; i < levelLimit; i++) {
|
|
756
|
+
const level = levels[i];
|
|
757
|
+
if (!level.data || level.width <= 0 || level.height <= 0) {
|
|
758
|
+
import_core.log.warn(`createCompressedTexture: mip level ${i} has invalid data/dimensions, truncating`)();
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
const levelFormat = resolveCompressedTextureFormat(level);
|
|
762
|
+
if (levelFormat && levelFormat !== format) {
|
|
763
|
+
import_core.log.warn(`createCompressedTexture: mip level ${i} format '${levelFormat}' differs from base '${format}', truncating`)();
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
const expectedW = Math.max(1, baseWidth >> i);
|
|
767
|
+
const expectedH = Math.max(1, baseHeight >> i);
|
|
768
|
+
if (level.width !== expectedW || level.height !== expectedH) {
|
|
769
|
+
import_core.log.warn(`createCompressedTexture: mip level ${i} dimensions ${level.width}x${level.height} don't match expected ${expectedW}x${expectedH}, truncating`)();
|
|
770
|
+
break;
|
|
771
|
+
}
|
|
772
|
+
validLevelCount++;
|
|
773
|
+
}
|
|
774
|
+
const texture = device.createTexture({
|
|
775
|
+
...baseOptions,
|
|
776
|
+
format,
|
|
777
|
+
usage: import_core.Texture.TEXTURE | import_core.Texture.COPY_DST,
|
|
778
|
+
width: baseWidth,
|
|
779
|
+
height: baseHeight,
|
|
780
|
+
mipLevels: validLevelCount,
|
|
781
|
+
data: baseLevel.data
|
|
782
|
+
});
|
|
783
|
+
for (let i = 1; i < validLevelCount; i++) {
|
|
784
|
+
texture.writeData(levels[i].data, {
|
|
785
|
+
width: levels[i].width,
|
|
786
|
+
height: levels[i].height,
|
|
787
|
+
mipLevel: i
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
return texture;
|
|
791
|
+
}
|
|
286
792
|
|
|
287
793
|
// dist/parsers/parse-gltf-lights.js
|
|
288
794
|
var import_core2 = require("@math.gl/core");
|
|
795
|
+
var GLTF_COLOR_FACTOR = 255;
|
|
289
796
|
function parseGLTFLights(gltf) {
|
|
290
|
-
var _a, _b, _c;
|
|
291
|
-
const lightDefs = (
|
|
797
|
+
var _a, _b, _c, _d;
|
|
798
|
+
const lightDefs = (
|
|
799
|
+
// `postProcessGLTF()` moves KHR_lights_punctual into `gltf.lights`.
|
|
800
|
+
gltf.lights || ((_b = (_a = gltf.extensions) == null ? void 0 : _a["KHR_lights_punctual"]) == null ? void 0 : _b["lights"])
|
|
801
|
+
);
|
|
292
802
|
if (!lightDefs || !Array.isArray(lightDefs) || lightDefs.length === 0) {
|
|
293
803
|
return [];
|
|
294
804
|
}
|
|
295
805
|
const lights = [];
|
|
806
|
+
const parentNodeById = createParentNodeMap(gltf.nodes || []);
|
|
807
|
+
const worldMatrixByNodeId = /* @__PURE__ */ new Map();
|
|
296
808
|
for (const node of gltf.nodes || []) {
|
|
297
|
-
const
|
|
298
|
-
if (
|
|
809
|
+
const lightIndex = node.light ?? ((_d = (_c = node.extensions) == null ? void 0 : _c.KHR_lights_punctual) == null ? void 0 : _d.light);
|
|
810
|
+
if (typeof lightIndex !== "number") {
|
|
299
811
|
continue;
|
|
300
812
|
}
|
|
301
|
-
const gltfLight = lightDefs[
|
|
813
|
+
const gltfLight = lightDefs[lightIndex];
|
|
302
814
|
if (!gltfLight) {
|
|
303
815
|
continue;
|
|
304
816
|
}
|
|
305
|
-
const color = gltfLight.color || [1, 1, 1];
|
|
817
|
+
const color = normalizeGLTFLightColor(gltfLight.color || [1, 1, 1]);
|
|
306
818
|
const intensity = gltfLight.intensity ?? 1;
|
|
307
819
|
const range = gltfLight.range;
|
|
820
|
+
const worldMatrix = getNodeWorldMatrix(node, parentNodeById, worldMatrixByNodeId);
|
|
308
821
|
switch (gltfLight.type) {
|
|
309
822
|
case "directional":
|
|
310
|
-
lights.push(parseDirectionalLight(
|
|
823
|
+
lights.push(parseDirectionalLight(worldMatrix, color, intensity));
|
|
311
824
|
break;
|
|
312
825
|
case "point":
|
|
313
|
-
lights.push(parsePointLight(
|
|
826
|
+
lights.push(parsePointLight(worldMatrix, color, intensity, range));
|
|
314
827
|
break;
|
|
315
828
|
case "spot":
|
|
316
|
-
lights.push(
|
|
829
|
+
lights.push(parseSpotLight(worldMatrix, color, intensity, range, gltfLight.spot));
|
|
317
830
|
break;
|
|
318
831
|
default:
|
|
319
832
|
break;
|
|
@@ -321,8 +834,11 @@ function parseGLTFLights(gltf) {
|
|
|
321
834
|
}
|
|
322
835
|
return lights;
|
|
323
836
|
}
|
|
324
|
-
function
|
|
325
|
-
|
|
837
|
+
function normalizeGLTFLightColor(color) {
|
|
838
|
+
return color.map((component) => component * GLTF_COLOR_FACTOR);
|
|
839
|
+
}
|
|
840
|
+
function parsePointLight(worldMatrix, color, intensity, range) {
|
|
841
|
+
const position = getLightPosition(worldMatrix);
|
|
326
842
|
let attenuation = [1, 0, 0];
|
|
327
843
|
if (range !== void 0 && range > 0) {
|
|
328
844
|
attenuation = [1, 0, 1 / (range * range)];
|
|
@@ -335,12 +851,8 @@ function parsePointLight(node, color, intensity, range) {
|
|
|
335
851
|
attenuation
|
|
336
852
|
};
|
|
337
853
|
}
|
|
338
|
-
function parseDirectionalLight(
|
|
339
|
-
|
|
340
|
-
if (node.rotation) {
|
|
341
|
-
const orientation = new import_core2.Matrix4().fromQuaternion(node.rotation);
|
|
342
|
-
direction = orientation.transformDirection([0, 0, -1]);
|
|
343
|
-
}
|
|
854
|
+
function parseDirectionalLight(worldMatrix, color, intensity) {
|
|
855
|
+
const direction = getLightDirection(worldMatrix);
|
|
344
856
|
return {
|
|
345
857
|
type: "directional",
|
|
346
858
|
direction,
|
|
@@ -348,22 +860,72 @@ function parseDirectionalLight(node, color, intensity) {
|
|
|
348
860
|
intensity
|
|
349
861
|
};
|
|
350
862
|
}
|
|
863
|
+
function parseSpotLight(worldMatrix, color, intensity, range, spot = {}) {
|
|
864
|
+
const position = getLightPosition(worldMatrix);
|
|
865
|
+
const direction = getLightDirection(worldMatrix);
|
|
866
|
+
let attenuation = [1, 0, 0];
|
|
867
|
+
if (range !== void 0 && range > 0) {
|
|
868
|
+
attenuation = [1, 0, 1 / (range * range)];
|
|
869
|
+
}
|
|
870
|
+
return {
|
|
871
|
+
type: "spot",
|
|
872
|
+
position,
|
|
873
|
+
direction,
|
|
874
|
+
color,
|
|
875
|
+
intensity,
|
|
876
|
+
attenuation,
|
|
877
|
+
innerConeAngle: spot.innerConeAngle ?? 0,
|
|
878
|
+
outerConeAngle: spot.outerConeAngle ?? Math.PI / 4
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
function createParentNodeMap(nodes) {
|
|
882
|
+
const parentNodeById = /* @__PURE__ */ new Map();
|
|
883
|
+
for (const node of nodes) {
|
|
884
|
+
for (const childNode of node.children || []) {
|
|
885
|
+
parentNodeById.set(childNode.id, node);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return parentNodeById;
|
|
889
|
+
}
|
|
890
|
+
function getNodeWorldMatrix(node, parentNodeById, worldMatrixByNodeId) {
|
|
891
|
+
const cachedWorldMatrix = worldMatrixByNodeId.get(node.id);
|
|
892
|
+
if (cachedWorldMatrix) {
|
|
893
|
+
return cachedWorldMatrix;
|
|
894
|
+
}
|
|
895
|
+
const localMatrix = getNodeLocalMatrix(node);
|
|
896
|
+
const parentNode = parentNodeById.get(node.id);
|
|
897
|
+
const worldMatrix = parentNode ? new import_core2.Matrix4(getNodeWorldMatrix(parentNode, parentNodeById, worldMatrixByNodeId)).multiplyRight(localMatrix) : localMatrix;
|
|
898
|
+
worldMatrixByNodeId.set(node.id, worldMatrix);
|
|
899
|
+
return worldMatrix;
|
|
900
|
+
}
|
|
901
|
+
function getNodeLocalMatrix(node) {
|
|
902
|
+
if (node.matrix) {
|
|
903
|
+
return new import_core2.Matrix4(node.matrix);
|
|
904
|
+
}
|
|
905
|
+
const matrix = new import_core2.Matrix4();
|
|
906
|
+
if (node.translation) {
|
|
907
|
+
matrix.translate(node.translation);
|
|
908
|
+
}
|
|
909
|
+
if (node.rotation) {
|
|
910
|
+
matrix.multiplyRight(new import_core2.Matrix4().fromQuaternion(node.rotation));
|
|
911
|
+
}
|
|
912
|
+
if (node.scale) {
|
|
913
|
+
matrix.scale(node.scale);
|
|
914
|
+
}
|
|
915
|
+
return matrix;
|
|
916
|
+
}
|
|
917
|
+
function getLightPosition(worldMatrix) {
|
|
918
|
+
return worldMatrix.transformAsPoint([0, 0, 0]);
|
|
919
|
+
}
|
|
920
|
+
function getLightDirection(worldMatrix) {
|
|
921
|
+
return worldMatrix.transformDirection([0, 0, -1]);
|
|
922
|
+
}
|
|
351
923
|
|
|
352
924
|
// dist/parsers/parse-gltf.js
|
|
353
|
-
var
|
|
354
|
-
var
|
|
925
|
+
var import_engine4 = require("@luma.gl/engine");
|
|
926
|
+
var import_shadertools2 = require("@luma.gl/shadertools");
|
|
355
927
|
|
|
356
928
|
// dist/webgl-to-webgpu/convert-webgl-topology.js
|
|
357
|
-
var GLEnum;
|
|
358
|
-
(function(GLEnum2) {
|
|
359
|
-
GLEnum2[GLEnum2["POINTS"] = 0] = "POINTS";
|
|
360
|
-
GLEnum2[GLEnum2["LINES"] = 1] = "LINES";
|
|
361
|
-
GLEnum2[GLEnum2["LINE_LOOP"] = 2] = "LINE_LOOP";
|
|
362
|
-
GLEnum2[GLEnum2["LINE_STRIP"] = 3] = "LINE_STRIP";
|
|
363
|
-
GLEnum2[GLEnum2["TRIANGLES"] = 4] = "TRIANGLES";
|
|
364
|
-
GLEnum2[GLEnum2["TRIANGLE_STRIP"] = 5] = "TRIANGLE_STRIP";
|
|
365
|
-
GLEnum2[GLEnum2["TRIANGLE_FAN"] = 6] = "TRIANGLE_FAN";
|
|
366
|
-
})(GLEnum || (GLEnum = {}));
|
|
367
929
|
function convertGLDrawModeToTopology(drawMode) {
|
|
368
930
|
switch (drawMode) {
|
|
369
931
|
case GLEnum.POINTS:
|
|
@@ -383,55 +945,94 @@ function convertGLDrawModeToTopology(drawMode) {
|
|
|
383
945
|
|
|
384
946
|
// dist/gltf/create-gltf-model.js
|
|
385
947
|
var import_core3 = require("@luma.gl/core");
|
|
386
|
-
var import_shadertools = require("@luma.gl/shadertools");
|
|
387
948
|
var import_engine2 = require("@luma.gl/engine");
|
|
949
|
+
var import_shadertools = require("@luma.gl/shadertools");
|
|
950
|
+
var import_engine3 = require("@luma.gl/engine");
|
|
388
951
|
var SHADER = (
|
|
389
952
|
/* WGSL */
|
|
390
953
|
`
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
954
|
+
struct VertexInputs {
|
|
955
|
+
@location(0) positions: vec3f,
|
|
956
|
+
#ifdef HAS_NORMALS
|
|
957
|
+
@location(1) normals: vec3f,
|
|
958
|
+
#endif
|
|
959
|
+
#ifdef HAS_TANGENTS
|
|
960
|
+
@location(2) TANGENT: vec4f,
|
|
961
|
+
#endif
|
|
962
|
+
#ifdef HAS_UV
|
|
963
|
+
@location(3) texCoords: vec2f,
|
|
964
|
+
#endif
|
|
965
|
+
#ifdef HAS_SKIN
|
|
966
|
+
@location(4) JOINTS_0: vec4u,
|
|
967
|
+
@location(5) WEIGHTS_0: vec4f,
|
|
968
|
+
#endif
|
|
969
|
+
};
|
|
400
970
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
971
|
+
struct FragmentInputs {
|
|
972
|
+
@builtin(position) position: vec4f,
|
|
973
|
+
@location(0) pbrPosition: vec3f,
|
|
974
|
+
@location(1) pbrUV: vec2f,
|
|
975
|
+
@location(2) pbrNormal: vec3f,
|
|
976
|
+
#ifdef HAS_TANGENTS
|
|
977
|
+
@location(3) pbrTangent: vec4f,
|
|
978
|
+
#endif
|
|
979
|
+
};
|
|
405
980
|
|
|
406
981
|
@vertex
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
982
|
+
fn vertexMain(inputs: VertexInputs) -> FragmentInputs {
|
|
983
|
+
var outputs: FragmentInputs;
|
|
984
|
+
var position = vec4f(inputs.positions, 1.0);
|
|
985
|
+
var normal = vec3f(0.0, 0.0, 1.0);
|
|
986
|
+
var tangent = vec4f(1.0, 0.0, 0.0, 1.0);
|
|
987
|
+
var uv = vec2f(0.0, 0.0);
|
|
411
988
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
989
|
+
#ifdef HAS_NORMALS
|
|
990
|
+
normal = inputs.normals;
|
|
991
|
+
#endif
|
|
992
|
+
#ifdef HAS_UV
|
|
993
|
+
uv = inputs.texCoords;
|
|
994
|
+
#endif
|
|
995
|
+
#ifdef HAS_TANGENTS
|
|
996
|
+
tangent = inputs.TANGENT;
|
|
997
|
+
#endif
|
|
998
|
+
#ifdef HAS_SKIN
|
|
999
|
+
let skinMatrix = getSkinMatrix(inputs.WEIGHTS_0, inputs.JOINTS_0);
|
|
1000
|
+
position = skinMatrix * position;
|
|
1001
|
+
normal = normalize((skinMatrix * vec4f(normal, 0.0)).xyz);
|
|
1002
|
+
#ifdef HAS_TANGENTS
|
|
1003
|
+
tangent = vec4f(normalize((skinMatrix * vec4f(tangent.xyz, 0.0)).xyz), tangent.w);
|
|
1004
|
+
#endif
|
|
1005
|
+
#endif
|
|
415
1006
|
|
|
416
|
-
|
|
417
|
-
_TANGENT = TANGENT;
|
|
418
|
-
#endif
|
|
1007
|
+
let worldPosition = pbrProjection.modelMatrix * position;
|
|
419
1008
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
1009
|
+
#ifdef HAS_NORMALS
|
|
1010
|
+
normal = normalize((pbrProjection.normalMatrix * vec4f(normal, 0.0)).xyz);
|
|
1011
|
+
#endif
|
|
1012
|
+
#ifdef HAS_TANGENTS
|
|
1013
|
+
let worldTangent = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);
|
|
1014
|
+
outputs.pbrTangent = vec4f(worldTangent, tangent.w);
|
|
1015
|
+
#endif
|
|
423
1016
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
1017
|
+
outputs.position = pbrProjection.modelViewProjectionMatrix * position;
|
|
1018
|
+
outputs.pbrPosition = worldPosition.xyz / worldPosition.w;
|
|
1019
|
+
outputs.pbrUV = uv;
|
|
1020
|
+
outputs.pbrNormal = normal;
|
|
1021
|
+
return outputs;
|
|
1022
|
+
}
|
|
427
1023
|
|
|
428
1024
|
@fragment
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
1025
|
+
fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {
|
|
1026
|
+
fragmentInputs.pbr_vPosition = inputs.pbrPosition;
|
|
1027
|
+
fragmentInputs.pbr_vUV = inputs.pbrUV;
|
|
1028
|
+
fragmentInputs.pbr_vNormal = inputs.pbrNormal;
|
|
1029
|
+
#ifdef HAS_TANGENTS
|
|
1030
|
+
let tangent = normalize(inputs.pbrTangent.xyz);
|
|
1031
|
+
let bitangent = normalize(cross(inputs.pbrNormal, tangent)) * inputs.pbrTangent.w;
|
|
1032
|
+
fragmentInputs.pbr_vTBN = mat3x3f(tangent, bitangent, inputs.pbrNormal);
|
|
1033
|
+
#endif
|
|
1034
|
+
return pbr_filterColor(vec4f(1.0));
|
|
1035
|
+
}
|
|
435
1036
|
`
|
|
436
1037
|
);
|
|
437
1038
|
var vs = (
|
|
@@ -455,6 +1056,11 @@ var vs = (
|
|
|
455
1056
|
in vec2 texCoords;
|
|
456
1057
|
#endif
|
|
457
1058
|
|
|
1059
|
+
#ifdef HAS_SKIN
|
|
1060
|
+
in uvec4 JOINTS_0;
|
|
1061
|
+
in vec4 WEIGHTS_0;
|
|
1062
|
+
#endif
|
|
1063
|
+
|
|
458
1064
|
void main(void) {
|
|
459
1065
|
vec4 _NORMAL = vec4(0.);
|
|
460
1066
|
vec4 _TANGENT = vec4(0.);
|
|
@@ -472,8 +1078,17 @@ var vs = (
|
|
|
472
1078
|
_TEXCOORD_0 = texCoords;
|
|
473
1079
|
#endif
|
|
474
1080
|
|
|
475
|
-
|
|
476
|
-
|
|
1081
|
+
vec4 pos = positions;
|
|
1082
|
+
|
|
1083
|
+
#ifdef HAS_SKIN
|
|
1084
|
+
mat4 skinMat = getSkinMatrix(WEIGHTS_0, JOINTS_0);
|
|
1085
|
+
pos = skinMat * pos;
|
|
1086
|
+
_NORMAL = skinMat * _NORMAL;
|
|
1087
|
+
_TANGENT = vec4((skinMat * vec4(_TANGENT.xyz, 0.)).xyz, _TANGENT.w);
|
|
1088
|
+
#endif
|
|
1089
|
+
|
|
1090
|
+
pbr_setPositionNormalTangentUV(pos, _NORMAL, _TANGENT, _TEXCOORD_0);
|
|
1091
|
+
gl_Position = pbrProjection.modelViewProjectionMatrix * pos;
|
|
477
1092
|
}
|
|
478
1093
|
`
|
|
479
1094
|
);
|
|
@@ -488,6 +1103,21 @@ var fs = (
|
|
|
488
1103
|
}
|
|
489
1104
|
`
|
|
490
1105
|
);
|
|
1106
|
+
function createGLTFMaterial(device, options) {
|
|
1107
|
+
const materialFactory = options.materialFactory || new import_engine3.MaterialFactory(device, { modules: [import_shadertools.pbrMaterial] });
|
|
1108
|
+
const pbrMaterialProps = { ...options.parsedPPBRMaterial.uniforms };
|
|
1109
|
+
delete pbrMaterialProps.camera;
|
|
1110
|
+
const materialBindings = Object.fromEntries(Object.entries({
|
|
1111
|
+
...pbrMaterialProps,
|
|
1112
|
+
...options.parsedPPBRMaterial.bindings
|
|
1113
|
+
}).filter(([name, value]) => materialFactory.ownsBinding(name) && isMaterialBindingResource(value)));
|
|
1114
|
+
const material = materialFactory.createMaterial({
|
|
1115
|
+
id: options.id,
|
|
1116
|
+
bindings: materialBindings
|
|
1117
|
+
});
|
|
1118
|
+
material.setProps({ pbrMaterial: pbrMaterialProps });
|
|
1119
|
+
return material;
|
|
1120
|
+
}
|
|
491
1121
|
function createGLTFModel(device, options) {
|
|
492
1122
|
const { id, geometry, parsedPPBRMaterial, vertexCount, modelOptions = {} } = options;
|
|
493
1123
|
import_core3.log.info(4, "createGLTFModel defines: ", parsedPPBRMaterial.defines)();
|
|
@@ -506,20 +1136,53 @@ function createGLTFModel(device, options) {
|
|
|
506
1136
|
geometry,
|
|
507
1137
|
topology: geometry.topology,
|
|
508
1138
|
vertexCount,
|
|
509
|
-
modules: [import_shadertools.pbrMaterial],
|
|
1139
|
+
modules: [import_shadertools.pbrMaterial, import_shadertools.skin],
|
|
510
1140
|
...modelOptions,
|
|
511
1141
|
defines: { ...parsedPPBRMaterial.defines, ...modelOptions.defines },
|
|
512
1142
|
parameters: { ...parameters, ...parsedPPBRMaterial.parameters, ...modelOptions.parameters }
|
|
513
1143
|
};
|
|
514
|
-
const
|
|
515
|
-
|
|
1144
|
+
const material = options.material || createGLTFMaterial(device, {
|
|
1145
|
+
id: id ? `${id}-material` : void 0,
|
|
1146
|
+
parsedPPBRMaterial
|
|
1147
|
+
});
|
|
1148
|
+
modelProps.material = material;
|
|
1149
|
+
const model = new import_engine3.Model(device, modelProps);
|
|
1150
|
+
const sceneShaderInputValues = {
|
|
516
1151
|
...parsedPPBRMaterial.uniforms,
|
|
517
1152
|
...modelOptions.uniforms,
|
|
518
1153
|
...parsedPPBRMaterial.bindings,
|
|
519
1154
|
...modelOptions.bindings
|
|
520
1155
|
};
|
|
521
|
-
model.shaderInputs.
|
|
522
|
-
|
|
1156
|
+
const sceneShaderInputProps = getSceneShaderInputProps(model.shaderInputs.getModules(), material, sceneShaderInputValues);
|
|
1157
|
+
model.shaderInputs.setProps(sceneShaderInputProps);
|
|
1158
|
+
return new import_engine3.ModelNode({ managedResources, model });
|
|
1159
|
+
}
|
|
1160
|
+
function isMaterialBindingResource(value) {
|
|
1161
|
+
return value instanceof import_core3.Buffer || value instanceof import_engine2.DynamicTexture || value instanceof import_core3.Sampler || value instanceof import_core3.Texture || value instanceof import_core3.TextureView;
|
|
1162
|
+
}
|
|
1163
|
+
function getSceneShaderInputProps(modules, material, shaderInputValues) {
|
|
1164
|
+
const propertyToModuleNameMap = /* @__PURE__ */ new Map();
|
|
1165
|
+
for (const module2 of modules) {
|
|
1166
|
+
for (const uniformName of Object.keys(module2.uniformTypes || {})) {
|
|
1167
|
+
propertyToModuleNameMap.set(uniformName, module2.name);
|
|
1168
|
+
}
|
|
1169
|
+
for (const binding of module2.bindingLayout || []) {
|
|
1170
|
+
propertyToModuleNameMap.set(binding.name, module2.name);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
const sceneShaderInputProps = {};
|
|
1174
|
+
for (const [propertyName, value] of Object.entries(shaderInputValues)) {
|
|
1175
|
+
if (value === void 0) {
|
|
1176
|
+
continue;
|
|
1177
|
+
}
|
|
1178
|
+
const moduleName = propertyToModuleNameMap.get(propertyName);
|
|
1179
|
+
if (!moduleName || material.ownsModule(moduleName)) {
|
|
1180
|
+
continue;
|
|
1181
|
+
}
|
|
1182
|
+
sceneShaderInputProps[moduleName] ||= {};
|
|
1183
|
+
sceneShaderInputProps[moduleName][propertyName] = value;
|
|
1184
|
+
}
|
|
1185
|
+
return sceneShaderInputProps;
|
|
523
1186
|
}
|
|
524
1187
|
|
|
525
1188
|
// dist/parsers/parse-gltf.js
|
|
@@ -530,73 +1193,103 @@ var defaultOptions = {
|
|
|
530
1193
|
lights: true,
|
|
531
1194
|
useTangents: false
|
|
532
1195
|
};
|
|
533
|
-
function parseGLTF(device, gltf,
|
|
534
|
-
const
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
1196
|
+
function parseGLTF(device, gltf, options = {}) {
|
|
1197
|
+
const combinedOptions = { ...defaultOptions, ...options };
|
|
1198
|
+
const materialFactory = new import_engine4.MaterialFactory(device, { modules: [import_shadertools2.pbrMaterial] });
|
|
1199
|
+
const materials = (gltf.materials || []).map((gltfMaterial, materialIndex) => createGLTFMaterial(device, {
|
|
1200
|
+
id: getGLTFMaterialId(gltfMaterial, materialIndex),
|
|
1201
|
+
parsedPPBRMaterial: parsePBRMaterial(device, gltfMaterial, {}, {
|
|
1202
|
+
...combinedOptions,
|
|
1203
|
+
gltf,
|
|
1204
|
+
validateAttributes: false
|
|
1205
|
+
}),
|
|
1206
|
+
materialFactory
|
|
1207
|
+
}));
|
|
1208
|
+
const gltfMaterialIdToMaterialMap = /* @__PURE__ */ new Map();
|
|
1209
|
+
(gltf.materials || []).forEach((gltfMaterial, materialIndex) => {
|
|
1210
|
+
gltfMaterialIdToMaterialMap.set(gltfMaterial.id, materials[materialIndex]);
|
|
544
1211
|
});
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
1212
|
+
const gltfMeshIdToNodeMap = /* @__PURE__ */ new Map();
|
|
1213
|
+
gltf.meshes.forEach((gltfMesh, idx) => {
|
|
1214
|
+
const newMesh = createNodeForGLTFMesh(device, gltfMesh, gltf, gltfMaterialIdToMaterialMap, combinedOptions);
|
|
1215
|
+
gltfMeshIdToNodeMap.set(gltfMesh.id, newMesh);
|
|
1216
|
+
});
|
|
1217
|
+
const gltfNodeIndexToNodeMap = /* @__PURE__ */ new Map();
|
|
1218
|
+
const gltfNodeIdToNodeMap = /* @__PURE__ */ new Map();
|
|
1219
|
+
gltf.nodes.forEach((gltfNode, idx) => {
|
|
1220
|
+
const newNode = createNodeForGLTFNode(device, gltfNode, combinedOptions);
|
|
1221
|
+
gltfNodeIndexToNodeMap.set(idx, newNode);
|
|
1222
|
+
gltfNodeIdToNodeMap.set(gltfNode.id, newNode);
|
|
1223
|
+
});
|
|
1224
|
+
gltf.nodes.forEach((gltfNode, idx) => {
|
|
1225
|
+
gltfNodeIndexToNodeMap.get(idx).add((gltfNode.children ?? []).map(({ id }) => {
|
|
1226
|
+
const child = gltfNodeIdToNodeMap.get(id);
|
|
1227
|
+
if (!child)
|
|
1228
|
+
throw new Error(`Cannot find child ${id} of node ${idx}`);
|
|
1229
|
+
return child;
|
|
1230
|
+
}));
|
|
551
1231
|
if (gltfNode.mesh) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
id: gltfNode.name || gltfNode.id,
|
|
556
|
-
children
|
|
557
|
-
});
|
|
558
|
-
if (gltfNode.matrix) {
|
|
559
|
-
node.setMatrix(gltfNode.matrix);
|
|
560
|
-
} else {
|
|
561
|
-
node.matrix.identity();
|
|
562
|
-
if (gltfNode.translation) {
|
|
563
|
-
node.matrix.translate(gltfNode.translation);
|
|
564
|
-
}
|
|
565
|
-
if (gltfNode.rotation) {
|
|
566
|
-
const rotationMatrix = new import_core4.Matrix4().fromQuaternion(gltfNode.rotation);
|
|
567
|
-
node.matrix.multiplyRight(rotationMatrix);
|
|
568
|
-
}
|
|
569
|
-
if (gltfNode.scale) {
|
|
570
|
-
node.matrix.scale(gltfNode.scale);
|
|
1232
|
+
const mesh = gltfMeshIdToNodeMap.get(gltfNode.mesh.id);
|
|
1233
|
+
if (!mesh) {
|
|
1234
|
+
throw new Error(`Cannot find mesh child ${gltfNode.mesh.id} of node ${idx}`);
|
|
571
1235
|
}
|
|
1236
|
+
gltfNodeIndexToNodeMap.get(idx).add(mesh);
|
|
572
1237
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
if (!gltfMesh._mesh) {
|
|
581
|
-
const gltfPrimitives = gltfMesh.primitives || [];
|
|
582
|
-
const primitives = gltfPrimitives.map((gltfPrimitive, i) => createPrimitive(device, gltfPrimitive, i, gltfMesh, options));
|
|
583
|
-
const mesh = new import_engine3.GroupNode({
|
|
584
|
-
id: gltfMesh.name || gltfMesh.id,
|
|
585
|
-
children: primitives
|
|
1238
|
+
});
|
|
1239
|
+
const scenes = gltf.scenes.map((gltfScene) => {
|
|
1240
|
+
const children = (gltfScene.nodes || []).map(({ id }) => {
|
|
1241
|
+
const child = gltfNodeIdToNodeMap.get(id);
|
|
1242
|
+
if (!child)
|
|
1243
|
+
throw new Error(`Cannot find child ${id} of scene ${gltfScene.name || gltfScene.id}`);
|
|
1244
|
+
return child;
|
|
586
1245
|
});
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
1246
|
+
return new import_engine4.GroupNode({
|
|
1247
|
+
id: gltfScene.name || gltfScene.id,
|
|
1248
|
+
children
|
|
1249
|
+
});
|
|
1250
|
+
});
|
|
1251
|
+
return { scenes, materials, gltfMeshIdToNodeMap, gltfNodeIdToNodeMap, gltfNodeIndexToNodeMap };
|
|
1252
|
+
}
|
|
1253
|
+
function createNodeForGLTFNode(device, gltfNode, options) {
|
|
1254
|
+
return new import_engine4.GroupNode({
|
|
1255
|
+
id: gltfNode.name || gltfNode.id,
|
|
1256
|
+
children: [],
|
|
1257
|
+
matrix: gltfNode.matrix,
|
|
1258
|
+
position: gltfNode.translation,
|
|
1259
|
+
rotation: gltfNode.rotation,
|
|
1260
|
+
scale: gltfNode.scale
|
|
1261
|
+
});
|
|
590
1262
|
}
|
|
591
|
-
function
|
|
592
|
-
const
|
|
1263
|
+
function createNodeForGLTFMesh(device, gltfMesh, gltf, gltfMaterialIdToMaterialMap, options) {
|
|
1264
|
+
const gltfPrimitives = gltfMesh.primitives || [];
|
|
1265
|
+
const primitives = gltfPrimitives.map((gltfPrimitive, i) => createNodeForGLTFPrimitive({
|
|
1266
|
+
device,
|
|
1267
|
+
gltfPrimitive,
|
|
1268
|
+
primitiveIndex: i,
|
|
1269
|
+
gltfMesh,
|
|
1270
|
+
gltf,
|
|
1271
|
+
gltfMaterialIdToMaterialMap,
|
|
1272
|
+
options
|
|
1273
|
+
}));
|
|
1274
|
+
const mesh = new import_engine4.GroupNode({
|
|
1275
|
+
id: gltfMesh.name || gltfMesh.id,
|
|
1276
|
+
children: primitives
|
|
1277
|
+
});
|
|
1278
|
+
return mesh;
|
|
1279
|
+
}
|
|
1280
|
+
function createNodeForGLTFPrimitive({ device, gltfPrimitive, primitiveIndex, gltfMesh, gltf, gltfMaterialIdToMaterialMap, options }) {
|
|
1281
|
+
const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${primitiveIndex}`;
|
|
593
1282
|
const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4);
|
|
594
1283
|
const vertexCount = gltfPrimitive.indices ? gltfPrimitive.indices.count : getVertexCount(gltfPrimitive.attributes);
|
|
595
1284
|
const geometry = createGeometry(id, gltfPrimitive, topology);
|
|
596
|
-
const parsedPPBRMaterial = parsePBRMaterial(device, gltfPrimitive.material, geometry.attributes,
|
|
1285
|
+
const parsedPPBRMaterial = parsePBRMaterial(device, gltfPrimitive.material, geometry.attributes, {
|
|
1286
|
+
...options,
|
|
1287
|
+
gltf
|
|
1288
|
+
});
|
|
597
1289
|
const modelNode = createGLTFModel(device, {
|
|
598
1290
|
id,
|
|
599
1291
|
geometry: createGeometry(id, gltfPrimitive, topology),
|
|
1292
|
+
material: gltfPrimitive.material ? gltfMaterialIdToMaterialMap.get(gltfPrimitive.material.id) || null : null,
|
|
600
1293
|
parsedPPBRMaterial,
|
|
601
1294
|
modelOptions: options.modelOptions,
|
|
602
1295
|
vertexCount
|
|
@@ -613,42 +1306,41 @@ function createGeometry(id, gltfPrimitive, topology) {
|
|
|
613
1306
|
const { components, size, value } = attribute;
|
|
614
1307
|
attributes[attributeName] = { size: size ?? components, value };
|
|
615
1308
|
}
|
|
616
|
-
return new
|
|
1309
|
+
return new import_engine4.Geometry({
|
|
617
1310
|
id,
|
|
618
1311
|
topology,
|
|
619
1312
|
indices: gltfPrimitive.indices.value,
|
|
620
1313
|
attributes
|
|
621
1314
|
});
|
|
622
1315
|
}
|
|
1316
|
+
function getGLTFMaterialId(gltfMaterial, materialIndex) {
|
|
1317
|
+
return gltfMaterial.name || gltfMaterial.id || `material-${materialIndex}`;
|
|
1318
|
+
}
|
|
623
1319
|
|
|
624
1320
|
// dist/gltf/gltf-animator.js
|
|
625
|
-
var
|
|
626
|
-
var import_core8 = require("@math.gl/core");
|
|
1321
|
+
var import_core6 = require("@luma.gl/core");
|
|
627
1322
|
|
|
628
1323
|
// dist/gltf/animations/interpolate.js
|
|
629
|
-
var
|
|
630
|
-
var
|
|
631
|
-
|
|
1324
|
+
var import_core4 = require("@luma.gl/core");
|
|
1325
|
+
var import_core5 = require("@math.gl/core");
|
|
1326
|
+
function updateTargetPath(target, path, newValue) {
|
|
1327
|
+
switch (path) {
|
|
1328
|
+
case "translation":
|
|
1329
|
+
return target.setPosition(newValue).updateMatrix();
|
|
1330
|
+
case "rotation":
|
|
1331
|
+
return target.setRotation(newValue).updateMatrix();
|
|
1332
|
+
case "scale":
|
|
1333
|
+
return target.setScale(newValue).updateMatrix();
|
|
1334
|
+
default:
|
|
1335
|
+
import_core4.log.warn(`Bad animation path ${path}`)();
|
|
1336
|
+
return null;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
632
1339
|
function interpolate(time, { input, interpolation, output }, target, path) {
|
|
633
1340
|
const maxTime = input[input.length - 1];
|
|
634
1341
|
const animationTime = time % maxTime;
|
|
635
1342
|
const nextIndex = input.findIndex((t) => t >= animationTime);
|
|
636
1343
|
const previousIndex = Math.max(0, nextIndex - 1);
|
|
637
|
-
if (!Array.isArray(target[path])) {
|
|
638
|
-
switch (path) {
|
|
639
|
-
case "translation":
|
|
640
|
-
target[path] = [0, 0, 0];
|
|
641
|
-
break;
|
|
642
|
-
case "rotation":
|
|
643
|
-
target[path] = [0, 0, 0, 1];
|
|
644
|
-
break;
|
|
645
|
-
case "scale":
|
|
646
|
-
target[path] = [1, 1, 1];
|
|
647
|
-
break;
|
|
648
|
-
default:
|
|
649
|
-
import_core5.log.warn(`Bad animation path ${path}`)();
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
1344
|
const previousTime = input[previousIndex];
|
|
653
1345
|
const nextTime = input[nextIndex];
|
|
654
1346
|
switch (interpolation) {
|
|
@@ -673,103 +1365,99 @@ function interpolate(time, { input, interpolation, output }, target, path) {
|
|
|
673
1365
|
}
|
|
674
1366
|
break;
|
|
675
1367
|
default:
|
|
676
|
-
|
|
1368
|
+
import_core4.log.warn(`Interpolation ${interpolation} not supported`)();
|
|
677
1369
|
break;
|
|
678
1370
|
}
|
|
679
1371
|
}
|
|
680
1372
|
function linearInterpolate(target, path, start, stop, ratio) {
|
|
681
|
-
if (!target[path]) {
|
|
682
|
-
throw new Error();
|
|
683
|
-
}
|
|
684
1373
|
if (path === "rotation") {
|
|
685
|
-
|
|
686
|
-
for (let i = 0; i < scratchQuaternion.length; i++) {
|
|
687
|
-
target[path][i] = scratchQuaternion[i];
|
|
688
|
-
}
|
|
1374
|
+
updateTargetPath(target, path, new import_core5.Quaternion().slerp({ start, target: stop, ratio }));
|
|
689
1375
|
} else {
|
|
1376
|
+
const newVal = [];
|
|
690
1377
|
for (let i = 0; i < start.length; i++) {
|
|
691
|
-
|
|
1378
|
+
newVal[i] = ratio * stop[i] + (1 - ratio) * start[i];
|
|
692
1379
|
}
|
|
1380
|
+
updateTargetPath(target, path, newVal);
|
|
693
1381
|
}
|
|
694
1382
|
}
|
|
695
1383
|
function cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio: t }) {
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}
|
|
699
|
-
for (let i = 0; i < target[path].length; i++) {
|
|
1384
|
+
const newVal = [];
|
|
1385
|
+
for (let i = 0; i < p0.length; i++) {
|
|
700
1386
|
const m0 = outTangent0[i] * tDiff;
|
|
701
1387
|
const m1 = inTangent1[i] * tDiff;
|
|
702
|
-
|
|
1388
|
+
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;
|
|
703
1389
|
}
|
|
1390
|
+
updateTargetPath(target, path, newVal);
|
|
704
1391
|
}
|
|
705
1392
|
function stepInterpolate(target, path, value) {
|
|
706
|
-
|
|
707
|
-
throw new Error();
|
|
708
|
-
}
|
|
709
|
-
for (let i = 0; i < value.length; i++) {
|
|
710
|
-
target[path][i] = value[i];
|
|
711
|
-
}
|
|
1393
|
+
updateTargetPath(target, path, value);
|
|
712
1394
|
}
|
|
713
1395
|
|
|
714
1396
|
// dist/gltf/gltf-animator.js
|
|
715
1397
|
var GLTFSingleAnimator = class {
|
|
1398
|
+
/** Animation definition being played. */
|
|
716
1399
|
animation;
|
|
1400
|
+
/** Target scenegraph lookup table. */
|
|
1401
|
+
gltfNodeIdToNodeMap;
|
|
1402
|
+
/** Playback start time in seconds. */
|
|
717
1403
|
startTime = 0;
|
|
1404
|
+
/** Whether playback is currently enabled. */
|
|
718
1405
|
playing = true;
|
|
1406
|
+
/** Playback speed multiplier. */
|
|
719
1407
|
speed = 1;
|
|
1408
|
+
/** Creates a single-animation controller. */
|
|
720
1409
|
constructor(props) {
|
|
721
1410
|
this.animation = props.animation;
|
|
1411
|
+
this.gltfNodeIdToNodeMap = props.gltfNodeIdToNodeMap;
|
|
722
1412
|
this.animation.name ||= "unnamed";
|
|
723
1413
|
Object.assign(this, props);
|
|
724
1414
|
}
|
|
1415
|
+
/** Advances the animation to the supplied wall-clock time in milliseconds. */
|
|
725
1416
|
setTime(timeMs) {
|
|
726
1417
|
if (!this.playing) {
|
|
727
1418
|
return;
|
|
728
1419
|
}
|
|
729
1420
|
const absTime = timeMs / 1e3;
|
|
730
1421
|
const time = (absTime - this.startTime) * this.speed;
|
|
731
|
-
this.animation.channels.forEach(({ sampler,
|
|
732
|
-
|
|
733
|
-
|
|
1422
|
+
this.animation.channels.forEach(({ sampler, targetNodeId, path }) => {
|
|
1423
|
+
const targetNode = this.gltfNodeIdToNodeMap.get(targetNodeId);
|
|
1424
|
+
if (!targetNode) {
|
|
1425
|
+
throw new Error(`Cannot find animation target node ${targetNodeId}`);
|
|
1426
|
+
}
|
|
1427
|
+
interpolate(time, sampler, targetNode, path);
|
|
734
1428
|
});
|
|
735
1429
|
}
|
|
736
1430
|
};
|
|
737
1431
|
var GLTFAnimator = class {
|
|
1432
|
+
/** Individual animation controllers. */
|
|
738
1433
|
animations;
|
|
1434
|
+
/** Creates an animator for the supplied glTF scenegraph. */
|
|
739
1435
|
constructor(props) {
|
|
740
1436
|
this.animations = props.animations.map((animation, index) => {
|
|
741
1437
|
const name = animation.name || `Animation-${index}`;
|
|
742
1438
|
return new GLTFSingleAnimator({
|
|
1439
|
+
gltfNodeIdToNodeMap: props.gltfNodeIdToNodeMap,
|
|
743
1440
|
animation: { name, channels: animation.channels }
|
|
744
1441
|
});
|
|
745
1442
|
});
|
|
746
1443
|
}
|
|
747
1444
|
/** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */
|
|
748
1445
|
animate(time) {
|
|
749
|
-
|
|
1446
|
+
import_core6.log.warn("GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead")();
|
|
750
1447
|
this.setTime(time);
|
|
751
1448
|
}
|
|
1449
|
+
/** Advances every animation to the supplied wall-clock time in milliseconds. */
|
|
752
1450
|
setTime(time) {
|
|
753
1451
|
this.animations.forEach((animation) => animation.setTime(time));
|
|
754
1452
|
}
|
|
1453
|
+
/** Returns the per-animation controllers managed by this animator. */
|
|
755
1454
|
getAnimations() {
|
|
756
1455
|
return this.animations;
|
|
757
1456
|
}
|
|
758
1457
|
};
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
if (gltfNode.translation) {
|
|
763
|
-
node.matrix.translate(gltfNode.translation);
|
|
764
|
-
}
|
|
765
|
-
if (gltfNode.rotation) {
|
|
766
|
-
const rotationMatrix = scratchMatrix.fromQuaternion(gltfNode.rotation);
|
|
767
|
-
node.matrix.multiplyRight(rotationMatrix);
|
|
768
|
-
}
|
|
769
|
-
if (gltfNode.scale) {
|
|
770
|
-
node.matrix.scale(gltfNode.scale);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
1458
|
+
|
|
1459
|
+
// dist/parsers/parse-gltf-animations.js
|
|
1460
|
+
var import_core7 = require("@luma.gl/core");
|
|
773
1461
|
|
|
774
1462
|
// dist/webgl-to-webgpu/convert-webgl-attribute.js
|
|
775
1463
|
var ATTRIBUTE_TYPE_TO_COMPONENTS = {
|
|
@@ -802,62 +1490,327 @@ function accessorToTypedArray(accessor) {
|
|
|
802
1490
|
// dist/parsers/parse-gltf-animations.js
|
|
803
1491
|
function parseGLTFAnimations(gltf) {
|
|
804
1492
|
const gltfAnimations = gltf.animations || [];
|
|
805
|
-
|
|
1493
|
+
const accessorCache1D = /* @__PURE__ */ new Map();
|
|
1494
|
+
const accessorCache2D = /* @__PURE__ */ new Map();
|
|
1495
|
+
return gltfAnimations.flatMap((animation, index) => {
|
|
806
1496
|
const name = animation.name || `Animation-${index}`;
|
|
807
|
-
const
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1497
|
+
const samplerCache = /* @__PURE__ */ new Map();
|
|
1498
|
+
const channels = animation.channels.flatMap(({ sampler, target }) => {
|
|
1499
|
+
const path = getSupportedAnimationPath(target.path);
|
|
1500
|
+
if (!path) {
|
|
1501
|
+
return [];
|
|
1502
|
+
}
|
|
1503
|
+
const targetNode = gltf.nodes[target.node ?? 0];
|
|
1504
|
+
if (!targetNode) {
|
|
1505
|
+
throw new Error(`Cannot find animation target ${target.node}`);
|
|
1506
|
+
}
|
|
1507
|
+
let parsedSampler = samplerCache.get(sampler);
|
|
1508
|
+
if (!parsedSampler) {
|
|
1509
|
+
const gltfSampler = animation.samplers[sampler];
|
|
1510
|
+
if (!gltfSampler) {
|
|
1511
|
+
throw new Error(`Cannot find animation sampler ${sampler}`);
|
|
1512
|
+
}
|
|
1513
|
+
const { input, interpolation = "LINEAR", output } = gltfSampler;
|
|
1514
|
+
parsedSampler = {
|
|
1515
|
+
input: accessorToJsArray1D(gltf.accessors[input], accessorCache1D),
|
|
1516
|
+
interpolation,
|
|
1517
|
+
output: accessorToJsArray2D(gltf.accessors[output], accessorCache2D)
|
|
1518
|
+
};
|
|
1519
|
+
samplerCache.set(sampler, parsedSampler);
|
|
1520
|
+
}
|
|
1521
|
+
return {
|
|
1522
|
+
sampler: parsedSampler,
|
|
1523
|
+
targetNodeId: targetNode.id,
|
|
1524
|
+
path
|
|
1525
|
+
};
|
|
1526
|
+
});
|
|
1527
|
+
return channels.length ? [{ name, channels }] : [];
|
|
818
1528
|
});
|
|
819
1529
|
}
|
|
820
|
-
function
|
|
821
|
-
if (
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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)));
|
|
1556
|
+
}
|
|
1557
|
+
accessorCache.set(accessor, result);
|
|
1558
|
+
return result;
|
|
1559
|
+
}
|
|
1560
|
+
function assert(condition, message) {
|
|
1561
|
+
if (!condition) {
|
|
1562
|
+
throw new Error(message);
|
|
832
1563
|
}
|
|
833
|
-
return accessor._animation;
|
|
834
1564
|
}
|
|
835
1565
|
|
|
836
|
-
// dist/
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1566
|
+
// dist/gltf/gltf-extension-support.js
|
|
1567
|
+
var UNKNOWN_EXTENSION_SUPPORT = {
|
|
1568
|
+
supportLevel: "none",
|
|
1569
|
+
comment: "Not currently listed in the luma.gl glTF extension support registry."
|
|
1570
|
+
};
|
|
1571
|
+
var GLTF_EXTENSION_SUPPORT_REGISTRY = {
|
|
1572
|
+
KHR_draco_mesh_compression: {
|
|
1573
|
+
supportLevel: "built-in",
|
|
1574
|
+
comment: "Decoded by loaders.gl before luma.gl builds the scenegraph."
|
|
1575
|
+
},
|
|
1576
|
+
EXT_meshopt_compression: {
|
|
1577
|
+
supportLevel: "built-in",
|
|
1578
|
+
comment: "Meshopt-compressed primitives are decoded during load."
|
|
1579
|
+
},
|
|
1580
|
+
KHR_mesh_quantization: {
|
|
1581
|
+
supportLevel: "built-in",
|
|
1582
|
+
comment: "Quantized accessors are unpacked before geometry creation."
|
|
1583
|
+
},
|
|
1584
|
+
KHR_lights_punctual: {
|
|
1585
|
+
supportLevel: "built-in",
|
|
1586
|
+
comment: "Parsed into luma.gl Light objects."
|
|
1587
|
+
},
|
|
1588
|
+
KHR_materials_unlit: {
|
|
1589
|
+
supportLevel: "built-in",
|
|
1590
|
+
comment: "Unlit materials bypass the default lighting path."
|
|
1591
|
+
},
|
|
1592
|
+
KHR_materials_emissive_strength: {
|
|
1593
|
+
supportLevel: "built-in",
|
|
1594
|
+
comment: "Applied by the stock PBR shader."
|
|
1595
|
+
},
|
|
1596
|
+
KHR_texture_basisu: {
|
|
1597
|
+
supportLevel: "built-in",
|
|
1598
|
+
comment: "BasisU / KTX2 textures pass through when the device supports them."
|
|
1599
|
+
},
|
|
1600
|
+
KHR_texture_transform: {
|
|
1601
|
+
supportLevel: "built-in",
|
|
1602
|
+
comment: "UV transforms are applied during load."
|
|
1603
|
+
},
|
|
1604
|
+
EXT_texture_webp: {
|
|
1605
|
+
supportLevel: "loader-only",
|
|
1606
|
+
comment: "Texture source is resolved during load; final support depends on browser and device decode support."
|
|
1607
|
+
},
|
|
1608
|
+
EXT_texture_avif: {
|
|
1609
|
+
supportLevel: "loader-only",
|
|
1610
|
+
comment: "Texture source is resolved during load; final support depends on browser and device decode support."
|
|
1611
|
+
},
|
|
1612
|
+
KHR_materials_specular: {
|
|
1613
|
+
supportLevel: "built-in",
|
|
1614
|
+
comment: "The stock shader now applies specular factors and textures to the dielectric F0 term."
|
|
1615
|
+
},
|
|
1616
|
+
KHR_materials_ior: {
|
|
1617
|
+
supportLevel: "built-in",
|
|
1618
|
+
comment: "The stock shader now drives dielectric reflectance from the glTF IOR value."
|
|
1619
|
+
},
|
|
1620
|
+
KHR_materials_transmission: {
|
|
1621
|
+
supportLevel: "built-in",
|
|
1622
|
+
comment: "The stock shader now applies transmission to the base layer and exposes transparency through alpha, without a scene-color refraction buffer."
|
|
1623
|
+
},
|
|
1624
|
+
KHR_materials_volume: {
|
|
1625
|
+
supportLevel: "built-in",
|
|
1626
|
+
comment: "Thickness and attenuation now tint transmitted light in the stock shader."
|
|
1627
|
+
},
|
|
1628
|
+
KHR_materials_clearcoat: {
|
|
1629
|
+
supportLevel: "built-in",
|
|
1630
|
+
comment: "The stock shader now adds a secondary clearcoat specular lobe."
|
|
1631
|
+
},
|
|
1632
|
+
KHR_materials_sheen: {
|
|
1633
|
+
supportLevel: "built-in",
|
|
1634
|
+
comment: "The stock shader now adds a sheen lobe for cloth-like materials."
|
|
1635
|
+
},
|
|
1636
|
+
KHR_materials_iridescence: {
|
|
1637
|
+
supportLevel: "built-in",
|
|
1638
|
+
comment: "The stock shader now tints specular response with a view-dependent thin-film iridescence approximation."
|
|
1639
|
+
},
|
|
1640
|
+
KHR_materials_anisotropy: {
|
|
1641
|
+
supportLevel: "built-in",
|
|
1642
|
+
comment: "The stock shader now shapes highlights and IBL response with an anisotropy-direction approximation."
|
|
1643
|
+
},
|
|
1644
|
+
KHR_materials_pbrSpecularGlossiness: {
|
|
1645
|
+
supportLevel: "loader-only",
|
|
1646
|
+
comment: "Extension data can be loaded, but it is not translated into the default metallic-roughness material path."
|
|
1647
|
+
},
|
|
1648
|
+
KHR_materials_variants: {
|
|
1649
|
+
supportLevel: "loader-only",
|
|
1650
|
+
comment: "Variant metadata can be loaded, but applications must choose and apply variants."
|
|
1651
|
+
},
|
|
1652
|
+
EXT_mesh_gpu_instancing: {
|
|
1653
|
+
supportLevel: "none",
|
|
1654
|
+
comment: "GPU instancing data is not yet converted into luma.gl instanced draw setup."
|
|
1655
|
+
},
|
|
1656
|
+
KHR_node_visibility: {
|
|
1657
|
+
supportLevel: "none",
|
|
1658
|
+
comment: "Node-visibility animations and toggles are not mapped onto runtime scenegraph state."
|
|
1659
|
+
},
|
|
1660
|
+
KHR_animation_pointer: {
|
|
1661
|
+
supportLevel: "none",
|
|
1662
|
+
comment: "Animation pointers are not mapped onto runtime scenegraph updates."
|
|
1663
|
+
},
|
|
1664
|
+
KHR_materials_diffuse_transmission: {
|
|
1665
|
+
supportLevel: "none",
|
|
1666
|
+
comment: "Diffuse-transmission shading is not implemented in the stock PBR shader."
|
|
1667
|
+
},
|
|
1668
|
+
KHR_materials_dispersion: {
|
|
1669
|
+
supportLevel: "none",
|
|
1670
|
+
comment: "Chromatic dispersion is not implemented in the stock PBR shader."
|
|
1671
|
+
},
|
|
1672
|
+
KHR_materials_volume_scatter: {
|
|
1673
|
+
supportLevel: "none",
|
|
1674
|
+
comment: "Volume scattering is not implemented in the stock PBR shader."
|
|
1675
|
+
},
|
|
1676
|
+
KHR_xmp: {
|
|
1677
|
+
supportLevel: "none",
|
|
1678
|
+
comment: "Metadata payloads remain in the loaded glTF, but luma.gl does not interpret them."
|
|
1679
|
+
},
|
|
1680
|
+
KHR_xmp_json_ld: {
|
|
1681
|
+
supportLevel: "none",
|
|
1682
|
+
comment: "Metadata is preserved in the glTF, but luma.gl does not interpret it."
|
|
1683
|
+
},
|
|
1684
|
+
EXT_lights_image_based: {
|
|
1685
|
+
supportLevel: "none",
|
|
1686
|
+
comment: "Use loadPBREnvironment() or custom environment setup instead."
|
|
1687
|
+
},
|
|
1688
|
+
EXT_texture_video: {
|
|
1689
|
+
supportLevel: "none",
|
|
1690
|
+
comment: "Video textures are not created automatically by the stock pipeline."
|
|
1691
|
+
},
|
|
1692
|
+
MSFT_lod: {
|
|
1693
|
+
supportLevel: "none",
|
|
1694
|
+
comment: "Level-of-detail switching is not implemented in the stock scenegraph loader."
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
function getGLTFExtensionSupport(gltf) {
|
|
1698
|
+
const extensionNames = Array.from(collectGLTFExtensionNames(gltf)).sort();
|
|
1699
|
+
const extensionSupportEntries = extensionNames.map((extensionName) => {
|
|
1700
|
+
const extensionSupportDefinition = GLTF_EXTENSION_SUPPORT_REGISTRY[extensionName] || UNKNOWN_EXTENSION_SUPPORT;
|
|
1701
|
+
return [
|
|
1702
|
+
extensionName,
|
|
1703
|
+
{
|
|
1704
|
+
extensionName,
|
|
1705
|
+
supported: extensionSupportDefinition.supportLevel === "built-in",
|
|
1706
|
+
supportLevel: extensionSupportDefinition.supportLevel,
|
|
1707
|
+
comment: extensionSupportDefinition.comment
|
|
1708
|
+
}
|
|
1709
|
+
];
|
|
1710
|
+
});
|
|
1711
|
+
return new Map(extensionSupportEntries);
|
|
1712
|
+
}
|
|
1713
|
+
function collectGLTFExtensionNames(gltf) {
|
|
1714
|
+
var _a;
|
|
1715
|
+
const gltfWithRemovedExtensions = gltf;
|
|
1716
|
+
const extensionNames = /* @__PURE__ */ new Set();
|
|
1717
|
+
addExtensionNames(extensionNames, gltf.extensionsUsed);
|
|
1718
|
+
addExtensionNames(extensionNames, gltf.extensionsRequired);
|
|
1719
|
+
addExtensionNames(extensionNames, gltfWithRemovedExtensions.extensionsRemoved);
|
|
1720
|
+
addExtensionNames(extensionNames, Object.keys(gltf.extensions || {}));
|
|
1721
|
+
if (((_a = gltfWithRemovedExtensions.lights) == null ? void 0 : _a.length) || gltf.nodes.some((node) => "light" in node)) {
|
|
1722
|
+
extensionNames.add("KHR_lights_punctual");
|
|
840
1723
|
}
|
|
841
|
-
if (
|
|
842
|
-
|
|
1724
|
+
if (gltf.materials.some((material) => {
|
|
1725
|
+
var _a2;
|
|
1726
|
+
const gltfMaterial = material;
|
|
1727
|
+
return gltfMaterial.unlit || ((_a2 = gltfMaterial.extensions) == null ? void 0 : _a2.KHR_materials_unlit);
|
|
1728
|
+
})) {
|
|
1729
|
+
extensionNames.add("KHR_materials_unlit");
|
|
843
1730
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
return result;
|
|
1731
|
+
return extensionNames;
|
|
1732
|
+
}
|
|
1733
|
+
function addExtensionNames(extensionNames, newExtensionNames = []) {
|
|
1734
|
+
for (const extensionName of newExtensionNames) {
|
|
1735
|
+
extensionNames.add(extensionName);
|
|
850
1736
|
}
|
|
851
|
-
return object;
|
|
852
1737
|
}
|
|
853
1738
|
|
|
854
1739
|
// dist/gltf/create-scenegraph-from-gltf.js
|
|
855
1740
|
function createScenegraphsFromGLTF(device, gltf, options) {
|
|
856
|
-
|
|
857
|
-
const scenes = parseGLTF(device, gltf, options);
|
|
1741
|
+
const { scenes, materials, gltfMeshIdToNodeMap, gltfNodeIdToNodeMap, gltfNodeIndexToNodeMap } = parseGLTF(device, gltf, options);
|
|
858
1742
|
const animations = parseGLTFAnimations(gltf);
|
|
859
|
-
const animator = new GLTFAnimator({ animations });
|
|
1743
|
+
const animator = new GLTFAnimator({ animations, gltfNodeIdToNodeMap });
|
|
860
1744
|
const lights = parseGLTFLights(gltf);
|
|
861
|
-
|
|
1745
|
+
const extensionSupport = getGLTFExtensionSupport(gltf);
|
|
1746
|
+
const sceneBounds = scenes.map((scene) => getScenegraphBounds(scene.getBounds()));
|
|
1747
|
+
const modelBounds = getCombinedScenegraphBounds(sceneBounds);
|
|
1748
|
+
return {
|
|
1749
|
+
scenes,
|
|
1750
|
+
materials,
|
|
1751
|
+
animator,
|
|
1752
|
+
lights,
|
|
1753
|
+
extensionSupport,
|
|
1754
|
+
sceneBounds,
|
|
1755
|
+
modelBounds,
|
|
1756
|
+
gltfMeshIdToNodeMap,
|
|
1757
|
+
gltfNodeIdToNodeMap,
|
|
1758
|
+
gltfNodeIndexToNodeMap,
|
|
1759
|
+
gltf
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
function getScenegraphBounds(bounds) {
|
|
1763
|
+
if (!bounds) {
|
|
1764
|
+
return {
|
|
1765
|
+
bounds: null,
|
|
1766
|
+
center: [0, 0, 0],
|
|
1767
|
+
size: [0, 0, 0],
|
|
1768
|
+
radius: 0.5,
|
|
1769
|
+
recommendedOrbitDistance: 1
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
const normalizedBounds = [
|
|
1773
|
+
[bounds[0][0], bounds[0][1], bounds[0][2]],
|
|
1774
|
+
[bounds[1][0], bounds[1][1], bounds[1][2]]
|
|
1775
|
+
];
|
|
1776
|
+
const size = [
|
|
1777
|
+
normalizedBounds[1][0] - normalizedBounds[0][0],
|
|
1778
|
+
normalizedBounds[1][1] - normalizedBounds[0][1],
|
|
1779
|
+
normalizedBounds[1][2] - normalizedBounds[0][2]
|
|
1780
|
+
];
|
|
1781
|
+
const center = [
|
|
1782
|
+
normalizedBounds[0][0] + size[0] * 0.5,
|
|
1783
|
+
normalizedBounds[0][1] + size[1] * 0.5,
|
|
1784
|
+
normalizedBounds[0][2] + size[2] * 0.5
|
|
1785
|
+
];
|
|
1786
|
+
const maxHalfExtent = Math.max(size[0], size[1], size[2]) * 0.5;
|
|
1787
|
+
const radius = Math.max(0.5 * Math.hypot(size[0], size[1], size[2]), 1e-3);
|
|
1788
|
+
return {
|
|
1789
|
+
bounds: normalizedBounds,
|
|
1790
|
+
center,
|
|
1791
|
+
size,
|
|
1792
|
+
radius,
|
|
1793
|
+
recommendedOrbitDistance: Math.max(Math.max(maxHalfExtent, 1e-3) / Math.tan(Math.PI / 6) * 1.15, radius * 1.1)
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
function getCombinedScenegraphBounds(sceneBounds) {
|
|
1797
|
+
let combinedBounds = null;
|
|
1798
|
+
for (const sceneBoundInfo of sceneBounds) {
|
|
1799
|
+
if (!sceneBoundInfo.bounds) {
|
|
1800
|
+
continue;
|
|
1801
|
+
}
|
|
1802
|
+
if (!combinedBounds) {
|
|
1803
|
+
combinedBounds = [
|
|
1804
|
+
[...sceneBoundInfo.bounds[0]],
|
|
1805
|
+
[...sceneBoundInfo.bounds[1]]
|
|
1806
|
+
];
|
|
1807
|
+
continue;
|
|
1808
|
+
}
|
|
1809
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
1810
|
+
combinedBounds[0][axis] = Math.min(combinedBounds[0][axis], sceneBoundInfo.bounds[0][axis]);
|
|
1811
|
+
combinedBounds[1][axis] = Math.max(combinedBounds[1][axis], sceneBoundInfo.bounds[1][axis]);
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
return getScenegraphBounds(combinedBounds);
|
|
862
1815
|
}
|
|
863
1816
|
//# sourceMappingURL=index.cjs.map
|