2

对于我的项目,我需要在 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/

单击时,被射线击中的每个元素都应变为蓝色,并且所有击中都会在控制台中注册。请注意球体的(恕我直言)奇怪的控制台输出。另外,为什么下球体没有被击中而上球体被击中?

您可以通过注释/取消注释行在 Cubes 和 Spheres 之间切换19/20

谁能帮我?我没有得到什么?

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

4

3 回答 3

0

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

于 2013-06-04T16:38:05.473 回答
0

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

您的场景正在颠倒渲染,因为您对正交相机的 args 不正确。

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

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

material.side属性告诉Raycaster您将脸部的哪一侧视为“正面”。

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

三.js r.58

于 2013-06-03T15:10:58.260 回答
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 的一个改进之处。

于 2013-06-04T11:13:16.370 回答