PepeW
PepeW

Reputation: 597

ThreeJS | Detect when an object leaves another object

I'm making a ThreeJS project in which I have planes (Object3D) flying inside a sphere (Mesh).

I'm trying to detect the collision between a plane and the border of the sphere so I can delete the plane and make it reappear at another place inside the sphere.

My question is how do I detect when an object leaves another object ?

The code I have now :

detectCollision(plane, sphere) {

  var boxPlane = new THREE.Box3().setFromObject(plane);
  boxPlane.applyMatrix4(plane.matrixWorld);

  var boxSphere = new THREE.Box3().setFromObject(sphere);
  boxSphere.applyMatrix4(sphere.matrixWorld);

  return boxPlane.intersectsBox(boxSphere);

}

In my render function :

var collision = this.detectCollision(plane, this.radar)
  if (collision == true) {
    console.log("the plane is inside the sphere")
  }
  else {
    console.log("the plane is outside the sphere")
  }
})

The problem is that when the planes are inside the sphere I get true and false basically all the time until all the planes leave the sphere. At that point I have a false and no more true.

Upvotes: 1

Views: 419

Answers (1)

M -
M -

Reputation: 28492

Box3 is not what you want to use to calculate sphere and plane collisions because the box won't respect the sphere's curvature, nor will it follow the plane's rotation.

Three.js has a class THREE.Sphere that is closer to what you need. Keep in mind that this class is not the same as a Mesh with a SphereGeometry, this is more of a math helper that doesn't render to the canvas. You can use its .containsPoint() method for what you need:

var sphereCalc = new THREE.Sphere( center, radius );
var point = new THREE.Vector3(10, 4, -6);

detectCollision() {
    var collided = sphereCalc.containsPoint(point);

    if (collided) {
        console.log("Point is in sphere");
    } else {
        console.log("No collision");
    }

    return collided;
}

You'll have to apply transforms and check all 4 points of each plane in a loop. Notice there's a Sphere.intersectsPlane() method that sounds like it would do this for you, but it's not the same because it uses an infinite plane to calculate the intersection, not one with a defined width and height, so don't use this.

Edit:

To clarify, each plane typically has 4 verts, so you'll have to check each vertex in a for() loop to see if the sphere contains each one of the 4 points.

Additionally, the plane will probably have been moved and rotated, so its original vertex positions will have a transform matrix applied to them. I think you were already taking this into account in your example, but it would be something like:

point.copy(vertex1);
point.applyMatrix4(plane.matrixWorld)
sphereCalc.containsPoint(point);

point.copy(vertex2);
point.applyMatrix4(plane.matrixWorld)
sphereCalc.containsPoint(point);

// ... and so on

Upvotes: 2

Related Questions