The functionality of mouse hover in multimaterial three.js appears to be not functioning

I'm facing an issue where I want to create a mouse hover effect on an object with multiple materials.

See an example here

function update()
{
    // Finding intersections

    // Creating a Ray with the origin at the mouse position
    //   and direction into the scene (camera direction)
    var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
    projector.unprojectVector( vector, camera );
    var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );

    // Creating an array containing all objects in the scene that intersect with the ray
    var intersects = ray.intersectObjects( scene.children );

    // INTERSECTED = the object in the scene currently closest to the camera 
    //      and intersected by the Ray projected from the mouse position    

    // If there are one or more intersections
    if ( intersects.length > 0 )
    {
        // If the closest object intersected is not the current intersection object
        if ( intersects[0].object != INTERSECTED ) 
        {
            // Restoring the previous intersection object color (if it exists) to its original color
            if ( INTERSECTED ) 
                INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
            // Storing reference to the closest object as the current intersection object
            INTERSECTED = intersects[0].object;
            // Storing the color of the closest object for later restoration
            INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
            // Setting a new color for the closest object
            INTERSECTED.material.color.setHex( 0xffff00 );
        }
    } 
    else // If there are no intersections
    {
        // Restoring the previous intersection object color (if it exists) to its original color
        if ( INTERSECTED ) 
            INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
        // Removing the reference to the previous intersection object by setting it to null
        INTERSECTED = null;
    }

    if ( keyboard.pressed("z") ) 
    { 
        // Do something
    }

    controls.update();
}

The code doesn't seem to work as intended. It always shows "Uncaught TypeError: Cannot read property 'setHex' of undefined"

I've made changes to the intersection code, but it's still not working:

function update()
{

    // Finding intersections

    // Creating a Ray with the origin at the mouse position and direction into the scene (camera direction)
    var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );

    projector.unprojectVector( vector, Camera );
    var ray = new THREE.Raycaster( Camera.position, vector.sub( Camera.position ).normalize() );

    // Creating an array containing all objects in the scene that intersect with the ray
    var intersects = ray.intersectObjects( Scene.children );

    // INTERSECTED = The object in the scene currently closest to the camera and intersected by the Ray projected from the mouse position

    // If there are one or more intersections (objects found with the mouse)
    if ( intersects.length > 0 )
    {
        // If the first object found is different from the previously found object
        if (intersects[0].object != INTERSECTED)
        {
            // Restoring the previous color of the object to the original color
            if (INTERSECTED)
            {
                INTERSECTED.material = INTERSECTED.currentHex;
            }
            // Storing reference to the closest object as current intersection object
            INTERSECTED = intersects[0].object;

            // Storing the color of the closest object for later restoration
            for(var p = 0; p < INTERSECTED.material.materials.length; p++)
            {
                INTERSECTED.currentHex = INTERSECTED.material.materials[p].emissive.getHex();
            }
        }
    }
    else // If there are no intersections
    {
        // Restoring the previous color of the object (if it exists) to its original color
        if ( INTERSECTED )
        {
            INTERSECTED.material = INTERSECTED.currentHex;
        }
        // Removing the reference to the previous intersection object by setting it to null
        INTERSECTED = null;
    }
    controls.update();
}

All objects appear black. The objects are loaded here:

function displayFloor()
{
    // Loading the school model. The first parameter is the model's URL and the second is the function to execute after loading it. In this case, I'm using an anonymous function.

    loader.load("models/computerScienceGroundFloor/GroundFloorWithoutRoom.js", function (geometry, materials)
        {
            let material = new THREE.MultiMaterial(materials);
            let object = new THREE.Mesh(geometry, material);
            object.name = "pavilion";
            Scene.add(object);
        }
    );

    loader.load("models/computerScienceGroundFloor/GroundFloorRoom.js", function (geometry, materials)
        {
            let material = new THREE.MultiMaterial(materials);
            let object = new THREE.Mesh(geometry, material);
            object.name = "room";
            Scene.add(object);
        }
    );
}

You can view the complete code here: https://github.com/kathyer/Mousehover. Any suggestions on what I can do to fix this? Thank you!

Answer №1

Give this a try and view the console to observe how it operates. Best of luck to everyone!


  /**
   * Function triggered on mouse move event.
   * @param event
   */
  onMouseMove(event) {
    event.preventDefault();
    this.mouse.x = (event.offsetX / this.w) * 2 - 1;
    this.mouse.y = -(event.offsetY / this.h) * 2 + 1;

    // this.checkIntersection('hover');
  }

  /**
   * Determine if an intersection has occurred.
   */
  checkIntersection (operation?) {

    // Set up the raycaster.
    this.raycaster.setFromCamera(this.mouse, this.camera);

    // console.log(this.cubeChilds);

    const intersects = this.raycaster.intersectObjects(this.scene.children);
    console.log(intersects);

    if (operation === 'hover') {

    }

    // Change the material of the intersected element.
    this.highlightIntersection (intersects);
  }

  highlightIntersection (intersects) {

    console.log('highlightIntersection initiated: ');

    const new_material = new THREE.MeshBasicMaterial({
      color: 0xff0000,
    });

    const new_green_material = new THREE.MeshBasicMaterial({
      color: 0x00ff40,
    });


    // Check if there is an intersected object
    if ( intersects.length > 0 ) {

      if ( this.INTERSECTED !== intersects[ 0 ].object ) {

        // Set the previous mesh material if available
        if ( this.INTERSECTED ) {
          this.INTERSECTED.material = this.intersected_last_mat;
          console.log('--1--');
        }


        this.INTERSECTED = intersects[ 0 ].object;
        this.intersected_last_mat = this.INTERSECTED.material;
        intersects[ 0 ].object.material = new_green_material;

        console.log(this.INTERSECTED);
        console.log('--2--');
      }
    } else {

      if ( this.INTERSECTED ) {
        this.INTERSECTED.material = this.intersected_last_mat;
        console.log('--3--');
      }
      this.INTERSECTED = null;
      console.log('--4--');

    }

    console.log('--5--');

    this.render();

  }

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

Challenges with exporting dynamically generated divs using jspdf in an Angular 2 project

I have been utilizing the jspdf library to print div elements in my current project. But I recently discovered an issue where dynamic content within a div is not being printed correctly. Specifically, when incorporating simple Angular if statements, jspdf ...

Is there a way to dynamically set the active panel of a JQuery Accordion when making a call?

Currently, I am faced with a scenario where I need to implement a greybox popup window using jQuery Accordion from the main page via links. I am curious to know if it is doable to specify a default active panel for the accordion when calling it. Below is ...

Find the time matching in a time string using Javascript

I need to extract the time in the format "HH:MM:SS" from a string like "HH:MM:SS CEST". How can I achieve this without including any additional strings such as CEST? ...

The text is not displaying as expected due to a timeout issue

Trying to create a pop-up that functions as follows: After 3 seconds, the close button should appear, but during those 3 seconds, there will be a countdown. However, I'm encountering an issue where no text is being displayed. var n = 3; function p ...

JavaScript - Issue encountered while reaching the bottom of the webpage

While conducting tests using Firebug/Firefox, I am trying to execute a simple command that will scroll the page to the bottom. Here is the command: window.scrollBy(0,3000); Seems straightforward, right? When testing on certain websites like Yahoo.com ...

Breadcrumb navigation that is determined by data hierarchies and relationships between parent and child items

I am looking to implement a dynamic breadcrumb system on my website using data-driven methodology. The necessary data is stored in a MariaDB database and has the following structure: parent_id | parent_name | child_id | child_name ——————— ...

Is there a way to utilize a parameter for the user's input instead of relying on document.getElementById when incorporating a button?

let totalScore = 0; var myArray = [1, 2, 3, 4, 5]; let randomNum; function NumGuess(userInput) { var userGuess = userInput; var i; for (i = 0; i < 1; i++) { var randomNum = myArray[Math.floor(Math.random() * myArray.length)]; } if (us ...

Is it possible for an object hidden in the DOM using jQuery to magically reappear when you click the back button or use the bfc

Is there a way to prevent a box from reappearing when using the back button on a webpage? On my website, there is a box that shows up on the first visit. However, when navigating using the back buttons on the site or the browser back button, the box appea ...

Passing an ID in Next.js without showing it in the URL

I am looking to transfer the product id from the category page to the product page without showing it in the URL Category.js <h2> <Link href={{ pathname: `/product/car/${title}`, query: { id: Item.id, }, }} as={`/p ...

When the user clicks on the page, show the data fetched from MySQL and echoed in

I am facing an issue with a table containing a loan_id. When fetching the information, everything appears to be in order. However, I need to be able to click on the loan_id number and have it display results based on the corresponding id number. <?php ...

Ordering request parameters in OAuth2 URL with npm passport can be achieved by following a specific method

I have successfully utilized Oauth2 strategies like Github and Twitter to log in to a web application using npm passport. Now, I am interested in logging in using the new global id authentication. You can explore it here ; it's really amazing. Whil ...

Sharing data with external domains and retrieving HTML output using JavaScript

When a browser sends a POST request and expects an HTML page result from JavaScript, problems arise if there is no Access-Control-Allow-Origin in the server response. Unfortunately, changing anything on the server side is not an option. If a human clicks ...

What are some methods for creating a more affordable sphere in aframe/three js?

In my VR application, I am currently using the aframe <a-sphere> element to render spheres, but it is creating a large number of triangles in my scene, causing a drastic drop in performance with frame rates down to the teens. Is there a more effici ...

Submitting an HTML form to trigger a PHP function through AJAX

I am currently working on a task that involves POSTing an email address entered in an HTML form to a PHP script for storage in a database. The script should also handle error messages if the user inputs an invalid email address. I want to make this process ...

Having trouble getting ngAnimate to work properly?

I am facing an issue with ngAnimate dependency injection. For some reason, whenever I add ngAnimate as a dependency in my JavaScript code, it does not seem to work. It's definitely not the script... Here is the HTML code snippet: <!doctype html& ...

Can a static text be displayed randomly using Javascript?

What I'm searching for is a unique text display feature that's different from scrolling. I envision a subtle fade in/out effect, but it's not necessary. The main goal is to fit within a small area on a website with limited vertical space - ...

What is the most effective way to show an error message within the login form itself?

I'm currently dealing with a dilemma involving my login.php and login_process.php files. The login form is in the former, while the validation process occurs in the latter. I'm struggling to figure out how to display error messages on the login f ...

Angular.js Issue: Repeating elements must be unique - Index tracking not functioning properly

I have been following a tutorial on the Ionic Framework, which utilizes Angular JS to develop a basic Todo application. The app adds a new task by utilizing the .push() method to append a new task object to an array of task objects. An issue arises when a ...

Steps for inserting an additional header in an Angular table

https://i.stack.imgur.com/6JI4p.png I am looking to insert an additional column above the existing ones with a colspan of 4, and it needs to remain fixed like a header column. Here is the code snippet: <div class="example-container mat-elevation-z8"> ...

Transforming an array in JavaScript into a JSON object

I'm currently working on creating a loop in JavaScript or jQuery to generate a new JSON object from an array. The goal is to convert an input JavaScript array into a desired format for the output. Here's the input array: INPUT: [ { ...