Commit 48a8afca authored by Alfakhori's avatar Alfakhori
Browse files

Update public/2-Hit.html, public/1-Cube.html, public/page2.html

Deleted public/build/aframe-ar-location-only.js, public/build/aframe-ar-new-location-only.js, public/build/aframe-ar-nft.js, public/build/aframe-ar.js, public/build/ar-threex-location-only.js, public/app.js
parent c4777486
Pipeline #7416 passed with stage
in 9 seconds
/*
* Copyright 2017 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Query for WebXR support. If there's no support for the `immersive-ar` mode,
* show an error.
*/
(async function() {
const isArSessionSupported = navigator.xr && navigator.xr.isSessionSupported && await navigator.xr.isSessionSupported("immersive-ar");
if (isArSessionSupported) {
document.getElementById("enter-ar").addEventListener("click", window.app.activateXR)
} else {
onNoXRDevice();
}
})();
/**
* Container class to manage connecting to the WebXR Device API
* and handle rendering on every frame.
*/
class App {
/**
* Run when the Start AR button is pressed.
*/
activateXR = async () => {
try {
// Initialize a WebXR session using "immersive-ar".
this.xrSession = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ['hit-test', 'dom-overlay'],
domOverlay: { root: document.body }
});
// Create the canvas that will contain our camera's background and our virtual scene.
this.createXRCanvas();
// With everything set up, start the app.
await this.onSessionStarted();
} catch(e) {
console.log(e);
onNoXRDevice();
}
}
/**
* Add a canvas element and initialize a WebGL context that is compatible with WebXR.
*/
createXRCanvas() {
this.canvas = document.createElement("canvas");
document.body.appendChild(this.canvas);
this.gl = this.canvas.getContext("webgl", {xrCompatible: true});
this.xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(this.xrSession, this.gl)
});
}
/**
* Called when the XRSession has begun. Here we set up our three.js
* renderer, scene, and camera and attach our XRWebGLLayer to the
* XRSession and kick off the render loop.
*/
onSessionStarted = async () => {
// Add the `ar` class to our body, which will hide our 2D components
document.body.classList.add('ar');
// To help with working with 3D on the web, we'll use three.js.
this.setupThreeJs();
// Setup an XRReferenceSpace using the "local" coordinate system.
this.localReferenceSpace = await this.xrSession.requestReferenceSpace('local');
// Create another XRReferenceSpace that has the viewer as the origin.
this.viewerSpace = await this.xrSession.requestReferenceSpace('viewer');
// Perform hit testing using the viewer as origin.
this.hitTestSource = await this.xrSession.requestHitTestSource({ space: this.viewerSpace });
// Start a rendering loop using this.onXRFrame.
this.xrSession.requestAnimationFrame(this.onXRFrame);
this.xrSession.addEventListener("select", this.onSelect);
}
/** Place a sunflower when the screen is tapped. */
onSelect = () => {
if (window.sunflower) {
const clone = window.sunflower.clone();
clone.position.copy(this.reticle.position);
this.scene.add(clone)
const shadowMesh = this.scene.children.find(c => c.name === 'shadowMesh');
shadowMesh.position.y = clone.position.y;
}
}
/**
* Called on the XRSession's requestAnimationFrame.
* Called with the time and XRPresentationFrame.
*/
onXRFrame = (time, frame) => {
// Queue up the next draw request.
this.xrSession.requestAnimationFrame(this.onXRFrame);
// Bind the graphics framebuffer to the baseLayer's framebuffer.
const framebuffer = this.xrSession.renderState.baseLayer.framebuffer
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer)
this.renderer.setFramebuffer(framebuffer);
// Retrieve the pose of the device.
// XRFrame.getViewerPose can return null while the session attempts to establish tracking.
const pose = frame.getViewerPose(this.localReferenceSpace);
if (pose) {
// In mobile AR, we only have one view.
const view = pose.views[0];
const viewport = this.xrSession.renderState.baseLayer.getViewport(view);
this.renderer.setSize(viewport.width, viewport.height)
// Use the view's transform matrix and projection matrix to configure the THREE.camera.
this.camera.matrix.fromArray(view.transform.matrix)
this.camera.projectionMatrix.fromArray(view.projectionMatrix);
this.camera.updateMatrixWorld(true);
// Conduct hit test.
const hitTestResults = frame.getHitTestResults(this.hitTestSource);
// If we have results, consider the environment stabilized.
if (!this.stabilized && hitTestResults.length > 0) {
this.stabilized = true;
document.body.classList.add('stabilized');
}
if (hitTestResults.length > 0) {
const hitPose = hitTestResults[0].getPose(this.localReferenceSpace);
// Update the reticle position
this.reticle.visible = true;
this.reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z)
this.reticle.updateMatrixWorld(true);
}
// Render the scene with THREE.WebGLRenderer.
this.renderer.render(this.scene, this.camera)
}
}
/**
* Initialize three.js specific rendering code, including a WebGLRenderer,
* a demo scene, and a camera for viewing the 3D content.
*/
setupThreeJs() {
// To help with working with 3D on the web, we'll use three.js.
// Set up the WebGLRenderer, which handles rendering to our session's base layer.
this.renderer = new THREE.WebGLRenderer({
alpha: true,
preserveDrawingBuffer: true,
canvas: this.canvas,
context: this.gl
});
this.renderer.autoClear = false;
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Initialize our demo scene.
this.scene = DemoUtils.createLitScene();
this.reticle = new Reticle();
this.scene.add(this.reticle);
// We'll update the camera matrices directly from API, so
// disable matrix auto updates so three.js doesn't attempt
// to handle the matrices independently.
this.camera = new THREE.PerspectiveCamera();
this.camera.matrixAutoUpdate = false;
}
};
window.app = new App();
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("aframe"),require("three")):"function"==typeof define&&define.amd?define(["aframe","three"],e):"object"==typeof exports?exports.ARjs=e(require("aframe"),require("three")):t.ARjs=e(t.AFRAME,t.THREE)}(this,((t,e)=>(()=>{"use strict";var i={223:e=>{e.exports=t},381:t=>{t.exports=e}},o={};function n(t){var e=o[t];if(void 0!==e)return e.exports;var s=o[t]={exports:{}};return i[t](s,s.exports,n),s.exports}n.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};return(()=>{n.r(s);var t=n(223),e=n(381);const i=function(t){var i=this;this.object=t,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation={},this.screenOrientation=0,this.alphaOffset=0,this.smoothingFactor=1,this.TWO_PI=2*Math.PI,this.HALF_PI=.5*Math.PI;var o,n,s,a,r=function(t){i.deviceOrientation=t},d=function(){i.screenOrientation=window.orientation||0},c=(o=new e.Vector3(0,0,1),n=new e.Euler,s=new e.Quaternion,a=new e.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),function(t,e,i,r,d){n.set(i,e,-r,"YXZ"),t.setFromEuler(n),t.multiply(a),t.multiply(s.setFromAxisAngle(o,-d))});this.connect=function(){d(),window.addEventListener("orientationchange",d,!1),window.addEventListener("deviceorientation",r,!1),i.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",d,!1),window.removeEventListener("deviceorientation",r,!1),i.enabled=!1},this.update=function(){if(!1!==i.enabled){var t=i.deviceOrientation;if(t){var o=t.alpha?e.MathUtils.degToRad(t.alpha)+i.alphaOffset:0,n=t.beta?e.MathUtils.degToRad(t.beta):0,s=t.gamma?e.MathUtils.degToRad(t.gamma):0,a=i.screenOrientation?e.MathUtils.degToRad(i.screenOrientation):0,r=this.smoothingFactor;this.lastOrientation?(o=this._getSmoothedAngle(o,this.lastOrientation.alpha,r),n=this._getSmoothedAngle(n+Math.PI,this.lastOrientation.beta,r),s=this._getSmoothedAngle(s+this.HALF_PI,this.lastOrientation.gamma,r,Math.PI)):(n+=Math.PI,s+=this.HALF_PI),this.lastOrientation={alpha:o,beta:n,gamma:s},c(i.object.quaternion,o,n-Math.PI,s-this.HALF_PI,a)}}},this._orderAngle=function(t,e,i=this.TWO_PI){return e>t&&Math.abs(e-t)<i/2||t>e&&Math.abs(e-t)>i/2?{left:t,right:e}:{left:e,right:t}},this._getSmoothedAngle=function(t,e,i,o=this.TWO_PI){const n=this._orderAngle(t,e,o),s=n.left,a=n.right;n.left=0,n.right-=s,n.right<0&&(n.right+=o);let r=a==e?(1-i)*n.right+i*n.left:i*n.right+(1-i)*n.left;return r+=s,r>=o&&(r-=o),r},this.dispose=function(){i.disconnect()},this.connect()};var o,a=Math.PI/2;t.registerComponent("arjs-look-controls",{dependencies:["position","rotation"],schema:{enabled:{default:!0},magicWindowTrackingEnabled:{default:!0},pointerLockEnabled:{default:!1},reverseMouseDrag:{default:!1},reverseTouchDrag:{default:!1},touchEnabled:{default:!0},smoothingFactor:{type:"number",default:1}},init:function(){this.deltaYaw=0,this.previousHMDPosition=new THREE.Vector3,this.hmdQuaternion=new THREE.Quaternion,this.magicWindowAbsoluteEuler=new THREE.Euler,this.magicWindowDeltaEuler=new THREE.Euler,this.position=new THREE.Vector3,this.magicWindowObject=new THREE.Object3D,this.rotation={},this.deltaRotation={},this.savedPose=null,this.pointerLocked=!1,this.setupMouseControls(),this.bindMethods(),this.previousMouseEvent={},this.setupMagicWindowControls(),this.savedPose={position:new THREE.Vector3,rotation:new THREE.Euler},this.el.sceneEl.is("vr-mode")&&this.onEnterVR()},setupMagicWindowControls:function(){var e,o=this.data;t.utils.device.isMobile()&&(e=this.magicWindowControls=new i(this.magicWindowObject),"undefined"!=typeof DeviceOrientationEvent&&DeviceOrientationEvent.requestPermission&&(e.enabled=!1,this.el.sceneEl.components["device-orientation-permission-ui"].permissionGranted?e.enabled=o.magicWindowTrackingEnabled:this.el.sceneEl.addEventListener("deviceorientationpermissiongranted",(function(){e.enabled=o.magicWindowTrackingEnabled}))))},update:function(t){var e=this.data;e.enabled!==t.enabled&&this.updateGrabCursor(e.enabled),t&&!e.magicWindowTrackingEnabled&&t.magicWindowTrackingEnabled&&(this.magicWindowAbsoluteEuler.set(0,0,0),this.magicWindowDeltaEuler.set(0,0,0)),this.magicWindowControls&&(this.magicWindowControls.enabled=e.magicWindowTrackingEnabled,this.magicWindowControls.smoothingFactor=e.smoothingFactor),t&&!e.pointerLockEnabled!==t.pointerLockEnabled&&(this.removeEventListeners(),this.addEventListeners(),this.pointerLocked&&this.exitPointerLock())},tick:function(t){this.data.enabled&&this.updateOrientation()},play:function(){this.addEventListeners()},pause:function(){this.removeEventListeners(),this.pointerLocked&&this.exitPointerLock()},remove:function(){this.removeEventListeners(),this.pointerLocked&&this.exitPointerLock()},bindMethods:function(){this.onMouseDown=t.utils.bind(this.onMouseDown,this),this.onMouseMove=t.utils.bind(this.onMouseMove,this),this.onMouseUp=t.utils.bind(this.onMouseUp,this),this.onTouchStart=t.utils.bind(this.onTouchStart,this),this.onTouchMove=t.utils.bind(this.onTouchMove,this),this.onTouchEnd=t.utils.bind(this.onTouchEnd,this),this.onEnterVR=t.utils.bind(this.onEnterVR,this),this.onExitVR=t.utils.bind(this.onExitVR,this),this.onPointerLockChange=t.utils.bind(this.onPointerLockChange,this),this.onPointerLockError=t.utils.bind(this.onPointerLockError,this)},setupMouseControls:function(){this.mouseDown=!1,this.pitchObject=new THREE.Object3D,this.yawObject=new THREE.Object3D,this.yawObject.position.y=10,this.yawObject.add(this.pitchObject)},addEventListeners:function(){var e=this.el.sceneEl,i=e.canvas;i?(i.addEventListener("mousedown",this.onMouseDown,!1),window.addEventListener("mousemove",this.onMouseMove,!1),window.addEventListener("mouseup",this.onMouseUp,!1),i.addEventListener("touchstart",this.onTouchStart),window.addEventListener("touchmove",this.onTouchMove),window.addEventListener("touchend",this.onTouchEnd),e.addEventListener("enter-vr",this.onEnterVR),e.addEventListener("exit-vr",this.onExitVR),this.data.pointerLockEnabled&&(document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),document.addEventListener("mozpointerlockchange",this.onPointerLockChange,!1),document.addEventListener("pointerlockerror",this.onPointerLockError,!1))):e.addEventListener("render-target-loaded",t.utils.bind(this.addEventListeners,this))},removeEventListeners:function(){var t=this.el.sceneEl,e=t&&t.canvas;e&&(e.removeEventListener("mousedown",this.onMouseDown),window.removeEventListener("mousemove",this.onMouseMove),window.removeEventListener("mouseup",this.onMouseUp),e.removeEventListener("touchstart",this.onTouchStart),window.removeEventListener("touchmove",this.onTouchMove),window.removeEventListener("touchend",this.onTouchEnd),t.removeEventListener("enter-vr",this.onEnterVR),t.removeEventListener("exit-vr",this.onExitVR),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1),document.removeEventListener("mozpointerlockchange",this.onPointerLockChange,!1),document.removeEventListener("pointerlockerror",this.onPointerLockError,!1))},updateOrientation:(o=new THREE.Matrix4,function(){var t,e=this.el.object3D,i=this.pitchObject,n=this.yawObject,s=this.el.sceneEl;s.is("vr-mode")&&s.checkHeadsetConnected()?s.hasWebXR&&(t=s.renderer.xr.getCameraPose())&&(o.elements=t.transform.matrix,o.decompose(e.position,e.rotation,e.scale)):(this.updateMagicWindowOrientation(),e.rotation.x=this.magicWindowDeltaEuler.x+i.rotation.x,e.rotation.y=this.magicWindowDeltaEuler.y+n.rotation.y,e.rotation.z=this.magicWindowDeltaEuler.z)}),updateMagicWindowOrientation:function(){var t=this.magicWindowAbsoluteEuler,e=this.magicWindowDeltaEuler;this.magicWindowControls&&this.magicWindowControls.enabled&&(this.magicWindowControls.update(),t.setFromQuaternion(this.magicWindowObject.quaternion,"YXZ"),this.previousMagicWindowYaw||0===t.y||(this.previousMagicWindowYaw=t.y),this.previousMagicWindowYaw&&(e.x=t.x,e.y+=t.y-this.previousMagicWindowYaw,e.z=t.z,this.previousMagicWindowYaw=t.y))},onMouseMove:function(t){var e,i,o,n=this.pitchObject,s=this.previousMouseEvent,r=this.yawObject;this.data.enabled&&(this.mouseDown||this.pointerLocked)&&(this.pointerLocked?(i=t.movementX||t.mozMovementX||0,o=t.movementY||t.mozMovementY||0):(i=t.screenX-s.screenX,o=t.screenY-s.screenY),this.previousMouseEvent.screenX=t.screenX,this.previousMouseEvent.screenY=t.screenY,e=this.data.reverseMouseDrag?1:-1,r.rotation.y+=.002*i*e,n.rotation.x+=.002*o*e,n.rotation.x=Math.max(-a,Math.min(a,n.rotation.x)))},onMouseDown:function(t){var e=this.el.sceneEl;if(!(!this.data.enabled||e.is("vr-mode")&&e.checkHeadsetConnected())&&0===t.button){var i=e&&e.canvas;this.mouseDown=!0,this.previousMouseEvent.screenX=t.screenX,this.previousMouseEvent.screenY=t.screenY,this.showGrabbingCursor(),this.data.pointerLockEnabled&&!this.pointerLocked&&(i.requestPointerLock?i.requestPointerLock():i.mozRequestPointerLock&&i.mozRequestPointerLock())}},showGrabbingCursor:function(){this.el.sceneEl.canvas.style.cursor="grabbing"},hideGrabbingCursor:function(){this.el.sceneEl.canvas.style.cursor=""},onMouseUp:function(){this.mouseDown=!1,this.hideGrabbingCursor()},onTouchStart:function(t){1===t.touches.length&&this.data.touchEnabled&&!this.el.sceneEl.is("vr-mode")&&(this.touchStart={x:t.touches[0].pageX,y:t.touches[0].pageY},this.touchStarted=!0)},onTouchMove:function(t){var e,i,o=this.el.sceneEl.canvas,n=this.yawObject;this.touchStarted&&this.data.touchEnabled&&(i=2*Math.PI*(t.touches[0].pageX-this.touchStart.x)/o.clientWidth,e=this.data.reverseTouchDrag?1:-1,n.rotation.y-=.5*i*e,this.touchStart={x:t.touches[0].pageX,y:t.touches[0].pageY})},onTouchEnd:function(){this.touchStarted=!1},onEnterVR:function(){var t=this.el.sceneEl;t.checkHeadsetConnected()&&(this.saveCameraPose(),this.el.object3D.position.set(0,0,0),this.el.object3D.rotation.set(0,0,0),t.hasWebXR&&(this.el.object3D.matrixAutoUpdate=!1,this.el.object3D.updateMatrix()))},onExitVR:function(){this.el.sceneEl.checkHeadsetConnected()&&(this.restoreCameraPose(),this.previousHMDPosition.set(0,0,0),this.el.object3D.matrixAutoUpdate=!0)},onPointerLockChange:function(){this.pointerLocked=!(!document.pointerLockElement&&!document.mozPointerLockElement)},onPointerLockError:function(){this.pointerLocked=!1},exitPointerLock:function(){document.exitPointerLock(),this.pointerLocked=!1},updateGrabCursor:function(t){var e=this.el.sceneEl;function i(){e.canvas.classList.add("a-grab-cursor")}function o(){e.canvas.classList.remove("a-grab-cursor")}e.canvas?t?i():o():t?e.addEventListener("render-target-loaded",i):e.addEventListener("render-target-loaded",o)},saveCameraPose:function(){var t=this.el;this.savedPose.position.copy(t.object3D.position),this.savedPose.rotation.copy(t.object3D.rotation),this.hasSavedPose=!0},restoreCameraPose:function(){var t=this.el,e=this.savedPose;this.hasSavedPose&&(t.object3D.position.copy(e.position),t.object3D.rotation.copy(e.rotation),this.hasSavedPose=!1)}}),t.registerComponent("arjs-webcam-texture",{init:function(){this.scene=this.el.sceneEl,this.texCamera=new e.OrthographicCamera(-.5,.5,.5,-.5,0,10),this.texScene=new e.Scene,this.scene.renderer.autoClear=!1,this.video=document.createElement("video"),this.video.setAttribute("autoplay",!0),this.video.setAttribute("playsinline",!0),this.video.setAttribute("display","none"),document.body.appendChild(this.video),this.geom=new e.PlaneBufferGeometry,this.texture=new e.VideoTexture(this.video),this.material=new e.MeshBasicMaterial({map:this.texture});const t=new e.Mesh(this.geom,this.material);this.texScene.add(t)},play:function(){if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){const t={video:{facingMode:"environment"}};navigator.mediaDevices.getUserMedia(t).then((t=>{this.video.srcObject=t,this.video.play()})).catch((t=>{this.el.sceneEl.systems.arjs._displayErrorPopup(`Webcam error: ${t}`)}))}else this.el.sceneEl.systems.arjs._displayErrorPopup("sorry - media devices API not supported")},tick:function(){this.scene.renderer.clear(),this.scene.renderer.render(this.texScene,this.texCamera),this.scene.renderer.clearDepth()},pause:function(){this.video.srcObject.getTracks().forEach((t=>{t.stop()}))},remove:function(){this.material.dispose(),this.texture.dispose(),this.geom.dispose()}}),t.registerComponent("gps-camera",{_watchPositionId:null,originCoords:null,currentCoords:null,lookControls:null,heading:null,schema:{simulateLatitude:{type:"number",default:0},simulateLongitude:{type:"number",default:0},simulateAltitude:{type:"number",default:0},positionMinAccuracy:{type:"int",default:100},alert:{type:"boolean",default:!1},minDistance:{type:"int",default:0},maxDistance:{type:"int",default:0},gpsMinDistance:{type:"number",default:5},gpsTimeInterval:{type:"number",default:0}},update:function(){if(0!==this.data.simulateLatitude&&0!==this.data.simulateLongitude){var t=Object.assign({},this.currentCoords||{});t.longitude=this.data.simulateLongitude,t.latitude=this.data.simulateLatitude,t.altitude=this.data.simulateAltitude,this.currentCoords=t,this.originCoords=null,this._updatePosition()}},init:function(){if(this.el.components["arjs-look-controls"]||this.el.components["look-controls"]){this.lastPosition={latitude:0,longitude:0},this.loader=document.createElement("DIV"),this.loader.classList.add("arjs-loader"),document.body.appendChild(this.loader),this.onGpsEntityPlaceAdded=this._onGpsEntityPlaceAdded.bind(this),window.addEventListener("gps-entity-place-added",this.onGpsEntityPlaceAdded),this.lookControls=this.el.components["arjs-look-controls"]||this.el.components["look-controls"];var t=this._getDeviceOrientationEventName();if(this._onDeviceOrientation=this._onDeviceOrientation.bind(this),navigator.userAgent.match(/Version\/[\d.]+.*Safari/))if("function"==typeof DeviceOrientationEvent.requestPermission){var e=function(){console.log("Requesting device orientation permissions..."),DeviceOrientationEvent.requestPermission(),document.removeEventListener("touchend",e)};document.addEventListener("touchend",(function(){e()}),!1),this.el.sceneEl.systems.arjs._displayErrorPopup("After camera permission prompt, please tap the screen to activate geolocation.")}else{var i=setTimeout((function(){this.el.sceneEl.systems.arjs._displayErrorPopup("Please enable device orientation in Settings > Safari > Motion & Orientation Access.")}),750);window.addEventListener(t,(function(){clearTimeout(i)}))}window.addEventListener(t,this._onDeviceOrientation,!1)}},play:function(){if(0!==this.data.simulateLatitude&&0!==this.data.simulateLongitude){var t=Object.assign({},this.currentCoords||{});t.latitude=this.data.simulateLatitude,t.longitude=this.data.simulateLongitude,0!==this.data.simulateAltitude&&(t.altitude=this.data.simulateAltitude),this.currentCoords=t,this._updatePosition()}else this._watchPositionId=this._initWatchGPS(function(t){var e={latitude:t.coords.latitude,longitude:t.coords.longitude,altitude:t.coords.altitude,accuracy:t.coords.accuracy,altitudeAccuracy:t.coords.altitudeAccuracy};0!==this.data.simulateAltitude&&(e.altitude=this.data.simulateAltitude),this.currentCoords=e,(this._haversineDist(this.lastPosition,this.currentCoords)>=this.data.gpsMinDistance||!this.originCoords)&&(this._updatePosition(),this.lastPosition={longitude:this.currentCoords.longitude,latitude:this.currentCoords.latitude})}.bind(this))},tick:function(){null!==this.heading&&this._updateRotation()},pause:function(){this._watchPositionId&&navigator.geolocation.clearWatch(this._watchPositionId),this._watchPositionId=null},remove:function(){var t=this._getDeviceOrientationEventName();window.removeEventListener(t,this._onDeviceOrientation,!1),window.removeEventListener("gps-entity-place-added",this.onGpsEntityPlaceAdded)},_getDeviceOrientationEventName:function(){if("ondeviceorientationabsolute"in window)var t="deviceorientationabsolute";else"ondeviceorientation"in window?t="deviceorientation":(t="",console.error("Compass not supported"));return t},_initWatchGPS:function(t,e){return e||(e=function(t){console.warn("ERROR("+t.code+"): "+t.message),1!==t.code?3!==t.code||this.el.sceneEl.systems.arjs._displayErrorPopup("Cannot retrieve GPS position. Signal is absent."):this.el.sceneEl.systems.arjs._displayErrorPopup("Please activate Geolocation and refresh the page. If it is already active, please check permissions for this website.")}),"geolocation"in navigator==0?(e({code:0,message:"Geolocation is not supported by your browser"}),Promise.resolve()):navigator.geolocation.watchPosition(t,e,{enableHighAccuracy:!0,maximumAge:this.data.gpsTimeInterval,timeout:27e3})},_updatePosition:function(){if(this.currentCoords.accuracy>this.data.positionMinAccuracy){if(this.data.alert&&!document.getElementById("alert-popup")){var t=document.createElement("div");t.innerHTML="GPS signal is very poor. Try move outdoor or to an area with a better signal.",t.setAttribute("id","alert-popup"),document.body.appendChild(t)}}else{var e=document.getElementById("alert-popup");if(this.currentCoords.accuracy<=this.data.positionMinAccuracy&&e&&document.body.removeChild(e),this.originCoords)this._setPosition();else{this.originCoords=this.currentCoords,this._setPosition();var i=document.querySelector(".arjs-loader");i&&i.remove(),window.dispatchEvent(new CustomEvent("gps-camera-origin-coord-set"))}}},_setPosition:function(){var t=this.el.getAttribute("position"),e={longitude:this.currentCoords.longitude,latitude:this.originCoords.latitude};t.x=this.computeDistanceMeters(this.originCoords,e),t.x*=this.currentCoords.longitude>this.originCoords.longitude?1:-1,e={longitude:this.originCoords.longitude,latitude:this.currentCoords.latitude},t.z=this.computeDistanceMeters(this.originCoords,e),t.z*=this.currentCoords.latitude>this.originCoords.latitude?-1:1,this.el.setAttribute("position",t),window.dispatchEvent(new CustomEvent("gps-camera-update-position",{detail:{position:this.currentCoords,origin:this.originCoords}}))},computeDistanceMeters:function(t,e,i){var o=this._haversineDist(t,e);return i&&this.data.minDistance&&this.data.minDistance>0&&o<this.data.minDistance||i&&this.data.maxDistance&&this.data.maxDistance>0&&o>this.data.maxDistance?Number.MAX_SAFE_INTEGER:o},_haversineDist:function(t,i){var o=e.MathUtils.degToRad(i.longitude-t.longitude),n=e.MathUtils.degToRad(i.latitude-t.latitude),s=Math.sin(n/2)*Math.sin(n/2)+Math.cos(e.MathUtils.degToRad(t.latitude))*Math.cos(e.MathUtils.degToRad(i.latitude))*(Math.sin(o/2)*Math.sin(o/2));return 2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s))*6371e3},_computeCompassHeading:function(t,e,i){var o=t*(Math.PI/180),n=e*(Math.PI/180),s=i*(Math.PI/180),a=Math.cos(o),r=Math.sin(o),d=Math.sin(n),c=Math.cos(s),h=Math.sin(s),u=-a*h-r*d*c,l=-r*h+a*d*c,p=Math.atan(u/l);return l<0?p+=Math.PI:u<0&&(p+=2*Math.PI),p*(180/Math.PI)},_onDeviceOrientation:function(t){void 0!==t.webkitCompassHeading?t.webkitCompassAccuracy<50?this.heading=t.webkitCompassHeading:console.warn("webkitCompassAccuracy is event.webkitCompassAccuracy"):null!==t.alpha?!0===t.absolute||void 0===t.absolute?this.heading=this._computeCompassHeading(t.alpha,t.beta,t.gamma):console.warn("event.absolute === false"):console.warn("event.alpha === null")},_updateRotation:function(){var t=(360-this.heading-(this.el.getAttribute("rotation").y-e.MathUtils.radToDeg(this.lookControls.yawObject.rotation.y)))%360;this.lookControls.yawObject.rotation.y=e.MathUtils.degToRad(t)},_onGpsEntityPlaceAdded:function(){this.originCoords&&window.dispatchEvent(new CustomEvent("gps-camera-origin-coord-set")),this.loader&&this.loader.parentElement&&document.body.removeChild(this.loader)}}),t.registerComponent("gps-entity-place",{_cameraGps:null,schema:{longitude:{type:"number",default:0},latitude:{type:"number",default:0}},remove:function(){window.removeEventListener("gps-camera-origin-coord-set",this.coordSetListener),window.removeEventListener("gps-camera-update-position",this.updatePositionListener)},init:function(){this.coordSetListener=()=>{if(!this._cameraGps){var t=document.querySelector("[gps-camera]");if(!t.components["gps-camera"])return void console.error("gps-camera not initialized");this._cameraGps=t.components["gps-camera"]}this._updatePosition()},this.updatePositionListener=t=>{if(this.data&&this._cameraGps){var e={longitude:this.data.longitude,latitude:this.data.latitude},i=this._cameraGps.computeDistanceMeters(t.detail.position,e);this.el.setAttribute("distance",i),this.el.setAttribute("distanceMsg",this._formatDistance(i)),this.el.dispatchEvent(new CustomEvent("gps-entity-place-update-position",{detail:{distance:i}})),this._cameraGps.computeDistanceMeters(t.detail.position,e,!0)===Number.MAX_SAFE_INTEGER?this.hideForMinDistance(this.el,!0):this.hideForMinDistance(this.el,!1)}},window.addEventListener("gps-camera-origin-coord-set",this.coordSetListener),window.addEventListener("gps-camera-update-position",this.updatePositionListener),this._positionXDebug=0,window.dispatchEvent(new CustomEvent("gps-entity-place-added",{detail:{component:this.el}}))},hideForMinDistance:function(t,e){e?t.setAttribute("visible","false"):t.setAttribute("visible","true")},_updatePosition:function(){var t={x:0,y:this.el.getAttribute("position").y||0,z:0},e={longitude:this.data.longitude,latitude:this._cameraGps.originCoords.latitude};if(t.x=this._cameraGps.computeDistanceMeters(this._cameraGps.originCoords,e),this._positionXDebug=t.x,t.x*=this.data.longitude>this._cameraGps.originCoords.longitude?1:-1,e={longitude:this._cameraGps.originCoords.longitude,latitude:this.data.latitude},t.z=this._cameraGps.computeDistanceMeters(this._cameraGps.originCoords,e),t.z*=this.data.latitude>this._cameraGps.originCoords.latitude?-1:1,0!==t.y){var i=void 0!==this._cameraGps.originCoords.altitude?this._cameraGps.originCoords.altitude:0;t.y=t.y-i}this.el.setAttribute("position",t)},_formatDistance:function(t){return(t=t.toFixed(0))>=1e3?t/1e3+" kilometers":t+" meters"}}),t.registerComponent("gps-projected-camera",{_watchPositionId:null,originCoords:null,currentCoords:null,lookControls:null,heading:null,schema:{simulateLatitude:{type:"number",default:0},simulateLongitude:{type:"number",default:0},simulateAltitude:{type:"number",default:0},positionMinAccuracy:{type:"int",default:100},alert:{type:"boolean",default:!1},minDistance:{type:"int",default:0},gpsMinDistance:{type:"number",default:0},gpsTimeInterval:{type:"number",default:0}},update:function(){if(0!==this.data.simulateLatitude&&0!==this.data.simulateLongitude){var t=Object.assign({},this.currentCoords||{});t.longitude=this.data.simulateLongitude,t.latitude=this.data.simulateLatitude,t.altitude=this.data.simulateAltitude,this.currentCoords=t,this.originCoords=null,this._updatePosition()}},init:function(){if(this.el.components["arjs-look-controls"]||this.el.components["look-controls"]){this.lastPosition={latitude:0,longitude:0},this.loader=document.createElement("DIV"),this.loader.classList.add("arjs-loader"),document.body.appendChild(this.loader),this.onGpsEntityPlaceAdded=this._onGpsEntityPlaceAdded.bind(this),window.addEventListener("gps-entity-place-added",this.onGpsEntityPlaceAdded),this.lookControls=this.el.components["arjs-look-controls"]||this.el.components["look-controls"];var t=this._getDeviceOrientationEventName();if(this._onDeviceOrientation=this._onDeviceOrientation.bind(this),navigator.userAgent.match(/Version\/[\d.]+.*Safari/))if("function"==typeof DeviceOrientationEvent.requestPermission){var e=function(){console.log("Requesting device orientation permissions..."),DeviceOrientationEvent.requestPermission(),document.removeEventListener("touchend",e)};document.addEventListener("touchend",(function(){e()}),!1),this.el.sceneEl.systems.arjs._displayErrorPopup("After camera permission prompt, please tap the screen to activate geolocation.")}else{var i=setTimeout((function(){this.el.sceneEl.systems.arjs._displayErrorPopup("Please enable device orientation in Settings > Safari > Motion & Orientation Access.")}),750);window.addEventListener(t,(function(){clearTimeout(i)}))}window.addEventListener(t,this._onDeviceOrientation,!1)}},play:function(){if(0!==this.data.simulateLatitude&&0!==this.data.simulateLongitude){var t=Object.assign({},this.currentCoords||{});t.latitude=this.data.simulateLatitude,t.longitude=this.data.simulateLongitude,0!==this.data.simulateAltitude&&(t.altitude=this.data.simulateAltitude),this.currentCoords=t,this._updatePosition()}else this._watchPositionId=this._initWatchGPS(function(t){var e={latitude:t.coords.latitude,longitude:t.coords.longitude,altitude:t.coords.altitude,accuracy:t.coords.accuracy,altitudeAccuracy:t.coords.altitudeAccuracy};0!==this.data.simulateAltitude&&(e.altitude=this.data.simulateAltitude),this.currentCoords=e,(this._haversineDist(this.lastPosition,this.currentCoords)>=this.data.gpsMinDistance||!this.originCoords)&&(this._updatePosition(),this.lastPosition={longitude:this.currentCoords.longitude,latitude:this.currentCoords.latitude})}.bind(this))},tick:function(){null!==this.heading&&this._updateRotation()},pause:function(){this._watchPositionId&&navigator.geolocation.clearWatch(this._watchPositionId),this._watchPositionId=null},remove:function(){var t=this._getDeviceOrientationEventName();window.removeEventListener(t,this._onDeviceOrientation,!1),window.removeEventListener("gps-entity-place-added",this.onGpsEntityPlaceAdded)},_getDeviceOrientationEventName:function(){if("ondeviceorientationabsolute"in window)var t="deviceorientationabsolute";else"ondeviceorientation"in window?t="deviceorientation":(t="",console.error("Compass not supported"));return t},_initWatchGPS:function(t,e){return e||(e=function(t){console.warn("ERROR("+t.code+"): "+t.message),1!==t.code?3!==t.code||this.el.sceneEl.systems.arjs._displayErrorPopup("Cannot retrieve GPS position. Signal is absent."):this.el.sceneEl.systems.arjs._displayErrorPopup("Please activate Geolocation and refresh the page. If it is already active, please check permissions for this website.")}),"geolocation"in navigator==0?(e({code:0,message:"Geolocation is not supported by your browser"}),Promise.resolve()):navigator.geolocation.watchPosition(t,e,{enableHighAccuracy:!0,maximumAge:this.data.gpsTimeInterval,timeout:27e3})},_updatePosition:function(){if(this.currentCoords.accuracy>this.data.positionMinAccuracy){if(this.data.alert&&!document.getElementById("alert-popup")){var t=document.createElement("div");t.innerHTML="GPS signal is very poor. Try move outdoor or to an area with a better signal.",t.setAttribute("id","alert-popup"),document.body.appendChild(t)}}else{var e=document.getElementById("alert-popup");if(this.currentCoords.accuracy<=this.data.positionMinAccuracy&&e&&document.body.removeChild(e),this.originCoords)this._setPosition();else{this.originCoords=this._project(this.currentCoords.latitude,this.currentCoords.longitude),this._setPosition();var i=document.querySelector(".arjs-loader");i&&i.remove(),window.dispatchEvent(new CustomEvent("gps-camera-origin-coord-set"))}}},_setPosition:function(){var t=this.el.getAttribute("position"),e=this.latLonToWorld(this.currentCoords.latitude,this.currentCoords.longitude);t.x=e[0],t.z=e[1],this.el.setAttribute("position",t),window.dispatchEvent(new CustomEvent("gps-camera-update-position",{detail:{position:this.currentCoords,origin:this.originCoords}}))},computeDistanceMeters:function(t,e){var i=this.el.getAttribute("position"),o=t.x-i.x,n=t.z-i.z,s=Math.sqrt(o*o+n*n);return e&&this.data.minDistance&&this.data.minDistance>0&&s<this.data.minDistance?Number.MAX_SAFE_INTEGER:s},latLonToWorld:function(t,e){var i=this._project(t,e);return[i[0]-this.originCoords[0],-(i[1]-this.originCoords[1])]},_project:function(t,e){const i=20037508.34;return[e/180*i,Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180)*i/180]},_unproject:function(t,e){const i=20037508.34;var o=e/i*180;return{longitude:t/i*180,latitude:180/Math.PI*(2*Math.atan(Math.exp(o*Math.PI/180))-Math.PI/2)}},_computeCompassHeading:function(t,e,i){var o=t*(Math.PI/180),n=e*(Math.PI/180),s=i*(Math.PI/180),a=Math.cos(o),r=Math.sin(o),d=Math.sin(n),c=Math.cos(s),h=Math.sin(s),u=-a*h-r*d*c,l=-r*h+a*d*c,p=Math.atan(u/l);return l<0?p+=Math.PI:u<0&&(p+=2*Math.PI),p*(180/Math.PI)},_onDeviceOrientation:function(t){void 0!==t.webkitCompassHeading?t.webkitCompassAccuracy<50?this.heading=t.webkitCompassHeading:console.warn("webkitCompassAccuracy is event.webkitCompassAccuracy"):null!==t.alpha?!0===t.absolute||void 0===t.absolute?this.heading=this._computeCompassHeading(t.alpha,t.beta,t.gamma):console.warn("event.absolute === false"):console.warn("event.alpha === null")},_updateRotation:function(){var t=(360-this.heading-(this.el.getAttribute("rotation").y-THREE.MathUtils.radToDeg(this.lookControls.yawObject.rotation.y)))%360;this.lookControls.yawObject.rotation.y=THREE.MathUtils.degToRad(t)},_haversineDist:function(t,e){var i=THREE.MathUtils.degToRad(e.longitude-t.longitude),o=THREE.MathUtils.degToRad(e.latitude-t.latitude),n=Math.sin(o/2)*Math.sin(o/2)+Math.cos(THREE.MathUtils.degToRad(t.latitude))*Math.cos(THREE.MathUtils.degToRad(e.latitude))*(Math.sin(i/2)*Math.sin(i/2));return 2*Math.atan2(Math.sqrt(n),Math.sqrt(1-n))*6371e3},_onGpsEntityPlaceAdded:function(){this.originCoords&&window.dispatchEvent(new CustomEvent("gps-camera-origin-coord-set")),this.loader&&this.loader.parentElement&&document.body.removeChild(this.loader)}}),t.registerComponent("gps-projected-entity-place",{_cameraGps:null,schema:{longitude:{type:"number",default:0},latitude:{type:"number",default:0}},remove:function(){window.removeEventListener("gps-camera-update-position",this.updatePositionListener)},init:function(){this.coordSetListener=()=>{if(!this._cameraGps){var t=document.querySelector("[gps-projected-camera]");if(!t.components["gps-projected-camera"])return void console.error("gps-projected-camera not initialized");this._cameraGps=t.components["gps-projected-camera"],this._updatePosition()}},this.updatePositionListener=t=>{if(this.data&&this._cameraGps){var e=this.el.getAttribute("position"),i=this._cameraGps.computeDistanceMeters(e);this.el.setAttribute("distance",i),this.el.setAttribute("distanceMsg",this._formatDistance(i)),this.el.dispatchEvent(new CustomEvent("gps-entity-place-update-position",{detail:{distance:i}})),this._cameraGps.computeDistanceMeters(e,!0)===Number.MAX_SAFE_INTEGER?this.hideForMinDistance(this.el,!0):this.hideForMinDistance(this.el,!1)}},window.addEventListener("gps-camera-origin-coord-set",this.coordSetListener),window.addEventListener("gps-camera-update-position",this.updatePositionListener),this._positionXDebug=0,window.dispatchEvent(new CustomEvent("gps-entity-place-added",{detail:{component:this.el}}))},hideForMinDistance:function(t,e){e?t.setAttribute("visible","false"):t.setAttribute("visible","true")},_updatePosition:function(){var t=this._cameraGps.latLonToWorld(this.data.latitude,this.data.longitude),e=this.el.getAttribute("position");this.el.setAttribute("position",{x:t[0],y:e.y,z:t[1]})},_formatDistance:function(t){return(t=t.toFixed(0))>=1e3?t/1e3+" kilometers":t+" meters"}})})(),s})()));
\ No newline at end of file
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("aframe"),require("three")):"function"==typeof define&&define.amd?define(["aframe","three"],e):"object"==typeof exports?exports.ARjs=e(require("aframe"),require("three")):t.ARjs=e(t.AFRAME,t.THREE)}(this,((t,e)=>(()=>{var i={254:function(t,e,i){var o;o=t=>(()=>{"use strict";var e={381:e=>{e.exports=t}},i={};function o(t){var n=i[t];if(void 0!==n)return n.exports;var s=i[t]={exports:{}};return e[t](s,s.exports,o),s.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return(()=>{o.r(n),o.d(n,{DeviceOrientationControls:()=>l,LocationBased:()=>i,WebcamRenderer:()=>s});class t{constructor(){this.EARTH=40075016.68,this.HALF_EARTH=20037508.34}project(t,e){return[this.lonToSphMerc(t),this.latToSphMerc(e)]}unproject(t){return[this.sphMercToLon(t[0]),this.sphMercToLat(t[1])]}lonToSphMerc(t){return t/180*this.HALF_EARTH}latToSphMerc(t){return Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180)*this.HALF_EARTH/180}sphMercToLon(t){return t/this.HALF_EARTH*180}sphMercToLat(t){var e=t/this.HALF_EARTH*180;return 180/Math.PI*(2*Math.atan(Math.exp(e*Math.PI/180))-Math.PI/2)}getID(){return"epsg:3857"}}var e=o(381);class i{constructor(e,i,o={}){this._scene=e,this._camera=i,this._proj=new t,this._eventHandlers={},this._lastCoords=null,this._gpsMinDistance=0,this._gpsMinAccuracy=100,this._maximumAge=0,this._watchPositionId=null,this.setGpsOptions(o),this.initialPosition=null,this.initialPositionAsOrigin=o.initialPositionAsOrigin||!1}setProjection(t){this._proj=t}setGpsOptions(t={}){void 0!==t.gpsMinDistance&&(this._gpsMinDistance=t.gpsMinDistance),void 0!==t.gpsMinAccuracy&&(this._gpsMinAccuracy=t.gpsMinAccuracy),void 0!==t.maximumAge&&(this._maximumAge=t.maximumAge)}startGps(t=0){return null===this._watchPositionId&&(this._watchPositionId=navigator.geolocation.watchPosition((t=>{this._gpsReceived(t)}),(t=>{this._eventHandlers.gpserror?this._eventHandlers.gpserror(t.code):alert(`GPS error: code ${t.code}`)}),{enableHighAccuracy:!0,maximumAge:0!=t?t:this._maximumAge}),!0)}stopGps(){return null!==this._watchPositionId&&(navigator.geolocation.clearWatch(this._watchPositionId),this._watchPositionId=null,!0)}fakeGps(t,e,i=null,o=0){null!==i&&this.setElevation(i),this._gpsReceived({coords:{longitude:t,latitude:e,accuracy:o}})}lonLatToWorldCoords(t,e){const i=this._proj.project(t,e);if(this.initialPositionAsOrigin){if(!this.initialPosition)throw"Trying to use 'initial position as origin' mode with no initial position determined";i[0]-=this.initialPosition[0],i[1]-=this.initialPosition[1]}return[i[0],-i[1]]}add(t,e,i,o){this.setWorldPosition(t,e,i,o),this._scene.add(t)}setWorldPosition(t,e,i,o){const n=this.lonLatToWorldCoords(e,i);void 0!==o&&(t.position.y=o),[t.position.x,t.position.z]=n}setElevation(t){this._camera.position.y=t}on(t,e){this._eventHandlers[t]=e}setWorldOrigin(t,e){this.initialPosition=this._proj.project(t,e)}_gpsReceived(t){let e=Number.MAX_VALUE;t.coords.accuracy<=this._gpsMinAccuracy&&(null===this._lastCoords?this._lastCoords={latitude:t.coords.latitude,longitude:t.coords.longitude}:e=this._haversineDist(this._lastCoords,t.coords),e>=this._gpsMinDistance&&(this._lastCoords.longitude=t.coords.longitude,this._lastCoords.latitude=t.coords.latitude,this.initialPositionAsOrigin&&!this.initialPosition&&this.setWorldOrigin(t.coords.longitude,t.coords.latitude),this.setWorldPosition(this._camera,t.coords.longitude,t.coords.latitude),this._eventHandlers.gpsupdate&&this._eventHandlers.gpsupdate(t,e)))}_haversineDist(t,i){const o=e.MathUtils.degToRad(i.longitude-t.longitude),n=e.MathUtils.degToRad(i.latitude-t.latitude),s=Math.sin(n/2)*Math.sin(n/2)+Math.cos(e.MathUtils.degToRad(t.latitude))*Math.cos(e.MathUtils.degToRad(i.latitude))*(Math.sin(o/2)*Math.sin(o/2));return 2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s))*6371e3}}class s{constructor(t,i){let o;this.renderer=t,this.renderer.autoClear=!1,this.sceneWebcam=new e.Scene,void 0===i?(o=document.createElement("video"),o.setAttribute("autoplay",!0),o.setAttribute("playsinline",!0),o.style.display="none",document.body.appendChild(o)):o=document.querySelector(i),this.geom=new e.PlaneBufferGeometry,this.texture=new e.VideoTexture(o),this.material=new e.MeshBasicMaterial({map:this.texture});const n=new e.Mesh(this.geom,this.material);if(this.sceneWebcam.add(n),this.cameraWebcam=new e.OrthographicCamera(-.5,.5,.5,-.5,0,10),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){const t={video:{width:1280,height:720,facingMode:"environment"}};navigator.mediaDevices.getUserMedia(t).then((t=>{console.log("using the webcam successfully..."),o.srcObject=t,o.play()})).catch((t=>{setTimeout((()=>{this.createErrorPopup("Webcam Error\nName: "+t.name+"\nMessage: "+t.message)}),1e3)}))}else setTimeout((()=>{this.createErrorPopup("sorry - media devices API not supported")}),1e3)}update(){this.renderer.clear(),this.renderer.render(this.sceneWebcam,this.cameraWebcam),this.renderer.clearDepth()}dispose(){this.material.dispose(),this.texture.dispose(),this.geom.dispose()}createErrorPopup(t){if(!document.getElementById("error-popup")){var e=document.createElement("div");e.innerHTML=t,e.setAttribute("id","error-popup"),document.body.appendChild(e)}}}const a=new e.Vector3(0,0,1),r=new e.Euler,c=new e.Quaternion,d=new e.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),h={type:"change"};class l extends e.EventDispatcher{constructor(t){super(),!1===window.isSecureContext&&console.error("THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)");const i=this,o=new e.Quaternion;this.object=t,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation={},this.screenOrientation=0,this.alphaOffset=0,this.TWO_PI=2*Math.PI,this.HALF_PI=.5*Math.PI,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=1;const n=function(t){i.deviceOrientation=t},s=function(){i.screenOrientation=window.orientation||0};this.connect=function(){s(),void 0!==window.DeviceOrientationEvent&&"function"==typeof window.DeviceOrientationEvent.requestPermission?window.DeviceOrientationEvent.requestPermission().then((t=>{"granted"===t&&(window.addEventListener("orientationchange",s),window.addEventListener(i.orientationChangeEventName,n))})).catch((function(t){console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:",t)})):(window.addEventListener("orientationchange",s),window.addEventListener(i.orientationChangeEventName,n)),i.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",s),window.removeEventListener(i.orientationChangeEventName,n),i.enabled=!1},this.update=function(){if(!1===i.enabled)return;const t=i.deviceOrientation;if(t){let n=t.alpha?e.MathUtils.degToRad(t.alpha)+i.alphaOffset:0,s=t.beta?e.MathUtils.degToRad(t.beta):0,l=t.gamma?e.MathUtils.degToRad(t.gamma):0;const u=i.screenOrientation?e.MathUtils.degToRad(i.screenOrientation):0;if(this.smoothingFactor<1){if(this.lastOrientation){const t=this.smoothingFactor;n=this._getSmoothedAngle(n,this.lastOrientation.alpha,t),s=this._getSmoothedAngle(s+Math.PI,this.lastOrientation.beta,t),l=this._getSmoothedAngle(l+this.HALF_PI,this.lastOrientation.gamma,t,Math.PI)}else s+=Math.PI,l+=this.HALF_PI;this.lastOrientation={alpha:n,beta:s,gamma:l}}!function(t,e,i,o,n){r.set(i,e,-o,"YXZ"),t.setFromEuler(r),t.multiply(d),t.multiply(c.setFromAxisAngle(a,-n))}(i.object.quaternion,n,this.smoothingFactor<1?s-Math.PI:s,this.smoothingFactor<1?l-this.HALF_PI:l,u),8*(1-o.dot(i.object.quaternion))>1e-6&&(o.copy(i.object.quaternion),i.dispatchEvent(h))}},this._orderAngle=function(t,e,i=this.TWO_PI){return e>t&&Math.abs(e-t)<i/2||t>e&&Math.abs(e-t)>i/2?{left:t,right:e}:{left:e,right:t}},this._getSmoothedAngle=function(t,e,i,o=this.TWO_PI){const n=this._orderAngle(t,e,o),s=n.left,a=n.right;n.left=0,n.right-=s,n.right<0&&(n.right+=o);let r=a==e?(1-i)*n.right+i*n.left:i*n.right+(1-i)*n.left;return r+=s,r>=o&&(r-=o),r},this.dispose=function(){i.disconnect()},this.connect()}}})(),n})(),t.exports=o(i(381))},223:e=>{"use strict";e.exports=t},381:t=>{"use strict";t.exports=e}},o={};function n(t){var e=o[t];if(void 0!==e)return e.exports;var s=o[t]={exports:{}};return i[t].call(s.exports,s,s.exports,n),s.exports}n.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};return(()=>{"use strict";n.r(s);var t=n(223),e=n(381);t.registerComponent("arjs-webcam-texture",{init:function(){this.scene=this.el.sceneEl,this.texCamera=new e.OrthographicCamera(-.5,.5,.5,-.5,0,10),this.texScene=new e.Scene,this.scene.renderer.autoClear=!1,this.video=document.createElement("video"),this.video.setAttribute("autoplay",!0),this.video.setAttribute("playsinline",!0),this.video.setAttribute("display","none"),document.body.appendChild(this.video),this.geom=new e.PlaneBufferGeometry,this.texture=new e.VideoTexture(this.video),this.material=new e.MeshBasicMaterial({map:this.texture});const t=new e.Mesh(this.geom,this.material);this.texScene.add(t)},play:function(){if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){const t={video:{facingMode:"environment"}};navigator.mediaDevices.getUserMedia(t).then((t=>{this.video.srcObject=t,this.video.play()})).catch((t=>{this.el.sceneEl.systems.arjs._displayErrorPopup(`Webcam error: ${t}`)}))}else this.el.sceneEl.systems.arjs._displayErrorPopup("sorry - media devices API not supported")},tick:function(){this.scene.renderer.clear(),this.scene.renderer.render(this.texScene,this.texCamera),this.scene.renderer.clearDepth()},pause:function(){this.video.srcObject.getTracks().forEach((t=>{t.stop()}))},remove:function(){this.material.dispose(),this.texture.dispose(),this.geom.dispose()}});var i=n(254);t.registerComponent("gps-new-camera",{schema:{simulateLatitude:{type:"number",default:0},simulateLongitude:{type:"number",default:0},simulateAltitude:{type:"number",default:-Number.MAX_VALUE},gpsMinDistance:{type:"number",default:0},positionMinAccuracy:{type:"number",default:100},gpsTimeInterval:{type:"number",default:0},initialPositionAsOrigin:{type:"boolean",default:!1}},init:function(){this._testForOrientationControls(),this.threeLoc=new i.LocationBased(this.el.sceneEl.object3D,this.el.object3D,{initialPositionAsOrigin:this.data.initialPositionAsOrigin}),this.threeLoc.on("gpsupdate",(t=>{this._currentPosition={longitude:t.coords.longitude,latitude:t.coords.latitude},this._sendGpsUpdateEvent(t.coords.longitude,t.coords.latitude)})),this.threeLoc.on("gpserror",(t=>{t>=1&&t<=3?this._displayError(["User denied access to GPS.","GPS satellites not available.","Timeout communicating with GPS satellites - try moving to a more open area."][t-1]):this._displayError(`Unknown geolocation error code ${t}.`)}));const t=this._isMobile();this.el.setAttribute("look-controls-enabled",!t),t&&this.el.setAttribute("arjs-device-orientation-controls",!0),navigator.userAgent.match(/Version\/[\d.]+.*Safari/)&&this._setupSafariOrientationPermissions(),this.el.sceneEl.addEventListener("gps-entity-place-added",(t=>{const e=t.detail.component.components["gps-new-entity-place"];this._currentPosition&&e.setDistanceFrom(this._currentPosition)}))},update:function(t){this.threeLoc.setGpsOptions({gpsMinAccuracy:this.data.positionMinAccuracy,gpsMinDistance:this.data.gpsMinDistance,maximumAge:this.data.gpsTimeInterval}),0===this.data.simulateLatitude&&0===this.data.simulateLongitude||this.data.simulateLatitude==t.simulateLatitude&&this.data.simulateLongitude==t.simulateLongitude||(this.threeLoc.stopGps(),this.threeLoc.fakeGps(this.data.simulateLongitude,this.data.simulateLatitude),this.data.simulateLatitude=0,this.data.simulateLongitude=0),this.data.simulateAltitude>-Number.MAX_VALUE&&this.threeLoc.setElevation(this.data.simulateAltitude+1.6)},play:function(){0===this.data.simulateLatitude&&0===this.data.simulateLongitude&&this.threeLoc.startGps()},pause:function(){this.threeLoc.stopGps()},latLonToWorld:function(t,e){return this.threeLoc.lonLatToWorldCoords(e,t)},getInitialPosition:function(){return this.threeLoc.initialPosition},_sendGpsUpdateEvent:function(t,e){this.el.emit("gps-camera-update-position",{position:{longitude:t,latitude:e}})},_testForOrientationControls:function(){this.el.components["arjs-device-orientation-controls"]||this.el.components["look-controls"]||this._displayError("WARNING - No orientation controls component, app will not respond to device rotation.")},_displayError:function(t){const e=this.el.sceneEl.systems.arjs;e?e._displayErrorPopup(t):alert(t)},_setupSafariOrientationPermissions:function(){if("function"==typeof window.DeviceOrientationEvent?.requestPermission){var t=function(){console.log("Requesting device orientation permissions..."),DeviceOrientationEvent.requestPermission(),document.removeEventListener("touchend",t)};document.addEventListener("touchend",(function(){t()}),!1),this.el.sceneEl.systems.arjs._displayErrorPopup("After camera permission prompt, please tap the screen to activate geolocation.")}else{var e=setTimeout((()=>{this.el.sceneEl.systems.arjs._displayErrorPopup("Please enable device orientation in Settings > Safari > Motion & Orientation Access.")}),750);window.addEventListener("deviceorientation",(function(){clearTimeout(e)}),{once:!0})}},_isMobile:function(){return!!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}}),t.registerComponent("gps-new-entity-place",{schema:{longitude:{type:"number",default:0},latitude:{type:"number",default:0}},init:function(){const t=document.querySelector("[gps-new-camera]");t.components["gps-new-camera"]?(this._cameraGps=t.components["gps-new-camera"],t.addEventListener("gps-camera-update-position",(t=>{this.distance=this._haversineDist(t.detail.position,this.data)})),this.el.sceneEl.emit("gps-entity-place-added",{component:this.el})):console.error("gps-new-camera not initialised")},update:function(){const t=this._cameraGps.threeLoc.lonLatToWorldCoords(this.data.longitude,this.data.latitude);this.el.object3D.position.set(t[0],this.el.object3D.position.y,t[1])},setDistanceFrom:function(t){this.distance=this._haversineDist(t,this.data)},_haversineDist:function(t,i){const o=e.MathUtils.degToRad(i.longitude-t.longitude),n=e.MathUtils.degToRad(i.latitude-t.latitude),s=Math.sin(n/2)*Math.sin(n/2)+Math.cos(e.MathUtils.degToRad(t.latitude))*Math.cos(e.MathUtils.degToRad(i.latitude))*(Math.sin(o/2)*Math.sin(o/2));return 2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s))*6371e3}}),t.registerComponent("arjs-device-orientation-controls",{schema:{smoothingFactor:{type:"number",default:1}},init:function(){this._orientationControls=new THREEx.DeviceOrientationControls(this.el.object3D)},update:function(){this._orientationControls.smoothingFactor=this.data.smoothingFactor},tick:function(){this._orientationControls.update()}})})(),s})()));
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("three")):"function"==typeof define&&define.amd?define(["three"],e):"object"==typeof exports?exports.THREEx=e(require("three")):t.THREEx=e(t.THREE)}(this,(t=>(()=>{"use strict";var e={381:e=>{e.exports=t}},i={};function o(t){var n=i[t];if(void 0!==n)return n.exports;var s=i[t]={exports:{}};return e[t](s,s.exports,o),s.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return(()=>{o.r(n),o.d(n,{DeviceOrientationControls:()=>l,LocationBased:()=>i,WebcamRenderer:()=>s});class t{constructor(){this.EARTH=40075016.68,this.HALF_EARTH=20037508.34}project(t,e){return[this.lonToSphMerc(t),this.latToSphMerc(e)]}unproject(t){return[this.sphMercToLon(t[0]),this.sphMercToLat(t[1])]}lonToSphMerc(t){return t/180*this.HALF_EARTH}latToSphMerc(t){return Math.log(Math.tan((90+t)*Math.PI/360))/(Math.PI/180)*this.HALF_EARTH/180}sphMercToLon(t){return t/this.HALF_EARTH*180}sphMercToLat(t){var e=t/this.HALF_EARTH*180;return 180/Math.PI*(2*Math.atan(Math.exp(e*Math.PI/180))-Math.PI/2)}getID(){return"epsg:3857"}}var e=o(381);class i{constructor(e,i,o={}){this._scene=e,this._camera=i,this._proj=new t,this._eventHandlers={},this._lastCoords=null,this._gpsMinDistance=0,this._gpsMinAccuracy=100,this._maximumAge=0,this._watchPositionId=null,this.setGpsOptions(o),this.initialPosition=null,this.initialPositionAsOrigin=o.initialPositionAsOrigin||!1}setProjection(t){this._proj=t}setGpsOptions(t={}){void 0!==t.gpsMinDistance&&(this._gpsMinDistance=t.gpsMinDistance),void 0!==t.gpsMinAccuracy&&(this._gpsMinAccuracy=t.gpsMinAccuracy),void 0!==t.maximumAge&&(this._maximumAge=t.maximumAge)}startGps(t=0){return null===this._watchPositionId&&(this._watchPositionId=navigator.geolocation.watchPosition((t=>{this._gpsReceived(t)}),(t=>{this._eventHandlers.gpserror?this._eventHandlers.gpserror(t.code):alert(`GPS error: code ${t.code}`)}),{enableHighAccuracy:!0,maximumAge:0!=t?t:this._maximumAge}),!0)}stopGps(){return null!==this._watchPositionId&&(navigator.geolocation.clearWatch(this._watchPositionId),this._watchPositionId=null,!0)}fakeGps(t,e,i=null,o=0){null!==i&&this.setElevation(i),this._gpsReceived({coords:{longitude:t,latitude:e,accuracy:o}})}lonLatToWorldCoords(t,e){const i=this._proj.project(t,e);if(this.initialPositionAsOrigin){if(!this.initialPosition)throw"Trying to use 'initial position as origin' mode with no initial position determined";i[0]-=this.initialPosition[0],i[1]-=this.initialPosition[1]}return[i[0],-i[1]]}add(t,e,i,o){this.setWorldPosition(t,e,i,o),this._scene.add(t)}setWorldPosition(t,e,i,o){const n=this.lonLatToWorldCoords(e,i);void 0!==o&&(t.position.y=o),[t.position.x,t.position.z]=n}setElevation(t){this._camera.position.y=t}on(t,e){this._eventHandlers[t]=e}setWorldOrigin(t,e){this.initialPosition=this._proj.project(t,e)}_gpsReceived(t){let e=Number.MAX_VALUE;t.coords.accuracy<=this._gpsMinAccuracy&&(null===this._lastCoords?this._lastCoords={latitude:t.coords.latitude,longitude:t.coords.longitude}:e=this._haversineDist(this._lastCoords,t.coords),e>=this._gpsMinDistance&&(this._lastCoords.longitude=t.coords.longitude,this._lastCoords.latitude=t.coords.latitude,this.initialPositionAsOrigin&&!this.initialPosition&&this.setWorldOrigin(t.coords.longitude,t.coords.latitude),this.setWorldPosition(this._camera,t.coords.longitude,t.coords.latitude),this._eventHandlers.gpsupdate&&this._eventHandlers.gpsupdate(t,e)))}_haversineDist(t,i){const o=e.MathUtils.degToRad(i.longitude-t.longitude),n=e.MathUtils.degToRad(i.latitude-t.latitude),s=Math.sin(n/2)*Math.sin(n/2)+Math.cos(e.MathUtils.degToRad(t.latitude))*Math.cos(e.MathUtils.degToRad(i.latitude))*(Math.sin(o/2)*Math.sin(o/2));return 2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s))*6371e3}}class s{constructor(t,i){let o;this.renderer=t,this.renderer.autoClear=!1,this.sceneWebcam=new e.Scene,void 0===i?(o=document.createElement("video"),o.setAttribute("autoplay",!0),o.setAttribute("playsinline",!0),o.style.display="none",document.body.appendChild(o)):o=document.querySelector(i),this.geom=new e.PlaneBufferGeometry,this.texture=new e.VideoTexture(o),this.material=new e.MeshBasicMaterial({map:this.texture});const n=new e.Mesh(this.geom,this.material);if(this.sceneWebcam.add(n),this.cameraWebcam=new e.OrthographicCamera(-.5,.5,.5,-.5,0,10),navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){const t={video:{width:1280,height:720,facingMode:"environment"}};navigator.mediaDevices.getUserMedia(t).then((t=>{console.log("using the webcam successfully..."),o.srcObject=t,o.play()})).catch((t=>{setTimeout((()=>{this.createErrorPopup("Webcam Error\nName: "+t.name+"\nMessage: "+t.message)}),1e3)}))}else setTimeout((()=>{this.createErrorPopup("sorry - media devices API not supported")}),1e3)}update(){this.renderer.clear(),this.renderer.render(this.sceneWebcam,this.cameraWebcam),this.renderer.clearDepth()}dispose(){this.material.dispose(),this.texture.dispose(),this.geom.dispose()}createErrorPopup(t){if(!document.getElementById("error-popup")){var e=document.createElement("div");e.innerHTML=t,e.setAttribute("id","error-popup"),document.body.appendChild(e)}}}const r=new e.Vector3(0,0,1),a=new e.Euler,h=new e.Quaternion,c=new e.Quaternion(-Math.sqrt(.5),0,0,Math.sqrt(.5)),d={type:"change"};class l extends e.EventDispatcher{constructor(t){super(),!1===window.isSecureContext&&console.error("THREE.DeviceOrientationControls: DeviceOrientationEvent is only available in secure contexts (https)");const i=this,o=new e.Quaternion;this.object=t,this.object.rotation.reorder("YXZ"),this.enabled=!0,this.deviceOrientation={},this.screenOrientation=0,this.alphaOffset=0,this.TWO_PI=2*Math.PI,this.HALF_PI=.5*Math.PI,this.orientationChangeEventName="ondeviceorientationabsolute"in window?"deviceorientationabsolute":"deviceorientation",this.smoothingFactor=1;const n=function(t){i.deviceOrientation=t},s=function(){i.screenOrientation=window.orientation||0};this.connect=function(){s(),void 0!==window.DeviceOrientationEvent&&"function"==typeof window.DeviceOrientationEvent.requestPermission?window.DeviceOrientationEvent.requestPermission().then((t=>{"granted"===t&&(window.addEventListener("orientationchange",s),window.addEventListener(i.orientationChangeEventName,n))})).catch((function(t){console.error("THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:",t)})):(window.addEventListener("orientationchange",s),window.addEventListener(i.orientationChangeEventName,n)),i.enabled=!0},this.disconnect=function(){window.removeEventListener("orientationchange",s),window.removeEventListener(i.orientationChangeEventName,n),i.enabled=!1},this.update=function(){if(!1===i.enabled)return;const t=i.deviceOrientation;if(t){let n=t.alpha?e.MathUtils.degToRad(t.alpha)+i.alphaOffset:0,s=t.beta?e.MathUtils.degToRad(t.beta):0,l=t.gamma?e.MathUtils.degToRad(t.gamma):0;const u=i.screenOrientation?e.MathUtils.degToRad(i.screenOrientation):0;if(this.smoothingFactor<1){if(this.lastOrientation){const t=this.smoothingFactor;n=this._getSmoothedAngle(n,this.lastOrientation.alpha,t),s=this._getSmoothedAngle(s+Math.PI,this.lastOrientation.beta,t),l=this._getSmoothedAngle(l+this.HALF_PI,this.lastOrientation.gamma,t,Math.PI)}else s+=Math.PI,l+=this.HALF_PI;this.lastOrientation={alpha:n,beta:s,gamma:l}}!function(t,e,i,o,n){a.set(i,e,-o,"YXZ"),t.setFromEuler(a),t.multiply(c),t.multiply(h.setFromAxisAngle(r,-n))}(i.object.quaternion,n,this.smoothingFactor<1?s-Math.PI:s,this.smoothingFactor<1?l-this.HALF_PI:l,u),8*(1-o.dot(i.object.quaternion))>1e-6&&(o.copy(i.object.quaternion),i.dispatchEvent(d))}},this._orderAngle=function(t,e,i=this.TWO_PI){return e>t&&Math.abs(e-t)<i/2||t>e&&Math.abs(e-t)>i/2?{left:t,right:e}:{left:e,right:t}},this._getSmoothedAngle=function(t,e,i,o=this.TWO_PI){const n=this._orderAngle(t,e,o),s=n.left,r=n.right;n.left=0,n.right-=s,n.right<0&&(n.right+=o);let a=r==e?(1-i)*n.right+i*n.left:i*n.right+(1-i)*n.left;return a+=s,a>=o&&(a-=o),a},this.dispose=function(){i.disconnect()},this.connect()}}})(),n})()));
<!doctype html>
<!--
/*
* Copyright 2017 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Building an augmented reality application with the WebXR Device API</title>
<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<!-- three.js -->
<script src="https://unpkg.com/three@0.126.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.126.0/examples/js/loaders/GLTFLoader.js"></script>
<link rel="stylesheet" type="text/css" href="../shared/app.css" />
<script src="../shared/utils.js"></script>
</head>
<body>
<div id="enter-ar-info" class="mdc-card demo-card">
<h2>Augmented Reality with the WebXR Device API</h2>
<p>
This is an experiment using augmented reality features with the WebXR Device API.
Upon entering AR, you will be surrounded by a world of cubes.
Learn more about these features from the <a href="https://codelabs.developers.google.com/codelabs/ar-with-webxr">Building an augmented reality application with the WebXR Device API</a> Code Lab.
</p>
<!-- Starting an immersive WebXR session requires user interaction. Start the WebXR experience with a simple button. -->
<a id="enter-ar" class="mdc-button mdc-button--raised mdc-button--accent">
Start augmented reality
</a>
</div>
<div id="unsupported-info" class="mdc-card demo-card">
<h2>Unsupported Browser</h2>
<p>
Your browser does not support AR features with WebXR. Learn more about these features from the
<a href="https://codelabs.developers.google.com/codelabs/ar-with-webxr">Building an augmented reality application with the WebXR Device API</a> Code Lab.
</p>
</div>
<script src="app.js"></script>
<div id="stabilization"></div>
</body>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>Hit Tree 1.0</title>
<!-- three.js -->
<script src="https://unpkg.com/three@0.126.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.126.0/examples/js/loaders/GLTFLoader.js"></script>
</head>
<body>
<!-- Starting an immersive WebXR session requires user interaction.
We start this one with a simple button. -->
<button onclick="activateXR()">Start Hello WebXR</button>
<script>
async function activateXR() {
// Add a canvas element and initialize a WebGL context that is compatible with WebXR.
const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
const gl = canvas.getContext("webgl", {xrCompatible: true});
const scene = new THREE.Scene();
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
directionalLight.position.set(10, 15, 10);
scene.add(directionalLight);
// Set up the WebGLRenderer, which handles rendering to the session's base layer.
const renderer = new THREE.WebGLRenderer({
alpha: true,
preserveDrawingBuffer: true,
canvas: canvas,
context: gl
});
renderer.autoClear = false;
// The API directly updates the camera matrices.
// Disable matrix auto updates so three.js doesn't attempt
// to handle the matrices independently.
const camera = new THREE.PerspectiveCamera();
camera.matrixAutoUpdate = false;
// Initialize a WebXR session using "immersive-ar".
const session = await navigator.xr.requestSession("immersive-ar", {requiredFeatures: ['hit-test']});
session.updateRenderState({
baseLayer: new XRWebGLLayer(session, gl)
});
// A 'local' reference space has a native origin that is located
// near the viewer's position at the time the session was created.
const referenceSpace = await session.requestReferenceSpace('local');
// Create another XRReferenceSpace that has the viewer as the origin.
const viewerSpace = await session.requestReferenceSpace('viewer');
// Perform hit testing using the viewer as origin.
const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });
const loader = new THREE.GLTFLoader();
let reticle;
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/reticle/reticle.gltf", function(gltf) {
reticle = gltf.scene;
reticle.visible = false;
scene.add(reticle);
})
let flower;
loader.load("/assets/tree/scene.gltf", function(gltf) {
flower = gltf.scene;
});
session.addEventListener("select", (event) => {
if (flower) {
const clone = flower.clone();
clone.position.copy(reticle.position);
scene.add(clone);
}
});
// Create a render loop that allows us to draw on the AR view.
const onXRFrame = (time, frame) => {
// Queue up the next draw request.
session.requestAnimationFrame(onXRFrame);
// Bind the graphics framebuffer to the baseLayer's framebuffer
gl.bindFramebuffer(gl.FRAMEBUFFER, session.renderState.baseLayer.framebuffer)
// Retrieve the pose of the device.
// XRFrame.getViewerPose can return null while the session attempts to establish tracking.
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
// In mobile AR, we only have one view.
const view = pose.views[0];
const viewport = session.renderState.baseLayer.getViewport(view);
renderer.setSize(viewport.width, viewport.height)
// Use the view's transform matrix and projection matrix to configure the THREE.camera.
camera.matrix.fromArray(view.transform.matrix)
camera.projectionMatrix.fromArray(view.projectionMatrix);
camera.updateMatrixWorld(true);
const hitTestResults = frame.getHitTestResults(hitTestSource);
if (hitTestResults.length > 0 && reticle) {
const hitPose = hitTestResults[0].getPose(referenceSpace);
reticle.visible = true;
reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z)
reticle.updateMatrixWorld(true);
}
// Render the scene with THREE.WebGLRenderer.
renderer.render(scene, camera)
}
}
session.requestAnimationFrame(onXRFrame);
}
</script>
</body>
</html>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment