Преглед на файлове

VRMLLoader: BufferGeometry support

Mugen87 преди 8 години
родител
ревизия
0e8dc49232
променени са 2 файла, в които са добавени 202 реда и са изтрити 200 реда
  1. 196 194
      examples/js/loaders/VRMLLoader.js
  2. 6 6
      examples/webgl_loader_vrml.html

+ 196 - 194
examples/js/loaders/VRMLLoader.js

@@ -54,44 +54,19 @@ THREE.VRMLLoader.prototype = {
 		var textureLoader = new THREE.TextureLoader( this.manager );
 		textureLoader.setCrossOrigin( this.crossOrigin );
 
-		var parseV1 = function ( lines, scene ) {
+		function parseV1( lines, scene ) {
 
-			console.warn( 'VRML V1.0 not supported yet' );
+			console.warn( 'THREE.VRMLLoader: V1.0 not supported yet.' );
 
 		};
 
-		var parseV2 = function ( lines, scene ) {
+		function parseV2( lines, scene ) {
 
 			var defines = {};
 			var float_pattern = /(\b|\-|\+)([\d\.e]+)/;
 			var float2_pattern = /([\d\.\+\-e]+)\s+([\d\.\+\-e]+)/g;
 			var float3_pattern = /([\d\.\+\-e]+)\s+([\d\.\+\-e]+)\s+([\d\.\+\-e]+)/g;
 
-			/**
-			* 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
@@ -112,13 +87,11 @@ THREE.VRMLLoader.prototype = {
 			 * @param radius
 			 * @param angles
 			 * @param colors
-			 * @param boolean directionIsDown Whether to work bottom up or top down.
+			 * @param boolean topDown Whether to work top down or bottom up.
 			 */
-			var paintFaces = function ( geometry, radius, angles, colors, directionIsDown ) {
+			function paintFaces( geometry, radius, angles, colors, topDown ) {
 
-				var direction = directionIsDown ? 1 : - 1;
-
-				var faceIndices = [ 'a', 'b', 'c', 'd' ];
+				var direction = ( topDown === true ) ? 1 : - 1;
 
 				var coord = [], A = {}, B = {}, applyColor = false;
 
@@ -135,62 +108,66 @@ THREE.VRMLLoader.prototype = {
 
 				}
 
-				// painting the colors on the faces
-				for ( var i = 0; i < geometry.faces.length ; i ++ ) {
+				var index = geometry.index;
+				var positionAttribute = geometry.attributes.position;
+				var colorAttribute = new THREE.BufferAttribute( new Float32Array( geometry.attributes.position.count * 3 ), 3 );
 
-					var f = geometry.faces[ i ];
+				var position = new THREE.Vector3();
+				var color = new THREE.Color();
 
-					var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
+				for ( var i = 0; i < index.count; i ++ ) {
 
-					for ( var j = 0; j < n; j ++ ) {
+					var vertexIndex = index.getX( i );
 
-						var vertexIndex = f[ faceIndices[ j ] ];
+					position.fromBufferAttribute( positionAttribute, vertexIndex );
 
-						var p = geometry.vertices[ vertexIndex ];
+					for ( var j = 0; j < colors.length; j ++ ) {
 
-						for ( var index = 0; index < colors.length; index ++ ) {
+						// linear interpolation between aColor and bColor, calculate proportion
+						// A is previous point (angle)
 
-							// linear interpolation between aColor and bColor, calculate proportion
-							// A is previous point (angle)
-							if ( index === 0 ) {
+						if ( j === 0 ) {
 
-								A.x = 0;
-								A.y = directionIsDown ? radius : - 1 * radius;
+							A.x = 0;
+							A.y = ( topDown === true ) ? radius : - 1 * radius;
 
-							} else {
+						} else {
 
-								A.x = coord[ index - 1 ].x;
-								A.y = coord[ index - 1 ].y;
+							A.x = coord[ j - 1 ].x;
+							A.y = coord[ j - 1 ].y;
 
-							}
+						}
 
-							// B is current point (angle)
-							B = coord[ index ];
+						// B is current point (angle)
 
-							if ( undefined !== B ) {
+						B = coord[ j ];
 
-								// 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;
+						if ( B !== undefined ) {
 
-								if ( applyColor ) {
+							// p has to be between the points A and B which we interpolate
 
-									var aColor = colors[ index ];
-									var bColor = colors[ index + 1 ];
+							applyColor = ( topDown === true ) ? ( position.y <= A.y && position.y > B.y ) : ( position.y >= A.y && position.y < B.y );
 
-									// below is simple linear interpolation
-									var t = Math.abs( p.y - A.y ) / ( A.y - B.y );
+							if ( applyColor === true ) {
 
-									// 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
-									var color = interpolateColors( aColor, bColor, t );
+								var aColor = colors[ j ];
+								var bColor = colors[ j + 1 ];
 
-									f.vertexColors[ j ] = color;
+								// below is simple linear interpolation
 
-								}
+								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
 
-							} else if ( undefined === f.vertexColors[ j ] ) {
+								color.copy( aColor ).lerp( bColor, t );
 
-								var colorIndex = directionIsDown ? colors.length - 1 : 0;
-								f.vertexColors[ j ] = colors[ colorIndex ];
+								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 );
 
 							}
 
@@ -200,11 +177,13 @@ THREE.VRMLLoader.prototype = {
 
 				}
 
+				geometry.addAttribute( 'color', colorAttribute );
+
 			};
 
 			var index = [];
 
-			var parseProperty = function ( node, line ) {
+			function parseProperty( node, line ) {
 
 				var parts = [], part, property = {}, fieldName;
 
@@ -216,7 +195,7 @@ THREE.VRMLLoader.prototype = {
 
 				var point, angles, colors;
 
-				while ( null != ( part = regex.exec( line ) ) ) {
+				while ( null !== ( part = regex.exec( line ) ) ) {
 
 					parts.push( part[ 0 ] );
 
@@ -233,22 +212,26 @@ THREE.VRMLLoader.prototype = {
 						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':
 					case 'texCoordIndex':
 						this.recordingFieldname = fieldName;
 						this.isRecordingFaces = true;
 						this.indexes = [];
+						break;
 				}
 
 				if ( this.isRecordingFaces ) {
@@ -266,7 +249,7 @@ THREE.VRMLLoader.prototype = {
 							}
 
 							// end of current face
-							if ( parts[ ind ] === "-1" ) {
+							if ( parts[ ind ] === '-1' ) {
 
 								if ( index.length > 0 ) {
 
@@ -400,9 +383,9 @@ THREE.VRMLLoader.prototype = {
 						case 'specularColor':
 						case 'color':
 
-							if ( parts.length != 4 ) {
+							if ( parts.length !== 4 ) {
 
-								console.warn( 'Invalid color format detected for ' + fieldName );
+								console.warn( 'THREE.VRMLLoader: Invalid color format detected for %s.', fieldName );
 								break;
 
 							}
@@ -420,9 +403,9 @@ THREE.VRMLLoader.prototype = {
 						case 'translation':
 						case 'scale':
 						case 'size':
-							if ( parts.length != 4 ) {
+							if ( parts.length !== 4 ) {
 
-								console.warn( 'Invalid vector format detected for ' + fieldName );
+								console.warn( 'THREE.VRMLLoader: Invalid vector format detected for %s.', fieldName );
 								break;
 
 							}
@@ -444,9 +427,9 @@ THREE.VRMLLoader.prototype = {
 						case 'transparency':
 						case 'shininess':
 						case 'ambientIntensity':
-							if ( parts.length != 2 ) {
+							if ( parts.length !== 2 ) {
 
-								console.warn( 'Invalid single float value specification detected for ' + fieldName );
+								console.warn( 'THREE.VRMLLoader: Invalid single float value specification detected for %s.', fieldName );
 								break;
 
 							}
@@ -456,9 +439,9 @@ THREE.VRMLLoader.prototype = {
 							break;
 
 						case 'rotation':
-							if ( parts.length != 5 ) {
+							if ( parts.length !== 5 ) {
 
-								console.warn( 'Invalid quaternion format detected for ' + fieldName );
+								console.warn( 'THREE.VRMLLoader: Invalid quaternion format detected for %s.', fieldName );
 								break;
 
 							}
@@ -477,9 +460,9 @@ THREE.VRMLLoader.prototype = {
 						case 'solid':
 						case 'colorPerVertex':
 						case 'convex':
-							if ( parts.length != 2 ) {
+							if ( parts.length !== 2 ) {
 
-								console.warn( 'Invalid format detected for ' + fieldName );
+								console.warn( 'THREE.VRMLLoader: Invalid format detected for %s.', fieldName );
 								break;
 
 							}
@@ -497,7 +480,7 @@ THREE.VRMLLoader.prototype = {
 
 			};
 
-			var getTree = function ( lines ) {
+			function getTree( lines ) {
 
 				var tree = { 'string': 'Scene', children: [] };
 				var current = tree;
@@ -578,9 +561,9 @@ THREE.VRMLLoader.prototype = {
 
 			};
 
-			var parseNode = function ( data, parent ) {
+			function parseNode( data, parent ) {
 
-				// console.log( data );
+				var object;
 
 				if ( typeof data === 'string' ) {
 
@@ -590,7 +573,7 @@ THREE.VRMLLoader.prototype = {
 
 						if ( undefined == defines[ defineKey ] ) {
 
-							console.warn( defineKey + ' is not defined.' );
+							console.warn( 'THREE.VRMLLoader: %s is not defined.', defineKey );
 
 						} else {
 
@@ -612,7 +595,7 @@ THREE.VRMLLoader.prototype = {
 
 							} else if ( defineKey ) {
 
-								var object = defines[ defineKey ].clone();
+								object = defines[ defineKey ].clone();
 								parent.add( object );
 
 							}
@@ -625,77 +608,72 @@ THREE.VRMLLoader.prototype = {
 
 				}
 
-				var object = parent;
+				object = parent;
+
+				if ( data.string.indexOf( 'AmbientLight') > - 1 && data.nodeType === 'PointLight' ) {
+
+					data.nodeType = 'AmbientLight';
 
-				if(data.string.indexOf("AmbientLight")>-1 && data.nodeType=='PointLight'){
-					//wenn im Namen "AmbientLight" vorkommt und es ein PointLight ist,
-					//diesen Typ in 'AmbientLight' ändern
-					data.nodeType='AmbientLight';
 				}
 
 				var l_visible = data.on !== undefined ? data.on : true;
 				var l_intensity = data.intensity !== undefined ? data.intensity : 1;
 				var l_color = new THREE.Color();
-				if ( data.color ) l_color.copy( data.color );
 
-				if('AmbientLight' === data.nodeType){
-					object=new THREE.AmbientLight(
-								l_color.getHex(),
-								l_intensity
-								);
-					object.visible=l_visible;
+				if ( data.color ) {
 
-					parent.add( object );
+					l_color.copy( data.color );
 
 				}
-				else
-				if('PointLight' === data.nodeType){
-						var l_distance =0;	//0="unendlich" ...1000
 
-						if(data.radius!=undefined && data.radius<1000){
-							//l_radius=data.radius;
-							l_distance=data.radius;
+				if ( 'AmbientLight' === data.nodeType){
+
+					object = new THREE.AmbientLight( l_color, l_intensity );
+					object.visible = l_visible;
+
+					parent.add( object );
+
+				} else if ( 'PointLight' === data.nodeType ) {
+
+						var l_distance = 0;
+
+						if ( data.radius !== undefined && data.radius < 1000 ){
+
+							l_distance = data.radius;
+
 						}
-						object=new THREE.PointLight(
-								l_color.getHex(),
-								l_intensity,
-								l_distance);
-						object.visible=l_visible;
+
+						object=new THREE.PointLight( l_color, l_intensity, l_distance );
+						object.visible = l_visible;
 
 						parent.add( object );
-				}
-				else
-				if('SpotLight' === data.nodeType){
-						var l_intensity=1;
-						var l_distance =0;//0="unendlich"=1000
-						var l_angle=Math.PI/3;
-						var l_penumbra=0.0;//0..1
-						var l_visible=true;
-
-						if(data.radius!=undefined && data.radius<1000){
-							//l_radius=data.radius;
-							l_distance=data.radius;
+
+				} else if ( 'SpotLight' === data.nodeType ) {
+
+						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;
+
 						}
-						if(data.cutOffAngle!=undefined)l_angle=data.cutOffAngle;
-
-						object = new THREE.SpotLight(
-									l_color.getHex(),
-									l_intensity,
-									l_distance,
-									l_angle,
-									l_penumbra
-									);
-						object.visible=l_visible;
+
+						object = new THREE.SpotLight( l_color, l_intensity, l_distance, l_angle, l_penumbra );
+						object.visible = l_visible;
+
 						parent.add( object );
-						/*
-						var lightHelper = new THREE.SpotLightHelper( object );
-						parent.parent.add( lightHelper );
-						lightHelper.update();
-						*/
-				}
-				else
 
-				if ( 'Transform' === data.nodeType || 'Group' === data.nodeType ) {
+				} else if ( 'Transform' === data.nodeType || 'Group' === data.nodeType ) {
 
 					object = new THREE.Object3D();
 
@@ -754,7 +732,7 @@ THREE.VRMLLoader.prototype = {
 
 					var radius = 2e4;
 
-					var skyGeometry = new THREE.SphereGeometry( radius, segments, segments );
+					var skyGeometry = new THREE.SphereBufferGeometry( radius, segments, segments );
 					var skyMaterial = new THREE.MeshBasicMaterial( { fog: false, side: THREE.BackSide } );
 
 					if ( data.skyColor.length > 1 ) {
@@ -778,7 +756,7 @@ THREE.VRMLLoader.prototype = {
 
 						radius = 1.2e4;
 
-						var groundGeometry = new THREE.SphereGeometry( radius, segments, segments, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI );
+						var groundGeometry = new THREE.SphereBufferGeometry( radius, segments, segments, 0, 2 * Math.PI, 0.5 * Math.PI, 1.5 * Math.PI );
 						var groundMaterial = new THREE.MeshBasicMaterial( { fog: false, side: THREE.BackSide, vertexColors: THREE.VertexColors } );
 
 						paintFaces( groundGeometry, radius, data.groundAngle, data.groundColor, false );
@@ -793,68 +771,82 @@ THREE.VRMLLoader.prototype = {
 
 						var s = data.size;
 
-						parent.geometry = new THREE.BoxGeometry( s.x, s.y, s.z );
+						parent.geometry = new THREE.BoxBufferGeometry( s.x, s.y, s.z );
 
 					} else if ( 'Cylinder' === data.nodeType ) {
 
-						parent.geometry = new THREE.CylinderGeometry( data.radius, data.radius, data.height );
+						parent.geometry = new THREE.CylinderBufferGeometry( data.radius, data.radius, data.height );
 
 					} else if ( 'Cone' === data.nodeType ) {
 
-						parent.geometry = new THREE.CylinderGeometry( data.topRadius, data.bottomRadius, data.height );
+						parent.geometry = new THREE.CylinderBufferGeometry( data.topRadius, data.bottomRadius, data.height );
 
 					} else if ( 'Sphere' === data.nodeType ) {
 
-						parent.geometry = new THREE.SphereGeometry( data.radius );
+						parent.geometry = new THREE.SphereBufferGeometry( data.radius );
 
 					} else if ( 'IndexedFaceSet' === data.nodeType ) {
 
-						var geometry = new THREE.Geometry();
+						var geometry = new THREE.BufferGeometry();
+
+						var index = [];
+						var positions = [];
+						var uvs = [];
 
-						var indexes, uvIndexes, uvs;
+						var position, uv;
 
-						for ( var i = 0, j = data.children.length; i < j; i ++ ) {
+						var i, il, j, jl;
+
+						for ( i = 0, il = data.children.length; i < il; i ++ ) {
 
 							var child = data.children[ i ];
 
-							var vec;
+							// uvs
 
 							if ( 'TextureCoordinate' === child.nodeType ) {
 
-								uvs = child.points;
+								if ( child.points ) {
+
+									for ( j = 0, jl = child.points.length; j < jl; j ++ ) {
+
+										uv = child.points[ j ];
+										uvs.push( uv.x, uv.y );
+
+									}
+
+								}
 
 							}
 
+							// positions
 
 							if ( 'Coordinate' === child.nodeType ) {
 
 								if ( child.points ) {
 
-									for ( var k = 0, l = child.points.length; k < l; k ++ ) {
-
-										var point = child.points[ k ];
-
-										vec = new THREE.Vector3( point.x, point.y, point.z );
+									for ( j = 0, jl = child.points.length; j < jl; j ++ ) {
 
-										geometry.vertices.push( vec );
+										position = child.points[ j ];
+										positions.push( position.x, position.y, position.z );
 
 									}
 
 								}
 
-								if ( child.string.indexOf ( 'DEF' ) > -1 ) {
+								if ( child.string.indexOf ( 'DEF' ) > - 1 ) {
 
 									var name = /DEF\s+([^\s]+)/.exec( child.string )[ 1 ];
 
-									defines[ name ] = geometry.vertices;
+									defines[ name ] = positions.slice( 0 );
 
 								}
 
-								if ( child.string.indexOf ( 'USE' ) > -1 ) {
+								if ( child.string.indexOf ( 'USE' ) > - 1 ) {
 
 									var defineKey = /USE\s+([^\s]+)/.exec( child.string )[ 1 ];
 
-									geometry.vertices = defines[ defineKey ];
+									positions = defines[ defineKey ];
+
 								}
 
 							}
@@ -864,56 +856,59 @@ THREE.VRMLLoader.prototype = {
 						var skip = 0;
 
 						// some shapes only have vertices for use in other shapes
+
 						if ( data.coordIndex ) {
 
-							// read this: http://math.hws.edu/eck/cs424/notes2013/16_Threejs_Advanced.html
-							for ( var i = 0, j = data.coordIndex.length; i < j; i ++ ) {
+							var newPositions = [];
+							var newUvs = [];
+
+							position = new THREE.Vector3();
+							uv = new THREE.Vector2();
+
+							for ( i = 0, il = data.coordIndex.length; i < il; i ++ ) {
+
+								var indexes = data.coordIndex[ i ];
 
-								indexes = data.coordIndex[ i ]; if ( data.texCoordIndex ) uvIndexes = data.texCoordIndex[ i ];
+								// VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
 
-								// vrml support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here
 								skip = 0;
 
-								// 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 ) ) {
 
-									var face = new THREE.Face3(
-										indexes[ 0 ],
-										indexes[ skip + (data.ccw ? 1 : 2) ],
-										indexes[ skip + (data.ccw ? 2 : 1) ],
-										null // normal, will be added later
-										// todo: pass in the color, if a color index is present
-									);
-
-									if ( uvs && uvIndexes ) {
-										geometry.faceVertexUvs [0].push( [
-											new THREE.Vector2 (
-												uvs[ uvIndexes[ 0 ] ].x ,
-												uvs[ uvIndexes[ 0 ] ].y
-											) ,
-											new THREE.Vector2 (
-												uvs[ uvIndexes[ skip + (data.ccw ? 1 : 2) ] ].x ,
-												uvs[ uvIndexes[ skip + (data.ccw ? 1 : 2) ] ].y
-											) ,
-											new THREE.Vector2 (
-												uvs[ uvIndexes[ skip + (data.ccw ? 2 : 1) ] ].x ,
-												uvs[ uvIndexes[ skip + (data.ccw ? 2 : 1) ] ].y
-											)
-										] );
-									}
+									var i1 = indexes[ 0 ];
+									var i2 = indexes[ skip + ( data.ccw ? 1 : 2 ) ];
+									var i3 = indexes[ skip + ( data.ccw ? 2 : 1 ) ];
 
-									skip ++;
+									// create non indexed geometry, necessary for face normal generation
 
-									geometry.faces.push( face );
+									position.fromArray( positions, i1 * 3 );
+									uv.fromArray( uvs, i1 * 2 );
+									newPositions.push( position.x, position.y, position.z );
+									newUvs.push( uv.x, uv.y );
 
-								}
+									position.fromArray( positions, i2 * 3 );
+									uv.fromArray( uvs, i2 * 2 );
+									newPositions.push( position.x, position.y, position.z );
+									newUvs.push( uv.x, uv.y );
 
+									position.fromArray( positions, i3 * 3 );
+									uv.fromArray( uvs, i3 * 2 );
+									newPositions.push( position.x, position.y, position.z );
+									newUvs.push( uv.x, uv.y );
+
+									skip ++;
+
+								}
 
 							}
 
+							positions = newPositions;
+							uvs = newUvs;
+
 						} else {
 
 							// do not add dummy mesh to the scene
+
 							parent.parent.remove( parent );
 
 						}
@@ -927,8 +922,15 @@ THREE.VRMLLoader.prototype = {
 						// we need to store it on the geometry for use with defines
 						geometry.solid = data.solid;
 
-						geometry.computeFaceNormals();
-						//geometry.computeVertexNormals(); // does not show
+						geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
+
+						if ( uvs.length > 0 ) {
+
+							geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
+
+						}
+
+						geometry.computeVertexNormals();
 						geometry.computeBoundingSphere();
 
 						// see if it's a define

+ 6 - 6
examples/webgl_loader_vrml.html

@@ -21,7 +21,12 @@
 				z-index: 100;
 				display:block;
 			}
-			#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
+			#info a, .button {
+				color: #f00;
+				font-weight: bold;
+				text-decoration: underline;
+				cursor: pointer
+			}
 		</style>
 	</head>
 
@@ -49,8 +54,6 @@
 
 			var camera, controls, scene, renderer;
 
-			var cross;
-
 			init();
 			animate();
 
@@ -61,9 +64,6 @@
 
 				controls = new THREE.OrbitControls( camera );
 
-				controls.rotateSpeed = 5.0;
-				controls.zoomSpeed = 5;
-
 				scene = new THREE.Scene();
 				scene.add( camera );