浏览代码

Moved *Exporter code to the objects themselves. See #4621.

Mr.doob 11 年之前
父节点
当前提交
f8ecbb150e

+ 1 - 8
editor/index.html

@@ -26,7 +26,6 @@
 		<script src="../examples/js/loaders/ctm/lzma.js"></script>
 		<script src="../examples/js/loaders/ctm/ctm.js"></script>
 		<script src="../examples/js/loaders/ctm/CTMLoader.js"></script>
-		<script src="../examples/js/exporters/SceneExporter.js"></script>
 		<script src="../examples/js/exporters/OBJExporter.js"></script>
 		<script src="../examples/js/exporters/STLExporter.js"></script>
 		<script src="../examples/js/renderers/RaytracingRenderer.js"></script>
@@ -35,11 +34,6 @@
 
 		<!-- WIP -->
 
-		<script src="../examples/js/exporters/BufferGeometryExporter.js"></script>
-		<script src="../examples/js/exporters/TypedGeometryExporter.js"></script>
-		<script src="../examples/js/exporters/GeometryExporter.js"></script>
-		<script src="../examples/js/exporters/MaterialExporter.js"></script>
-		<script src="../examples/js/exporters/ObjectExporter.js"></script>
 		<script src="../examples/js/renderers/WebGLRenderer3.js"></script>
 
 		<script src="js/libs/signals.min.js"></script>
@@ -130,7 +124,6 @@
 				//
 
 				var timeout;
-				var exporter = new THREE.ObjectExporter();
 
 				var saveState = function ( scene ) {
 
@@ -138,7 +131,7 @@
 
 					timeout = setTimeout( function () {
 
-						editor.storage.set( exporter.parse( editor.scene ) );
+						editor.storage.set( editor.scene.toJSON() );
 
 					}, 1000 );
 

+ 53 - 62
editor/js/Menubar.File.js

@@ -86,15 +86,11 @@ Menubar.File = function ( editor ) {
 
 		}
 
-		if ( geometry instanceof THREE.BufferGeometry ) {
-
-			exportGeometry( THREE.BufferGeometryExporter );
-
-		} else if ( geometry instanceof THREE.Geometry ) {
-
-			exportGeometry( THREE.GeometryExporter );
+		var output = geometry.toJSON();
+		output = JSON.stringify( output, null, '\t' );
+		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
 
-		}
+		exportString( output );
 
 	} );
 	options.add( option );
@@ -106,14 +102,20 @@ Menubar.File = function ( editor ) {
 	option.setTextContent( 'Export Object' );
 	option.onClick( function () {
 
-		if ( editor.selected === null ) {
+		var object = editor.selected;
+
+		if ( object === null ) {
 
 			alert( 'No object selected' );
 			return;
 
 		}
 
-		exportObject( THREE.ObjectExporter );
+		var output = object.toJSON();
+		output = JSON.stringify( output, null, '\t' );
+		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
+
+		exportString( output );
 
 	} );
 	options.add( option );
@@ -125,7 +127,11 @@ Menubar.File = function ( editor ) {
 	option.setTextContent( 'Export Scene' );
 	option.onClick( function () {
 
-		exportScene( THREE.ObjectExporter );
+		var output = editor.scene.toJSON();
+		output = JSON.stringify( output, null, '\t' );
+		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
+
+		exportString( output );
 
 	} );
 	options.add( option );
@@ -137,7 +143,27 @@ Menubar.File = function ( editor ) {
 	option.setTextContent( 'Export OBJ' );
 	option.onClick( function () {
 
-		exportGeometry( THREE.OBJExporter );
+		var object = editor.selected;
+
+		if ( object === null ) {
+
+			alert( 'No object selected.' );
+			return;
+
+		}
+
+		var geometry = object.geometry;
+
+		if ( geometry === undefined ) {
+
+			alert( 'The selected object doesn\'t have geometry.' );
+			return;
+
+		}
+
+		var exporter = new OBJExporter();
+
+		exportString( exporter.parse( geometry ) );
 
 	} );
 	options.add( option );
@@ -149,7 +175,9 @@ Menubar.File = function ( editor ) {
 	option.setTextContent( 'Export STL' );
 	option.onClick( function () {
 
-		exportScene( THREE.STLExporter );
+		var exporter = new STLExporter();
+
+		exportString( exporter.parse( editor.scene ) );
 
 	} );
 	options.add( option );
@@ -158,6 +186,8 @@ Menubar.File = function ( editor ) {
 
 	options.add( new UI.HorizontalRule() );
 
+	/*
+
 	// Test
 
 	var option = new UI.Panel();
@@ -170,61 +200,22 @@ Menubar.File = function ( editor ) {
 
 	} );
 	options.add( option );
+	*/
 
+	// Publish
 
-	//
-	
-	var exportGeometry = function ( exporterClass ) {
-
-		var object = editor.selected;
-		var exporter = new exporterClass();
-
-		var output = exporter.parse( object.geometry );
-
-		if ( exporter instanceof THREE.BufferGeometryExporter ||
-		     exporter instanceof THREE.GeometryExporter ) {
-
-			output = JSON.stringify( output, null, '\t' );
-			output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
-
-		}
-
-		var blob = new Blob( [ output ], { type: 'text/plain' } );
-		var objectURL = URL.createObjectURL( blob );
-
-		window.open( objectURL, '_blank' );
-		window.focus();
-
-	};
-
-	var exportObject = function ( exporterClass ) {
-
-		var object = editor.selected;
-		var exporter = new exporterClass();
-
-		var output = JSON.stringify( exporter.parse( object ), null, '\t' );
-		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
-
-		var blob = new Blob( [ output ], { type: 'text/plain' } );
-		var objectURL = URL.createObjectURL( blob );
-
-		window.open( objectURL, '_blank' );
-		window.focus();
-
-	};
-
-	var exportScene = function ( exporterClass ) {
-
-		var exporter = new exporterClass();
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'Publish' );
+	option.onClick( function () {
 
-		var output = exporter.parse( editor.scene );
+	} );
+	options.add( option );
 
-		if ( exporter instanceof THREE.ObjectExporter ) {
 
-			output = JSON.stringify( output, null, '\t' );
-			output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
+	//
 
-		}
+	var exportString = function ( output ) {
 
 		var blob = new Blob( [ output ], { type: 'text/plain' } );
 		var objectURL = URL.createObjectURL( blob );

+ 0 - 66
examples/js/exporters/BufferGeometryExporter.js

@@ -1,66 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-THREE.BufferGeometryExporter = function () {};
-
-THREE.BufferGeometryExporter.prototype = {
-
-	constructor: THREE.BufferGeometryExporter,
-
-	parse: function ( geometry ) {
-
-		var output = {
-			metadata: {
-				version: 4.0,
-				type: 'BufferGeometry',
-				generator: 'BufferGeometryExporter'
-			},
-			attributes: {
-			}
-		};
-
-		var attributes = geometry.attributes;
-		var offsets = geometry.offsets;
-		var boundingSphere = geometry.boundingSphere;
-
-		for ( var key in attributes ) {
-
-			var attribute = attributes[ key ];
-
-			var array = [], typeArray = attribute.array;
-
-			for ( var i = 0, l = typeArray.length; i < l; i ++ ) {
-
-				array[ i ] = typeArray[ i ];
-
-			}
-
-			output.attributes[ key ] = {
-				itemSize: attribute.itemSize,
-				type: attribute.array.constructor.name,
-				array: array
-			}
-
-		}
-
-		if ( offsets.length > 0 ) {
-
-			output.offsets = JSON.parse( JSON.stringify( offsets ) );
-
-		}
-
-		if ( boundingSphere !== null ) {
-
-			output.boundingSphere = {
-				center: boundingSphere.center.toArray(),
-				radius: boundingSphere.radius
-			}
-
-		}
-
-		return output;
-
-	}
-
-};

+ 0 - 192
examples/js/exporters/GeometryExporter.js

@@ -1,192 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-THREE.GeometryExporter = function () {};
-
-THREE.GeometryExporter.prototype = {
-
-	constructor: THREE.GeometryExporter,
-
-	parse: function ( geometry ) {
-
-		var output = {
-			metadata: {
-				version: 4.0,
-				type: 'geometry',
-				generator: 'GeometryExporter'
-			}
-		};
-
-		var vertices = [];
-
-		for ( var i = 0; i < geometry.vertices.length; i ++ ) {
-
-			var vertex = geometry.vertices[ i ];
-			vertices.push( vertex.x, vertex.y, vertex.z );
-
-		}
-
-		var faces = [];
-		var normals = [];
-		var normalsHash = {};
-		var colors = [];
-		var colorsHash = {};
-		var uvs = [];
-		var uvsHash = {};
-
-		for ( var i = 0; i < geometry.faces.length; i ++ ) {
-
-			var face = geometry.faces[ i ];
-
-			var hasMaterial = false; // face.materialIndex !== undefined;
-			var hasFaceUv = false; // deprecated
-			var hasFaceVertexUv = geometry.faceVertexUvs[ 0 ][ i ] !== undefined;
-			var hasFaceNormal = face.normal.length() > 0;
-			var hasFaceVertexNormal = face.vertexNormals.length > 0;
-			var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
-			var hasFaceVertexColor = face.vertexColors.length > 0;
-
-			var faceType = 0;
-
-			faceType = setBit( faceType, 0, 0 );
-			faceType = setBit( faceType, 1, hasMaterial );
-			faceType = setBit( faceType, 2, hasFaceUv );
-			faceType = setBit( faceType, 3, hasFaceVertexUv );
-			faceType = setBit( faceType, 4, hasFaceNormal );
-			faceType = setBit( faceType, 5, hasFaceVertexNormal );
-			faceType = setBit( faceType, 6, hasFaceColor );
-			faceType = setBit( faceType, 7, hasFaceVertexColor );
-
-			faces.push( faceType );
-			faces.push( face.a, face.b, face.c );
-
-
-			/*
-			if ( hasMaterial ) {
-
-				faces.push( face.materialIndex );
-
-			}
-			*/
-
-			if ( hasFaceVertexUv ) {
-
-				var faceVertexUvs = geometry.faceVertexUvs[ 0 ][ i ];
-
-				faces.push(
-					getUvIndex( faceVertexUvs[ 0 ] ),
-					getUvIndex( faceVertexUvs[ 1 ] ),
-					getUvIndex( faceVertexUvs[ 2 ] )
-				);
-
-			}
-
-			if ( hasFaceNormal ) {
-
-				faces.push( getNormalIndex( face.normal ) );
-
-			}
-
-			if ( hasFaceVertexNormal ) {
-
-				var vertexNormals = face.vertexNormals;
-
-				faces.push(
-					getNormalIndex( vertexNormals[ 0 ] ),
-					getNormalIndex( vertexNormals[ 1 ] ),
-					getNormalIndex( vertexNormals[ 2 ] )
-				);
-
-			}
-
-			if ( hasFaceColor ) {
-
-				faces.push( getColorIndex( face.color ) );
-
-			}
-
-			if ( hasFaceVertexColor ) {
-
-				var vertexColors = face.vertexColors;
-
-				faces.push(
-					getColorIndex( vertexColors[ 0 ] ),
-					getColorIndex( vertexColors[ 1 ] ),
-					getColorIndex( vertexColors[ 2 ] )
-				);
-
-			}
-
-		}
-
-		function setBit( value, position, enabled ) {
-
-			return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position) );
-
-		}
-
-		function getNormalIndex( normal ) {
-
-			var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
-
-			if ( normalsHash[ hash ] !== undefined ) {
-
-				return normalsHash[ hash ];
-
-			}
-
-			normalsHash[ hash ] = normals.length / 3;
-			normals.push( normal.x, normal.y, normal.z );
-
-			return normalsHash[ hash ];
-
-		}
-
-		function getColorIndex( color ) {
-
-			var hash = color.r.toString() + color.g.toString() + color.b.toString();
-
-			if ( colorsHash[ hash ] !== undefined ) {
-
-				return colorsHash[ hash ];
-
-			}
-
-			colorsHash[ hash ] = colors.length;
-			colors.push( color.getHex() );
-
-			return colorsHash[ hash ];
-
-		}
-
-		function getUvIndex( uv ) {
-
-			var hash = uv.x.toString() + uv.y.toString();
-
-			if ( uvsHash[ hash ] !== undefined ) {
-
-				return uvsHash[ hash ];
-
-			}
-
-			uvsHash[ hash ] = uvs.length / 2;
-			uvs.push( uv.x, uv.y );
-
-			return uvsHash[ hash ];
-
-		}
-
-		output.vertices = vertices;
-		output.normals = normals;
-		if ( colors.length > 0 ) output.colors = colors;
-		if ( uvs.length > 0 ) output.uvs = [ uvs ]; // temporal backward compatibility
-		output.faces = faces;
-
-		//
-
-		return output;
-
-	}
-
-};

+ 0 - 17
examples/js/exporters/HTMLExporter.js

@@ -1,17 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-THREE.HTMLExporter = function () {};
-
-THREE.HTMLExporter.prototype = {
-
-	constructor: THREE.HTMLExporter,
-
-	parse: function ( scene ) {
-
-		return output;
-
-	}
-
-}

+ 0 - 113
examples/js/exporters/MaterialExporter.js

@@ -1,113 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-THREE.MaterialExporter = function () {};
-
-THREE.MaterialExporter.prototype = {
-
-	constructor: THREE.MaterialExporter,
-
-	parse: function ( material ) {
-
-		var output = {
-			metadata: {
-				version: 4.2,
-				type: 'material',
-				generator: 'MaterialExporter'
-			}
-		};
-
-		output.uuid = material.uuid;
-
-		if ( material.name !== "" ) output.name = material.name;
-
-		if ( material instanceof THREE.MeshBasicMaterial ) {
-
-			output.type = 'MeshBasicMaterial';
-			output.color = material.color.getHex();
-			if ( material.vertexColors !== THREE.NoColors ) output.vertexColors = material.vertexColors;
-			if ( material.blending !== THREE.NormalBlending ) output.blending = material.blending;
-			if ( material.side !== THREE.FrontSide ) output.side = material.side;
-			output.opacity = material.opacity;
-			output.transparent = material.transparent;
-			output.wireframe = material.wireframe;
-
-		} else if ( material instanceof THREE.MeshLambertMaterial ) {
-
-			output.type = 'MeshLambertMaterial';
-			output.color = material.color.getHex();
-			output.ambient = material.ambient.getHex();
-			output.emissive = material.emissive.getHex();
-			if ( material.vertexColors !== THREE.NoColors ) output.vertexColors = material.vertexColors;
-			if ( material.blending !== THREE.NormalBlending ) output.blending = material.blending;
-			if ( material.side !== THREE.FrontSide ) output.side = material.side;
-			output.opacity = material.opacity;
-			output.transparent = material.transparent;
-			output.wireframe = material.wireframe;
-
-		} else if ( material instanceof THREE.MeshPhongMaterial ) {
-
-			output.type = 'MeshPhongMaterial';
-			output.color = material.color.getHex();
-			output.ambient = material.ambient.getHex();
-			output.emissive = material.emissive.getHex();
-			output.specular = material.specular.getHex();
-			output.shininess = material.shininess;
-			if ( material.vertexColors !== THREE.NoColors ) output.vertexColors = material.vertexColors;
-			if ( material.blending !== THREE.NormalBlending ) output.blending = material.blending;
-			if ( material.side !== THREE.FrontSide ) output.side = material.side;
-			output.opacity = material.opacity;
-			output.transparent = material.transparent;
-			output.wireframe = material.wireframe;
-
-		} else if ( material instanceof THREE.MeshNormalMaterial ) {
-
-			output.type = 'MeshNormalMaterial';
-			if ( material.blending !== THREE.NormalBlending ) output.blending = material.blending;
-			if ( material.side !== THREE.FrontSide ) output.side = material.side;
-			output.opacity = material.opacity;
-			output.transparent = material.transparent;
-			output.wireframe = material.wireframe;
-
-		} else if ( material instanceof THREE.MeshDepthMaterial ) {
-
-			output.type = 'MeshDepthMaterial';
-			if ( material.blending !== THREE.NormalBlending ) output.blending = material.blending;
-			if ( material.side !== THREE.FrontSide ) output.side = material.side;
-			output.opacity = material.opacity;
-			output.transparent = material.transparent;
-			output.wireframe = material.wireframe;
-
-		} else if ( material instanceof THREE.MeshFaceMaterial ) {
-
-			output.type = 'MeshFaceMaterial';
-			output.materials = [];
-
-			for ( var i = 0, l = material.materials.length; i < l; i ++ ) {
-
-				output.materials.push( this.parse( material.materials[ i ] ) );
-
-			}
-
-		} else if ( material instanceof THREE.ShaderMaterial ) {
-
-			output.type = 'ShaderMaterial';
-			output.uniforms = material.uniforms;
-			output.vertexShader = material.vertexShader;
-			output.fragmentShader = material.fragmentShader;
-
-		} else if ( material instanceof THREE.SpriteMaterial ) {
-
-			output.type = 'SpriteMaterial';
-			output.color = material.color.getHex();
-			output.opacity = material.opacity;
-			output.transparent = material.transparent;
-
-		}
-
-		return output;
-
-	}
-
-};

+ 0 - 268
examples/js/exporters/ObjectExporter.js

@@ -1,268 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-THREE.ObjectExporter = function () {};
-
-THREE.ObjectExporter.prototype = {
-
-	constructor: THREE.ObjectExporter,
-
-	parse: function ( object ) {
-
-		// console.log( object );
-
-		var output = {
-			metadata: {
-				version: 4.3,
-				type: 'Object',
-				generator: 'ObjectExporter'
-			}
-		};
-
-		//
-
-		var geometries = {};
-		var geometryExporter = new THREE.GeometryExporter();
-		var bufferGeometryExporter = new THREE.BufferGeometryExporter();
-
-		var parseGeometry = function ( geometry ) {
-
-			if ( output.geometries === undefined ) {
-
-				output.geometries = [];
-
-			}
-
-			if ( geometries[ geometry.uuid ] === undefined ) {
-
-				var data = {};
-
-				data.uuid = geometry.uuid;
-
-				if ( geometry.name !== "" ) data.name = geometry.name;
-
-				var handleParameters = function ( parameters ) {
-
-					for ( var i = 0; i < parameters.length; i ++ ) {
-
-						var parameter = parameters[ i ];
-
-						if ( geometry.parameters[ parameter ] !== undefined ) {
-
-							data[ parameter ] = geometry.parameters[ parameter ];
-
-						}
-
-					}
-
-				};
-
-				if ( geometry instanceof THREE.PlaneGeometry ) {
-
-					data.type = 'PlaneGeometry';
-					handleParameters( [ 'width', 'height', 'widthSegments', 'heightSegments' ] );
-
-				} else if ( geometry instanceof THREE.BoxGeometry ) {
-
-					data.type = 'BoxGeometry';
-					handleParameters( [ 'width', 'height', 'depth', 'widthSegments', 'heightSegments', 'depthSegments' ] );
-
-				} else if ( geometry instanceof THREE.CircleGeometry ) {
-
-					data.type = 'CircleGeometry';
-					handleParameters( [ 'radius', 'segments' ] );
-
-				} else if ( geometry instanceof THREE.CylinderGeometry ) {
-
-					data.type = 'CylinderGeometry';
-					handleParameters( [ 'radiusTop', 'radiusBottom', 'height', 'radialSegments', 'heightSegments', 'openEnded' ] );
-
-				} else if ( geometry instanceof THREE.SphereGeometry ) {
-
-					data.type = 'SphereGeometry';
-					handleParameters( [ 'radius', 'widthSegments', 'heightSegments', 'phiStart', 'phiLength', 'thetaStart', 'thetaLength' ] );
-
-				} else if ( geometry instanceof THREE.IcosahedronGeometry ) {
-
-					data.type = 'IcosahedronGeometry';
-					handleParameters( [ 'radius', 'detail' ] );
-
-				} else if ( geometry instanceof THREE.TorusGeometry ) {
-
-					data.type = 'TorusGeometry';
-					handleParameters( [ 'radius', 'tube', 'radialSegments', 'tubularSegments', 'arc' ] );
-
-				} else if ( geometry instanceof THREE.TorusKnotGeometry ) {
-
-					data.type = 'TorusKnotGeometry';
-					handleParameters( [ 'radius', 'tube', 'radialSegments', 'tubularSegments', 'p', 'q', 'heightScale' ] );
-
-				} else if ( geometry instanceof THREE.BufferGeometry ) {
-
-					data.type = 'BufferGeometry';
-					data.data = bufferGeometryExporter.parse( geometry );
-
-					delete data.data.metadata;
-
-				} else if ( geometry instanceof THREE.Geometry ) {
-
-					data.type = 'Geometry';
-					data.data = geometryExporter.parse( geometry );
-
-					delete data.data.metadata;
-
-				}
-
-				geometries[ geometry.uuid ] = data;
-
-				output.geometries.push( data );
-
-			}
-
-			return geometry.uuid;
-
-		};
-
-		//
-
-		var materials = {};
-		var materialExporter = new THREE.MaterialExporter();
-
-		var parseMaterial = function ( material ) {
-
-			if ( output.materials === undefined ) {
-
-				output.materials = [];
-
-			}
-
-			if ( materials[ material.uuid ] === undefined ) {
-
-				var data = materialExporter.parse( material );
-
-				delete data.metadata;
-
-				materials[ material.uuid ] = data;
-
-				output.materials.push( data );
-
-			}
-
-			return material.uuid;
-
-		};
-
-		//
-
-		var parseObject = function ( object ) {
-
-			var data = {};
-
-			data.uuid = object.uuid;
-
-			if ( object.name !== '' ) data.name = object.name;
-			if ( JSON.stringify( object.userData ) !== '{}' ) data.userData = object.userData;
-			if ( object.visible !== true ) data.visible = object.visible;
-
-			if ( object instanceof THREE.Scene ) {
-
-				data.type = 'Scene';
-
-			} else if ( object instanceof THREE.PerspectiveCamera ) {
-
-				data.type = 'PerspectiveCamera';
-				data.fov = object.fov;
-				data.aspect = object.aspect;
-				data.near = object.near;
-				data.far = object.far;
-
-			} else if ( object instanceof THREE.OrthographicCamera ) {
-
-				data.type = 'OrthographicCamera';
-				data.left = object.left;
-				data.right = object.right;
-				data.top = object.top;
-				data.bottom = object.bottom;
-				data.near = object.near;
-				data.far = object.far;
-
-			} else if ( object instanceof THREE.AmbientLight ) {
-
-				data.type = 'AmbientLight';
-				data.color = object.color.getHex();
-
-			} else if ( object instanceof THREE.DirectionalLight ) {
-
-				data.type = 'DirectionalLight';
-				data.color = object.color.getHex();
-				data.intensity = object.intensity;
-
-			} else if ( object instanceof THREE.PointLight ) {
-
-				data.type = 'PointLight';
-				data.color = object.color.getHex();
-				data.intensity = object.intensity;
-				data.distance = object.distance;
-
-			} else if ( object instanceof THREE.SpotLight ) {
-
-				data.type = 'SpotLight';
-				data.color = object.color.getHex();
-				data.intensity = object.intensity;
-				data.distance = object.distance;
-				data.angle = object.angle;
-				data.exponent = object.exponent;
-
-			} else if ( object instanceof THREE.HemisphereLight ) {
-
-				data.type = 'HemisphereLight';
-				data.color = object.color.getHex();
-				data.groundColor = object.groundColor.getHex();
-
-			} else if ( object instanceof THREE.Mesh ) {
-
-				data.type = 'Mesh';
-				data.geometry = parseGeometry( object.geometry );
-				data.material = parseMaterial( object.material );
-
-			} else if ( object instanceof THREE.Sprite ) {
-
-				data.type = 'Sprite';
-				data.material = parseMaterial( object.material );
-
-			} else if ( object instanceof THREE.Group ) {
-
-				data.type = 'Group';
-
-			} else {
-
-				data.type = 'Object3D';
-
-			}
-
-			data.matrix = object.matrix.toArray();
-
-			if ( object.children.length > 0 ) {
-
-				data.children = [];
-
-				for ( var i = 0; i < object.children.length; i ++ ) {
-
-					data.children.push( parseObject( object.children[ i ] ) );
-
-				}
-
-			}
-
-			return data;
-
-		}
-
-		output.object = parseObject( object );
-
-		return output;
-
-	}
-
-}

+ 59 - 0
src/core/BufferGeometry.js

@@ -1,5 +1,6 @@
 /**
  * @author alteredq / http://alteredqualia.com/
+ * @author mrdoob / http://mrdoob.com/
  */
 
 THREE.BufferGeometry = function () {
@@ -869,6 +870,64 @@ THREE.BufferGeometry.prototype = {
 		}
 	},
 
+	toJSON: function () {
+
+		var output = {
+			metadata: {
+				version: 4.0,
+				type: 'BufferGeometry',
+				generator: 'BufferGeometryExporter'
+			},
+			uuid: this.uuid,
+			type: this.type,
+			data: {
+				attributes: {}
+			}
+		};
+
+		var attributes = this.attributes;
+		var offsets = this.offsets;
+		var boundingSphere = this.boundingSphere;
+
+		for ( var key in attributes ) {
+
+			var attribute = attributes[ key ];
+
+			var array = [], typeArray = attribute.array;
+
+			for ( var i = 0, l = typeArray.length; i < l; i ++ ) {
+
+				array[ i ] = typeArray[ i ];
+
+			}
+
+			output.data.attributes[ key ] = {
+				itemSize: attribute.itemSize,
+				type: attribute.array.constructor.name,
+				array: array
+			}
+
+		}
+
+		if ( offsets.length > 0 ) {
+
+			output.data.offsets = JSON.parse( JSON.stringify( offsets ) );
+
+		}
+
+		if ( boundingSphere !== null ) {
+
+			output.data.boundingSphere = {
+				center: boundingSphere.center.toArray(),
+				radius: boundingSphere.radius
+			}
+
+		}
+
+		return output;
+
+	},
+
 	clone: function () {
 
 		var geometry = new THREE.BufferGeometry();

+ 201 - 0
src/core/Geometry.js

@@ -732,6 +732,207 @@ THREE.Geometry.prototype = {
 
 	} )(),
 
+	toJSON: function () {
+
+		var output = {
+			metadata: {
+				version: 4.0,
+				type: 'BufferGeometry',
+				generator: 'BufferGeometryExporter'
+			},
+			uuid: this.uuid,
+			type: this.type
+		};
+
+		if ( this.name !== "" ) output.name = this.name;
+
+		if ( this.parameters !== undefined ) {
+
+			var parameters = this.parameters;
+
+			for ( var key in parameters ) {
+
+				if ( parameters[ key ] !== undefined ) output[ key ] = parameters[ key ];
+
+			}
+
+			return output;
+
+		}
+
+		var vertices = [];
+
+		for ( var i = 0; i < this.vertices.length; i ++ ) {
+
+			var vertex = this.vertices[ i ];
+			vertices.push( vertex.x, vertex.y, vertex.z );
+
+		}
+
+		var faces = [];
+		var normals = [];
+		var normalsHash = {};
+		var colors = [];
+		var colorsHash = {};
+		var uvs = [];
+		var uvsHash = {};
+
+		for ( var i = 0; i < this.faces.length; i ++ ) {
+
+			var face = this.faces[ i ];
+
+			var hasMaterial = false; // face.materialIndex !== undefined;
+			var hasFaceUv = false; // deprecated
+			var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
+			var hasFaceNormal = face.normal.length() > 0;
+			var hasFaceVertexNormal = face.vertexNormals.length > 0;
+			var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
+			var hasFaceVertexColor = face.vertexColors.length > 0;
+
+			var faceType = 0;
+
+			faceType = setBit( faceType, 0, 0 );
+			faceType = setBit( faceType, 1, hasMaterial );
+			faceType = setBit( faceType, 2, hasFaceUv );
+			faceType = setBit( faceType, 3, hasFaceVertexUv );
+			faceType = setBit( faceType, 4, hasFaceNormal );
+			faceType = setBit( faceType, 5, hasFaceVertexNormal );
+			faceType = setBit( faceType, 6, hasFaceColor );
+			faceType = setBit( faceType, 7, hasFaceVertexColor );
+
+			faces.push( faceType );
+			faces.push( face.a, face.b, face.c );
+
+
+			/*
+			if ( hasMaterial ) {
+
+				faces.push( face.materialIndex );
+
+			}
+			*/
+
+			if ( hasFaceVertexUv ) {
+
+				var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
+
+				faces.push(
+					getUvIndex( faceVertexUvs[ 0 ] ),
+					getUvIndex( faceVertexUvs[ 1 ] ),
+					getUvIndex( faceVertexUvs[ 2 ] )
+				);
+
+			}
+
+			if ( hasFaceNormal ) {
+
+				faces.push( getNormalIndex( face.normal ) );
+
+			}
+
+			if ( hasFaceVertexNormal ) {
+
+				var vertexNormals = face.vertexNormals;
+
+				faces.push(
+					getNormalIndex( vertexNormals[ 0 ] ),
+					getNormalIndex( vertexNormals[ 1 ] ),
+					getNormalIndex( vertexNormals[ 2 ] )
+				);
+
+			}
+
+			if ( hasFaceColor ) {
+
+				faces.push( getColorIndex( face.color ) );
+
+			}
+
+			if ( hasFaceVertexColor ) {
+
+				var vertexColors = face.vertexColors;
+
+				faces.push(
+					getColorIndex( vertexColors[ 0 ] ),
+					getColorIndex( vertexColors[ 1 ] ),
+					getColorIndex( vertexColors[ 2 ] )
+				);
+
+			}
+
+		}
+
+		function setBit( value, position, enabled ) {
+
+			return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position) );
+
+		}
+
+		function getNormalIndex( normal ) {
+
+			var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
+
+			if ( normalsHash[ hash ] !== undefined ) {
+
+				return normalsHash[ hash ];
+
+			}
+
+			normalsHash[ hash ] = normals.length / 3;
+			normals.push( normal.x, normal.y, normal.z );
+
+			return normalsHash[ hash ];
+
+		}
+
+		function getColorIndex( color ) {
+
+			var hash = color.r.toString() + color.g.toString() + color.b.toString();
+
+			if ( colorsHash[ hash ] !== undefined ) {
+
+				return colorsHash[ hash ];
+
+			}
+
+			colorsHash[ hash ] = colors.length;
+			colors.push( color.getHex() );
+
+			return colorsHash[ hash ];
+
+		}
+
+		function getUvIndex( uv ) {
+
+			var hash = uv.x.toString() + uv.y.toString();
+
+			if ( uvsHash[ hash ] !== undefined ) {
+
+				return uvsHash[ hash ];
+
+			}
+
+			uvsHash[ hash ] = uvs.length / 2;
+			uvs.push( uv.x, uv.y );
+
+			return uvsHash[ hash ];
+
+		}
+
+		output.data = {};
+
+		output.data.vertices = vertices;
+		output.data.normals = normals;
+		if ( colors.length > 0 ) output.data.colors = colors;
+		if ( uvs.length > 0 ) output.data.uvs = [ uvs ]; // temporal backward compatibility
+		output.data.faces = faces;
+
+		//
+
+		return output;
+
+	},
+
 	clone: function () {
 
 		var geometry = new THREE.Geometry();

+ 158 - 0
src/core/Object3D.js

@@ -500,6 +500,164 @@ THREE.Object3D.prototype = {
 
 	},
 
+	toJSON: function () {
+
+		var output = {
+			metadata: {
+				version: 4.3,
+				type: 'Object',
+				generator: 'ObjectExporter'
+			}
+		};
+
+		//
+
+		var geometries = {};
+
+		var parseGeometry = function ( geometry ) {
+
+			if ( output.geometries === undefined ) {
+
+				output.geometries = [];
+
+			}
+
+			if ( geometries[ geometry.uuid ] === undefined ) {
+
+				var json = geometry.toJSON();
+
+				delete json.metadata;
+
+				geometries[ geometry.uuid ] = json;
+
+				output.geometries.push( json );
+
+			}
+
+			return geometry.uuid;
+
+		};
+
+		//
+
+		var materials = {};
+
+		var parseMaterial = function ( material ) {
+
+			if ( output.materials === undefined ) {
+
+				output.materials = [];
+
+			}
+
+			if ( materials[ material.uuid ] === undefined ) {
+
+				var json = material.toJSON();
+
+				delete json.metadata;
+
+				materials[ material.uuid ] = json;
+
+				output.materials.push( json );
+
+			}
+
+			return material.uuid;
+
+		};
+
+		//
+
+		var parseObject = function ( object ) {
+
+			var data = {};
+
+			data.uuid = object.uuid;
+			data.type = object.type;
+
+			if ( object.name !== '' ) data.name = object.name;
+			if ( JSON.stringify( object.userData ) !== '{}' ) data.userData = object.userData;
+			if ( object.visible !== true ) data.visible = object.visible;
+
+			if ( object instanceof THREE.PerspectiveCamera ) {
+
+				data.fov = object.fov;
+				data.aspect = object.aspect;
+				data.near = object.near;
+				data.far = object.far;
+
+			} else if ( object instanceof THREE.OrthographicCamera ) {
+
+				data.left = object.left;
+				data.right = object.right;
+				data.top = object.top;
+				data.bottom = object.bottom;
+				data.near = object.near;
+				data.far = object.far;
+
+			} else if ( object instanceof THREE.AmbientLight ) {
+
+				data.color = object.color.getHex();
+
+			} else if ( object instanceof THREE.DirectionalLight ) {
+
+				data.color = object.color.getHex();
+				data.intensity = object.intensity;
+
+			} else if ( object instanceof THREE.PointLight ) {
+
+				data.color = object.color.getHex();
+				data.intensity = object.intensity;
+				data.distance = object.distance;
+
+			} else if ( object instanceof THREE.SpotLight ) {
+
+				data.color = object.color.getHex();
+				data.intensity = object.intensity;
+				data.distance = object.distance;
+				data.angle = object.angle;
+				data.exponent = object.exponent;
+
+			} else if ( object instanceof THREE.HemisphereLight ) {
+
+				data.color = object.color.getHex();
+				data.groundColor = object.groundColor.getHex();
+
+			} else if ( object instanceof THREE.Mesh ) {
+
+				data.geometry = parseGeometry( object.geometry );
+				data.material = parseMaterial( object.material );
+
+			} else if ( object instanceof THREE.Sprite ) {
+
+				data.material = parseMaterial( object.material );
+
+			}
+
+			data.matrix = object.matrix.toArray();
+
+			if ( object.children.length > 0 ) {
+
+				data.children = [];
+
+				for ( var i = 0; i < object.children.length; i ++ ) {
+
+					data.children.push( parseObject( object.children[ i ] ) );
+
+				}
+
+			}
+
+			return data;
+
+		}
+
+		output.object = parseObject( this );
+
+		return output;
+
+	},
+
 	clone: function ( object, recursive ) {
 
 		if ( object === undefined ) object = new THREE.Object3D();

+ 1 - 0
src/loaders/MaterialLoader.js

@@ -45,6 +45,7 @@ THREE.MaterialLoader.prototype = {
 		if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
 		if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;		
 		if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
+		if ( json.shading !== undefined ) material.shading = json.shading;
 		if ( json.blending !== undefined ) material.blending = json.blending;
 		if ( json.side !== undefined ) material.side = json.side;
 		if ( json.opacity !== undefined ) material.opacity = json.opacity;

+ 72 - 0
src/materials/Material.js

@@ -85,6 +85,78 @@ THREE.Material.prototype = {
 
 	},
 
+	toJSON: function () {
+
+		var output = {
+			metadata: {
+				version: 4.2,
+				type: 'material',
+				generator: 'MaterialExporter'
+			},
+			uuid: this.uuid,
+			type: this.type
+		};
+
+		if ( this.name !== "" ) output.name = this.name;
+
+		if ( this instanceof THREE.MeshBasicMaterial ) {
+
+			output.color = this.color.getHex();
+			if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors;
+			if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending;
+			if ( this.side !== THREE.FrontSide ) output.side = this.side;
+
+		} else if ( this instanceof THREE.MeshLambertMaterial ) {
+
+			output.color = this.color.getHex();
+			output.ambient = this.ambient.getHex();
+			output.emissive = this.emissive.getHex();
+			if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors;
+			if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending;
+			if ( this.side !== THREE.FrontSide ) output.side = this.side;
+
+		} else if ( this instanceof THREE.MeshPhongMaterial ) {
+
+			output.color = this.color.getHex();
+			output.ambient = this.ambient.getHex();
+			output.emissive = this.emissive.getHex();
+			output.specular = this.specular.getHex();
+			output.shininess = this.shininess;
+			if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors;
+			if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending;
+			if ( this.side !== THREE.FrontSide ) output.side = this.side;
+
+		} else if ( this instanceof THREE.MeshNormalMaterial ) {
+
+			if ( this.shading !== THREE.FlatShading ) output.shading = this.shading;
+			if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending;
+			if ( this.side !== THREE.FrontSide ) output.side = this.side;
+
+		} else if ( this instanceof THREE.MeshDepthMaterial ) {
+
+			if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending;
+			if ( this.side !== THREE.FrontSide ) output.side = this.side;
+
+		} else if ( this instanceof THREE.ShaderMaterial ) {
+
+			output.uniforms = this.uniforms;
+			output.vertexShader = this.vertexShader;
+			output.fragmentShader = this.fragmentShader;
+
+		} else if ( this instanceof THREE.SpriteMaterial ) {
+
+			output.color = this.color.getHex();
+
+		}
+
+		if ( this.opacity < 1 ) output.opacity = this.opacity;
+		if ( this.transparent !== false ) output.transparent = this.transparent;
+		if ( this.wireframe !== false ) output.wireframe = this.wireframe;
+
+		return output;
+
+	},
+
 	clone: function ( material ) {
 
 		if ( material === undefined ) material = new THREE.Material();

+ 38 - 6
src/materials/MeshFaceMaterial.js

@@ -4,21 +4,53 @@
 
 THREE.MeshFaceMaterial = function ( materials ) {
 
+	this.uuid = THREE.Math.generateUUID();
+
 	this.type = 'MeshFaceMaterial';
+	
 	this.materials = materials instanceof Array ? materials : [];
 
 };
 
-THREE.MeshFaceMaterial.prototype.clone = function () {
+THREE.MeshFaceMaterial.prototype = {
 
-	var material = new THREE.MeshFaceMaterial();
+	constructor: THREE.MeshFaceMaterial,
 
-	for ( var i = 0; i < this.materials.length; i ++ ) {
+	toJSON: function () {
 
-		material.materials.push( this.materials[ i ].clone() );
+		var output = {
+			metadata: {
+				version: 4.2,
+				type: 'material',
+				generator: 'MaterialExporter'
+			},
+			uuid: this.uuid,
+			type: this.type,
+			materials: []
+		};
 
-	}
+		for ( var i = 0, l = this.materials.length; i < l; i ++ ) {
+
+			output.materials.push( this.materials[ i ].toJSON() );
+
+		}
+
+		return output;
+
+	},
+
+	clone: function () {
 
-	return material;
+		var material = new THREE.MeshFaceMaterial();
+
+		for ( var i = 0; i < this.materials.length; i ++ ) {
+
+			material.materials.push( this.materials[ i ].clone() );
+
+		}
+
+		return material;
+
+	}
 
 };