Three.js 以相机为原点的光线投射

use*_*022 2 three.js raycasting

我试图确定空间中的某个点是否对相机可见或隐藏在场景中其他对象后面。我通过从相机位置向空间中的该点投射光线并测试该光线是否与一组可相交的对象相交来实现此目的。

我的问题是,在相机位置本身与可相交对象集中的一个对象相交之前,不会发生相交。

我创建了一个 jsfiddle,其中如果检测到交叉点,则会从相机位置到我正在测试可见性的空间位置绘制一条线。目前我认为,该线仅在相机位置与可相交对象集相交的特定点处绘制。

如何让相交按应有的方式进行注册,而不必使相机位置与可相交对象集中的对象相交?

代码:

    var container;
    var camera, controls, scene, renderer;

    init();
    animate();

    function init() {

        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.z = 1000;

        controls = new THREE.OrbitControls(camera);

        controls.rotateSpeed = 1.0;
        controls.zoomSpeed = 1.2;
        controls.panSpeed = 0.8;

        controls.noZoom = false;
        controls.noPan = false;

        controls.staticMoving = true;
        controls.dynamicDampingFactor = 0.3;

        controls.keys = [65, 83, 68];

        controls.addEventListener('change', render);

        // world

        scene = new THREE.Scene();

        var testObject_G = new THREE.CubeGeometry(100, 100, 5);
        var testObject_M = new THREE.MeshBasicMaterial({
            color: 0xBBBBBB
        });
        var testObject_Mesh = new THREE.Mesh(testObject_G, testObject_M);
        testObject_Mesh.position.x = -150;
        scene.add(testObject_Mesh);
        var testObject_Mesh2 = new THREE.Mesh(testObject_G, testObject_M);
        testObject_Mesh2.position.x = 0;
        scene.add(testObject_Mesh2);
        var testObject_Mesh3 = new THREE.Mesh(testObject_G, testObject_M);
        testObject_Mesh3.position.x = 150;
        scene.add(testObject_Mesh3);


        scene2 = new THREE.Object3D();

        // renderer

        renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0xffffff, 1);
        container = document.getElementById('container');
        container.appendChild(renderer.domElement);



        //

        window.addEventListener('resize', onWindowResize, false);

    }

    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth, window.innerHeight);

        controls.handleResize();

        render();

    }

    function animate() {

        requestAnimationFrame(animate);
        controls.update();

    }

    function render() {

        renderer.render(scene, camera);
        castRays();

    }

    function castRays() {

        // rays

        var direction = new THREE.Vector3(0, 200, -200);

        var startPoint = camera.position.clone();

        var ray = new THREE.Raycaster(startPoint, direction);

        scene.updateMatrixWorld(); // required, since you haven't rendered yet

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

        if (rayIntersects[0]) {
            console.log(rayIntersects[0]);

            var material = new THREE.LineBasicMaterial({
              color: 0x0000ff
            });
            var geometry = new THREE.Geometry();
            geometry.vertices.push(new THREE.Vector3(ray.ray.origin.x, ray.ray.origin.y, ray.ray.origin.z));
            geometry.vertices.push(new THREE.Vector3(ray.ray.direction.x, ray.ray.direction.y, ray.ray.direction.z));
            var line = new THREE.Line(geometry, material);
            scene2.add( line );

        }

        scene.add(scene2);

    }
Run Code Online (Sandbox Code Playgroud)

谢谢

小智 5

对于当前看到此线程的任何人,THREE.Projector 已被替换。

Three.js THREE.Projector 已移至

下面的代码处理 3D 矢量。如果您访问上面的链接,第一个评论者提供了 2D 矢量的代码。

var vector = new THREE.Vector3();
var raycaster = new THREE.Raycaster();
var dir = new THREE.Vector3();
Run Code Online (Sandbox Code Playgroud)

...

if ( camera instanceof THREE.OrthographicCamera ) {

    vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, - 1 ); // z = - 1 important!

    vector.unproject( camera );

    dir.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );

    raycaster.set( vector, dir );

} else if ( camera instanceof THREE.PerspectiveCamera ) {

   vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); // z = 0.5 important!

   vector.unproject( camera );

   raycaster.set( camera.position, vector.sub( camera.position ).normalize());

}

var intersects = raycaster.intersectObjects( objects, recursiveFlag );`
Run Code Online (Sandbox Code Playgroud)