Browse Source

GLTFLoader: Load materials and geometries in parallel

Instead of waiting for all materials of a mesh before fetching geometry
data, we now push all promises into one large array and wait on all of
this at once.

This means we can load .bin file in parallel with texture data when
texture assets are using separate files, and potentially start decoding
geometry earlier.
Arseny Kapoulkine 5 years ago
parent
commit
876fe225de
2 changed files with 114 additions and 112 deletions
  1. 57 56
      examples/js/loaders/GLTFLoader.js
  2. 57 56
      examples/jsm/loaders/GLTFLoader.js

+ 57 - 56
examples/js/loaders/GLTFLoader.js

@@ -2591,108 +2591,109 @@ THREE.GLTFLoader = ( function () {
 
 		}
 
-		return Promise.all( pending ).then( function ( originalMaterials ) {
+		pending.push( parser.loadGeometries( primitives ) );
 
-			return parser.loadGeometries( primitives ).then( function ( geometries ) {
+		return Promise.all( pending ).then( function ( results ) {
 
-				var meshes = [];
+			var materials = results.slice( 0, results.length - 1 );
+			var geometries = results[ results.length - 1 ];
 
-				for ( var i = 0, il = geometries.length; i < il; i ++ ) {
+			var meshes = [];
 
-					var geometry = geometries[ i ];
-					var primitive = primitives[ i ];
+			for ( var i = 0, il = geometries.length; i < il; i ++ ) {
 
-					// 1. create Mesh
+				var geometry = geometries[ i ];
+				var primitive = primitives[ i ];
 
-					var mesh;
+				// 1. create Mesh
 
-					var material = originalMaterials[ i ];
+				var mesh;
 
-					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
-						primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
-						primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
-						primitive.mode === undefined ) {
+				var material = materials[ i ];
 
-						// .isSkinnedMesh isn't in glTF spec. See .markDefs()
-						mesh = meshDef.isSkinnedMesh === true
-							? new THREE.SkinnedMesh( geometry, material )
-							: new THREE.Mesh( geometry, material );
+				if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
+					primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
+					primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
+					primitive.mode === undefined ) {
 
-						if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
+					// .isSkinnedMesh isn't in glTF spec. See .markDefs()
+					mesh = meshDef.isSkinnedMesh === true
+						? new THREE.SkinnedMesh( geometry, material )
+						: new THREE.Mesh( geometry, material );
 
-							// we normalize floating point skin weight array to fix malformed assets (see #15319)
-							// it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
-							mesh.normalizeSkinWeights();
+					if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
 
-						}
+						// we normalize floating point skin weight array to fix malformed assets (see #15319)
+						// it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
+						mesh.normalizeSkinWeights();
 
-						if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
+					}
 
-							mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleStripDrawMode );
+					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
 
-						} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
+						mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleStripDrawMode );
 
-							mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleFanDrawMode );
+					} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
 
-						}
+						mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleFanDrawMode );
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
+					}
 
-						mesh = new THREE.LineSegments( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
+					mesh = new THREE.LineSegments( geometry, material );
 
-						mesh = new THREE.Line( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
+					mesh = new THREE.Line( geometry, material );
 
-						mesh = new THREE.LineLoop( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
+					mesh = new THREE.LineLoop( geometry, material );
 
-						mesh = new THREE.Points( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
 
-					} else {
+					mesh = new THREE.Points( geometry, material );
 
-						throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
+				} else {
 
-					}
+					throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
 
-					if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
+				}
 
-						updateMorphTargets( mesh, meshDef );
+				if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
 
-					}
+					updateMorphTargets( mesh, meshDef );
 
-					mesh.name = meshDef.name || ( 'mesh_' + meshIndex );
+				}
 
-					if ( geometries.length > 1 ) mesh.name += '_' + i;
+				mesh.name = meshDef.name || ( 'mesh_' + meshIndex );
 
-					assignExtrasToUserData( mesh, meshDef );
+				if ( geometries.length > 1 ) mesh.name += '_' + i;
 
-					parser.assignFinalMaterial( mesh );
+				assignExtrasToUserData( mesh, meshDef );
 
-					meshes.push( mesh );
+				parser.assignFinalMaterial( mesh );
 
-				}
+				meshes.push( mesh );
 
-				if ( meshes.length === 1 ) {
+			}
 
-					return meshes[ 0 ];
+			if ( meshes.length === 1 ) {
 
-				}
+				return meshes[ 0 ];
 
-				var group = new THREE.Group();
+			}
 
-				for ( var i = 0, il = meshes.length; i < il; i ++ ) {
+			var group = new THREE.Group();
 
-					group.add( meshes[ i ] );
+			for ( var i = 0, il = meshes.length; i < il; i ++ ) {
 
-				}
+				group.add( meshes[ i ] );
 
-				return group;
+			}
 
-			} );
+			return group;
 
 		} );
 

+ 57 - 56
examples/jsm/loaders/GLTFLoader.js

@@ -2658,108 +2658,109 @@ var GLTFLoader = ( function () {
 
 		}
 
-		return Promise.all( pending ).then( function ( originalMaterials ) {
+		pending.push( parser.loadGeometries( primitives ) );
 
-			return parser.loadGeometries( primitives ).then( function ( geometries ) {
+		return Promise.all( pending ).then( function ( results ) {
 
-				var meshes = [];
+			var materials = results.slice( 0, results.length - 1 );
+			var geometries = results[ results.length - 1 ];
 
-				for ( var i = 0, il = geometries.length; i < il; i ++ ) {
+			var meshes = [];
 
-					var geometry = geometries[ i ];
-					var primitive = primitives[ i ];
+			for ( var i = 0, il = geometries.length; i < il; i ++ ) {
 
-					// 1. create Mesh
+				var geometry = geometries[ i ];
+				var primitive = primitives[ i ];
 
-					var mesh;
+				// 1. create Mesh
 
-					var material = originalMaterials[ i ];
+				var mesh;
 
-					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
-						primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
-						primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
-						primitive.mode === undefined ) {
+				var material = materials[ i ];
 
-						// .isSkinnedMesh isn't in glTF spec. See .markDefs()
-						mesh = meshDef.isSkinnedMesh === true
-							? new SkinnedMesh( geometry, material )
-							: new Mesh( geometry, material );
+				if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
+					primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
+					primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
+					primitive.mode === undefined ) {
 
-						if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
+					// .isSkinnedMesh isn't in glTF spec. See .markDefs()
+					mesh = meshDef.isSkinnedMesh === true
+						? new SkinnedMesh( geometry, material )
+						: new Mesh( geometry, material );
 
-							// we normalize floating point skin weight array to fix malformed assets (see #15319)
-							// it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
-							mesh.normalizeSkinWeights();
+					if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
 
-						}
+						// we normalize floating point skin weight array to fix malformed assets (see #15319)
+						// it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
+						mesh.normalizeSkinWeights();
 
-						if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
+					}
 
-							mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleStripDrawMode );
+					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
 
-						} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
+						mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleStripDrawMode );
 
-							mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleFanDrawMode );
+					} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
 
-						}
+						mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleFanDrawMode );
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
+					}
 
-						mesh = new LineSegments( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
+					mesh = new LineSegments( geometry, material );
 
-						mesh = new Line( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
+					mesh = new Line( geometry, material );
 
-						mesh = new LineLoop( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
 
-					} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
+					mesh = new LineLoop( geometry, material );
 
-						mesh = new Points( geometry, material );
+				} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
 
-					} else {
+					mesh = new Points( geometry, material );
 
-						throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
+				} else {
 
-					}
+					throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
 
-					if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
+				}
 
-						updateMorphTargets( mesh, meshDef );
+				if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
 
-					}
+					updateMorphTargets( mesh, meshDef );
 
-					mesh.name = meshDef.name || ( 'mesh_' + meshIndex );
+				}
 
-					if ( geometries.length > 1 ) mesh.name += '_' + i;
+				mesh.name = meshDef.name || ( 'mesh_' + meshIndex );
 
-					assignExtrasToUserData( mesh, meshDef );
+				if ( geometries.length > 1 ) mesh.name += '_' + i;
 
-					parser.assignFinalMaterial( mesh );
+				assignExtrasToUserData( mesh, meshDef );
 
-					meshes.push( mesh );
+				parser.assignFinalMaterial( mesh );
 
-				}
+				meshes.push( mesh );
 
-				if ( meshes.length === 1 ) {
+			}
 
-					return meshes[ 0 ];
+			if ( meshes.length === 1 ) {
 
-				}
+				return meshes[ 0 ];
 
-				var group = new Group();
+			}
 
-				for ( var i = 0, il = meshes.length; i < il; i ++ ) {
+			var group = new Group();
 
-					group.add( meshes[ i ] );
+			for ( var i = 0, il = meshes.length; i < il; i ++ ) {
 
-				}
+				group.add( meshes[ i ] );
 
-				return group;
+			}
 
-			} );
+			return group;
 
 		} );