How to detect mesh intersections without collisions?

I’m trying to update the player’s coordinates when they move into a new part of my game’s grid, the grid is 20x20x20 blocks with most of them alpha=0 (eg air blocks) and then a “floor” of ground blocks with a texture (it’s going to be similar to minecraft).

So what I’ve done is put the air blocks and ground blocks into different collision groups, and then the player hitbox has the collision with the ground block group, which works fine. And I can detect the collisions as you move across the ground blocks with the following code…

  this.playerhitbox.onCollideObservable.add((d,s) => {
  console.log('collision with block: x=' + Math.floor(d.position.x / this.blockSize) + ' y= '  + Math.floor(d.position.y / this.blockSize) + ' z= '+ Math.floor(d.position.z / this.blockSize) )
});

So this seems fine but this is only detecting a collision between the “floor” block and the player mesh, if i allow collisions on the air blocks then they do trigger the event but you can’t move through them.

So how can i detect the intersection of the player mesh and the “air block” meshes without having it occur via a collision which blocks movement?

The intersectsMesh should give you what you want.

Hi JohnK, I was hoping that there would be some kind of event that fires when the meshes intersect, like there is when collisions are enabled, i’d really prefer not to have to check in a loop, maybe there’s some way of having collisions that don’t block movement?

This could be done using CannonJSPlugin (Use a Physics Engine - Babylon.js Documentation), setting your mesh’s mesh.physicsImpostor.physicsBody.collisionResponse = 0 (so your mesh can pass through other meshes), and then settings your events:

mesh.physicsImpostor.onCollideEvent = (self, other) => {
    
}

// or

mesh.physicsImpostor.registerOnPhysicsCollide(arrayOfPhysicsImposters, (self, other) => {
    
});

With blocks of size S form a 3D array 20 * 20 * 20, if block at (i, j, k) has ground block set to 1, 0 otherwise for a player at (x, y, z), for central start of blocks at origin, the player will be in block given by

i = 10 + Math.floor(x / S);
j = 10 + Math.floor(y / S);
k = 10 + Math.floor(z / S);

check if array value for i, j, k is 0 or 1;
depending on actual position of blocks relative to origin the 10 will need changing.

Thanks JohnK, i didn’t want to do it using that method because if you had a collision like say your player ran into a wall then the wall collision would hit the same event stream but the player wouldn’t be on top of it.

I’m trying to follow the instructions on that page but it is not working out so far, i can enable physics with

this.physicsPlugin = new CannonJSPlugin();
this.scene.enablePhysics(new Vector3(0,-9.81, 0), this.physicsPlugin);

but as soon as i try adding a physics imposter to the meshes the game starts to run really slow (like less than 1 fps / second)

const airMaterial = new StandardMaterial('air', this.scene);
airMaterial.alpha = 0;
thisBlock.material = airMaterial;
thisBlock.collisionGroup = CollisionGroup.Uno;
thisBlock.physicsImpostor = new PhysicsImpostor(thisBlock, PhysicsImpostor.BoxImpostor, { mass: 0, restitution: 0 }, this.scene);
thisBlock.physicsImpostor.physicsBody.collisionResponse = 0;
thisBlock.checkCollisions = true;

Ah, just saw you had 20^3 boxes. That may be too many physicsImpostors to run at a good FPS. As @JohnK mentioned, intersectsMesh with some bucketing algorithm seems promising for your use case

Oh ok, I was thinking about it and if there is a way i could tell which face of the mesh was collided with then if it was the top face i know it is “ground” (eg safe for a player to respawn there), so that’s one approach if I want to stick with just collisions on physical blocks.

The problem with trying to use intersectsMesh is that isn’t connected to an event, so I would have to link in to some other event or check on loop both of which aren’t really desirable, I have done some web development previously so I was just assuming there would be a 3d equivalent of like “mouseenter”, like I just need to know when the player mesh (or camera) has entered one of the air blocks, that would be better than ground collisions because you could track the players location even in freefall if it were independent of physical collisions.

Hi @erin_collective,

Have you tried the Action Manager feature?
https://doc.babylonjs.com/how_to/how_to_use_actions

I made this PG to show you an example with intersectionEnter/Exit triggers:
https://www.babylonjs-playground.com/#I5DXR6#1
(use the keyboard’s arrows to move the “player”)

4 Likes

Hi LeJohn, thanks, this works exactly like I want it to, was able to get air block intersection events using the action manager, now I need to figure out why my physics is broken, lol, but that’s a different issue.

1 Like