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.
- package/index.cjs.js +1 -1
- package/loaders/GLTFLoader.cjs.js +1 -1
- package/loaders/GLTFLoader.js +360 -413
- package/loaders/VRMLoader.cjs.js +1 -1
- package/package.json +1 -1
- package/webxr/OculusHandModel.cjs.js +1 -1
- package/webxr/XRControllerModelFactory.cjs.js +1 -1
- package/webxr/XRHandMeshModel.cjs.js +1 -1
- package/webxr/XRHandModelFactory.cjs.js +1 -1
package/loaders/GLTFLoader.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
import { Loader, LoaderUtils, FileLoader, Color, SpotLight, PointLight, DirectionalLight, MeshBasicMaterial, sRGBEncoding, MeshPhysicalMaterial, Vector2,
|
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
|
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
|
-
|
135
|
-
} else {
|
136
|
-
const magic =
|
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
|
-
|
154
|
+
json = JSON.parse(extensions[EXTENSIONS.KHR_BINARY_GLTF].content);
|
147
155
|
} else {
|
148
|
-
|
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
|
-
|
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:
|
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 =
|
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
|
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 = {}; //
|
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
|
-
|
1690
|
-
|
1691
|
-
|
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();
|
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.
|
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
|
-
|
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
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
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
|
-
|
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
|
-
|
2221
|
-
|
2222
|
-
if (mapDef.texCoord !== undefined && mapDef.texCoord
|
2223
|
-
|
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.
|
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
|
-
|
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
|
2554
|
-
//
|
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<
|
2634
|
+
* @return {Promise<Skeleton>}
|
2641
2635
|
*/
|
2642
2636
|
|
2643
2637
|
|
2644
2638
|
loadSkin(skinIndex) {
|
2645
2639
|
const skinDef = this.json.skins[skinIndex];
|
2646
|
-
const
|
2647
|
-
|
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
|
2651
|
-
|
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
|
2655
|
-
|
2656
|
-
|
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
|
-
|
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];
|
2829
|
+
const nodeDef = json.nodes[nodeIndex];
|
2809
2830
|
|
2810
|
-
const
|
2811
|
-
return function () {
|
2812
|
-
const pending = [];
|
2831
|
+
const nodePending = parser._loadNodeShallow(nodeIndex);
|
2813
2832
|
|
2814
|
-
|
2815
|
-
|
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 (
|
2819
|
-
|
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
|
-
|
2823
|
-
|
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
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
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
|
-
|
2835
|
-
|
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(
|
2975
|
+
pending.push(parser.getDependency('node', nodeIds[i]));
|
2911
2976
|
}
|
2912
2977
|
|
2913
|
-
return Promise.all(pending).then(function () {
|
2914
|
-
|
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 };
|