Utilizing the Three JS raycaster to detect intersections as the mouse cursor moves around

I have a strong intuition that the current method I am using is completely off base because I am struggling to achieve optimal performance for my website.

Take a look at the primary code snippet:

onDocumentMouseMove( event ) {
    if ( this.isUserInteracting === true ) {
      this.lon = ( this.onMouseDownMouseX - event.clientX ) * 0.1 + this.onMouseDownLon;
      this.lat = ( event.clientY - this.onMouseDownMouseY ) * 0.1 + this.onMouseDownLat;
    }
    this.mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    this.mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

    if( !this.state.VR ){
      this.raycaster.setFromCamera( this.mouse, this.camera );
      var intersects = this.raycaster.intersectObjects( this.indicatorHotspotPlane );

      if( intersects.length > 0 ) {
        this.actualIntersect = intersects[0];

        $('html,body').css('cursor', 'pointer');
        if(!intersects[ 0 ].object.isAction){
          this.marker.material.opacity = 1;
          this.marker.lookAt( intersects[ 0 ].face.normal );
          this.marker.position.copy( intersects[ 0 ].point );
          this.marker.position.y = this.marker.position.y + 30;
          if( intersects[ 0 ].point.x >= 0 ){
            this.marker.position.x = this.marker.position.x - 30;
          }else{
            this.marker.position.x = this.marker.position.x + 30;
          } 
        }
      } else {
        this.actualIntersect = null;
        $('html,body').css('cursor', 'move');
        this.marker.material.opacity = 0;
      }
    }
  }

I am under the impression that running raycaster.intersectObjects is a computationally intensive task within this event handler.

When I remove this specific code snippet, everything operates smoothly.

Is there an alternative method for detecting intersections while the mouse is in motion without encountering performance issues?

In my code, this.indicatorHotspotPlane is an array containing around 5 objects similar to this:

var hotspotPlane = new THREE.Mesh( new THREE.PlaneBufferGeometry( hotpot.width , hotpot.height ) );

Furthermore, my scene is comprised of these objects along with a sphere geometry featuring a textured surface.

Answer №1

Check out this cool demonstration using three.js.

Here's what's happening in this interactive example:

  1. The scene is displayed on an off-screen render target with a unique color for each shape.
  2. The mouse position is compared to the render target coordinates to determine the color under the cursor.
  3. The color is matched to a map of color->mesh.
  4. The corresponding mesh is updated to show it's "highlighted" state.
  5. The main scene is re-rendered with the highlighted part.

Although this method is more straightforward than raycasting, there are still some drawbacks. Each time the render target needs to be refreshed, an extra render is required. Additionally, for large scenes, the performance may be similar to raycasting. However, reading a color value from a buffer is generally easier than performing a raycast.

It's important to note that this approach only works for the nearest shape (similar to intersects[0]). Occluded shapes will not have their colors exposed, making raycasting a better option for identifying all shapes under the cursor.

Additional Details:

Before diving into solving the raytracing issue, I missed a part of your code. Upon further examination:

It seems you are checking for a specific property of the intersected object:

if(!intersects[ 0 ].object.isAction){

By using the method described above, you can check for that property on the object retrieved from your color map.

To obtain the intersection point, a raycast is still necessary, but it will only be triggered if the object passes your test first, instead of with every mouse movement.

The raycast will occur for each mouse movement over a relevant object, so you might want to adjust how often the marker is updated (e.g., every N frames), or set the marker only the first time a specific shape is encountered. Depending on your use case, this may or may not be feasible.

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

How to access global variables in node.js modules?

I'm looking to move some functionality to a new file called helpers.js. Below is the code that I have put in this file. How can I access the app variable within my method so that I can retrieve the config element called Path? Helpers = { fs: requ ...

When attempting to log API results in Next.js, a TypeError occurs because the property is undefined

I'm encountering a rather unusual error. In my Next.js app, I am attempting to console log the results of an API call to see what data I receive. The API function is responsible for verifying if a user is logged in, and if they are, I render a specifi ...

Delay the occurrence of a hover effect until the previous effect has finished executing

As I hover over an element, the desired animation is displayed while hiding other elements on the page. The challenge I'm encountering is that if I quickly hover over many divs, the animations queue up and hide the divs sequentially. I want only one ...

Error: The `ngMetadataName` property cannot be accessed because it is undefined or null in Internet Explorer version 10

Encountered an issue in IE 10 that is not present in IE 11: Error: TypeError: Unable to get property 'ngMetadataName' of undefined or null reference The property ngMetadataName can be found in the file vendor.js. This is the content of polyf ...

Thumbnail image preview fails to display after preloading an image in dropzonejs

Currently, I have a form where users can input their name and upload an image (logo). The client side language being used is AngularJS with dropzonejs as the image upload library. When the user clicks on the 'Edit' button, I want them to see a pr ...

Unable to add the div using a jQuery click event

Hey there, I'm looking to add a div dynamically when clicking on another div. Check out the code snippet below: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8> <title></title> <script src= ...

How to verify for an empty array within a condition in JavaScript

I can't figure out why my conditional statement to handle the edge case of an empty input array is not working as expected. When I test it with my current example, it returns NaN (no clue why). However, if I change the conditional to if (array.length ...

What is the best way to save request URLs in JavaScript while following the DRY principle?

Is there a standard practice in JavaScript for storing the URLs of endpoints used in AJAX applications? Would you, for instance, consider creating a "Service" class to encapsulate the URLs? ...

Using jQuery to emphasize search text in a user-friendly manner

After successfully implementing a search function for a table, I faced the challenge of highlighting the search keyword within a cell. Despite searching for a solution online, I couldn't find anything useful! Here is my HTML code: <table class="s ...

AngularJS Module Instantiation Error

My angularjs module is not loading correctly and I'm struggling to figure out why. Despite reading numerous tutorials, I can't seem to get it to work. [17:22:36.338] Error: [$injector:modulerr] Failed to instantiate module wc2013mongoMod due t ...

Why is this basic HTML code not functioning as expected?

I attempted to combine HTML and JS to change the color of a box upon clicking it, but after reviewing the code multiple times, I am unable to pinpoint the issue. <!doctype html> <html> <head> </head> <body> <d ...

Ways to verify the authenticity of a JWT token

I recently came across a tutorial on creating user authentication with Vue.js and Lumen. The tutorial utilizes the tymon/jwt-auth library to handle authentication. So far, everything is working smoothly. The API manages all my data and provides a token to ...

Testing a Vue component that includes a Vuetify data table with customized slots

I have been struggling to write a Jest test for a simple component that includes a nested v-data-table component. While the page renders correctly in the browser, my test keeps failing. The problem seems to lie with the template I am using for the slot - ...

Creating space between flex items in Slick Carousel with Vue

This is my current Slick Carousel. There are 4 items in a row, and I am looking to insert some margin between each item while maintaining the existing aspect-ratio: 1.3/1; I'm struggling with overriding the classes from vue-slick-carousel. Does any ...

Problem with input field borders in Firefox when displayed within table cells

Demo When clicking on any cell in the table within the JSFiddle using Firefox, you may notice that the bottom and right borders are hidden. Is there a clever solution to overcome this issue? I have experimented with a few approaches but none of them work ...

What could be causing the repetitive output in an Angular click event loop?

I am facing an issue while trying to log the data of the user based on the user tab that has been clicked. The problem is that it always displays the same data and not the data of other users. https://i.sstatic.net/ACo7y.png For example, when I click on ...

Combining Images and Navigation in Next.js using Tailwind CSS

I am facing an issue where the image from a particular section overlaps with the Navbar dropdown on mobile devices. Adding z-50 to the navbar did not solve the problem as expected. What I want is for the image to remain below the dropdown menu when it is ...

Transforming Javascript code using regular expressions into C#

Currently, I am facing a challenge while trying to translate some Javascript code into .NET. Despite my efforts, I have not been able to get it right. The task at hand involves converting paths like /test/:value1/:value2 in Express for NodeJS to a regular ...

Unable to populate an array with a JSON object using Angular framework

Here is the JSON object I have: Object { JP: "JAPAN", PAK: "PAKISTAN", IND: "INDIA", AUS: "AUSTRALIA" } This JSON data was retrieved as a response from an HTTP GET request using HttpClient in Angular. Now, I want to populate this data into the following ...

Having trouble getting the Random Function to function correctly in Discord.js

I'm working on a piece of code that generates a random value to select two different values from two separate arrays. Every time I run it, however, the result seems to be the same and not truly random. I'm not sure where I went wrong with this. I ...