three-stdlib 2.21.9 → 2.21.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
- import { Loader, LoaderUtils, FileLoader, Color, SpotLight, PointLight, DirectionalLight, MeshBasicMaterial, sRGBEncoding, MeshPhysicalMaterial, Vector2, TangentSpaceNormalMap, Quaternion, TextureLoader, ImageBitmapLoader, InterleavedBuffer, InterleavedBufferAttribute, BufferAttribute, LinearFilter, LinearMipmapLinearFilter, RepeatWrapping, PointsMaterial, Material, LineBasicMaterial, MeshStandardMaterial, DoubleSide, PropertyBinding, BufferGeometry, SkinnedMesh, Mesh, LineSegments, Line, LineLoop, Points, Group, PerspectiveCamera, MathUtils, OrthographicCamera, InterpolateLinear, AnimationClip, Bone, Object3D, Matrix4, Skeleton, TriangleFanDrawMode, NearestFilter, NearestMipmapNearestFilter, LinearMipmapNearestFilter, NearestMipmapLinearFilter, ClampToEdgeWrapping, MirroredRepeatWrapping, InterpolateDiscrete, FrontSide, Texture, TriangleStripDrawMode, VectorKeyframeTrack, QuaternionKeyframeTrack, NumberKeyframeTrack, Box3, Vector3, Sphere, Interpolant } from 'three';
1
+ import { Loader, LoaderUtils, FileLoader, Color, SpotLight, PointLight, DirectionalLight, MeshBasicMaterial, sRGBEncoding, MeshPhysicalMaterial, Vector2, Matrix4, Vector3, Quaternion, InstancedMesh, Object3D, TextureLoader, ImageBitmapLoader, BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, LinearFilter, LinearMipmapLinearFilter, RepeatWrapping, PointsMaterial, Material, LineBasicMaterial, MeshStandardMaterial, DoubleSide, PropertyBinding, BufferGeometry, SkinnedMesh, Mesh, TriangleStripDrawMode, TriangleFanDrawMode, LineSegments, Line, LineLoop, Points, Group, PerspectiveCamera, MathUtils, OrthographicCamera, Skeleton, InterpolateLinear, AnimationClip, Bone, NearestFilter, NearestMipmapNearestFilter, LinearMipmapNearestFilter, NearestMipmapLinearFilter, ClampToEdgeWrapping, MirroredRepeatWrapping, InterpolateDiscrete, FrontSide, Texture, VectorKeyframeTrack, QuaternionKeyframeTrack, NumberKeyframeTrack, Box3, Sphere, Interpolant } from 'three';
2
+ import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';
2
3
 
3
4
  class GLTFLoader extends Loader {
4
5
  constructor(manager) {
@@ -16,6 +17,9 @@ class GLTFLoader extends Loader {
16
17
  this.register(function (parser) {
17
18
  return new GLTFTextureWebPExtension(parser);
18
19
  });
20
+ this.register(function (parser) {
21
+ return new GLTFTextureAVIFExtension(parser);
22
+ });
19
23
  this.register(function (parser) {
20
24
  return new GLTFMaterialsSheenExtension(parser);
21
25
  });
@@ -43,6 +47,9 @@ class GLTFLoader extends Loader {
43
47
  this.register(function (parser) {
44
48
  return new GLTFMeshoptCompression(parser);
45
49
  });
50
+ this.register(function (parser) {
51
+ return new GLTFMeshGpuInstancing(parser);
52
+ });
46
53
  }
47
54
 
48
55
  load(url, onLoad, onProgress, onError) {
@@ -126,14 +133,15 @@ class GLTFLoader extends Loader {
126
133
  }
127
134
 
128
135
  parse(data, path, onLoad, onError) {
129
- let content;
136
+ let json;
130
137
  const extensions = {};
131
138
  const plugins = {};
139
+ const textDecoder = new TextDecoder();
132
140
 
133
141
  if (typeof data === 'string') {
134
- content = data;
135
- } else {
136
- const magic = LoaderUtils.decodeText(new Uint8Array(data, 0, 4));
142
+ json = JSON.parse(data);
143
+ } else if (data instanceof ArrayBuffer) {
144
+ const magic = textDecoder.decode(new Uint8Array(data, 0, 4));
137
145
 
138
146
  if (magic === BINARY_EXTENSION_HEADER_MAGIC) {
139
147
  try {
@@ -143,14 +151,14 @@ class GLTFLoader extends Loader {
143
151
  return;
144
152
  }
145
153
 
146
- content = extensions[EXTENSIONS.KHR_BINARY_GLTF].content;
154
+ json = JSON.parse(extensions[EXTENSIONS.KHR_BINARY_GLTF].content);
147
155
  } else {
148
- content = LoaderUtils.decodeText(new Uint8Array(data));
156
+ json = JSON.parse(textDecoder.decode(data));
149
157
  }
158
+ } else {
159
+ json = data;
150
160
  }
151
161
 
152
- const json = JSON.parse(content);
153
-
154
162
  if (json.asset === undefined || json.asset.version[0] < 2) {
155
163
  if (onError) onError(new Error('THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.'));
156
164
  return;
@@ -186,10 +194,6 @@ class GLTFLoader extends Loader {
186
194
  extensions[extensionName] = new GLTFMaterialsUnlitExtension();
187
195
  break;
188
196
 
189
- case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
190
- extensions[extensionName] = new GLTFMaterialsPbrSpecularGlossinessExtension();
191
- break;
192
-
193
197
  case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
194
198
  extensions[extensionName] = new GLTFDracoMeshCompressionExtension(json, this.dracoLoader);
195
199
  break;
@@ -257,7 +261,6 @@ const EXTENSIONS = {
257
261
  KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
258
262
  KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
259
263
  KHR_MATERIALS_IOR: 'KHR_materials_ior',
260
- KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
261
264
  KHR_MATERIALS_SHEEN: 'KHR_materials_sheen',
262
265
  KHR_MATERIALS_SPECULAR: 'KHR_materials_specular',
263
266
  KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
@@ -269,7 +272,9 @@ const EXTENSIONS = {
269
272
  KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
270
273
  KHR_MATERIALS_EMISSIVE_STRENGTH: 'KHR_materials_emissive_strength',
271
274
  EXT_TEXTURE_WEBP: 'EXT_texture_webp',
272
- EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression'
275
+ EXT_TEXTURE_AVIF: 'EXT_texture_avif',
276
+ EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
277
+ EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'
273
278
  };
274
279
  /**
275
280
  * Punctual Lights Extension
@@ -348,6 +353,7 @@ class GLTFLightsExtension {
348
353
 
349
354
  lightNode.position.set(0, 0, 0);
350
355
  lightNode.decay = 2;
356
+ assignExtrasToUserData(lightNode, lightDef);
351
357
  if (lightDef.intensity !== undefined) lightNode.intensity = lightDef.intensity;
352
358
  lightNode.name = parser.createUniqueName(lightDef.name || 'light_' + lightIndex);
353
359
  dependency = Promise.resolve(lightNode);
@@ -355,6 +361,11 @@ class GLTFLightsExtension {
355
361
  return dependency;
356
362
  }
357
363
 
364
+ getDependency(type, index) {
365
+ if (type !== 'light') return;
366
+ return this._loadLight(index);
367
+ }
368
+
358
369
  createNodeAttachment(nodeIndex) {
359
370
  const self = this;
360
371
  const parser = this.parser;
@@ -883,6 +894,68 @@ class GLTFTextureWebPExtension {
883
894
  return this.isSupported;
884
895
  }
885
896
 
897
+ }
898
+ /**
899
+ * AVIF Texture Extension
900
+ *
901
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_avif
902
+ */
903
+
904
+
905
+ class GLTFTextureAVIFExtension {
906
+ constructor(parser) {
907
+ this.parser = parser;
908
+ this.name = EXTENSIONS.EXT_TEXTURE_AVIF;
909
+ this.isSupported = null;
910
+ }
911
+
912
+ loadTexture(textureIndex) {
913
+ const name = this.name;
914
+ const parser = this.parser;
915
+ const json = parser.json;
916
+ const textureDef = json.textures[textureIndex];
917
+
918
+ if (!textureDef.extensions || !textureDef.extensions[name]) {
919
+ return null;
920
+ }
921
+
922
+ const extension = textureDef.extensions[name];
923
+ const source = json.images[extension.source];
924
+ let loader = parser.textureLoader;
925
+
926
+ if (source.uri) {
927
+ const handler = parser.options.manager.getHandler(source.uri);
928
+ if (handler !== null) loader = handler;
929
+ }
930
+
931
+ return this.detectSupport().then(function (isSupported) {
932
+ if (isSupported) return parser.loadTextureImage(textureIndex, extension.source, loader);
933
+
934
+ if (json.extensionsRequired && json.extensionsRequired.indexOf(name) >= 0) {
935
+ throw new Error('THREE.GLTFLoader: AVIF required by asset but unsupported.');
936
+ } // Fall back to PNG or JPEG.
937
+
938
+
939
+ return parser.loadTexture(textureIndex);
940
+ });
941
+ }
942
+
943
+ detectSupport() {
944
+ if (!this.isSupported) {
945
+ this.isSupported = new Promise(function (resolve) {
946
+ const image = new Image(); // Lossy test image.
947
+
948
+ image.src = 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABcAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB9tZGF0EgAKCBgABogQEDQgMgkQAAAAB8dSLfI=';
949
+
950
+ image.onload = image.onerror = function () {
951
+ resolve(image.height === 1);
952
+ };
953
+ });
954
+ }
955
+
956
+ return this.isSupported;
957
+ }
958
+
886
959
  }
887
960
  /**
888
961
  * meshopt BufferView Compression Extension
@@ -940,6 +1013,109 @@ class GLTFMeshoptCompression {
940
1013
  }
941
1014
  }
942
1015
 
1016
+ }
1017
+ /**
1018
+ * GPU Instancing Extension
1019
+ *
1020
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing
1021
+ *
1022
+ */
1023
+
1024
+
1025
+ class GLTFMeshGpuInstancing {
1026
+ constructor(parser) {
1027
+ this.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING;
1028
+ this.parser = parser;
1029
+ }
1030
+
1031
+ createNodeMesh(nodeIndex) {
1032
+ const json = this.parser.json;
1033
+ const nodeDef = json.nodes[nodeIndex];
1034
+
1035
+ if (!nodeDef.extensions || !nodeDef.extensions[this.name] || nodeDef.mesh === undefined) {
1036
+ return null;
1037
+ }
1038
+
1039
+ const meshDef = json.meshes[nodeDef.mesh]; // No Points or Lines + Instancing support yet
1040
+
1041
+ for (const primitive of meshDef.primitives) {
1042
+ if (primitive.mode !== WEBGL_CONSTANTS.TRIANGLES && primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP && primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN && primitive.mode !== undefined) {
1043
+ return null;
1044
+ }
1045
+ }
1046
+
1047
+ const extensionDef = nodeDef.extensions[this.name];
1048
+ const attributesDef = extensionDef.attributes; // @TODO: Can we support InstancedMesh + SkinnedMesh?
1049
+
1050
+ const pending = [];
1051
+ const attributes = {};
1052
+
1053
+ for (const key in attributesDef) {
1054
+ pending.push(this.parser.getDependency('accessor', attributesDef[key]).then(accessor => {
1055
+ attributes[key] = accessor;
1056
+ return attributes[key];
1057
+ }));
1058
+ }
1059
+
1060
+ if (pending.length < 1) {
1061
+ return null;
1062
+ }
1063
+
1064
+ pending.push(this.parser.createNodeMesh(nodeIndex));
1065
+ return Promise.all(pending).then(results => {
1066
+ const nodeObject = results.pop();
1067
+ const meshes = nodeObject.isGroup ? nodeObject.children : [nodeObject];
1068
+ const count = results[0].count; // All attribute counts should be same
1069
+
1070
+ const instancedMeshes = [];
1071
+
1072
+ for (const mesh of meshes) {
1073
+ // Temporal variables
1074
+ const m = new Matrix4();
1075
+ const p = new Vector3();
1076
+ const q = new Quaternion();
1077
+ const s = new Vector3(1, 1, 1);
1078
+ const instancedMesh = new InstancedMesh(mesh.geometry, mesh.material, count);
1079
+
1080
+ for (let i = 0; i < count; i++) {
1081
+ if (attributes.TRANSLATION) {
1082
+ p.fromBufferAttribute(attributes.TRANSLATION, i);
1083
+ }
1084
+
1085
+ if (attributes.ROTATION) {
1086
+ q.fromBufferAttribute(attributes.ROTATION, i);
1087
+ }
1088
+
1089
+ if (attributes.SCALE) {
1090
+ s.fromBufferAttribute(attributes.SCALE, i);
1091
+ }
1092
+
1093
+ instancedMesh.setMatrixAt(i, m.compose(p, q, s));
1094
+ } // Add instance attributes to the geometry, excluding TRS.
1095
+
1096
+
1097
+ for (const attributeName in attributes) {
1098
+ if (attributeName !== 'TRANSLATION' && attributeName !== 'ROTATION' && attributeName !== 'SCALE') {
1099
+ mesh.geometry.setAttribute(attributeName, attributes[attributeName]);
1100
+ }
1101
+ } // Just in case
1102
+
1103
+
1104
+ Object3D.prototype.copy.call(instancedMesh, mesh);
1105
+ this.parser.assignFinalMaterial(instancedMesh);
1106
+ instancedMeshes.push(instancedMesh);
1107
+ }
1108
+
1109
+ if (nodeObject.isGroup) {
1110
+ nodeObject.clear();
1111
+ nodeObject.add(...instancedMeshes);
1112
+ return nodeObject;
1113
+ }
1114
+
1115
+ return instancedMeshes[0];
1116
+ });
1117
+ }
1118
+
943
1119
  }
944
1120
  /* BINARY EXTENSION */
945
1121
 
@@ -957,8 +1133,9 @@ class GLTFBinaryExtension {
957
1133
  this.content = null;
958
1134
  this.body = null;
959
1135
  const headerView = new DataView(data, 0, BINARY_EXTENSION_HEADER_LENGTH);
1136
+ const textDecoder = new TextDecoder();
960
1137
  this.header = {
961
- magic: LoaderUtils.decodeText(new Uint8Array(data.slice(0, 4))),
1138
+ magic: textDecoder.decode(new Uint8Array(data.slice(0, 4))),
962
1139
  version: headerView.getUint32(4, true),
963
1140
  length: headerView.getUint32(8, true)
964
1141
  };
@@ -981,7 +1158,7 @@ class GLTFBinaryExtension {
981
1158
 
982
1159
  if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON) {
983
1160
  const contentArray = new Uint8Array(data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength);
984
- this.content = LoaderUtils.decodeText(contentArray);
1161
+ this.content = textDecoder.decode(contentArray);
985
1162
  } else if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN) {
986
1163
  const byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
987
1164
  this.body = data.slice(byteOffset, byteOffset + chunkLength);
@@ -1070,17 +1247,17 @@ class GLTFTextureTransformExtension {
1070
1247
  }
1071
1248
 
1072
1249
  extendTexture(texture, transform) {
1073
- if (transform.texCoord !== undefined) {
1074
- console.warn('THREE.GLTFLoader: Custom UV sets in "' + this.name + '" extension not yet supported.');
1075
- }
1076
-
1077
- if (transform.offset === undefined && transform.rotation === undefined && transform.scale === undefined) {
1250
+ if ((transform.texCoord === undefined || transform.texCoord === texture.channel) && transform.offset === undefined && transform.rotation === undefined && transform.scale === undefined) {
1078
1251
  // See https://github.com/mrdoob/three.js/issues/21819.
1079
1252
  return texture;
1080
1253
  }
1081
1254
 
1082
1255
  texture = texture.clone();
1083
1256
 
1257
+ if (transform.texCoord !== undefined) {
1258
+ texture.channel = transform.texCoord;
1259
+ }
1260
+
1084
1261
  if (transform.offset !== undefined) {
1085
1262
  texture.offset.fromArray(transform.offset);
1086
1263
  }
@@ -1097,198 +1274,6 @@ class GLTFTextureTransformExtension {
1097
1274
  return texture;
1098
1275
  }
1099
1276
 
1100
- }
1101
- /**
1102
- * Specular-Glossiness Extension
1103
- *
1104
- * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness
1105
- */
1106
-
1107
- /**
1108
- * A sub class of StandardMaterial with some of the functionality
1109
- * changed via the `onBeforeCompile` callback
1110
- * @pailhead
1111
- */
1112
-
1113
-
1114
- class GLTFMeshStandardSGMaterial extends MeshStandardMaterial {
1115
- constructor(params) {
1116
- super();
1117
- this.isGLTFSpecularGlossinessMaterial = true; //various chunks that need replacing
1118
-
1119
- const specularMapParsFragmentChunk = ['#ifdef USE_SPECULARMAP', ' uniform sampler2D specularMap;', '#endif'].join('\n');
1120
- const glossinessMapParsFragmentChunk = ['#ifdef USE_GLOSSINESSMAP', ' uniform sampler2D glossinessMap;', '#endif'].join('\n');
1121
- const specularMapFragmentChunk = ['vec3 specularFactor = specular;', '#ifdef USE_SPECULARMAP', ' vec4 texelSpecular = texture2D( specularMap, vUv );', ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture', ' specularFactor *= texelSpecular.rgb;', '#endif'].join('\n');
1122
- const glossinessMapFragmentChunk = ['float glossinessFactor = glossiness;', '#ifdef USE_GLOSSINESSMAP', ' vec4 texelGlossiness = texture2D( glossinessMap, vUv );', ' // reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture', ' glossinessFactor *= texelGlossiness.a;', '#endif'].join('\n');
1123
- const lightPhysicalFragmentChunk = ['PhysicalMaterial material;', 'material.diffuseColor = diffuseColor.rgb * ( 1. - max( specularFactor.r, max( specularFactor.g, specularFactor.b ) ) );', 'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );', 'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );', 'material.roughness = max( 1.0 - glossinessFactor, 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap.', 'material.roughness += geometryRoughness;', 'material.roughness = min( material.roughness, 1.0 );', 'material.specularColor = specularFactor;'].join('\n');
1124
- const uniforms = {
1125
- specular: {
1126
- value: new Color().setHex(0xffffff)
1127
- },
1128
- glossiness: {
1129
- value: 1
1130
- },
1131
- specularMap: {
1132
- value: null
1133
- },
1134
- glossinessMap: {
1135
- value: null
1136
- }
1137
- };
1138
- this._extraUniforms = uniforms;
1139
-
1140
- this.onBeforeCompile = function (shader) {
1141
- for (const uniformName in uniforms) {
1142
- shader.uniforms[uniformName] = uniforms[uniformName];
1143
- }
1144
-
1145
- shader.fragmentShader = shader.fragmentShader.replace('uniform float roughness;', 'uniform vec3 specular;').replace('uniform float metalness;', 'uniform float glossiness;').replace('#include <roughnessmap_pars_fragment>', specularMapParsFragmentChunk).replace('#include <metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk).replace('#include <roughnessmap_fragment>', specularMapFragmentChunk).replace('#include <metalnessmap_fragment>', glossinessMapFragmentChunk).replace('#include <lights_physical_fragment>', lightPhysicalFragmentChunk);
1146
- };
1147
-
1148
- Object.defineProperties(this, {
1149
- specular: {
1150
- get: function () {
1151
- return uniforms.specular.value;
1152
- },
1153
- set: function (v) {
1154
- uniforms.specular.value = v;
1155
- }
1156
- },
1157
- specularMap: {
1158
- get: function () {
1159
- return uniforms.specularMap.value;
1160
- },
1161
- set: function (v) {
1162
- uniforms.specularMap.value = v;
1163
-
1164
- if (v) {
1165
- this.defines.USE_SPECULARMAP = ''; // USE_UV is set by the renderer for specular maps
1166
- } else {
1167
- delete this.defines.USE_SPECULARMAP;
1168
- }
1169
- }
1170
- },
1171
- glossiness: {
1172
- get: function () {
1173
- return uniforms.glossiness.value;
1174
- },
1175
- set: function (v) {
1176
- uniforms.glossiness.value = v;
1177
- }
1178
- },
1179
- glossinessMap: {
1180
- get: function () {
1181
- return uniforms.glossinessMap.value;
1182
- },
1183
- set: function (v) {
1184
- uniforms.glossinessMap.value = v;
1185
-
1186
- if (v) {
1187
- this.defines.USE_GLOSSINESSMAP = '';
1188
- this.defines.USE_UV = '';
1189
- } else {
1190
- delete this.defines.USE_GLOSSINESSMAP;
1191
- delete this.defines.USE_UV;
1192
- }
1193
- }
1194
- }
1195
- });
1196
- delete this.metalness;
1197
- delete this.roughness;
1198
- delete this.metalnessMap;
1199
- delete this.roughnessMap;
1200
- this.setValues(params);
1201
- }
1202
-
1203
- copy(source) {
1204
- super.copy(source);
1205
- this.specularMap = source.specularMap;
1206
- this.specular.copy(source.specular);
1207
- this.glossinessMap = source.glossinessMap;
1208
- this.glossiness = source.glossiness;
1209
- delete this.metalness;
1210
- delete this.roughness;
1211
- delete this.metalnessMap;
1212
- delete this.roughnessMap;
1213
- return this;
1214
- }
1215
-
1216
- }
1217
-
1218
- class GLTFMaterialsPbrSpecularGlossinessExtension {
1219
- constructor() {
1220
- this.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS;
1221
- this.specularGlossinessParams = ['color', 'map', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveIntensity', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalMapType', 'displacementMap', 'displacementScale', 'displacementBias', 'specularMap', 'specular', 'glossinessMap', 'glossiness', 'alphaMap', 'envMap', 'envMapIntensity', 'refractionRatio'];
1222
- }
1223
-
1224
- getMaterialType() {
1225
- return GLTFMeshStandardSGMaterial;
1226
- }
1227
-
1228
- extendParams(materialParams, materialDef, parser) {
1229
- const pbrSpecularGlossiness = materialDef.extensions[this.name];
1230
- materialParams.color = new Color(1.0, 1.0, 1.0);
1231
- materialParams.opacity = 1.0;
1232
- const pending = [];
1233
-
1234
- if (Array.isArray(pbrSpecularGlossiness.diffuseFactor)) {
1235
- const array = pbrSpecularGlossiness.diffuseFactor;
1236
- materialParams.color.fromArray(array);
1237
- materialParams.opacity = array[3];
1238
- }
1239
-
1240
- if (pbrSpecularGlossiness.diffuseTexture !== undefined) {
1241
- pending.push(parser.assignTexture(materialParams, 'map', pbrSpecularGlossiness.diffuseTexture, sRGBEncoding));
1242
- }
1243
-
1244
- materialParams.emissive = new Color(0.0, 0.0, 0.0);
1245
- materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
1246
- materialParams.specular = new Color(1.0, 1.0, 1.0);
1247
-
1248
- if (Array.isArray(pbrSpecularGlossiness.specularFactor)) {
1249
- materialParams.specular.fromArray(pbrSpecularGlossiness.specularFactor);
1250
- }
1251
-
1252
- if (pbrSpecularGlossiness.specularGlossinessTexture !== undefined) {
1253
- const specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
1254
- pending.push(parser.assignTexture(materialParams, 'glossinessMap', specGlossMapDef));
1255
- pending.push(parser.assignTexture(materialParams, 'specularMap', specGlossMapDef, sRGBEncoding));
1256
- }
1257
-
1258
- return Promise.all(pending);
1259
- }
1260
-
1261
- createMaterial(materialParams) {
1262
- const material = new GLTFMeshStandardSGMaterial(materialParams);
1263
- material.fog = true;
1264
- material.color = materialParams.color;
1265
- material.map = materialParams.map === undefined ? null : materialParams.map;
1266
- material.lightMap = null;
1267
- material.lightMapIntensity = 1.0;
1268
- material.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap;
1269
- material.aoMapIntensity = 1.0;
1270
- material.emissive = materialParams.emissive;
1271
- material.emissiveIntensity = materialParams.emissiveIntensity === undefined ? 1.0 : materialParams.emissiveIntensity;
1272
- material.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap;
1273
- material.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap;
1274
- material.bumpScale = 1;
1275
- material.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap;
1276
- material.normalMapType = TangentSpaceNormalMap;
1277
- if (materialParams.normalScale) material.normalScale = materialParams.normalScale;
1278
- material.displacementMap = null;
1279
- material.displacementScale = 1;
1280
- material.displacementBias = 0;
1281
- material.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap;
1282
- material.specular = materialParams.specular;
1283
- material.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap;
1284
- material.glossiness = materialParams.glossiness;
1285
- material.alphaMap = null;
1286
- material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
1287
- material.envMapIntensity = 1.0;
1288
- material.refractionRatio = 0.98;
1289
- return material;
1290
- }
1291
-
1292
1277
  }
1293
1278
  /**
1294
1279
  * Mesh Quantization Extension
@@ -1650,13 +1635,13 @@ function getImageURIMimeType(uri) {
1650
1635
  if (uri.search(/\.webp($|\?)/i) > 0 || uri.search(/^data\:image\/webp/) === 0) return 'image/webp';
1651
1636
  return 'image/png';
1652
1637
  }
1638
+
1639
+ const _identityMatrix = new Matrix4();
1653
1640
  /* GLTF PARSER */
1654
1641
 
1655
1642
 
1656
1643
  class GLTFParser {
1657
1644
  constructor(json = {}, options = {}) {
1658
- var _navigator$userAgent, _navigator$userAgent2;
1659
-
1660
1645
  this.json = json;
1661
1646
  this.extensions = {};
1662
1647
  this.plugins = {};
@@ -1666,7 +1651,9 @@ class GLTFParser {
1666
1651
 
1667
1652
  this.associations = new Map(); // BufferGeometry caching
1668
1653
 
1669
- this.primitiveCache = {}; // Object3D instance caches
1654
+ this.primitiveCache = {}; // Node cache
1655
+
1656
+ this.nodeCache = {}; // Object3D instance caches
1670
1657
 
1671
1658
  this.meshCache = {
1672
1659
  refs: {},
@@ -1686,9 +1673,15 @@ class GLTFParser {
1686
1673
  this.nodeNamesUsed = {}; // Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the
1687
1674
  // expensive work of uploading a texture to the GPU off the main thread.
1688
1675
 
1689
- const isSafari = typeof navigator !== 'undefined' && /^((?!chrome|android).)*safari/i.test(navigator.userAgent) === true;
1690
- const isFirefox = typeof navigator !== 'undefined' && ((_navigator$userAgent = navigator.userAgent) === null || _navigator$userAgent === void 0 ? void 0 : _navigator$userAgent.indexOf('Firefox')) > -1;
1691
- const firefoxVersion = typeof navigator !== 'undefined' && isFirefox ? (_navigator$userAgent2 = navigator.userAgent) === null || _navigator$userAgent2 === void 0 ? void 0 : _navigator$userAgent2.match(/Firefox\/([0-9]+)\./)[1] : -1;
1676
+ let isSafari = false;
1677
+ let isFirefox = false;
1678
+ let firefoxVersion = -1;
1679
+
1680
+ if (typeof navigator !== 'undefined') {
1681
+ isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) === true;
1682
+ isFirefox = navigator.userAgent.indexOf('Firefox') > -1;
1683
+ firefoxVersion = isFirefox ? navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1] : -1;
1684
+ }
1692
1685
 
1693
1686
  if (typeof createImageBitmap === 'undefined' || isSafari || isFirefox && firefoxVersion < 98) {
1694
1687
  this.textureLoader = new TextureLoader(this.options.manager);
@@ -1719,7 +1712,8 @@ class GLTFParser {
1719
1712
  const json = this.json;
1720
1713
  const extensions = this.extensions; // Clear the loader cache
1721
1714
 
1722
- this.cache.removeAll(); // Mark the special nodes/meshes in json for efficient parse
1715
+ this.cache.removeAll();
1716
+ this.nodeCache = {}; // Mark the special nodes/meshes in json for efficient parse
1723
1717
 
1724
1718
  this._invokeAll(function (ext) {
1725
1719
  return ext._markDefs && ext._markDefs();
@@ -1876,7 +1870,9 @@ class GLTFParser {
1876
1870
  break;
1877
1871
 
1878
1872
  case 'node':
1879
- dependency = this.loadNode(index);
1873
+ dependency = this._invokeOne(function (ext) {
1874
+ return ext.loadNode && ext.loadNode(index);
1875
+ });
1880
1876
  break;
1881
1877
 
1882
1878
  case 'mesh':
@@ -1926,7 +1922,15 @@ class GLTFParser {
1926
1922
  break;
1927
1923
 
1928
1924
  default:
1929
- throw new Error('Unknown type: ' + type);
1925
+ dependency = this._invokeOne(function (ext) {
1926
+ return ext != this && ext.getDependency && ext.getDependency(type, index);
1927
+ });
1928
+
1929
+ if (!dependency) {
1930
+ throw new Error('Unknown type: ' + type);
1931
+ }
1932
+
1933
+ break;
1930
1934
  }
1931
1935
 
1932
1936
  this.cache.add(cacheKey, dependency);
@@ -2010,10 +2014,11 @@ class GLTFParser {
2010
2014
  const accessorDef = this.json.accessors[accessorIndex];
2011
2015
 
2012
2016
  if (accessorDef.bufferView === undefined && accessorDef.sparse === undefined) {
2013
- // Ignore empty accessors, which may be used to declare runtime
2014
- // information about attributes coming from another source (e.g. Draco
2015
- // compression extension).
2016
- return Promise.resolve(null);
2017
+ const itemSize = WEBGL_TYPE_SIZES[accessorDef.type];
2018
+ const TypedArray = WEBGL_COMPONENT_TYPES[accessorDef.componentType];
2019
+ const normalized = accessorDef.normalized === true;
2020
+ const array = new TypedArray(accessorDef.count * itemSize);
2021
+ return Promise.resolve(new BufferAttribute(array, itemSize, normalized));
2017
2022
  }
2018
2023
 
2019
2024
  const pendingBufferViews = [];
@@ -2096,7 +2101,7 @@ class GLTFParser {
2096
2101
  /**
2097
2102
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
2098
2103
  * @param {number} textureIndex
2099
- * @return {Promise<THREE.Texture>}
2104
+ * @return {Promise<THREE.Texture|null>}
2100
2105
  */
2101
2106
 
2102
2107
 
@@ -2130,7 +2135,12 @@ class GLTFParser {
2130
2135
 
2131
2136
  const promise = this.loadImageSource(sourceIndex, loader).then(function (texture) {
2132
2137
  texture.flipY = false;
2133
- if (textureDef.name) texture.name = textureDef.name;
2138
+ texture.name = textureDef.name || sourceDef.name || '';
2139
+
2140
+ if (texture.name === '' && typeof sourceDef.uri === 'string' && sourceDef.uri.startsWith('data:image/') === false) {
2141
+ texture.name = sourceDef.uri;
2142
+ }
2143
+
2134
2144
  const samplers = json.samplers || {};
2135
2145
  const sampler = samplers[textureDef.sampler] || {};
2136
2146
  texture.magFilter = WEBGL_FILTERS[sampler.magFilter] || LinearFilter;
@@ -2217,10 +2227,11 @@ class GLTFParser {
2217
2227
  assignTexture(materialParams, mapName, mapDef, encoding) {
2218
2228
  const parser = this;
2219
2229
  return this.getDependency('texture', mapDef.index).then(function (texture) {
2220
- // Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
2221
- // However, we will copy UV set 0 to UV set 1 on demand for aoMap
2222
- if (mapDef.texCoord !== undefined && mapDef.texCoord != 0 && !(mapName === 'aoMap' && mapDef.texCoord == 1)) {
2223
- console.warn('THREE.GLTFLoader: Custom UV set ' + mapDef.texCoord + ' for texture ' + mapName + ' not yet supported.');
2230
+ if (!texture) return null;
2231
+
2232
+ if (mapDef.texCoord !== undefined && mapDef.texCoord > 0) {
2233
+ texture = texture.clone();
2234
+ texture.channel = mapDef.texCoord;
2224
2235
  }
2225
2236
 
2226
2237
  if (parser.extensions[EXTENSIONS.KHR_TEXTURE_TRANSFORM]) {
@@ -2281,6 +2292,7 @@ class GLTFParser {
2281
2292
  lineMaterial = new LineBasicMaterial();
2282
2293
  Material.prototype.copy.call(lineMaterial, material);
2283
2294
  lineMaterial.color.copy(material.color);
2295
+ lineMaterial.map = material.map;
2284
2296
  this.cache.add(cacheKey, lineMaterial);
2285
2297
  }
2286
2298
 
@@ -2290,7 +2302,6 @@ class GLTFParser {
2290
2302
 
2291
2303
  if (useDerivativeTangents || useVertexColors || useFlatShading) {
2292
2304
  let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
2293
- if (material.isGLTFSpecularGlossinessMaterial) cacheKey += 'specular-glossiness:';
2294
2305
  if (useDerivativeTangents) cacheKey += 'derivative-tangents:';
2295
2306
  if (useVertexColors) cacheKey += 'vertex-colors:';
2296
2307
  if (useFlatShading) cacheKey += 'flat-shading:';
@@ -2312,11 +2323,6 @@ class GLTFParser {
2312
2323
  }
2313
2324
 
2314
2325
  material = cachedMaterial;
2315
- } // workarounds for mesh and geometry
2316
-
2317
-
2318
- if (material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined) {
2319
- geometry.setAttribute('uv2', geometry.attributes.uv);
2320
2326
  }
2321
2327
 
2322
2328
  mesh.material = material;
@@ -2342,11 +2348,7 @@ class GLTFParser {
2342
2348
  const materialExtensions = materialDef.extensions || {};
2343
2349
  const pending = [];
2344
2350
 
2345
- if (materialExtensions[EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS]) {
2346
- const sgExtension = extensions[EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS];
2347
- materialType = sgExtension.getMaterialType();
2348
- pending.push(sgExtension.extendParams(materialParams, materialDef, parser));
2349
- } else if (materialExtensions[EXTENSIONS.KHR_MATERIALS_UNLIT]) {
2351
+ if (materialExtensions[EXTENSIONS.KHR_MATERIALS_UNLIT]) {
2350
2352
  const kmuExtension = extensions[EXTENSIONS.KHR_MATERIALS_UNLIT];
2351
2353
  materialType = kmuExtension.getMaterialType();
2352
2354
  pending.push(kmuExtension.extendParams(materialParams, materialDef, parser));
@@ -2428,14 +2430,7 @@ class GLTFParser {
2428
2430
  }
2429
2431
 
2430
2432
  return Promise.all(pending).then(function () {
2431
- let material;
2432
-
2433
- if (materialType === GLTFMeshStandardSGMaterial) {
2434
- material = extensions[EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS].createMaterial(materialParams);
2435
- } else {
2436
- material = new materialType(materialParams);
2437
- }
2438
-
2433
+ const material = new materialType(materialParams);
2439
2434
  if (materialDef.name) material.name = materialDef.name;
2440
2435
  assignExtrasToUserData(material, materialDef);
2441
2436
  parser.associations.set(material, {
@@ -2550,9 +2545,8 @@ class GLTFParser {
2550
2545
  // .isSkinnedMesh isn't in glTF spec. See ._markDefs()
2551
2546
  mesh = meshDef.isSkinnedMesh === true ? new SkinnedMesh(geometry, material) : new Mesh(geometry, material);
2552
2547
 
2553
- if (mesh.isSkinnedMesh === true && !mesh.geometry.attributes.skinWeight.normalized) {
2554
- // we normalize floating point skin weight array to fix malformed assets (see #15319)
2555
- // it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
2548
+ if (mesh.isSkinnedMesh === true) {
2549
+ // normalize skin weights to fix malformed assets (see #15319)
2556
2550
  mesh.normalizeSkinWeights();
2557
2551
  }
2558
2552
 
@@ -2637,23 +2631,50 @@ class GLTFParser {
2637
2631
  /**
2638
2632
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
2639
2633
  * @param {number} skinIndex
2640
- * @return {Promise<Object>}
2634
+ * @return {Promise<Skeleton>}
2641
2635
  */
2642
2636
 
2643
2637
 
2644
2638
  loadSkin(skinIndex) {
2645
2639
  const skinDef = this.json.skins[skinIndex];
2646
- const skinEntry = {
2647
- joints: skinDef.joints
2648
- };
2640
+ const pending = [];
2641
+
2642
+ for (let i = 0, il = skinDef.joints.length; i < il; i++) {
2643
+ pending.push(this._loadNodeShallow(skinDef.joints[i]));
2644
+ }
2649
2645
 
2650
- if (skinDef.inverseBindMatrices === undefined) {
2651
- return Promise.resolve(skinEntry);
2646
+ if (skinDef.inverseBindMatrices !== undefined) {
2647
+ pending.push(this.getDependency('accessor', skinDef.inverseBindMatrices));
2648
+ } else {
2649
+ pending.push(null);
2652
2650
  }
2653
2651
 
2654
- return this.getDependency('accessor', skinDef.inverseBindMatrices).then(function (accessor) {
2655
- skinEntry.inverseBindMatrices = accessor;
2656
- return skinEntry;
2652
+ return Promise.all(pending).then(function (results) {
2653
+ const inverseBindMatrices = results.pop();
2654
+ const jointNodes = results; // Note that bones (joint nodes) may or may not be in the
2655
+ // scene graph at this time.
2656
+
2657
+ const bones = [];
2658
+ const boneInverses = [];
2659
+
2660
+ for (let i = 0, il = jointNodes.length; i < il; i++) {
2661
+ const jointNode = jointNodes[i];
2662
+
2663
+ if (jointNode) {
2664
+ bones.push(jointNode);
2665
+ const mat = new Matrix4();
2666
+
2667
+ if (inverseBindMatrices !== null) {
2668
+ mat.fromArray(inverseBindMatrices.array, i * 16);
2669
+ }
2670
+
2671
+ boneInverses.push(mat);
2672
+ } else {
2673
+ console.warn('THREE.GLTFLoader: Joint "%s" could not be found.', skinDef.joints[i]);
2674
+ }
2675
+ }
2676
+
2677
+ return new Skeleton(bones, boneInverses);
2657
2678
  });
2658
2679
  }
2659
2680
  /**
@@ -2666,6 +2687,7 @@ class GLTFParser {
2666
2687
  loadAnimation(animationIndex) {
2667
2688
  const json = this.json;
2668
2689
  const animationDef = json.animations[animationIndex];
2690
+ const animationName = animationDef.name ? animationDef.name : 'animation_' + animationIndex;
2669
2691
  const pendingNodes = [];
2670
2692
  const pendingInputAccessors = [];
2671
2693
  const pendingOutputAccessors = [];
@@ -2679,6 +2701,7 @@ class GLTFParser {
2679
2701
  const name = target.node;
2680
2702
  const input = animationDef.parameters !== undefined ? animationDef.parameters[sampler.input] : sampler.input;
2681
2703
  const output = animationDef.parameters !== undefined ? animationDef.parameters[sampler.output] : sampler.output;
2704
+ if (target.node === undefined) continue;
2682
2705
  pendingNodes.push(this.getDependency('node', name));
2683
2706
  pendingInputAccessors.push(this.getDependency('accessor', input));
2684
2707
  pendingOutputAccessors.push(this.getDependency('accessor', output));
@@ -2767,8 +2790,7 @@ class GLTFParser {
2767
2790
  }
2768
2791
  }
2769
2792
 
2770
- const name = animationDef.name ? animationDef.name : 'animation_' + animationIndex;
2771
- return new AnimationClip(name, undefined, tracks);
2793
+ return new AnimationClip(animationName, undefined, tracks);
2772
2794
  });
2773
2795
  }
2774
2796
 
@@ -2803,36 +2825,79 @@ class GLTFParser {
2803
2825
 
2804
2826
  loadNode(nodeIndex) {
2805
2827
  const json = this.json;
2806
- const extensions = this.extensions;
2807
2828
  const parser = this;
2808
- const nodeDef = json.nodes[nodeIndex]; // reserve node's name before its dependencies, so the root has the intended name.
2829
+ const nodeDef = json.nodes[nodeIndex];
2809
2830
 
2810
- const nodeName = nodeDef.name ? parser.createUniqueName(nodeDef.name) : '';
2811
- return function () {
2812
- const pending = [];
2831
+ const nodePending = parser._loadNodeShallow(nodeIndex);
2813
2832
 
2814
- const meshPromise = parser._invokeOne(function (ext) {
2815
- return ext.createNodeMesh && ext.createNodeMesh(nodeIndex);
2816
- });
2833
+ const childPending = [];
2834
+ const childrenDef = nodeDef.children || [];
2835
+
2836
+ for (let i = 0, il = childrenDef.length; i < il; i++) {
2837
+ childPending.push(parser.getDependency('node', childrenDef[i]));
2838
+ }
2839
+
2840
+ const skeletonPending = nodeDef.skin === undefined ? Promise.resolve(null) : parser.getDependency('skin', nodeDef.skin);
2841
+ return Promise.all([nodePending, Promise.all(childPending), skeletonPending]).then(function (results) {
2842
+ const node = results[0];
2843
+ const children = results[1];
2844
+ const skeleton = results[2];
2817
2845
 
2818
- if (meshPromise) {
2819
- pending.push(meshPromise);
2846
+ if (skeleton !== null) {
2847
+ // This full traverse should be fine because
2848
+ // child glTF nodes have not been added to this node yet.
2849
+ node.traverse(function (mesh) {
2850
+ if (!mesh.isSkinnedMesh) return;
2851
+ mesh.bind(skeleton, _identityMatrix);
2852
+ });
2820
2853
  }
2821
2854
 
2822
- if (nodeDef.camera !== undefined) {
2823
- pending.push(parser.getDependency('camera', nodeDef.camera).then(function (camera) {
2824
- return parser._getNodeRef(parser.cameraCache, nodeDef.camera, camera);
2825
- }));
2855
+ for (let i = 0, il = children.length; i < il; i++) {
2856
+ node.add(children[i]);
2826
2857
  }
2827
2858
 
2828
- parser._invokeAll(function (ext) {
2829
- return ext.createNodeAttachment && ext.createNodeAttachment(nodeIndex);
2830
- }).forEach(function (promise) {
2831
- pending.push(promise);
2832
- });
2859
+ return node;
2860
+ });
2861
+ } // ._loadNodeShallow() parses a single node.
2862
+ // skin and child nodes are created and added in .loadNode() (no '_' prefix).
2863
+
2864
+
2865
+ _loadNodeShallow(nodeIndex) {
2866
+ const json = this.json;
2867
+ const extensions = this.extensions;
2868
+ const parser = this; // This method is called from .loadNode() and .loadSkin().
2869
+ // Cache a node to avoid duplication.
2870
+
2871
+ if (this.nodeCache[nodeIndex] !== undefined) {
2872
+ return this.nodeCache[nodeIndex];
2873
+ }
2874
+
2875
+ const nodeDef = json.nodes[nodeIndex]; // reserve node's name before its dependencies, so the root has the intended name.
2876
+
2877
+ const nodeName = nodeDef.name ? parser.createUniqueName(nodeDef.name) : '';
2878
+ const pending = [];
2879
+
2880
+ const meshPromise = parser._invokeOne(function (ext) {
2881
+ return ext.createNodeMesh && ext.createNodeMesh(nodeIndex);
2882
+ });
2883
+
2884
+ if (meshPromise) {
2885
+ pending.push(meshPromise);
2886
+ }
2887
+
2888
+ if (nodeDef.camera !== undefined) {
2889
+ pending.push(parser.getDependency('camera', nodeDef.camera).then(function (camera) {
2890
+ return parser._getNodeRef(parser.cameraCache, nodeDef.camera, camera);
2891
+ }));
2892
+ }
2833
2893
 
2834
- return Promise.all(pending);
2835
- }().then(function (objects) {
2894
+ parser._invokeAll(function (ext) {
2895
+ return ext.createNodeAttachment && ext.createNodeAttachment(nodeIndex);
2896
+ }).forEach(function (promise) {
2897
+ pending.push(promise);
2898
+ });
2899
+
2900
+ this.nodeCache[nodeIndex] = Promise.all(pending).then(function (objects) {
2836
2901
  let node; // .isBone isn't in glTF spec. See ._markDefs
2837
2902
 
2838
2903
  if (nodeDef.isBone === true) {
@@ -2884,6 +2949,7 @@ class GLTFParser {
2884
2949
  parser.associations.get(node).nodes = nodeIndex;
2885
2950
  return node;
2886
2951
  });
2952
+ return this.nodeCache[nodeIndex];
2887
2953
  }
2888
2954
  /**
2889
2955
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes
@@ -2893,7 +2959,6 @@ class GLTFParser {
2893
2959
 
2894
2960
 
2895
2961
  loadScene(sceneIndex) {
2896
- const json = this.json;
2897
2962
  const extensions = this.extensions;
2898
2963
  const sceneDef = this.json.scenes[sceneIndex];
2899
2964
  const parser = this; // Loader returns Group, not Scene.
@@ -2907,12 +2972,16 @@ class GLTFParser {
2907
2972
  const pending = [];
2908
2973
 
2909
2974
  for (let i = 0, il = nodeIds.length; i < il; i++) {
2910
- pending.push(buildNodeHierarchy(nodeIds[i], scene, json, parser));
2975
+ pending.push(parser.getDependency('node', nodeIds[i]));
2911
2976
  }
2912
2977
 
2913
- return Promise.all(pending).then(function () {
2914
- // Removes dangling associations, associations that reference a node that
2978
+ return Promise.all(pending).then(function (nodes) {
2979
+ for (let i = 0, il = nodes.length; i < il; i++) {
2980
+ scene.add(nodes[i]);
2981
+ } // Removes dangling associations, associations that reference a node that
2915
2982
  // didn't make it into the scene.
2983
+
2984
+
2916
2985
  const reduceAssociations = node => {
2917
2986
  const reducedAssociations = new Map();
2918
2987
 
@@ -2938,66 +3007,6 @@ class GLTFParser {
2938
3007
  }
2939
3008
 
2940
3009
  }
2941
-
2942
- function buildNodeHierarchy(nodeId, parentObject, json, parser) {
2943
- const nodeDef = json.nodes[nodeId];
2944
- return parser.getDependency('node', nodeId).then(function (node) {
2945
- if (nodeDef.skin === undefined) return node; // build skeleton here as well
2946
-
2947
- let skinEntry;
2948
- return parser.getDependency('skin', nodeDef.skin).then(function (skin) {
2949
- skinEntry = skin;
2950
- const pendingJoints = [];
2951
-
2952
- for (let i = 0, il = skinEntry.joints.length; i < il; i++) {
2953
- pendingJoints.push(parser.getDependency('node', skinEntry.joints[i]));
2954
- }
2955
-
2956
- return Promise.all(pendingJoints);
2957
- }).then(function (jointNodes) {
2958
- node.traverse(function (mesh) {
2959
- if (!mesh.isMesh) return;
2960
- const bones = [];
2961
- const boneInverses = [];
2962
-
2963
- for (let j = 0, jl = jointNodes.length; j < jl; j++) {
2964
- const jointNode = jointNodes[j];
2965
-
2966
- if (jointNode) {
2967
- bones.push(jointNode);
2968
- const mat = new Matrix4();
2969
-
2970
- if (skinEntry.inverseBindMatrices !== undefined) {
2971
- mat.fromArray(skinEntry.inverseBindMatrices.array, j * 16);
2972
- }
2973
-
2974
- boneInverses.push(mat);
2975
- } else {
2976
- console.warn('THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[j]);
2977
- }
2978
- }
2979
-
2980
- mesh.bind(new Skeleton(bones, boneInverses), mesh.matrixWorld);
2981
- });
2982
- return node;
2983
- });
2984
- }).then(function (node) {
2985
- // build node hierachy
2986
- parentObject.add(node);
2987
- const pending = [];
2988
-
2989
- if (nodeDef.children) {
2990
- const children = nodeDef.children;
2991
-
2992
- for (let i = 0, il = children.length; i < il; i++) {
2993
- const child = children[i];
2994
- pending.push(buildNodeHierarchy(child, node, json, parser));
2995
- }
2996
- }
2997
-
2998
- return Promise.all(pending);
2999
- });
3000
- }
3001
3010
  /**
3002
3011
  * @param {BufferGeometry} geometry
3003
3012
  * @param {GLTF.Primitive} primitiveDef
@@ -3114,67 +3123,5 @@ function addPrimitiveAttributes(geometry, primitiveDef, parser) {
3114
3123
  return primitiveDef.targets !== undefined ? addMorphTargets(geometry, primitiveDef.targets, parser) : geometry;
3115
3124
  });
3116
3125
  }
3117
- /**
3118
- * @param {BufferGeometry} geometry
3119
- * @param {Number} drawMode
3120
- * @return {BufferGeometry}
3121
- */
3122
-
3123
-
3124
- function toTrianglesDrawMode(geometry, drawMode) {
3125
- let index = geometry.getIndex(); // generate index if not present
3126
-
3127
- if (index === null) {
3128
- const indices = [];
3129
- const position = geometry.getAttribute('position');
3130
-
3131
- if (position !== undefined) {
3132
- for (let i = 0; i < position.count; i++) {
3133
- indices.push(i);
3134
- }
3135
-
3136
- geometry.setIndex(indices);
3137
- index = geometry.getIndex();
3138
- } else {
3139
- console.error('THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.');
3140
- return geometry;
3141
- }
3142
- } //
3143
-
3144
-
3145
- const numberOfTriangles = index.count - 2;
3146
- const newIndices = [];
3147
-
3148
- if (drawMode === TriangleFanDrawMode) {
3149
- // gl.TRIANGLE_FAN
3150
- for (let i = 1; i <= numberOfTriangles; i++) {
3151
- newIndices.push(index.getX(0));
3152
- newIndices.push(index.getX(i));
3153
- newIndices.push(index.getX(i + 1));
3154
- }
3155
- } else {
3156
- // gl.TRIANGLE_STRIP
3157
- for (let i = 0; i < numberOfTriangles; i++) {
3158
- if (i % 2 === 0) {
3159
- newIndices.push(index.getX(i));
3160
- newIndices.push(index.getX(i + 1));
3161
- newIndices.push(index.getX(i + 2));
3162
- } else {
3163
- newIndices.push(index.getX(i + 2));
3164
- newIndices.push(index.getX(i + 1));
3165
- newIndices.push(index.getX(i));
3166
- }
3167
- }
3168
- }
3169
-
3170
- if (newIndices.length / 3 !== numberOfTriangles) {
3171
- console.error('THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.');
3172
- } // build final geometry
3173
-
3174
-
3175
- const newGeometry = geometry.clone();
3176
- newGeometry.setIndex(newIndices);
3177
- return newGeometry;
3178
- }
3179
3126
 
3180
3127
  export { GLTFLoader };