"Masked" zones in random-object-populated world

Hello everyone!

I am working on a scene (https://playcanvas.com/editor/scene/991455) where I want to spawn clones of entities in a random manner in relatively large areas. But also, within those large areas I want to specify some parts where i DONT want clones to be spawned.

I ended up attaching rigidbodies and collisions to clones and “mask areas” to detect the presence of unwanted entities in those “masked areas” and destroying them.
However, this approach got me in a little bit of trouble, as I cant seem to destroy that “mask area” until all entities have been initialized and the collisions have been processed. So I ended up destroing it in the update function, which looks a bit clumsy and I am sure its not good practice.

Also I am concerned about performance issues. I made 800 clones with rigidbody components calculating collisions and in the end of the day I might need 0 of them to actually have rigidbody behaviour in my game.

Also this whole approach seems quite messy. Can you think of other approaches to the same problem? How would you go about it?

Thanks in advance!

Hi @Francisco_Bozzo and welcome,

Good thinking using mask entities in editor to define areas that should not allow any spawning. But as you found out to save performance you shouldn’t be using physics, rigid bodies.

You can still use the collision boxes with custom pc.BoundingBox instances to check in your spawn loop if the next point is allowed or not. So you don’t go through the trouble of spawning and then checking collisions (that is slow).

// sample code
var maskAabb = new pc.BoundingBox(this.maskEntity.getPosition(), this.maskEntity.collision.halfExtents);

// in your spawn loop
for (var j = 0; j < this.templates.length; j++) {

   var spawnPos = ...; // calculate the next spawn pos

   // check if it's valid or in the masked area
   if( maskAabb.containsPoint(spawnPos) === true){
      continue;
   } 
}
2 Likes

Note that you don’t have to have rigidbodies if all your are doing is raycasting so that will save on the simulation cost. Just collisions are enough IIRC.

You can also basic sphere/box checks when placing instead if you don’t wan’t any physics components at all.

1 Like

HI, Leonidas, thanks for the reply,

that makes complete total sense! I haven´t come across with pc.BoundingBox before, it seems perfect for my intentions.

1 Like

I have just re-wrote the code using BoundingBox, it does the job perfectly.

thanks @Leonidas and @yaustar for helping

2 Likes

I’ve been testing this a bit, and I found some issues when trying to “merge” multiple Aabb’s. First of all I noticed that the aabb.add() method doesn’t combine aabb’s (which is what I was trying to do) it actually does some kind of vectorial sum, right? But it’s been also kind of hard to debug because when console logging the aabb’s, I got the following:

the green area is aabb1, the red area is aabb2 and the blue area is a visualization of the result of adding them.

CloneManager.prototype.initialize = function() {
    
    var aabb1 = new pc.BoundingBox(this.aabb1.getPosition(), this.aabb1.getLocalScale()/2);
    var aabb2 = new pc.BoundingBox(this.aabb2.getPosition(), this.aabb2.getLocalScale()/2);
    
    console.log("aabb1 before adding" , aabb1);
    console.log("aabb2 before adding" , aabb2);
    aabb1.add(aabb2);
    console.log("aabb1 after adding" , aabb1);
    console.log("aabb2 after adding" ,aabb2);

//do testing to decide whether or not to place a cloned entity.
}

notice the first console log shows the “already-added up” values, although it was called in a higher line.

This is the link for the project https://playcanvas.com/editor/scene/991455

The result that I was expecting was to “combine” or “merge” multiple aabb’s. Is this possible? I am thinking about evaluating for each of them in a loop.

Hi @Francisco_Bozzo,

The aabb.add() will find the total new aabb that contains the two smaller ones. There isn’t a method to just merge or combine two aabb shapes.

But I think you don’t need that, you can in your spawn loop, run a smaller loop to check if the pos is included in any aabb in your list.

// array that includes all aabb shapes
var maskAabbList = [...]

// in your spawn loop
SpawnLoop:
for (var j = 0; j < this.templates.length; j++) {

   var spawnPos = ...; // calculate the next spawn pos

   // check if it's valid or in the masked area
   for (var i = 0; i < maskAabbList.length; i++) {
      if( maskAabbList[i].containsPoint(spawnPos) === true){
         continue SpawnLoop;
      } 
   }
}
1 Like

Thanks for the reply! I ended up writing something like this

//arrat that includes all aabb boxes
this.boxes = [...]

if (!this.boxes.some(this.maskCheck, this)) {
                do the cloning
}

And this worked just fine.

But still I can’t understand why am I getting that strange result when adding the BoundingBoxes I posted before. As well as the console logging issue.

So, console.log() will print a reference to an object, meaning it’s not really before/after but it will be just a reference to this object.

if the object changes, then the before output will be updated as well, hence why you see the same values for aabb1, you see only the after.