GLTFLoader.js 7.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/**
 * @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' );

54 55 56 57
		var library = {
			buffers: {},
			bufferViews: {},
			accessors: {},
58 59
			textures: {},
			materials: {},
60 61 62 63 64
			meshes: {},
			nodes: {},
			scenes: {}
		};

65 66 67 68 69 70 71 72 73 74 75 76 77 78
		// 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 ) {

79
					library.buffers[ bufferId ] = stringToArrayBuffer( buffer.uri.substr( header.length ) );
80 81 82 83 84 85 86 87 88 89 90 91 92 93

				}

			}

		}

		// buffer views

		var bufferViews = json.bufferViews;

		for ( var bufferViewId in bufferViews ) {

			var bufferView = bufferViews[ bufferViewId ];
94
			var arraybuffer = library.buffers[ bufferView.buffer ];
95

96
			library.bufferViews[ bufferViewId ] = arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength );
97 98 99 100 101 102 103 104 105 106

		}

		// accessors

		var COMPONENT_TYPES = {
			5120: Int8Array,
			5121: Uint8Array,
			5122: Int16Array,
			5123: Uint16Array,
107
			5125: Uint32Array,
108 109 110 111 112 113 114 115 116 117 118 119 120 121
			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 ];

122
			var arraybuffer = library.bufferViews[ accessor.bufferView ];
123 124 125 126 127
			var itemSize = TYPE_SIZES[ accessor.type ];
			var TypedArray = COMPONENT_TYPES[ accessor.componentType ];

			var array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize );

128
			library.accessors[ accessorId ] = new THREE.BufferAttribute( array, itemSize );
129 130 131

		}

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
		// 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;

M
Mr.doob 已提交
196
			if ( Array.isArray( values.diffuse ) ) {
197

M
Mr.doob 已提交
198
					_material.color.fromArray( values.diffuse );
199

M
Mr.doob 已提交
200
			} else if ( typeof( values.diffuse ) === 'string' ) {
201

M
Mr.doob 已提交
202
					_material.map = library.textures[ values.diffuse ];
203 204 205

			}

206 207 208 209 210 211
			if ( typeof( values.bump ) === 'string' ) {

					_material.bumpMap = library.textures[ values.bump ];

			}

M
Mr.doob 已提交
212 213 214 215 216 217
			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;


218 219 220 221
			library.materials[ materialId ] = _material;

		}

222 223 224 225 226 227 228 229
		// meshes

		var meshes = json.meshes;

		for ( var meshId in meshes ) {

			var mesh = meshes[ meshId ];

230 231
			var group = new THREE.Group();
			group.name = mesh.name;
232 233 234

			var primitives = mesh.primitives;

235
			for ( var i = 0; i < primitives.length; i ++ ) {
236

237
				var primitive = primitives[ i ];
238 239
				var attributes = primitive.attributes;

240 241
				var geometry = new THREE.BufferGeometry();

242 243
				if ( primitive.indices ) {

244
					geometry.setIndex( library.accessors[ primitive.indices ] );
245 246 247 248 249 250

				}

				for ( var attributeId in attributes ) {

					var attribute = attributes[ attributeId ];
251
					var bufferAttribute = library.accessors[ attribute ];
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

					switch ( attributeId ) {

						case 'POSITION':
							geometry.addAttribute( 'position', bufferAttribute );
							break;

						case 'NORMAL':
							geometry.addAttribute( 'normal', bufferAttribute );
							break;

						case 'TEXCOORD_0':
							geometry.addAttribute( 'uv', bufferAttribute );
							break;

					}

				}

271 272 273
				var material = library.materials[ primitive.material ];

				group.add( new THREE.Mesh( geometry, material ) );
274

275 276
			}

277
			library.meshes[ meshId ] = group;
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

		}

		// 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 ];
323
					var group = library.meshes[ meshId ];
324

325
					object.add( group.clone() );
326 327 328 329 330

				}

			}

331
			library.nodes[ nodeId ] = object;
332 333 334 335 336 337 338 339 340 341 342

		}

		for ( var nodeId in nodes ) {

			var node = nodes[ nodeId ];

			for ( var i = 0; i < node.children.length; i ++ ) {

				var child = node.children[ i ];

343
				library.nodes[ nodeId ].add( library.nodes[ child ] );
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360

			}

		}

		// 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 ];
361
				container.add( library.nodes[ node ] );
362 363 364

			}

365
			library.scenes[ sceneId ] = container;
366 367 368 369 370 371 372

		}

		console.timeEnd( 'GLTFLoader' );

		return {

373
			scene: library.scenes[ json.scene ]
374 375 376 377 378 379

		};

	}

};