poor performance in three js due to raycasting operations

Recently, I've been delving into the world of ray casting in Three.js. However, I encountered some major performance issues when testing it out on both FireFox and Chrome. Interestingly, Chrome seems to be experiencing camera rubber banding even in a small local game setting. When I added the following code snippet to the animate loop:


var intersects = raycaster.intersectObjects(sceneObjects);

if (intersects.length > 0) {
    var firstIntersectedObject = intersects[0];
    console.log(intersects[0].object.userData);
    console.log(intersects[0].object.userData.glow);
    if (intersects[0].object.userData.glow === 'true') {
        console.log("GLOW");
    } else {
        console.log("NO!");
    }
    //intersects[0].object.material.wireframe = true
    //This will give you the first intersected Object if there are multiple.
}

My game started experiencing lag as soon as this code was added, and I'm completely stumped as to why. Any suggestions or pointers would be greatly appreciated.

Answer №1

To optimize performance, it is recommended to avoid raycasting on every single frame and instead set up a specific interval for raycasting. This can be achieved by using functions like setTimeout or setInterval, or by checking the timing within the update loop.

onUpdate() {
    // Code that runs once per frame

    // Check if enough time has passed to perform raycast
    if (Date.now() - this.lastRaycast > this.raycastInterval && this.qRaycast) {
        this.handleRaycast();
        this.lastRaycast = Date.now();
        this.qRaycast = false;
    }
    requestAnimationFrame( () => this.onUpdate() );
}

In addition, consider queuing up raycasts only when the mouse moves, as there's no need to continuously raycast when the mouse is stationary. Also, disable raycasting during panning movements to prevent any jitter during such actions.

// Event Handlers
// Record mouse position for raycast
onMouseMove(e) {
    this.mouse.x = (e.clientX / window.innerWidth ) * 2 - 1;
    this.mouse.y = -((e.clientY - 50) / window.innerHeight ) * 2 + 1;

    // Do not queue raycast if panning
    this.qRaycast = !this.mouseState.held;
}

// Disable raycast during panning
onMouseDown(e) {
    this.mouseState.lastClick = Date.now();
    this.mouseState.clicked = false;
    this.mouseState.held = true;
}

onMouseUp(e) {
    this.mouseState.held = false;
}

Once the conditions are met, handling the raycast like so:

// Handling Raycast
handleRaycast() {
    let hits = null;
    let hitcount = 0;
    if (UI.raycast && meshObj) {
        this.raygun.setFromCamera(this.mouse, this.camera);
        hits = this.raygun.intersectObject(meshObj, false);
        hitcount = hits.length;
    }

    if (hitcount > 0) {
        // Actions with the raycast results
    }
}

If further optimization is needed, consider breaking down the loop function into smaller parts to allow UI updates in between iterations:

An example could be sorting through all hits to find the closest point to the cursor:

// Optimization
let startTime = 0;
let maxTime = 75; // maximum time in ms
let dist = 1;
let hitIndex;
let i = 0;

function findClosest() {
    return new Promise((resolve) => {
        function loop() {
            startTime = performance.now();
            while (i < hitcount) {
                // Break loop after max time
                let currentTime = performance.now();
                if ((currentTime - startTime) > maxTime) {
                    console.log('Loop exceeded max time: ' + 
                        (currentTime - startTime).toFixed(3) );
                    startTime = currentTime;
                    break;
                }

                // Finding the closest raycast point to cursor
                dist = hits[i].distanceToRay;
                if (dist < smallestDist) {
                    smallestDist = dist;
                    smallestPointIndex = hits[i].index;
                }
                i++;
            }

            if (i < hitcount) {
                // Update UI and continue looping
                setTimeout(loop, 1);
            } else {
                resolve(smallestPointIndex);
            }
        }
        loop();
    });
}

findClosest().then(result => {
    // Handle result here
}

Additionally, reducing the number of objects being raycasted to can also help improve performance significantly.

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's the reason Rails is not recognizing relative JavaScript files?

app/assets/javascripts/application.js: //= require jquery //= require jquery_ujs //= require_tree . //= require bootstrap.min app/assets/javascripts/economy.js: $(document).ready(function() { console.log("loaded file"); }); app/views/economy/index.ht ...

Issues with Videojs Responsive Lightbox Functionality

I am looking for a solution to display VideoJS in a lightbox while keeping it responsive. I came across this helpful code snippet: https://github.com/rudkovskyi/videojs_popup. It seemed perfect until I tried using it with the latest version of Videojs and ...

Using Jquery to trigger a function with varying parameters by clicking on multiple buttons

I have a query about extracting values from input text fields in my code. Is there a solution for this issue? <?php for ($i=0;$i<3;$i++){ echo ('<input type="text" class="form-control" name="vec" id="vec'.$i.'" value=" ...

The JavaScript code is not being executed, as the address bar displays the function name instead

In my project, I have created numerous "js-classes" with various functions spread across different files. Unfortunately, the codebase is too large to share entirely. However, towards the end of the project, I encountered a bug where a specific function wa ...

Discover the distinctions within 2 arrays containing multiple dimensions

Recently, I've been struggling to identify the disparities between two multi-dimensional arrays. Let's take a look at the arrays: let arr1 = [["Tag2","TES"],["Tag3","TES"],["Fedex Ground","T ...

Vue3 - Suspense not displaying backup content

I have a parent component and a child component set up as follows: . ├── Index.vue (Parent) └── _GetShipment.vue (Child) Within Index.vue, I am using Office.js's getAsync method to retrieve the content of an email body: <script> imp ...

Tips for utilizing jQuery Ajax data action

I've been trying to understand how to effectively utilize the data parameter in a $.Ajax call. However, I am facing confusion regarding the 'action' part within the data call. Is it meant to trigger an action in a controller? If so, how can ...

Is there a way to trigger $q notify without initiating a $digest cycle?

Within my application, the $digest cycle typically takes around 5ms to complete. I heavily utilize $q.defer with deferred.notify throughout my codebase, but I've encountered an issue. Each time deferred.notify is triggered, it schedules a new digest c ...

What is the best way to remove a particular element from an array stored in Local Storage?

Currently working on a web application that features a grade calculator allowing users to add and delete grades, all saved in local storage. However, encountering an issue where attempting to delete a specific grade ends up removing the most recently add ...

Method for developing a screen-sharing application

I'm in the process of developing a screen sharing application. I initially attempted to utilize WebRTC, but encountered numerous challenges with it. As a result, I am contemplating an alternative approach outlined below. For the Host side, capture ...

After every postback, the Validation function (Page_ClientValidate('mygroup')) consistently returns true

I am encountering an issue with my page validations. Most of my validations are happening on the client side, but there is one validation that requires server-side processing. The problem arises when I trigger the server side validation and my page posts ...

Extract table information from MuiDataTable

I am having trouble retrieving the row data from MuiDataTable. When I try to set the index from the onRowSelectionChange function to a state, it causes my checkbox animation to stop working. Below is how my options are currently configured: const option ...

Creating an additional window without the use of JavaScript or an anchor tag

I have a query that may come across as unconventional. As I am in the process of creating a website, I am looking to incorporate some advertisements. I would like for a new window to pop up when users visit my site. While I initially achieved this using ...

What could be causing setViewValue() to fail to update values in all instances in this scenario?

index.html represents: <!DOCTYPE html> <html ng-app="myApp"> <head> <script src="js/angular.js" type="text/javascript"></script> <script src="js/app.js" type="text/javascript"></script> &l ...

Using Ajax to invoke a C# webmethod

I'm trying to call a webmethod defined in this specific class <%@ WebService Language="C#" Class="emt7anReyady.myService" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using System.Linq; usi ...

What is the best way to transform React API data into props that can be utilized in different components?

I've been struggling with this issue for quite some time now, unable to understand how to manipulate the data in a way that allows me to use it in other components. Although I can display the data correctly, I'm advised to structure it within a f ...

Can lazy loading be implemented for the video tag using JavaScript?

Currently, I am in the process of working on a project that entails incorporating three videos onto the homepage. However, loading them simultaneously is causing a significant decrease in load time. In addition, I prefer to utilize the <video/> tag ...

What is the process for incorporating a third-party library into Angular 6?

Many developers face the challenge of using external libraries in Angular that are not officially supported, such as Clappr and HashWords. The desire is to integrate these libraries seamlessly into an Angular project, almost treating them like native Ang ...

Radio buttons with multiple levels

Looking to implement a unique two-level radio button feature for a specific option only. Currently, I have written a logic that will display additional radio buttons under the 'Spring' option. However, the issue is that when it's selected, t ...

Techniques for triggering JavaScript on elements that have been dynamically loaded via Ajax

When it comes to ensuring that a certain functionality works both when the document is ready and after an Ajax call, there are some considerations to keep in mind for optimal performance. An approach I found effective involves defining the desired code wi ...