以相机为原点的 Three.js Raycasting [英] Three.js Raycasting with Camera as Origin

查看:42
本文介绍了以相机为原点的 Three.js Raycasting的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试确定空间中的某个点是对相机可见还是隐藏在场景中的其他对象后面.我这样做是通过从相机的位置向空间中的那个点投射光线并测试该光线是否与一组可相交的对象相交.

I'm trying to determine whether a point in space is visible to the camera or hidden behind other objects in the scene. I'm doing this by casting a ray from the position of the camera to that point in space and testing if that ray is intersected by an set of intersectable objects.

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

My problem is no intersections occur until the camera position itself intersects one of the objects in the set of intersectable objects.

我创建了一个 jsfiddle,如果检测到交叉点,则会从相机位置到我正在测试可见性的空间位置绘制一条线.目前我相信,这条线只在相机位置与一组可相交对象相交的特定点处绘制.

I've created a jsfiddle in which, if an intersection is detected, a line is drawn from the camera position to the position in space i'm testing for visibility. Currently I believe, the line is only draw at specific points where the camera position intersects the set of intersectable objects.

如何让相交点按原样注册,而不必让相机位置与可相交对象集中的对象相交?

How do I get the intersections to be registered as they should be, without having to have the camera position intersect objects in the set of intersectable objects?

代码:

    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);

    }

谢谢

推荐答案

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

For anyone currently seeing this thread, THREE.Projector has been replaced.

Three.js THREE.Projector 已移至

下面的代码处理 3D 矢量.如果您转到上面的链接,第一个评论者提供了二维向量的代码.

The code below handles a 3D vector. If you go to the link above, the first commenter provided the code for a 2D vector.

var vector = new THREE.Vector3();
var raycaster = new THREE.Raycaster();
var dir = new THREE.Vector3();

...

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 );`

这篇关于以相机为原点的 Three.js Raycasting的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆