Shashank Chaurasia
Shashank Chaurasia

Reputation: 141

three js Collision detection in group (THREE.Group)

I am working on 3D AABB collisions detection for box and sphere.

If box is directly added to scene then collision is detected but if its added in a group (THREE.Group) and rotated, then collision is not detected.

This is the code to add box

function addPlatforms() {

    var coreGroup = new THREE.Group(); // this is the group
    scene.add(coreGroup);

    var box = [];

    cube_box1 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
    box.push(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid));
    box[0].position.set(-1.83, -0.22, 1.11);
    box[0].rotation.x += Math.PI / 2;
    box[0].rotation.z -= 0.78;
    box[0].receiveShadow = true;


    cube_box2 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
    box.push(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid));
    box[1].position.set(-2.15, -0.22, 0.51);
    box[1].rotation.x += Math.PI / 2;
    box[1].receiveShadow = true;

    var platGroup = new THREE.Group();
    platGroup.add(box[0]);
    platGroup.add(box[1]);
    platGroup.rotation.y -= 2;
    platGroup.position.y  = 1;

    coreGroup.add(platGroup);


    cube_box1.setFromObject(box[0]);
    platformArr.push(cube_box1);

    cube_box2.setFromObject(box[1]);
    platformArr.push(cube_box2);
}

Code to get Collision between box and sphere.

Visit https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_collision_detection/Bounding_volume_collision_detection_with_THREE.js

THREE.Sphere.__closest = new THREE.Vector3();
THREE.Sphere.prototype.intersectsBox = function(box) {
    // get box closest point to sphere center by clamping
    THREE.Sphere.__closest.set(this.center.x, this.center.y, this.center.z);
    THREE.Sphere.__closest.clamp(box.min, box.max);

    var distance = this.center.distanceToSquared(THREE.Sphere.__closest);
    return distance < (this.radius * this.radius);
};

function isCollision() {
    for (var i = 0; i < platformArr.length; i++) {
        _cubeBox = platformArr[i];
        return sphereBox.intersectsBox(_cubeBox);
    }
}

This is how sphere is added

function addBall(){

    sphere = new THREE.Mesh(
        new THREE.SphereGeometry(0.19, 20, 20), materials.solid);
    sphere.position.set(0, 1, -2);
    sphere.geometry.computeBoundingSphere();
    scene.add(sphere);

    sphereBox = new THREE.Sphere(sphere.position, sphere.geometry.boundingSphere.radius);
    sphereBox.radius = sphere.geometry.boundingSphere.radius;

    cy = sphere.position.y;
}  

Logic to render

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);

    if (collision) { // ball is on surface
        vy = -vy;
        collision = false;
    }

    cy -= vy * dt;

    sphere.position.y = cy;

    if (vy <= mvy)
        vy += gravity;

    collision = isCollision();
}

If a box is added to scene and collision is detected with sphere then its working. Ex - Create a simple box and change some properties like rotation and position

var _box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0.2), materials.solid);
_box.position.set(-1.83, -0.22, 1.11);
_box.rotation.x += Math.PI / 2;
_box.rotation.z -= 0.78;
_box.receiveShadow = true;

Then find the collision in animate update

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);

    if (collision) { // ball is on surface
        vy = -vy;
        collision = false;
    }

    cy -= vy * dt;

    sphere.position.y = cy;

    if (vy <= mvy)
        vy += gravity;

    collision = sphereBox.intersectsBox(_box);
}

Upvotes: 0

Views: 1149

Answers (1)

Brakebein
Brakebein

Reputation: 2237

By default, the object's world matrix will be updated every frame. You are instantiating these boxes, transforming, and adding them to the group. Then you instantly call cube_box1.setFromObject(box[0]);, which uses matrixWorld internally. But the world matrices of the boxes are not set yet. You can wait a frame to let the matrices to be computed automatically, or you have to trigger matrix updates manually:

//... your code ...
coreGroup.add(platGroup);

coreGroup.updateMatrixWorld( true );

cube_box1.setFromObject(box[0]);
platformArr.push(cube_box1);
//... your code ...

Three.js Docs Matrix Transformations

When either the parent or the child object's transformation changes, you can request that the child object's matrixWorld be updated by calling updateMatrixWorld().

Three.js Docs Object3D

.matrixAutoUpdate : Boolean

When this is set, it calculates the matrix of position, (rotation or quaternion) and scale every frame and also recalculates the matrixWorld property. Default is Object3D.DefaultMatrixAutoUpdate (true).

Upvotes: 1

Related Questions