I am making a simple three.js game where the user controls a spaceship called playerModel (a Mesh obj with a simple BoxGeometry), and must avoid asteroids (SphereGeometry) which are generated far off in the -Z direction and move in the +Z direction towards the ship.

This is my detectCollisions function:

// Returns true if playerModel is intersecting with 
// any of obstacles, false otherwise.
function detectCollisions(obstacles) {
    var origin = playerModel.position.clone();

    for (var v = 0; v < playerModel.geometry.vertices.length; v++) {       
        var localVertex = playerModel.geometry.vertices[v].clone();
        var globalVertex = localVertex.applyMatrix4(playerModel.matrix);
        var directionVector = globalVertex.sub(playerModel.position);

        var ray = new THREE.Raycaster(origin, directionVector.clone().normalize());
        var intersections = ray.intersectObjects(obstacles);
        if (intersections.length > 0 && 
            intersections[0].distance < directionVector.length()) {
            console.log("Fatal collision!");    // definitely a collision
            return true;
          }
    }
    return false;
}  

I call this method in the game loop as follows, where "spheres" is the array of asteroids:

function draw() {   
    // loop draw function call
    requestAnimationFrame(draw);
    // draw THREE.JS scene
    renderer.render(scene, camera);

    if (!isGameOver) {
        generateSpheres();
        handleKey();  // updates player direction
        movePlayer(); // moves player in direction
        moveSpheres();
        if (detectCollisions(spheres))
            gameOver();
    }
}

This is 'working' in the sense that it detects intersections and calls the gameOver function when it does so, but it is detecting collisions that, visually, are not even close to being collisions. The ray.intersectObjects method seems to return intersections whose distance is calculated as quite close (something like 10), even though the position of the asteroid object it is supposedly intersecting with is very far (position is something like: x:-872 y:-331 z:-5940) from the playerModel which is at (0, 0, 50).

It also seems like the intersecting asteroid object causing the fatal collision always has faceIndex 37, not sure why. The asteroids are created with rings and segments == 7 and varying radii between 20 and 150. The playerModel is fairly small (w:15, h:15, d:30). Thanks so much in advance for any help!

1

There are 1 best solutions below

1
On

Maybe it's the BoundingSphere but this can only be a problem if the Object change the size (without scale).

Object.Model.geometry.computeBoundingSphere();

BoundingSphere

But I don't think this is the solution for your Problem. Can you upload an jsfiddle please?