0% found this document useful (0 votes)
39K views65 pages

GLTFLoader

The document describes the THREE.GLTFLoader class which is used to load and parse glTF files. It defines functions like load, parse, setDRACOLoader, and register which handle loading the data, parsing it, and integrating plugin extensions. It also defines constants for common glTF extensions and a GLTFRegistry to store loaded objects.

Uploaded by

mangatha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39K views65 pages

GLTFLoader

The document describes the THREE.GLTFLoader class which is used to load and parse glTF files. It defines functions like load, parse, setDRACOLoader, and register which handle loading the data, parsing it, and integrating plugin extensions. It also defines constants for common glTF extensions and a GLTFRegistry to store loaded objects.

Uploaded by

mangatha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

[Link]( "THREE.

GLTFLoader: As part of the transition to ES6 Modules, the


files in 'examples/js' were deprecated in May 2020 (r117) and will be deleted in
December 2020 (r124). You can find more information about developing using ES6
Modules in [Link]
modules." );
/**
* @author Rich Tibbett / [Link]
* @author mrdoob / [Link]
* @author Tony Parisi / [Link]
* @author Takahiro / [Link]
* @author Don McCurdy / [Link]
*/

[Link] = ( function () {

function GLTFLoader( manager ) {

[Link]( this, manager );

[Link] = null;
[Link] = null;

[Link] = [];
[Link]( function ( parser ) {

return new GLTFMaterialsClearcoatExtension( parser );

} );

[Link] =
[Link]( [Link]( [Link] ), {

constructor: GLTFLoader,

load: function ( url, onLoad, onProgress, onError ) {

var scope = this;

var resourcePath;

if ( [Link] !== '' ) {

resourcePath = [Link];

} else if ( [Link] !== '' ) {

resourcePath = [Link];

} else {

resourcePath = [Link]( url );

// Tells the LoadingManager to track an extra item, which


resolves after
// the model is fully loaded. This means the count of items
loaded will
// be incorrect, but ensures [Link]() does not fire
early.
[Link]( url );

var _onError = function ( e ) {

if ( onError ) {

onError( e );

} else {

[Link]( e );

[Link]( url );
[Link]( url );

};

var loader = new [Link]( [Link] );

[Link]( [Link] );
[Link]( 'arraybuffer' );
[Link]( [Link] );

if ( [Link] === 'use-credentials' ) {

[Link]( true );

[Link]( url, function ( data ) {

try {

[Link]( data, resourcePath, function ( gltf ) {

onLoad( gltf );

[Link]( url );

}, _onError );

} catch ( e ) {

_onError( e );

}, onProgress, _onError );

},

setDRACOLoader: function ( dracoLoader ) {

[Link] = dracoLoader;
return this;

},

setDDSLoader: function ( ddsLoader ) {

[Link] = ddsLoader;
return this;

},

register: function ( callback ) {

if ( [Link]( callback ) === - 1 ) {

[Link]( callback );

return this;

},

unregister: function ( callback ) {

if ( [Link]( callback ) !== - 1 ) {

[Link]( [Link]( callback ), 1 );

return this;

},

parse: function ( data, path, onLoad, onError ) {

var content;
var extensions = {};
var plugins = {};

if ( typeof data === 'string' ) {

content = data;

} else {

var magic = [Link]( new


Uint8Array( data, 0, 4 ) );

if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {

try {

extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new


GLTFBinaryExtension( data );

} catch ( error ) {
if ( onError ) onError( error );
return;

content =
extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;

} else {

content = [Link]( new


Uint8Array( data ) );

var json = [Link]( content );

if ( [Link] === undefined || [Link][ 0 ] < 2 ) {

if ( onError ) onError( new Error( '[Link]:


Unsupported asset. glTF versions >=2.0 are supported.' ) );
return;

var parser = new GLTFParser( json, {

path: path || [Link] || '',


crossOrigin: [Link],
manager: [Link]

} );

[Link]( [Link] );

for ( var i = 0; i < [Link]; i ++ ) {

var plugin = [Link][ i ]( parser );


plugins[ [Link] ] = plugin;

// Workaround to avoid determining as unknown extension


// in addUnknownExtensionsToUserData().
// Remove this workaround if we move all the existing
// extension handlers to plugin system
extensions[ [Link] ] = true;

if ( [Link] ) {

for ( var i = 0; i < [Link]; ++ i ) {

var extensionName = [Link][ i ];


var extensionsRequired = [Link] ||
[];
switch ( extensionName ) {

case EXTENSIONS.KHR_LIGHTS_PUNCTUAL:
extensions[ extensionName ] = new
GLTFLightsExtension( json );
break;

case EXTENSIONS.KHR_MATERIALS_UNLIT:
extensions[ extensionName ] = new
GLTFMaterialsUnlitExtension();
break;

case
EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
extensions[ extensionName ] = new
GLTFMaterialsPbrSpecularGlossinessExtension();
break;

case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
extensions[ extensionName ] = new
GLTFDracoMeshCompressionExtension( json, [Link] );
break;

case EXTENSIONS.MSFT_TEXTURE_DDS:
extensions[ extensionName ] = new
GLTFTextureDDSExtension( [Link] );
break;

case EXTENSIONS.KHR_TEXTURE_TRANSFORM:
extensions[ extensionName ] = new
GLTFTextureTransformExtension();
break;

case EXTENSIONS.KHR_MESH_QUANTIZATION:
extensions[ extensionName ] = new
GLTFMeshQuantizationExtension();
break;

default:

if
( [Link]( extensionName ) >= 0 && plugins[ extensionName ] ===
undefined ) {

[Link]( '[Link]:
Unknown extension "' + extensionName + '".' );

[Link]( extensions );
[Link]( plugins );
[Link]( onLoad, onError );
}

} );

/* GLTFREGISTRY */

function GLTFRegistry() {

var objects = {};

return {

get: function ( key ) {

return objects[ key ];

},

add: function ( key, object ) {

objects[ key ] = object;

},

remove: function ( key ) {

delete objects[ key ];

},

removeAll: function () {

objects = {};

};

/*********************************/
/********** EXTENSIONS ***********/
/*********************************/

var EXTENSIONS = {
KHR_BINARY_GLTF: 'KHR_binary_glTF',
KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
'KHR_materials_pbrSpecularGlossiness',
KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
};

/**
* DDS Texture Extension
*
* Specification:
[Link]
_dds
*
*/
function GLTFTextureDDSExtension( ddsLoader ) {

if ( ! ddsLoader ) {

throw new Error( '[Link]: Attempting to load .dds


texture without importing [Link]' );

[Link] = EXTENSIONS.MSFT_TEXTURE_DDS;
[Link] = ddsLoader;

/**
* Punctual Lights Extension
*
* Specification:
[Link]
punctual
*/
function GLTFLightsExtension( json ) {

[Link] = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;

var extension = ( [Link] &&


[Link][ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ] ) || {};
[Link] = [Link] || [];

[Link] = function ( lightIndex ) {

var lightDef = [Link][ lightIndex ];


var lightNode;

var color = new [Link]( 0xffffff );


if ( [Link] !== undefined ) [Link]( [Link] );

var range = [Link] !== undefined ? [Link] : 0;

switch ( [Link] ) {

case 'directional':
lightNode = new [Link]( color );
[Link]( 0, 0, - 1 );
[Link]( [Link] );
break;

case 'point':
lightNode = new [Link]( color );
[Link] = range;
break;
case 'spot':
lightNode = new [Link]( color );
[Link] = range;
// Handle spotlight properties.
[Link] = [Link] || {};
[Link] = [Link]
!== undefined ? [Link] : 0;
[Link] = [Link]
!== undefined ? [Link] : [Link] / 4.0;
[Link] = [Link];
[Link] = 1.0 - [Link] /
[Link];
[Link]( 0, 0, - 1 );
[Link]( [Link] );
break;

default:
throw new Error( '[Link]: Unexpected light type,
"' + [Link] + '".' );

// 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.
[Link]( 0, 0, 0 );

[Link] = 2;

if ( [Link] !== undefined ) [Link] =


[Link];

[Link] = [Link] || ( 'light_' + lightIndex );

return [Link]( lightNode );

};

/**
* Unlit Materials Extension
*
* Specification:
[Link]
ls_unlit
*/
function GLTFMaterialsUnlitExtension() {

[Link] = EXTENSIONS.KHR_MATERIALS_UNLIT;

[Link] = function () {

return [Link];

};
[Link] = function
( materialParams, materialDef, parser ) {

var pending = [];

[Link] = new [Link]( 1.0, 1.0, 1.0 );


[Link] = 1.0;

var metallicRoughness = [Link];

if ( metallicRoughness ) {

if ( [Link]( [Link] ) ) {

var array = [Link];

[Link]( array );
[Link] = array[ 3 ];

if ( [Link] !== undefined ) {

[Link]( [Link]( materialParams, 'map',


[Link] ) );

return [Link]( pending );

};

/**
* Clearcoat Materials Extension
*
* Specification:
[Link]
ls_clearcoat
*/
function GLTFMaterialsClearcoatExtension( parser ) {

[Link] = parser;
[Link] = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;

[Link] = function ( /*
materialIndex */ ) {

return [Link];

};

[Link] = function
( materialIndex, materialParams ) {

var parser = [Link];


var materialDef = [Link][ materialIndex ];

if ( ! [Link] || !
[Link][ [Link] ] ) {

return [Link]();

var pending = [];

var extension = [Link][ [Link] ];

if ( [Link] !== undefined ) {

[Link] = [Link];

if ( [Link] !== undefined ) {

[Link]( [Link]( materialParams,


'clearcoatMap', [Link] ) );

if ( [Link] !== undefined ) {

[Link] =
[Link];

if ( [Link] !== undefined ) {

[Link]( [Link]( materialParams,


'clearcoatRoughnessMap', [Link] ) );

if ( [Link] !== undefined ) {

[Link]( [Link]( materialParams,


'clearcoatNormalMap', [Link] ) );

if ( [Link] !== undefined ) {

var scale = [Link];

[Link] = new
THREE.Vector2( scale, scale );

return [Link]( pending );

};
/* BINARY EXTENSION */
var BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
var BINARY_EXTENSION_HEADER_LENGTH = 12;
var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };

function GLTFBinaryExtension( data ) {

[Link] = EXTENSIONS.KHR_BINARY_GLTF;
[Link] = null;
[Link] = null;

var headerView = new DataView( data, 0,


BINARY_EXTENSION_HEADER_LENGTH );

[Link] = {
magic: [Link]( new
Uint8Array( [Link]( 0, 4 ) ) ),
version: headerView.getUint32( 4, true ),
length: headerView.getUint32( 8, true )
};

if ( [Link] !== BINARY_EXTENSION_HEADER_MAGIC ) {

throw new Error( '[Link]: Unsupported glTF-Binary


header.' );

} else if ( [Link] < 2.0 ) {

throw new Error( '[Link]: Legacy binary file detected.'


);

var chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );


var chunkIndex = 0;

while ( chunkIndex < [Link] ) {

var chunkLength = chunkView.getUint32( chunkIndex, true );


chunkIndex += 4;

var chunkType = chunkView.getUint32( chunkIndex, true );


chunkIndex += 4;

if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {

var contentArray = new Uint8Array( data,


BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );
[Link] =
[Link]( contentArray );

} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {

var byteOffset = BINARY_EXTENSION_HEADER_LENGTH +


chunkIndex;
[Link] = [Link]( byteOffset, byteOffset +
chunkLength );
}

// Clients must ignore chunks with unknown types.

chunkIndex += chunkLength;

if ( [Link] === null ) {

throw new Error( '[Link]: JSON content not found.' );

/**
* DRACO Mesh Compression Extension
*
* Specification:
[Link]
esh_compression
*/
function GLTFDracoMeshCompressionExtension( json, dracoLoader ) {

if ( ! dracoLoader ) {

throw new Error( '[Link]: No DRACOLoader instance


provided.' );

[Link] = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
[Link] = json;
[Link] = dracoLoader;
[Link]();

[Link] = function
( primitive, parser ) {

var json = [Link];


var dracoLoader = [Link];
var bufferViewIndex = [Link][ [Link] ].bufferView;
var gltfAttributeMap = [Link][ [Link] ].attributes;
var threeAttributeMap = {};
var attributeNormalizedMap = {};
var attributeTypeMap = {};

for ( var attributeName in gltfAttributeMap ) {

var threeAttributeName = ATTRIBUTES[ attributeName ] ||


[Link]();

threeAttributeMap[ threeAttributeName ] =
gltfAttributeMap[ attributeName ];

}
for ( attributeName in [Link] ) {

var threeAttributeName = ATTRIBUTES[ attributeName ] ||


[Link]();

if ( gltfAttributeMap[ attributeName ] !== undefined ) {

var accessorDef =
[Link][ [Link][ attributeName ] ];
var componentType =
WEBGL_COMPONENT_TYPES[ [Link] ];

attributeTypeMap[ threeAttributeName ] = componentType;


attributeNormalizedMap[ threeAttributeName ] =
[Link] === true;

return [Link]( 'bufferView',


bufferViewIndex ).then( function ( bufferView ) {

return new Promise( function ( resolve ) {

[Link]( bufferView, function


( geometry ) {

for ( var attributeName in [Link] ) {

var attribute =
[Link][ attributeName ];
var normalized =
attributeNormalizedMap[ attributeName ];

if ( normalized !== undefined )


[Link] = normalized;

resolve( geometry );

}, threeAttributeMap, attributeTypeMap );

} );

} );

};

/**
* Texture Transform Extension
*
* Specification:
[Link]
_transform
*/
function GLTFTextureTransformExtension() {
[Link] = EXTENSIONS.KHR_TEXTURE_TRANSFORM;

[Link] = function ( texture,


transform ) {

texture = [Link]();

if ( [Link] !== undefined ) {

[Link]( [Link] );

if ( [Link] !== undefined ) {

[Link] = [Link];

if ( [Link] !== undefined ) {

[Link]( [Link] );

if ( [Link] !== undefined ) {

[Link]( '[Link]: Custom UV sets in "' + [Link]


+ '" extension not yet supported.' );

[Link] = true;

return texture;

};

/**
* Specular-Glossiness Extension
*
* Specification:
[Link]
ls_pbrSpecularGlossiness
*/

/**
* A sub class of [Link] with some of the functionality
* changed via the `onBeforeCompile` callback
* @pailhead
*/

function GLTFMeshStandardSGMaterial( params ) {

[Link]( this );
[Link] = true;

//various chunks that need replacing


var specularMapParsFragmentChunk = [
'#ifdef USE_SPECULARMAP',
' uniform sampler2D specularMap;',
'#endif'
].join( '\n' );

var glossinessMapParsFragmentChunk = [
'#ifdef USE_GLOSSINESSMAP',
' uniform sampler2D glossinessMap;',
'#endif'
].join( '\n' );

var specularMapFragmentChunk = [
'vec3 specularFactor = specular;',
'#ifdef USE_SPECULARMAP',
' vec4 texelSpecular = texture2D( specularMap, vUv );',
' texelSpecular = sRGBToLinear( texelSpecular );',
' // reads channel RGB, compatible with a glTF Specular-
Glossiness (RGBA) texture',
' specularFactor *= [Link];',
'#endif'
].join( '\n' );

var 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' );

var lightPhysicalFragmentChunk = [
'PhysicalMaterial material;',
'[Link] = [Link];',
'vec3 dxy = max( abs( dFdx( geometryNormal ) ),
abs( dFdy( geometryNormal ) ) );',
'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );',
'[Link] = max( 1.0 - glossinessFactor, 0.0525
);// 0.0525 corresponds to the base mip of a 256 cubemap.',
'[Link] += geometryRoughness;',
'[Link] = min( [Link],
1.0 );',
'[Link] = [Link];',
].join( '\n' );

var uniforms = {
specular: { value: new [Link]().setHex( 0xffffff ) },
glossiness: { value: 1 },
specularMap: { value: null },
glossinessMap: { value: null }
};

this._extraUniforms = uniforms;
// please see #14031 or #13198 for an alternate approach
[Link] = function ( shader ) {

for ( var uniformName in uniforms ) {

[Link][ uniformName ] = uniforms[ uniformName ];

[Link] = [Link]( 'uniform


float roughness;', 'uniform vec3 specular;' );
[Link] = [Link]( 'uniform
float metalness;', 'uniform float glossiness;' );
[Link] = [Link]( '#include
<roughnessmap_pars_fragment>', specularMapParsFragmentChunk );
[Link] = [Link]( '#include
<metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk );
[Link] = [Link]( '#include
<roughnessmap_fragment>', specularMapFragmentChunk );
[Link] = [Link]( '#include
<metalnessmap_fragment>', glossinessMapFragmentChunk );
[Link] = [Link]( '#include
<lights_physical_fragment>', lightPhysicalFragmentChunk );

};

/*eslint-disable*/
[Link](
this,
{
specular: {
get: function () { return [Link]; },
set: function ( v ) { [Link] = v; }
},
specularMap: {
get: function () { return [Link];
},
set: function ( v ) { [Link] = v;
}
},
glossiness: {
get: function () { return
[Link]; },
set: function ( v ) { [Link] =
v; }
},
glossinessMap: {
get: function () { return
[Link]; },
set: function ( v ) {

[Link] = v;
//how about something like this - @pailhead
if ( v ) {

[Link].USE_GLOSSINESSMAP = '';
// set USE_ROUGHNESSMAP to enable vUv
[Link].USE_ROUGHNESSMAP = '';
} else {

delete [Link].USE_ROUGHNESSMAP;
delete [Link].USE_GLOSSINESSMAP;

}
}
}
);

/*eslint-enable*/
delete [Link];
delete [Link];
delete [Link];
delete [Link];

[Link]( params );

[Link] =
[Link]( [Link] );
[Link] =
GLTFMeshStandardSGMaterial;

[Link] = function ( source ) {

[Link]( this, source );


[Link] = [Link];
[Link]( [Link] );
[Link] = [Link];
[Link] = [Link];
delete [Link];
delete [Link];
delete [Link];
delete [Link];
return this;

};

function GLTFMaterialsPbrSpecularGlossinessExtension() {

return {

name: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,

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',
],

getMaterialType: function () {

return GLTFMeshStandardSGMaterial;

},

extendParams: function ( materialParams, materialDef, parser ) {

var pbrSpecularGlossiness =
[Link][ [Link] ];

[Link] = new [Link]( 1.0, 1.0, 1.0 );


[Link] = 1.0;

var pending = [];

if ( [Link]( [Link] ) )
{

var array = [Link];

[Link]( array );
[Link] = array[ 3 ];

if ( [Link] !== undefined ) {

[Link]( [Link]( materialParams,


'map', [Link] ) );

[Link] = new [Link]( 0.0, 0.0, 0.0 );


[Link] =
[Link] !== undefined ?
[Link] : 1.0;
[Link] = new [Link]( 1.0, 1.0, 1.0 );

if
( [Link]( [Link] ) ) {
[Link]( [Link] );

if ( [Link] !==
undefined ) {

var specGlossMapDef =
[Link];
[Link]( [Link]( materialParams,
'glossinessMap', specGlossMapDef ) );
[Link]( [Link]( materialParams,
'specularMap', specGlossMapDef ) );

return [Link]( pending );

},

createMaterial: function ( materialParams ) {

var material = new


GLTFMeshStandardSGMaterial( materialParams );
[Link] = true;

[Link] = [Link];

[Link] = [Link] === undefined ? null :


[Link];

[Link] = null;
[Link] = 1.0;

[Link] = [Link] === undefined ?


null : [Link];
[Link] = 1.0;

[Link] = [Link];
[Link] = 1.0;
[Link] = [Link] ===
undefined ? null : [Link];

[Link] = [Link] === undefined ?


null : [Link];
[Link] = 1;

[Link] = [Link] === undefined


? null : [Link];
[Link] = [Link];

if ( [Link] ) [Link] =
[Link];

[Link] = null;
[Link] = 1;
[Link] = 0;

[Link] = [Link] ===


undefined ? null : [Link];
[Link] = [Link];

[Link] = [Link] ===


undefined ? null : [Link];
[Link] = [Link];

[Link] = null;

[Link] = [Link] === undefined ?


null : [Link];
[Link] = 1.0;

[Link] = 0.98;

return material;

},

};

/**
* Mesh Quantization Extension
*
* Specification:
[Link]
antization
*/
function GLTFMeshQuantizationExtension() {

[Link] = EXTENSIONS.KHR_MESH_QUANTIZATION;

/*********************************/
/********** INTERPOLATION ********/
/*********************************/

// Spline Interpolation
// Specification:
[Link]
ix-c-spline-interpolation
function GLTFCubicSplineInterpolant( parameterPositions, sampleValues,
sampleSize, resultBuffer ) {

[Link]( this, parameterPositions, sampleValues,


sampleSize, resultBuffer );

[Link] =
[Link]( [Link] );
[Link] =
GLTFCubicSplineInterpolant;

[Link].copySampleValue_ = function ( index ) {


// Copies a sample value to the result buffer. See description of glTF
// CUBICSPLINE values layout in interpolate_() function below.

var result = [Link],


values = [Link],
valueSize = [Link],
offset = index * valueSize * 3 + valueSize;

for ( var i = 0; i !== valueSize; i ++ ) {

result[ i ] = values[ offset + i ];

return result;

};

[Link].beforeStart_ =
[Link].copySampleValue_;

[Link].afterEnd_ =
[Link].copySampleValue_;

[Link].interpolate_ = function ( i1, t0, t,


t1 ) {

var result = [Link];


var values = [Link];
var stride = [Link];

var stride2 = stride * 2;


var stride3 = stride * 3;

var td = t1 - t0;

var p = ( t - t0 ) / td;
var pp = p * p;
var ppp = pp * p;

var offset1 = i1 * stride3;


var offset0 = offset1 - stride3;

var s2 = - 2 * ppp + 3 * pp;


var s3 = ppp - pp;
var s0 = 1 - s2;
var s1 = s3 - pp + p;

// Layout of keyframe output values for CUBICSPLINE animations:


// [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2,
splineVertex_2, ... ]
for ( var i = 0; i !== stride; i ++ ) {

var p0 = values[ offset0 + i + stride ]; // splineVertex_k


var m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k *
(t_k+1 - t_k)
var p1 = values[ offset1 + i + stride ]; // splineVertex_k+1
var m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 -
t_k)
result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;

return result;

};

/*********************************/
/********** INTERNALS ************/
/*********************************/

/* CONSTANTS */

var WEBGL_CONSTANTS = {
FLOAT: 5126,
//FLOAT_MAT2: 35674,
FLOAT_MAT3: 35675,
FLOAT_MAT4: 35676,
FLOAT_VEC2: 35664,
FLOAT_VEC3: 35665,
FLOAT_VEC4: 35666,
LINEAR: 9729,
REPEAT: 10497,
SAMPLER_2D: 35678,
POINTS: 0,
LINES: 1,
LINE_LOOP: 2,
LINE_STRIP: 3,
TRIANGLES: 4,
TRIANGLE_STRIP: 5,
TRIANGLE_FAN: 6,
UNSIGNED_BYTE: 5121,
UNSIGNED_SHORT: 5123
};

var WEBGL_COMPONENT_TYPES = {
5120: Int8Array,
5121: Uint8Array,
5122: Int16Array,
5123: Uint16Array,
5125: Uint32Array,
5126: Float32Array
};

var WEBGL_FILTERS = {
9728: [Link],
9729: [Link],
9984: [Link],
9985: [Link],
9986: [Link],
9987: [Link]
};

var WEBGL_WRAPPINGS = {
33071: [Link],
33648: [Link],
10497: [Link]
};

var WEBGL_TYPE_SIZES = {
'SCALAR': 1,
'VEC2': 2,
'VEC3': 3,
'VEC4': 4,
'MAT2': 4,
'MAT3': 9,
'MAT4': 16
};

var ATTRIBUTES = {
POSITION: 'position',
NORMAL: 'normal',
TANGENT: 'tangent',
TEXCOORD_0: 'uv',
TEXCOORD_1: 'uv2',
COLOR_0: 'color',
WEIGHTS_0: 'skinWeight',
JOINTS_0: 'skinIndex',
};

var PATH_PROPERTIES = {
scale: 'scale',
translation: 'position',
rotation: 'quaternion',
weights: 'morphTargetInfluences'
};

var INTERPOLATION = {
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: [Link],
STEP: [Link]
};

var ALPHA_MODES = {
OPAQUE: 'OPAQUE',
MASK: 'MASK',
BLEND: 'BLEND'
};

var MIME_TYPE_FORMATS = {
'image/png': [Link],
'image/jpeg': [Link]
};

/* UTILITY FUNCTIONS */

function resolveURL( url, path ) {

// Invalid URL
if ( typeof url !== 'string' || url === '' ) return '';

// Host Relative URL


if ( /^https?:\/\//[Link]( path ) && /^\//.test( url ) ) {
path = [Link]( /(^https?:\/\/[^\/]+).*/i, '$1' );

// Absolute URL [Link]


if ( /^(https?:)?\/\//[Link]( url ) ) return url;

// Data URI
if ( /^data:.*,.*$/[Link]( url ) ) return url;

// Blob URL
if ( /^blob:.*$/[Link]( url ) ) return url;

// Relative URL
return path + url;

/**
* Specification:
[Link]
t-material
*/
function createDefaultMaterial( cache ) {

if ( cache[ 'DefaultMaterial' ] === undefined ) {

cache[ 'DefaultMaterial' ] = new [Link]( {


color: 0xFFFFFF,
emissive: 0x000000,
metalness: 1,
roughness: 1,
transparent: false,
depthTest: true,
side: [Link]
} );

return cache[ 'DefaultMaterial' ];

function addUnknownExtensionsToUserData( knownExtensions, object, objectDef )


{

// Add unknown glTF extensions to an object's userData.

for ( var name in [Link] ) {

if ( knownExtensions[ name ] === undefined ) {

[Link] =
[Link] || {};
[Link][ name ] =
[Link][ name ];

}
}

/**
* @param {THREE.Object3D|[Link]|[Link]} object
* @param {[Link]} gltfDef
*/
function assignExtrasToUserData( object, gltfDef ) {

if ( [Link] !== undefined ) {

if ( typeof [Link] === 'object' ) {

[Link]( [Link], [Link] );

} else {

[Link]( '[Link]: Ignoring primitive type


.extras, ' + [Link] );

/**
* Specification:
[Link]
targets
*
* @param {[Link]} geometry
* @param {Array<[Link]>} targets
* @param {GLTFParser} parser
* @return {Promise<[Link]>}
*/
function addMorphTargets( geometry, targets, parser ) {

var hasMorphPosition = false;


var hasMorphNormal = false;

for ( var i = 0, il = [Link]; i < il; i ++ ) {

var target = targets[ i ];

if ( [Link] !== undefined ) hasMorphPosition = true;


if ( [Link] !== undefined ) hasMorphNormal = true;

if ( hasMorphPosition && hasMorphNormal ) break;

if ( ! hasMorphPosition && ! hasMorphNormal ) return


[Link]( geometry );

var pendingPositionAccessors = [];


var pendingNormalAccessors = [];
for ( var i = 0, il = [Link]; i < il; i ++ ) {

var target = targets[ i ];

if ( hasMorphPosition ) {

var pendingAccessor = [Link] !== undefined


? [Link]( 'accessor', [Link] )
: [Link];

[Link]( pendingAccessor );

if ( hasMorphNormal ) {

var pendingAccessor = [Link] !== undefined


? [Link]( 'accessor', [Link] )
: [Link];

[Link]( pendingAccessor );

return [Link]( [
[Link]( pendingPositionAccessors ),
[Link]( pendingNormalAccessors )
] ).then( function ( accessors ) {

var morphPositions = accessors[ 0 ];


var morphNormals = accessors[ 1 ];

if ( hasMorphPosition ) [Link] =
morphPositions;
if ( hasMorphNormal ) [Link] =
morphNormals;
[Link] = true;

return geometry;

} );

/**
* @param {[Link]} mesh
* @param {[Link]} meshDef
*/
function updateMorphTargets( mesh, meshDef ) {

[Link]();

if ( [Link] !== undefined ) {

for ( var i = 0, il = [Link]; i < il; i ++ ) {


[Link][ i ] = [Link][ i ];

// .extras has user-defined data, so check that .[Link] is


an array.
if ( [Link] && [Link]( [Link] ) ) {

var targetNames = [Link];

if ( [Link] === [Link] ) {

[Link] = {};

for ( var i = 0, il = [Link]; i < il; i ++ ) {

[Link][ targetNames[ i ] ] = i;

} else {

[Link]( '[Link]: Invalid [Link]


length. Ignoring names.' );

function createPrimitiveKey( primitiveDef ) {

var dracoExtension = [Link] &&


[Link][ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];
var geometryKey;

if ( dracoExtension ) {

geometryKey = 'draco:' + [Link]


+ ':' + [Link]
+ ':' + createAttributesKey( [Link] );

} else {

geometryKey = [Link] + ':' +


createAttributesKey( [Link] ) + ':' + [Link];

return geometryKey;

function createAttributesKey( attributes ) {

var attributesKey = '';


var keys = [Link]( attributes ).sort();

for ( var i = 0, il = [Link]; i < il; i ++ ) {

attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';

return attributesKey;

/* GLTF PARSER */

function GLTFParser( json, options ) {

[Link] = json || {};


[Link] = {};
[Link] = {};
[Link] = options || {};

// loader object cache


[Link] = new GLTFRegistry();

// associations between [Link] objects and glTF elements


[Link] = new Map();

// BufferGeometry caching
[Link] = {};

// Use an ImageBitmapLoader if imageBitmaps are supported. Moves much


of the
// expensive work of uploading a texture to the GPU off the main
thread.
if ( typeof createImageBitmap !== 'undefined' &&
/Firefox/.test( [Link] ) === false ) {

[Link] = new
[Link]( [Link] );

} else {

[Link] = new
[Link]( [Link] );

[Link]( [Link] );

[Link] = new [Link]( [Link] );


[Link]( 'arraybuffer' );

if ( [Link] === 'use-credentials' ) {

[Link]( true );

}
}

[Link] = function ( extensions ) {

[Link] = extensions;

};

[Link] = function ( plugins ) {

[Link] = plugins;

};

[Link] = function ( onLoad, onError ) {

var parser = this;


var json = [Link];
var extensions = [Link];

// Clear the loader cache


[Link]();

// Mark the special nodes/meshes in json for efficient parse


[Link]();

[Link]( [

[Link]( 'scene' ),
[Link]( 'animation' ),
[Link]( 'camera' ),

] ).then( function ( dependencies ) {

var result = {
scene: dependencies[ 0 ][ [Link] || 0 ],
scenes: dependencies[ 0 ],
animations: dependencies[ 1 ],
cameras: dependencies[ 2 ],
asset: [Link],
parser: parser,
userData: {}
};

addUnknownExtensionsToUserData( extensions, result, json );

assignExtrasToUserData( result, json );

onLoad( result );

} ).catch( onError );

};

/**
* Marks the special nodes/meshes in json for efficient parse.
*/
[Link] = function () {
var nodeDefs = [Link] || [];
var skinDefs = [Link] || [];
var meshDefs = [Link] || [];

var meshReferences = {};


var meshUses = {};

// Nothing in the node definition indicates whether it is a Bone or an


// Object3D. Use the skins' joint references to mark bones.
for ( var skinIndex = 0, skinLength = [Link]; skinIndex <
skinLength; skinIndex ++ ) {

var joints = skinDefs[ skinIndex ].joints;

for ( var i = 0, il = [Link]; i < il; i ++ ) {

nodeDefs[ joints[ i ] ].isBone = true;

// Meshes can (and should) be reused by multiple nodes in a glTF asset.


To
// avoid having more than one [Link] with the same name, count
// references and rename instances below.
//
// Example: CesiumMilkTruck sample model reuses "Wheel" meshes.
for ( var nodeIndex = 0, nodeLength = [Link]; nodeIndex <
nodeLength; nodeIndex ++ ) {

var nodeDef = nodeDefs[ nodeIndex ];

if ( [Link] !== undefined ) {

if ( meshReferences[ [Link] ] === undefined ) {

meshReferences[ [Link] ] =
meshUses[ [Link] ] = 0;

meshReferences[ [Link] ] ++;

// Nothing in the mesh definition indicates whether it is


// a SkinnedMesh or Mesh. Use the node's mesh reference
// to mark SkinnedMesh if node has skin.
if ( [Link] !== undefined ) {

meshDefs[ [Link] ].isSkinnedMesh = true;

[Link] = meshReferences;
[Link] = meshUses;
};

[Link]._invokeOne = function ( func ) {

var extensions = [Link]( [Link] );


[Link]( this );

for ( var i = 0; i < [Link]; i ++ ) {

var result = func( extensions[ i ] );

if ( result ) return result;

};

[Link]._invokeAll = function ( func ) {

var extensions = [Link]( [Link] );


[Link]( this );

var pending = [];

for ( var i = 0; i < [Link]; i ++ ) {

[Link]( func( extensions[ i ] ) );

return [Link]( pending );

};

/**
* Requests the specified dependency asynchronously, with caching.
* @param {string} type
* @param {number} index
* @return {Promise<THREE.Object3D|[Link]|[Link]|
[Link]|ArrayBuffer|Object>}
*/
[Link] = function ( type, index ) {

var cacheKey = type + ':' + index;


var dependency = [Link]( cacheKey );

if ( ! dependency ) {

switch ( type ) {

case 'scene':
dependency = [Link]( index );
break;

case 'node':
dependency = [Link]( index );
break;
case 'mesh':
dependency = this._invokeOne( function ( ext ) {

return [Link] && [Link]( index );

} );
break;

case 'accessor':
dependency = [Link]( index );
break;

case 'bufferView':
dependency = this._invokeOne( function ( ext ) {

return [Link] &&


[Link]( index );

} );
break;

case 'buffer':
dependency = [Link]( index );
break;

case 'material':
dependency = this._invokeOne( function ( ext ) {

return [Link] &&


[Link]( index );

} );
break;

case 'texture':
dependency = [Link]( index );
break;

case 'skin':
dependency = [Link]( index );
break;

case 'animation':
dependency = [Link]( index );
break;

case 'camera':
dependency = [Link]( index );
break;

case 'light':
dependency =
[Link][ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );
break;

default:
throw new Error( 'Unknown type: ' + type );

}
[Link]( cacheKey, dependency );

return dependency;

};

/**
* Requests all dependencies of the specified type asynchronously, with
caching.
* @param {string} type
* @return {Promise<Array<Object>>}
*/
[Link] = function ( type ) {

var dependencies = [Link]( type );

if ( ! dependencies ) {

var parser = this;


var defs = [Link][ type + ( type === 'mesh' ? 'es' : 's' ) ]
|| [];

dependencies = [Link]( [Link]( function ( def, index ) {

return [Link]( type, index );

} ) );

[Link]( type, dependencies );

return dependencies;

};

/**
* Specification:
[Link]
s-and-buffer-views
* @param {number} bufferIndex
* @return {Promise<ArrayBuffer>}
*/
[Link] = function ( bufferIndex ) {

var bufferDef = [Link][ bufferIndex ];


var loader = [Link];

if ( [Link] && [Link] !== 'arraybuffer' ) {

throw new Error( '[Link]: ' + [Link] + ' buffer


type is not supported.' );

// If present, GLB container is required to be the first buffer.


if ( [Link] === undefined && bufferIndex === 0 ) {

return
[Link]( [Link][ EXTENSIONS.KHR_BINARY_GLTF ].body );

var options = [Link];

return new Promise( function ( resolve, reject ) {

[Link]( resolveURL( [Link], [Link] ), resolve,


undefined, function () {

reject( new Error( '[Link]: Failed to load buffer


"' + [Link] + '".' ) );

} );

} );

};

/**
* Specification:
[Link]
s-and-buffer-views
* @param {number} bufferViewIndex
* @return {Promise<ArrayBuffer>}
*/
[Link] = function ( bufferViewIndex ) {

var bufferViewDef = [Link][ bufferViewIndex ];

return [Link]( 'buffer',


[Link] ).then( function ( buffer ) {

var byteLength = [Link] || 0;


var byteOffset = [Link] || 0;
return [Link]( byteOffset, byteOffset + byteLength );

} );

};

/**
* Specification:
[Link]
ors
* @param {number} accessorIndex
* @return {Promise<[Link]|[Link]>}
*/
[Link] = function ( accessorIndex ) {

var parser = this;


var json = [Link];

var accessorDef = [Link][ accessorIndex ];


if ( [Link] === undefined && [Link] ===
undefined ) {

// Ignore empty accessors, which may be used to declare runtime


// information about attributes coming from another source (e.g.
Draco
// compression extension).
return [Link]( null );

var pendingBufferViews = [];

if ( [Link] !== undefined ) {

[Link]( [Link]( 'bufferView',


[Link] ) );

} else {

[Link]( null );

if ( [Link] !== undefined ) {

[Link]( [Link]( 'bufferView',


[Link] ) );
[Link]( [Link]( 'bufferView',
[Link] ) );

return [Link]( pendingBufferViews ).then( function ( bufferViews )


{

var bufferView = bufferViews[ 0 ];

var itemSize = WEBGL_TYPE_SIZES[ [Link] ];


var TypedArray = WEBGL_COMPONENT_TYPES[ [Link]
];

// For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.


var elementBytes = TypedArray.BYTES_PER_ELEMENT;
var itemBytes = elementBytes * itemSize;
var byteOffset = [Link] || 0;
var byteStride = [Link] !== undefined ?
[Link][ [Link] ].byteStride : undefined;
var normalized = [Link] === true;
var array, bufferAttribute;

// The buffer is not interleaved if the stride is the item size


in bytes.
if ( byteStride && byteStride !== itemBytes ) {

// Each "slice" of the buffer, as defined by 'count'


elements of 'byteStride' bytes, gets its own InterleavedBuffer
// This makes sure that [Link] reflects [Link]
properly
var ibSlice = [Link]( byteOffset / byteStride );
var ibCacheKey = 'InterleavedBuffer:' +
[Link] + ':' + [Link] + ':' + ibSlice + ':' +
[Link];
var ib = [Link]( ibCacheKey );

if ( ! ib ) {

array = new TypedArray( bufferView, ibSlice *


byteStride, [Link] * byteStride / elementBytes );

// Integer parameters to IB/IBA are in array


elements, not bytes.
ib = new [Link]( array, byteStride /
elementBytes );

[Link]( ibCacheKey, ib );

bufferAttribute = new [Link]( ib,


itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );

} else {

if ( bufferView === null ) {

array = new TypedArray( [Link] *


itemSize );

} else {

array = new TypedArray( bufferView, byteOffset,


[Link] * itemSize );

bufferAttribute = new [Link]( array,


itemSize, normalized );

//
[Link]
-accessors
if ( [Link] !== undefined ) {

var itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;


var TypedArrayIndices =
WEBGL_COMPONENT_TYPES[ [Link] ];

var byteOffsetIndices =
[Link] || 0;
var byteOffsetValues = [Link]
|| 0;

var sparseIndices = new


TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, [Link] *
itemSizeIndices );
var sparseValues = new TypedArray( bufferViews[ 2 ],
byteOffsetValues, [Link] * itemSize );

if ( bufferView !== null ) {

// Avoid modifying the original ArrayBuffer, if the


bufferView wasn't initialized with zeroes.
bufferAttribute = new
[Link]( [Link](), [Link],
[Link] );

for ( var i = 0, il = [Link]; i < il; i ++ )


{

var index = sparseIndices[ i ];

[Link]( index, sparseValues[ i *


itemSize ] );
if ( itemSize >= 2 ) [Link]( index,
sparseValues[ i * itemSize + 1 ] );
if ( itemSize >= 3 ) [Link]( index,
sparseValues[ i * itemSize + 2 ] );
if ( itemSize >= 4 ) [Link]( index,
sparseValues[ i * itemSize + 3 ] );
if ( itemSize >= 5 ) throw new
Error( '[Link]: Unsupported itemSize in sparse BufferAttribute.' );

return bufferAttribute;

} );

};

/**
* Specification:
[Link]
* @param {number} textureIndex
* @return {Promise<[Link]>}
*/
[Link] = function ( textureIndex ) {

var parser = this;


var json = [Link];
var options = [Link];
var textureLoader = [Link];

var URL = [Link] || [Link];

var textureDef = [Link][ textureIndex ];

var textureExtensions = [Link] || {};

var source;
if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {

source =
[Link][ textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].source ];

} else {

source = [Link][ [Link] ];

var sourceURI = [Link];


var isObjectURL = false;

if ( [Link] !== undefined ) {

// Load binary image data from bufferView, if provided.

sourceURI = [Link]( 'bufferView', [Link]


).then( function ( bufferView ) {

isObjectURL = true;
var blob = new Blob( [ bufferView ], { type:
[Link] } );
sourceURI = [Link]( blob );
return sourceURI;

} );

return [Link]( sourceURI ).then( function ( sourceURI ) {

// Load Texture resource.

var loader = [Link]( sourceURI );

if ( ! loader ) {

loader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]


?
[Link][ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader
: textureLoader;

return new Promise( function ( resolve, reject ) {

var onLoad = resolve;

if ( [Link] === true ) {

onLoad = function ( imageBitmap ) {

resolve( new [Link]( imageBitmap )


);

};
}

[Link]( resolveURL( sourceURI, [Link] ), onLoad,


undefined, reject );

} );

} ).then( function ( texture ) {

// Clean up resources and configure Texture.

if ( isObjectURL === true ) {

[Link]( sourceURI );

[Link] = false;

if ( [Link] ) [Link] = [Link];

// Ignore unknown mime types, like DDS files.


if ( [Link] in MIME_TYPE_FORMATS ) {

[Link] = MIME_TYPE_FORMATS[ [Link] ];

var samplers = [Link] || {};


var sampler = samplers[ [Link] ] || {};

[Link] = WEBGL_FILTERS[ [Link] ] ||


[Link];
[Link] = WEBGL_FILTERS[ [Link] ] ||
[Link];
[Link] = WEBGL_WRAPPINGS[ [Link] ] ||
[Link];
[Link] = WEBGL_WRAPPINGS[ [Link] ] ||
[Link];

[Link]( texture, {
type: 'textures',
index: textureIndex
} );

return texture;

} );

};

/**
* Asynchronously assigns a texture to the given material parameters.
* @param {Object} materialParams
* @param {string} mapName
* @param {Object} mapDef
* @return {Promise}
*/
[Link] = function ( materialParams, mapName,
mapDef ) {

var parser = this;

return [Link]( 'texture', [Link] ).then( function


( texture ) {

if ( ! [Link] ) {

switch ( mapName ) {

case 'aoMap':
case 'emissiveMap':
case 'metalnessMap':
case 'normalMap':
case 'roughnessMap':
[Link] = [Link];
break;

// Materials sample aoMap from UV set 1 and other maps from UV


set 0 - this can't be configured
// However, we will copy UV set 0 to UV set 1 on demand for aoMap
if ( [Link] !== undefined && [Link] != 0 && ! (
mapName === 'aoMap' && [Link] == 1 ) ) {

[Link]( '[Link]: Custom UV set ' +


[Link] + ' for texture ' + mapName + ' not yet supported.' );

if ( [Link][ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {

var transform = [Link] !== undefined ?


[Link][ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;

if ( transform ) {

var gltfReference =
[Link]( texture );
texture =
[Link][ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture,
transform );
[Link]( texture, gltfReference );

materialParams[ mapName ] = texture;

} );

};
/**
* 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.
*/
[Link] = function ( mesh ) {

var geometry = [Link];


var material = [Link];

var useVertexTangents = [Link] !== undefined;


var useVertexColors = [Link] !== undefined;
var useFlatShading = [Link] === undefined;
var useSkinning = [Link] === true;
var useMorphTargets = [Link]( [Link] ).length >
0;
var useMorphNormals = useMorphTargets &&
[Link] !== undefined;

if ( [Link] ) {

var cacheKey = 'PointsMaterial:' + [Link];

var pointsMaterial = [Link]( cacheKey );

if ( ! pointsMaterial ) {

pointsMaterial = new [Link]();


[Link]( pointsMaterial,
material );
[Link]( [Link] );
[Link] = [Link];
[Link] = false; // glTF spec says
points should be 1px

[Link]( cacheKey, pointsMaterial );

material = pointsMaterial;

} else if ( [Link] ) {

var cacheKey = 'LineBasicMaterial:' + [Link];

var lineMaterial = [Link]( cacheKey );

if ( ! lineMaterial ) {

lineMaterial = new [Link]();


[Link]( lineMaterial,
material );
[Link]( [Link] );

[Link]( cacheKey, lineMaterial );


}

material = lineMaterial;

// Clone the material if it will be modified


if ( useVertexTangents || useVertexColors || useFlatShading ||
useSkinning || useMorphTargets ) {

var cacheKey = 'ClonedMaterial:' + [Link] + ':';

if ( [Link] ) 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 = [Link]( cacheKey );

if ( ! cachedMaterial ) {

cachedMaterial = [Link]();

if ( useSkinning ) [Link] = true;


if ( useVertexTangents ) [Link] =
true;
if ( useVertexColors ) [Link] = true;
if ( useFlatShading ) [Link] = true;
if ( useMorphTargets ) [Link] = true;
if ( useMorphNormals ) [Link] = true;

[Link]( cacheKey, cachedMaterial );

[Link]( cachedMaterial,
[Link]( material ) );

material = cachedMaterial;

// workarounds for mesh and geometry

if ( [Link] && [Link].uv2 === undefined &&


[Link] !== undefined ) {

[Link]( 'uv2', [Link] );

// [Link]
507003995
if ( [Link] && ! useVertexTangents ) {
[Link].y = - [Link].y;

if ( [Link] && ! useVertexTangents ) {

[Link].y = -
[Link].y;

[Link] = material;

};

[Link] = function ( /* materialIndex */ ) {

return [Link];

};

/**
* Specification:
[Link]
als
* @param {number} materialIndex
* @return {Promise<[Link]>}
*/
[Link] = function ( materialIndex ) {

var parser = this;


var json = [Link];
var extensions = [Link];
var materialDef = [Link][ materialIndex ];

var materialType;
var materialParams = {};
var materialExtensions = [Link] || {};

var pending = [];

if
( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {

var sgExtension =
extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];
materialType = [Link]();
[Link]( [Link]( materialParams,
materialDef, parser ) );

} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {

var kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];


materialType = [Link]();
[Link]( [Link]( materialParams,
materialDef, parser ) );

} else {
// Specification:
//
[Link]
roughness-material

var metallicRoughness = [Link] || {};

[Link] = new [Link]( 1.0, 1.0, 1.0 );


[Link] = 1.0;

if ( [Link]( [Link] ) ) {

var array = [Link];

[Link]( array );
[Link] = array[ 3 ];

if ( [Link] !== undefined ) {

[Link]( [Link]( materialParams, 'map',


[Link] ) );

[Link] = [Link] !==


undefined ? [Link] : 1.0;
[Link] = [Link] !==
undefined ? [Link] : 1.0;

if ( [Link] !== undefined ) {

[Link]( [Link]( materialParams,


'metalnessMap', [Link] ) );
[Link]( [Link]( materialParams,
'roughnessMap', [Link] ) );

materialType = this._invokeOne( function ( ext ) {

return [Link] &&


[Link]( materialIndex );

} );

[Link]( this._invokeAll( function ( ext ) {

return [Link] &&


[Link]( materialIndex, materialParams );

} ) );

if ( [Link] === true ) {

[Link] = [Link];
}

var alphaMode = [Link] || ALPHA_MODES.OPAQUE;

if ( alphaMode === ALPHA_MODES.BLEND ) {

[Link] = true;

// See: [Link]
[Link] = false;

} else {

[Link] = false;

if ( alphaMode === ALPHA_MODES.MASK ) {

[Link] = [Link] !==


undefined ? [Link] : 0.5;

if ( [Link] !== undefined && materialType !==


[Link] ) {

[Link]( [Link]( materialParams, 'normalMap',


[Link] ) );

[Link] = new THREE.Vector2( 1, 1 );

if ( [Link] !== undefined ) {

[Link]( [Link],
[Link] );

if ( [Link] !== undefined && materialType !==


[Link] ) {

[Link]( [Link]( materialParams, 'aoMap',


[Link] ) );

if ( [Link] !== undefined ) {

[Link] =
[Link];

if ( [Link] !== undefined && materialType !==


[Link] ) {

[Link] = new
[Link]().fromArray( [Link] );

if ( [Link] !== undefined && materialType !==


[Link] ) {

[Link]( [Link]( materialParams,


'emissiveMap', [Link] ) );

return [Link]( pending ).then( function () {

var material;

if ( materialType === GLTFMeshStandardSGMaterial ) {

material =
extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( mate
rialParams );

} else {

material = new materialType( materialParams );

if ( [Link] ) [Link] = [Link];

// baseColorTexture, emissiveTexture, and


specularGlossinessTexture use sRGB encoding.
if ( [Link] ) [Link] = [Link];
if ( [Link] ) [Link] =
[Link];

assignExtrasToUserData( material, materialDef );

[Link]( material, { type: 'materials', index:


materialIndex } );

if ( [Link] )
addUnknownExtensionsToUserData( extensions, material, materialDef );

return material;

} );

};

/**
* @param {[Link]} geometry
* @param {[Link]} primitiveDef
* @param {GLTFParser} parser
*/
function computeBounds( geometry, primitiveDef, parser ) {
var attributes = [Link];

var box = new THREE.Box3();

if ( [Link] !== undefined ) {

var accessor = [Link][ [Link] ];

var min = [Link];


var max = [Link];

// glTF requires 'min' and 'max', but VRM (which extends glTF)
currently ignores that requirement.

if ( min !== undefined && max !== undefined ) {

[Link](
new THREE.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
new THREE.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) );

} else {

[Link]( '[Link]: Missing min/max properties


for accessor POSITION.' );

return;

} else {

return;

var targets = [Link];

if ( targets !== undefined ) {

var maxDisplacement = new THREE.Vector3();


var vector = new THREE.Vector3();

for ( var i = 0, il = [Link]; i < il; i ++ ) {

var target = targets[ i ];

if ( [Link] !== undefined ) {

var accessor = [Link][ [Link]


];
var min = [Link];
var max = [Link];

// glTF requires 'min' and 'max', but VRM (which


extends glTF) currently ignores that requirement.

if ( min !== undefined && max !== undefined ) {


// we need to get max of absolute components
because target weight is [-1,1]
[Link]( [Link]( [Link]( min[ 0 ] ),
[Link]( max[ 0 ] ) ) );
[Link]( [Link]( [Link]( min[ 1 ] ),
[Link]( max[ 1 ] ) ) );
[Link]( [Link]( [Link]( min[ 2 ] ),
[Link]( max[ 2 ] ) ) );

// Note: this assumes that the sum of all


weights is at most 1. This isn't quite correct - it's more conservative
// to assume that each target can have a max
weight of 1. However, for some use cases - notably, when morph targets
// are used to implement key-frame animations
and as such only two are active at a time - this results in very large
// boxes. So for now we make a box that's
sometimes a touch too small but is hopefully mostly of reasonable size.
[Link]( vector );

} else {

[Link]( '[Link]: Missing


min/max properties for accessor POSITION.' );

// As per comment above this box isn't conservative, but has a


reasonable size for a very large number of morph targets.
[Link]( maxDisplacement );

[Link] = box;

var sphere = new [Link]();

[Link]( [Link] );
[Link] = [Link]( [Link] ) / 2;

[Link] = sphere;

/**
* @param {[Link]} geometry
* @param {[Link]} primitiveDef
* @param {GLTFParser} parser
* @return {Promise<[Link]>}
*/
function addPrimitiveAttributes( geometry, primitiveDef, parser ) {

var attributes = [Link];

var pending = [];


function assignAttributeAccessor( accessorIndex, attributeName ) {

return [Link]( 'accessor', accessorIndex )


.then( function ( accessor ) {

[Link]( attributeName, accessor );

} );

for ( var gltfAttributeName in attributes ) {

var threeAttributeName = ATTRIBUTES[ gltfAttributeName ] ||


[Link]();

// Skip attributes already provided by e.g. Draco extension.


if ( threeAttributeName in [Link] ) continue;

[Link]( assignAttributeAccessor( attributes[ gltfAttributeName ],


threeAttributeName ) );

if ( [Link] !== undefined && ! [Link] ) {

var accessor = [Link]( 'accessor',


[Link] ).then( function ( accessor ) {

[Link]( accessor );

} );

[Link]( accessor );

assignExtrasToUserData( geometry, primitiveDef );

computeBounds( geometry, primitiveDef, parser );

return [Link]( pending ).then( function () {

return [Link] !== undefined


? addMorphTargets( geometry, [Link], parser )
: geometry;

} );

/**
* @param {[Link]} geometry
* @param {Number} drawMode
* @return {[Link]}
*/
function toTrianglesDrawMode( geometry, drawMode ) {
var index = [Link]();

// generate index if not present

if ( index === null ) {

var indices = [];

var position = [Link]( 'position' );

if ( position !== undefined ) {

for ( var i = 0; i < [Link]; i ++ ) {

[Link]( i );

[Link]( indices );
index = [Link]();

} else {

[Link]( '[Link]():
Undefined position attribute. Processing not possible.' );
return geometry;

//

var numberOfTriangles = [Link] - 2;


var newIndices = [];

if ( drawMode === [Link] ) {

// gl.TRIANGLE_FAN

for ( var i = 1; i <= numberOfTriangles; i ++ ) {

[Link]( [Link]( 0 ) );
[Link]( [Link]( i ) );
[Link]( [Link]( i + 1 ) );

} else {

// gl.TRIANGLE_STRIP

for ( var i = 0; i < numberOfTriangles; i ++ ) {

if ( i % 2 === 0 ) {

[Link]( [Link]( i ) );
[Link]( [Link]( i + 1 ) );
[Link]( [Link]( i + 2 ) );
} else {

[Link]( [Link]( i + 2 ) );
[Link]( [Link]( i + 1 ) );
[Link]( [Link]( i ) );

if ( ( [Link] / 3 ) !== numberOfTriangles ) {

[Link]( '[Link](): Unable to


generate correct amount of triangles.' );

// build final geometry

var newGeometry = [Link]();


[Link]( newIndices );

return newGeometry;

/**
* Specification:
[Link]
ry
*
* Creates BufferGeometries from primitives.
*
* @param {Array<[Link]>} primitives
* @return {Promise<Array<[Link]>>}
*/
[Link] = function ( primitives ) {

var parser = this;


var extensions = [Link];
var cache = [Link];

function createDracoPrimitive( primitive ) {

return extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]


.decodePrimitive( primitive, parser )
.then( function ( geometry ) {

return addPrimitiveAttributes( geometry, primitive,


parser );

} );

}
var pending = [];

for ( var i = 0, il = [Link]; i < il; i ++ ) {

var primitive = primitives[ i ];


var cacheKey = createPrimitiveKey( primitive );

// See if we've already created this geometry


var cached = cache[ cacheKey ];

if ( cached ) {

// Use the cached geometry if it exists


[Link]( [Link] );

} else {

var geometryPromise;

if ( [Link] &&
[Link][ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {

// Use DRACO geometry if available


geometryPromise = createDracoPrimitive( primitive );

} else {

// Otherwise create a new geometry


geometryPromise = addPrimitiveAttributes( new
[Link](), primitive, parser );

// Cache this geometry


cache[ cacheKey ] = { primitive: primitive, promise:
geometryPromise };

[Link]( geometryPromise );

return [Link]( pending );

};

/**
* Specification:
[Link]
* @param {number} meshIndex
* @return {Promise<[Link]|[Link]|[Link]>}
*/
[Link] = function ( meshIndex ) {

var parser = this;


var json = [Link];

var meshDef = [Link][ meshIndex ];


var primitives = [Link];

var pending = [];

for ( var i = 0, il = [Link]; i < il; i ++ ) {

var material = primitives[ i ].material === undefined


? createDefaultMaterial( [Link] )
: [Link]( 'material',
primitives[ i ].material );

[Link]( material );

[Link]( [Link]( primitives ) );

return [Link]( pending ).then( function ( results ) {

var materials = [Link]( 0, [Link] - 1 );


var geometries = results[ [Link] - 1 ];

var meshes = [];

for ( var i = 0, il = [Link]; i < il; i ++ ) {

var geometry = geometries[ i ];


var primitive = primitives[ i ];

// 1. create Mesh

var mesh;

var material = materials[ i ];

if ( [Link] === WEBGL_CONSTANTS.TRIANGLES ||


[Link] === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
[Link] === WEBGL_CONSTANTS.TRIANGLE_FAN ||
[Link] === undefined ) {

// .isSkinnedMesh isn't in glTF spec. See .markDefs()


mesh = [Link] === true
? new [Link]( geometry, material )
: new [Link]( geometry, material );

if ( [Link] === true && !


[Link] ) {

// 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
[Link]();

if ( [Link] ===
WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
[Link] =
toTrianglesDrawMode( [Link], [Link] );

} else if ( [Link] ===


WEBGL_CONSTANTS.TRIANGLE_FAN ) {

[Link] =
toTrianglesDrawMode( [Link], [Link] );

} else if ( [Link] === WEBGL_CONSTANTS.LINES ) {

mesh = new [Link]( geometry, material );

} else if ( [Link] === WEBGL_CONSTANTS.LINE_STRIP )


{

mesh = new [Link]( geometry, material );

} else if ( [Link] === WEBGL_CONSTANTS.LINE_LOOP )


{

mesh = new [Link]( geometry, material );

} else if ( [Link] === WEBGL_CONSTANTS.POINTS ) {

mesh = new [Link]( geometry, material );

} else {

throw new Error( '[Link]: Primitive mode


unsupported: ' + [Link] );

if ( [Link]( [Link] ).length >


0 ) {

updateMorphTargets( mesh, meshDef );

[Link] = [Link] || ( 'mesh_' + meshIndex );

if ( [Link] > 1 ) [Link] += '_' + i;

assignExtrasToUserData( mesh, meshDef );

[Link]( mesh );

[Link]( mesh );

if ( [Link] === 1 ) {

return meshes[ 0 ];
}

var group = new [Link]();

for ( var i = 0, il = [Link]; i < il; i ++ ) {

[Link]( meshes[ i ] );

return group;

} );

};

/**
* Specification:
[Link]
* @param {number} cameraIndex
* @return {Promise<[Link]>}
*/
[Link] = function ( cameraIndex ) {

var camera;
var cameraDef = [Link][ cameraIndex ];
var params = cameraDef[ [Link] ];

if ( ! params ) {

[Link]( '[Link]: Missing camera parameters.' );


return;

if ( [Link] === 'perspective' ) {

camera = new
[Link]( [Link]( [Link] ),
[Link] || 1, [Link] || 1, [Link] || 2e6 );

} else if ( [Link] === 'orthographic' ) {

camera = new [Link]( - [Link],


[Link], [Link], - [Link], [Link], [Link] );

if ( [Link] ) [Link] = [Link];

assignExtrasToUserData( camera, cameraDef );

return [Link]( camera );

};

/**
* Specification:
[Link]
* @param {number} skinIndex
* @return {Promise<Object>}
*/
[Link] = function ( skinIndex ) {

var skinDef = [Link][ skinIndex ];

var skinEntry = { joints: [Link] };

if ( [Link] === undefined ) {

return [Link]( skinEntry );

return [Link]( 'accessor',


[Link] ).then( function ( accessor ) {

[Link] = accessor;

return skinEntry;

} );

};

/**
* Specification:
[Link]
* @param {number} animationIndex
* @return {Promise<[Link]>}
*/
[Link] = function ( animationIndex ) {

var json = [Link];

var animationDef = [Link][ animationIndex ];

var pendingNodes = [];


var pendingInputAccessors = [];
var pendingOutputAccessors = [];
var pendingSamplers = [];
var pendingTargets = [];

for ( var i = 0, il = [Link]; i < il; i ++ ) {

var channel = [Link][ i ];


var sampler = [Link][ [Link] ];
var target = [Link];
var name = [Link] !== undefined ? [Link] :
[Link]; // NOTE: [Link] is deprecated.
var input = [Link] !== undefined ?
[Link][ [Link] ] : [Link];
var output = [Link] !== undefined ?
[Link][ [Link] ] : [Link];

[Link]( [Link]( 'node', name ) );


[Link]( [Link]( 'accessor', input
) );
[Link]( [Link]( 'accessor',
output ) );
[Link]( sampler );
[Link]( target );

return [Link]( [

[Link]( pendingNodes ),
[Link]( pendingInputAccessors ),
[Link]( pendingOutputAccessors ),
[Link]( pendingSamplers ),
[Link]( pendingTargets )

] ).then( function ( dependencies ) {

var nodes = dependencies[ 0 ];


var inputAccessors = dependencies[ 1 ];
var outputAccessors = dependencies[ 2 ];
var samplers = dependencies[ 3 ];
var targets = dependencies[ 4 ];

var tracks = [];

for ( var i = 0, il = [Link]; i < il; i ++ ) {

var node = nodes[ i ];


var inputAccessor = inputAccessors[ i ];
var outputAccessor = outputAccessors[ i ];
var sampler = samplers[ i ];
var target = targets[ i ];

if ( node === undefined ) continue;

[Link]();
[Link] = true;

var TypedKeyframeTrack;

switch ( PATH_PROPERTIES[ [Link] ] ) {

case PATH_PROPERTIES.weights:

TypedKeyframeTrack = [Link];
break;

case PATH_PROPERTIES.rotation:

TypedKeyframeTrack =
[Link];
break;

case PATH_PROPERTIES.position:
case PATH_PROPERTIES.scale:
default:

TypedKeyframeTrack = [Link];
break;
}

var targetName = [Link] ? [Link] : [Link];

var interpolation = [Link] !== undefined ?


INTERPOLATION[ [Link] ] : [Link];

var targetNames = [];

if ( PATH_PROPERTIES[ [Link] ] ===


PATH_PROPERTIES.weights ) {

// Node may be a [Link] (glTF mesh with several


primitives) or a [Link].
[Link]( function ( object ) {

if ( [Link] === true &&


[Link] ) {

[Link]( [Link] ?
[Link] : [Link] );

} );

} else {

[Link]( targetName );

var outputArray = [Link];

if ( [Link] ) {

var scale;

if ( [Link] === Int8Array ) {

scale = 1 / 127;

} else if ( [Link] === Uint8Array )


{

scale = 1 / 255;

} else if ( [Link] == Int16Array ) {

scale = 1 / 32767;

} else if ( [Link] === Uint16Array )


{

scale = 1 / 65535;

} else {
throw new Error( '[Link]: Unsupported
output accessor component type.' );

var scaled = new Float32Array( [Link] );

for ( var j = 0, jl = [Link]; j < jl; j +


+ ) {

scaled[ j ] = outputArray[ j ] * scale;

outputArray = scaled;

for ( var j = 0, jl = [Link]; j < jl; j ++ ) {

var track = new TypedKeyframeTrack(


targetNames[ j ] + '.' +
PATH_PROPERTIES[ [Link] ],
[Link],
outputArray,
interpolation
);

// Override interpolation with custom factory method.


if ( [Link] === 'CUBICSPLINE' ) {

[Link] = function
InterpolantFactoryMethodGLTFCubicSpline( result ) {

// A CUBICSPLINE keyframe in glTF has


three output values for each input value,
// representing inTangent, splineVertex,
and outTangent. As a result, [Link]()
// must be divided by three to get the
interpolant's sampleSize argument.

return new
GLTFCubicSplineInterpolant( [Link], [Link], [Link]() / 3,
result );

};

// Mark as CUBICSPLINE.
`[Link]()` doesn't support custom interpolants.

[Link] = true;

[Link]( track );

}
var name = [Link] ? [Link] : 'animation_' +
animationIndex;

return new [Link]( name, undefined, tracks );

} );

};

/**
* Specification:
[Link]
hierarchy
* @param {number} nodeIndex
* @return {Promise<THREE.Object3D>}
*/
[Link] = function ( nodeIndex ) {

var json = [Link];


var extensions = [Link];
var parser = this;

var meshReferences = [Link];


var meshUses = [Link];

var nodeDef = [Link][ nodeIndex ];

return ( function () {

var pending = [];

if ( [Link] !== undefined ) {

[Link]( [Link]( 'mesh',


[Link] ).then( function ( mesh ) {

var node;

if ( meshReferences[ [Link] ] > 1 ) {

var instanceNum = meshUses[ [Link] ] ++;

node = [Link]();
[Link] += '_instance_' + instanceNum;

} else {

node = mesh;

// if weights are provided on the node, override


weights on the mesh.
if ( [Link] !== undefined ) {

[Link]( function ( o ) {

if ( ! [Link] ) return;
for ( var i = 0, il =
[Link]; i < il; i ++ ) {

[Link][ i ] =
[Link][ i ];

} );

return node;

} ) );

if ( [Link] !== undefined ) {

[Link]( [Link]( 'camera',


[Link] ) );

if ( [Link]
&& [Link][ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ]
&&
[Link][ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light !== undefined ) {

[Link]( [Link]( 'light',


[Link][ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light ) );

return [Link]( pending );

}() ).then( function ( objects ) {

var node;

// .isBone isn't in glTF spec. See .markDefs


if ( [Link] === true ) {

node = new [Link]();

} else if ( [Link] > 1 ) {

node = new [Link]();

} else if ( [Link] === 1 ) {

node = objects[ 0 ];

} else {

node = new THREE.Object3D();


}

if ( node !== objects[ 0 ] ) {

for ( var i = 0, il = [Link]; i < il; i ++ ) {

[Link]( objects[ i ] );

if ( [Link] ) {

[Link] = [Link];
[Link] =
[Link]( [Link] );

assignExtrasToUserData( node, nodeDef );

if ( [Link] )
addUnknownExtensionsToUserData( extensions, node, nodeDef );

if ( [Link] !== undefined ) {

var matrix = new THREE.Matrix4();


[Link]( [Link] );
node.applyMatrix4( matrix );

} else {

if ( [Link] !== undefined ) {

[Link]( [Link] );

if ( [Link] !== undefined ) {

[Link]( [Link] );

if ( [Link] !== undefined ) {

[Link]( [Link] );

[Link]( node, { type: 'nodes', index:


nodeIndex } );

return node;

} );
};

/**
* Specification:
[Link]
* @param {number} sceneIndex
* @return {Promise<[Link]>}
*/
[Link] = function () {

// scene node hierachy builder

function buildNodeHierachy( nodeId, parentObject, json, parser ) {

var nodeDef = [Link][ nodeId ];

return [Link]( 'node', nodeId ).then( function


( node ) {

if ( [Link] === undefined ) return node;

// build skeleton here as well

var skinEntry;

return [Link]( 'skin',


[Link] ).then( function ( skin ) {

skinEntry = skin;

var pendingJoints = [];

for ( var i = 0, il = [Link]; i <


il; i ++ ) {

[Link]( [Link]( 'node', [Link][ i ] ) );

return [Link]( pendingJoints );

} ).then( function ( jointNodes ) {

[Link]( function ( mesh ) {

if ( ! [Link] ) return;

var bones = [];


var boneInverses = [];

for ( var j = 0, jl = [Link]; j <


jl; j ++ ) {

var jointNode = jointNodes[ j ];

if ( jointNode ) {
[Link]( jointNode );

var mat = new THREE.Matrix4();

if
( [Link] !== undefined ) {

[Link]( [Link], j * 16 );

[Link]( mat );

} else {

[Link]( '[Link]:
Joint "%s" could not be found.', [Link][ j ] );

[Link]( new [Link]( bones,


boneInverses ), [Link] );

} );

return node;

} );

} ).then( function ( node ) {

// build node hierachy

[Link]( node );

var pending = [];

if ( [Link] ) {

var children = [Link];

for ( var i = 0, il = [Link]; i < il; i ++ )


{

var child = children[ i ];


[Link]( buildNodeHierachy( child, node,
json, parser ) );

return [Link]( pending );

} );
}

return function loadScene( sceneIndex ) {

var json = [Link];


var extensions = [Link];
var sceneDef = [Link][ sceneIndex ];
var parser = this;

// Loader returns Group, not Scene.


// See:
[Link]
var scene = new [Link]();
if ( [Link] ) [Link] = [Link];

assignExtrasToUserData( scene, sceneDef );

if ( [Link] )
addUnknownExtensionsToUserData( extensions, scene, sceneDef );

var nodeIds = [Link] || [];

var pending = [];

for ( var i = 0, il = [Link]; i < il; i ++ ) {

[Link]( buildNodeHierachy( nodeIds[ i ], scene, json,


parser ) );

return [Link]( pending ).then( function () {

return scene;

} );

};

}();

return GLTFLoader;

} )();

You might also like