Three.js Camera Hit Test

The one of my project was wralk in 2018, real-time visualization on browsers and one of the problem was 360 degree hit test in scene. I figured it out this problem as I will explain in this post.

Here is demo and source code:

http://wralk.azmicirit.com/demo

http://wralk.azmicirit.com/villavr

https://github.com/azmicirit/wralk/blob/master/wralk.js

     prepareRotationMatrices: function () {
        let rotationMatrixF = new THREE.Matrix4();
        rotationMatrixF.makeRotationY(0);
        this.ROTATION_MATRICES.push(rotationMatrixF);

        let rotationMatrixB = new THREE.Matrix4();
        rotationMatrixB.makeRotationY(180 * Math.PI / 180);
        this.ROTATION_MATRICES.push(rotationMatrixB);

        let rotationMatrixL = new THREE.Matrix4();
        rotationMatrixL.makeRotationY(90 * Math.PI / 180);
        this.ROTATION_MATRICES.push(rotationMatrixL);

        let rotationMatrixR = new THREE.Matrix4();
        rotationMatrixR.makeRotationY((360 - 90) * Math.PI / 180);
        this.ROTATION_MATRICES.push(rotationMatrixR);

        let rotationMatrixU = new THREE.Matrix4();
        rotationMatrixU.makeRotationX(90 * Math.PI / 180);
        this.ROTATION_MATRICES.push(rotationMatrixU);

        let rotationMatrixD = new THREE.Matrix4();
        rotationMatrixD.makeRotationX((360 - 90) * Math.PI / 180);
        this.ROTATION_MATRICES.push(rotationMatrixD);
    },
    hitTest: function () {
        this.unlockAllDirections();
        for (let i = 0; i < 6; i++) {
            let cameraDirection = this.getDirection(new THREE.Vector3(0, 0, 0), this, (i > 3)).clone();
            let direction = cameraDirection.clone();
            direction.applyMatrix4(this.ROTATION_MATRICES[i]);
            let rayCaster = new THREE.Raycaster(this.getObject().position, direction, 0.1, 50);
            let intersects = rayCaster.intersectObjects(this.COLLIDABLE_OBJS);
            if (intersects.length > 0 && intersects[0].distance < this.HIT_DISTANCE) {
                this.lockDirectionByIndex(i);
            }
        }
    }

First of all we need to setup matrices (6 axis) for all around camera like a box: Up, Down, Left, Right, Front and Back.

call function prepareRotationMatrices();

call funtion hitTest(); every render cycle

Then get camera direction as Vector (3-D) to apply these matrices to test intersects.

direction.applyMatrix4(this.ROTATION_MATRICES[i]);

We will lock directions which vectors are.

this.HIT_DISTANCE = 150;

this.COLLIDABLE_OBJS = [];  // Only collidable objects can be intersected

let rayCaster = new THREE.Raycaster(this.getObject().position, direction, 0.1, 50);

let intersects = rayCaster.intersectObjects(this.COLLIDABLE_OBJS);

if (intersects.length > 0 && intersects[0].distance < this.HIT_DISTANCE) {

  this.lockDirectionByIndex(i);

}

‘this’ references to PointerLockControl. We can replace it with any Object3D.
this.getObject() // PointerLockController.js
https://threejs.org/examples/js/controls/PointerLockControls.js

https://threejs.org/docs/#api/en/core/Raycaster

 

azmi.cirit.wp

 

Leave a Reply

Your email address will not be published. Required fields are marked *