three-stdlib 2.21.9 → 2.21.10
Sign up to get free protection for your applications and to get access to all the features.
- 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 };
|