Mastering the art of raycasting onto a point cloud in ThreeJs R71

I am currently working with Autodesk Forge, leveraging Three.js r71, and I am looking to implement a raycaster to identify clicks on various elements within a point cloud.

If anyone could provide a sample code snippet on how to achieve this using Three.js r71, that would be greatly appreciated.

Currently, I have registered an extension with the Forge API and am executing the code below within it. This code generates a point cloud and places the points at predetermined locations (stored within the cameraInfo array).

let geometry = new THREE.Geometry();
this.cameraInfo.forEach(function(e) {
    geometry.vertices.push(e.position);
});
const material = new THREE.PointCloudMaterial({ size: 150, color: 0Xff0000, sizeAttenuation: true });
this.points = new THREE.PointCloud(geometry, material);
this.scene.add(this.points);

/* Event listeners setup */
document.addEventListener('mousemove', event => {
    let mouse = {
        x: (event.clientX / window.innerWidth) * 2 - 1,
        y: -(event.clientY / window.innerHeight) * 2 + 1
    };

    let raycaster = new THREE.Raycaster();
    raycaster.params.PointCloud.threshold = 15;
    let vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(this.camera);
    raycaster.ray.set(this.camera.position, vector.sub(this.camera.position).normalize());
    this.scene.updateMatrixWorld();
    let intersects = raycaster.intersectObject(this.points);

    if (intersects.length > 0) {
        const hitIndex = intersects[0].index;
        const hitPoint = this.points.geometry.vertices[hitIndex];
        console.log(hitIndex);
        console.log(hitPoint);
    }
}, false);

However, the output appears to be inconsistent. In some camera positions, it continuously reports intersections within the point cloud (regardless of mouse position), while in other positions, it fails to detect any intersection at all.

In short, the raycaster does not consistently identify intersections between my point cloud and the mouse cursor.

Answer №1

The code has been streamlined by utilizing some viewer APIs and sample points from the point cloud:

  const viewer = NOP_VIEWER;
  const geometry = new THREE.Geometry();
  for (let i = -100; i <= 100; i += 10) {
    geometry.vertices.push(new THREE.Vector3(i, i, i));
  }
  const material = new THREE.PointCloudMaterial({ size: 50, color: 0Xff0000, sizeAttenuation: true });
  const points = new THREE.PointCloud(geometry, material);
  viewer.impl.scene.add(points);

  const raycaster = new THREE.Raycaster();
  raycaster.params.PointCloud.threshold = 50;
  document.addEventListener('mousemove', function(event) {
    const ray = viewer.impl.viewportToRay(viewer.impl.clientToViewport(event.clientX, event.clientY));
    raycaster.ray.set(ray.origin, ray.direction);
    let intersects = raycaster.intersectObject(viewer.impl.scene, true);
    if (intersects.length > 0) {
      console.log(intersects[0]);
    }
  });

To improve the intersection results, adjusting the

raycaster.params.PointCloud.threshold
value may be necessary. The ray casting process in three.js calculates the distance between the ray and the point, only registering an intersection if the distance is below the threshold value. Setting the threshold to 50 yielded somewhat improved results in this example.

Consider utilizing HTML elements overlaid on the 3D view instead of point clouds if they are not essential for the scene. The demo (source) demonstrates this method by displaying annotations attached to specific positions in the 3D space. With this approach, custom intersection handling is not required as the browser manages it automatically.

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

Ways to enhance the efficiency of this javascript duplicates

I recently wrote this JavaScript code but, as I am still in the early stages of learning, I am struggling to optimize it efficiently. I ended up duplicating the code for each if statement. $(function() { var lang = $(".lang input[type='checkbox&a ...

What is the reason `addEventListener` does not work with a class method?

Recently, I discovered that the listener passed to addEventListener can actually be an object with a handleEvent function instead of just a callback function (here). However, I encountered an issue when trying to use handleEvent as a class method: class F ...

Solving the issue of 'b-modal' not appearing in a Vue.js custom component

Software Used: Vue.js Bootstrap-Vue () Issue: My aim is to show a popup when a row is clicked within a bootstrap grid. Once the modal is closed, I want it to disappear and the selected item to be removed. To tackle this problem, I have developed a custo ...

Struggling with transitioning from TypeScript to React when implementing react-data-grid 7.0.0

I'm trying to add drag and drop functionality to my React project using react-data-grid, but I keep encountering a "TypeError: Object(...) is not a function" error. I have a TypeScript version of the file in the sandbox as a reference, but when I try ...

The click event is triggering before it is able to be removed by the code preceding the trigger

Here's a scenario I recently experienced that involves some code written using JQuery. It's more of a statement than a question, but I'm curious if others have encountered this as well: <input type="submit" value="Delete" o ...

Building routes for nested relationships in the MEAN stack: A comprehensive guide

Within my Mongoose Schema, I am dealing with two models - User and Plans. Each user can have multiple plans, so in the Plans Schema, I am embedding a userID like this: var PlanSchema = new mongoose.Schema({ title: {type: String}, userId: {type: Stri ...

Initiate the Bull Queue Process upon launching the Application

As I develop my API, I am setting up a queue and adding jobs to it. Additionally, I have configured the API to start processing these jobs as soon as they are added. const newQueue = createQueue(queueName, opts); newQueue.add('JokesJob', data, o ...

Unlock the encrypted information in the blockchain

I've been working on encrypting and decrypting values using Node's built-in crypto module. I found a helpful tutorial that showed me how to encrypt the data, but it didn't provide any sample code for decryption. When I tried using code from ...

Displaying <p> content upon selection of a radio button

As a beginner in JS + HTML, I am looking to create 4 radio buttons with different names like this: o PS4 o Xbox o Nintendo DS When one of these is clicked/checked, I want to display the price which will be located in a "p" tag next to them, like so: o P ...

Tips for attaching a callback to Angular UI Popover's trigger

I recently implemented an Angular UI Popover in the following manner: <div popover-is-open="prfList.isProfileClosed===false" popover-trigger="'outsideClick'" popover-append-to-body="true" popover-placement="right-top" popover-class="popover1 ...

Observing nested data changes in Vue.JS?

In my Vue.js components, I have a group of checkboxes that are sending data to the parent element. My goal is to monitor this data for changes and use it to filter information in an API call. When certain checkboxes are selected, the data stored on the pa ...

Defining the signature of an unnamed function in TypeScript

Within my Express code, I have an anonymous function set up like this: app.use((err, req, res, next) => { // ... }); I am looking to specify the type of the function as ErrorRequestHandler (not the return type). One way to achieve this is by defining ...

"Encountered an error: AngularJS is unable to read the property 'push' as it is

I'm attempting to generate an array using data retrieved from an API. However, I continue to encounter an error message stating cannot read property 'push' of undefined in Javascript. Could someone please guide me on how to resolve this iss ...

Having trouble sending data from AJAX to PHP

My goal is to implement a "load more" feature in my web app that automatically calls a PHP file to load additional products as soon as the page is fully loaded. In order to achieve this, I am using AJAX to call the PHP file: $(document).ready(function() { ...

Error encountered in amCharts Serial Chart when data parsing is enabled with the setting "parseDates": true which resulted in the failure to display data

Using Spring as a webservice, I received a JSON response with stock data: [ { "date": "2016-04-17", "open": 1085.0, "high": 1092.2, "low": 1072.0, "close": 1088.3, "volume": 54100, "value": 1088.3 }, { "date": "2016-04-14", "open": 1081. ...

Avoiding errors caused by higher order array methods

Is there a way to avoid errors when filtering data? The function below may encounter issues at conversationMember.Name.toLowerCase() if conversationMember is not present. This function is part of a computed property in a Vue application. Feel free to ask ...

Is it possible to trigger a JavaScript function and an AJAX command with just one button click?

I'm looking to achieve a specific functionality using one button within a form. The requirements are as follows: 1) When the button is clicked, it should trigger a JavaScript function that performs animations such as fadeout and fadein. 2) Following ...

Incorporating an SVG with CSS styling from a stylesheet

After exploring various articles and questions on the topic, I am yet to find a definitive solution. I have an external file named icon.svg, and my objective is to utilize it across multiple HTML files with different fill colors and sizes for each instanc ...

Tips for incorporating user-entered data from a text box into a JavaScript function and utilizing a loop

Although my code is functioning correctly, I am looking to make some adjustments but seem to be struggling to achieve the desired outcome. Essentially, I have two labels and an input field in which the user is prompted to enter a specific number of weeks ...

Fetch a document from a NodeJS Server utilizing Express

Is there a way to download a file from my server to my machine by accessing a page on a nodeJS server? I am currently using ExpressJS and I have attempted the following: app.get('/download', function(req, res){ var file = fs.readFileSync(__d ...