ThreeJS - 线和球体的交点 [英] ThreeJS - Intersection of a line and sphere

查看:81
本文介绍了ThreeJS - 线和球体的交点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的场景中有两个对象:一条红线和一个球体.

当相机旋转/缩放/移动时,我需要检查以下内容:

  • 从相机的当前位置看,这条线是否与球体相交(请参见下图)?请使用在图像上创建场景的,它检查线和球体的交点并可视化光线以进行调试.>

    JS Fiddle 代码:

     var 相机、控件、场景、渲染器;在里面();动画();使成为();函数初始化(){camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 10000);相机.位置.z = 800;控件 = 新的 THREE.TrackballControls(camera);control.rotateSpeed = 5.0;control.zoomSpeed = 1.2;控制.panSpeed = 4;control.noZoom = false;control.noPan = false;control.staticMoving = true;control.addEventListener('change', render);//世界场景 = 新的 THREE.Scene();SceneTarget = new THREE.Scene();var grid = new THREE.GridHelper(500, 50);场景添加(网格);/*** 创建线*/var lineMaterial = new THREE.LineBasicMaterial({颜色:0xFF0000});var lineGeometry = new THREE.Geometry();lineGeometry.vertices.push(new THREE.Vector3(100, 200, 100));lineGeometry.vertices.push(new THREE.Vector3(300, 200, 200));var line = new THREE.Line(lineGeometry, lineMaterial);sceneTarget.add(line);/** 创造领域*/var sphere = new THREE.Mesh(new THREE.SphereGeometry(150, 100, 100), new THREE.MeshNormalMaterial());sphere.overdraw = true;场景添加(球体);//渲染器渲染器 = 新的 THREE.WebGLRenderer({阿尔法:真实});renderer.setSize(window.innerWidth, window.innerHeight);renderer.autoClear = false;renderer.setClearColor(0xffffff, 1);document.body.appendChild(renderer.domElement);}函数动画(){请求动画帧(动画);控制更新();}函数渲染(){renderer.render(场景,相机);renderer.render(sceneTarget, camera);相交();}函数相交(){var 方向 = new THREE.Vector3(100, 200, 100);var startPoint = camera.position.clone();var directionVector = direction.sub( startPoint );var ray = new THREE.Raycaster(startPoint, directionVector.clone(). normalize());场景.updateMatrixWorld();//必须的,因为你还没有渲染var rayIntersects = ray.intersectObjects(scene.children, true);如果(射线相交[0]){//找到交点console.log(rayIntersects[0]);//可视化光线以进行调试var material = new THREE.LineBasicMaterial({颜色: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(100, 200, 100));var line = new THREE.Line(geometry, material);场景目标.添加(行);}}

    I have two objects on my scene: a red line and a sphere.

    While camera rotating/zooming/moving, I need to check the following:

    • Does the line intersects with the sphere looking from the current position of the camera (please see images below)? Please use this JS fiddle that creates the scene on the images.

    I know how to find the intersection between the current mouse position and objects on the scene (just like this example shows).

    But how to do this in my case?

    JS Fiddle Code:

        /**
         * PREPARE SCENE
         */
        var mouse = {
            x : 0,
            y : 0
        };
    
        var projector = new THREE.Projector();
    
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75,
                window.innerWidth / window.innerHeight, 0.1, 1000);
    
        camera.position.x = -5;
        camera.position.y = 5;
        camera.position.z = 30;
    
        var renderer = new THREE.WebGLRenderer({ alpha: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
    
        var controls = new THREE.TrackballControls(camera,
                renderer.domElement);
    
        controls.rotateSpeed = 3.0;
        controls.zoomSpeed = 1.5;
        controls.panSpeed = 1.0;
    
        controls.staticMoving = true;
    
        var grid = new THREE.GridHelper(20, 5);
        scene.add(grid);
    
        /**
         * CREATE SPHERE
         */
        var sphere = new THREE.Mesh(
                new THREE.SphereGeometry(5, 10, 10),
                new THREE.MeshNormalMaterial());
        sphere.overdraw = true;
        scene.add(sphere);
    
        /**
         * CREATE LINE
         */
        var lineMaterial = new THREE.LineBasicMaterial({
            color : 0xFF0000
        });
        var lineGeometry = new THREE.Geometry();
        lineGeometry.vertices.push(new THREE.Vector3(8, 8, 8));
        lineGeometry.vertices.push(new THREE.Vector3(8, 8, 20));
        var line = new THREE.Line(lineGeometry, lineMaterial);
         scene.add(line);
    
    
        renderer.domElement.addEventListener('mousemove', render, false);
        render();
    
        function render(event) {
    
            var mouse = {};
    
            /*
             * INTERSECTION
             */
            if (event != null) {
                //intersection job???
            }
            controls.update();
            renderer.render(scene, camera);
        }
    

    解决方案

    So, I found the solution that is pretty simple (of course). See new JS Fiddle that checks intersection of the line and sphere and visualizes the ray for debugging.

    The JS Fiddle code:

        var camera, controls, scene, renderer;
    
    init();
    animate();
    render();
    
    function init() {
    
        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.z = 800;
    
        controls = new THREE.TrackballControls(camera);
        controls.rotateSpeed = 5.0;
        controls.zoomSpeed = 1.2;
        controls.panSpeed = 4;
        controls.noZoom = false;
        controls.noPan = false;
        controls.staticMoving = true;
    
        controls.addEventListener('change', render);
    
        // world
    
        scene = new THREE.Scene();
        sceneTarget = new THREE.Scene();
    
        var grid = new THREE.GridHelper(500, 50);
            scene.add(grid);
    
         /**
         * CREATE LINE
         */
        var lineMaterial = new THREE.LineBasicMaterial({
            color : 0xFF0000
        });
        var lineGeometry = new THREE.Geometry();
        lineGeometry.vertices.push(new THREE.Vector3(100, 200, 100));
        lineGeometry.vertices.push(new THREE.Vector3(300, 200, 200));
        var line = new THREE.Line(lineGeometry, lineMaterial);
         sceneTarget.add(line);
    
        /*
        * CREARE SPHERE
        */
        var sphere = new THREE.Mesh(new THREE.SphereGeometry(150, 100, 100), new THREE.MeshNormalMaterial());
      sphere.overdraw = true;
      scene.add(sphere);
    
        // renderer
    
        renderer = new THREE.WebGLRenderer({
            alpha: true 
        });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.autoClear = false;
        renderer.setClearColor(0xffffff, 1);
    
         document.body.appendChild(renderer.domElement);
    }
    
    function animate() {
    
        requestAnimationFrame(animate);
        controls.update();
    
    }
    
    function render() {
    
        renderer.render(scene, camera);
        renderer.render(sceneTarget, camera);
        intersect();
    
    }
    
    function intersect() {
    
        var direction = new THREE.Vector3(100, 200, 100);
    
        var startPoint = camera.position.clone();
    
        var directionVector = direction.sub( startPoint );
    
        var ray = new THREE.Raycaster(startPoint, directionVector.clone(). normalize());
    
        scene.updateMatrixWorld(); // required, since you haven't rendered yet
    
        var rayIntersects = ray.intersectObjects(scene.children, true);
    
        if (rayIntersects[0]) {
            //inersection is found
            console.log(rayIntersects[0]);
    
            //visualize the ray for debugging
            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(100, 200, 100));
            var line = new THREE.Line(geometry, material);
            sceneTarget.add( line );
    
        }
    
    }
    

    这篇关于ThreeJS - 线和球体的交点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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