Issue with the intersection of mouse and camera rays in three.js

I've been working on a simple program that involves creating a clickable 3D object in Three.js. I've referenced my code from

When I click directly on the object, it works as expected, but upon examining the resulting array, I noticed that the object is included twice. I'm assuming this happens because the ray intersects it both when entering and exiting.

However, if I click around the object rather than directly on it, raycaster.intersectObjects still returns the object instead of an empty array. Why does this happen? Is it normal for an object to be included twice in the intersect array due to the ray entering and exiting?

You can see a live example of the code here:

https://codepen.io/ettir_deul/pen/PoGLNZx

(open the console to view the intersect array after clicking on the screen)

Below is a snippet of the code:

<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<script src="libs/three.min.js.r116.1"></script>
</head>

<body>
<div id="threejsCanvas"></div>
<script>

let scene, center, camera, renderer, raycaster;
const mouse = new THREE.Vector2();
const threejsCanvas = document.getElementById("threejsCanvas");


init3d();


function init3d(){
  
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xAAAAEE);
  
  center = new THREE.Vector3(0, 0, 0);
  
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.set(center.x, center.y, center.z+1);
  camera.lookAt(center);

  buttonMesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), new THREE.MeshBasicMaterial({map : null, color: 0x008844, wireframe: false, side: THREE.DoubleSide}));
  buttonMesh.position.set(center.x, center.y, center.z);
  scene.add(buttonMesh);
  buttonMesh.objId = "buttonMesh";
  
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  threejsCanvas.appendChild(renderer.domElement);
  renderer.render(scene, camera);
  
  raycaster = new THREE.Raycaster();

  document.addEventListener('click', onMouseClick, false);
}



function onMouseClick(event){

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

  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(scene.children);
  console.log(intersects);
}

</script>
</body>
</html>

Answer №1

The reason for encountering the object twice lies in

the setting: THREE.DoubleSide

within the material. To resolve this, try utilizing THREE.FrontSide instead.

The issue of selecting the object when the mouse is near arises from a discrepancy between canvas and window dimensions. To address this problem, simply include:

 body{ 
  padding: 0;
  margin: 0; 
} 

in your CSS code to rectify the situation.

For a functional demonstration, check out this codepen example.

Answer №2

  1. It's normal to get two results - each side of the mesh is intersected by the ray. Check the intersection properties for each result: face, faceIndex, point.

  2. The Raycaster may not be very precise and can be slow. You can adjust its precision using 'params' (see ). Another option is to use GPUPicker, which is more accurate and faster. More information can be found here:

https://github.com/brianxu/GPUPicker

Edit: Changing the material can help avoid getting 2 intersections, but it might not always be suitable for all surfaces.

Edit: Precision settings only impact point and line picking. GPUPicker can accurately pick rendering results of points (such as shader effects and symbols with transparency), whereas standard raycaster cannot.

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

choose and adjust elements within a three-dimensional scene using three.js

I have a JSON file containing object data that I load into my scene using ObjectLoader. After adding the objects to the scene, I want to customize their textures by adding parameters like THREE.SmoothShading and an envMap. I know how to find a specific obj ...

Deciphering unidentified Json data

Having some trouble with an error in my note taker app built using expressjs. Everything was working fine until I tried to save a new note and it's throwing this error: SyntaxError: Unexpected token o in JSON at position 1 at JSON.parse () Here&apos ...

Flask is failing to display AJAX data

Looking to embark on a Flask project involving sending an AJAX request. In the Flask code, I want to assign a variable to handle the request and display it on the page using a Jinja variable. Flask from flask import Flask,render_template,request app = Fla ...

Developing a custom function to retrieve an array as a callback

I'm currently diving into the world of Node.js Struggling with implementing my own callback function in a certain method. It may seem like a straightforward task, but I'm finding it quite challenging to grasp. This specific function takes an ad ...

Incomplete JSON response being received

We set up an express server to call an API and successfully requested the JSON object in our server. However, we are facing an issue where the JSON data is getting cut off when being displayed as a complete object on the client side. We tried using parse i ...

Extracting live TV channels from an m3u file by differentiating them from VOD content

Currently, I am developing an IPTV player app and have successfully parsed the m3u file. My current challenge is separating live TV channels from Video on Demand (VOD). I am unsure of where exactly the transition happens in the playlists. Below are the ke ...

Showing JSON data as a table in an HTML format

After receiving the JSON String from the server as a response, which can be viewed here, I've implemented the following Jquery Code: function loadCategories() { $.ajax({ type: "POST", url: "/Services/ControllerService. ...

What tools do Sketchfab and Thangs utilize to display 3D models?

My website functions as a digital library for a particular niche of 3D models. However, I've noticed that the performance on mobile devices when using modelviewer to display glb files is quite poor. Frequently, the page crashes and reloads unexpectedl ...

Is there a more efficient alternative to the sluggish scroll event?

Currently, I have set up a scroll event that tracks the user's position on the page and updates the navigation styling based on which section they are viewing. However, the calculation I'm using during scrolling is quite resource-intensive and ca ...

JavaScript isn't functioning properly after UserControl is loaded via Ajax

Thank you, Stilgar for helping me solve my issue. I created a javascript file and placed all my code in it. After adding this file to the UserControl and retrieving the UserControl's html, I used $("#DivID").html(UserControlHTML). Now everything is wo ...

What is the best way to transfer Kendo Grid row data to a Kendo popup window within a partial view using jQuery?

I am currently facing a challenge in passing the row data from the Kendo Grid to a partial view that is displayed through a Kendo popup window. Within the partial view, users have the option to upload an image file related to the specific row record. This ...

Enhancing the user experience by providing auto-complete suggestions while still maintaining the original form functionality

Encountering a curious bug that appears to be affecting only IE and Webkit browsers. I've set up a simple form as follows: <div id="output">Form output is shown here</div> <form id="myForm" action="#" method="post"> <input type= ...

Is it obligatory to reply with status code 200 in Express?

Is it required to explicitly include a status 200 code in the response or is it set automatically? response.json({ status: 'OK', }); vs. response .status(200) .json({ status: 'OK', }); Upon testing the route in my browser, ...

Is it a suboptimal method to repeatedly use order.find, collect data, and transmit a substantial data payload to the front end in

Currently, I am working with Express, React, and MongoDB but I am relatively new to using express and REST API. My goal is to add an analytics feature to my frontend that focuses on sales and orders. The plan is to allow users to search within a specified ...

What is the best way to break down this function from props in React?

Forgive me if this question sounds naive, but as I delve into the world of React and useState, I am encountering a scenario where I have a signup function coded. Upon sending a username and password through a POST request to an API endpoint, a response mes ...

When entering a sub-URL into the browser address bar, the routes do not display as expected

I am encountering an issue with navigating to different routes within my React application. While the home route is visible and functions properly when I start the app locally (npm run dev), I am unable to access other routes. No errors are displayed in t ...

Cross-Origin Resource Sharing (CORS) Issue: How Angular.JS, Node.JS, and

Encountering problems retrieving data from a http post request to my API. Seeing the following error message: XMLHttpRequest cannot load (URL to API here). No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin &ap ...

Overlaying a div on top of an iframe

Struggling to make this work for a while now. It seems like a small issue related to CSS. The image isn't overlaying the IFrame at the top of the page as expected, it's going straight to the bottom. Here is the code snippet: .overlay{ width: ...

"Experience the magic of Datepicker jQuery with just a click

Does anyone know how to capture the click event when a day is selected using jQuery Datepicker? Is it possible, and if so, how can I achieve this? https://i.sstatic.net/ZG4r8.png Here is the HTML code snippet: Date From : <input type="text" ...

What is the best way to filter out and combine one array from two arrays in lodash based on their unique properties?

Lodash v 4.17.15 Consider the scenario where two arrays are involved: var users = [{ id: 12, name: Adam },{ id: 14, name: Bob },{ id: 16, name: Charlie },{ id: 18, name: David } ] var jobs = [ ...