Optimize ray intersectsObjects

Hello everyone, I ran into the problem with many lags.
I found where most of the load goes, it’s Raycaster, the thing is that I use to render the collision from the bullets.

But the more objects the more lags, so here is the location in the game, the objects are all optimized and have a minimum of polygons.

Is it possible to somehow optimize the Raycaster?
For example, choose only those objects that can obviously fall under the ray, to be honest I do not know how Raycaster works)
If it is possible to somehow optimize more it would be cool :slight_smile:

Sure, you can split your scene via octree and for example cluster N objects per node, then you need to raycast the octree first and raycast the list of objects in a node if any.

According to your screenshot (if those are all objects) you shouldn’t already run into issues, as it first checks the bounding sphere, then bounding box, and only then starts to test each triangle.

But your screencap is probably only part of a larger scene with a lot more objects, and using the raycaster against the scene will at least bounding-sphere-test all objects in it, including those not visible.

It also depends how you actually use it, how many calls per frame?

I improved performance a little, there is no box for checking by default on all objects.

At loading geometry now I do: geometry.computeBoundingBox();

It got better, but still I want to optimize to the maximum, I’m trying to make a simple check, I found the code where it can be done.

if ( geometry.boundingBox !== null ) {
    if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
    //Here you can return a lie if you specify a simple check

But I ran into the problem, if the beginning of the beam is in the inside of the box, then the code for me is not correct.

The fact is that the player is surrounded by a certain protective sphere, the beginning of the ray occurs inside this sphere, therefore in the answer it constantly returns this sphere.

How can I check if the beam is inside the box?

I tried to check it this way

var point = new THREE.Vector3().setFromMatrixPosition(matrixWorld).sub(raycaster.ray.origin.clone()).divide(this.scale)
var inside = geometry.boundingBox.containsPoint(point);

if(inside) return;

But something still does not work :cry:

Depends on the number of players, each player has a firearm, so there are rockets that calculate each frame.

Yes the bounding sphere and bounding box should always be available.
The raycaster returns a array, sorted by distance of the intersected objects from near to far.

You could simply wrap the raycaster into a function you’ll loop through the result list and check e.g for a property “solid” (or the opposite) which you’ll set on each solid or non solid object. More consistent approach would be solid, maybe extend the prototype “THREE.Object3D.prototype.solid = false” for default.

In this loop you can filter those objects, if you only require the goal you can directly return the first solid one. How do you calculate the rockets, once or “march x units” per frame?

You might also analyze your code with the timeline, to ensure what the actual framerate drop causes.

There are few more things that can be improved, for example, i extended it for instancing, filter while raycast, and compound objects, for example when your player consists of multiple objects (weapon, player, armor) the first result within this hierarchy or a enclosing bounding sphere represents the result and stops from there. Also few minor things, like pooling the result list, but those things shouldn’t be necessary by default.

Edit: the filter (solid) method should be within the raycaster function of Object3D, if you want it to really skip the object, as the raycaster would still check them. A more simple approach to this solid check is to provide a separated list of collidable objects.

Anyway, if you use a octree you would’nt cast against the scene anway and you could just not track unwanted objects with the octree.

I was thinking of doing a simple check whether ray box crosses or not, then check whether this object is in the camera or not, if it means to continue and make a complex check.

But then I realized that it’s pointless, if the object is behind the camera, then there will be problems since bullets will pass through the object))

I revised all the code, I found places where can optimize even more, for example, instead of rendering all objects function (intersectObjects), It is better to use (intersectObject)


 var objects = this.raycaster.intersectObjects(this.obstructionObjects);

 if(objects.length > 0) return false;


for(var i = 0; i < this.obstructionObjects.length; i++){
    var object = this.obstructionObjects[i];
        return false;

As you said revised where you can put a delay in time, that would reduce the load)

The rockets are calculated in each frame, since they change the trajectory constantly.
Here probably I can also put a delay or calculate through each frame, I honestly do not know how I can optimize here)

Now everything suits me, the lag has become much smaller :slight_smile: