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