From 2a29bd2b5450637b1c22ffdf0279774d9b32bbb9 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Thu, 14 Mar 2019 19:01:52 -0700 Subject: [PATCH] Updated generated jsm files. --- examples/jsm/controls/OrbitControls.js | 29 +- examples/jsm/controls/TrackballControls.js | 2 +- examples/jsm/loaders/GLTFLoader.js | 667 +++++++-------------- 3 files changed, 247 insertions(+), 451 deletions(-) diff --git a/examples/jsm/controls/OrbitControls.js b/examples/jsm/controls/OrbitControls.js index 708006af1b..8a8aa21453 100644 --- a/examples/jsm/controls/OrbitControls.js +++ b/examples/jsm/controls/OrbitControls.js @@ -546,32 +546,44 @@ var OrbitControls = function ( object, domElement ) { function handleKeyDown( event ) { - //console.log( 'handleKeyDown' ); + // console.log( 'handleKeyDown' ); + + var needsUpdate = false; switch ( event.keyCode ) { case scope.keys.UP: pan( 0, scope.keyPanSpeed ); - scope.update(); + needsUpdate = true; break; case scope.keys.BOTTOM: pan( 0, - scope.keyPanSpeed ); - scope.update(); + needsUpdate = true; break; case scope.keys.LEFT: pan( scope.keyPanSpeed, 0 ); - scope.update(); + needsUpdate = true; break; case scope.keys.RIGHT: pan( - scope.keyPanSpeed, 0 ); - scope.update(); + needsUpdate = true; break; } + if ( needsUpdate ) { + + // prevent the browser from scrolling on cursor keys + event.preventDefault(); + + scope.update(); + + } + + } function handleTouchStartRotate( event ) { @@ -682,8 +694,15 @@ var OrbitControls = function ( object, domElement ) { if ( scope.enabled === false ) return; + // Prevent the browser from scrolling. + event.preventDefault(); + // Manually set the focus since calling preventDefault above + // prevents the browser from setting it automatically. + + scope.domElement.focus ? scope.domElement.focus() : window.focus(); + switch ( event.button ) { case scope.mouseButtons.LEFT: diff --git a/examples/jsm/controls/TrackballControls.js b/examples/jsm/controls/TrackballControls.js index c3858044bc..5a27ada004 100644 --- a/examples/jsm/controls/TrackballControls.js +++ b/examples/jsm/controls/TrackballControls.js @@ -499,7 +499,7 @@ var TrackballControls = function ( object, domElement ) { function touchstart( event ) { if ( _this.enabled === false ) return; - + event.preventDefault(); switch ( event.touches.length ) { diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index 8f37ff6058..213563a5da 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -10,12 +10,10 @@ import { AddEquation, AlwaysDepth, AnimationClip, - AnimationUtils, BackSide, Bone, BufferAttribute, BufferGeometry, - BufferGeometryUtils, Camera, ClampToEdgeWrapping, Color, @@ -34,7 +32,6 @@ import { Interpolant, InterpolateDiscrete, InterpolateLinear, - InterpolateSmooth, LessDepth, LessEqualDepth, Line, @@ -284,7 +281,7 @@ var GLTFLoader = ( function () { break; case EXTENSIONS.MSFT_TEXTURE_DDS: - extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension( json ); + extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension(); break; case EXTENSIONS.KHR_TEXTURE_TRANSFORM: @@ -313,23 +310,7 @@ var GLTFLoader = ( function () { } ); - parser.parse( function ( scene, scenes, cameras, animations, json ) { - - var glTF = { - scene: scene, - scenes: scenes, - cameras: cameras, - animations: animations, - asset: json.asset, - parser: parser, - userData: {} - }; - - addUnknownExtensionsToUserData( extensions, glTF, json ); - - onLoad( glTF ); - - }, onError ); + parser.parse( onLoad, onError ); } @@ -460,6 +441,10 @@ var GLTFLoader = ( function () { } + // Some lights (e.g. spot) default to a position other than the origin. Reset the position + // here, because node-level parsing will only override position if explicitly specified. + lightNode.position.set( 0, 0, 0 ); + lightNode.decay = 2; if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity; @@ -603,7 +588,6 @@ var GLTFLoader = ( function () { this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION; this.json = json; this.dracoLoader = dracoLoader; - THREE.DRACOLoader.getDecoderModule(); } @@ -619,21 +603,23 @@ var GLTFLoader = ( function () { for ( var attributeName in gltfAttributeMap ) { - if ( ! ( attributeName in ATTRIBUTES ) ) continue; + var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase(); - threeAttributeMap[ ATTRIBUTES[ attributeName ] ] = gltfAttributeMap[ attributeName ]; + threeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ]; } for ( attributeName in primitive.attributes ) { - if ( ATTRIBUTES[ attributeName ] !== undefined && gltfAttributeMap[ attributeName ] !== undefined ) { + var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase(); + + if ( gltfAttributeMap[ attributeName ] !== undefined ) { var accessorDef = json.accessors[ primitive.attributes[ attributeName ] ]; var componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ]; - attributeTypeMap[ ATTRIBUTES[ attributeName ] ] = componentType; - attributeNormalizedMap[ ATTRIBUTES[ attributeName ] ] = accessorDef.normalized === true; + attributeTypeMap[ threeAttributeName ] = componentType; + attributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true; } @@ -1293,6 +1279,7 @@ var GLTFLoader = ( function () { var ATTRIBUTES = { POSITION: 'position', NORMAL: 'normal', + TANGENT: 'tangent', TEXCOORD_0: 'uv', TEXCOORD_1: 'uv2', COLOR_0: 'color', @@ -1308,10 +1295,8 @@ var GLTFLoader = ( function () { }; var INTERPOLATION = { - CUBICSPLINE: InterpolateSmooth, // We use custom interpolation GLTFCubicSplineInterpolation for CUBICSPLINE. - // KeyframeTrack.optimize() can't handle glTF Cubic Spline output values layout, - // using InterpolateSmooth for KeyframeTrack instantiation to prevent optimization. - // See KeyframeTrack.optimize() for the detail. + CUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each + // keyframe track will be initialized with a default interpolation type, then modified. LINEAR: InterpolateLinear, STEP: InterpolateDiscrete }; @@ -1357,12 +1342,14 @@ var GLTFLoader = ( function () { } + var defaultMaterial; + /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material */ function createDefaultMaterial() { - return new MeshStandardMaterial( { + defaultMaterial = defaultMaterial || new MeshStandardMaterial( { color: 0xFFFFFF, emissive: 0x000000, metalness: 1, @@ -1372,6 +1359,8 @@ var GLTFLoader = ( function () { side: FrontSide } ); + return defaultMaterial; + } function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) { @@ -1448,34 +1437,21 @@ var GLTFLoader = ( function () { if ( hasMorphPosition ) { - // TODO: Error-prone use of a callback inside a loop. - var accessor = target.POSITION !== undefined + var pendingAccessor = target.POSITION !== undefined ? parser.getDependency( 'accessor', target.POSITION ) - .then( function ( accessor ) { - - // Cloning not to pollute original accessor below - return cloneBufferAttribute( accessor ); - - } ) : geometry.attributes.position; - pendingPositionAccessors.push( accessor ); + pendingPositionAccessors.push( pendingAccessor ); } if ( hasMorphNormal ) { - // TODO: Error-prone use of a callback inside a loop. - var accessor = target.NORMAL !== undefined + var pendingAccessor = target.NORMAL !== undefined ? parser.getDependency( 'accessor', target.NORMAL ) - .then( function ( accessor ) { - - return cloneBufferAttribute( accessor ); - - } ) : geometry.attributes.normal; - pendingNormalAccessors.push( accessor ); + pendingNormalAccessors.push( pendingAccessor ); } @@ -1489,6 +1465,24 @@ var GLTFLoader = ( function () { var morphPositions = accessors[ 0 ]; var morphNormals = accessors[ 1 ]; + // Clone morph target accessors before modifying them. + + for ( var i = 0, il = morphPositions.length; i < il; i ++ ) { + + if ( geometry.attributes.position === morphPositions[ i ] ) continue; + + morphPositions[ i ] = cloneBufferAttribute( morphPositions[ i ] ); + + } + + for ( var i = 0, il = morphNormals.length; i < il; i ++ ) { + + if ( geometry.attributes.normal === morphNormals[ i ] ) continue; + + morphNormals[ i ] = cloneBufferAttribute( morphNormals[ i ] ); + + } + for ( var i = 0, il = targets.length; i < il; i ++ ) { var target = targets[ i ]; @@ -1609,30 +1603,6 @@ var GLTFLoader = ( function () { } } - - function isPrimitiveEqual( a, b ) { - - var dracoExtA = a.extensions ? a.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] : undefined; - var dracoExtB = b.extensions ? b.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] : undefined; - - if ( dracoExtA && dracoExtB ) { - - if ( dracoExtA.bufferView !== dracoExtB.bufferView ) return false; - - return isObjectEqual( dracoExtA.attributes, dracoExtB.attributes ); - - } - - if ( a.indices !== b.indices ) { - - return false; - - } - - return isObjectEqual( a.attributes, b.attributes ); - - } - function isObjectEqual( a, b ) { if ( Object.keys( a ).length !== Object.keys( b ).length ) return false; @@ -1647,59 +1617,40 @@ var GLTFLoader = ( function () { } - function isArrayEqual( a, b ) { + function createPrimitiveKey( primitiveDef ) { - if ( a.length !== b.length ) return false; + var dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]; + var geometryKey; - for ( var i = 0, il = a.length; i < il; i ++ ) { + if ( dracoExtension ) { - if ( a[ i ] !== b[ i ] ) return false; - - } - - return true; - - } + geometryKey = 'draco:' + dracoExtension.bufferView + + ':' + dracoExtension.indices + + ':' + createAttributesKey( dracoExtension.attributes ); - function getCachedGeometry( cache, newPrimitive ) { - - for ( var i = 0, il = cache.length; i < il; i ++ ) { - - var cached = cache[ i ]; + } else { - if ( isPrimitiveEqual( cached.primitive, newPrimitive ) ) return cached.promise; + geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode; } - return null; + return geometryKey; } - function getCachedCombinedGeometry( cache, geometries ) { - - for ( var i = 0, il = cache.length; i < il; i ++ ) { - - var cached = cache[ i ]; - - if ( isArrayEqual( geometries, cached.baseGeometries ) ) return cached.geometry; - - } - - return null; - - } + function createAttributesKey( attributes ) { - function getCachedMultiPassGeometry( cache, geometry, primitives ) { + var attributesKey = ''; - for ( var i = 0, il = cache.length; i < il; i ++ ) { + var keys = Object.keys( attributes ).sort(); - var cached = cache[ i ]; + for ( var i = 0, il = keys.length; i < il; i ++ ) { - if ( geometry === cached.baseGeometry && isArrayEqual( primitives, cached.primitives ) ) return cached.geometry; + attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';'; } - return null; + return attributesKey; } @@ -1728,48 +1679,6 @@ var GLTFLoader = ( function () { } - /** - * Checks if we can build a single Mesh with MultiMaterial from multiple primitives. - * Returns true if all primitives use the same attributes/morphAttributes/mode - * and also have index. Otherwise returns false. - * - * @param {Array} primitives - * @return {Boolean} - */ - function isMultiPassGeometry( primitives ) { - - if ( primitives.length < 2 ) return false; - - var primitive0 = primitives[ 0 ]; - var targets0 = primitive0.targets || []; - - if ( primitive0.indices === undefined ) return false; - - for ( var i = 1, il = primitives.length; i < il; i ++ ) { - - var primitive = primitives[ i ]; - - if ( primitive0.mode !== primitive.mode ) return false; - if ( primitive.indices === undefined ) return false; - if ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) return false; - if ( ! isObjectEqual( primitive0.attributes, primitive.attributes ) ) return false; - - var targets = primitive.targets || []; - - if ( targets0.length !== targets.length ) return false; - - for ( var j = 0, jl = targets0.length; j < jl; j ++ ) { - - if ( ! isObjectEqual( targets0[ j ], targets[ j ] ) ) return false; - - } - - } - - return true; - - } - /* GLTF PARSER */ function GLTFParser( json, extensions, options ) { @@ -1782,9 +1691,7 @@ var GLTFLoader = ( function () { this.cache = new GLTFRegistry(); // BufferGeometry caching - this.primitiveCache = []; - this.multiplePrimitivesCache = []; - this.multiPassGeometryCache = []; + this.primitiveCache = {}; this.textureLoader = new TextureLoader( this.options.manager ); this.textureLoader.setCrossOrigin( this.options.crossOrigin ); @@ -1796,7 +1703,9 @@ var GLTFLoader = ( function () { GLTFParser.prototype.parse = function ( onLoad, onError ) { + var parser = this; var json = this.json; + var extensions = this.extensions; // Clear the loader cache this.cache.removeAll(); @@ -1804,21 +1713,27 @@ var GLTFLoader = ( function () { // Mark the special nodes/meshes in json for efficient parse this.markDefs(); - // Fire the callback on complete - this.getMultiDependencies( [ + Promise.all( [ - 'scene', - 'animation', - 'camera' + this.getDependencies( 'scene' ), + this.getDependencies( 'animation' ), + this.getDependencies( 'camera' ), ] ).then( function ( dependencies ) { - var scenes = dependencies.scenes || []; - var scene = scenes[ json.scene || 0 ]; - var animations = dependencies.animations || []; - var cameras = dependencies.cameras || []; + var result = { + scene: dependencies[ 0 ][ json.scene || 0 ], + scenes: dependencies[ 0 ], + animations: dependencies[ 1 ], + cameras: dependencies[ 2 ], + asset: json.asset, + parser: parser, + userData: {} + }; + + addUnknownExtensionsToUserData( extensions, result, json ); - onLoad( scene, scenes, cameras, animations, json ); + onLoad( result ); } ).catch( onError ); @@ -1991,40 +1906,6 @@ var GLTFLoader = ( function () { }; - /** - * Requests all multiple dependencies of the specified types asynchronously, with caching. - * @param {Array} types - * @return {Promise>>} - */ - GLTFParser.prototype.getMultiDependencies = function ( types ) { - - var results = {}; - var pending = []; - - for ( var i = 0, il = types.length; i < il; i ++ ) { - - var type = types[ i ]; - var value = this.getDependencies( type ); - - // TODO: Error-prone use of a callback inside a loop. - value = value.then( function ( key, value ) { - - results[ key ] = value; - - }.bind( this, type + ( type === 'mesh' ? 'es' : 's' ) ) ); - - pending.push( value ); - - } - - return Promise.all( pending ).then( function () { - - return results; - - } ); - - }; - /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views * @param {number} bufferIndex @@ -2327,6 +2208,18 @@ var GLTFLoader = ( function () { return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) { + switch ( mapName ) { + + case 'aoMap': + case 'emissiveMap': + case 'metalnessMap': + case 'normalMap': + case 'roughnessMap': + texture.format = RGBFormat; + break; + + } + if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) { var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined; @@ -2345,6 +2238,124 @@ var GLTFLoader = ( function () { }; + /** + * Assigns final material to a Mesh, Line, or Points instance. The instance + * already has a material (generated from the glTF material options alone) + * but reuse of the same glTF material may require multiple threejs materials + * to accomodate different primitive types, defines, etc. New materials will + * be created if necessary, and reused from a cache. + * @param {Object3D} mesh Mesh, Line, or Points instance. + */ + GLTFParser.prototype.assignFinalMaterial = function ( mesh ) { + + var geometry = mesh.geometry; + var material = mesh.material; + var extensions = this.extensions; + + var useVertexTangents = geometry.attributes.tangent !== undefined; + var useVertexColors = geometry.attributes.color !== undefined; + var useFlatShading = geometry.attributes.normal === undefined; + var useSkinning = mesh.isSkinnedMesh === true; + var useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0; + var useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined; + + if ( mesh.isPoints ) { + + var cacheKey = 'PointsMaterial:' + material.uuid; + + var pointsMaterial = this.cache.get( cacheKey ); + + if ( ! pointsMaterial ) { + + pointsMaterial = new PointsMaterial(); + Material.prototype.copy.call( pointsMaterial, material ); + pointsMaterial.color.copy( material.color ); + pointsMaterial.map = material.map; + pointsMaterial.lights = false; // PointsMaterial doesn't support lights yet + + this.cache.add( cacheKey, pointsMaterial ); + + } + + material = pointsMaterial; + + } else if ( mesh.isLine ) { + + var cacheKey = 'LineBasicMaterial:' + material.uuid; + + var lineMaterial = this.cache.get( cacheKey ); + + if ( ! lineMaterial ) { + + lineMaterial = new LineBasicMaterial(); + Material.prototype.copy.call( lineMaterial, material ); + lineMaterial.color.copy( material.color ); + lineMaterial.lights = false; // LineBasicMaterial doesn't support lights yet + + this.cache.add( cacheKey, lineMaterial ); + + } + + material = lineMaterial; + + } + + // Clone the material if it will be modified + if ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) { + + var cacheKey = 'ClonedMaterial:' + material.uuid + ':'; + + if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:'; + if ( useSkinning ) cacheKey += 'skinning:'; + if ( useVertexTangents ) cacheKey += 'vertex-tangents:'; + if ( useVertexColors ) cacheKey += 'vertex-colors:'; + if ( useFlatShading ) cacheKey += 'flat-shading:'; + if ( useMorphTargets ) cacheKey += 'morph-targets:'; + if ( useMorphNormals ) cacheKey += 'morph-normals:'; + + var cachedMaterial = this.cache.get( cacheKey ); + + if ( ! cachedMaterial ) { + + cachedMaterial = material.isGLTFSpecularGlossinessMaterial + ? extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].cloneMaterial( material ) + : material.clone(); + + if ( useSkinning ) cachedMaterial.skinning = true; + if ( useVertexTangents ) cachedMaterial.vertexTangents = true; + if ( useVertexColors ) cachedMaterial.vertexColors = VertexColors; + if ( useFlatShading ) cachedMaterial.flatShading = true; + if ( useMorphTargets ) cachedMaterial.morphTargets = true; + if ( useMorphNormals ) cachedMaterial.morphNormals = true; + + this.cache.add( cacheKey, cachedMaterial ); + + } + + material = cachedMaterial; + + } + + // workarounds for mesh and geometry + + if ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) { + + console.log( 'THREE.GLTFLoader: Duplicating UVs to support aoMap.' ); + geometry.addAttribute( 'uv2', new BufferAttribute( geometry.attributes.uv.array, 2 ) ); + + } + + if ( material.isGLTFSpecularGlossinessMaterial ) { + + // for GLTFSpecularGlossinessMaterial(ShaderMaterial) uniforms runtime update + mesh.onBeforeRender = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].refreshUniforms; + + } + + mesh.material = material; + + }; + /** * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials * @param {number} materialIndex @@ -2492,14 +2503,6 @@ var GLTFLoader = ( function () { if ( materialDef.name !== undefined ) material.name = materialDef.name; - // Normal map textures use OpenGL conventions: - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture - if ( material.normalScale ) { - - material.normalScale.y = - material.normalScale.y; - - } - // baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding. if ( material.map ) material.map.encoding = sRGBEncoding; if ( material.emissiveMap ) material.emissiveMap.encoding = sRGBEncoding; @@ -2540,9 +2543,7 @@ var GLTFLoader = ( function () { for ( var gltfAttributeName in attributes ) { - var threeAttributeName = ATTRIBUTES[ gltfAttributeName ]; - - if ( ! threeAttributeName ) continue; + var threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase(); // Skip attributes already provided by e.g. Draco extension. if ( threeAttributeName in geometry.attributes ) continue; @@ -2579,8 +2580,6 @@ var GLTFLoader = ( function () { * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry * * Creates BufferGeometries from primitives. - * If we can build a single BufferGeometry with .groups from multiple primitives, returns one BufferGeometry. - * Otherwise, returns BufferGeometries without .groups as many as primitives. * * @param {Array} primitives * @return {Promise>} @@ -2591,22 +2590,6 @@ var GLTFLoader = ( function () { var extensions = this.extensions; var cache = this.primitiveCache; - var isMultiPass = isMultiPassGeometry( primitives ); - var originalPrimitives; - - if ( isMultiPass ) { - - originalPrimitives = primitives; // save original primitives and use later - - // We build a single BufferGeometry with .groups from multiple primitives - // because all primitives share the same attributes/morph/mode and have indices. - - primitives = [ primitives[ 0 ] ]; - - // Sets .groups and combined indices to a geometry later in this method. - - } - function createDracoPrimitive( primitive ) { return extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] @@ -2624,14 +2607,15 @@ var GLTFLoader = ( function () { for ( var i = 0, il = primitives.length; i < il; i ++ ) { var primitive = primitives[ i ]; + var cacheKey = createPrimitiveKey( primitive ); // See if we've already created this geometry - var cached = getCachedGeometry( cache, primitive ); + var cached = cache[ cacheKey ]; if ( cached ) { // Use the cached geometry if it exists - pending.push( cached ); + pending.push( cached.promise ); } else { @@ -2650,7 +2634,7 @@ var GLTFLoader = ( function () { } // Cache this geometry - cache.push( { primitive: primitive, promise: geometryPromise } ); + cache[ cacheKey ] = { primitive: primitive, promise: geometryPromise }; pending.push( geometryPromise ); @@ -2658,95 +2642,7 @@ var GLTFLoader = ( function () { } - return Promise.all( pending ).then( function ( geometries ) { - - if ( isMultiPass ) { - - var baseGeometry = geometries[ 0 ]; - - // See if we've already created this combined geometry - var cache = parser.multiPassGeometryCache; - var cached = getCachedMultiPassGeometry( cache, baseGeometry, originalPrimitives ); - - if ( cached !== null ) return [ cached.geometry ]; - - // Cloning geometry because of index override. - // Attributes can be reused so cloning by myself here. - var geometry = new BufferGeometry(); - - geometry.name = baseGeometry.name; - geometry.userData = baseGeometry.userData; - - for ( var key in baseGeometry.attributes ) geometry.addAttribute( key, baseGeometry.attributes[ key ] ); - for ( var key in baseGeometry.morphAttributes ) geometry.morphAttributes[ key ] = baseGeometry.morphAttributes[ key ]; - - var pendingIndices = []; - - for ( var i = 0, il = originalPrimitives.length; i < il; i ++ ) { - - pendingIndices.push( parser.getDependency( 'accessor', originalPrimitives[ i ].indices ) ); - - } - - return Promise.all( pendingIndices ).then( function ( accessors ) { - - var indices = []; - var offset = 0; - - for ( var i = 0, il = originalPrimitives.length; i < il; i ++ ) { - - var accessor = accessors[ i ]; - - for ( var j = 0, jl = accessor.count; j < jl; j ++ ) indices.push( accessor.array[ j ] ); - - geometry.addGroup( offset, accessor.count, i ); - - offset += accessor.count; - - } - - geometry.setIndex( indices ); - - cache.push( { geometry: geometry, baseGeometry: baseGeometry, primitives: originalPrimitives } ); - - return [ geometry ]; - - } ); - - } else if ( geometries.length > 1 && BufferGeometryUtils !== undefined ) { - - // Tries to merge geometries with BufferGeometryUtils if possible - - for ( var i = 1, il = primitives.length; i < il; i ++ ) { - - // can't merge if draw mode is different - if ( primitives[ 0 ].mode !== primitives[ i ].mode ) return geometries; - - } - - // See if we've already created this combined geometry - var cache = parser.multiplePrimitivesCache; - var cached = getCachedCombinedGeometry( cache, geometries ); - - if ( cached ) { - - if ( cached.geometry !== null ) return [ cached.geometry ]; - - } else { - - var geometry = BufferGeometryUtils.mergeBufferGeometries( geometries, true ); - - cache.push( { geometry: geometry, baseGeometries: geometries } ); - - if ( geometry !== null ) return [ geometry ]; - - } - - } - - return geometries; - - } ); + return Promise.all( pending ); }; @@ -2780,8 +2676,6 @@ var GLTFLoader = ( function () { return parser.loadGeometries( primitives ).then( function ( geometries ) { - var isMultiMaterial = geometries.length === 1 && geometries[ 0 ].groups.length > 0; - var meshes = []; for ( var i = 0, il = geometries.length; i < il; i ++ ) { @@ -2793,7 +2687,7 @@ var GLTFLoader = ( function () { var mesh; - var material = isMultiMaterial ? originalMaterials : originalMaterials[ i ]; + var material = originalMaterials[ i ]; if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP || @@ -2851,118 +2745,9 @@ var GLTFLoader = ( function () { assignExtrasToUserData( mesh, meshDef ); - meshes.push( mesh ); - - // 2. update Material depending on Mesh and BufferGeometry - - var materials = isMultiMaterial ? mesh.material : [ mesh.material ]; - - var useVertexColors = geometry.attributes.color !== undefined; - var useFlatShading = geometry.attributes.normal === undefined; - var useSkinning = mesh.isSkinnedMesh === true; - var useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0; - var useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined; - - for ( var j = 0, jl = materials.length; j < jl; j ++ ) { - - var material = materials[ j ]; - - if ( mesh.isPoints ) { - - var cacheKey = 'PointsMaterial:' + material.uuid; - - var pointsMaterial = parser.cache.get( cacheKey ); - - if ( ! pointsMaterial ) { - - pointsMaterial = new PointsMaterial(); - Material.prototype.copy.call( pointsMaterial, material ); - pointsMaterial.color.copy( material.color ); - pointsMaterial.map = material.map; - pointsMaterial.lights = false; // PointsMaterial doesn't support lights yet - - parser.cache.add( cacheKey, pointsMaterial ); - - } - - material = pointsMaterial; - - } else if ( mesh.isLine ) { - - var cacheKey = 'LineBasicMaterial:' + material.uuid; - - var lineMaterial = parser.cache.get( cacheKey ); - - if ( ! lineMaterial ) { + parser.assignFinalMaterial( mesh ); - lineMaterial = new LineBasicMaterial(); - Material.prototype.copy.call( lineMaterial, material ); - lineMaterial.color.copy( material.color ); - lineMaterial.lights = false; // LineBasicMaterial doesn't support lights yet - - parser.cache.add( cacheKey, lineMaterial ); - - } - - material = lineMaterial; - - } - - // Clone the material if it will be modified - if ( useVertexColors || useFlatShading || useSkinning || useMorphTargets ) { - - var cacheKey = 'ClonedMaterial:' + material.uuid + ':'; - - if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:'; - if ( useSkinning ) cacheKey += 'skinning:'; - if ( useVertexColors ) cacheKey += 'vertex-colors:'; - if ( useFlatShading ) cacheKey += 'flat-shading:'; - if ( useMorphTargets ) cacheKey += 'morph-targets:'; - if ( useMorphNormals ) cacheKey += 'morph-normals:'; - - var cachedMaterial = parser.cache.get( cacheKey ); - - if ( ! cachedMaterial ) { - - cachedMaterial = material.isGLTFSpecularGlossinessMaterial - ? extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].cloneMaterial( material ) - : material.clone(); - - if ( useSkinning ) cachedMaterial.skinning = true; - if ( useVertexColors ) cachedMaterial.vertexColors = VertexColors; - if ( useFlatShading ) cachedMaterial.flatShading = true; - if ( useMorphTargets ) cachedMaterial.morphTargets = true; - if ( useMorphNormals ) cachedMaterial.morphNormals = true; - - parser.cache.add( cacheKey, cachedMaterial ); - - } - - material = cachedMaterial; - - } - - materials[ j ] = material; - - // workarounds for mesh and geometry - - if ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) { - - console.log( 'THREE.GLTFLoader: Duplicating UVs to support aoMap.' ); - geometry.addAttribute( 'uv2', new BufferAttribute( geometry.attributes.uv.array, 2 ) ); - - } - - if ( material.isGLTFSpecularGlossinessMaterial ) { - - // for GLTFSpecularGlossinessMaterial(ShaderMaterial) uniforms runtime update - mesh.onBeforeRender = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].refreshUniforms; - - } - - } - - mesh.material = isMultiMaterial ? materials : materials[ 0 ]; + meshes.push( mesh ); } @@ -3147,10 +2932,7 @@ var GLTFLoader = ( function () { if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) { - // node can be Group here but - // PATH_PROPERTIES.weights(morphTargetInfluences) should be - // the property of a mesh object under group. - + // Node may be a Group (glTF mesh with several primitives) or a Mesh. node.traverse( function ( object ) { if ( object.isMesh === true && object.morphTargetInfluences ) { @@ -3167,20 +2949,16 @@ var GLTFLoader = ( function () { } - // KeyframeTrack.optimize() will modify given 'times' and 'values' - // buffers before creating a truncated copy to keep. Because buffers may - // be reused by other tracks, make copies here. for ( var j = 0, jl = targetNames.length; j < jl; j ++ ) { var track = new TypedKeyframeTrack( targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ], - AnimationUtils.arraySlice( inputAccessor.array, 0 ), - AnimationUtils.arraySlice( outputAccessor.array, 0 ), + inputAccessor.array, + outputAccessor.array, interpolation ); - // Here is the trick to enable custom interpolation. - // Overrides .createInterpolant in a factory method which creates custom interpolation. + // Override interpolation with custom factory method. if ( sampler.interpolation === 'CUBICSPLINE' ) { track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) { @@ -3193,8 +2971,7 @@ var GLTFLoader = ( function () { }; - // Workaround, provide an alternate way to know if the interpolant type is cubis spline to track. - // track.getInterpolation() doesn't return valid value for custom interpolant. + // Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants. track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true; } -- GitLab