Jordumus
Jordumus

Reputation: 2783

Raycasting as collision detector: not accurate

I got a scene with multiple random forms (like triangles, trapezoids, but also more custom designs), and I'm trying to write the code for the collision detection. The shapes are all 2D and are location on Y=0

As the forms are more complicated than just circles and rectangles, I decided to use raycasting to check for collisions.

 var raycastCollision = function () {

        var originPoint = activeElement.position.clone();
        var vertices = activeElement.geometry.vertices;


        //loop
        for (var vertexIndex = 0; vertexIndex < vertices.length; vertexIndex++) {

            var localVertex = vertices[vertexIndex].clone();
            var globalVertex = localVertex.applyMatrix4(activeElement.matrix);
            var directionVector = globalVertex.sub(activeElement.position);

            var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize(),true);
            ray.ray.direction.y = 0;
            var collisionResults = ray.intersectObjects(elements);
            debug["ray" + vertexIndex] = ray;
            if (collisionResults.length > 0 && collisionResults[0].object != activeElement && collisionResults[0].distance < directionVector.length()) {

                debug["raycast detection"] = "HIT";
                break;
            }
        }
    }

ActiveElement is the current selected shape, and elements is the list of all shapes on scene.

The problem I have is that it only detects "hits" in certain situations, and I've not been able yet to pinpoint in what situations that is. But 1 thing is sure: it more often than not, doesn't detect a hit when it should.

Can anyone detect the error(s) in my code?

Edit: example pictures of a "no hit" and a "hit" situation hit

No hit

Upvotes: 1

Views: 693

Answers (1)

TOAOGG
TOAOGG

Reputation: 392

As my old answer is not correct, I removed it.

I tried your function on a test scene and the following solution works:

https://jsfiddle.net/qzL9L38a/

I guess the problem are the parallel faces in your case.

For spheres the following works:

var raycastCollision = function () {

var originPoint = spheres[0].position.clone();
var vertices = spheres[0].geometry.vertices;


//loop
for (var vertexIndex = 0; vertexIndex < vertices.length; vertexIndex++) {

    var localVertex = vertices[vertexIndex]; // no need to clone if applyMatrix4 won'T change localVertex.
    var globalVertex = localVertex.applyMatrix4(spheres[0].matrix);
    var directionVector = globalVertex.sub(originPoint);

    var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize(),true);
    var collisionResults = ray.intersectObjects(spheres);
    collisionResults = collisionResults.filter(function(element)
    {
      return element.distance < directionVector.length();                                         
    });
    if (collisionResults.length > 0 ) {

        console.log('HIT: '+collisionResults);
        break;
    }
}

}

Upvotes: 1

Related Questions