|
@@ -1267,12 +1267,14 @@ THREE.GLTFLoader = ( function () {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ var defaultMaterial;
|
|
|
+
|
|
|
/**
|
|
|
* Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
|
|
|
*/
|
|
|
function createDefaultMaterial() {
|
|
|
|
|
|
- return new THREE.MeshStandardMaterial( {
|
|
|
+ defaultMaterial = defaultMaterial || new THREE.MeshStandardMaterial( {
|
|
|
color: 0xFFFFFF,
|
|
|
emissive: 0x000000,
|
|
|
metalness: 1,
|
|
@@ -1282,6 +1284,8 @@ THREE.GLTFLoader = ( function () {
|
|
|
side: THREE.FrontSide
|
|
|
} );
|
|
|
|
|
|
+ return defaultMaterial;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {
|
|
@@ -1570,34 +1574,6 @@ THREE.GLTFLoader = ( function () {
|
|
|
|
|
|
}
|
|
|
|
|
|
- function createArrayKeyBufferGeometry( a ) {
|
|
|
-
|
|
|
- var arrayKey = '';
|
|
|
-
|
|
|
- for ( var i = 0, il = a.length; i < il; i ++ ) {
|
|
|
-
|
|
|
- arrayKey += ':' + a[ i ].uuid;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return arrayKey;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function createMultiPassGeometryKey( geometry, primitives ) {
|
|
|
-
|
|
|
- var key = geometry.uuid;
|
|
|
-
|
|
|
- for ( var i = 0, il = primitives.length; i < il; i ++ ) {
|
|
|
-
|
|
|
- key += i + createPrimitiveKey( primitives[ i ] );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return key;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
function cloneBufferAttribute( attribute ) {
|
|
|
|
|
|
if ( attribute.isInterleavedBufferAttribute ) {
|
|
@@ -1623,48 +1599,6 @@ THREE.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<GLTF.Primitive>} 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 ) {
|
|
@@ -1678,8 +1612,6 @@ THREE.GLTFLoader = ( function () {
|
|
|
|
|
|
// BufferGeometry caching
|
|
|
this.primitiveCache = {};
|
|
|
- this.multiplePrimitivesCache = {};
|
|
|
- this.multiPassGeometryCache = {};
|
|
|
|
|
|
this.textureLoader = new THREE.TextureLoader( this.options.manager );
|
|
|
this.textureLoader.setCrossOrigin( this.options.crossOrigin );
|
|
@@ -2252,6 +2184,124 @@ THREE.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 {THREE.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 THREE.PointsMaterial();
|
|
|
+ THREE.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 THREE.LineBasicMaterial();
|
|
|
+ THREE.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 = THREE.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 THREE.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
|
|
@@ -2478,8 +2528,6 @@ THREE.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<GLTF.Primitive>} primitives
|
|
|
* @return {Promise<Array<THREE.BufferGeometry>>}
|
|
@@ -2490,22 +2538,6 @@ THREE.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 ]
|
|
@@ -2558,97 +2590,7 @@ THREE.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 cacheKey = createMultiPassGeometryKey( baseGeometry, originalPrimitives );
|
|
|
- var cached = cache[ cacheKey ];
|
|
|
-
|
|
|
- if ( cached ) return [ cached.geometry ];
|
|
|
-
|
|
|
- // Cloning geometry because of index override.
|
|
|
- // Attributes can be reused so cloning by myself here.
|
|
|
- var geometry = new THREE.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[ cacheKey ] = { geometry: geometry, baseGeometry: baseGeometry, primitives: originalPrimitives };
|
|
|
-
|
|
|
- return [ geometry ];
|
|
|
-
|
|
|
- } );
|
|
|
-
|
|
|
- } else if ( geometries.length > 1 && THREE.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 cacheKey = createArrayKeyBufferGeometry( geometries );
|
|
|
- var cached = cache[ cacheKey ];
|
|
|
-
|
|
|
- if ( cached ) {
|
|
|
-
|
|
|
- if ( cached.geometry !== null ) return [ cached.geometry ];
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- var geometry = THREE.BufferGeometryUtils.mergeBufferGeometries( geometries, true );
|
|
|
-
|
|
|
- cache[ cacheKey ] = { geometry: geometry, baseGeometries: geometries };
|
|
|
-
|
|
|
- if ( geometry !== null ) return [ geometry ];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return geometries;
|
|
|
-
|
|
|
- } );
|
|
|
+ return Promise.all( pending );
|
|
|
|
|
|
};
|
|
|
|
|
@@ -2682,8 +2624,6 @@ THREE.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 ++ ) {
|
|
@@ -2695,7 +2635,7 @@ THREE.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 ||
|
|
@@ -2753,121 +2693,9 @@ THREE.GLTFLoader = ( function () {
|
|
|
|
|
|
assignExtrasToUserData( mesh, meshDef );
|
|
|
|
|
|
- meshes.push( mesh );
|
|
|
-
|
|
|
- // 2. update Material depending on Mesh and BufferGeometry
|
|
|
-
|
|
|
- var materials = isMultiMaterial ? mesh.material : [ mesh.material ];
|
|
|
-
|
|
|
- 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;
|
|
|
-
|
|
|
- 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 THREE.PointsMaterial();
|
|
|
- THREE.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 ) {
|
|
|
-
|
|
|
- lineMaterial = new THREE.LineBasicMaterial();
|
|
|
- THREE.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 ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {
|
|
|
+ parser.assignFinalMaterial( mesh );
|
|
|
|
|
|
- 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 = 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 ( useVertexTangents ) cachedMaterial.vertexTangents = true;
|
|
|
- if ( useVertexColors ) cachedMaterial.vertexColors = THREE.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 THREE.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 );
|
|
|
|
|
|
}
|
|
|
|