123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /**
- * @author mrdoob / http://mrdoob.com/
- */
- THREE.GLTFLoader = function ( manager ) {
- this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
- };
- THREE.GLTFLoader.prototype = {
- constructor: THREE.GLTFLoader,
- load: function ( url, onLoad, onProgress, onError ) {
- var scope = this;
- var loader = new THREE.XHRLoader( scope.manager );
- loader.load( url, function ( text ) {
- onLoad( scope.parse( JSON.parse( text ) ) );
- }, onProgress, onError );
- },
- setCrossOrigin: function ( value ) {
- this.crossOrigin = value;
- },
- parse: function ( json ) {
- function stringToArrayBuffer( string ) {
- var bytes = atob( string );
- var buffer = new ArrayBuffer( bytes.length );
- var bufferView = new Uint8Array( buffer );
- for ( var i = 0; i < bytes.length; i ++ ) {
- bufferView[ i ] = bytes.charCodeAt( i );
- }
- return buffer;
- }
- console.time( 'GLTFLoader' );
- var library = {
- buffers: {},
- bufferViews: {},
- accessors: {},
- textures: {},
- materials: {},
- meshes: {},
- nodes: {},
- scenes: {}
- };
- // buffers
- var buffers = json.buffers;
- for ( var bufferId in buffers ) {
- var buffer = buffers[ bufferId ];
- if ( buffer.type === 'arraybuffer' ) {
- var header = 'data:application/octet-stream;base64,';
- if ( buffer.uri.indexOf( header ) === 0 ) {
- library.buffers[ bufferId ] = stringToArrayBuffer( buffer.uri.substr( header.length ) );
- }
- }
- }
- // buffer views
- var bufferViews = json.bufferViews;
- for ( var bufferViewId in bufferViews ) {
- var bufferView = bufferViews[ bufferViewId ];
- var arraybuffer = library.buffers[ bufferView.buffer ];
- library.bufferViews[ bufferViewId ] = arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength );
- }
- // accessors
- var COMPONENT_TYPES = {
- 5120: Int8Array,
- 5121: Uint8Array,
- 5122: Int16Array,
- 5123: Uint16Array,
- 5125: Uint32Array,
- 5126: Float32Array,
- };
- var TYPE_SIZES = {
- 'SCALAR': 1, 'VEC2': 2, 'VEC3': 3, 'VEC4': 4,
- 'MAT2': 4, 'MAT3': 9, 'MAT4': 16
- };
- var accessors = json.accessors;
- for ( var accessorId in accessors ) {
- var accessor = accessors[ accessorId ];
- var arraybuffer = library.bufferViews[ accessor.bufferView ];
- var itemSize = TYPE_SIZES[ accessor.type ];
- var TypedArray = COMPONENT_TYPES[ accessor.componentType ];
- var array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize );
- library.accessors[ accessorId ] = new THREE.BufferAttribute( array, itemSize );
- }
- // textures
- var FILTERS = {
- 9728: THREE.NearestFilter,
- 9729: THREE.LinearFilter,
- 9984: THREE.NearestMipMapNearestFilter,
- 9985: THREE.LinearMipMapNearestFilter,
- 9986: THREE.NearestMipMapLinearFilter,
- 9987: THREE.LinearMipMapLinearFilter
- };
- var WRAPPINGS = {
- 33071: THREE.ClampToEdgeWrapping,
- 33648: THREE.MirroredRepeatWrapping,
- 10497: THREE.RepeatWrapping
- };
- var textures = json.textures;
- for ( var textureId in textures ) {
- var texture = textures[ textureId ];
- var _texture = new THREE.Texture();
- _texture.flipY = false;
- if ( texture.source ) {
- var source = json.images[ texture.source ];
- _texture.image = new Image();
- _texture.image.src = source.uri;
- _texture.needsUpdate = true;
- }
- if ( texture.sampler ) {
- var sampler = json.samplers[ texture.sampler ];
- _texture.magFilter = FILTERS[ sampler.magFilter ];
- _texture.minFilter = FILTERS[ sampler.minFilter ];
- _texture.wrapS = WRAPPINGS[ sampler.wrapS ];
- _texture.wrapT = WRAPPINGS[ sampler.wrapT ];
- }
- library.textures[ textureId ] = _texture;
- }
- // materials
- var materials = json.materials;
- for ( var materialId in materials ) {
- var material = materials[ materialId ];
- var _material = new THREE.MeshPhongMaterial();
- _material.name = material.name;
- var values = material.values;
- if ( Array.isArray( values.diffuse ) ) {
- _material.color.fromArray( values.diffuse );
- } else if ( typeof( values.diffuse ) === 'string' ) {
- _material.map = library.textures[ values.diffuse ];
- }
- if ( Array.isArray( values.emission ) ) _material.emissive.fromArray( values.emission );
- if ( Array.isArray( values.specular ) ) _material.specular.fromArray( values.specular );
- if ( values.shininess !== undefined ) _material.shininess = values.shininess;
- library.materials[ materialId ] = _material;
- }
- // meshes
- var meshes = json.meshes;
- for ( var meshId in meshes ) {
- var mesh = meshes[ meshId ];
- var group = new THREE.Group();
- group.name = mesh.name;
- var primitives = mesh.primitives;
- for ( var i = 0; i < primitives.length; i ++ ) {
- var primitive = primitives[ i ];
- var attributes = primitive.attributes;
- var geometry = new THREE.BufferGeometry();
- if ( primitive.indices ) {
- geometry.setIndex( library.accessors[ primitive.indices ] );
- }
- for ( var attributeId in attributes ) {
- var attribute = attributes[ attributeId ];
- var bufferAttribute = library.accessors[ attribute ];
- switch ( attributeId ) {
- case 'POSITION':
- geometry.addAttribute( 'position', bufferAttribute );
- break;
- case 'NORMAL':
- geometry.addAttribute( 'normal', bufferAttribute );
- break;
- case 'TEXCOORD_0':
- geometry.addAttribute( 'uv', bufferAttribute );
- break;
- }
- }
- var material = library.materials[ primitive.material ];
- group.add( new THREE.Mesh( geometry, material ) );
- }
- library.meshes[ meshId ] = group;
- }
- // nodes
- var nodes = json.nodes;
- var matrix = new THREE.Matrix4();
- for ( var nodeId in nodes ) {
- var node = nodes[ nodeId ];
- var object = new THREE.Group();
- object.name = node.name;
- if ( node.translation !== undefined ) {
- object.position.fromArray( node.translation );
- }
- if ( node.rotation !== undefined ) {
- object.quaternion.fromArray( node.rotation );
- }
- if ( node.scale !== undefined ) {
- object.scale.fromArray( node.scale );
- }
- if ( node.matrix !== undefined ) {
- matrix.fromArray( node.matrix );
- matrix.decompose( object.position, object.quaternion, object.scale );
- }
- if ( node.meshes !== undefined ) {
- for ( var i = 0; i < node.meshes.length; i ++ ) {
- var meshId = node.meshes[ i ];
- var group = library.meshes[ meshId ];
- object.add( group.clone() );
- }
- }
- library.nodes[ nodeId ] = object;
- }
- for ( var nodeId in nodes ) {
- var node = nodes[ nodeId ];
- for ( var i = 0; i < node.children.length; i ++ ) {
- var child = node.children[ i ];
- library.nodes[ nodeId ].add( library.nodes[ child ] );
- }
- }
- // scenes
- var scenes = json.scenes;
- for ( var sceneId in scenes ) {
- var scene = scenes[ sceneId ];
- var container = new THREE.Scene();
- for ( var i = 0; i < scene.nodes.length; i ++ ) {
- var node = scene.nodes[ i ];
- container.add( library.nodes[ node ] );
- }
- library.scenes[ sceneId ] = container;
- }
- console.timeEnd( 'GLTFLoader' );
- return {
- scene: library.scenes[ json.scene ]
- };
- }
- };
|