Juna
Juna

Reputation: 338

ThreeJS - Intersection of a line and sphere

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

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

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?

does not intersect

intersect

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

Upvotes: 3

Views: 3911

Answers (1)

Juna
Juna

Reputation: 338

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.

enter image description here

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

    }

}

Upvotes: 1

Related Questions