import { ARButton } from "https://threejs.org/examples/jsm/webxr/ARButton.js";

let glb_model;

let camera, scene, renderer, container;

let controller, controls, camera_pos, object_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 );

glb_model = document.querySelector("#glb_model").object3D; glb_model.visible = false; object_type = "glb_model"; 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"] }) );

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");

if (Math.abs(radians_to_degrees(euler_angle.x)) > 80) { //placed on the wall glb_model.visible = true; glb_model.rotation.x = euler_angle.x; glb_model.rotation.y = euler_angle.y; glb_model.rotation.z = euler_angle.z; glb_model.position.setFromMatrixPosition(reticle.matrix); }

else { //placed on the floor var model_pos = new THREE.Vector3(); glb_model.position.setFromMatrixPosition(reticle.matrix); glb_model.position.y -= 0.2; glb_model.visible = true; glb_model.updateMatrixWorld(); model_pos.setFromMatrixPosition(glb_model.matrixWorld); glb_model.lookAt(camera_pos.x, model_pos.y, camera_pos.z); } } }

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); }