Jump to content

New properties; collisionGroup & collisionMask added to babylon collisions.


aWeirdo
 Share

Recommended Posts

Hi all,
 

Update - 17 / 02 

mesh.collisionGroup = maskNumber; have been added to AbstractMesh.

 

Two new properties, collisionGroup and collisionMask, have been added to AbstractMesh, collisionMask have been added to FreeCamera, and is coming with 2.6.
 

Why? What do they do?

The collisionGroup & collisionMask checks whether a camera Vs mesh or mesh Vs mesh collision should happen.
Thus, it allows us to customize collisions, enabling us to decide what meshes should collide with each other and which meshes should collide with the camera
An example could be to have collisions between the camera and a box aswell as the camera and a sphere, but no collision between the sphere and the box all at the same time.
 

Once it's live, it will work like this;

var group1 = 1; // x to the power of 2, starting from 1.
var group2 = 2; // 1*2 = 2
var group3 = 4; // 2*2 = 4
var group4 = 8; // 4*2 = 8, and so on.

// This mesh is part of the group1 collisionGroup, camera's and other (moving) meshes with group1 in their collisionMask will collide with this mesh.
mesh.collisionGroup = group1;

// While moving, this mesh will collide with other meshes which has either group1 or group2 as their collisionGroup
mesh.collisionMask = group1 + group2;

// While moving, the camera will collide with meshes which has either group1 or group2 as their collisionGroup
camera.collisionMask = group1 | group2; // doing group1 | group2 has the same effect as, but is less dynamic than, group1 + group2

 

You can also do; 

camera.collisionMask = group1; // Set mask to collide with group1.

camera.collisionMask += group2; // Set mask to also collide with group2.

camera.collisionMask -= group1; // Remove group1 from mask so we only collide with group2.

// Take careful note before using this method, to avoid issues, you must first override the default mask (-1) by doing cameraOrMesh.collisionMask = your_group_x_variable;

 

It is currently not available for webworkers.
 

Backwards compatibility,
If this isn't something that interests you, you're all good, nothing has changed.
 

Masks
Masks are numbers to the power of 2, starting from 1.

Special masks
  -1 ; Always collides.
   0 ; Never collides, overrides mask -1. // not recommended to use on camera with standard gravity applied.

Standard masks , x to the power of 2;  1 | 1*2 = 2 | 2*2 = 4 | 4*2 = 8 | 8*2 = 16 | etc.
   1  
   2 
   4 
   8 
 16 
    Etc

PG Example; 
The camera collides with the ground & box, but not with the sphere and the sphere and box doesn't collide with each other either.

http://www.babylonjs-playground.com/#20PQBI#43


Cheers.

If you have any questions, ideas or thoughts, please do continue the discussion below. :) 

Link to comment
Share on other sites

Thank you for this feature.

I have a hard time understanding everything.

If I want all the characters to collide with the objects in the scene, but not between them, which mask should I use?

If all my characters have a mask of 2, they will be in collision.

I have a function that create all my characters, so they have an identical mask, so we will collide with each other.

I have a hard time understanding how it works.

If I remember at the beginning, it was the identical masks that will not be in collision but collide with any lower value mask.

Link to comment
Share on other sites

hi @Dad72 
Sorry for my bad explaination, i will update it in a few minutes, i made it a lot harder than it have to be :) 

Okay, updated, you want objects to always collide, leave them at -1.

you want your npc's & players to never collide, give them a unique mask,

var nextMask = 1; //global variable

newPlayer.collisionMask = nextMask; //set unique mask

nextMask *= 2; //update nextMask

Link to comment
Share on other sites

At the moment, mask 0 overrides all masks and no collision at all happens, as if collisions where disabled for that mesh, because Math :P.

We could hard-code the mask 0 to not override -1,
so e.g. if mask is set to 0, you only collide with mask -1,

That would simplify the situation where you have a large group of meshes that shouldn't collide each other but should collide with other meshes like the ground mesh.

would need to get @Deltakosh thoughts on that though.

Link to comment
Share on other sites

I had imagined that the identical mask would not collide, but it will be with the mask of lower value. This is what you had done with the filters previously.

All the characters in my case will have an identical mask to their creation and will therefore collide with each other.

I understood better the method with the filters previously. Should not the identical mask not collide, but only with the asci of lower value?

Link to comment
Share on other sites

I was downvoted on that setup, 

For now, you can leave all objects, walls, floors & ground meshes at -1,

and just create a global mask variable, something like this;

var globalMask = .5; //first mask will be 1.

function getNewMask(){
return globalMask *=2;
}

function createPlayer(/* ... */){
    var newPlayer = playerMesh.clone('newPlayer');
        newPlayer.collisionMask = getNewMask();
}

 

Link to comment
Share on other sites

Your method is interesting, but I only create 1 character per computer (it's for a network game, so many characters on the scenes, but per customer), so this global variable will be the same for each client and will not be Do not increase unless I add it in a global file for everyone (I can get it, but that means that 1, 2, 4, 8, 16, 32, 64... will not collide with each other? )

Link to comment
Share on other sites

My vote is for collisionGroups + collisionMasks.  Then you can define your groups assign them to meshes and then apply a collisionMask to your meshes.

var group1 = 1;

var group2 = 2;

var group3 = 4;

mesh1.collisionGroup = group1;

mesh1.collisionMask = group1 | group3;  //mesh will collide with group1 and group3

mesh2.collisionGroup = group2;

mesh2.collisionMask = group1; //mesh only collides with group1

mesh3.collisionGroup = group3;

mesh3.collisionMask = group1 | group2;  //mesh collides with group1 and group2

 

Link to comment
Share on other sites

I'm not a big fan of the collisionGroup setup tbh,
it can quickly cause problems and turn into a situation like your example @adam
if mesh2 moves it collides with mesh1, but if mesh1 moves it doesn't collide with mesh2

If you guys really want collisionGroups, i do have a PR ready that will add them, 

but we can also turn around how the masks works.
so instead of same masks colliding with each other, same masks would instead ignore collisions.

so;

ground.collisionMask = 0; // always collides.

mesh1.collisionMask = group 1; //mesh1 collides with ground, mesh2 & mesh3.

mesh2.collisionMask = group 2; //mesh2 collides with ground & mesh1, but not with mesh3.

mesh3.collisionMask = group 2; //mesh3 collides with ground & mesh1, but not with mesh2.

http://www.babylonjs-playground.com/#20PQBI#31

Link to comment
Share on other sites

Both Oimo and Cannon use this pattern.  It just makes more sense to me to align with what other physics engines are doing.

Maybe some other people can chime in.

edit:

My quick and dirty example above was to just show flexibility and ease of use.

 

Link to comment
Share on other sites

@adam 
it would be nice being able to just mesh.collidesWith.push(thisOrThatGroup),
I've thought about doing something along those lines to allow more dynamic changes to what should collide.
but it would mean that we have to run another loop in the collision code for each single mesh to compare the groups, a short loop, but still a loop. :(

Link to comment
Share on other sites

21 minutes ago, aWeirdo said:

@adam 
it would be nice being able to just mesh.collidesWith.push(thisOrThatGroup),
I've thought about doing something along those lines to allow more dynamic changes to what should collide.
but it would mean that we have to run another loop in the collision code for each single mesh to compare the groups, a short loop, but still a loop. :(

I deleted that post, because I didn't want to overwhelm.   Since you commented on it, I'll try to recreate it:

 

Better yet, it would be cool if you could keep the numbers under the hood and do something like this:

mesh1.collisionGroup = "group1";

mesh1.collisionMask = ["group1", "group2"];

mesh2.collisionGroup = "group2";

mesh2.collisionMask = ["group1", "group3"];

mesh3.collisionGroup = "group3";

mesh3.collisionMask = ["group2", "group3"];

 

You wouldn't have to do a loop.  You could create getters and setters for collisionGroup and collisionMask.  You would be doing the same pattern I described above.  None of it (such us the power of 2 group numbers) would be exposed to the user.

 

Link to comment
Share on other sites

@adam 
 

I ment in the collision code itself, this is how it looks at the moment;

for (var index = 0; index < this._scene.meshes.length; index++) {
                var mesh = this._scene.meshes[index];
                if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh && ((collisionMask & mesh.collisionMask) !== 0)) {
                    mesh._checkCollision(collider);
                }
            }

if we turn the collider's collisionMask into an array, we would have to run another loop for each mesh inside the main loop

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...