draupnie
draupnie

Reputation: 1130

pick geometry from the scene and remove geometry and its wireframe together

I want to add and remove a geometry with its wireframe together. I can use raycaster to pick object from the scene but it is hard to pick a wireframe.

One way I can think of is creating a group of object and its wireframe, when the raycaster intersect with the object (e.g. obj.geometry.type == "BoxGeometry"), find its parent and delete the parent. However, the wireframe has to be some geometry that can be added as a child. I am using a Boxhelper to create a wireframe for a cube, which should be added to the scene directly, not to be added as a child to any object. What is a good way to solve this?

Thanks.

Upvotes: 1

Views: 1403

Answers (2)

Hugo Nava Kopp
Hugo Nava Kopp

Reputation: 3064

There is also a way of doing what you require with the Three.EdgesHelper instead of cloning, as exemplified in this fiddle. This shows the wireframes without the diagonals.

Even if you don't want to use the Three.EdgesHelper, I noticed that while implementing the clone solution above, it didn't completely show the wireframe, because it was slightly hidden.

To avoid this hiding I added the following code to the constructor of material, which offsets the original shape slightly so that the wireframe can be completely seen:

var material = new THREE.MeshLambertMaterial({ polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 1 })

I hope this is somehow useful.

Upvotes: 1

micnil
micnil

Reputation: 4805

I am not sure if i understand what you are after exactly, but maybe ou can create a clone of your object, and render that one as a wireframe. The clone wireframe object can then be added as a child to the original object. So when the original object is picked, you can remove it from the scene, and then the wireframe object will be removed aswell.

Clone your object and change its material to wireframe:

var wireframe = cube.clone();
wireframe.material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
cube.add( wireframe ); // adding wireframe as child to the cube

When object is picked: check whether it is a cubegeometry (if you only want it to work with cubes) and check whether its material is wireframe (if you dont want to be able to remove the wireframe without removing the cube aswell)

if (pickedObject.geometry.type == "BoxGeometry" && 
   !pickedObject.material["wireframe"]){
  pickedObject.parent.remove(pickedObject); //this will remove object from
                                            // scene if it has no parents
}

Working example:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );

var wireframe = cube.clone();
wireframe.material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
    
cube.add( wireframe );

//picking stuff
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

function onMouseClick( event ) {

	// calculate mouse position in normalized device coordinates
	// (-1 to +1) for both components

	mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
	mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;		
  
  // update the picking ray with the camera and mouse position	
	raycaster.setFromCamera( mouse, camera );	

	// calculate objects intersecting the picking ray
	var intersects = raycaster.intersectObjects( scene.children );

	for ( var i = 0; i < intersects.length; i++ ) {

    if (intersects[ i ].object.geometry.type == "BoxGeometry" && 
       !intersects[ i ].object.material["wireframe"]){
			intersects[ i ].object.parent.remove(intersects[ i ].object);
		}
	}

}

camera.position.z = 5;

var render = function () {
  requestAnimationFrame( render );

  cube.rotation.x += 0.1;
  cube.rotation.y += 0.1;

  renderer.render(scene, camera);
};
window.addEventListener( 'mouseup', onMouseClick, false );
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>

Upvotes: 2

Related Questions