Browse Source

Merge pull request #8427 from Mugen87/exporter

OBJExporter: Use BufferGeometry instead of Geometry
Mr.doob 9 years ago
parent
commit
53fbc5d5ab
2 changed files with 181 additions and 130 deletions
  1. 92 66
      examples/js/exporters/OBJExporter.js
  2. 89 64
      examples/webgl_exporter_obj.html

+ 92 - 66
examples/js/exporters/OBJExporter.js

@@ -16,60 +16,70 @@ THREE.OBJExporter.prototype = {
 		var indexVertexUvs = 0;
 		var indexNormals = 0;
 
-		var faceVertexKeys = [ "a", "b", "c" ];
+		var vertex = new THREE.Vector3();
+		var normal = new THREE.Vector3();
+		var uv = new THREE.Vector2();
+
+		var i, j, m, face = [];
 
 		var parseMesh = function ( mesh ) {
 
 			var nbVertex = 0;
-			var nbVertexUvs = 0;
 			var nbNormals = 0;
+			var nbVertexUvs = 0;
 
 			var geometry = mesh.geometry;
 
-			if ( geometry instanceof THREE.BufferGeometry ) {
-
-				geometry = new THREE.Geometry().fromBufferGeometry( geometry );
-
-			}
+			var normalMatrixWorld = new THREE.Matrix3();
 
 			if ( geometry instanceof THREE.Geometry ) {
 
-				output += 'o ' + mesh.name + '\n';
+				geometry = new THREE.BufferGeometry().setFromObject( mesh );
+
+			}
 
-				var vertices = geometry.vertices;
+			if ( geometry instanceof THREE.BufferGeometry ) {
 
-				for ( var i = 0, l = vertices.length; i < l; i ++ ) {
+				// shortcuts
+				var vertices = geometry.getAttribute( 'position' );
+				var normals = geometry.getAttribute( 'normal' );
+				var uvs = geometry.getAttribute( 'uv' );
+				var indices = geometry.getIndex();
 
-					var vertex = vertices[ i ].clone();
-					vertex.applyMatrix4( mesh.matrixWorld );
+				// name of the mesh object
+				output += 'o ' + mesh.name + '\n';
 
-					output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
+				// vertices
 
-					nbVertex ++;
+				if( vertices !== undefined ) {
 
-				}
+					for ( i = 0; i < vertices.count ; i ++, nbVertex++ ) {
 
-				// uvs
+						vertex.x = vertices.getX( i );
+						vertex.y = vertices.getY( i );
+						vertex.z = vertices.getZ( i );
 
-				var faces = geometry.faces;
-				var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
-				var hasVertexUvs = faces.length === faceVertexUvs.length;
+						// transfrom the vertex to world space
+						vertex.applyMatrix4( mesh.matrixWorld );
 
-				if ( hasVertexUvs ) {
+						// transform the vertex to export format
+						output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
 
-					for ( var i = 0, l = faceVertexUvs.length; i < l; i ++ ) {
+					}
 
-						var vertexUvs = faceVertexUvs[ i ];
+				}
 
-						for ( var j = 0, jl = vertexUvs.length; j < jl; j ++ ) {
+				// uvs
 
-							var uv = vertexUvs[ j ];
+				if( uvs !== undefined ) {
 
-							output += 'vt ' + uv.x + ' ' + uv.y + '\n';
+					for ( i = 0; i < uvs.count ; i ++, nbVertexUvs++ ) {
 
-							nbVertexUvs ++;
+						uv.x = uvs.getX( i );
+						uv.y = uvs.getY( i );
 
-						}
+						// transform the uv to export format
+						output += 'vt ' + uv.x + ' ' + uv.y + '\n';
 
 					}
 
@@ -77,64 +87,67 @@ THREE.OBJExporter.prototype = {
 
 				// normals
 
-				var normalMatrixWorld = new THREE.Matrix3();
-				normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
+				if( normals !== undefined ) {
 
-				for ( var i = 0, l = faces.length; i < l; i ++ ) {
+					normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
 
-					var face = faces[ i ];
-					var vertexNormals = face.vertexNormals;
+					for ( i = 0; i < normals.count ; i ++, nbNormals++ ) {
 
-					if ( vertexNormals.length === 3 ) {
+						normal.x = normals.getX( i );
+						normal.y = normals.getY( i );
+						normal.z = normals.getZ( i );
 
-						for ( var j = 0, jl = vertexNormals.length; j < jl; j ++ ) {
+						// transfrom the normal to world space
+						normal.applyMatrix3( normalMatrixWorld );
 
-							var normal = vertexNormals[ j ].clone();
-							normal.applyMatrix3( normalMatrixWorld );
+						// transform the normal to export format
+						output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
 
-							output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
+					}
 
-							nbNormals ++;
+				}
 
-						}
+				// faces
 
-					} else {
+				if( indices !== null ) {
 
-						var normal = face.normal.clone();
-						normal.applyMatrix3( normalMatrixWorld );
+					for ( i = 0; i < indices.count ; i += 3 ) {
 
-						for ( var j = 0; j < 3; j ++ ) {
+						for( m = 0; m < 3; m ++ ){
 
-							output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
+							j = indices.getX( i + m ) + 1;
 
-							nbNormals ++;
+							face[ m ] = ( indexVertex + j ) + '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j );
 
 						}
 
+						// transform the face to export format
+						output += 'f ' + face.join( ' ' ) + "\n";
+
 					}
 
-				}
+				} else {
 
-				// faces
-				var indices = [];
+					for ( i = 0; i < vertices.count ; i += 3 ) {
 
-				for ( var i = 0, j = 1, l = faces.length; i < l; i ++, j += 3 ) {
+						for( m = 0; m < 3; m ++ ){
 
-					var face = faces[ i ];
+							j = i + m + 1;
 
-					for ( var m = 0; m < 3; m ++ ) {
+							face[ m ] = ( indexVertex + j ) + '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j );
 
-					    indices[ m ] = ( indexVertex + face[ faceVertexKeys[ m ] ] + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + m + 1 ) : '' ) + '/' + ( indexNormals + j + m + 1 );
+						}
 
-					}
+						// transform the face to export format
+						output += 'f ' + face.join( ' ' ) + "\n";
 
-					output += 'f ' + indices.join( ' ' ) + "\n";
+					}
 
 				}
 
 			} else {
 
-				console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', mesh );
+				console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', geometry );
 
 			}
 
@@ -150,24 +163,36 @@ THREE.OBJExporter.prototype = {
 			var geometry = line.geometry;
 			var type = line.type;
 
-			if ( geometry instanceof THREE.BufferGeometry ) {
+			if ( geometry instanceof THREE.Geometry ) {
 
-				geometry = new THREE.Geometry().fromBufferGeometry( geometry );
+				geometry = new THREE.BufferGeometry().setFromObject( line );
 
 			}
 
-			if ( geometry instanceof THREE.Geometry ) {
+			if ( geometry instanceof THREE.BufferGeometry ) {
+
+				// shortcuts
+				var vertices = geometry.getAttribute( 'position' );
+				var indices = geometry.getIndex();
 
+				// name of the line object
 				output += 'o ' + line.name + '\n';
 
-				var vertices = geometry.vertices;
+				if( vertices !== undefined ) {
 
-				for ( var i = 0, l = vertices.length; i < l; i++ ) {
+					for ( i = 0; i < vertices.count ; i ++ ) {
 
-					var vertex = vertices[ i ].clone();
-					vertex.applyMatrix4( line.matrixWorld );
+						vertex.x = vertices.getX( i );
+						vertex.y = vertices.getY( i );
+						vertex.z = vertices.getZ( i );
 
-					output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
+						// transfrom the vertex to world space
+						vertex.applyMatrix4( line.matrixWorld );
+
+						// transform the vertex to export format
+						output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
+
+					}
 
 				}
 
@@ -175,7 +200,7 @@ THREE.OBJExporter.prototype = {
 
 					output += 'l ';
 
-					for ( var j = 1, m = vertices.length; j <= m; j++ ) {
+					for ( j = 1; j <= vertices.count; j++ ) {
 
 						output += j + ' ';
 
@@ -187,7 +212,7 @@ THREE.OBJExporter.prototype = {
 
 				if ( type === 'LineSegments' ) {
 
-					for ( var j = 1, k = j + 1, m = vertices.length; j < m; j += 2, k = j + 1 ) {
+					for ( j = 1, k = j + 1; j < vertices.count; j += 2, k = j + 1 ) {
 
 						output += 'l ' + j + ' ' + k + '\n';
 
@@ -197,9 +222,10 @@ THREE.OBJExporter.prototype = {
 
 			} else {
 
-				console.warn('THREE.OBJExporter.parseLine(): geometry type unsupported', line);
+				console.warn('THREE.OBJExporter.parseLine(): geometry type unsupported', geometry );
 
 			}
+
 		};
 
 		object.traverse( function ( child ) {

+ 89 - 64
examples/webgl_exporter_obj.html

@@ -70,77 +70,93 @@
 			var exportButton, floatingDiv;
 			var mouseX = 0, mouseY = 0;
 
-			function exportToObj ()
-			{
-				var exporter = new THREE.OBJExporter ();
-				var result = exporter.parse (scene);
+			function exportToObj() {
+
+				var exporter = new THREE.OBJExporter();
+				var result = exporter.parse( scene );
 				floatingDiv.style.display = 'block';
-				floatingDiv.innerHTML = result.split ('\n').join ('<br />');
+				floatingDiv.innerHTML = result.split( '\n' ).join ( '<br />' );
+
 			}
 
-			function addGeometry (type)
-			{
-				for (var i = 0; i < scene.children.length; i++) {
-					var current = scene.children[i];
-					if (current instanceof THREE.Mesh) {
-						current.geometry.dispose ();
-						scene.remove (current);
+			function addGeometry( type ) {
+
+				for( var i = 0; i < scene.children.length; i++ ) {
+
+					var current = scene.children[ i ];
+
+					if( current instanceof THREE.Mesh ) {
+
+						current.geometry.dispose();
+						scene.remove( current );
 						i--;
+
 					}
+
 				}
 
-				console.log (renderer.info);
-
-				if (type == 1) {
-					var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } );
-					var geometry = new THREE.Geometry ();
-					geometry.vertices.push (new THREE.Vector3 (-50, -50, 0));
-					geometry.vertices.push (new THREE.Vector3 (50, -50, 0));
-					geometry.vertices.push (new THREE.Vector3 (50, 50, 0));
-					var face = new THREE.Face3 (0, 1, 2);
-					geometry.faces.push (face);
-					geometry.computeFaceNormals ();
+				if ( type === 1 ) {
+
+					var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } );
+
+					var geometry = new THREE.Geometry();
+					geometry.vertices.push( new THREE.Vector3( -50, -50, 0 ) );
+					geometry.vertices.push( new THREE.Vector3(  50, -50, 0 ) );
+					geometry.vertices.push( new THREE.Vector3(  50,  50, 0 ) );
+					var face = new THREE.Face3( 0, 1, 2 );
+					geometry.faces.push( face );
+					geometry.computeFaceNormals();
+
 					scene.add( new THREE.Mesh( geometry, material ) );
-				} else if (type == 2) {
-					var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } );
-					var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+
+
+				} else if ( type === 2 ) {
+
+					var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } );
+					var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
 					scene.add( new THREE.Mesh( geometry, material ) );
-				} else if (type == 3) {
-					var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } );
-					var geometry = new THREE.CylinderGeometry( 50, 50, 100, 30, 1 );
+
+				} else if ( type === 3 ) {
+
+					var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } );
+					var geometry = new THREE.CylinderBufferGeometry( 50, 50, 100, 30, 1 );
 					scene.add( new THREE.Mesh( geometry, material ) );
-				} else if (type == 4 || type == 5) {
-					var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } );
-
-					var geometry = new THREE.Geometry ();
-					geometry.vertices.push (new THREE.Vector3 (-50, -50, 0));
-					geometry.vertices.push (new THREE.Vector3 (50, -50, 0));
-					geometry.vertices.push (new THREE.Vector3 (50, 50, 0));
-					geometry.faces.push (new THREE.Face3 (0, 1, 2));
-					geometry.computeFaceNormals ();
+
+				} else if ( type === 4 || type === 5 ) {
+
+					var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } );
+
+					var geometry = new THREE.Geometry();
+					geometry.vertices.push( new THREE.Vector3( -50, -50, 0 ) );
+					geometry.vertices.push( new THREE.Vector3(  50, -50, 0 ) );
+					geometry.vertices.push( new THREE.Vector3(  50,  50, 0 ) );
+					var face = new THREE.Face3( 0, 1, 2 );
+					geometry.faces.push( face );
+					geometry.computeFaceNormals();
+
 					var mesh = new THREE.Mesh( geometry, material );
 					mesh.position.x = -200;
-					if (type == 5) {
-						mesh.rotation.y = Math.PI / 4.0;
-					}
 					scene.add( mesh );
 
-					var geometry2 = new THREE.BoxGeometry( 100, 100, 100 );
+					var geometry2 = new THREE.BoxBufferGeometry( 100, 100, 100 );
 					var mesh2 = new THREE.Mesh( geometry2, material );
-					if (type == 5) {
-						mesh2.rotation.y = Math.PI / 4.0;
-					}
 					scene.add( mesh2 );
 
-					var geometry3 = new THREE.CylinderGeometry( 50, 50, 100, 30, 1 );
+					var geometry3 = new THREE.CylinderBufferGeometry( 50, 50, 100, 30, 1 );
 					var mesh3 = new THREE.Mesh( geometry3, material );
-					if (type == 5) {
+					mesh3.position.x = 200;
+					scene.add( mesh3 );
+
+					if ( type === 5 ) {
+
+						mesh.rotation.y = Math.PI / 4.0;
+						mesh2.rotation.y = Math.PI / 4.0;
 						mesh3.rotation.y = Math.PI / 4.0;
+
 					}
-					mesh3.position.x = 200;
 
-					scene.add( mesh3 );
 				}
+
 			}
 
 			function init() {
@@ -151,48 +167,57 @@
 				document.body.appendChild( renderer.domElement );
 
 				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
-				camera.position.set (0, 0, 400);
+				camera.position.set( 0, 0, 400 );
 
 				scene = new THREE.Scene();
 
 				light = new THREE.DirectionalLight( 0xffffff );
 				scene.add( light );
 
-				addGeometry (1);
+				addGeometry( 1 );
 
 				window.addEventListener( 'click', onWindowClick, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
 				document.addEventListener( 'mouseover', onDocumentMouseMove, false );
 
-				document.getElementById( 'triangle' ).addEventListener( 'click', function() { addGeometry (1); });
-				document.getElementById( 'cube' ).addEventListener( 'click', function() { addGeometry (2); });
-				document.getElementById( 'cylinder' ).addEventListener( 'click', function() { addGeometry (3); });
-				document.getElementById( 'both' ).addEventListener( 'click', function() { addGeometry (4); });
-				document.getElementById( 'transformed' ).addEventListener( 'click', function() { addGeometry (5); });
+				document.getElementById( 'triangle' ).addEventListener( 'click', function() { addGeometry( 1 ); } );
+				document.getElementById( 'cube' ).addEventListener( 'click', function() { addGeometry( 2 ); } );
+				document.getElementById( 'cylinder' ).addEventListener( 'click', function() { addGeometry( 3 ); } );
+				document.getElementById( 'both' ).addEventListener( 'click', function() { addGeometry( 4 ); } );
+				document.getElementById( 'transformed' ).addEventListener( 'click', function() { addGeometry( 5 ); } );
 
 				exportButton = document.getElementById( 'export' );
-				exportButton.addEventListener( 'click', function() { exportToObj (); });
+				exportButton.addEventListener( 'click', function() { exportToObj(); });
 
-				floatingDiv = document.createElement ('div');
+				floatingDiv = document.createElement( 'div' );
 				floatingDiv.className = 'floating';
-				document.body.appendChild (floatingDiv);
+				document.body.appendChild( floatingDiv );
+
 			}
 
-			function onWindowClick(event) {
+			function onWindowClick( event ) {
 
 				var needToClose = true;
 				var target = event.target;
-				while (target !== null) {
-					if (target === floatingDiv || target == exportButton) {
+
+				while( target !== null ) {
+
+					if ( target === floatingDiv || target === exportButton ) {
+
 						needToClose = false;
 						break;
+
 					}
+
 					target = target.parentElement;
+
 				}
 
-				if (needToClose) {
+				if ( needToClose ) {
+
 					floatingDiv.style.display = 'none';
+
 				}
 
 			}
@@ -223,7 +248,7 @@
 				camera.position.y += ( -mouseY - camera.position.y ) * .05;
 				camera.lookAt( scene.position );
 
-				light.position.set( camera.position.x, camera.position.y, camera.position.z ).normalize ();
+				light.position.set( camera.position.x, camera.position.y, camera.position.z ).normalize();
 				renderer.render( scene, camera );
 
 			}