【问题标题】:ThreeJS - how to pick just one type of objects?ThreeJS - 如何只选择一种类型的对象?
【发布时间】:2015-04-24 21:36:10
【问题描述】:

我是 ThreeJS 的新手,在通过光线投射选择对象时遇到问题。我已经创建了一些球体和一些线,但只想在鼠标悬停时更改球体。我想我需要在光线投射代码中添加一些条件,但我不知道是什么......

这是我的代码,希望有人能提供帮助:

这会创建对象:

var numSpheres = 10;
var angRand = [numSpheres];
var spread = 10;
var radius = windowY/5;
var radiusControl = 20;

//sphere
var sphereGeometry = new THREE.SphereGeometry(0.35, 100, 100);

//line
var lineGeometry = new THREE.Geometry();
var lineMaterial = new THREE.LineBasicMaterial({
    color: 0xCCCCCC
});

//create dynamically
for (var i = 0; i < numSpheres; i++) {

    var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x334455});
    var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

    var line = new THREE.Line(lineGeometry, lineMaterial);

    angRand[i] = Math.floor((Math.random() * 360) + 1);//random angle for each sphere/line
    var radiusIncr = spread * (angRand[i]+200)/180;
    var xPos = Math.cos((360/numSpheres * (i) + angRand[i]/2 )) * (radius - radiusIncr);
    var yPos = Math.sin((360/numSpheres * (i) + angRand[i]/2 )) * (radius - radiusIncr);
    var offsetY = Math.floor((Math.random()*5)+1);

    sphere.position.x = xPos/radiusControl;
    sphere.position.y = yPos/radiusControl + offsetY; 

    lineGeometry.vertices.push(
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3(sphere.position.x, sphere.position.y, 0)
    );

    scene.add(sphere);
    scene.add(line);
}

这是我的光线投射:

var mouse = {
        x: 0,
        y: 0
    },
    INTERSECTED;

window.addEventListener('mousemove', onMouseMove, false);
window.requestAnimationFrame(render);

function onMouseMove(event) {
    // calculate mouse position in normalized device coordinates 
    // (-1 to +1) for both components 
    //event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    //console.log(mouse.x + " | " + mouse.y);
}

function mousePos() {
    // find intersections

    // create a Ray with origin at the mouse position
    //   and direction into the scene (camera direction)
    var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
    vector.unproject(camera);

    var ray = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
    ray.linePrecision = 1;

    // create an array containing all objects in the scene with which the ray intersects
    var intersects = ray.intersectObjects(scene.children, true);

    //console.log(intersects.length);

    // INTERSECTED = the object in the scene currently closest to the camera 
    //      and intersected by the Ray projected from the mouse position    

    // if there is one (or more) intersections
    if (intersects.length > 0) {
        // if the closest object intersected is not the currently stored intersection object
        if (intersects[0].object != INTERSECTED) {
            // restore previous intersection object (if it exists) to its original color
            if (INTERSECTED)
                INTERSECTED.material.color.setHex(INTERSECTED.currentHex);

            // store reference to closest object as current intersection object
            INTERSECTED = intersects[0].object;
            // store color of closest object (for later restoration)
            INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
            // set a new color for closest object
            INTERSECTED.material.color.setHex(0xEE7F00);
            //INTERSECTED.radius.set( 1, 2, 2 );
        }
    } else // there are no intersections
    {
        // restore previous intersection object (if it exists) to its original color
        if (INTERSECTED)
            INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
        //INTERSECTED.scale.set( 1, 1, 1 );
        // remove previous intersection object reference
        //     by setting current intersection object to "nothing"
        INTERSECTED = null;
    }
}

【问题讨论】:

标签: three.js onmouseover raycasting


【解决方案1】:

光线投射返回一个相交对象数组,该数组本身包含有关光线命中对象的信息。

由于您只有球体和线,您可以在几何类型 intersects[0].object.geometry.type 上进行分支,这将是 'LineGeometry''SphereGeometry'

编辑: 必需的 jsfiddle,请参阅控制台以获取命中输出。 http://jsfiddle.net/z43hjqm9/1/

【讨论】:

  • 这个的正确语法是什么? intersects[0].object.SphereGeometry?
  • 找到了这个:var intersects = ray.intersectObjects([sphere]);,但不知道如何扩展我的以下代码,使其适用于所有领域..​​(来源:josdirksen github
  • 几何的类型属性是一个字符串,因此您可以检查您点击的几何类型,如switch(intersects[0].object.geometry.type){ case 'LineGeometry': doSomething();break; case 'SphereGeometry'; doSomethingElse(); break; default:break:}
【解决方案2】:

为了简化鼠标操作,您可以使用 EventsControls 类。尝试通过这个example

<script src="js/controls/EventsControls.js"></script>

EventsControls = new EventsControls( camera, renderer.domElement );

EventsControls.attachEvent('mouseOver', function() {

    this.container.style.cursor = 'pointer';
    this.mouseOvered.material = selMaterial;
    ... 

});

EventsControls.attachEvent('mouseOut', function() {

    this.container.style.cursor = 'auto';
    this.mouseOvered.material = autoMaterial;
    ...

});

    //

    function render() {
           EventsControls.update();
           controls.update();
           renderer.render(scene, camera);
    }

【讨论】:

    【解决方案3】:

    在您的代码中,

    var intersects = ray.intersectObjects(scene.children, true);
    

    调用的第一个参数是一个对象,它将被评估以查看它或其任何后代(递归为真)是否与射线相交。

    因此,只需创建一个对象目标并将球体添加到其中(但不添加线条)。

    这将使您的通话更加有效

    【讨论】:

      【解决方案4】:

      1.使用不同的数组放置不同的对象
      a.对于所有objectType1,在scene.add(objectType1)->之后做array1.push(objectType1)
      b.对于所有objectType 2,在scene.add(objectType2)->做array2.push(objectType2)之后

      现在,无论您要交互哪种类型的对象,都以 intersect 的形式传递该数组-
      var intersects = raycaster.intersectObjects( arrayType1,true);

      现在只有 arrayType1 对象会交互。

      【讨论】:

        猜你喜欢
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 2013-12-08
        • 1970-01-01
        • 2020-09-18
        • 2019-05-27
        • 1970-01-01
        • 2012-01-10
        相关资源
        最近更新 更多