OBJLoader.js 16.6 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4
/**
 * @author mrdoob / http://mrdoob.com/
 */

M
r59  
Mr.doob 已提交
5 6 7 8
THREE.OBJLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

M
r74  
Mr.doob 已提交
9 10
	this.materials = null;

M
r76  
Mr.doob 已提交
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
	this.regexp = {
		// v float float float
		vertex_pattern           : /^v\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
		// vn float float float
		normal_pattern           : /^vn\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
		// vt float float
		uv_pattern               : /^vt\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
		// f vertex vertex vertex
		face_vertex              : /^f\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)(?:\s+(-?\d+))?/,
		// f vertex/uv vertex/uv vertex/uv
		face_vertex_uv           : /^f\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+))?/,
		// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
		face_vertex_uv_normal    : /^f\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+)\/(-?\d+))?/,
		// f vertex//normal vertex//normal vertex//normal
		face_vertex_normal       : /^f\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)(?:\s+(-?\d+)\/\/(-?\d+))?/,
		// o object_name | g group_name
		object_pattern           : /^[og]\s*(.+)?/,
		// s boolean
		smoothing_pattern        : /^s\s+(\d+|on|off)/,
		// mtllib file_reference
		material_library_pattern : /^mtllib /,
		// usemtl material_name
		material_use_pattern     : /^usemtl /
	};

M
r59  
Mr.doob 已提交
36
};
M
Mr.doob 已提交
37 38 39 40 41

THREE.OBJLoader.prototype = {

	constructor: THREE.OBJLoader,

M
r59  
Mr.doob 已提交
42
	load: function ( url, onLoad, onProgress, onError ) {
M
Mr.doob 已提交
43 44 45

		var scope = this;

M
r59  
Mr.doob 已提交
46
		var loader = new THREE.XHRLoader( scope.manager );
M
r74  
Mr.doob 已提交
47
		loader.setPath( this.path );
M
r59  
Mr.doob 已提交
48
		loader.load( url, function ( text ) {
M
Mr.doob 已提交
49

M
r59  
Mr.doob 已提交
50
			onLoad( scope.parse( text ) );
M
Mr.doob 已提交
51

M
r69  
Mr.doob 已提交
52
		}, onProgress, onError );
M
Mr.doob 已提交
53 54 55

	},

M
r74  
Mr.doob 已提交
56 57 58 59 60 61 62
	setPath: function ( value ) {

		this.path = value;

	},

	setMaterials: function ( materials ) {
M
r72  
Mr.doob 已提交
63

M
r74  
Mr.doob 已提交
64
		this.materials = materials;
M
r72  
Mr.doob 已提交
65 66 67

	},

M
r76  
Mr.doob 已提交
68
	_createParserState : function () {
M
Mr.doob 已提交
69

M
r76  
Mr.doob 已提交
70 71 72
		var state = {
			objects  : [],
			object   : {},
M
Mr.doob 已提交
73

M
r76  
Mr.doob 已提交
74 75 76
			vertices : [],
			normals  : [],
			uvs      : [],
M
r74  
Mr.doob 已提交
77

M
r76  
Mr.doob 已提交
78
			materialLibraries : [],
M
r74  
Mr.doob 已提交
79

M
r76  
Mr.doob 已提交
80
			startObject: function ( name, fromDeclaration ) {
M
r74  
Mr.doob 已提交
81

M
r76  
Mr.doob 已提交
82 83 84
				// If the current object (initial from reset) is not from a g/o declaration in the parsed
				// file. We need to use it for the first parsed g/o to keep things in sync.
				if ( this.object && this.object.fromDeclaration === false ) {
M
r74  
Mr.doob 已提交
85

M
r76  
Mr.doob 已提交
86 87 88
					this.object.name = name;
					this.object.fromDeclaration = ( fromDeclaration !== false );
					return;
M
r74  
Mr.doob 已提交
89

M
r76  
Mr.doob 已提交
90
				}
M
r74  
Mr.doob 已提交
91

M
r77  
Mr.doob 已提交
92 93 94 95 96 97
				if ( this.object && typeof this.object._finalize === 'function' ) {

					this.object._finalize();

				}

M
r76  
Mr.doob 已提交
98 99
				this.object = {
					name : name || '',
M
r77  
Mr.doob 已提交
100 101
					fromDeclaration : ( fromDeclaration !== false ),

M
r76  
Mr.doob 已提交
102 103 104 105 106
					geometry : {
						vertices : [],
						normals  : [],
						uvs      : []
					},
M
r77  
Mr.doob 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
					materials : [],
					smooth : true,

					startMaterial : function( name, libraries ) {

						var previous = this._finalize( false );

						var material = {
							index      : this.materials.length,
							name       : name || '',
							mtllib     : ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
							smooth     : ( previous !== undefined ? previous.smooth : this.smooth ),
							groupStart : ( previous !== undefined ? previous.groupEnd : 0 ),
							groupEnd   : -1,
							groupCount : -1
						};

						this.materials.push( material );

						return material;

M
r76  
Mr.doob 已提交
128
					},
M
r77  
Mr.doob 已提交
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

					currentMaterial : function() {

						if ( this.materials.length > 0 ) {
							return this.materials[ this.materials.length - 1 ];
						}

						return undefined;

					},

					_finalize : function( end ) {

						var lastMultiMaterial = this.currentMaterial();
						if ( lastMultiMaterial && lastMultiMaterial.groupEnd === -1 ) {

							lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
							lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;

						}

						// Guarantee at least one empty material, this makes the creation later more straight forward.
						if ( end !== false && this.materials.length === 0 ) {
							this.materials.push({
								name   : '',
								smooth : this.smooth
							});
						}

						return lastMultiMaterial;

					}
M
r76  
Mr.doob 已提交
161
				};
M
Mr.doob 已提交
162

M
r76  
Mr.doob 已提交
163
				this.objects.push( this.object );
M
Mr.doob 已提交
164

M
r76  
Mr.doob 已提交
165
			},
M
Mr.doob 已提交
166

M
r77  
Mr.doob 已提交
167 168 169 170 171 172 173 174 175 176
			finalize : function() {

				if ( this.object && typeof this.object._finalize === 'function' ) {

					this.object._finalize();

				}

			},

M
r76  
Mr.doob 已提交
177
			parseVertexIndex: function ( value, len ) {
M
Mr.doob 已提交
178

M
r76  
Mr.doob 已提交
179 180
				var index = parseInt( value, 10 );
				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
M
Mr.doob 已提交
181

M
r76  
Mr.doob 已提交
182
			},
M
r69  
Mr.doob 已提交
183

M
r76  
Mr.doob 已提交
184
			parseNormalIndex: function ( value, len ) {
M
Mr.doob 已提交
185

M
r76  
Mr.doob 已提交
186 187
				var index = parseInt( value, 10 );
				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
M
Mr.doob 已提交
188

M
r76  
Mr.doob 已提交
189
			},
M
r66  
Mr.doob 已提交
190

M
r76  
Mr.doob 已提交
191
			parseUVIndex: function ( value, len ) {
M
r66  
Mr.doob 已提交
192

M
r76  
Mr.doob 已提交
193 194
				var index = parseInt( value, 10 );
				return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
M
r66  
Mr.doob 已提交
195

M
r76  
Mr.doob 已提交
196
			},
M
r66  
Mr.doob 已提交
197

M
r76  
Mr.doob 已提交
198
			addVertex: function ( a, b, c ) {
M
r66  
Mr.doob 已提交
199

M
r76  
Mr.doob 已提交
200 201
				var src = this.vertices;
				var dst = this.object.geometry.vertices;
M
r66  
Mr.doob 已提交
202

M
r76  
Mr.doob 已提交
203 204 205 206 207 208 209 210 211
				dst.push( src[ a + 0 ] );
				dst.push( src[ a + 1 ] );
				dst.push( src[ a + 2 ] );
				dst.push( src[ b + 0 ] );
				dst.push( src[ b + 1 ] );
				dst.push( src[ b + 2 ] );
				dst.push( src[ c + 0 ] );
				dst.push( src[ c + 1 ] );
				dst.push( src[ c + 2 ] );
M
r66  
Mr.doob 已提交
212

M
r76  
Mr.doob 已提交
213
			},
M
r66  
Mr.doob 已提交
214

M
r76  
Mr.doob 已提交
215
			addVertexLine: function ( a ) {
M
r69  
Mr.doob 已提交
216

M
r76  
Mr.doob 已提交
217 218
				var src = this.vertices;
				var dst = this.object.geometry.vertices;
M
r69  
Mr.doob 已提交
219

M
r76  
Mr.doob 已提交
220 221 222
				dst.push( src[ a + 0 ] );
				dst.push( src[ a + 1 ] );
				dst.push( src[ a + 2 ] );
M
r66  
Mr.doob 已提交
223

M
r76  
Mr.doob 已提交
224
			},
M
r66  
Mr.doob 已提交
225

M
r76  
Mr.doob 已提交
226
			addNormal : function ( a, b, c ) {
M
r66  
Mr.doob 已提交
227

M
r76  
Mr.doob 已提交
228 229
				var src = this.normals;
				var dst = this.object.geometry.normals;
M
r63  
Mr.doob 已提交
230

M
r76  
Mr.doob 已提交
231 232 233 234 235 236 237 238 239
				dst.push( src[ a + 0 ] );
				dst.push( src[ a + 1 ] );
				dst.push( src[ a + 2 ] );
				dst.push( src[ b + 0 ] );
				dst.push( src[ b + 1 ] );
				dst.push( src[ b + 2 ] );
				dst.push( src[ c + 0 ] );
				dst.push( src[ c + 1 ] );
				dst.push( src[ c + 2 ] );
M
r63  
Mr.doob 已提交
240

M
r76  
Mr.doob 已提交
241
			},
M
r69  
Mr.doob 已提交
242

M
r76  
Mr.doob 已提交
243
			addUV: function ( a, b, c ) {
M
r69  
Mr.doob 已提交
244

M
r76  
Mr.doob 已提交
245 246
				var src = this.uvs;
				var dst = this.object.geometry.uvs;
M
r63  
Mr.doob 已提交
247

M
r76  
Mr.doob 已提交
248 249 250 251 252 253
				dst.push( src[ a + 0 ] );
				dst.push( src[ a + 1 ] );
				dst.push( src[ b + 0 ] );
				dst.push( src[ b + 1 ] );
				dst.push( src[ c + 0 ] );
				dst.push( src[ c + 1 ] );
M
r63  
Mr.doob 已提交
254

M
r76  
Mr.doob 已提交
255
			},
M
r69  
Mr.doob 已提交
256

M
r76  
Mr.doob 已提交
257
			addUVLine: function ( a ) {
M
r63  
Mr.doob 已提交
258

M
r76  
Mr.doob 已提交
259 260 261 262 263
				var src = this.uvs;
				var dst = this.object.geometry.uvs;

				dst.push( src[ a + 0 ] );
				dst.push( src[ a + 1 ] );
M
r63  
Mr.doob 已提交
264

M
r76  
Mr.doob 已提交
265
			},
M
r63  
Mr.doob 已提交
266

M
r76  
Mr.doob 已提交
267 268 269 270 271 272 273 274
			addFace: function ( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) {

				var vLen = this.vertices.length;

				var ia = this.parseVertexIndex( a, vLen );
				var ib = this.parseVertexIndex( b, vLen );
				var ic = this.parseVertexIndex( c, vLen );
				var id;
M
r63  
Mr.doob 已提交
275

M
r69  
Mr.doob 已提交
276 277
				if ( d === undefined ) {

M
r76  
Mr.doob 已提交
278
					this.addVertex( ia, ib, ic );
M
r69  
Mr.doob 已提交
279 280 281

				} else {

M
r76  
Mr.doob 已提交
282
					id = this.parseVertexIndex( d, vLen );
M
r63  
Mr.doob 已提交
283

M
r76  
Mr.doob 已提交
284 285
					this.addVertex( ia, ib, id );
					this.addVertex( ib, ic, id );
M
r63  
Mr.doob 已提交
286 287 288

				}

M
r76  
Mr.doob 已提交
289
				if ( ua !== undefined ) {
M
r63  
Mr.doob 已提交
290

M
r76  
Mr.doob 已提交
291
					var uvLen = this.uvs.length;
M
r63  
Mr.doob 已提交
292

M
r76  
Mr.doob 已提交
293 294 295
					ia = this.parseUVIndex( ua, uvLen );
					ib = this.parseUVIndex( ub, uvLen );
					ic = this.parseUVIndex( uc, uvLen );
M
r63  
Mr.doob 已提交
296

M
r76  
Mr.doob 已提交
297
					if ( d === undefined ) {
M
r63  
Mr.doob 已提交
298

M
r76  
Mr.doob 已提交
299
						this.addUV( ia, ib, ic );
M
r69  
Mr.doob 已提交
300

M
r76  
Mr.doob 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
					} else {

						id = this.parseUVIndex( ud, uvLen );

						this.addUV( ia, ib, id );
						this.addUV( ib, ic, id );

					}

				}

				if ( na !== undefined ) {

					// Normals are many times the same. If so, skip function call and parseInt.
					var nLen = this.normals.length;
					ia = this.parseNormalIndex( na, nLen );

					ib = na === nb ? ia : this.parseNormalIndex( nb, nLen );
					ic = na === nc ? ia : this.parseNormalIndex( nc, nLen );

					if ( d === undefined ) {

						this.addNormal( ia, ib, ic );

					} else {

						id = this.parseNormalIndex( nd, nLen );

						this.addNormal( ia, ib, id );
						this.addNormal( ib, ic, id );

					}

				}

			},

			addLineGeometry: function ( vertices, uvs ) {

				this.object.geometry.type = 'Line';

				var vLen = this.vertices.length;
				var uvLen = this.uvs.length;

				for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {

					this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
M
r63  
Mr.doob 已提交
348

M
r76  
Mr.doob 已提交
349 350 351
				}

				for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
M
r69  
Mr.doob 已提交
352

M
r76  
Mr.doob 已提交
353
					this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
M
r63  
Mr.doob 已提交
354 355 356 357

				}

			}
M
r69  
Mr.doob 已提交
358

M
r76  
Mr.doob 已提交
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
		};

		state.startObject( '', false );

		return state;

	},

	parse: function ( text ) {

		console.time( 'OBJLoader' );

		var state = this._createParserState();

		if ( text.indexOf( '\r\n' ) !== - 1 ) {

			// This is faster than String.split with regex that splits on both
			text = text.replace( '\r\n', '\n' );

M
r63  
Mr.doob 已提交
378
		}
M
Mr.doob 已提交
379

M
r76  
Mr.doob 已提交
380 381 382 383
		var lines = text.split( '\n' );
		var line = '', lineFirstChar = '', lineSecondChar = '';
		var lineLength = 0;
		var result = [];
M
Mr.doob 已提交
384

M
r76  
Mr.doob 已提交
385 386
		// Faster to just trim left side of the line. Use if available.
		var trimLeft = ( typeof ''.trimLeft === 'function' );
M
Mr.doob 已提交
387

M
r76  
Mr.doob 已提交
388
		for ( var i = 0, l = lines.length; i < l; i ++ ) {
M
Mr.doob 已提交
389

M
r76  
Mr.doob 已提交
390
			line = lines[ i ];
M
Mr.doob 已提交
391

M
r76  
Mr.doob 已提交
392
			line = trimLeft ? line.trimLeft() : line.trim();
M
Mr.doob 已提交
393

M
r76  
Mr.doob 已提交
394
			lineLength = line.length;
M
Mr.doob 已提交
395

M
r76  
Mr.doob 已提交
396
			if ( lineLength === 0 ) continue;
M
Mr.doob 已提交
397

M
r76  
Mr.doob 已提交
398
			lineFirstChar = line.charAt( 0 );
M
Mr.doob 已提交
399

M
r76  
Mr.doob 已提交
400 401
			// @todo invoke passed in handler if any
			if ( lineFirstChar === '#' ) continue;
M
r74  
Mr.doob 已提交
402

M
r76  
Mr.doob 已提交
403
			if ( lineFirstChar === 'v' ) {
M
Mr.doob 已提交
404

M
r76  
Mr.doob 已提交
405
				lineSecondChar = line.charAt( 1 );
M
Mr.doob 已提交
406

M
r76  
Mr.doob 已提交
407
				if ( lineSecondChar === ' ' && ( result = this.regexp.vertex_pattern.exec( line ) ) !== null ) {
M
Mr.doob 已提交
408

M
r76  
Mr.doob 已提交
409 410
					// 0                  1      2      3
					// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
M
Mr.doob 已提交
411

M
r76  
Mr.doob 已提交
412 413 414 415 416
					state.vertices.push(
						parseFloat( result[ 1 ] ),
						parseFloat( result[ 2 ] ),
						parseFloat( result[ 3 ] )
					);
M
Mr.doob 已提交
417

M
r76  
Mr.doob 已提交
418
				} else if ( lineSecondChar === 'n' && ( result = this.regexp.normal_pattern.exec( line ) ) !== null ) {
M
Mr.doob 已提交
419

M
r76  
Mr.doob 已提交
420 421
					// 0                   1      2      3
					// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
M
Mr.doob 已提交
422

M
r76  
Mr.doob 已提交
423 424 425 426 427
					state.normals.push(
						parseFloat( result[ 1 ] ),
						parseFloat( result[ 2 ] ),
						parseFloat( result[ 3 ] )
					);
M
Mr.doob 已提交
428

M
r76  
Mr.doob 已提交
429
				} else if ( lineSecondChar === 't' && ( result = this.regexp.uv_pattern.exec( line ) ) !== null ) {
M
Mr.doob 已提交
430

M
r76  
Mr.doob 已提交
431 432
					// 0               1      2
					// ["vt 0.1 0.2", "0.1", "0.2"]
M
Mr.doob 已提交
433

M
r76  
Mr.doob 已提交
434 435 436 437
					state.uvs.push(
						parseFloat( result[ 1 ] ),
						parseFloat( result[ 2 ] )
					);
M
Mr.doob 已提交
438

M
r76  
Mr.doob 已提交
439
				} else {
M
Mr.doob 已提交
440

M
r76  
Mr.doob 已提交
441
					throw new Error( "Unexpected vertex/normal/uv line: '" + line  + "'" );
M
Mr.doob 已提交
442

M
r76  
Mr.doob 已提交
443
				}
M
Mr.doob 已提交
444

M
r76  
Mr.doob 已提交
445
			} else if ( lineFirstChar === "f" ) {
M
Mr.doob 已提交
446

M
r76  
Mr.doob 已提交
447
				if ( ( result = this.regexp.face_vertex_uv_normal.exec( line ) ) !== null ) {
M
Mr.doob 已提交
448

M
r76  
Mr.doob 已提交
449 450 451
					// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
					// 0                        1    2    3    4    5    6    7    8    9   10         11         12
					// ["f 1/1/1 2/2/2 3/3/3", "1", "1", "1", "2", "2", "2", "3", "3", "3", undefined, undefined, undefined]
M
Mr.doob 已提交
452

M
r76  
Mr.doob 已提交
453 454 455 456 457
					state.addFace(
						result[ 1 ], result[ 4 ], result[ 7 ], result[ 10 ],
						result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
						result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
					);
M
Mr.doob 已提交
458

M
r76  
Mr.doob 已提交
459
				} else if ( ( result = this.regexp.face_vertex_uv.exec( line ) ) !== null ) {
M
Mr.doob 已提交
460

M
r76  
Mr.doob 已提交
461 462 463
					// f vertex/uv vertex/uv vertex/uv
					// 0                  1    2    3    4    5    6   7          8
					// ["f 1/1 2/2 3/3", "1", "1", "2", "2", "3", "3", undefined, undefined]
M
r62  
Mr.doob 已提交
464

M
r76  
Mr.doob 已提交
465 466 467 468
					state.addFace(
						result[ 1 ], result[ 3 ], result[ 5 ], result[ 7 ],
						result[ 2 ], result[ 4 ], result[ 6 ], result[ 8 ]
					);
M
r60  
Mr.doob 已提交
469

M
r76  
Mr.doob 已提交
470
				} else if ( ( result = this.regexp.face_vertex_normal.exec( line ) ) !== null ) {
M
r71  
Mr.doob 已提交
471

M
r76  
Mr.doob 已提交
472 473 474
					// f vertex//normal vertex//normal vertex//normal
					// 0                     1    2    3    4    5    6   7          8
					// ["f 1//1 2//2 3//3", "1", "1", "2", "2", "3", "3", undefined, undefined]
M
r62  
Mr.doob 已提交
475

M
r76  
Mr.doob 已提交
476 477 478 479 480
					state.addFace(
						result[ 1 ], result[ 3 ], result[ 5 ], result[ 7 ],
						undefined, undefined, undefined, undefined,
						result[ 2 ], result[ 4 ], result[ 6 ], result[ 8 ]
					);
M
r62  
Mr.doob 已提交
481

M
r76  
Mr.doob 已提交
482
				} else if ( ( result = this.regexp.face_vertex.exec( line ) ) !== null ) {
M
r62  
Mr.doob 已提交
483

M
r76  
Mr.doob 已提交
484 485 486
					// f vertex vertex vertex
					// 0            1    2    3   4
					// ["f 1 2 3", "1", "2", "3", undefined]
M
Mr.doob 已提交
487

M
r76  
Mr.doob 已提交
488 489 490
					state.addFace(
						result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ]
					);
M
Mr.doob 已提交
491

M
r76  
Mr.doob 已提交
492
				} else {
M
r62  
Mr.doob 已提交
493

M
r76  
Mr.doob 已提交
494
					throw new Error( "Unexpected face line: '" + line  + "'" );
M
Mr.doob 已提交
495

M
r76  
Mr.doob 已提交
496
				}
M
Mr.doob 已提交
497

M
r76  
Mr.doob 已提交
498
			} else if ( lineFirstChar === "l" ) {
M
r69  
Mr.doob 已提交
499

M
r76  
Mr.doob 已提交
500 501
				var lineParts = line.substring( 1 ).trim().split( " " );
				var lineVertices = [], lineUVs = [];
M
r69  
Mr.doob 已提交
502

M
r76  
Mr.doob 已提交
503
				if ( line.indexOf( "/" ) === - 1 ) {
M
r61  
Mr.doob 已提交
504

M
r76  
Mr.doob 已提交
505
					lineVertices = lineParts;
M
r61  
Mr.doob 已提交
506

M
r74  
Mr.doob 已提交
507
				} else {
M
Mr.doob 已提交
508

M
r76  
Mr.doob 已提交
509 510 511 512 513 514 515 516
					for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) {

						var parts = lineParts[ li ].split( "/" );

						if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] );
						if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] );

					}
M
r74  
Mr.doob 已提交
517 518

				}
M
r76  
Mr.doob 已提交
519 520 521 522 523 524 525 526 527 528
				state.addLineGeometry( lineVertices, lineUVs );

			} else if ( ( result = this.regexp.object_pattern.exec( line ) ) !== null ) {

				// o object_name
				// or
				// g group_name

				var name = result[ 0 ].substr( 1 ).trim();
				state.startObject( name );
M
Mr.doob 已提交
529

M
r76  
Mr.doob 已提交
530
			} else if ( this.regexp.material_use_pattern.test( line ) ) {
M
Mr.doob 已提交
531 532 533

				// material

M
r77  
Mr.doob 已提交
534
				state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
M
Mr.doob 已提交
535

M
r76  
Mr.doob 已提交
536
			} else if ( this.regexp.material_library_pattern.test( line ) ) {
M
Mr.doob 已提交
537 538 539

				// mtl file

M
r76  
Mr.doob 已提交
540 541 542
				state.materialLibraries.push( line.substring( 7 ).trim() );

			} else if ( ( result = this.regexp.smoothing_pattern.exec( line ) ) !== null ) {
M
Mr.doob 已提交
543 544 545

				// smooth shading

M
r77  
Mr.doob 已提交
546 547 548 549 550 551 552
				// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
				// but does not define a usemtl for each face set.
				// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
				// This requires some care to not create extra material on each smooth value for "normal" obj files.
				// where explicit usemtl defines geometry groups.
				// Example asset: examples/models/obj/cerberus/Cerberus.obj

M
r76  
Mr.doob 已提交
553
				var value = result[ 1 ].trim().toLowerCase();
M
r77  
Mr.doob 已提交
554 555 556 557 558 559 560 561
				state.object.smooth = ( value === '1' || value === 'on' );

				var material = state.object.currentMaterial();
				if ( material ) {

					material.smooth = state.object.smooth;

				}
M
r74  
Mr.doob 已提交
562

M
Mr.doob 已提交
563 564
			} else {

M
r76  
Mr.doob 已提交
565 566 567 568
				// Handle null terminated files without exception
				if ( line === '\0' ) continue;

				throw new Error( "Unexpected line: '" + line  + "'" );
M
Mr.doob 已提交
569 570 571 572 573

			}

		}

M
r77  
Mr.doob 已提交
574 575
		state.finalize();

M
r74  
Mr.doob 已提交
576
		var container = new THREE.Group();
M
r76  
Mr.doob 已提交
577
		container.materialLibraries = [].concat( state.materialLibraries );
M
r66  
Mr.doob 已提交
578

M
r76  
Mr.doob 已提交
579
		for ( var i = 0, l = state.objects.length; i < l; i ++ ) {
M
r61  
Mr.doob 已提交
580

M
r76  
Mr.doob 已提交
581
			var object = state.objects[ i ];
M
r74  
Mr.doob 已提交
582
			var geometry = object.geometry;
M
r77  
Mr.doob 已提交
583
			var materials = object.materials;
M
r76  
Mr.doob 已提交
584 585 586 587
			var isLine = ( geometry.type === 'Line' );

			// Skip o/g line declarations that did not follow with any faces
			if ( geometry.vertices.length === 0 ) continue;
M
r61  
Mr.doob 已提交
588

M
r69  
Mr.doob 已提交
589 590 591 592 593
			var buffergeometry = new THREE.BufferGeometry();

			buffergeometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( geometry.vertices ), 3 ) );

			if ( geometry.normals.length > 0 ) {
M
r72  
Mr.doob 已提交
594

M
r69  
Mr.doob 已提交
595
				buffergeometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( geometry.normals ), 3 ) );
M
r72  
Mr.doob 已提交
596

M
r74  
Mr.doob 已提交
597 598 599 600
			} else {

				buffergeometry.computeVertexNormals();

M
r69  
Mr.doob 已提交
601 602 603
			}

			if ( geometry.uvs.length > 0 ) {
M
r72  
Mr.doob 已提交
604

M
r69  
Mr.doob 已提交
605
				buffergeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( geometry.uvs ), 2 ) );
M
r72  
Mr.doob 已提交
606

M
r69  
Mr.doob 已提交
607 608
			}

M
r77  
Mr.doob 已提交
609 610 611 612 613 614 615 616
			// Create materials

			var createdMaterials = [];

			for ( var mi = 0, miLen = materials.length; mi < miLen ; mi++ ) {

				var sourceMaterial = materials[mi];
				var material = undefined;
M
r74  
Mr.doob 已提交
617

M
r77  
Mr.doob 已提交
618
				if ( this.materials !== null ) {
M
r74  
Mr.doob 已提交
619

M
r77  
Mr.doob 已提交
620
					material = this.materials.create( sourceMaterial.name );
M
r74  
Mr.doob 已提交
621

M
r77  
Mr.doob 已提交
622 623
					// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
					if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) {
M
r76  
Mr.doob 已提交
624

M
r77  
Mr.doob 已提交
625 626 627 628 629
						var materialLine = new THREE.LineBasicMaterial();
						materialLine.copy( material );
						material = materialLine;

					}
M
r76  
Mr.doob 已提交
630 631 632

				}

M
r77  
Mr.doob 已提交
633
				if ( ! material ) {
M
r74  
Mr.doob 已提交
634

M
r77  
Mr.doob 已提交
635 636
					material = ( ! isLine ? new THREE.MeshPhongMaterial() : new THREE.LineBasicMaterial() );
					material.name = sourceMaterial.name;
M
r74  
Mr.doob 已提交
637

M
r77  
Mr.doob 已提交
638 639 640 641 642
				}

				material.shading = sourceMaterial.smooth ? THREE.SmoothShading : THREE.FlatShading;

				createdMaterials.push(material);
M
r74  
Mr.doob 已提交
643 644 645

			}

M
r77  
Mr.doob 已提交
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
			// Create mesh

			var mesh;

			if ( createdMaterials.length > 1 ) {

				for ( var mi = 0, miLen = materials.length; mi < miLen ; mi++ ) {

					var sourceMaterial = materials[mi];
					buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );

				}

				var multiMaterial = new THREE.MultiMaterial( createdMaterials );
				mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, multiMaterial ) : new THREE.Line( buffergeometry, multiMaterial ) );

			} else {

				mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ) : new THREE.Line( buffergeometry, createdMaterials[ 0 ] ) );
			}
M
r69  
Mr.doob 已提交
666 667 668 669

			mesh.name = object.name;

			container.add( mesh );
M
r61  
Mr.doob 已提交
670 671

		}
M
r69  
Mr.doob 已提交
672 673 674 675

		console.timeEnd( 'OBJLoader' );

		return container;
M
Mr.doob 已提交
676 677 678

	}

M
r68  
Mr.doob 已提交
679
};