VRMLLoader.js 19.1 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4 5 6 7 8
/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.VRMLLoader = function () {};

THREE.VRMLLoader.prototype = {

9
	constructor: THREE.VRMLLoader,
M
Mr.doob 已提交
10

11 12 13 14 15
	// for IndexedFaceSet support
	isRecordingPoints: false,
	isRecordingFaces: false,
	points: [],
	indexes : [],
16

17 18 19 20 21
	// for Background support
	isRecordingAngles: false,
	isRecordingColors: false,
	angles: [],
	colors: [],
22

23
	recordingFieldname: null,
24

M
Mr.doob 已提交
25 26 27 28 29 30 31 32 33 34 35
	load: function ( url, callback ) {

		var scope = this;
		var request = new XMLHttpRequest();

		request.addEventListener( 'load', function ( event ) {

			var object = scope.parse( event.target.responseText );

			scope.dispatchEvent( { type: 'load', content: object } );

36 37
			if ( callback ) callback( object );

M
Mr.doob 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
		}, false );

		request.addEventListener( 'progress', function ( event ) {

			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );

		}, false );

		request.addEventListener( 'error', function () {

			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );

		}, false );

		request.open( 'GET', url, true );
		request.send( null );

	},

	parse: function ( data ) {

		var parseV1 = function ( lines, scene ) {

M
Mr.doob 已提交
61
			console.warn( 'VRML V1.0 not supported yet' );
M
Mr.doob 已提交
62 63 64 65

		};

		var parseV2 = function ( lines, scene ) {
66 67
			var defines = {};
			var float_pattern = /(\b|\-|\+)([\d\.e]+)/;
68
			var float3_pattern = /([\d\.\+\-e]+)\s+([\d\.\+\-e]+)\s+([\d\.\+\-e]+)/g;
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

			/**
			* Interpolates colors a and b following their relative distance
			* expressed by t.
			*
			* @param float a
			* @param float b
			* @param float t
			* @returns {Color}
			*/
			var interpolateColors = function(a, b, t) {
			   var deltaR = a.r - b.r;
			   var deltaG = a.g - b.g;
			   var deltaB = a.b - b.b;

			   var c = new THREE.Color();

			   c.r = a.r - t * deltaR;
			   c.g = a.g - t * deltaG;
			   c.b = a.b - t * deltaB;

			   return c;
			};

			/**
			 * Vertically paints the faces interpolating between the
			 * specified colors at the specified angels. This is used for the Background
			 * node, but could be applied to other nodes with multiple faces as well.
			 *
			 * When used with the Background node, default is directionIsDown is true if
			 * interpolating the skyColor down from the Zenith. When interpolationg up from
			 * the Nadir i.e. interpolating the groundColor, the directionIsDown is false.
			 *
			 * The first angle is never specified, it is the Zenith (0 rad). Angles are specified
			 * in radians. The geometry is thought a sphere, but could be anything. The color interpolation
			 * is linear along the Y axis in any case.
			 *
			 * You must specify one more color than you have angles at the beginning of the colors array.
			 * This is the color of the Zenith (the top of the shape).
			 *
			 * @param geometry
			 * @param radius
			 * @param angles
			 * @param colors
			 * @param boolean directionIsDown Whether to work bottom up or top down.
			 */
			var paintFaces = function (geometry, radius, angles, colors, directionIsDown) {

				var f, n, p, vertexIndex, color;

				var direction = directionIsDown ? 1 : -1;

				var faceIndices = [ 'a', 'b', 'c', 'd' ];

				var coord = [ ], aColor, bColor, t = 1, A = {}, B = {}, applyColor = false, colorIndex;

				for ( var k = 0; k < angles.length; k++ ) {

					var vec = { };

					// push the vector at which the color changes
					vec.y = direction * ( Math.cos( angles[k] ) * radius);

					vec.x = direction * ( Math.sin( angles[k] ) * radius);

					coord.push( vec );
135

136 137 138 139 140 141 142 143
				}

				// painting the colors on the faces
				for ( var i = 0; i < geometry.faces.length ; i++ ) {

					f  = geometry.faces[ i ];

					n = ( f instanceof THREE.Face3 ) ? 3 : 4;
144

145
					for ( var j = 0; j < n; j++ ) {
146

147
						vertexIndex = f[ faceIndices[ j ] ];
148

149
						p = geometry.vertices[ vertexIndex ];
150

151
						for ( var index = 0; index < colors.length; index++ ) {
152

153 154 155
							// linear interpolation between aColor and bColor, calculate proportion
							// A is previous point (angle)
							if ( index === 0 ) {
156

157 158 159 160 161 162 163 164 165
								A.x = 0;
								A.y = directionIsDown ? radius : -1 * radius;

							} else {

								A.x = coord[ index-1 ].x;
								A.y = coord[ index-1 ].y;

							}
166

167 168
							// B is current point (angle)
							B = coord[index];
169

170 171 172
							if ( undefined !== B ) {
								// p has to be between the points A and B which we interpolate
								applyColor = directionIsDown ? p.y <= A.y && p.y > B.y : p.y >= A.y && p.y < B.y;
173

174
								if (applyColor) {
175

176
									bColor = colors[ index + 1 ];
177

178
									aColor = colors[ index ];
179

180 181
									// below is simple linear interpolation
									t = Math.abs( p.y - A.y ) / ( A.y - B.y );
182

183 184
									// to make it faster, you can only calculate this if the y coord changes, the color is the same for points with the same y
									color = interpolateColors( aColor, bColor, t );
185

186 187
									f.vertexColors[ j ] = color;
								}
188

189 190 191
							} else if ( undefined === f.vertexColors[ j ] ) {
								colorIndex = directionIsDown ? colors.length -1 : 0;
								f.vertexColors[ j ] = colors[ colorIndex ];
192

193 194
							}
						}
195

196
					}
197

198 199
				}
			};
200

201
			var parseProperty = function (node, line) {
202

203
				var parts = [], part, property = {}, fieldName;
204

205 206 207 208 209
				/**
				 * Expression for matching relevant information, such as a name or value, but not the separators
				 * @type {RegExp}
				 */
				var regex = /[^\s,\[\]]+/g;
210

211
				var point, index, angles, colors;
212

213 214 215
				while (null != ( part = regex.exec(line) ) ) {
					parts.push(part[0]);
				}
216

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
				fieldName = parts[0];


				// trigger several recorders
				switch (fieldName) {
					case 'skyAngle':
					case 'groundAngle':
						this.recordingFieldname = fieldName;
						this.isRecordingAngles = true;
						this.angles = [];
						break;
					case 'skyColor':
					case 'groundColor':
						this.recordingFieldname = fieldName;
						this.isRecordingColors = true;
						this.colors = [];
						break;
					case 'point':
						this.recordingFieldname = fieldName;
						this.isRecordingPoints = true;
						this.points = [];
						break;
					case 'coordIndex':
						this.recordingFieldname = fieldName;
						this.isRecordingFaces = true;
						this.indexes = [];
						break;
				}
245

246
				if (this.isRecordingFaces) {
247

248 249 250
					// the parts hold the indexes as strings
					if (parts.length > 0) {
						index = [];
251

252
						for (var ind = 0;ind < parts.length; ind++) {
253

254 255 256 257
							// the part should either be positive integer or -1
							if (!/(-?\d+)/.test( parts[ind]) ) {
								continue;
							}
258

259 260 261 262 263
							// end of current face
							if (parts[ind] === "-1") {
								if (index.length > 0) {
								   this.indexes.push(index);
								}
264

265 266 267 268 269 270
								// start new one
								index = [];
							} else {
								index.push(parseInt( parts[ind]) );
							}
						}
271

272
					}
273

274 275 276 277 278
					// end
					if (/]/.exec(line)) {
						this.isRecordingFaces = false;
						node.coordIndex = this.indexes;
					}
279

280
				} else if (this.isRecordingPoints) {
281

282
					while ( null !== ( parts = float3_pattern.exec(line) ) ) {
283 284 285 286 287
						point = {
							x: parseFloat(parts[1]),
							y: parseFloat(parts[2]),
							z: parseFloat(parts[3])
						};
288

289 290
						this.points.push(point);
					}
291

292 293 294 295 296
					// end
					if ( /]/.exec(line) ) {
						this.isRecordingPoints = false;
						node.points = this.points;
					}
297

298
				} else if ( this.isRecordingAngles ) {
299

300 301
					// the parts hold the angles as strings
					if ( parts.length > 0 ) {
302

303
						for ( var ind = 0;ind < parts.length; ind++ ) {
304

305 306 307 308
							// the part should be a float
							if ( ! float_pattern.test( parts[ind] ) ) {
								continue;
							}
309

310 311
							this.angles.push( parseFloat( parts[ind] ) );
						}
312

313
					}
314

315 316 317 318 319
					// end
					if ( /]/.exec(line) ) {
						this.isRecordingAngles = false;
						node[this.recordingFieldname] = this.angles;
					}
320

321
				} else if (this.isRecordingColors) {
322

323
					while( null !== ( parts = float3_pattern.exec(line) ) ) {
324

325 326 327 328 329
						color = {
							r: parseFloat(parts[1]),
							g: parseFloat(parts[2]),
							b: parseFloat(parts[3])
						};
330

331
						this.colors.push(color);
332

333
					}
334

335 336 337 338 339
					// end
					if (/]/.exec(line)) {
						this.isRecordingColors = false;
						node[this.recordingFieldname] = this.colors;
					}
340

341
				} else if ( parts[parts.length -1] !== 'NULL' && fieldName !== 'children') {
342

343
					switch (fieldName) {
344

345 346 347 348
						case 'diffuseColor':
						case 'emissiveColor':
						case 'specularColor':
						case 'color':
349

350 351 352 353
							if (parts.length != 4) {
								console.warn('Invalid color format detected for ' + fieldName );
								break;
							}
354

355 356 357 358 359
							property = {
								'r'         : parseFloat(parts[1]),
								'g'         : parseFloat(parts[2]),
								'b'         : parseFloat(parts[3])
							}
360

361
							break;
362

363 364 365 366 367 368 369
						case 'translation':
						case 'scale':
						case 'size':
							if (parts.length != 4) {
								console.warn('Invalid vector format detected for ' + fieldName);
								break;
							}
370

371 372 373 374 375
							property = {
								'x'         : parseFloat(parts[1]),
								'y'         : parseFloat(parts[2]),
								'z'         : parseFloat(parts[3])
							}
376

377 378 379 380 381 382 383 384 385 386 387 388 389
							break;

						case 'radius':
						case 'topRadius':
						case 'bottomRadius':
						case 'height':
						case 'transparency':
						case 'shininess':
						case 'ambientIntensity':
							if (parts.length != 2) {
								console.warn('Invalid single float value specification detected for ' + fieldName);
								break;
							}
390

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
							property = parseFloat(parts[1]);

							break;

						case 'rotation':
							if (parts.length != 5) {
								console.warn('Invalid quaternion format detected for ' + fieldName);
								break;
							}

							property = {
								'x'         : parseFloat(parts[1]),
								'y'         : parseFloat(parts[2]),
								'z'         : parseFloat(parts[3]),
								'w'         : parseFloat(parts[4])
							}

							break;

						case 'ccw':
						case 'solid':
						case 'colorPerVertex':
						case 'convex':
							if (parts.length != 2) {
								console.warn('Invalid format detected for ' + fieldName);
								break;
							}

							property = parts[1] === 'TRUE' ? true : false;

							break;
					}

					node[fieldName] = property;
				}

				return property;
			};
M
Mr.doob 已提交
429 430 431 432 433

			var getTree = function ( lines ) {

				var tree = { 'string': 'Scene', children: [] };
				var current = tree;
434 435
				var matches;
				var specification;
M
Mr.doob 已提交
436 437 438

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

439
					var comment = '';
440

M
Mr.doob 已提交
441 442
					var line = lines[ i ];

443 444 445 446
					// omit whitespace only lines
					if ( null !== ( result = /^\s+?$/g.exec( line ) ) ) {
						continue;
					}
447

448
					line = line.trim();
449

450 451 452 453
					// skip empty lines
					if (line === '') {
						continue;
					}
454

455
					if ( /#/.exec( line ) ) {
M
Mr.doob 已提交
456

457
						var parts = line.split('#');
M
Mr.doob 已提交
458

459 460
						// discard everything after the #, it is a comment
						line = parts[0];
M
Mr.doob 已提交
461

462 463
						// well, let's also keep the comment
						comment = parts[1];
464
					}
465

466
					if ( matches = /([^\s]*){1}\s?{/.exec( line ) ) { // first subpattern should match the Node name
467

468
						var block = { 'nodeType' : matches[1], 'string': line, 'parent': current, 'children': [],'comment' : comment};
M
Mr.doob 已提交
469 470 471 472
						current.children.push( block );
						current = block;

						if ( /}/.exec( line ) ) {
473 474
							// example: geometry Box { size 1 1 1 } # all on the same line
							specification = /{(.*)}/.exec( line )[ 1 ];
475

476
							// todo: remove once new parsing is complete?
477 478
							block.children.push( specification );

479
							parseProperty(current, specification);
M
Mr.doob 已提交
480 481 482 483 484 485 486 487 488 489 490

							current = current.parent;

						}

					} else if ( /}/.exec( line ) ) {

						current = current.parent;

					} else if ( line !== '' ) {

491 492 493
						parseProperty(current, line);
						// todo: remove once new parsing is complete? we still do not parse geometry and appearance the new way
						current.children.push( line );
M
Mr.doob 已提交
494 495 496 497 498

					}

				}

499
				return tree;
M
Mr.doob 已提交
500 501 502 503 504 505 506 507 508 509
			}

			var parseNode = function ( data, parent ) {

				// console.log( data );

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

					if ( /USE/.exec( data ) ) {

510
						var defineKey = /USE\s+?(\w+)/.exec( data )[ 1 ];
M
Mr.doob 已提交
511

512 513 514
						if (undefined == defines[defineKey]) {
							console.warn(defineKey + ' is not defined.');
						} else {
M
Mr.doob 已提交
515

516
							if ( /appearance/.exec( data ) && defineKey ) {
B
Bart McLeod 已提交
517

518
								parent.material = defines[ defineKey ].clone();
B
Bart McLeod 已提交
519

520
							} else if ( /geometry/.exec( data ) && defineKey ) {
521

522
								parent.geometry = defines[ defineKey ].clone();
523

524 525 526 527 528
								// the solid property is not cloned with clone(), is only needed for VRML loading, so we need to transfer it
								if (undefined !== defines[ defineKey ].solid && defines[ defineKey ].solid === false) {
									parent.geometry.solid = false;
									parent.material.side = THREE.DoubleSide;
								}
529

530
							} else if (defineKey){
531

532 533
								var object = defines[ defineKey ].clone();
								parent.add( object );
B
Bart McLeod 已提交
534

535
							}
B
Bart McLeod 已提交
536

537
						}
M
Mr.doob 已提交
538 539 540 541 542 543 544 545 546

					}

					return;

				}

				var object = parent;

547 548
				if ( 'Transform' === data.nodeType || 'Group' === data.nodeType ) {

M
Mr.doob 已提交
549 550 551
					object = new THREE.Object3D();

					if ( /DEF/.exec( data.string ) ) {
552
						object.name = /DEF\s+(\w+)/.exec( data.string )[ 1 ];
M
Mr.doob 已提交
553 554 555
						defines[ object.name ] = object;
					}

556
					if ( undefined !== data['translation'] ) {
M
Mr.doob 已提交
557

558
						var t = data.translation;
M
Mr.doob 已提交
559

560
						object.position.set(t.x, t.y, t.z);
M
Mr.doob 已提交
561

562
					}
M
Mr.doob 已提交
563

564
					if ( undefined !== data.rotation ) {
M
Mr.doob 已提交
565

566
						var r = data.rotation;
567

568
						object.quaternion.setFromAxisAngle( new THREE.Vector3( r.x, r.y, r.z ), r.w );
M
Mr.doob 已提交
569

570
					}
M
Mr.doob 已提交
571

572
					if ( undefined !== data.scale ) {
M
Mr.doob 已提交
573

574
						var s = data.scale;
M
Mr.doob 已提交
575

576
						object.scale.set( s.x, s.y, s.z );
M
Mr.doob 已提交
577

578
					}
M
Mr.doob 已提交
579 580 581

					parent.add( object );

582
				} else if ( 'Shape' === data.nodeType ) {
M
Mr.doob 已提交
583 584 585 586

					object = new THREE.Mesh();

					if ( /DEF/.exec( data.string ) ) {
587

M
Mr.doob 已提交
588
						object.name = /DEF (\w+)/.exec( data.string )[ 1 ];
589

M
Mr.doob 已提交
590 591 592 593 594
						defines[ object.name ] = object;
					}

					parent.add( object );

595
				} else if ( 'Background' === data.nodeType ) {
M
Mr.doob 已提交
596

597
					var segments = 20;
598

599 600
					// sky (full sphere):
					var radius = 2e4;
601

602
					var skyGeometry = new THREE.SphereGeometry( radius, segments, segments );
603

604
					var skyMaterial = new THREE.MeshBasicMaterial( { color: 'white', vertexColors: THREE.VertexColors, shading: THREE.NoShading } );
605

606
					skyMaterial.side = THREE.BackSide;
607

608
					skyMaterial.fog = false;
609

610
					skyMaterial.color = new THREE.Color();
611

612
					paintFaces( skyGeometry, radius, data.skyAngle, data.skyColor, true );
613

614
					var sky = new THREE.Mesh( skyGeometry, skyMaterial );
615

616
					scene.add( sky );
617

618
					// ground (half sphere):
619

620
					radius = 1.2e4;
621

622
					var groundGeometry = new THREE.SphereGeometry( radius, segments, segments, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI );
623

624
					var groundMaterial = new THREE.MeshBasicMaterial( { color: 'white', vertexColors: THREE.VertexColors, shading: THREE.NoShading } );
625

626
					groundMaterial.side = THREE.BackSide;
627

628
					groundMaterial.fog = false;
629

630
					groundMaterial.color = new THREE.Color();
631

632
					paintFaces( groundGeometry, radius, data.groundAngle, data.groundColor, false );
633

634
					var ground = new THREE.Mesh( groundGeometry, groundMaterial );
635

636
					scene.add( ground );
M
Mr.doob 已提交
637

638
				} else if ( /geometry/.exec( data.string ) ) {
M
Mr.doob 已提交
639

640
					if ( 'Box' === data.nodeType ) {
M
Mr.doob 已提交
641

642
						var s = data.size;
M
Mr.doob 已提交
643

M
Mr.doob 已提交
644
						parent.geometry = new THREE.BoxGeometry( s.x, s.y, s.z );
M
Mr.doob 已提交
645

646
					} else if ( 'Cylinder' === data.nodeType ) {
M
Mr.doob 已提交
647

648
						parent.geometry = new THREE.CylinderGeometry( data.radius, data.radius, data.height );
M
Mr.doob 已提交
649

650
					} else if ( 'Cone' === data.nodeType ) {
M
Mr.doob 已提交
651

652
						parent.geometry = new THREE.CylinderGeometry( data.topRadius, data.bottomRadius, data.height );
M
Mr.doob 已提交
653

654
					} else if ( 'Sphere' === data.nodeType ) {
M
Mr.doob 已提交
655

656
						parent.geometry = new THREE.SphereGeometry( data.radius );
M
Mr.doob 已提交
657

658
					} else if ( 'IndexedFaceSet' === data.nodeType ) {
659

660
						var geometry = new THREE.Geometry();
661

662
						var indexes;
663

664
						for ( var i = 0, j = data.children.length; i < j; i++ ) {
665

666
							var child = data.children[ i ];
667

668
							var vec;
669

670
							if ( 'Coordinate' === child.nodeType ) {
671

672
								for ( var k = 0, l = child.points.length; k < l; k++ ) {
673

674
									var point = child.points[ k ];
675

676
									vec = new THREE.Vector3( point.x, point.y, point.z );
677

678 679
									geometry.vertices.push( vec );
								}
680

681 682 683
								break;
							}
						}
684

685
						var skip = 0;
686

687 688
						// read this: http://math.hws.edu/eck/cs424/notes2013/16_Threejs_Advanced.html
						for ( var i = 0, j = data.coordIndex.length; i < j; i++ ) {
689

690
							indexes = data.coordIndex[i];
691

692 693
							// vrml support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
							skip = 0;
694

695
							// todo: this is the time to check if the faces are ordered ccw or not (cw)
696

697 698
							// Face3 only works with triangles, but IndexedFaceSet allows shapes with more then three vertices, build them of triangles
							while ( indexes.length >= 3 && skip < ( indexes.length -2 ) ) {
699

700 701 702 703 704 705 706
								var face = new THREE.Face3(
									indexes[0],
									indexes[skip + 1],
									indexes[skip + 2],
									null // normal, will be added later
									// todo: pass in the color, if a color index is present
								);
707

708
								skip++;
709

710
								geometry.faces.push( face );
711

712
							}
713 714


715
						}
716

717 718 719
						if ( false === data.solid ) {
							parent.material.side = THREE.DoubleSide;
						}
720

721 722
						// we need to store it on the geometry for use with defines
						geometry.solid = data.solid;
723

724 725 726
						geometry.computeFaceNormals();
						//geometry.computeVertexNormals(); // does not show
						geometry.computeBoundingSphere();
727

728 729 730 731 732
						// see if it's a define
						if ( /DEF/.exec( data.string ) ) {
							geometry.name = /DEF (\w+)/.exec( data.string )[ 1 ];
							defines[ geometry.name ] = geometry;
						}
733

734
						parent.geometry = geometry;
M
Mr.doob 已提交
735 736 737 738 739 740 741 742 743 744
					}

					return;

				} else if ( /appearance/.exec( data.string ) ) {

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

						var child = data.children[ i ];

745
						if ( 'Material' === child.nodeType ) {
M
Mr.doob 已提交
746 747
							var material = new THREE.MeshPhongMaterial();

748
							if ( undefined !== child.diffuseColor ) {
M
Mr.doob 已提交
749

750
								var d = child.diffuseColor;
M
Mr.doob 已提交
751

752
								material.color.setRGB( d.r, d.g, d.b );
M
Mr.doob 已提交
753

754
							}
M
Mr.doob 已提交
755

756
							if ( undefined !== child.emissiveColor ) {
M
Mr.doob 已提交
757

758
								var e = child.emissiveColor;
M
Mr.doob 已提交
759

760
								material.emissive.setRGB( e.r, e.g, e.b );
M
Mr.doob 已提交
761

762
							}
M
Mr.doob 已提交
763

764
							if ( undefined !== child.specularColor ) {
M
Mr.doob 已提交
765

766
								var s = child.specularColor;
M
Mr.doob 已提交
767

768
								material.specular.setRGB( s.r, s.g, s.b );
M
Mr.doob 已提交
769

770
							}
M
Mr.doob 已提交
771

772
							if ( undefined !== child.transparency ) {
M
Mr.doob 已提交
773

774
								var t = child.transparency;
775

776 777
								// transparency is opposite of opacity
								material.opacity = Math.abs( 1 - t );
778

779
								material.transparent = true;
780

781
							}
M
Mr.doob 已提交
782 783 784 785

							if ( /DEF/.exec( data.string ) ) {

								material.name = /DEF (\w+)/.exec( data.string )[ 1 ];
786

M
Mr.doob 已提交
787 788 789 790
								defines[ material.name ] = material;

							}

791
							parent.material = material;
M
Mr.doob 已提交
792

793 794
							// material found, stop looping
							break;
M
Mr.doob 已提交
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
						}

					}

					return;

				}

				for ( var i = 0, l = data.children.length; i < l; i ++ ) {

					var child = data.children[ i ];

					parseNode( data.children[ i ], object );

				}

			}

			parseNode( getTree( lines ), scene );

		};

		var scene = new THREE.Scene();

		var lines = data.split( '\n' );
820

M
Mr.doob 已提交
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
		var header = lines.shift();

		if ( /V1.0/.exec( header ) ) {

			parseV1( lines, scene );

		} else if ( /V2.0/.exec( header ) ) {

			parseV2( lines, scene );

		}

		return scene;

	}

};
M
Mr.doob 已提交
838 839

THREE.EventDispatcher.prototype.apply( THREE.VRMLLoader.prototype );
840