从场景中拾取几何体并将几何体及其线框一起移除

时间:2015-04-11 00:23:22

标签: three.js

我想在线框中添加和删除几何体。我可以使用raycaster从场景中拾取对象,但很难选择线框。

我能想到的一种方法是创建一组对象及其线框,当raycaster与对象相交时(例如obj.geometry.type ==" BoxGeometry"),找到它的父对象并删除父母。但是,线框必须是一些可以作为子项添加的几何体。我正在使用Boxhelper为立方体创建线框,应该直接添加到场景中,而不是作为子项添加到任何对象。解决这个问题的好方法是什么?

感谢。

2 个答案:

答案 0 :(得分:2)

我不确定我是否完全理解你的内容,但也许你可以创建一个对象的克隆,并将其渲染为线框。然后可以将克隆线框对象作为子项添加到原始对象。因此,当拾取原始对象时,您可以将其从场景中移除,然后线框对象也将被移除。

克隆您的对象并将其材质更改为线框:

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

当拾取对象时:检查它是否是立方体几何(如果你只想让它与立方体一起使用)并检查它的材质是否是线框(如果你不想在不移除立方体的情况下移除线框)

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

工作示例:



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();
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

还有一种方法可以使用Three.EdgesHelper而不是克隆来执行您需要的操作,如this小提琴中所示。这显示没有对角线的线框。

即使您不想使用Three.EdgesHelper,我也注意到在实施上面的克隆解决方案时,它没有完全显示线框,因为它稍微隐藏了。

为了避免这种隐藏,我将以下代码添加到material的构造函数中,这会稍微抵消原始形状,以便可以完全看到线框:

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

我希望这在某种程度上有用。