Raycasting in three.js - mouse pointer and highlighting not precisely aligned with intersected mesh

My current setup involves using a raycaster to highlight a row of cubes arranged in a grid format. The highlighting works fine, but I'm encountering issues with the cursor turning into a pointer precisely over the cubes in the row. Moreover, the highlight does not occur when I move the mouse over the cubes on the right side. It only activates when I hover over the left side of the grid or even outside it. Each individual cube is actually a group of 9 small cubes, and the recursive flag is set to true so that it identifies the 9 cubes individually as intersected meshes. This allows me to highlight other cubes in the same row. The cursor also changes to a pointer in the area where the highlight works, specifically the left part of the grid. Is there a way to ensure that the highlight and cursor work when hovering over any mesh in the row rather than just outside the grid?

var cubesList = new THREE.Group();

function createScene () {

var cubeSize = 2;



for ( var i = 0; i < noOfEntries; i++ ) {
    var entry = entries[ i ];

    var entryObjects = entry.objects;

    var entryCubesGroup = new THREE.Group();

    var noOfObjects = entry.objects.length;
    for ( var j = 0; j < noOfObjects; j++ ) {
        var object = entryObjects[ j ];


        var cube = createCube( cubeSize ); //THREE.Object3d group of 9 cubes

        entryCubesGroup.add( cube );
        if ( j === Math.round( noOfObjects / 4 ) - 1 && i === Math.round( noOfEntries / 4 ) - 1 ) {
            cameraTarget = cube;

        }

    }


    cubesList.add( entryCubesGroup );
}

scene.add( cubesList );

camera.position.x = 15;
camera.position.y = 15;
camera.position.z = 15;
camera.lookAt( new THREE.Vector3( cameraTarget.position.x, cameraTarget.position.y, cameraTarget.position.z ) );



var light = new THREE.PointLight( 0xffffff, 1, 0 );
light.position.set( 15, 15, 5 );
light.castShadow = true;
scene.add( light );

}

function animate () {

renderer.render( scene, camera );
update();

}

function onDocumentMouseMove ( event ) {

event.preventDefault();

mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = -( event.clientY / renderer.domElement.height ) * 2 + 1;



animate();

}

function update() {

            var vector = new THREE.Vector3(mouse.x, mouse.y, 1);
            vector.unproject(camera);
            var ray = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());

            var intersects = ray.intersectObjects(eventCubesList.children, true);

            if (intersects.length > 0) {

                  $('html,body').css('cursor', 'pointer');
                if (intersects[0].object != INTERSECTED) {                       

                    if (highlightedRow)
                        unhighlightRow(highlightedRow);

                    INTERSECTED = intersects[0].object;
                    var timestamp = INTERSECTED.userData;

                    var selectedRow = getSelectedRow(timestamp);
                    highlightedRow = selectedRow;
                    highlightRow(selectedRow);

                }
                else {
                    if (INTERSECTED) {
                        if (highlightedRow) {
                            var timestamp = INTERSECTED.userData;
                            var row = getSelectedRow(timestamp);
                            unhighlightRow(row);
                        }
                        highlightedRow = null;

                    }


                    INTERSECTED = null;
                }



            }
            else
            {
                    $('html,body').css('cursor', 'default');
            }
                
        }

             function unhighlightRow(cubes) {
            for (var i= 0; i < cubes.length; i++) {
                var cube = cubes[i];
                for (var j = 0; j < cube.children.length; j++) {
                    var child = cube.children[j];
                    child.material.color.setHex(cube.originalColor);

                }


            }
        }

        function  highlightRow(cubes) {
            for (var i = 0; i < cubes.length; i++) {
                var cube = cubes[i];
                for (var j = 0; j < cube.children.length; j++) {
                    var child = cube.children[j];                       
                    child.material.color.setHex(0xffff00);
                    break;

                }

            }
        }

Answer №1

After some troubleshooting, I realized the solution was to substitute renderer.domElement with window when converting from regular space to NDC space. The correct code looks like this:

mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

By making this adjustment, my cursor now aligns perfectly over the cubes instead of being positioned outside the grid.

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

What is the reason that em takes precedence over p for font-family?

Take a look at this CSS snippet: * { font-family: Gill Sans, Verdana, Arial, Helvetica, Sans-Serif} p { font-family: Courier; } Now let's consider this HTML markup: <p>Hi there. So <em>very</em> pleased to make your acquaintance. ...

How can I simulate the response of a VueX action using Vue-test-utils?

I am currently developing a test for a Vue component that interacts with a module store to execute an action and utilize the result from it. Since the action involves making requests to our API, I prefer not to run the test using the actual action. Instea ...

Is there a way to obtain metadata for a specific link?

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><$BlogPageTitle$></title> <meta property="og:title" content=" ...

Check if an object is already in an array before pushing it in: JavaScript

Summary: I am facing an issue with adding products to the cart on a webpage. There are 10 different "add to cart" buttons for 10 different products. When a user clicks on the button, the product should be added to the this.itemsInCart array if it is not a ...

Is it possible to pass the image source to a Vue.js component through a

I am encountering an issue while trying to display an image in the designated location within display.vue. Even though {{ someText }} returns the correct file path (../assets/city.png), the image is not being output correctly. Here is how my code looks: ...

Avoiding Duplicate Paths in URLs with Perl CatalystOne common issue that can occur in web development is the presence of double

I recently developed a web application using Catalyst framework. The login page can be accessed by typing the URL: http://mydomainname/login When accessing this URL, the login page is displayed beautifully with all its styling from the CSS file. However ...

How about: "Insert a line break inside a div element"

My goal is to have 3 icons positioned side by side that will float left if the window shrinks. Under each icon, I plan to include some text. Below you can see that I've made progress on this layout. .icons { BORDER-TOP: black 1px solid; HEIGHT: 10 ...

Encountered an error searching for module 'autoprefixer' while executing the npx tailwindcss init -p command

I am currently working with Vue 3 and attempting to integrate tailwindcss by following this helpful tutorial: https://tailwindcss.com/docs/guides/vue-3-vite#install-tailwind-via-npm I have successfully installed the necessary dependencies using the comman ...

Updating ListItemText styles in MUI when active with react-router

I am currently using ListItem from Material-UI. I am attempting to increase its font weight when it is active, but for some reason the font-weight property does not seem to have any effect. Below you will find the code snippet: <List component=&a ...

Utilizing Zustand state management with Next.js 13.4.12 for routing and server-side rendering, enhanced with local storage

My Zustand store code looks like this: import create from "zustand"; import { persist } from "zustand/middleware"; const useProjectStore = create( persist( (set) => ({ selectedProject: null, setSelectedProject: (pr ...

What is the best way to implement a delay for ajax requests triggered by onkeyup events, and then restart the delay countdown each

Is there a way to add a delay for ajax requests triggered by onkeyup and reset the delay if onkeyup is triggered again? For instance, consider this code: When a user enters data into id="fname" triggering an onkeyup event, a loading span id="loading" wil ...

When the width of the element is set to 100vw, it disrupts the

I'm attempting to expand a sticky element to fit the size of the screen. Here is the HTML code I am using: .large { height: 200vw; width: 200vw; } .header { left: 0; top: 0; color:white; position: sticky; width: 100px; height: 10 ...

The initial execution of the getDocs function may encounter some difficulties

Whenever a user connects from localhost:3000/ (which automatically redirects to /profile), I try to fetch all documents from Firebase. However, it does not work on the first attempt. Strangely, upon refreshing the page, it successfully retrieves the docume ...

Turn off link preview feature on Android messages

As a developer, I am looking for a way to disable or hide link previews on Android devices when someone receives a text message with a link to our website. I still want the URL address to be visible, but I prefer to keep the link previews on IOS devices. I ...

What is the method to utilize the process.env object from within an imported npm package in the importing class?

In my React app, I used dotenv to set process.env variables for each component. When all components were in the same source code repo and imported via '../component/component_name', accessing these variables was easy using process.env.variable_na ...

AngularJS - Issue with Scope not being properly utilized in view when calling controller function

I'm attempting to update a variable within $scope in a controller function, and while the assignment is successful, it doesn't reflect in the view. app.controller('LoginCtrl', ['$scope', '$http', function ($scope, $ ...

Is it possible to generate an HTML element by utilizing an array of coordinates?

I have a set of 4 x/y coordinates that looks like this: [{x: 10, y: 5}, {x:10, y:15}, {x:20, y:10}, {x:20, y:20}] Is there a way to create an HTML element where each corner matches one of the coordinates in the array? I am aware that this can be done usi ...

Fixing the vertical centering of content when printing HTML

My bootstrap 4-based HTML page is looking good on most screens, but when I try to print it, the content is vertically centered in the print layout. How can I ensure that the content is displayed at the top of the paper? https://i.sstatic.net/kfjrx.png Be ...

Tips for adjusting the dimensions of my chart using JavaScript or Jquery

Utilizing DevExtreme widgets for the creation of a line chart in jQuery as shown below: var dataSource = [{"Date Range": "August-2018", Benelux: 194, Czech_Slovakia: 128, ...

What is the best way to retrieve recently inserted data using Sequelize in PostgreSql?

Is there a way to retrieve updated table values after adding a user to the "WOD" table without making an additional query? Currently, when I add a third user to my WOD table, I can only return the first two users because I am unable to access the updated ...