import { ARButton } from "https://threejs.org/examples/jsm/webxr/ARButton.js"; let television_floor, television_wall, television_screen; let projector_plane; let camera, scene, renderer, container; let controller, controls, camera_pos, screen_type; let reticle; let hitTestSource = null; let hitTestSourceRequested = false; init(); animate(); function init() { camera_pos = new THREE.Vector3(); container = document.createElement("div"); document.body.appendChild(container); scene = document.querySelector("a-scene").object3D; camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 20 ); //if it's television if(document.querySelector("#television_screen") != null){ television_screen = document.querySelector("#television_screen").object3D; television_screen.visible = false; screen_type = "television"; } else{ projector_plane = document.querySelector("#projector_plane").object3D; projector_plane.visible = false; screen_type = "projector"; } renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); renderer.xr.enabled = true; container.appendChild(renderer.domElement); document.body.appendChild( ARButton.createButton(renderer, { requiredFeatures: ["hit-test"] }) ); if(screen_type == "television"){ television_floor = document.querySelector("#television_floor").object3D; television_floor.visible = false; television_wall = document.querySelector("#television_wall").object3D; television_wall.visible = false; } function onSelect() { if (reticle.visible) { const material = new THREE.MeshPhongMaterial({ color: 0xffffff * Math.random(), }); const mesh = new THREE.Mesh(geometry, material); mesh.position.setFromMatrixPosition(reticle.matrix); mesh.scale.y = Math.random() * 2 + 1; var quat_angle = new THREE.Quaternion(); reticle.getWorldQuaternion(quat_angle); var euler_angle = new THREE.Euler().setFromQuaternion(quat_angle, "XYZ"); var video = document.querySelector("#video"); if (video != null) { video.load(); video.play(); } if (Math.abs(radians_to_degrees(euler_angle.x)) > 80) { //placed on the wall if(screen_type == "television"){ television_wall.visible = true; television_floor.visible = false; television_wall.rotation.x = euler_angle.x; television_wall.rotation.y = euler_angle.y; television_wall.rotation.z = euler_angle.z; television_wall.position.setFromMatrixPosition(reticle.matrix); television_wall.add(television_screen); television_screen.rotation.x = -1.5708; television_screen.position.x = 0; television_screen.position.y = 0.002; television_screen.position.z = 0; television_screen.visible = true; } else{ projector_plane.visible = true; projector_plane.rotation.x = euler_angle.x; projector_plane.rotation.y = euler_angle.y; projector_plane.rotation.z = euler_angle.z; projector_plane.rotateX(-1.5708); projector_plane.position.setFromMatrixPosition(reticle.matrix); } } else { //placed on the floor if(screen_type == "television"){ var television_pos = new THREE.Vector3(); television_floor.position.setFromMatrixPosition(reticle.matrix); television_floor.position.y -= 0.1; television_floor.visible = true; television_wall.visible = false; television_floor.updateMatrixWorld(); television_pos.setFromMatrixPosition(television_floor.matrixWorld); television_floor.lookAt(camera_pos.x, television_pos.y, camera_pos.z); television_floor.add(television_screen); television_screen.rotation.x = 0; television_screen.position.x = 0; television_screen.position.y = 0.048; television_screen.position.z = 0.002; television_screen.visible = true; } else{ var plane_pos = new THREE.Vector3(); projector_plane.position.setFromMatrixPosition(reticle.matrix); projector_plane.position.y -= 0.2; projector_plane.visible = true; projector_plane.updateMatrixWorld(); plane_pos.setFromMatrixPosition(projector_plane.matrixWorld); projector_plane.lookAt(camera_pos.x, plane_pos.y, camera_pos.z); projector_plane.rotateX(-1.5708); } } } } controller = renderer.xr.getController(0); controller.addEventListener("select", onSelect); scene.add(controller); reticle = new THREE.Mesh( new THREE.RingGeometry(0.15, 0.2, 32).rotateX(-Math.PI / 2), new THREE.MeshBasicMaterial() ); reticle.matrixAutoUpdate = false; reticle.visible = false; scene.add(reticle); const geometry = new THREE.CylinderGeometry(0.1, 0.1, 0.2, 32).translate( 0, 0, 0 ); window.addEventListener("resize", onWindowResize); } function move_toward_target() {} function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function radians_to_degrees(radians) { var pi = Math.PI; return radians * (180 / pi); } function animate() { renderer.setAnimationLoop(render); } function render(timestamp, frame) { camera_pos.setFromMatrixPosition(camera.matrixWorld); if (frame) { const referenceSpace = renderer.xr.getReferenceSpace(); const session = renderer.xr.getSession(); if (hitTestSourceRequested === false) { session.requestReferenceSpace("viewer").then(function (referenceSpace) { session .requestHitTestSource({ space: referenceSpace }) .then(function (source) { hitTestSource = source; }); }); session.addEventListener("end", function () { hitTestSourceRequested = false; hitTestSource = null; }); hitTestSourceRequested = true; } if (hitTestSource) { const hitTestResults = frame.getHitTestResults(hitTestSource); if (hitTestResults.length) { const hit = hitTestResults[0]; reticle.visible = true; reticle.matrix.fromArray(hit.getPose(referenceSpace).transform.matrix); } else { reticle.visible = false; } } } renderer.render(scene, camera); }