three-stdlib 2.21.9 → 2.21.10

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.
@@ -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 };