How to perform a deep clone of a scene?

I have a Scene that I want to copy and then change it without effecting the original Scene.

Object3D copy method is copying by reference.

How can I duplicate to an independent Scene?

Try clone().

Tried it but still the material etc. are referenced to the original object.

1 Like

After you clone the scene, traverse it and clone referenced properties like

myScene.traverse(function(object) {

        if ( object.isMesh ) {

            object.material = object.material.clone();

        }

    });

You need to do it as deep as you require, a cloned material will still share it’s program for example, in case you don’t want this to be referenced either.

3 Likes

@Fyrestar works :muscle:t4:

Thank you!

Here is some code that uses this example clone - I load one .obj, and make a pile of copies of it - setting the position and color of each one

Blockquote

var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath(‘textures/cont1/’);
mtlLoader.load(‘container2.mtl’, function (materials) {
materials.preload();

  //var material = new THREE.MeshFaceMaterial(materials);
  materials.transparency = 0.2;
  materials.transparent = true;
  materials.opacity = 0.6;
  //material.depthWrite = false;
  //
  var objLoader = new THREE.OBJLoader();
  objLoader.setMaterials(materials);
  objLoader.setPath('textures/cont1/');

  objLoader.load('/Container2.obj', function (container) {
  	for (var sc = 0; sc < posns.length; sc++) {
  		var scale = posns[sc].scale;
  		var rotation = posns[sc].rotation;
  		var posn = posns[sc].position;
  		var model3d = new THREE.Object3D();
  		//clone main obj
  		model3d = container.clone();
  		//clone obnj meshes
  		model3d.traverse(function (object) {
  			if (object.isMesh) {
  				object.material = object.material.clone();
  			}
  		});

  		model3d.scale.x = parseFloat(scale.x);
  		model3d.scale.y = parseFloat(scale.y);
  		model3d.scale.z = parseFloat(scale.z);

  		//container.position = new THREE.Vector3(posn.x, posn.y, posn.z);
  		model3d.position.x = posn.x;
  		model3d.position.y = posn.y;
  		model3d.position.z = posn.z;

  		model3d.rotation.x = rotation._x;
  		model3d.rotation.y = rotation._y;
  		model3d.rotation.z = rotation._z;

  		var color = '999933';//default grey
  		if (!posns[sc].color) {
  			var rnd = (Math.random() * 100);
  			if (rnd >90) {
  				console.log('blue');
  				posns[sc].color = '456F87';
  			} else if (rnd > 50) {
  				console.log('red');
  				posns[sc].color = 'C04B0C';//
  			}else if (rnd > 20) {
  				console.log('yellow');
  				posns[sc].color = 'F3CD8B';
  			}else {
  				console.log('grey');
  				posns[sc].color = color;

  			}

  		}
  		model3d.traverse(function (child) {
  			if (child instanceof THREE.Mesh) {
  				//var c = hexToRgb(color);
  				var c = hexToRgb(posns[sc].color);
  				child.material.color = new THREE.Color("rgb(" + c.r + ", " + c.g + ", " + c.b + ")");
  				//child.material.emissive.setHex(0xdaa514);
  				//child.material.opacity = 1 + Math.sin(new Date().getTime() * .0025);
  				child.castShadow = true; //default is false
  				child.receiveShadow = false; //default
  			}
  		});
  		if (!model3d.userData.color) {
  			model3d.userData.color = posns[sc].color;
  		};

  		model3d.name = posns[sc].name;

  		group = new THREE.Group();
  		scene.add(group);

  		var textMaterial = new THREE.MeshBasicMaterial({
  			color: new THREE.Color(1, 1, 1),
  			side: THREE.DoubleSide,
  			wireframe: false
  		});

  		var textShapes = font.generateShapes(model3d.name, .4);

  		var geometry = new THREE.ShapeBufferGeometry(textShapes);
  		geometry.computeBoundingBox();

  		var text = new THREE.Mesh(geometry, textMaterial);

  		text.position.x = posn.x - ((geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2);
  		text.position.y = posn.y + 5;
  		text.position.z = posn.z + 0;

  		group.add(text);
  		group.add(model3d);


  		containers.push(model3d);

  		scene.add(model3d);
  	}

  }, onProgress, onError);

});

Blockquote

Hello. you can throw off all the code? I will be very grateful, thanks.

Should the documentation for Object3D.clone() warn that materials will not be cloned ?

-jg-