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

M
r72  
Mr.doob 已提交
5 6 7 8 9
THREE.VRMLLoader = function ( manager ) {

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

};
M
r59  
Mr.doob 已提交
10 11 12

THREE.VRMLLoader.prototype = {

M
r62  
Mr.doob 已提交
13
	constructor: THREE.VRMLLoader,
M
r59  
Mr.doob 已提交
14

M
r66  
Mr.doob 已提交
15 16 17 18
	// for IndexedFaceSet support
	isRecordingPoints: false,
	isRecordingFaces: false,
	points: [],
M
r88  
Mr.doob 已提交
19
	indexes: [],
M
r63  
Mr.doob 已提交
20

M
r66  
Mr.doob 已提交
21 22 23 24 25
	// for Background support
	isRecordingAngles: false,
	isRecordingColors: false,
	angles: [],
	colors: [],
M
r63  
Mr.doob 已提交
26

M
r66  
Mr.doob 已提交
27
	recordingFieldname: null,
M
r63  
Mr.doob 已提交
28

M
r94  
Mr.doob 已提交
29
	crossOrigin: 'anonymous',
M
r87  
Mr.doob 已提交
30

M
r72  
Mr.doob 已提交
31
	load: function ( url, onLoad, onProgress, onError ) {
M
r59  
Mr.doob 已提交
32 33 34

		var scope = this;

M
r97  
Mr.doob 已提交
35 36
		var path = ( scope.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : scope.path;

M
r83  
Mr.doob 已提交
37
		var loader = new THREE.FileLoader( this.manager );
M
r97  
Mr.doob 已提交
38
		loader.setPath( scope.path );
M
r72  
Mr.doob 已提交
39
		loader.load( url, function ( text ) {
M
r66  
Mr.doob 已提交
40

M
r97  
Mr.doob 已提交
41
			onLoad( scope.parse( text, path ) );
M
r59  
Mr.doob 已提交
42

M
r72  
Mr.doob 已提交
43
		}, onProgress, onError );
M
r59  
Mr.doob 已提交
44

M
r72  
Mr.doob 已提交
45
	},
M
r59  
Mr.doob 已提交
46

M
r97  
Mr.doob 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60
	setPath: function ( value ) {

		this.path = value;
		return this;

	},

	setResourcePath: function ( value ) {

		this.resourcePath = value;
		return this;

	},

M
r72  
Mr.doob 已提交
61
	setCrossOrigin: function ( value ) {
M
r59  
Mr.doob 已提交
62

M
r72  
Mr.doob 已提交
63
		this.crossOrigin = value;
M
r94  
Mr.doob 已提交
64
		return this;
M
r59  
Mr.doob 已提交
65 66 67

	},

M
r97  
Mr.doob 已提交
68
	parse: function ( data, path ) {
M
r59  
Mr.doob 已提交
69

M
r96  
Mr.doob 已提交
70
		var scope = this;
M
r73  
Mr.doob 已提交
71

M
r74  
Mr.doob 已提交
72
		var textureLoader = new THREE.TextureLoader( this.manager );
M
r97  
Mr.doob 已提交
73
		textureLoader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
M
r74  
Mr.doob 已提交
74

M
r88  
Mr.doob 已提交
75
		function parseV2( lines, scene ) {
M
r69  
Mr.doob 已提交
76

M
r66  
Mr.doob 已提交
77 78
			var defines = {};
			var float_pattern = /(\b|\-|\+)([\d\.e]+)/;
M
r73  
Mr.doob 已提交
79
			var float2_pattern = /([\d\.\+\-e]+)\s+([\d\.\+\-e]+)/g;
M
r69  
Mr.doob 已提交
80
			var float3_pattern = /([\d\.\+\-e]+)\s+([\d\.\+\-e]+)\s+([\d\.\+\-e]+)/g;
M
r66  
Mr.doob 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

			/**
			 * 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
M
r88  
Mr.doob 已提交
102
			 * @param boolean topDown Whether to work top down or bottom up.
M
r66  
Mr.doob 已提交
103
			 */
M
r88  
Mr.doob 已提交
104
			function paintFaces( geometry, radius, angles, colors, topDown ) {
M
r66  
Mr.doob 已提交
105

M
r88  
Mr.doob 已提交
106
				var direction = ( topDown === true ) ? 1 : - 1;
M
r66  
Mr.doob 已提交
107

M
r86  
Mr.doob 已提交
108
				var coord = [], A = {}, B = {}, applyColor = false;
M
r66  
Mr.doob 已提交
109

M
r71  
Mr.doob 已提交
110
				for ( var k = 0; k < angles.length; k ++ ) {
M
r66  
Mr.doob 已提交
111 112 113

					// push the vector at which the color changes

M
r86  
Mr.doob 已提交
114 115 116 117
					var vec = {
						x: direction * ( Math.cos( angles[ k ] ) * radius ),
						y: direction * ( Math.sin( angles[ k ] ) * radius )
					};
M
r66  
Mr.doob 已提交
118 119 120 121 122

					coord.push( vec );

				}

M
r88  
Mr.doob 已提交
123 124 125
				var index = geometry.index;
				var positionAttribute = geometry.attributes.position;
				var colorAttribute = new THREE.BufferAttribute( new Float32Array( geometry.attributes.position.count * 3 ), 3 );
M
r66  
Mr.doob 已提交
126

M
r88  
Mr.doob 已提交
127 128
				var position = new THREE.Vector3();
				var color = new THREE.Color();
M
r66  
Mr.doob 已提交
129

M
r88  
Mr.doob 已提交
130
				for ( var i = 0; i < index.count; i ++ ) {
M
r66  
Mr.doob 已提交
131

M
r88  
Mr.doob 已提交
132
					var vertexIndex = index.getX( i );
M
r66  
Mr.doob 已提交
133

M
r88  
Mr.doob 已提交
134
					position.fromBufferAttribute( positionAttribute, vertexIndex );
M
r66  
Mr.doob 已提交
135

M
r88  
Mr.doob 已提交
136
					for ( var j = 0; j < colors.length; j ++ ) {
M
r66  
Mr.doob 已提交
137

M
r88  
Mr.doob 已提交
138 139
						// linear interpolation between aColor and bColor, calculate proportion
						// A is previous point (angle)
M
r66  
Mr.doob 已提交
140

M
r88  
Mr.doob 已提交
141
						if ( j === 0 ) {
M
r66  
Mr.doob 已提交
142

M
r88  
Mr.doob 已提交
143 144
							A.x = 0;
							A.y = ( topDown === true ) ? radius : - 1 * radius;
M
r66  
Mr.doob 已提交
145

M
r88  
Mr.doob 已提交
146
						} else {
M
r66  
Mr.doob 已提交
147

M
r88  
Mr.doob 已提交
148 149
							A.x = coord[ j - 1 ].x;
							A.y = coord[ j - 1 ].y;
M
r66  
Mr.doob 已提交
150

M
r88  
Mr.doob 已提交
151
						}
M
r63  
Mr.doob 已提交
152

M
r88  
Mr.doob 已提交
153
						// B is current point (angle)
M
r63  
Mr.doob 已提交
154

M
r88  
Mr.doob 已提交
155
						B = coord[ j ];
M
r72  
Mr.doob 已提交
156

M
r88  
Mr.doob 已提交
157
						if ( B !== undefined ) {
M
r63  
Mr.doob 已提交
158

M
r88  
Mr.doob 已提交
159
							// p has to be between the points A and B which we interpolate
M
r63  
Mr.doob 已提交
160

M
r88  
Mr.doob 已提交
161
							applyColor = ( topDown === true ) ? ( position.y <= A.y && position.y > B.y ) : ( position.y >= A.y && position.y < B.y );
M
r63  
Mr.doob 已提交
162

M
r88  
Mr.doob 已提交
163
							if ( applyColor === true ) {
M
r63  
Mr.doob 已提交
164

M
r88  
Mr.doob 已提交
165 166
								var aColor = colors[ j ];
								var bColor = colors[ j + 1 ];
M
r63  
Mr.doob 已提交
167

M
r88  
Mr.doob 已提交
168
								// below is simple linear interpolation
M
r72  
Mr.doob 已提交
169

M
r88  
Mr.doob 已提交
170 171 172
								var t = Math.abs( position.y - A.y ) / ( A.y - B.y );

								// 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
M
r63  
Mr.doob 已提交
173

M
r88  
Mr.doob 已提交
174
								color.copy( aColor ).lerp( bColor, t );
M
r72  
Mr.doob 已提交
175

M
r88  
Mr.doob 已提交
176 177 178 179 180 181 182
								colorAttribute.setXYZ( vertexIndex, color.r, color.g, color.b );

							} else {

								var colorIndex = ( topDown === true ) ? colors.length - 1 : 0;
								var c = colors[ colorIndex ];
								colorAttribute.setXYZ( vertexIndex, c.r, c.g, c.b );
M
r63  
Mr.doob 已提交
183

M
r66  
Mr.doob 已提交
184
							}
M
r72  
Mr.doob 已提交
185

M
r66  
Mr.doob 已提交
186 187 188
						}

					}
M
r63  
Mr.doob 已提交
189

M
r66  
Mr.doob 已提交
190
				}
M
r72  
Mr.doob 已提交
191

M
r88  
Mr.doob 已提交
192 193 194
				geometry.addAttribute( 'color', colorAttribute );

			}
M
r66  
Mr.doob 已提交
195

M
Mr.doob 已提交
196 197
			var index = [];

M
r88  
Mr.doob 已提交
198
			function parseProperty( node, line ) {
M
r63  
Mr.doob 已提交
199

M
r66  
Mr.doob 已提交
200
				var parts = [], part, property = {}, fieldName;
M
r63  
Mr.doob 已提交
201

M
r66  
Mr.doob 已提交
202 203 204 205 206
				/**
				 * Expression for matching relevant information, such as a name or value, but not the separators
				 * @type {RegExp}
				 */
				var regex = /[^\s,\[\]]+/g;
M
r63  
Mr.doob 已提交
207

M
r88  
Mr.doob 已提交
208
				var point;
M
r63  
Mr.doob 已提交
209

M
r88  
Mr.doob 已提交
210
				while ( null !== ( part = regex.exec( line ) ) ) {
M
r72  
Mr.doob 已提交
211 212 213

					parts.push( part[ 0 ] );

M
r66  
Mr.doob 已提交
214
				}
M
r63  
Mr.doob 已提交
215

M
r72  
Mr.doob 已提交
216
				fieldName = parts[ 0 ];
M
r66  
Mr.doob 已提交
217 218 219


				// trigger several recorders
M
r72  
Mr.doob 已提交
220
				switch ( fieldName ) {
M
r88  
Mr.doob 已提交
221

M
r66  
Mr.doob 已提交
222 223
					case 'skyAngle':
					case 'groundAngle':
M
r96  
Mr.doob 已提交
224 225 226
						scope.recordingFieldname = fieldName;
						scope.isRecordingAngles = true;
						scope.angles = [];
M
r66  
Mr.doob 已提交
227
						break;
M
r88  
Mr.doob 已提交
228

M
r97  
Mr.doob 已提交
229
					case 'color':
M
r66  
Mr.doob 已提交
230 231
					case 'skyColor':
					case 'groundColor':
M
r96  
Mr.doob 已提交
232 233 234
						scope.recordingFieldname = fieldName;
						scope.isRecordingColors = true;
						scope.colors = [];
M
r66  
Mr.doob 已提交
235
						break;
M
r88  
Mr.doob 已提交
236

M
r66  
Mr.doob 已提交
237
					case 'point':
M
r97  
Mr.doob 已提交
238
					case 'vector':
M
r96  
Mr.doob 已提交
239 240 241
						scope.recordingFieldname = fieldName;
						scope.isRecordingPoints = true;
						scope.points = [];
M
r66  
Mr.doob 已提交
242
						break;
M
r88  
Mr.doob 已提交
243

M
r97  
Mr.doob 已提交
244
					case 'colorIndex':
M
r66  
Mr.doob 已提交
245
					case 'coordIndex':
M
r97  
Mr.doob 已提交
246
					case 'normalIndex':
M
r73  
Mr.doob 已提交
247
					case 'texCoordIndex':
M
r96  
Mr.doob 已提交
248 249 250
						scope.recordingFieldname = fieldName;
						scope.isRecordingFaces = true;
						scope.indexes = [];
M
r88  
Mr.doob 已提交
251 252
						break;

M
r66  
Mr.doob 已提交
253
				}
M
r63  
Mr.doob 已提交
254

M
r96  
Mr.doob 已提交
255
				if ( scope.isRecordingFaces ) {
M
r63  
Mr.doob 已提交
256

M
r66  
Mr.doob 已提交
257
					// the parts hold the indexes as strings
M
r72  
Mr.doob 已提交
258 259 260
					if ( parts.length > 0 ) {

						for ( var ind = 0; ind < parts.length; ind ++ ) {
M
r63  
Mr.doob 已提交
261

M
r66  
Mr.doob 已提交
262
							// the part should either be positive integer or -1
M
r72  
Mr.doob 已提交
263 264
							if ( ! /(-?\d+)/.test( parts[ ind ] ) ) {

M
r66  
Mr.doob 已提交
265
								continue;
M
r72  
Mr.doob 已提交
266

M
r66  
Mr.doob 已提交
267
							}
M
r63  
Mr.doob 已提交
268

M
r66  
Mr.doob 已提交
269
							// end of current face
M
r88  
Mr.doob 已提交
270
							if ( parts[ ind ] === '-1' ) {
M
r72  
Mr.doob 已提交
271 272 273

								if ( index.length > 0 ) {

M
r96  
Mr.doob 已提交
274
									scope.indexes.push( index );
M
r72  
Mr.doob 已提交
275

M
r66  
Mr.doob 已提交
276
								}
M
r63  
Mr.doob 已提交
277

M
r66  
Mr.doob 已提交
278 279
								// start new one
								index = [];
M
r72  
Mr.doob 已提交
280

M
r66  
Mr.doob 已提交
281
							} else {
M
r72  
Mr.doob 已提交
282 283 284

								index.push( parseInt( parts[ ind ] ) );

M
r66  
Mr.doob 已提交
285
							}
M
r72  
Mr.doob 已提交
286

M
r66  
Mr.doob 已提交
287
						}
M
r63  
Mr.doob 已提交
288

M
r66  
Mr.doob 已提交
289
					}
M
r63  
Mr.doob 已提交
290

M
r66  
Mr.doob 已提交
291
					// end
M
r72  
Mr.doob 已提交
292 293
					if ( /]/.exec( line ) ) {

M
Mr.doob 已提交
294 295
						if ( index.length > 0 ) {

M
r96  
Mr.doob 已提交
296
							scope.indexes.push( index );
M
Mr.doob 已提交
297 298 299 300 301 302

						}

						// start new one
						index = [];

M
r96  
Mr.doob 已提交
303 304
						scope.isRecordingFaces = false;
						node[ scope.recordingFieldname ] = scope.indexes;
M
r72  
Mr.doob 已提交
305

M
r66  
Mr.doob 已提交
306
					}
M
r63  
Mr.doob 已提交
307

M
r96  
Mr.doob 已提交
308
				} else if ( scope.isRecordingPoints ) {
M
r72  
Mr.doob 已提交
309

M
r88  
Mr.doob 已提交
310
					if ( node.nodeType == 'Coordinate' ) {
M
r73  
Mr.doob 已提交
311

M
r88  
Mr.doob 已提交
312
						while ( null !== ( parts = float3_pattern.exec( line ) ) ) {
M
r63  
Mr.doob 已提交
313

M
r88  
Mr.doob 已提交
314 315 316 317 318
							point = {
								x: parseFloat( parts[ 1 ] ),
								y: parseFloat( parts[ 2 ] ),
								z: parseFloat( parts[ 3 ] )
							};
M
r63  
Mr.doob 已提交
319

M
r96  
Mr.doob 已提交
320
							scope.points.push( point );
M
r88  
Mr.doob 已提交
321 322

						}
M
r72  
Mr.doob 已提交
323

M
r66  
Mr.doob 已提交
324
					}
M
r63  
Mr.doob 已提交
325

M
r97  
Mr.doob 已提交
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
					if ( node.nodeType == 'Normal' ) {

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

							point = {
								x: parseFloat( parts[ 1 ] ),
								y: parseFloat( parts[ 2 ] ),
								z: parseFloat( parts[ 3 ] )
							};

							scope.points.push( point );

						}

					}

M
r88  
Mr.doob 已提交
342
					if ( node.nodeType == 'TextureCoordinate' ) {
M
r73  
Mr.doob 已提交
343

M
r88  
Mr.doob 已提交
344
						while ( null !== ( parts = float2_pattern.exec( line ) ) ) {
M
r73  
Mr.doob 已提交
345

M
r88  
Mr.doob 已提交
346 347 348 349
							point = {
								x: parseFloat( parts[ 1 ] ),
								y: parseFloat( parts[ 2 ] )
							};
M
r73  
Mr.doob 已提交
350

M
r96  
Mr.doob 已提交
351
							scope.points.push( point );
M
r88  
Mr.doob 已提交
352 353

						}
M
r73  
Mr.doob 已提交
354 355 356

					}

M
r66  
Mr.doob 已提交
357
					// end
M
r72  
Mr.doob 已提交
358 359
					if ( /]/.exec( line ) ) {

M
r96  
Mr.doob 已提交
360 361
						scope.isRecordingPoints = false;
						node.points = scope.points;
M
r72  
Mr.doob 已提交
362

M
r66  
Mr.doob 已提交
363
					}
M
r63  
Mr.doob 已提交
364

M
r96  
Mr.doob 已提交
365
				} else if ( scope.isRecordingAngles ) {
M
r63  
Mr.doob 已提交
366

M
r66  
Mr.doob 已提交
367 368
					// the parts hold the angles as strings
					if ( parts.length > 0 ) {
M
r63  
Mr.doob 已提交
369

M
r71  
Mr.doob 已提交
370
						for ( var ind = 0; ind < parts.length; ind ++ ) {
M
r63  
Mr.doob 已提交
371

M
r66  
Mr.doob 已提交
372
							// the part should be a float
M
r72  
Mr.doob 已提交
373 374
							if ( ! float_pattern.test( parts[ ind ] ) ) {

M
r66  
Mr.doob 已提交
375
								continue;
M
r72  
Mr.doob 已提交
376

M
r66  
Mr.doob 已提交
377
							}
M
r63  
Mr.doob 已提交
378

M
r96  
Mr.doob 已提交
379
							scope.angles.push( parseFloat( parts[ ind ] ) );
M
r72  
Mr.doob 已提交
380

M
r66  
Mr.doob 已提交
381
						}
M
r63  
Mr.doob 已提交
382

M
r66  
Mr.doob 已提交
383
					}
M
r63  
Mr.doob 已提交
384

M
r66  
Mr.doob 已提交
385
					// end
M
r72  
Mr.doob 已提交
386 387
					if ( /]/.exec( line ) ) {

M
r96  
Mr.doob 已提交
388 389
						scope.isRecordingAngles = false;
						node[ scope.recordingFieldname ] = scope.angles;
M
r72  
Mr.doob 已提交
390

M
r66  
Mr.doob 已提交
391
					}
M
r63  
Mr.doob 已提交
392

M
r96  
Mr.doob 已提交
393
				} else if ( scope.isRecordingColors ) {
M
r63  
Mr.doob 已提交
394

M
r72  
Mr.doob 已提交
395
					while ( null !== ( parts = float3_pattern.exec( line ) ) ) {
M
r63  
Mr.doob 已提交
396

M
r86  
Mr.doob 已提交
397
						var color = {
M
r72  
Mr.doob 已提交
398 399 400
							r: parseFloat( parts[ 1 ] ),
							g: parseFloat( parts[ 2 ] ),
							b: parseFloat( parts[ 3 ] )
M
r66  
Mr.doob 已提交
401
						};
M
r63  
Mr.doob 已提交
402

M
r96  
Mr.doob 已提交
403
						scope.colors.push( color );
M
r63  
Mr.doob 已提交
404

M
r66  
Mr.doob 已提交
405
					}
M
r63  
Mr.doob 已提交
406

M
r66  
Mr.doob 已提交
407
					// end
M
r72  
Mr.doob 已提交
408 409
					if ( /]/.exec( line ) ) {

M
r96  
Mr.doob 已提交
410 411
						scope.isRecordingColors = false;
						node[ scope.recordingFieldname ] = scope.colors;
M
r72  
Mr.doob 已提交
412

M
r66  
Mr.doob 已提交
413
					}
M
r63  
Mr.doob 已提交
414

M
r72  
Mr.doob 已提交
415
				} else if ( parts[ parts.length - 1 ] !== 'NULL' && fieldName !== 'children' ) {
M
r63  
Mr.doob 已提交
416

M
r72  
Mr.doob 已提交
417
					switch ( fieldName ) {
M
r63  
Mr.doob 已提交
418

M
r66  
Mr.doob 已提交
419 420 421 422
						case 'diffuseColor':
						case 'emissiveColor':
						case 'specularColor':
						case 'color':
M
r63  
Mr.doob 已提交
423

M
r88  
Mr.doob 已提交
424
							if ( parts.length !== 4 ) {
M
r72  
Mr.doob 已提交
425

M
r88  
Mr.doob 已提交
426
								console.warn( 'THREE.VRMLLoader: Invalid color format detected for %s.', fieldName );
M
r66  
Mr.doob 已提交
427
								break;
M
r72  
Mr.doob 已提交
428

M
r66  
Mr.doob 已提交
429
							}
M
r63  
Mr.doob 已提交
430

M
r66  
Mr.doob 已提交
431
							property = {
M
r72  
Mr.doob 已提交
432 433 434 435
								r: parseFloat( parts[ 1 ] ),
								g: parseFloat( parts[ 2 ] ),
								b: parseFloat( parts[ 3 ] )
							};
M
r63  
Mr.doob 已提交
436

M
r66  
Mr.doob 已提交
437
							break;
M
r86  
Mr.doob 已提交
438

M
r83  
Mr.doob 已提交
439 440
						case 'location':
						case 'direction':
M
r66  
Mr.doob 已提交
441 442 443
						case 'translation':
						case 'scale':
						case 'size':
M
r88  
Mr.doob 已提交
444
							if ( parts.length !== 4 ) {
M
r72  
Mr.doob 已提交
445

M
r88  
Mr.doob 已提交
446
								console.warn( 'THREE.VRMLLoader: Invalid vector format detected for %s.', fieldName );
M
r66  
Mr.doob 已提交
447
								break;
M
r72  
Mr.doob 已提交
448

M
r66  
Mr.doob 已提交
449
							}
M
r63  
Mr.doob 已提交
450

M
r66  
Mr.doob 已提交
451
							property = {
M
r72  
Mr.doob 已提交
452 453 454 455
								x: parseFloat( parts[ 1 ] ),
								y: parseFloat( parts[ 2 ] ),
								z: parseFloat( parts[ 3 ] )
							};
M
r63  
Mr.doob 已提交
456

M
r66  
Mr.doob 已提交
457 458
							break;

M
r86  
Mr.doob 已提交
459
						case 'intensity':
M
r83  
Mr.doob 已提交
460
						case 'cutOffAngle':
M
r66  
Mr.doob 已提交
461 462 463 464 465 466 467
						case 'radius':
						case 'topRadius':
						case 'bottomRadius':
						case 'height':
						case 'transparency':
						case 'shininess':
						case 'ambientIntensity':
M
r97  
Mr.doob 已提交
468
						case 'creaseAngle':
M
r88  
Mr.doob 已提交
469
							if ( parts.length !== 2 ) {
M
r72  
Mr.doob 已提交
470

M
r88  
Mr.doob 已提交
471
								console.warn( 'THREE.VRMLLoader: Invalid single float value specification detected for %s.', fieldName );
M
r66  
Mr.doob 已提交
472
								break;
M
r72  
Mr.doob 已提交
473

M
r66  
Mr.doob 已提交
474
							}
M
r63  
Mr.doob 已提交
475

M
r72  
Mr.doob 已提交
476
							property = parseFloat( parts[ 1 ] );
M
r63  
Mr.doob 已提交
477

M
r66  
Mr.doob 已提交
478
							break;
M
r63  
Mr.doob 已提交
479

M
r66  
Mr.doob 已提交
480
						case 'rotation':
M
r88  
Mr.doob 已提交
481
							if ( parts.length !== 5 ) {
M
r72  
Mr.doob 已提交
482

M
r88  
Mr.doob 已提交
483
								console.warn( 'THREE.VRMLLoader: Invalid quaternion format detected for %s.', fieldName );
M
r66  
Mr.doob 已提交
484
								break;
M
r72  
Mr.doob 已提交
485

M
r66  
Mr.doob 已提交
486
							}
M
r63  
Mr.doob 已提交
487

M
r66  
Mr.doob 已提交
488
							property = {
M
r72  
Mr.doob 已提交
489 490 491 492 493
								x: parseFloat( parts[ 1 ] ),
								y: parseFloat( parts[ 2 ] ),
								z: parseFloat( parts[ 3 ] ),
								w: parseFloat( parts[ 4 ] )
							};
M
r63  
Mr.doob 已提交
494

M
r66  
Mr.doob 已提交
495
							break;
M
r86  
Mr.doob 已提交
496

M
r83  
Mr.doob 已提交
497
						case 'on':
M
r66  
Mr.doob 已提交
498 499 500 501
						case 'ccw':
						case 'solid':
						case 'colorPerVertex':
						case 'convex':
M
r88  
Mr.doob 已提交
502
							if ( parts.length !== 2 ) {
M
r72  
Mr.doob 已提交
503

M
r88  
Mr.doob 已提交
504
								console.warn( 'THREE.VRMLLoader: Invalid format detected for %s.', fieldName );
M
r66  
Mr.doob 已提交
505
								break;
M
r72  
Mr.doob 已提交
506

M
r66  
Mr.doob 已提交
507
							}
M
r63  
Mr.doob 已提交
508

M
r72  
Mr.doob 已提交
509
							property = parts[ 1 ] === 'TRUE' ? true : false;
M
r63  
Mr.doob 已提交
510

M
r66  
Mr.doob 已提交
511
							break;
M
r88  
Mr.doob 已提交
512

M
r66  
Mr.doob 已提交
513
					}
M
r63  
Mr.doob 已提交
514

M
r104  
Mr.doob 已提交
515 516 517
					// VRMLLoader does not support text so it can't process the "string" property yet

					if ( fieldName !== 'string' ) node[ fieldName ] = property;
M
r72  
Mr.doob 已提交
518

M
r66  
Mr.doob 已提交
519
				}
M
r63  
Mr.doob 已提交
520

M
r66  
Mr.doob 已提交
521
				return property;
M
r72  
Mr.doob 已提交
522

M
r88  
Mr.doob 已提交
523
			}
M
r59  
Mr.doob 已提交
524

M
r88  
Mr.doob 已提交
525
			function getTree( lines ) {
M
r59  
Mr.doob 已提交
526 527 528

				var tree = { 'string': 'Scene', children: [] };
				var current = tree;
M
r66  
Mr.doob 已提交
529 530
				var matches;
				var specification;
M
r59  
Mr.doob 已提交
531 532 533

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

M
r66  
Mr.doob 已提交
534
					var comment = '';
M
r62  
Mr.doob 已提交
535

M
r59  
Mr.doob 已提交
536 537
					var line = lines[ i ];

M
r66  
Mr.doob 已提交
538
					// omit whitespace only lines
M
r88  
Mr.doob 已提交
539
					if ( null !== ( /^\s+?$/g.exec( line ) ) ) {
M
r72  
Mr.doob 已提交
540

M
r66  
Mr.doob 已提交
541
						continue;
M
r72  
Mr.doob 已提交
542

M
r66  
Mr.doob 已提交
543
					}
M
r62  
Mr.doob 已提交
544

M
r66  
Mr.doob 已提交
545
					line = line.trim();
M
r63  
Mr.doob 已提交
546

M
r66  
Mr.doob 已提交
547
					// skip empty lines
M
r72  
Mr.doob 已提交
548 549
					if ( line === '' ) {

M
r66  
Mr.doob 已提交
550
						continue;
M
r72  
Mr.doob 已提交
551

M
r66  
Mr.doob 已提交
552
					}
M
r63  
Mr.doob 已提交
553

M
r62  
Mr.doob 已提交
554 555
					if ( /#/.exec( line ) ) {

M
r72  
Mr.doob 已提交
556
						var parts = line.split( '#' );
M
r59  
Mr.doob 已提交
557

M
r66  
Mr.doob 已提交
558
						// discard everything after the #, it is a comment
M
r72  
Mr.doob 已提交
559
						line = parts[ 0 ];
M
r59  
Mr.doob 已提交
560

M
r66  
Mr.doob 已提交
561
						// well, let's also keep the comment
M
r72  
Mr.doob 已提交
562 563
						comment = parts[ 1 ];

M
r62  
Mr.doob 已提交
564
					}
M
r63  
Mr.doob 已提交
565

M
r73  
Mr.doob 已提交
566
					if ( matches = /([^\s]*){1}(?:\s+)?{/.exec( line ) ) {
M
r59  
Mr.doob 已提交
567

M
r72  
Mr.doob 已提交
568 569
						// first subpattern should match the Node name

M
r88  
Mr.doob 已提交
570
						var block = { 'nodeType': matches[ 1 ], 'string': line, 'parent': current, 'children': [], 'comment': comment };
M
r59  
Mr.doob 已提交
571 572 573 574
						current.children.push( block );
						current = block;

						if ( /}/.exec( line ) ) {
M
r72  
Mr.doob 已提交
575

M
r66  
Mr.doob 已提交
576 577
							// example: geometry Box { size 1 1 1 } # all on the same line
							specification = /{(.*)}/.exec( line )[ 1 ];
M
r63  
Mr.doob 已提交
578

M
r66  
Mr.doob 已提交
579
							// todo: remove once new parsing is complete?
M
r63  
Mr.doob 已提交
580 581
							block.children.push( specification );

M
r72  
Mr.doob 已提交
582
							parseProperty( current, specification );
M
r59  
Mr.doob 已提交
583 584 585 586 587 588 589 590 591 592 593

							current = current.parent;

						}

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

						current = current.parent;

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

M
r72  
Mr.doob 已提交
594
						parseProperty( current, line );
M
r66  
Mr.doob 已提交
595 596
						// todo: remove once new parsing is complete? we still do not parse geometry and appearance the new way
						current.children.push( line );
M
r59  
Mr.doob 已提交
597 598 599 600 601

					}

				}

M
r66  
Mr.doob 已提交
602
				return tree;
M
r72  
Mr.doob 已提交
603

M
r88  
Mr.doob 已提交
604
			}
M
r59  
Mr.doob 已提交
605

M
r88  
Mr.doob 已提交
606
			function parseNode( data, parent ) {
M
r59  
Mr.doob 已提交
607

M
r88  
Mr.doob 已提交
608
				var object;
M
r59  
Mr.doob 已提交
609 610 611 612 613

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

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

M
r75  
Mr.doob 已提交
614
						var defineKey = /USE\s+?([^\s]+)/.exec( data )[ 1 ];
M
r59  
Mr.doob 已提交
615

M
r72  
Mr.doob 已提交
616 617
						if ( undefined == defines[ defineKey ] ) {

M
r88  
Mr.doob 已提交
618
							console.warn( 'THREE.VRMLLoader: %s is not defined.', defineKey );
M
r72  
Mr.doob 已提交
619

M
r66  
Mr.doob 已提交
620
						} else {
M
r59  
Mr.doob 已提交
621

M
r66  
Mr.doob 已提交
622
							if ( /appearance/.exec( data ) && defineKey ) {
M
r59  
Mr.doob 已提交
623

M
r66  
Mr.doob 已提交
624
								parent.material = defines[ defineKey ].clone();
M
r62  
Mr.doob 已提交
625

M
r66  
Mr.doob 已提交
626
							} else if ( /geometry/.exec( data ) && defineKey ) {
M
r62  
Mr.doob 已提交
627

M
r66  
Mr.doob 已提交
628
								parent.geometry = defines[ defineKey ].clone();
M
r63  
Mr.doob 已提交
629

M
r66  
Mr.doob 已提交
630
								// the solid property is not cloned with clone(), is only needed for VRML loading, so we need to transfer it
M
r98  
Mr.doob 已提交
631
								if ( defines[ defineKey ].solid !== undefined && defines[ defineKey ].solid === false ) {
M
r72  
Mr.doob 已提交
632

M
r66  
Mr.doob 已提交
633 634
									parent.geometry.solid = false;
									parent.material.side = THREE.DoubleSide;
M
r72  
Mr.doob 已提交
635

M
r66  
Mr.doob 已提交
636
								}
M
r62  
Mr.doob 已提交
637

M
r72  
Mr.doob 已提交
638
							} else if ( defineKey ) {
M
r63  
Mr.doob 已提交
639

M
r88  
Mr.doob 已提交
640
								object = defines[ defineKey ].clone();
M
r66  
Mr.doob 已提交
641
								parent.add( object );
M
r62  
Mr.doob 已提交
642

M
r66  
Mr.doob 已提交
643
							}
M
r62  
Mr.doob 已提交
644

M
r66  
Mr.doob 已提交
645
						}
M
r59  
Mr.doob 已提交
646 647 648 649 650 651 652

					}

					return;

				}

M
r88  
Mr.doob 已提交
653 654 655 656 657
				object = parent;

				if ( data.string.indexOf( 'AmbientLight' ) > - 1 && data.nodeType === 'PointLight' ) {

					data.nodeType = 'AmbientLight';
M
r59  
Mr.doob 已提交
658

M
r83  
Mr.doob 已提交
659
				}
M
r86  
Mr.doob 已提交
660 661 662 663 664

				var l_visible = data.on !== undefined ? data.on : true;
				var l_intensity = data.intensity !== undefined ? data.intensity : 1;
				var l_color = new THREE.Color();

M
r88  
Mr.doob 已提交
665
				if ( data.color ) {
M
r86  
Mr.doob 已提交
666

M
r88  
Mr.doob 已提交
667
					l_color.copy( data.color );
M
r86  
Mr.doob 已提交
668

M
r83  
Mr.doob 已提交
669
				}
M
r86  
Mr.doob 已提交
670

M
r88  
Mr.doob 已提交
671
				if ( data.nodeType === 'AmbientLight' ) {
M
r86  
Mr.doob 已提交
672

M
r88  
Mr.doob 已提交
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
					object = new THREE.AmbientLight( l_color, l_intensity );
					object.visible = l_visible;

					parent.add( object );

				} else if ( data.nodeType === 'PointLight' ) {

					var l_distance = 0;

					if ( data.radius !== undefined && data.radius < 1000 ) {

						l_distance = data.radius;

					}

					object = new THREE.PointLight( l_color, l_intensity, l_distance );
					object.visible = l_visible;

					parent.add( object );
M
r86  
Mr.doob 已提交
692

M
r88  
Mr.doob 已提交
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
				} else if ( data.nodeType === 'SpotLight' ) {

					var l_intensity = 1;
					var l_distance = 0;
					var l_angle = Math.PI / 3;
					var l_penumbra = 0;
					var l_visible = true;

					if ( data.radius !== undefined && data.radius < 1000 ) {

						l_distance = data.radius;

					}

					if ( data.cutOffAngle !== undefined ) {

						l_angle = data.cutOffAngle;

					}

					object = new THREE.SpotLight( l_color, l_intensity, l_distance, l_angle, l_penumbra );
					object.visible = l_visible;

					parent.add( object );

				} else if ( data.nodeType === 'Transform' || data.nodeType === 'Group' ) {
M
r63  
Mr.doob 已提交
719

M
r59  
Mr.doob 已提交
720 721 722
					object = new THREE.Object3D();

					if ( /DEF/.exec( data.string ) ) {
M
r72  
Mr.doob 已提交
723

M
r75  
Mr.doob 已提交
724
						object.name = /DEF\s+([^\s]+)/.exec( data.string )[ 1 ];
M
r59  
Mr.doob 已提交
725
						defines[ object.name ] = object;
M
r72  
Mr.doob 已提交
726

M
r59  
Mr.doob 已提交
727 728
					}

M
r88  
Mr.doob 已提交
729
					if ( data.translation !== undefined ) {
M
r59  
Mr.doob 已提交
730

M
r66  
Mr.doob 已提交
731
						var t = data.translation;
M
r59  
Mr.doob 已提交
732

M
r72  
Mr.doob 已提交
733
						object.position.set( t.x, t.y, t.z );
M
r59  
Mr.doob 已提交
734

M
r66  
Mr.doob 已提交
735
					}
M
r59  
Mr.doob 已提交
736

M
r88  
Mr.doob 已提交
737
					if ( data.rotation !== undefined ) {
M
r59  
Mr.doob 已提交
738

M
r66  
Mr.doob 已提交
739
						var r = data.rotation;
M
r59  
Mr.doob 已提交
740

M
r66  
Mr.doob 已提交
741
						object.quaternion.setFromAxisAngle( new THREE.Vector3( r.x, r.y, r.z ), r.w );
M
r62  
Mr.doob 已提交
742

M
r66  
Mr.doob 已提交
743
					}
M
r59  
Mr.doob 已提交
744

M
r88  
Mr.doob 已提交
745
					if ( data.scale !== undefined ) {
M
r59  
Mr.doob 已提交
746

M
r66  
Mr.doob 已提交
747
						var s = data.scale;
M
r59  
Mr.doob 已提交
748

M
r66  
Mr.doob 已提交
749
						object.scale.set( s.x, s.y, s.z );
M
r59  
Mr.doob 已提交
750

M
r66  
Mr.doob 已提交
751
					}
M
r59  
Mr.doob 已提交
752 753 754

					parent.add( object );

M
r88  
Mr.doob 已提交
755
				} else if ( data.nodeType === 'Shape' ) {
M
r59  
Mr.doob 已提交
756 757 758 759

					object = new THREE.Mesh();

					if ( /DEF/.exec( data.string ) ) {
M
r63  
Mr.doob 已提交
760

M
r75  
Mr.doob 已提交
761
						object.name = /DEF\s+([^\s]+)/.exec( data.string )[ 1 ];
M
r63  
Mr.doob 已提交
762

M
r59  
Mr.doob 已提交
763
						defines[ object.name ] = object;
M
r72  
Mr.doob 已提交
764

M
r59  
Mr.doob 已提交
765 766 767 768
					}

					parent.add( object );

M
r88  
Mr.doob 已提交
769
				} else if ( data.nodeType === 'Background' ) {
M
r59  
Mr.doob 已提交
770

M
r66  
Mr.doob 已提交
771
					var segments = 20;
M
r59  
Mr.doob 已提交
772

M
r66  
Mr.doob 已提交
773
					// sky (full sphere):
M
r69  
Mr.doob 已提交
774

M
r66  
Mr.doob 已提交
775
					var radius = 2e4;
M
r59  
Mr.doob 已提交
776

M
r88  
Mr.doob 已提交
777
					var skyGeometry = new THREE.SphereBufferGeometry( radius, segments, segments );
M
r69  
Mr.doob 已提交
778
					var skyMaterial = new THREE.MeshBasicMaterial( { fog: false, side: THREE.BackSide } );
M
r59  
Mr.doob 已提交
779

M
r69  
Mr.doob 已提交
780
					if ( data.skyColor.length > 1 ) {
M
r59  
Mr.doob 已提交
781

M
r69  
Mr.doob 已提交
782
						paintFaces( skyGeometry, radius, data.skyAngle, data.skyColor, true );
M
r59  
Mr.doob 已提交
783

M
r88  
Mr.doob 已提交
784
						skyMaterial.vertexColors = THREE.VertexColors;
M
r59  
Mr.doob 已提交
785

M
r69  
Mr.doob 已提交
786
					} else {
M
r59  
Mr.doob 已提交
787

M
r69  
Mr.doob 已提交
788 789
						var color = data.skyColor[ 0 ];
						skyMaterial.color.setRGB( color.r, color.b, color.g );
M
r59  
Mr.doob 已提交
790

M
r69  
Mr.doob 已提交
791
					}
M
r59  
Mr.doob 已提交
792

M
r69  
Mr.doob 已提交
793
					scene.add( new THREE.Mesh( skyGeometry, skyMaterial ) );
M
r59  
Mr.doob 已提交
794

M
r66  
Mr.doob 已提交
795
					// ground (half sphere):
M
r59  
Mr.doob 已提交
796

M
r69  
Mr.doob 已提交
797
					if ( data.groundColor !== undefined ) {
M
r59  
Mr.doob 已提交
798

M
r69  
Mr.doob 已提交
799
						radius = 1.2e4;
M
r59  
Mr.doob 已提交
800

M
r88  
Mr.doob 已提交
801
						var groundGeometry = new THREE.SphereBufferGeometry( radius, segments, segments, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI );
M
r69  
Mr.doob 已提交
802
						var groundMaterial = new THREE.MeshBasicMaterial( { fog: false, side: THREE.BackSide, vertexColors: THREE.VertexColors } );
M
r59  
Mr.doob 已提交
803

M
r69  
Mr.doob 已提交
804
						paintFaces( groundGeometry, radius, data.groundAngle, data.groundColor, false );
M
r59  
Mr.doob 已提交
805

M
r69  
Mr.doob 已提交
806
						scene.add( new THREE.Mesh( groundGeometry, groundMaterial ) );
M
r59  
Mr.doob 已提交
807

M
r69  
Mr.doob 已提交
808
					}
M
r59  
Mr.doob 已提交
809

M
r63  
Mr.doob 已提交
810
				} else if ( /geometry/.exec( data.string ) ) {
M
r59  
Mr.doob 已提交
811

M
r88  
Mr.doob 已提交
812
					if ( data.nodeType === 'Box' ) {
M
r59  
Mr.doob 已提交
813

M
r66  
Mr.doob 已提交
814
						var s = data.size;
M
r59  
Mr.doob 已提交
815

M
r88  
Mr.doob 已提交
816 817 818 819 820
						parent.geometry = new THREE.BoxBufferGeometry( s.x, s.y, s.z );

					} else if ( data.nodeType === 'Cylinder' ) {

						parent.geometry = new THREE.CylinderBufferGeometry( data.radius, data.radius, data.height );
M
r59  
Mr.doob 已提交
821

M
r88  
Mr.doob 已提交
822
					} else if ( data.nodeType === 'Cone' ) {
M
r59  
Mr.doob 已提交
823

M
r88  
Mr.doob 已提交
824
						parent.geometry = new THREE.CylinderBufferGeometry( data.topRadius, data.bottomRadius, data.height );
M
r59  
Mr.doob 已提交
825

M
r88  
Mr.doob 已提交
826
					} else if ( data.nodeType === 'Sphere' ) {
M
r59  
Mr.doob 已提交
827

M
r88  
Mr.doob 已提交
828
						parent.geometry = new THREE.SphereBufferGeometry( data.radius );
M
r59  
Mr.doob 已提交
829

M
r104  
Mr.doob 已提交
830 831 832 833 834 835 836 837 838 839
					} else if ( data.nodeType === 'IndexedLineSet' ) {

						console.warn( 'THREE.VRMLLoader: IndexedLineSet not supported yet.' );
						parent.parent.remove( parent ); // since the loader is not able to parse the geometry, remove the respective 3D object

					} else if ( data.nodeType === 'Text' ) {

						console.warn( 'THREE.VRMLLoader: Text not supported yet.' );
						parent.parent.remove( parent );

M
r88  
Mr.doob 已提交
840
					} else if ( data.nodeType === 'IndexedFaceSet' ) {
M
r59  
Mr.doob 已提交
841

M
r88  
Mr.doob 已提交
842
						var geometry = new THREE.BufferGeometry();
M
r59  
Mr.doob 已提交
843

M
r88  
Mr.doob 已提交
844
						var positions = [];
M
r97  
Mr.doob 已提交
845 846
						var colors = [];
						var normals = [];
M
r88  
Mr.doob 已提交
847
						var uvs = [];
M
r62  
Mr.doob 已提交
848

M
r97  
Mr.doob 已提交
849
						var position, color, normal, uv;
M
r62  
Mr.doob 已提交
850

M
r88  
Mr.doob 已提交
851
						var i, il, j, jl;
M
r62  
Mr.doob 已提交
852

M
r88  
Mr.doob 已提交
853
						for ( i = 0, il = data.children.length; i < il; i ++ ) {
M
r62  
Mr.doob 已提交
854

M
r66  
Mr.doob 已提交
855
							var child = data.children[ i ];
M
r62  
Mr.doob 已提交
856

M
r88  
Mr.doob 已提交
857
							// uvs
M
r62  
Mr.doob 已提交
858

M
r88  
Mr.doob 已提交
859
							if ( child.nodeType === 'TextureCoordinate' ) {
M
r73  
Mr.doob 已提交
860

M
r88  
Mr.doob 已提交
861
								if ( child.points ) {
M
r73  
Mr.doob 已提交
862

M
r88  
Mr.doob 已提交
863
									for ( j = 0, jl = child.points.length; j < jl; j ++ ) {
M
r73  
Mr.doob 已提交
864

M
r88  
Mr.doob 已提交
865 866
										uv = child.points[ j ];
										uvs.push( uv.x, uv.y );
M
r73  
Mr.doob 已提交
867

M
r88  
Mr.doob 已提交
868
									}
M
r62  
Mr.doob 已提交
869

M
r88  
Mr.doob 已提交
870 871 872
								}

							}
M
r73  
Mr.doob 已提交
873

M
r97  
Mr.doob 已提交
874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
							// normals

							if ( child.nodeType === 'Normal' ) {

								if ( child.points ) {

									for ( j = 0, jl = child.points.length; j < jl; j ++ ) {

										normal = child.points[ j ];
										normals.push( normal.x, normal.y, normal.z );

									}

								}

							}

							// colors

							if ( child.nodeType === 'Color' ) {

								if ( child.color ) {

									for ( j = 0, jl = child.color.length; j < jl; j ++ ) {

										color = child.color[ j ];
										colors.push( color.r, color.g, color.b );

									}

								}

							}

M
r88  
Mr.doob 已提交
908
							// positions
M
r62  
Mr.doob 已提交
909

M
r88  
Mr.doob 已提交
910
							if ( child.nodeType === 'Coordinate' ) {
M
r62  
Mr.doob 已提交
911

M
r88  
Mr.doob 已提交
912
								if ( child.points ) {
M
r62  
Mr.doob 已提交
913

M
r88  
Mr.doob 已提交
914 915 916 917
									for ( j = 0, jl = child.points.length; j < jl; j ++ ) {

										position = child.points[ j ];
										positions.push( position.x, position.y, position.z );
M
r73  
Mr.doob 已提交
918 919

									}
M
r72  
Mr.doob 已提交
920

M
r66  
Mr.doob 已提交
921
								}
M
r62  
Mr.doob 已提交
922

M
r88  
Mr.doob 已提交
923
								if ( child.string.indexOf( 'DEF' ) > - 1 ) {
M
r72  
Mr.doob 已提交
924

M
r75  
Mr.doob 已提交
925
									var name = /DEF\s+([^\s]+)/.exec( child.string )[ 1 ];
M
r72  
Mr.doob 已提交
926

M
r88  
Mr.doob 已提交
927
									defines[ name ] = positions.slice( 0 );
M
r62  
Mr.doob 已提交
928

M
r73  
Mr.doob 已提交
929 930
								}

M
r88  
Mr.doob 已提交
931
								if ( child.string.indexOf( 'USE' ) > - 1 ) {
M
r63  
Mr.doob 已提交
932

M
r75  
Mr.doob 已提交
933
									var defineKey = /USE\s+([^\s]+)/.exec( child.string )[ 1 ];
M
r62  
Mr.doob 已提交
934

M
r88  
Mr.doob 已提交
935 936
									positions = defines[ defineKey ];

M
r73  
Mr.doob 已提交
937
								}
M
r62  
Mr.doob 已提交
938

M
r73  
Mr.doob 已提交
939
							}
M
r62  
Mr.doob 已提交
940

M
r73  
Mr.doob 已提交
941
						}
M
r62  
Mr.doob 已提交
942

M
r73  
Mr.doob 已提交
943
						// some shapes only have vertices for use in other shapes
M
r88  
Mr.doob 已提交
944

M
r73  
Mr.doob 已提交
945 946
						if ( data.coordIndex ) {

M
r102  
Mr.doob 已提交
947
							function triangulateIndexArray( indexArray, ccw, colorPerVertex ) {
M
r97  
Mr.doob 已提交
948 949 950 951 952 953 954 955 956 957 958 959 960

								if ( ccw === undefined ) {

									// ccw is true by default
									ccw = true;

								}

								var triangulatedIndexArray = [];
								var skip = 0;

								for ( i = 0, il = indexArray.length; i < il; i ++ ) {

M
r102  
Mr.doob 已提交
961
									if ( colorPerVertex === false ) {
M
r97  
Mr.doob 已提交
962

M
r102  
Mr.doob 已提交
963
										var colorIndices = indexArray[ i ];
M
r97  
Mr.doob 已提交
964

M
r102  
Mr.doob 已提交
965
										for ( j = 0, jl = colorIndices.length; j < jl; j ++ ) {
M
r97  
Mr.doob 已提交
966

M
r102  
Mr.doob 已提交
967
											var index = colorIndices[ j ];
M
r97  
Mr.doob 已提交
968

M
r102  
Mr.doob 已提交
969
											triangulatedIndexArray.push( index, index, index );
M
r97  
Mr.doob 已提交
970

M
r102  
Mr.doob 已提交
971
										}
M
r97  
Mr.doob 已提交
972

M
r102  
Mr.doob 已提交
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
									} else {

										var indexedFace = indexArray[ i ];

										// VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here

										skip = 0;

										while ( indexedFace.length >= 3 && skip < ( indexedFace.length - 2 ) ) {

											var i1 = indexedFace[ 0 ];
											var i2 = indexedFace[ skip + ( ccw ? 1 : 2 ) ];
											var i3 = indexedFace[ skip + ( ccw ? 2 : 1 ) ];

											triangulatedIndexArray.push( i1, i2, i3 );

											skip ++;

										}
M
r97  
Mr.doob 已提交
992 993 994 995 996 997 998 999 1000 1001 1002

									}

								}

								return triangulatedIndexArray;

							}

							var positionIndexes = data.coordIndex ? triangulateIndexArray( data.coordIndex, data.ccw ) : [];
							var normalIndexes = data.normalIndex ? triangulateIndexArray( data.normalIndex, data.ccw ) : positionIndexes;
M
r102.1  
Mr.doob 已提交
1003
							var colorIndexes = data.colorIndex ? triangulateIndexArray( data.colorIndex, data.ccw, data.colorPerVertex ) : [];
M
r97  
Mr.doob 已提交
1004 1005 1006
							var uvIndexes = data.texCoordIndex ? triangulateIndexArray( data.texCoordIndex, data.ccw ) : positionIndexes;

							var newIndexes = [];
M
r88  
Mr.doob 已提交
1007
							var newPositions = [];
M
r97  
Mr.doob 已提交
1008 1009
							var newNormals = [];
							var newColors = [];
M
r88  
Mr.doob 已提交
1010 1011
							var newUvs = [];

M
r97  
Mr.doob 已提交
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
							// if any other index array does not match the coordinate indexes, split any points that differ

							var pointMap = Object.create( null );

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

								var pointAttributes = [];

								var positionIndex = positionIndexes[ i ];
								var normalIndex = normalIndexes[ i ];
								var colorIndex = colorIndexes[ i ];
								var uvIndex = uvIndexes[ i ];

								var base = 10; // which base to use to represent each value

								pointAttributes.push( positionIndex.toString( base ) );

								if ( normalIndex !== undefined ) {

									pointAttributes.push( normalIndex.toString( base ) );

								}

								if ( colorIndex !== undefined ) {

									pointAttributes.push( colorIndex.toString( base ) );

								}

								if ( uvIndex !== undefined ) {

									pointAttributes.push( uvIndex.toString( base ) );
M
r73  
Mr.doob 已提交
1044

M
r97  
Mr.doob 已提交
1045 1046 1047 1048
								}

								var pointId = pointAttributes.join( ',' );
								var newIndex = pointMap[ pointId ];
M
r88  
Mr.doob 已提交
1049

M
r97  
Mr.doob 已提交
1050
								if ( newIndex === undefined ) {
M
r88  
Mr.doob 已提交
1051

M
r97  
Mr.doob 已提交
1052 1053
									newIndex = newPositions.length / 3;
									pointMap[ pointId ] = newIndex;
M
r73  
Mr.doob 已提交
1054

M
r97  
Mr.doob 已提交
1055 1056 1057 1058 1059
									newPositions.push(
										positions[ positionIndex * 3 ],
										positions[ positionIndex * 3 + 1 ],
										positions[ positionIndex * 3 + 2 ]
									);
M
r73  
Mr.doob 已提交
1060

M
r97  
Mr.doob 已提交
1061
									if ( normalIndex !== undefined && normals.length > 0 ) {
M
r73  
Mr.doob 已提交
1062

M
r97  
Mr.doob 已提交
1063 1064 1065 1066 1067
										newNormals.push(
											normals[ normalIndex * 3 ],
											normals[ normalIndex * 3 + 1 ],
											normals[ normalIndex * 3 + 2 ]
										);
M
r73  
Mr.doob 已提交
1068

M
r97  
Mr.doob 已提交
1069
									}
M
r73  
Mr.doob 已提交
1070

M
r97  
Mr.doob 已提交
1071
									if ( colorIndex !== undefined && colors.length > 0 ) {
M
r63  
Mr.doob 已提交
1072

M
r97  
Mr.doob 已提交
1073 1074 1075 1076 1077
										newColors.push(
											colors[ colorIndex * 3 ],
											colors[ colorIndex * 3 + 1 ],
											colors[ colorIndex * 3 + 2 ]
										);
M
r88  
Mr.doob 已提交
1078

M
r97  
Mr.doob 已提交
1079
									}
M
r88  
Mr.doob 已提交
1080

M
r97  
Mr.doob 已提交
1081
									if ( uvIndex !== undefined && uvs.length > 0 ) {
M
r63  
Mr.doob 已提交
1082

M
r97  
Mr.doob 已提交
1083 1084 1085 1086 1087 1088
										newUvs.push(
											uvs[ uvIndex * 2 ],
											uvs[ uvIndex * 2 + 1 ]
										);

									}
M
r88  
Mr.doob 已提交
1089 1090

								}
M
r62  
Mr.doob 已提交
1091

M
r97  
Mr.doob 已提交
1092 1093
								newIndexes.push( newIndex );

M
r66  
Mr.doob 已提交
1094
							}
M
r62  
Mr.doob 已提交
1095

M
r88  
Mr.doob 已提交
1096
							positions = newPositions;
M
r97  
Mr.doob 已提交
1097
							normals = newNormals;
M
r98  
Mr.doob 已提交
1098
							colors = newColors;
M
r88  
Mr.doob 已提交
1099 1100
							uvs = newUvs;

M
r97  
Mr.doob 已提交
1101 1102
							geometry.setIndex( newIndexes );

M
r73  
Mr.doob 已提交
1103 1104 1105
						} else {

							// do not add dummy mesh to the scene
M
r88  
Mr.doob 已提交
1106

M
r73  
Mr.doob 已提交
1107
							parent.parent.remove( parent );
M
r62  
Mr.doob 已提交
1108

M
r66  
Mr.doob 已提交
1109
						}
M
r62  
Mr.doob 已提交
1110

M
r66  
Mr.doob 已提交
1111
						if ( false === data.solid ) {
M
r72  
Mr.doob 已提交
1112

M
r66  
Mr.doob 已提交
1113
							parent.material.side = THREE.DoubleSide;
M
r72  
Mr.doob 已提交
1114

M
r66  
Mr.doob 已提交
1115
						}
M
r63  
Mr.doob 已提交
1116

M
r66  
Mr.doob 已提交
1117 1118
						// we need to store it on the geometry for use with defines
						geometry.solid = data.solid;
M
r63  
Mr.doob 已提交
1119

M
r88  
Mr.doob 已提交
1120 1121
						geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );

M
r97  
Mr.doob 已提交
1122 1123 1124 1125
						if ( colors.length > 0 ) {

							geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );

M
r102  
Mr.doob 已提交
1126 1127
							parent.material.vertexColors = THREE.VertexColors;

M
r97  
Mr.doob 已提交
1128 1129
						}

M
r88  
Mr.doob 已提交
1130 1131 1132 1133 1134 1135
						if ( uvs.length > 0 ) {

							geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );

						}

M
r97  
Mr.doob 已提交
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
						if ( normals.length > 0 ) {

							geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );

						} else {

							// convert geometry to non-indexed to get sharp normals
							geometry = geometry.toNonIndexed();
							geometry.computeVertexNormals();

						}

M
r66  
Mr.doob 已提交
1148
						geometry.computeBoundingSphere();
M
r62  
Mr.doob 已提交
1149

M
r66  
Mr.doob 已提交
1150 1151
						// see if it's a define
						if ( /DEF/.exec( data.string ) ) {
M
r72  
Mr.doob 已提交
1152

M
r75  
Mr.doob 已提交
1153
							geometry.name = /DEF ([^\s]+)/.exec( data.string )[ 1 ];
M
r66  
Mr.doob 已提交
1154
							defines[ geometry.name ] = geometry;
M
r72  
Mr.doob 已提交
1155

M
r66  
Mr.doob 已提交
1156
						}
M
r62  
Mr.doob 已提交
1157

M
r66  
Mr.doob 已提交
1158
						parent.geometry = geometry;
M
r72  
Mr.doob 已提交
1159

M
r59  
Mr.doob 已提交
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
					}

					return;

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

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

						var child = data.children[ i ];

M
r88  
Mr.doob 已提交
1170
						if ( child.nodeType === 'Material' ) {
M
r72  
Mr.doob 已提交
1171

M
r59  
Mr.doob 已提交
1172 1173
							var material = new THREE.MeshPhongMaterial();

M
r88  
Mr.doob 已提交
1174
							if ( child.diffuseColor !== undefined ) {
M
r59  
Mr.doob 已提交
1175

M
r66  
Mr.doob 已提交
1176
								var d = child.diffuseColor;
M
r59  
Mr.doob 已提交
1177

M
r66  
Mr.doob 已提交
1178
								material.color.setRGB( d.r, d.g, d.b );
M
r59  
Mr.doob 已提交
1179

M
r66  
Mr.doob 已提交
1180
							}
M
r59  
Mr.doob 已提交
1181

M
r88  
Mr.doob 已提交
1182
							if ( child.emissiveColor !== undefined ) {
M
r59  
Mr.doob 已提交
1183

M
r66  
Mr.doob 已提交
1184
								var e = child.emissiveColor;
M
r59  
Mr.doob 已提交
1185

M
r66  
Mr.doob 已提交
1186
								material.emissive.setRGB( e.r, e.g, e.b );
M
r59  
Mr.doob 已提交
1187

M
r66  
Mr.doob 已提交
1188
							}
M
r59  
Mr.doob 已提交
1189

M
r88  
Mr.doob 已提交
1190
							if ( child.specularColor !== undefined ) {
M
r59  
Mr.doob 已提交
1191

M
r66  
Mr.doob 已提交
1192
								var s = child.specularColor;
M
r59  
Mr.doob 已提交
1193

M
r66  
Mr.doob 已提交
1194
								material.specular.setRGB( s.r, s.g, s.b );
M
r59  
Mr.doob 已提交
1195

M
r66  
Mr.doob 已提交
1196
							}
M
r59  
Mr.doob 已提交
1197

M
r88  
Mr.doob 已提交
1198
							if ( child.transparency !== undefined ) {
M
r59  
Mr.doob 已提交
1199

M
r66  
Mr.doob 已提交
1200
								var t = child.transparency;
M
r59  
Mr.doob 已提交
1201

M
r66  
Mr.doob 已提交
1202 1203
								// transparency is opposite of opacity
								material.opacity = Math.abs( 1 - t );
M
r63  
Mr.doob 已提交
1204

M
r66  
Mr.doob 已提交
1205
								material.transparent = true;
M
r63  
Mr.doob 已提交
1206

M
r66  
Mr.doob 已提交
1207
							}
M
r59  
Mr.doob 已提交
1208 1209 1210

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

M
r75  
Mr.doob 已提交
1211
								material.name = /DEF ([^\s]+)/.exec( data.string )[ 1 ];
M
r62  
Mr.doob 已提交
1212

M
r59  
Mr.doob 已提交
1213 1214 1215 1216 1217 1218
								defines[ material.name ] = material;

							}

							parent.material = material;

M
r73  
Mr.doob 已提交
1219 1220
						}

M
r88  
Mr.doob 已提交
1221
						if ( child.nodeType === 'ImageTexture' ) {
M
r73  
Mr.doob 已提交
1222

M
r88  
Mr.doob 已提交
1223
							var textureName = /"([^"]+)"/.exec( child.children[ 0 ] );
M
r73  
Mr.doob 已提交
1224

M
r88  
Mr.doob 已提交
1225
							if ( textureName ) {
M
r73  
Mr.doob 已提交
1226 1227 1228

								parent.material.name = textureName[ 1 ];

M
r97  
Mr.doob 已提交
1229
								parent.material.map = textureLoader.load( textureName[ 1 ] );
M
r73  
Mr.doob 已提交
1230 1231

							}
M
r72  
Mr.doob 已提交
1232

M
r59  
Mr.doob 已提交
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246
						}

					}

					return;

				}

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

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

				}

M
r88  
Mr.doob 已提交
1247
			}
M
r59  
Mr.doob 已提交
1248 1249 1250

			parseNode( getTree( lines ), scene );

M
r88  
Mr.doob 已提交
1251
		}
M
r59  
Mr.doob 已提交
1252 1253 1254 1255

		var scene = new THREE.Scene();

		var lines = data.split( '\n' );
M
r63  
Mr.doob 已提交
1256

M
r73  
Mr.doob 已提交
1257
		// some lines do not have breaks
M
r88  
Mr.doob 已提交
1258

M
r104  
Mr.doob 已提交
1259
		for ( var i = lines.length - 1; i > 0; i -- ) {
M
r73  
Mr.doob 已提交
1260

M
r97  
Mr.doob 已提交
1261 1262
			// The # symbol indicates that all subsequent text, until the end of the line is a comment,
			// and should be ignored. (see http://gun.teipir.gr/VRML-amgem/spec/part1/grammar.html)
M
r104  
Mr.doob 已提交
1263 1264 1265
			lines[ i ] = lines[ i ].replace( /(#.*)/, '' );

			var line = lines[ i ];
M
r97  
Mr.doob 已提交
1266

M
r73  
Mr.doob 已提交
1267
			// split lines with {..{ or {..[ - some have both
M
r88  
Mr.doob 已提交
1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
			if ( /{.*[{\[]/.test( line ) ) {

				var parts = line.split( '{' ).join( '{\n' ).split( '\n' );
				parts.unshift( 1 );
				parts.unshift( i );
				lines.splice.apply( lines, parts );

			} else if ( /\].*}/.test( line ) ) {

				// split lines with ]..}
				var parts = line.split( ']' ).join( ']\n' ).split( '\n' );
				parts.unshift( 1 );
				parts.unshift( i );
				lines.splice.apply( lines, parts );

M
r73  
Mr.doob 已提交
1283 1284
			}

M
r104  
Mr.doob 已提交
1285 1286
			line = lines[ i ];

M
r88  
Mr.doob 已提交
1287 1288 1289 1290 1291 1292 1293 1294
			if ( /}.*}/.test( line ) ) {

				// split lines with }..}
				var parts = line.split( '}' ).join( '}\n' ).split( '\n' );
				parts.unshift( 1 );
				parts.unshift( i );
				lines.splice.apply( lines, parts );

M
r73  
Mr.doob 已提交
1295 1296
			}

M
r104  
Mr.doob 已提交
1297 1298
			line = lines[ i ];

M
r88  
Mr.doob 已提交
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
			if ( /^\b[^\s]+\b$/.test( line.trim() ) ) {

				// prevent lines with single words like "coord" or "geometry", see #12209
				lines[ i + 1 ] = line + ' ' + lines[ i + 1 ].trim();
				lines.splice( i, 1 );

			} else if ( ( line.indexOf( 'coord' ) > - 1 ) && ( line.indexOf( '[' ) < 0 ) && ( line.indexOf( '{' ) < 0 ) ) {

				// force the parser to create Coordinate node for empty coords
				// coord USE something -> coord USE something Coordinate {}

				lines[ i ] += ' Coordinate {}';

M
r73  
Mr.doob 已提交
1312
			}
M
r88  
Mr.doob 已提交
1313

M
r73  
Mr.doob 已提交
1314 1315
		}

M
r59  
Mr.doob 已提交
1316 1317 1318 1319
		var header = lines.shift();

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

M
r92  
Mr.doob 已提交
1320
			console.warn( 'THREE.VRMLLoader: V1.0 not supported yet.' );
M
r59  
Mr.doob 已提交
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332

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

			parseV2( lines, scene );

		}

		return scene;

	}

};