Raycaster.intersectObject - on big Terrain work very slow (heavy load on the processor)

Good afternoon, I have a large map of the area with mountains and depressions. I need to move the character taking into account the height, tobish point Y. This miscalculation is done on the server, every step of the movement, since the map is loaded there in memory, this is not a problem. But the [Raycaster.intersectObject] function causes too much load and the system will start to hang. The only way out that I found was to virtually split the map into sections and calculate the height for each section and write it to a file, but this worked, even though the height was not ideal, since the rendering step was 0.2, but if you make it just smaller, then the files will be very large. If anyone knows, please tell me how you can get out of this situation, maybe there are better calculations that do not load the system so much?

1 Like

You can speed up the performance of ray intersection tests in various ways. A typical approach is the usage of a bounding volume hierarchy. Check out:


Thanks a lot I will try.

Or, break up your terrain into smaller tiles
Three.js TypeScript Tutorials by Sean Bradley : https://sbcode.net/threejs

Yes, this is a great idea, but I have a ready-made sample, and I have nothing to break it with, I tried to disassemble the geometry into parts, but there is, as I understand it, connected points, this leads to an error.

No, it didn’t help, but are there any utilities to break the geometry into pieces?

Alternative way
Many points of your ground looks unnecessary for collision.
cuold you try to use an auxiliary geometry (not shown) only for raycast, very reduced in vertex count.


Thanks a lot to everyone, but dividing the map into sections managed to relieve all the load, soon I will finally make the first large geometric map.

No, it didn’t help

If the map is one big piece of geometry then three-mesh-bvh should have been able to reduce the time it takes to raycast pretty easily. If this is still an issue can you provide more information on how you used it and what didn’t work? Perhaps the docs can be updated to be made more clear. Improving raycast performance against complex geometry is the primary purpose of the extension.

Sorry for the delay, didn’t see the message right away.

global.THREE = require(‘three-full’);

global.BVH = require(‘three-mesh-bvh’);
THREE.BufferGeometry.prototype.computeBoundsTree = BVH.computeBoundsTree;
THREE.BufferGeometry.prototype.disposeBoundsTree = BVH.disposeBoundsTree;
THREE.Mesh.prototype.raycast = BVH.acceleratedRaycast;

and after function check

this.rayFloor.set(targetPos, new THREE.Vector3( 0, -1, 0 ) );
this.rayFloor.firstHitOnly = true;
this.rayFloor.intersectObject(obj, true);

global.THREE = require(‘three-full’);

I’m unfamiliar with “three-full” but it looks like it imports a completely different copy of three.js. three-mesh-bvh relies on the “three” package so I can’t guarantee that it works when using the “three-full” package. That aside it looks like it’s deprecated and is based on a fairly old version of three.js. Either way I’d recommend using the official three.js distribution.

this.rayFloor.set(targetPos, new THREE.Vector3( 0, -1, 0 ) );
this.rayFloor.firstHitOnly = true;
this.rayFloor.intersectObject(obj, true);

Having said that you do need to call computeBoundsTree before raycast performance can be improved, which I don’t see called in your above snippet. The BVH is not generated automatically on raycasting. You’ll need to add a line like this when generating your terrain geometry:

terrainMesh.geometry.computeBoundsTree( { lazyGeneration: false } );

Thank you very much, I will try, if everything is fine, then it will dump the load a little more.

Thank you very much yes it helped
→ geometry.computeBoundsTree ({lazyGeneration: false});

The load dropped to 5%, and it was about 22%.
Now I am thinking of making in one beam and a system of movement in geometry and contact with obstacles.


1 Like

Hi, I had a similar issue to you and came across this topic.

I put my terrain object on a specific layer.
I set my raycaster to only look at that layer number and saw huge performance gains!

raycaster.layers.set( 1 );
object.layers.enable( 1 );

Hope it helps :slight_smile:

1 Like