Optimizing Performance in THREE .JS Raycasting

I am attempting to determine the shortest distance from a point to a large, intricate Mesh along a plane within a specific direction range:

 for (var zDown in verticalDistances) {
    var myIntersect = {};  
   for (var theta = Math.PI / 2 - 0.5; theta < Math.PI / 2 + 0.5; theta += 0.3) {
                var rayDirection = new THREE.Vector3(
                    Math.cos(theta),
                    Math.sin(theta),
                    0
                ).transformDirection(object.matrixWorld);
                 //  console.log(rayDirection);

                _raycaster.set(verticalDistances[zDown].minFacePoint, rayDirection, 0, 50);
                //  console.time('raycast: ');
                var intersect = _raycaster.intersectObject(planeBufferMesh);
                //   console.timeEnd('raycast: '); // this is huge!!! ~ 2,300 ms

                //   console.log(_raycaster);
                //    console.log(intersect);
                if (intersect.length == 0) continue;
                if ((!('distance' in myIntersect)) || myIntersect.distance > intersect[0].distance) {
                    myIntersect.distance = intersect[0].distance;
                    myIntersect.point = intersect[0].point.clone();
                }
            }
// do stuff
}

While mouse hovering on the same surface yields good results, the raycasting loop is taking over 2 seconds per cast. Could the DoubleSide Material BackSide be causing this delay?

Interestingly, if I increase the spacing between verticalDistances[zDown].minFacePoint, the raycast speeds up significantly (500ms /cast). So, as the distance between verticalDistances[i].minFacePoint and verticalDistances[i+1].minFacePoint grows, the raycaster performs faster.

My consideration is to use octree, but the mouse hover event works flawlessly on the same planeBuffer. Could the issue be related to the Material side, which might be resolved by loading 2 FrontSide meshes pointing in opposite directions?

Thank You!!!!

EDIT: it is not a front back issue. I ran my raycast down the front and back side of the plane buffer geometry with the same spot result. Live example coming.

EDIT 2: working example here. Performance is little better than Original case but still too slow. I need to move the cylinder in real time. I can optimize a bit by finding certain things, but mouse hover is instant. When you look at the console time the first two(500ms) are the results i am getting for all results.

EDIT 3: added a mouse hover event, that performs the same as the other raycasters. I am not getting results in my working code that i get in this sample though. The results I get for all raycast are the same as i get for the first 1 or 2 in the sample around 500ms. If i could get it down to 200ms i can target the items i am looking for and do way less raycasting. I am completely open to suggestions on better methods. Is octree the way to go?

raycast: : 467.27001953125ms
raycast: : 443.830810546875ms

EDIT 4: @pailhead Here is my plan. 1. find closest grid vertex to point on the plane. I can do a scan of vertex in x/y direction then calculate the min distance. 2. once i have that closest vertex i know that my closest point has to be on a face containing that vertex. So i will find all faces with that vertex using the object.mesh.index.array and calculate the plane to point of each face. Seems like a ray cast should be a little bit smarter than a full scan when intersecting a mesh and at least cull points based on max distance? @WestLangley any suggestions?

EDIT 5: @pailhead thank you for the help. Its appreciated. I have really simplified my example(<200 lines with tons more comments); Is raycaster checking every face? Much quicker to pick out the faces within the set raycasting range specified in the constructor and do a face to point calc. There is no way this should be looping over every face to raycast. I'm going to write my own PlaneBufferGeometry raycast function tonight, after taking a peak at the source code and checking octree. I would think if we have a range in the raycaster constructor, pull out plane buffer vertices within that range ignoring z. Then just raycast those or do a point to plane calculation. I guess i could just create a "mini" surface from that bounding circle and then raycast against it. But the fact that the max distance(manual uses "far") doesn't effect the speed of the raycaster makes me wonder how much it is optimized for planeBuffer geometries. FYI your 300k loop is ~3ms on jsfiddle.

EDIT 6: Looks like all meshes are treated the same in the raycast function. That means it wont smart hunt out the area for a plane Buffer Geometry. Looking at mesh.js lines 266 we loop over the entire index array. I guess for a regular mesh you dont know what faces are where because its a TIN, but a planeBuffer could really use a bounding box/sphere rule, because your x/y are known order positions and only the Z are unknown. Last edit, Answer will be next

Answer №1

Just a heads-up: to achieve maximum velocity, you may want to consider employing mathematical calculations instead of relying on ray casting. Check out this resource for more information on 3D coordinate geometry and the equation of a plane:

Answer №2

After overcoming significant challenges, I successfully implemented a solution to filter faces of a planeBufferGeometry based on vertex index. By identifying a bounding sphere or rectangle within the geometry, I was able to efficiently locate and isolate the necessary faces. The use of x/y ordering in the index array proved to be a helpful filter as well. To pinpoint the bottom left and top right corners in the index array, I utilized indexOf and lastIndexOf respectively. It's important to note that RAYCASTING CHECKS EVERY FACE throughout this process.

In order to optimize performance, I abandoned the approach of finding the distance from each face of the object. Instead, I opted for a vertical path down the center of the object, resulting in a decrease in the number of ray castings required.

Furthermore, I implemented a custom face walk through technique, utilizing the triangle.closestPointToPoint() function on each face. The end result was achieving approximately 10ms per point to surface calculation (single raycast), and around 100ms per object (10 vertical slices) to surface. Prior to these optimizations, I was experiencing 2.5 seconds per raycast and 25+ seconds per object.

Answer №3

My journey began with creating planes for terrains and utilizing height maps for extrusions. I soon discovered that it was easier to simply download Blender for free and follow a tutorial on creating heightmap terrains. In just 10 minutes, I was able to transform it into a gtfl file. Although I may have misspelled that.

if( typeof mesh[1] == 'object' ){
var raycaster = new THREE.Raycaster(fued.position, new THREE.Vector3(0, -1, 0));
var intersections = raycaster.intersectObject( mesh[1] );
if (intersections.length > 0 ){
fued.position.y = fued.position.y - intersections[0].distance + 2500;
}}

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

Update the VueJS application by loading and replacing the existing JSON data with new information

Is there a way to dynamically re-render the entire v-for loop and DOM after fetching and loading new JSON data to replace the current one? I want to be able to click on different options and have the products updated. Vue.use(VueResource); var produ ...

The feature for sending posts in Angular.js appears to be malfunctioning

I have developed a rest-API for adding todos in a MongoDB database. When I use Postman with the setup below, I can successfully save instances: http://localhost:3000/api/addtodo x-www-form-urlencoded with values text="Test", completed: "false". However, ...

Using JavaScript variables in a Jinja array

I encountered a frustrating issue that has been causing me some trouble. In my project setup, data is being transferred from Python to the frontend using Jinja in the form of a 2D list. My goal is to loop through this array using a for loop, but I'm ...

What is the reason why the "@wordpress/scripts" package does not produce the *.asset.php file when running "npm run build"?

I have been creating custom Gutenberg blocks using npm, webpack, and @wordpress/scripts. Everything was running smoothly until I encountered an issue with the block.json file. In order to use the block.json file, I discovered that I needed a block.asset.ph ...

Crack open a JSON object

I am struggling to parse a JSON object. It seems like the code is not working, can you help me? var mock_data = { "available": [{ "UserID": 7, "UserName": "Manoj", "Language": "Java", "Score": 9, "TimeLimit": 4.0 }, { "UserID ...

Implementing specifications throughout the entire nodejs route

In my Nodejs app, I have a RESTful API where I need to check for a user's role before sending a response with data or 404 error. apiRouter.route('/users') .get(function (req, res) { var currentUser = req.decoded; if(curr ...

The code begins executing even before the function has finished its execution

I believe that is what's happening, but I'm not entirely sure. There's code in a .js file that invokes a function from another .js file. This function performs an ajax call to a php page which generates and returns a list of radio buttons wi ...

The issue with the jQuery function lies in its inability to properly retrieve and return values

Within my code, I have a function that looks like this: $.fn.validate.checkValidationName = function(id) { $.post("PHP/submitButtonName.php", {checkValidation: id}, function(data) { if(data.returnValue === true) { name = true; } else { ...

Identifying edited files within the node_modules directory: A comprehensive guide

While working with the serverless framework, I installed it using npm. During my debugging process, I made some modifications by adding console.log statements to different files within the node_modules folder. Unfortunately, I can't recall which speci ...

Tips for updating the display by fetching data from a database through a websocket

I am looking for a solution to update a specific part of my webpage without having to refresh the entire content. On my index.html page, I have three panels displaying various ticket statuses. I want to automatically update the number of resolved tickets s ...

Using jQuery to swap out sections of a HTML tag

Similar Question: Use of jQuery for Modifying an HTML Tag? After extensive research, I have not come across a solution that fits my specific requirements. My objective is to replace a part of an HTML tag without completely replacing the entire tag. To ...

`Jump-start Your Development with jQuery Lightbox Centering`

Recently, I implemented a lightbox effect for images on my website. However, I encountered an issue where the lightbox was not centering properly in the window upon initial click. Instead, the lightbox would appear at the bottom of the page on the first cl ...

React maintains the state of just a single element within an array at a time

I'm faced with a roadblock while developing my covid19 application. The app should display a list of countries on the left side of the screen, allowing users to add any number of countries to the right side for more detailed covid data. I'm still ...

`sendNodejs header not being transmitted during connection``

My nodejs application utilizes stomp to connect to a server using websockets. However, I am encountering an issue where the application is failing to send the headers that I have specified. Despite referring to clear documentation and examples on how to in ...

The Vue v-on:click event listener seems to be unresponsive when applied to a

I've been attempting to utilize the on-click directive within a component, but for some reason, it doesn't seem to be functioning. Whenever I click on the component, nothing happens, even though I should see 'test clicked' in the consol ...

Identify when a click occurs outside specific elements

I've been searching for solutions to address this issue, but so far nothing has worked. Here is the JavaScript code I am using: var specifiedElement = document.getElementById('a'); document.addEventListener('click', function(eve ...

Is it necessary to re-export a module after modifying an attribute in it in JS/ES6?

From my understanding of the module system, when I use import 'some_module' in a file, I will always receive the same instance of that module and not a new instance each time. However, I am a bit puzzled by a pattern I have observed in certain a ...

What is the best way to link my "dynamic sub-component" with AngularJS?

While I have a solid grasp on the fundamentals of AngularJS and can create basic CRUD applications, when it comes to applying this knowledge to real-world scenarios, I find myself struggling with how to integrate the concepts effectively. One specific cha ...

Choosing comparable choices from the drop-down menu

I am working on a dropdown menu that contains different options. I need to use jQuery to automatically select the option that corresponds to the branch of the currently logged in user. However, when some option text is very similar, it causes an issue. // ...

Modify the base URL with JavaScript

Is it possible to dynamically change the href using JavaScript? I attempted to make this change with the code below in my HTML file, but unfortunately, it didn't work: <base href="/" /> <script type="text/javascript"> function setbasehr ...