从场景中拾取几何体并将几何体及其线框一起移除
pick geometry from the scene and remove geometry and its wireframe together
我想添加和删除一个几何图形及其线框。我可以使用 raycaster 从场景中选取 object,但很难选取线框。
我能想到的一种方法是创建一组 object 及其线框,当光线投射器与 object 相交时(例如 obj.geometry.type == "BoxGeometry" ), 找到它的 parent 并删除 parent。但是,线框必须是一些可以添加为 child 的几何体。我正在使用 Boxhelper 为立方体创建线框,它应该直接添加到场景中,而不是作为 child 添加到任何 object。什么是解决这个问题的好方法?
谢谢。
我不确定我是否理解您的确切意图,但也许您可以创建对象的克隆,并将其渲染为线框。然后可以将克隆线框对象作为子对象添加到原始对象。所以当原始物体被拾取时,您可以将其从场景中移除,然后线框物体也会被移除。
克隆您的对象并将其 material 更改为线框:
var wireframe = cube.clone();
wireframe.material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
cube.add( wireframe ); // adding wireframe as child to the cube
拾取对象时:检查它是否是立方体几何体(如果您只希望它与立方体一起使用)并检查其 material 是否是线框(如果您不想删除线框也没有移除立方体)
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();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
还有一种方法可以使用 Three.EdgesHelper
而不是克隆来完成您需要的操作,如 this fiddle 中所示。这显示了没有对角线的线框。
即使您不想使用 Three.EdgesHelper
,我注意到在实施上面的克隆解决方案时,它并没有完全显示线框,因为它被稍微隐藏了。
为了避免这种隐藏,我在 material
的构造函数中添加了以下代码,它稍微偏移了原始形状,以便可以完全看到线框:
var material = new THREE.MeshLambertMaterial({ polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 1 })
我希望这在某种程度上有用。
我想添加和删除一个几何图形及其线框。我可以使用 raycaster 从场景中选取 object,但很难选取线框。
我能想到的一种方法是创建一组 object 及其线框,当光线投射器与 object 相交时(例如 obj.geometry.type == "BoxGeometry" ), 找到它的 parent 并删除 parent。但是,线框必须是一些可以添加为 child 的几何体。我正在使用 Boxhelper 为立方体创建线框,它应该直接添加到场景中,而不是作为 child 添加到任何 object。什么是解决这个问题的好方法?
谢谢。
我不确定我是否理解您的确切意图,但也许您可以创建对象的克隆,并将其渲染为线框。然后可以将克隆线框对象作为子对象添加到原始对象。所以当原始物体被拾取时,您可以将其从场景中移除,然后线框物体也会被移除。
克隆您的对象并将其 material 更改为线框:
var wireframe = cube.clone();
wireframe.material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
cube.add( wireframe ); // adding wireframe as child to the cube
拾取对象时:检查它是否是立方体几何体(如果您只希望它与立方体一起使用)并检查其 material 是否是线框(如果您不想删除线框也没有移除立方体)
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();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
还有一种方法可以使用 Three.EdgesHelper
而不是克隆来完成您需要的操作,如 this fiddle 中所示。这显示了没有对角线的线框。
即使您不想使用 Three.EdgesHelper
,我注意到在实施上面的克隆解决方案时,它并没有完全显示线框,因为它被稍微隐藏了。
为了避免这种隐藏,我在 material
的构造函数中添加了以下代码,它稍微偏移了原始形状,以便可以完全看到线框:
var material = new THREE.MeshLambertMaterial({ polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 1 })
我希望这在某种程度上有用。