Intersecting a line with a sphere in ThreeJS

I am working with a scene that includes a red line and a sphere.

As the camera rotates, zooms, or moves, I need to check if the line intersects with the sphere from the current camera position (refer to the images below). To visualize this scenario, please refer to this JS fiddle.

I already know how to find intersections between the mouse position and objects in the scene, as demonstrated in this example.

However, I am unsure of how to approach this specific case. Can anyone provide guidance on how to achieve this?

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

Answer №1

After much searching, I stumbled upon a surprisingly simple solution. Take a look at the new JS Fiddle that examines the intersection of a line and sphere while providing a visual representation of the ray for easy debugging.

The code in the JS Fiddle:

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

    /*
    * CREATE 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 );

    }

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

We're facing some technical difficulties with the form for the school project. Furthermore, I need to ensure that the answers are

Upon inspection, it seems that the HTML code is fine, but there appears to be an issue with the JavaScript. I also need to store the answers in an array, which is a task for later. <form> <fieldset> <legend>Content:</lege ...

Tips for broadcasting a router event

Currently, I am working with 2 modules - one being the sidenav module where I can select menus and the other is the content module which contains a router-outlet. I am looking for the best way to display components in the content module based on menu selec ...

Executing multiple promise.all functions simultaneously

I have a large volume of 400 requests to a server, each encapsulated within a promise. However, when I attempt to run all 400 requests simultaneously using Promise.all, the system crashes. To address this issue, I decided to split the requests into batche ...

Learn the simple trick to switch to full screen by just clicking

import { Component, OnInit, ElementRef } from '@angular/core'; declare var JQuery : any; @Component({ selector: 'app-presentation', templateUrl: './presentation.component.html', styleUrls: ['./presentation.c ...

Check if a rotated rectangle lies within the circular boundary of the canvas

I have a rectangular shape that has been rotated using the ctx.rotate method, and there is also an arc on the canvas. My goal is to determine if any part of the rectangle lies within the boundaries of the arc. See the example below: https://i.sstatic.net/ ...

Using the _id String in a GraphQL query to retrieve information based on the Object ID stored in a

Encountering an issue with my graphql query not returning anything when sending the _id as a string. Interestingly, querying the DB using any other stored key (like name: "Account 1") works perfectly and returns the object. I've defined my Account sch ...

What is the best way to add a simple Search bar to the Material UI Data Grid component?

If we take a look at this data grid example: check it out here I'd like to incorporate a simple search bar similar to the one shown here Can someone provide guidance on how to add this feature to Data Grid MUI? ...

Organizing a Javascript project for development and production with the help of npm and grunt

I have been working on structuring the JavaScript files in my project. I opted to use NPM for managing modules and Grunt for concatenating and compressing js and css files for deployment purposes. Here is the current structure I am using: -[project root ...

Updating the jQuery $ function to accommodate outdated codebases

After using stackoverflow as a valuable resource for years, I decided to join. I have a good grasp on JavaScript and noticed some questions that I could provide input on. As I delved into the platform, I realized the prevalence of jQuery. This prompted me ...

Bringing in d3js into Angular 2

Is there a way to successfully import d3js into an Angular2 project? I have already installed d3js using npm and added it to my systemJs, but am encountering a traceur.js error. I also attempted to just use the latest cdn in a script tag and tried import * ...

The CSS Bootstrap 4 class 'input-group-append' is not functioning properly. Just recently, the styles were displaying correctly

My web application using AngularJS 1.7.8, jQuery 3.3.1, Bootstrap 4.3.1, and various other CSS and JS libraries worked seamlessly last week. However, today I noticed an issue with the button visualization. To Replicate: Visit openskymap.org to see my d ...

Ways to effectively test a custom hook event using Enzyme and Jest: A guide on testing the useKeyPress hook

Looking for guidance on testing a custom hook event called useKeyPress with Enzyme and Jest This is my current custom hook for capturing keyboard events and updating keyPress value: import React, { useEffect, useState } from 'react' const useKe ...

What is the best way to switch from http to https in a React application?

When performing audits in Chrome, I encountered a net::ERR_EMPTY_RESPONSE error because Lighthouse was not able to consistently load the requested page. Google developers have recommended configuring my server (possibly node.js) to redirect from http to ht ...

Is it possible to use AJAX to change the class name of a Font Awesome icon?

I am considering updating the icon after deleting a row. Should I initially include the font awesome icon once in the blade, then remove the class name and add it back with ajax? blade: <div id="status-{{ $country->id }}"> <div id ...

Using AngularJS date picker to set value in Spring model setter

When using AngularJS with Spring, I noticed a discrepancy in the date values between my view file and the POJO User object. In my view file, I have used an input type date to bind the "user.dateOfBirth" attribute. When I select a date, it is displayed cor ...

Setting the `setCustomValidity()` method for dynamically inserted HTML elements Explanation on how to use

I am dynamically adding elements to my view and setting their attributes using the jQuery attr function as demonstrated in the code snippet below: var input = $("<input type='text' name='"+inputFieldName+"' '>"); input.attr( ...

Effective ways to fill a Map<string, string> with input data

Check out this Stackblitz Here is the model I am working with: export class Items { items: Map<string, string>; createdBy: string; deliveredBy: string; } I am trying to dynamically generate input fields based on items in an array, but struggl ...

What is the method for renaming Props in Vue components?

I recently embarked on my VueJS journey and attempted to implement v-model in a component, following an example I found. <template> <div class="date-picker"> Month: <input type="number" ref="monthPicker" :value="value.month" @in ...

Check for my variable in the redux state before proceeding

Currently, I am creating connection and registration screens, with a profile button on the bottom tab bar. The objective is for the user to be directed to their profile page if they are logged in (user data stored in Redux), or to a landing screen with log ...

Bringing in JavaScript files from a Bootstrap theme to incorporate them into a Vue3 application

Incorporating Bootstrap 5, a HTML theme with a CSS bundle file, and separate JS bundle files (main JS bundle file and plugin bundle file) containing Bootstrap code base + custom template features into a Vue 3 project is my current objective. I aim to utili ...