From 876fe225debd5aad7d52724db199cdbbad1da7d9 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Wed, 11 Dec 2019 19:53:29 -0800 Subject: [PATCH] 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. --- examples/js/loaders/GLTFLoader.js | 113 +++++++++++++++-------------- examples/jsm/loaders/GLTFLoader.js | 113 +++++++++++++++-------------- 2 files changed, 114 insertions(+), 112 deletions(-) diff --git a/examples/js/loaders/GLTFLoader.js b/examples/js/loaders/GLTFLoader.js index 256787a436..416b9a6d33 100644 --- a/examples/js/loaders/GLTFLoader.js +++ b/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; } ); diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index d2a125b2e4..2535ea6099 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/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; } ); -- GitLab