for some reason the portal edge body is not set in exactly the position of the circle :  shoot(event) {
        this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
        this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

        this.raycaster.setFromCamera({ x: 0, y: 0 }, this.game.camera.instance)

        const intersects = this.raycaster.intersectObjects([
            this.plane, this.roof, this.scene.getObjectByName('backWall'),
            this.scene.getObjectByName('frontWall'), this.scene.getObjectByName('leftWall'),
            this.scene.getObjectByName('rightWall')
        ])

        if (intersects.length > 0) {
            const intersection = intersects[0]
            const object = intersection.object

            const geometry = new THREE.CircleGeometry(5, 32)
            const material = new THREE.MeshBasicMaterial({ color: 0x000000 })
            const circle = new THREE.Mesh(geometry, material)

            const portalSize = new THREE.Vector2(10, 15)
            const halfPortalSize = portalSize.clone().multiplyScalar(0.5)
            const wallSize = new THREE.Vector2(object.geometry.parameters.width, object.geometry.parameters.height)
            const halfWallSize = wallSize.clone().multiplyScalar(0.5)

            let localPosition = this.worldToLocal(object, intersection.point)

            localPosition.x = THREE.MathUtils.clamp(localPosition.x, -halfWallSize.x + halfPortalSize.x, halfWallSize.x - halfPortalSize.x)
            localPosition.y = THREE.MathUtils.clamp(localPosition.y, -halfWallSize.y + halfPortalSize.y, halfWallSize.y - halfPortalSize.y)

            const validPoint = this.localToWorld(object, localPosition)

            circle.position.copy(validPoint)
            circle.rotation.copy(object.rotation)
            circle.scale.y = 1.5

            circle.position.addScaledVector(circle.getWorldDirection(new THREE.Vector3()), 0.01)
            this.boxBody = new CANNON.Body({
                collisionFilterGroup: GROUP_PORTAL,
                collisionFilterMask: GROUP_WALL | GROUP_DEFAULT | GROUP_CUBE | GROUP_PLAYER,
            })
            this.boxBody.mass = 0
            this.boxBody.material = this.defaultMaterial
            this.boxBody.collisionResponse = false
            this.boxBody.addShape(new CANNON.Box(new CANNON.Vec3(3.34, 5, 1.5)))
            this.boxBody.quaternion.copy(circle.quaternion)
            this.boxBody.position.copy(circle.position)
            this.boxBody.class = 'portal'
            this.boxBody.object = intersects[0].object

            
            this.portalEdgeBody = new CANNON.Body({
                collisionFilterGroup: GROUP_DEFAULT,
                collisionFilterMask: GROUP_PLAYER,
                mass: 0,
                material: this.defaultMaterial,
            });
            
            // Position and orient the portal edge body
            this.portalEdgeBody.position.copy(circle.position);
            this.portalEdgeBody.quaternion.copy(circle.quaternion);
            
            this.portalEdgeBody.addShape(new CANNON.Box(new CANNON.Vec3(3.34, 0.1, 5)), new CANNON.Vec3(0, -5, 0));

            this.physics.addBody(this.portalEdgeBody)

            // Keep a reference to the portal edge body
            circle.portalEdgeBody = this.portalEdgeBody;

            let intersectionDetected = false
            if (event.button === 0) {
                this.rightPortal.forEach((rightPortal) => {
                    if (this.boxBody.object === rightPortal.physicObject.object && this.detectIntersection(this.boxBody, rightPortal.physicObject)) {
                        intersectionDetected = true
                    }
                })
            } else if (event.button === 2) {
                this.leftPortal.forEach((leftPortal) => {
                    if (this.boxBody.object === leftPortal.physicObject.object && this.detectIntersection(this.boxBody, leftPortal.physicObject)) {
                        intersectionDetected = true
                    }
                })
            }

            if (intersectionDetected) {
                return
            }

            this.physics.addBody(this.boxBody)
            circle.physicObject = this.boxBody

            const geometry1 = new THREE.PlaneGeometry(19, 19)
            let materialPortal

            if (event.button === 0) {
                this.materialBlue = new THREE.ShaderMaterial({
                    uniforms: {
                        iResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
                        iTime: { value: 0 }
                    },
                    vertexShader: document.getElementById('vertexShader').textContent,
                    fragmentShader: document.getElementById('fragmentShaderOrange').textContent
                })
                materialPortal = this.materialBlue
                this.boxBody.ref = 'left'
                this.leftPortal.push(circle)
            } else if (event.button === 2) {
                this.materialOrange = new THREE.ShaderMaterial({
                    uniforms: {
                        iResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
                        iTime: { value: 0 }
                    },
                    vertexShader: document.getElementById('vertexShader').textContent,
                    fragmentShader: document.getElementById('fragmentShaderBlue').textContent
                })
                materialPortal = this.materialOrange
                this.boxBody.ref = 'right'
                this.rightPortal.push(circle)
            }

            const planePortal = new THREE.Mesh(geometry1, materialPortal)
            planePortal.position.copy(circle.position)
            planePortal.rotation.copy(circle.rotation)
            planePortal.position.addScaledVector(circle.getWorldDirection(new THREE.Vector3()), 0.01)

            this.scene.add(planePortal)
            circle.torus = planePortal
        }
    }