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
