Browse Source

Merge pull request #6252 from kumavis/toJSON

toJSON - move class specific code onto class implementations
Mr.doob 10 years ago
parent
commit
645c8f37ce

+ 15 - 0
src/cameras/OrthographicCamera.js

@@ -56,3 +56,18 @@ THREE.OrthographicCamera.prototype.clone = function () {
 
 	return camera;
 };
+
+THREE.OrthographicCamera.prototype.toJSON = function ( meta ) {
+
+	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.left = this.left;
+	data.object.right = this.right;
+	data.object.top = this.top;
+	data.object.bottom = this.bottom;
+	data.object.near = this.near;
+	data.object.far = this.far;
+
+	return data;
+
+};

+ 13 - 0
src/cameras/PerspectiveCamera.js

@@ -140,3 +140,16 @@ THREE.PerspectiveCamera.prototype.clone = function () {
 	return camera;
 
 };
+
+THREE.PerspectiveCamera.prototype.toJSON = function ( meta ) {
+
+	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.fov = this.fov;
+	data.object.aspect = this.aspect;
+	data.object.near = this.near;
+	data.object.far = this.far;
+
+	return data;
+
+};

+ 24 - 19
src/core/BufferGeometry.js

@@ -874,22 +874,27 @@ THREE.BufferGeometry.prototype = {
 		}
 	},
 
-	toJSON: function () {
-
-		var output = {
-			metadata: {
-				version: 4.0,
-				type: 'BufferGeometry',
-				generator: 'BufferGeometryExporter'
-			},
-			uuid: this.uuid,
-			type: this.type,
-			data: {
-				attributes: {}
-			}
-		};
+	toJSON: function() {
 
-		var attributes = this.attributes;
+	  // we will store all serialization data on 'data'
+	  var data = {};
+
+    // add metadata
+    data.metadata = {
+			version: 4.4,
+			type: 'BufferGeometry',
+			generator: 'BufferGeometry.toJSON'
+		}
+
+	  // standard BufferGeometry serialization
+
+	  data.type = this.type;
+	  data.uuid = this.uuid;
+	  if ( this.name !== '' ) data.name = this.name;
+	  data.data = {};
+	  data.data.attributes = {};
+
+	  var attributes = this.attributes;
 		var offsets = this.offsets;
 		var boundingSphere = this.boundingSphere;
 
@@ -899,7 +904,7 @@ THREE.BufferGeometry.prototype = {
 
 			var array = Array.prototype.slice.call( attribute.array );
 
-			output.data.attributes[ key ] = {
+			data.data.attributes[ key ] = {
 				itemSize: attribute.itemSize,
 				type: attribute.array.constructor.name,
 				array: array
@@ -909,20 +914,20 @@ THREE.BufferGeometry.prototype = {
 
 		if ( offsets.length > 0 ) {
 
-			output.data.offsets = JSON.parse( JSON.stringify( offsets ) );
+			data.data.offsets = JSON.parse( JSON.stringify( offsets ) );
 
 		}
 
 		if ( boundingSphere !== null ) {
 
-			output.data.boundingSphere = {
+			data.data.boundingSphere = {
 				center: boundingSphere.center.toArray(),
 				radius: boundingSphere.radius
 			}
 
 		}
 
-		return output;
+	  return data;
 
 	},
 

+ 25 - 23
src/core/Geometry.js

@@ -797,31 +797,35 @@ THREE.Geometry.prototype = {
 
 	},
 
-	toJSON: function () {
-
-		var output = {
-			metadata: {
-				version: 4.0,
-				type: 'BufferGeometry',
-				generator: 'BufferGeometryExporter'
-			},
-			uuid: this.uuid,
-			type: this.type
+	toJSON: function() {
+
+	  // we will store all serialization data on 'data'
+	  var data = {};
+
+    // add metadata
+    data.metadata = {
+			version: 4.4,
+			type: 'Geometry',
+			generator: 'Geometry.toJSON'
 		};
 
-		if ( this.name !== "" ) output.name = this.name;
+	  // standard Geometry serialization
 
-		if ( this.parameters !== undefined ) {
+	  data.type = this.type;
+	  data.uuid = this.uuid;
+	  if ( this.name !== '' ) data.name = this.name;
+
+	  if ( this.parameters !== undefined ) {
 
 			var parameters = this.parameters;
 
 			for ( var key in parameters ) {
 
-				if ( parameters[ key ] !== undefined ) output[ key ] = parameters[ key ];
+				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
 
 			}
 
-			return output;
+			return data;
 
 		}
 
@@ -984,17 +988,15 @@ THREE.Geometry.prototype = {
 
 		}
 
-		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;
+		data.data = {};
 
-		//
+		data.data.vertices = vertices;
+		data.data.normals = normals;
+		if ( colors.length > 0 ) data.data.colors = colors;
+		if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
+		data.data.faces = faces;
 
-		return output;
+	  return data;
 
 	},
 

+ 58 - 134
src/core/Object3D.js

@@ -567,165 +567,89 @@ THREE.Object3D.prototype = {
 
 	},
 
-	toJSON: function () {
+	toJSON: function( meta ) {
 
-		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 = [];
-
-			}
+		var isRootObject = ( meta === undefined );
 
-			if ( materials[ material.uuid ] === undefined ) {
+	  // we will store all serialization data on 'data'
+	  var data = {};
+	  var metadata;
 
-				var json = material.toJSON();
+	  // meta is a hash used to collect geometries, materials.
+	  // not providing it implies that this is the root object
+	  // being serialized.
+	  if ( isRootObject ) {
 
-				delete json.metadata;
-
-				materials[ material.uuid ] = json;
-
-				output.materials.push( json );
+	    // initialize meta obj
+	    meta = {
+	      geometries: {},
+	      materials: {}
+	    }
 
+	    // add metadata
+	    metadata = {
+				version: 4.4,
+				type: 'Object',
+				generator: 'Object3D.toJSON'
 			}
 
-			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;
+	  // standard Object3D serialization
 
-			} else if ( object instanceof THREE.AmbientLight ) {
+	  data.type = this.type;
+	  data.uuid = this.uuid;
+	  if ( this.name !== '' ) data.name = this.name;
+	  if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
+	  if ( this.visible !== true ) data.visible = this.visible;
 
-				data.color = object.color.getHex();
+	  data.matrix = this.matrix.toArray();
 
-			} else if ( object instanceof THREE.DirectionalLight ) {
+	  if ( this.children.length > 0 ) {
 
-				data.color = object.color.getHex();
-				data.intensity = object.intensity;
+	    data.children = [];
 
-			} else if ( object instanceof THREE.PointLight ) {
+	    for ( var i = 0; i < this.children.length; i ++ ) {
 
-				data.color = object.color.getHex();
-				data.intensity = object.intensity;
-				data.distance = object.distance;
-				data.decay = object.decay;
+	      data.children.push( this.children[ i ].toJSON( meta ).object );
 
-			} 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;
-				data.decay = object.decay;
+	  }
 
-			} else if ( object instanceof THREE.HemisphereLight ) {
+	  // wrap serialized object with additional data
 
-				data.color = object.color.getHex();
-				data.groundColor = object.groundColor.getHex();
+	  var output;
 
-			} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) {
+	  if ( isRootObject ) {
 
-				data.geometry = parseGeometry( object.geometry );
-				data.material = parseMaterial( object.material );
+	  	output = {
+	  		metadata: metadata,
+	  		geometries: extractFromCache(meta.geometries),
+	  		materials: extractFromCache(meta.materials),
+	  		object: data
+	  	};
 
-				if ( object instanceof THREE.Line ) data.mode = object.mode;
+	  } else {
 
-			} else if ( object instanceof THREE.Sprite ) {
+	  	output = { object: data };
 
-				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;
 
-		return output;
+	  // extract data from the cache hash
+	  // remove metadata on each item
+	  // and return as array
+	  function extractFromCache ( cache ) {
+	  	var values = [];
+	  	for ( var key in cache ) {
+	  		var data = cache[ key ];
+	  		delete data.metadata;
+	  		values.push( data );
+	  	}
+	  	return values;
+	  }
 
 	},
 

+ 10 - 0
src/lights/AmbientLight.js

@@ -22,3 +22,13 @@ THREE.AmbientLight.prototype.clone = function () {
 	return light;
 
 };
+
+THREE.AmbientLight.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+  data.object.color = this.color.getHex();
+
+  return data;
+
+};

+ 11 - 0
src/lights/DirectionalLight.js

@@ -111,3 +111,14 @@ THREE.DirectionalLight.prototype.clone = function () {
 	return light;
 
 };
+
+THREE.DirectionalLight.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+  data.object.color = this.color.getHex();
+	data.object.intensity = this.intensity;
+
+  return data;
+
+};

+ 11 - 0
src/lights/HemisphereLight.js

@@ -30,3 +30,14 @@ THREE.HemisphereLight.prototype.clone = function () {
 	return light;
 
 };
+
+THREE.HemisphereLight.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.color = this.color.getHex();
+	data.object.groundColor = this.groundColor.getHex();
+
+  return data;
+
+};

+ 13 - 0
src/lights/PointLight.js

@@ -30,3 +30,16 @@ THREE.PointLight.prototype.clone = function () {
 	return light;
 
 };
+
+THREE.PointLight.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.color = this.color.getHex();
+	data.object.intensity = this.intensity;
+	data.object.distance = this.distance;
+	data.object.decay = this.decay;
+
+  return data;
+
+};

+ 15 - 0
src/lights/SpotLight.js

@@ -80,3 +80,18 @@ THREE.SpotLight.prototype.clone = function () {
 	return light;
 
 };
+
+THREE.SpotLight.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.color = this.color.getHex();
+	data.object.intensity = this.intensity;
+	data.object.distance = this.distance;
+	data.object.angle = this.angle;
+	data.object.exponent = this.exponent;
+	data.object.decay = this.decay;
+
+  return data;
+
+};

+ 17 - 72
src/materials/Material.js

@@ -107,83 +107,28 @@ THREE.Material.prototype = {
 
 	},
 
-	toJSON: function () {
+	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.emissive = this.emissive.getHex();
-			if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors;
-			if ( this.shading !== THREE.SmoothShading ) 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.MeshPhongMaterial ) {
-
-			output.color = this.color.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.shading !== THREE.SmoothShading ) 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.MeshNormalMaterial ) {
-
-			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.PointCloudMaterial ) {
-
-			output.size  = this.size;
-			output.sizeAttenuation = this.sizeAttenuation;
-			output.color = this.color.getHex();
-
-			if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors;
-			if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending;
-
-		} 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();
+	  // we will store all serialization data on 'data'
+	  var data = {};
 
+    // add metadata
+    data.metadata = {
+			version: 4.4,
+			type: 'Material',
+			generator: 'Material.toJSON'
 		}
 
-		if ( this.opacity < 1 ) output.opacity = this.opacity;
-		if ( this.transparent !== false ) output.transparent = this.transparent;
-		if ( this.wireframe !== false ) output.wireframe = this.wireframe;
+	  // standard Material serialization
+	  data.type = this.type;
+	  data.uuid = this.uuid;
+	  if ( this.name !== '' ) data.name = this.name;
+
+	  if ( this.opacity < 1 ) data.opacity = this.opacity;
+		if ( this.transparent !== false ) data.transparent = this.transparent;
+		if ( this.wireframe !== false ) data.wireframe = this.wireframe;
 
-		return output;
+	  return data;
 
 	},
 

+ 13 - 0
src/materials/MeshBasicMaterial.js

@@ -115,3 +115,16 @@ THREE.MeshBasicMaterial.prototype.clone = function () {
 	return material;
 
 };
+
+THREE.MeshBasicMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+	data.color = this.color.getHex();
+  if ( this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
+  if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
+  if ( this.side !== THREE.FrontSide ) data.side = this.side;
+
+	return data;
+
+};

+ 11 - 0
src/materials/MeshDepthMaterial.js

@@ -43,3 +43,14 @@ THREE.MeshDepthMaterial.prototype.clone = function () {
 	return material;
 
 };
+
+THREE.MeshDepthMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+  if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
+  if ( this.side !== THREE.FrontSide ) data.side = this.side;
+
+	return data;
+
+};

+ 6 - 13
src/materials/MeshFaceMaterial.js

@@ -7,7 +7,7 @@ THREE.MeshFaceMaterial = function ( materials ) {
 	this.uuid = THREE.Math.generateUUID();
 
 	this.type = 'MeshFaceMaterial';
-	
+
 	this.materials = materials instanceof Array ? materials : [];
 
 };
@@ -18,24 +18,17 @@ THREE.MeshFaceMaterial.prototype = {
 
 	toJSON: function () {
 
-		var output = {
-			metadata: {
-				version: 4.2,
-				type: 'material',
-				generator: 'MaterialExporter'
-			},
-			uuid: this.uuid,
-			type: this.type,
-			materials: []
-		};
+		var data = THREE.Material.prototype.toJSON.call( this );
+
+		data.materials = [];
 
 		for ( var i = 0, l = this.materials.length; i < l; i ++ ) {
 
-			output.materials.push( this.materials[ i ].toJSON() );
+			data.materials.push( this.materials[ i ].toJSON() );
 
 		}
 
-		return output;
+		return data;
 
 	},
 

+ 15 - 0
src/materials/MeshLambertMaterial.js

@@ -128,3 +128,18 @@ THREE.MeshLambertMaterial.prototype.clone = function () {
 	return material;
 
 };
+
+THREE.MeshLambertMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+	data.color = this.color.getHex();
+  data.emissive = this.emissive.getHex();
+  if ( this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
+  if ( this.shading !== THREE.SmoothShading ) data.shading = this.shading;
+  if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
+  if ( this.side !== THREE.FrontSide ) data.side = this.side;
+
+	return data;
+
+};

+ 11 - 0
src/materials/MeshNormalMaterial.js

@@ -44,3 +44,14 @@ THREE.MeshNormalMaterial.prototype.clone = function () {
 	return material;
 
 };
+
+THREE.MeshPhongMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+  if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
+  if ( this.side !== THREE.FrontSide ) data.side = this.side;
+
+	return data;
+
+};

+ 18 - 0
src/materials/MeshPhongMaterial.js

@@ -168,3 +168,21 @@ THREE.MeshPhongMaterial.prototype.clone = function () {
 	return material;
 
 };
+
+THREE.MeshPhongMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+	data.color = this.color.getHex();
+  data.emissive = this.emissive.getHex();
+  data.specular = this.specular.getHex();
+  data.shininess = this.shininess;
+
+  if ( this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
+  if ( this.shading !== THREE.SmoothShading ) data.shading = this.shading;
+  if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
+  if ( this.side !== THREE.FrontSide ) data.side = this.side;
+
+	return data;
+
+};

+ 15 - 0
src/materials/PointCloudMaterial.js

@@ -65,6 +65,21 @@ THREE.PointCloudMaterial.prototype.clone = function () {
 
 };
 
+THREE.MeshDepthMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+  data.size  = this.size;
+  data.sizeAttenuation = this.sizeAttenuation;
+  data.color = this.color.getHex();
+
+  if ( this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
+  if ( this.blending !== THREE.NormalBlending ) data.blending = this.blending;
+
+	return data;
+
+};
+
 // backwards compatibility
 
 THREE.ParticleBasicMaterial = function ( parameters ) {

+ 12 - 0
src/materials/ShaderMaterial.js

@@ -109,3 +109,15 @@ THREE.ShaderMaterial.prototype.clone = function () {
 	return material;
 
 };
+
+THREE.ShaderMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+  data.uniforms = this.uniforms;
+  data.vertexShader = this.vertexShader;
+  data.fragmentShader = this.fragmentShader;
+
+	return data;
+
+};

+ 10 - 0
src/materials/SpriteMaterial.js

@@ -55,3 +55,13 @@ THREE.SpriteMaterial.prototype.clone = function () {
 	return material;
 
 };
+
+THREE.SpriteMaterial.prototype.toJSON = function () {
+
+	var data = THREE.Material.prototype.toJSON.call( this );
+
+  data.color = this.color.getHex();
+
+	return data;
+
+};

+ 23 - 0
src/objects/Line.js

@@ -191,3 +191,26 @@ THREE.Line.prototype.clone = function ( object ) {
 	return object;
 
 };
+
+THREE.Line.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.mode = this.mode;
+
+	// only serialize if not in meta geometries cache
+	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
+		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON();
+	}
+
+	// only serialize if not in meta materials cache
+	if ( meta.materials[ this.material.uuid ] === undefined ) {
+		meta.materials[ this.material.uuid ] = this.material.toJSON();
+	}
+
+	data.object.geometry = this.geometry.uuid;
+	data.object.material = this.material.uuid;
+
+  return data;
+
+};

+ 22 - 1
src/objects/Mesh.js

@@ -10,7 +10,7 @@ THREE.Mesh = function ( geometry, material ) {
 	THREE.Object3D.call( this );
 
 	this.type = 'Mesh';
-	
+
 	this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
 	this.material = material !== undefined ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } );
 
@@ -323,3 +323,24 @@ THREE.Mesh.prototype.clone = function ( object, recursive ) {
 	return object;
 
 };
+
+THREE.Mesh.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	// only serialize if not in meta geometries cache
+	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
+		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON();
+	}
+
+	// only serialize if not in meta materials cache
+	if ( meta.materials[ this.material.uuid ] === undefined ) {
+		meta.materials[ this.material.uuid ] = this.material.toJSON();
+	}
+
+	data.object.geometry = this.geometry.uuid;
+	data.object.material = this.material.uuid;
+
+  return data;
+
+};

+ 21 - 0
src/objects/PointCloud.js

@@ -153,6 +153,27 @@ THREE.PointCloud.prototype.clone = function ( object ) {
 
 };
 
+THREE.PointCloud.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	// only serialize if not in meta geometries cache
+	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
+		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON();
+	}
+
+	// only serialize if not in meta materials cache
+	if ( meta.materials[ this.material.uuid ] === undefined ) {
+		meta.materials[ this.material.uuid ] = this.material.toJSON();
+	}
+
+	data.object.geometry = this.geometry.uuid;
+	data.object.material = this.material.uuid;
+
+  return data;
+
+};
+
 // Backwards compatibility
 
 THREE.ParticleSystem = function ( geometry, material ) {

+ 15 - 0
src/objects/Sprite.js

@@ -69,6 +69,21 @@ THREE.Sprite.prototype.clone = function ( object ) {
 
 };
 
+THREE.Sprite.prototype.toJSON = function ( meta ) {
+
+  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	// only serialize if not in meta materials cache
+	if ( meta.materials[ this.material.uuid ] === undefined ) {
+		meta.materials[ this.material.uuid ] = this.material.toJSON();
+	}
+
+	data.object.material = this.material.uuid;
+
+  return data;
+
+};
+
 // Backwards compatibility
 
 THREE.Particle = THREE.Sprite;