用THREE.Raycaster对球体进行三次碰撞检测

时间:2013-06-03 14:01:27

标签: three.js webgl raycasting

对于我的项目,我需要在Three.js中进行碰撞测试。在我的CollisionDetection课程中,我试图让Raycaster工作。而且我发现了一些我无法解释但又无法解决的奇怪现象:

我的CollisionDetector适用于Cubes ..但是当我使用Spheres时,它并没有给我相同的结果 - 我错误地期望与立方体相同的结果?或者我会错过其他什么?

这是我的代码:

var renderer, camera, scene;

init();
animate();

function init() {
    var container = document.getElementById("scene");
    var width = window.innerWidth;
    var height = window.innerHeight;        

    renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height); 
    camera = new THREE.OrthographicCamera( 0, width, 0, height, 1, 10000 );
    camera.position.z = 300;
    scene = new THREE.Scene();
    scene.add(camera);
    container.appendChild(renderer.domElement);

    var geometry =  new THREE.SphereGeometry(10,16, 16);
    //var geometry =  new THREE.CubeGeometry( 10, 10, 10 );

    var material1 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
    var material2 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
    var material3 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
    var material4 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
    var material5 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );

    var element1 = new THREE.Mesh( geometry, material1 );
    var element2 = new THREE.Mesh( geometry, material2 );
    var element3 = new THREE.Mesh( geometry, material3 );
    var element4 = new THREE.Mesh( geometry, material4 );
    var element5 = new THREE.Mesh( geometry, material5 );

    element1.position.set(200,200,0);
    element2.position.set(200,100,0);
    element3.position.set(200,300,0);
    element4.position.set(100,200,0);
    element5.position.set(300,200,0);

    scene.add(element1);
    scene.add(element2);
    scene.add(element3);
    scene.add(element4);
    scene.add(element5);

    var CollisionDetector = new CollisionDetection();   
    CollisionDetector.addRay(new THREE.Vector3(0, -1, 0));
    CollisionDetector.addRay(new THREE.Vector3(0, 1, 0));
    CollisionDetector.addRay(new THREE.Vector3(1, 0, 0));
    CollisionDetector.addRay(new THREE.Vector3(-1, 0, 0));

    CollisionDetector.addElement(element1);
    CollisionDetector.addElement(element2);
    CollisionDetector.addElement(element3);
    CollisionDetector.addElement(element4);
    CollisionDetector.addElement(element5);

   document.onclick = function(){
        CollisionDetector.testElement(element1);
    };
}

function CollisionDetection(){
    var caster = new THREE.Raycaster();
    var rays = [];
    var elements = [];

    this.testElement = function(element){
        for(var i=0; i<rays.length; i++) {
            caster.set(element.position, rays[i]);
            var hits = caster.intersectObjects(elements, true);
            for(var k=0; k<hits.length; k++) {
                console.log("hit", hits[k]);
                hits[k].object.material.color.setHex(0x0000ff);
            }
        }
    } 
    this.addRay = function(ray) {
        rays.push(ray.normalize());
    }
    this.addElement = function(element){
        elements.push(element);
    }
}
function animate() {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
}

或者最好,亲眼看看它的行为:http://jsfiddle.net/mymL5/12/

开启单击光线所击中的每个元素都应变为蓝色,并且所有命中都会在控制台中注册。 注意球体的(imho)奇怪的控制台输出。 另外,为什么较低的球体没有击中,而鞋帮是?

您可以通过评论/取消注释第19/20页

在多维数据集和球体之间切换

任何人都可以帮助我吗?我没得到什么?

PS:我是Three.js的新手,所以我可能很蠢。

3 个答案:

答案 0 :(得分:0)

由于这是与家庭作业相关的,我只会提供一些提示。

您的场景呈现颠倒,因为您的正交相机的参数不正确。

你的球体比你的立方体大。

你的光线正好击中你球体的北极和南极。这些要点有什么不同?

material.side属性告诉Raycaster脸部的哪一侧要考虑“前方”。

您的fidde示例正在运行three.js的旧版本(r.54)。

three.js r.58

答案 1 :(得分:0)

增加球体大小。 通过一些非平凡的角度旋转球体(因此它们不会在N / S极点上被击中)。 现在它有效吗? :P

var geometry =  new THREE.SphereGeometry(20,17, 17);

element1.position.set(0,0,0);
element2.position.set(0,100,0);
element3.position.set(100,0,0);
element4.position.set(0,-100,0);
element5.position.set(-100,0,0);

element1.rotation.set(0,0,10);
element2.rotation.set(0,0,10);
element3.rotation.set(0,0,10);
element4.rotation.set(0,0,10);
element5.rotation.set(0,0,10);

然而,射线测试应该知道击中三角形的精确顶点或边缘,因此可以将其视为Three.js的改进位置。

答案 2 :(得分:0)

我在Three.js存储库中提交了一个相关问题: https://github.com/mrdoob/three.js/issues/3541