BinaryLoader.js 20.6 KB
Newer Older
1 2 3 4 5 6 7
/**
 * @author alteredq / http://alteredqualia.com/
 */

THREE.BinaryLoader = function ( showStatus ) {

	THREE.Loader.call( this, showStatus );
8

9 10
};

11
THREE.BinaryLoader.prototype = Object.create( THREE.Loader.prototype );
12

13 14 15
// Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
//  - binary models consist of two files: JS and BIN
//  - parameters
16
//		- url (required)
17
//		- callback (required)
18 19
//		- texturePath (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
//		- binaryPath (optional: if not specified, binary file will be assumed to be in the same folder as JS model file)
20

21 22
THREE.BinaryLoader.prototype.load = function( url, callback, texturePath, binaryPath ) {

23 24 25 26
	// todo: unify load API to for easier SceneLoader use

	texturePath = texturePath && ( typeof texturePath === "string" ) ? texturePath : this.extractUrlBase( url );
	binaryPath = binaryPath && ( typeof binaryPath === "string" ) ? binaryPath : this.extractUrlBase( url );
27 28 29 30 31

	var callbackProgress = this.showProgress ? THREE.Loader.prototype.updateProgress : null;

	this.onLoadStart();

32
	// #1 load JS part via web worker
33

34
	this.loadAjaxJSON( this, url, callback, texturePath, binaryPath, callbackProgress );
35

36
};
37

M
Mr.doob 已提交
38
THREE.BinaryLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, binaryPath, callbackProgress ) {
39

40
	var xhr = new XMLHttpRequest();
41

M
Mr.doob 已提交
42
	xhr.onreadystatechange = function () {
43 44

		if ( xhr.readyState == 4 ) {
45

46
			if ( xhr.status == 200 || xhr.status == 0 ) {
47

M
Mr.doob 已提交
48 49
				var json = JSON.parse( xhr.responseText );
				context.loadAjaxBuffers( json, callback, binaryPath, texturePath, callbackProgress );
50

51 52
			} else {

M
Mr.doob 已提交
53
				console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
54 55 56 57 58 59 60 61 62 63 64 65

			}

		}

	};

	xhr.open( "GET", url, true );
	xhr.send( null );

};

M
Mr.doob 已提交
66
THREE.BinaryLoader.prototype.loadAjaxBuffers = function ( json, callback, binaryPath, texturePath, callbackProgress ) {
67

68
	var xhr = new XMLHttpRequest(),
69
		url = binaryPath + "/" + json.buffers;
70

71
	var length = 0;
72

M
Mr.doob 已提交
73
	xhr.onreadystatechange = function () {
74

75
		if ( xhr.readyState == 4 ) {
76

77
			if ( xhr.status == 200 || xhr.status == 0 ) {
78

79 80 81
				var buffer = xhr.response;
				if ( buffer === undefined ) buffer = ( new Uint8Array( xhr.responseBody ) ).buffer; // IEWEBGL needs this
				THREE.BinaryLoader.prototype.createBinModel( buffer, callback, texturePath, json.materials );
82

83
			} else {
84

M
Mr.doob 已提交
85
				console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
86

87
			}
88

89
		} else if ( xhr.readyState == 3 ) {
90

91
			if ( callbackProgress ) {
92

93
				if ( length == 0 ) {
94

95
					length = xhr.getResponseHeader( "Content-Length" );
96

97
				}
98

99
				callbackProgress( { total: length, loaded: xhr.responseText.length } );
100

101
			}
102

103 104 105 106
		} else if ( xhr.readyState == 2 ) {

			length = xhr.getResponseHeader( "Content-Length" );

107 108
		}

109
	};
110

111
	xhr.open( "GET", url, true );
112
	xhr.responseType = "arraybuffer";
113
	xhr.send( null );
114

115
};
116

117
// Binary AJAX parser
118

119
THREE.BinaryLoader.prototype.createBinModel = function ( data, callback, texturePath, jsonMaterials ) {
120

121
	var Model = function ( texturePath ) {
122

123 124 125 126 127 128 129 130 131 132
		var scope = this,
			currentOffset = 0,
			md,
			normals = [],
			uvs = [],
			start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv,
			start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv,
			tri_size, quad_size,
			len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv,
			len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv;
133 134


135
		THREE.Geometry.call( this );
136

137
		md = parseMetaData( data, currentOffset );
138

139 140 141 142 143 144 145
		currentOffset += md.header_bytes;
/*
		md.vertex_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
		md.material_index_bytes = Uint16Array.BYTES_PER_ELEMENT;
		md.normal_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
		md.uv_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
*/
146
		// buffers sizes
147

148 149
		tri_size =  md.vertex_index_bytes * 3 + md.material_index_bytes;
		quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes;
150

151 152 153 154
		len_tri_flat      = md.ntri_flat      * ( tri_size );
		len_tri_smooth    = md.ntri_smooth    * ( tri_size + md.normal_index_bytes * 3 );
		len_tri_flat_uv   = md.ntri_flat_uv   * ( tri_size + md.uv_index_bytes * 3 );
		len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 );
155

156 157 158 159
		len_quad_flat      = md.nquad_flat      * ( quad_size );
		len_quad_smooth    = md.nquad_smooth    * ( quad_size + md.normal_index_bytes * 4 );
		len_quad_flat_uv   = md.nquad_flat_uv   * ( quad_size + md.uv_index_bytes * 4 );
		len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 );
160

161
		// read buffers
162

163
		currentOffset += init_vertices( currentOffset );
164

165
		currentOffset += init_normals( currentOffset );
166 167
		currentOffset += handlePadding( md.nnormals * 3 );

168
		currentOffset += init_uvs( currentOffset );
169

170
		start_tri_flat 		= currentOffset;
171 172 173
		start_tri_smooth    = start_tri_flat    + len_tri_flat    + handlePadding( md.ntri_flat * 2 );
		start_tri_flat_uv   = start_tri_smooth  + len_tri_smooth  + handlePadding( md.ntri_smooth * 2 );
		start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv + handlePadding( md.ntri_flat_uv * 2 );
174

175 176 177 178
		start_quad_flat     = start_tri_smooth_uv + len_tri_smooth_uv  + handlePadding( md.ntri_smooth_uv * 2 );
		start_quad_smooth   = start_quad_flat     + len_quad_flat	   + handlePadding( md.nquad_flat * 2 );
		start_quad_flat_uv  = start_quad_smooth   + len_quad_smooth    + handlePadding( md.nquad_smooth * 2 );
		start_quad_smooth_uv= start_quad_flat_uv  + len_quad_flat_uv   + handlePadding( md.nquad_flat_uv * 2 );
179

180 181
		// have to first process faces with uvs
		// so that face and uv indices match
182

183 184
		init_triangles_flat_uv( start_tri_flat_uv );
		init_triangles_smooth_uv( start_tri_smooth_uv );
185

186 187
		init_quads_flat_uv( start_quad_flat_uv );
		init_quads_smooth_uv( start_quad_smooth_uv );
188

189
		// now we can process untextured faces
190

191 192
		init_triangles_flat( start_tri_flat );
		init_triangles_smooth( start_tri_smooth );
193

194 195
		init_quads_flat( start_quad_flat );
		init_quads_smooth( start_quad_smooth );
196

197 198
		this.computeCentroids();
		this.computeFaceNormals();
M
Mr.doob 已提交
199

200 201 202 203 204 205
		function handlePadding( n ) {

			return ( n % 4 ) ? ( 4 - n % 4 ) : 0;

		};

206
		function parseMetaData( data, offset ) {
207

208
			var metaData = {
209

210 211
				'signature'               :parseString( data, offset,  12 ),
				'header_bytes'            :parseUChar8( data, offset + 12 ),
212

213 214 215
				'vertex_coordinate_bytes' :parseUChar8( data, offset + 13 ),
				'normal_coordinate_bytes' :parseUChar8( data, offset + 14 ),
				'uv_coordinate_bytes'     :parseUChar8( data, offset + 15 ),
216

217 218 219 220
				'vertex_index_bytes'      :parseUChar8( data, offset + 16 ),
				'normal_index_bytes'      :parseUChar8( data, offset + 17 ),
				'uv_index_bytes'          :parseUChar8( data, offset + 18 ),
				'material_index_bytes'    :parseUChar8( data, offset + 19 ),
221

222 223 224
				'nvertices'    :parseUInt32( data, offset + 20 ),
				'nnormals'     :parseUInt32( data, offset + 20 + 4*1 ),
				'nuvs'         :parseUInt32( data, offset + 20 + 4*2 ),
225

226 227 228 229
				'ntri_flat'      :parseUInt32( data, offset + 20 + 4*3 ),
				'ntri_smooth'    :parseUInt32( data, offset + 20 + 4*4 ),
				'ntri_flat_uv'   :parseUInt32( data, offset + 20 + 4*5 ),
				'ntri_smooth_uv' :parseUInt32( data, offset + 20 + 4*6 ),
230

231 232 233 234
				'nquad_flat'      :parseUInt32( data, offset + 20 + 4*7 ),
				'nquad_smooth'    :parseUInt32( data, offset + 20 + 4*8 ),
				'nquad_flat_uv'   :parseUInt32( data, offset + 20 + 4*9 ),
				'nquad_smooth_uv' :parseUInt32( data, offset + 20 + 4*10 )
235

236
			};
237 238
/*
			console.log( "signature: " + metaData.signature );
239

240 241 242 243
			console.log( "header_bytes: " + metaData.header_bytes );
			console.log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
			console.log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
			console.log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
244

245 246 247 248
			console.log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
			console.log( "normal_index_bytes: " + metaData.normal_index_bytes );
			console.log( "uv_index_bytes: " + metaData.uv_index_bytes );
			console.log( "material_index_bytes: " + metaData.material_index_bytes );
249

250 251 252
			console.log( "nvertices: " + metaData.nvertices );
			console.log( "nnormals: " + metaData.nnormals );
			console.log( "nuvs: " + metaData.nuvs );
253

254 255 256 257
			console.log( "ntri_flat: " + metaData.ntri_flat );
			console.log( "ntri_smooth: " + metaData.ntri_smooth );
			console.log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
			console.log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
258

259 260 261 262
			console.log( "nquad_flat: " + metaData.nquad_flat );
			console.log( "nquad_smooth: " + metaData.nquad_smooth );
			console.log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
			console.log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
263

264 265 266 267 268 269 270 271 272 273 274 275
			var total = metaData.header_bytes
					  + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
					  + metaData.nnormals * metaData.normal_coordinate_bytes * 3
					  + metaData.nuvs * metaData.uv_coordinate_bytes * 2
					  + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes )
					  + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 )
					  + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 )
					  + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 )
					  + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes )
					  + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 )
					  + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 )
					  + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
276 277
			console.log( "total bytes: " + total );
*/
278

279
			return metaData;
280

281
		};
282

283
		function parseString( data, offset, length ) {
284

285
			var charArray = new Uint8Array( data, offset, length );
286

287
			var text = "";
288

289
			for ( var i = 0; i < length; i ++ ) {
290

291
				text += String.fromCharCode( charArray[ offset + i ] );
292

293
			}
294

295
			return text;
296

297
		};
298

299
		function parseUChar8( data, offset ) {
300

301
			var charArray = new Uint8Array( data, offset, 1 );
302

303
			return charArray[ 0 ];
304

305
		};
306

307
		function parseUInt32( data, offset ) {
308

309
			var intArray = new Uint32Array( data, offset, 1 );
310

311
			return intArray[ 0 ];
312

313
		};
314

315
		function init_vertices( start ) {
316

317
			var nElements = md.nvertices;
318

319
			var coordArray = new Float32Array( data, start, nElements * 3 );
320

321
			var i, x, y, z;
322

323
			for( i = 0; i < nElements; i ++ ) {
324

325 326 327
				x = coordArray[ i * 3 ];
				y = coordArray[ i * 3 + 1 ];
				z = coordArray[ i * 3 + 2 ];
328

329
				vertex( scope, x, y, z );
330 331 332

			}

333
			return nElements * 3 * Float32Array.BYTES_PER_ELEMENT;
334

335
		};
336

337
		function init_normals( start ) {
338

339
			var nElements = md.nnormals;
340

341
			if ( nElements ) {
342

343
				var normalArray = new Int8Array( data, start, nElements * 3 );
344

345 346 347 348 349 350 351 352 353 354 355
				var i, x, y, z;

				for( i = 0; i < nElements; i ++ ) {

					x = normalArray[ i * 3 ];
					y = normalArray[ i * 3 + 1 ];
					z = normalArray[ i * 3 + 2 ];

					normals.push( x/127, y/127, z/127 );

				}
356 357 358

			}

359
			return nElements * 3 * Int8Array.BYTES_PER_ELEMENT;
360

361
		};
362

363
		function init_uvs( start ) {
364

365
			var nElements = md.nuvs;
366

367
			if ( nElements ) {
368

369
				var uvArray = new Float32Array( data, start, nElements * 2 );
370

371 372 373 374 375 376 377 378 379 380
				var i, u, v;

				for( i = 0; i < nElements; i ++ ) {

					u = uvArray[ i * 2 ];
					v = uvArray[ i * 2 + 1 ];

					uvs.push( u, v );

				}
381

382 383
			}

384
			return nElements * 2 * Float32Array.BYTES_PER_ELEMENT;
385

386
		};
387

388
		function init_uvs3( nElements, offset ) {
389

390
			var i, uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
391

392
			var uvIndexBuffer = new Uint32Array( data, offset, 3 * nElements );
393

394
			for( i = 0; i < nElements; i ++ ) {
395

396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
				uva = uvIndexBuffer[ i * 3 ];
				uvb = uvIndexBuffer[ i * 3 + 1 ];
				uvc = uvIndexBuffer[ i * 3 + 2 ];

				u1 = uvs[ uva*2 ];
				v1 = uvs[ uva*2 + 1 ];

				u2 = uvs[ uvb*2 ];
				v2 = uvs[ uvb*2 + 1 ];

				u3 = uvs[ uvc*2 ];
				v3 = uvs[ uvc*2 + 1 ];

				uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 );

			}
412

413
		};
414

415 416 417 418 419 420 421 422 423 424 425 426
		function init_uvs4( nElements, offset ) {

			var i, uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;

			var uvIndexBuffer = new Uint32Array( data, offset, 4 * nElements );

			for( i = 0; i < nElements; i ++ ) {

				uva = uvIndexBuffer[ i * 4 ];
				uvb = uvIndexBuffer[ i * 4 + 1 ];
				uvc = uvIndexBuffer[ i * 4 + 2 ];
				uvd = uvIndexBuffer[ i * 4 + 3 ];
427

428 429
				u1 = uvs[ uva*2 ];
				v1 = uvs[ uva*2 + 1 ];
430

431 432
				u2 = uvs[ uvb*2 ];
				v2 = uvs[ uvb*2 + 1 ];
433

434 435
				u3 = uvs[ uvc*2 ];
				v3 = uvs[ uvc*2 + 1 ];
436

437 438
				u4 = uvs[ uvd*2 ];
				v4 = uvs[ uvd*2 + 1 ];
439

440 441 442
				uv4( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3, u4, v4 );

			}
443

444
		};
445

446 447 448 449 450 451 452 453
		function init_faces3_flat( nElements, offsetVertices, offsetMaterials ) {

			var i, a, b, c, m;

			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );

			for( i = 0; i < nElements; i ++ ) {
454

455 456 457
				a = vertexIndexBuffer[ i * 3 ];
				b = vertexIndexBuffer[ i * 3 + 1 ];
				c = vertexIndexBuffer[ i * 3 + 2 ];
458

459
				m = materialIndexBuffer[ i ];
460

461
				f3( scope, a, b, c, m );
462

463
			}
464

465
		};
466

467 468 469
		function init_faces4_flat( nElements, offsetVertices, offsetMaterials ) {

			var i, a, b, c, d, m;
470

471 472
			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
473

474
			for( i = 0; i < nElements; i ++ ) {
475

476 477 478 479
				a = vertexIndexBuffer[ i * 4 ];
				b = vertexIndexBuffer[ i * 4 + 1 ];
				c = vertexIndexBuffer[ i * 4 + 2 ];
				d = vertexIndexBuffer[ i * 4 + 3 ];
480

481
				m = materialIndexBuffer[ i ];
482

483 484 485
				f4( scope, a, b, c, d, m );

			}
486

487
		};
488

489 490 491 492
		function init_faces3_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {

			var i, a, b, c, m;
			var na, nb, nc;
493

494 495 496
			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
			var normalIndexBuffer = new Uint32Array( data, offsetNormals, 3 * nElements );
			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
497

498
			for( i = 0; i < nElements; i ++ ) {
499

500 501 502
				a = vertexIndexBuffer[ i * 3 ];
				b = vertexIndexBuffer[ i * 3 + 1 ];
				c = vertexIndexBuffer[ i * 3 + 2 ];
503

504 505 506
				na = normalIndexBuffer[ i * 3 ];
				nb = normalIndexBuffer[ i * 3 + 1 ];
				nc = normalIndexBuffer[ i * 3 + 2 ];
507

508
				m = materialIndexBuffer[ i ];
509

510 511 512
				f3n( scope, normals, a, b, c, m, na, nb, nc );

			}
513

514
		};
515

516
		function init_faces4_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
517

518 519
			var i, a, b, c, d, m;
			var na, nb, nc, nd;
520

521 522 523
			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
			var normalIndexBuffer = new Uint32Array( data, offsetNormals, 4 * nElements );
			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
524

525
			for( i = 0; i < nElements; i ++ ) {
526

527 528 529 530
				a = vertexIndexBuffer[ i * 4 ];
				b = vertexIndexBuffer[ i * 4 + 1 ];
				c = vertexIndexBuffer[ i * 4 + 2 ];
				d = vertexIndexBuffer[ i * 4 + 3 ];
531

532 533 534 535
				na = normalIndexBuffer[ i * 4 ];
				nb = normalIndexBuffer[ i * 4 + 1 ];
				nc = normalIndexBuffer[ i * 4 + 2 ];
				nd = normalIndexBuffer[ i * 4 + 3 ];
536

537
				m = materialIndexBuffer[ i ];
538

539 540 541
				f4n( scope, normals, a, b, c, d, m, na, nb, nc, nd );

			}
542

543
		};
544

545
		function init_triangles_flat( start ) {
546

547
			var nElements = md.ntri_flat;
548

549
			if ( nElements ) {
550

551 552
				var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
				init_faces3_flat( nElements, start, offsetMaterials );
553 554 555

			}

556
		};
557

558
		function init_triangles_flat_uv( start ) {
559

560
			var nElements = md.ntri_flat_uv;
561

562
			if ( nElements ) {
563

564 565
				var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
566

567 568
				init_faces3_flat( nElements, start, offsetMaterials );
				init_uvs3( nElements, offsetUvs );
569

570
			}
571

572
		};
573

574
		function init_triangles_smooth( start ) {
575

576
			var nElements = md.ntri_smooth;
577

578
			if ( nElements ) {
579

580 581
				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
				var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
582

583
				init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
584

585
			}
586

587
		};
588

589
		function init_triangles_smooth_uv( start ) {
590

591
			var nElements = md.ntri_smooth_uv;
592

593
			if ( nElements ) {
594

595 596 597
				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
				var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
598

599 600
				init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
				init_uvs3( nElements, offsetUvs );
601

602
			}
603

604
		};
605

606
		function init_quads_flat( start ) {
607

608
			var nElements = md.nquad_flat;
609

610
			if ( nElements ) {
611

612 613
				var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
				init_faces4_flat( nElements, start, offsetMaterials );
614 615 616

			}

617
		};
618

619
		function init_quads_flat_uv( start ) {
620

621
			var nElements = md.nquad_flat_uv;
622

623
			if ( nElements ) {
624

625 626
				var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
627

628 629
				init_faces4_flat( nElements, start, offsetMaterials );
				init_uvs4( nElements, offsetUvs );
630

631
			}
632 633

		};
634

635
		function init_quads_smooth( start ) {
636

637
			var nElements = md.nquad_smooth;
638

639
			if ( nElements ) {
640

641 642
				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
				var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
643

644
				init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
645

646
			}
647

648
		};
649

650
		function init_quads_smooth_uv( start ) {
651

652
			var nElements = md.nquad_smooth_uv;
653

654
			if ( nElements ) {
655

656 657 658
				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
				var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
659

660 661
				init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
				init_uvs4( nElements, offsetUvs );
662

663
			}
664

665
		};
666

667
	};
668

669
	function vertex ( scope, x, y, z ) {
670

M
Mr.doob 已提交
671
		scope.vertices.push( new THREE.Vector3( x, y, z ) );
672

673
	};
674

675
	function f3 ( scope, a, b, c, mi ) {
676

677
		scope.faces.push( new THREE.Face3( a, b, c, null, null, mi ) );
678

679
	};
680

681
	function f4 ( scope, a, b, c, d, mi ) {
682

683
		scope.faces.push( new THREE.Face4( a, b, c, d, null, null, mi ) );
684

685
	};
686

687
	function f3n ( scope, normals, a, b, c, mi, na, nb, nc ) {
688

689
		var nax = normals[ na*3     ],
690 691 692 693 694 695 696 697 698 699 700
			nay = normals[ na*3 + 1 ],
			naz = normals[ na*3 + 2 ],

			nbx = normals[ nb*3     ],
			nby = normals[ nb*3 + 1 ],
			nbz = normals[ nb*3 + 2 ],

			ncx = normals[ nc*3     ],
			ncy = normals[ nc*3 + 1 ],
			ncz = normals[ nc*3 + 2 ];

701 702 703
		scope.faces.push( new THREE.Face3( a, b, c,
						  [new THREE.Vector3( nax, nay, naz ),
						   new THREE.Vector3( nbx, nby, nbz ),
A
alteredq 已提交
704 705
						   new THREE.Vector3( ncx, ncy, ncz )],
						  null,
706
						  mi ) );
707

708
	};
709

710
	function f4n ( scope, normals, a, b, c, d, mi, na, nb, nc, nd ) {
711

712
		var nax = normals[ na*3     ],
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
			nay = normals[ na*3 + 1 ],
			naz = normals[ na*3 + 2 ],

			nbx = normals[ nb*3     ],
			nby = normals[ nb*3 + 1 ],
			nbz = normals[ nb*3 + 2 ],

			ncx = normals[ nc*3     ],
			ncy = normals[ nc*3 + 1 ],
			ncz = normals[ nc*3 + 2 ],

			ndx = normals[ nd*3     ],
			ndy = normals[ nd*3 + 1 ],
			ndz = normals[ nd*3 + 2 ];

		scope.faces.push( new THREE.Face4( a, b, c, d,
729 730 731
						  [new THREE.Vector3( nax, nay, naz ),
						   new THREE.Vector3( nbx, nby, nbz ),
						   new THREE.Vector3( ncx, ncy, ncz ),
A
alteredq 已提交
732 733
						   new THREE.Vector3( ndx, ndy, ndz )],
						  null,
734
						  mi ) );
735

736
	};
737

738
	function uv3 ( where, u1, v1, u2, v2, u3, v3 ) {
739

740
		where.push( [
M
Mr.doob 已提交
741 742 743
			new THREE.Vector2( u1, v1 ),
			new THREE.Vector2( u2, v2 ),
			new THREE.Vector2( u3, v3 )
744
		] );
745

746
	};
747

748
	function uv4 ( where, u1, v1, u2, v2, u3, v3, u4, v4 ) {
749

750
		where.push( [
M
Mr.doob 已提交
751 752 753 754
			new THREE.Vector2( u1, v1 ),
			new THREE.Vector2( u2, v2 ),
			new THREE.Vector2( u3, v3 ),
			new THREE.Vector2( u4, v4 )
755
		] );
756 757
	};

758
	Model.prototype = Object.create( THREE.Geometry.prototype );
759

760 761 762 763 764 765
	var geometry = new Model( texturePath );
	var materials = this.initMaterials( jsonMaterials, texturePath );

	if ( this.needsTangents( materials ) ) geometry.computeTangents();

	callback( geometry, materials );
766

767
};