From 526b77dc63904656a4bc065f6fd6a9317c989cfe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 May 2024 19:49:25 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=B7=20MRjs=20-=20Auto=20Generated=20Di?= =?UTF-8?q?st=20=F0=9F=91=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes at bc1d687b5ffe023f8fcb7b57b34faf22f59f49f6 --- dist/mr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/mr.js b/dist/mr.js index 136a7ae4..8d4bb28e 100644 --- a/dist/mr.js +++ b/dist/mr.js @@ -487,7 +487,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AnchorSystem: () => (/* binding */ AnchorSystem)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var mrjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mrjs */ \"./src/index.js\");\n/* harmony import */ var mrjs_core_MREntity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mrjs/core/MREntity */ \"./src/core/MREntity.js\");\n/* harmony import */ var mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! mrjs/core/MRSystem */ \"./src/core/MRSystem.js\");\n/* harmony import */ var mrjs_dataManagers_MRPlaneManager__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! mrjs/dataManagers/MRPlaneManager */ \"./src/dataManagers/MRPlaneManager.js\");\n\n\n\n\n\n\n\n\n/**\n * @class AnchorSystem\n * @classdesc creates and manages WebXR anchors in the MR scene.\n * @augments MRSystem\n */\nclass AnchorSystem extends mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_2__.MRSystem {\n /**\n * @class\n * @description AnchorSystem's default constructor including setting up event listeners for XR initialization, user interaction, and the MRPlaneManager\n */\n constructor() {\n super();\n this.sourceRequest = false;\n this.source;\n this.currentEntity = null;\n this.tempMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n\n this.planeManager = new mrjs_dataManagers_MRPlaneManager__WEBPACK_IMPORTED_MODULE_3__.MRPlaneManager(this.app.scene, this.app.getAttribute('occlusion'));\n this.anchoringQueue = new Set();\n\n this.hitResults;\n\n this.userWorldPosition = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n this.cameraForward = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n this.pinchDistance = 0;\n\n this.axisSwapQuat = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion().setFromAxisAngle(new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(1, 0, 0), -(3 * Math.PI) / 2);\n\n this.hand = null;\n\n this.snapDistance = 0.6;\n\n this.scale = 1;\n\n let existing = document.querySelectorAll('[data-comp-anchor]');\n\n this.originPosition = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n\n for (const entity of existing) {\n this.attachedComponent(entity);\n this.registry.add(entity);\n }\n\n this.app.addEventListener('enterxr', () => {\n if (this.sourceRequest == false) {\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestReferenceSpace('viewer').then((viewerSpace) => {\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestHitTestSource({ space: viewerSpace }).then((source) => {\n this.source = source;\n });\n });\n\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.addEventListener('end', () => {\n this.sourceRequest = false;\n this.source = null;\n this.hand = null;\n });\n\n this.sourceRequest = true;\n }\n });\n\n this.app.addEventListener('exitxr', () => {\n this.deleteAnchor(this.app);\n this.app.origin.matrix.copy(new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4());\n });\n\n document.addEventListener('selectstart', (event) => {\n if (this.currentEntity == null || (this.hand && this.hand != event.detail.handedness)) {\n return;\n }\n if (!event.detail) {\n return;\n }\n this.hand = event.detail.handedness;\n });\n\n document.addEventListener('selectmoved', (event) => {\n if (this.currentEntity && this.hand == event.detail.handedness) {\n this.userWorldPosition.setFromMatrixPosition(this.app.camera.matrixWorld);\n this.cameraForward.setFromMatrixPosition(this.app.user.forward.matrixWorld);\n\n this.pinchDistance = this.cameraForward.distanceTo(event.detail.position);\n this.scale = Math.exp(2 * this.pinchDistance);\n this.app.anchor.position.z = this.app.user.forward.position.z * this.scale;\n this.app.anchor.lookAt(this.userWorldPosition);\n }\n });\n\n document.addEventListener('selectend', (event) => {\n if (this.currentEntity == null || this.hand == null || this.hand != event.detail.handedness) {\n return;\n }\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n frame.createAnchor(this.matrix4ToXRRigidTransform(this.currentEntity.object3D.matrixWorld), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n this.currentEntity.anchor = anchor;\n this.anchoringQueue.delete(this.currentEntity);\n this.currentEntity = null;\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n this.hand = null;\n });\n }\n\n /**\n * @function\n * @description This update function maintains the transforms of anchored entities.\n * This overrides any other transform values set on the element when in mixed reality.\n * @param {number} deltaTime - given timestep to be used for any feature changes\n * @param {object} frame - given frame information to be used for any feature changes\n */\n update(deltaTime, frame) {\n if (mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.isPresenting) {\n if (this.currentEntity) {\n this.floating(frame);\n }\n\n if (!this.app.anchor) {\n this.setAppOrigin();\n } else {\n this.updateOrigin(frame);\n }\n }\n\n for (const entity of this.registry) {\n if (mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.isPresenting) {\n let anchorComp = entity.components.get('anchor');\n if (entity.anchor == null && !this.anchoringQueue.has(entity)) {\n entity.object3D.matrixWorldAutoUpdate = false;\n this.createAnchor(entity, anchorComp);\n } else if (entity.anchor) {\n let pose = frame.getPose(entity.anchor.anchorSpace, mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace);\n let transform = this.multiplyQuaternionWithXRRigidTransform(this.axisSwapQuat, pose.transform);\n\n entity.object3D.matrix.copy(this.adjustTransform(transform));\n } else {\n this.createAnchor(entity, anchorComp);\n }\n } else if (entity.anchor) {\n entity.object3D.matrix.copy(entity.object3D.userData.originalMatrix);\n this.deleteAnchor(entity);\n }\n }\n }\n\n /**\n * @function\n * @description Called when the entity component is initialized\n * @param {object} entity - the entity being attached/initialized.\n */\n attachedComponent(entity) {\n entity.object3D.userData.originalMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n entity.object3D.userData.originalMatrix.copy(entity.object3D.matrixWorld);\n entity.object3D.matrixAutoUpdate = false;\n }\n\n /**\n * @function\n * @description Called when the entity component is updated\n * @param {object} entity - the entity being updated based on the component.\n */\n updatedComponent(entity) {\n // delete before creating a new one.\n this.deleteAnchor(entity);\n // // These cases can be managed instantly\n // this.createAnchor(entity, comp);\n }\n\n /**\n * @function\n * @description Called when the entity component is detached\n * @param {object} entity - the entity being updated based on the component being detached.\n */\n detachedComponent(entity) {\n entity.object3D.matrixAutoUpdate = true;\n this.deleteAnchor(entity);\n }\n\n /**\n * @function\n * @description deletes anchors from the scene and removes all references to the anchored plane (if any)\n * @param {object} entity - the entity whose anchor is being deleted.\n */\n deleteAnchor(entity) {\n if (entity.plane) {\n entity.plane.occupied = false;\n entity.plane.mesh.visible = true;\n entity.plane = null;\n }\n entity.anchor = null;\n entity.dispatchEvent(new CustomEvent('anchorremoved', { bubbles: true }));\n }\n\n /**\n * @function\n * @description creates the anchor specified by the data-anchor-comp\n * @param {object} entity - the entity whose anchor is being created.\n * @param {object} comp - the data component with a type value that represents the string 'fixed', 'plane', 'floating', etc\n */\n createAnchor(entity, comp) {\n switch (comp.type) {\n case 'fixed':\n this.fixed(entity);\n break;\n case 'plane':\n this.plane(entity, comp);\n break;\n case 'floating':\n this.currentEntity = entity;\n this.anchoringQueue.add(entity);\n break;\n default:\n break;\n }\n }\n\n /**\n * @function\n * @description Sets the origin of the MRApp being touched by all systems to allow anchoring to position\n * itself properly.\n */\n setAppOrigin() {\n if (!mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.isPresenting) {\n return;\n }\n let originMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n originMatrix.copyPosition(this.app.user.forward.matrixWorld);\n frame.createAnchor(this.matrix4ToXRRigidTransform(originMatrix), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n this.app.origin.matrixAutoUpdate = false;\n this.app.anchor = anchor;\n this.app.dispatchEvent(new CustomEvent('anchored', { bubbles: true }));\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n }\n\n /**\n * @function\n * @description Updates the origin of the MRApp being touched by all systems to allow anchoring to position.\n * @param {object} frame - given frame information to be used for any feature changes (from the update(..) loop)\n */\n updateOrigin(frame) {\n let pose = frame.getPose(this.app.anchor.anchorSpace, mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace);\n let transform = this.multiplyQuaternionWithXRRigidTransform(this.axisSwapQuat, pose.transform);\n\n this.app.origin.matrix.copy(this.adjustTransform(transform, true));\n\n this.originPosition.setFromMatrixPosition(this.app.origin.matrixWorld);\n }\n\n /**\n * @function\n * @description Anchors the given entity half a meter in front of the users position at launch.\n * @param {object} entity - the entity being positioned.\n */\n fixed(entity) {\n this.anchoringQueue.add(entity);\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n frame.createAnchor(this.matrix4ToXRRigidTransform(this.app.user.forward.matrixWorld), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n entity.anchor = anchor;\n entity.dispatchEvent(new CustomEvent('anchored', { bubbles: true }));\n this.anchoringQueue.delete(entity);\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n }\n\n /**\n * @function\n * @description Creates an anchor at the position specified by the user,\n * either floating in front of them or pinned to the scene mesh\n * @param {object} frame - given frame information to be used for any feature changes (from the update(..) loop)\n */\n floating(frame) {\n this.hitResults = frame.getHitTestResults(this.source);\n const hit = this.hitResults[0];\n const pose = hit?.getPose(mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace);\n\n if (pose && this.userWorldPosition.distanceTo(pose.transform.position) < this.snapDistance * this.scale) {\n let transform = this.multiplyQuaternionWithXRRigidTransform(this.axisSwapQuat, pose.transform);\n this.currentEntity.object3D.matrix.copy(this.adjustTransform(transform));\n } else {\n this.currentEntity.object3D.matrix.copy(this.app.anchor.matrixWorld);\n }\n }\n\n /**\n * @function\n * @description Anchors the provided entity to the nearest unoccupied plane that meets the given orientation and label.\n * each plane is currently limited to one anchor for simplicity.\n * @param {object} entity - the entity being anchored by this function.\n * @param {object} comp - the data-component to determine the orientation and label of the associated plane\n */\n plane(entity, comp) {\n this.anchoringQueue.add(entity);\n this.userWorldPosition.setFromMatrixPosition(this.app.user.forward.matrixWorld);\n let sort = Array.from(this.planeManager.planeDictionary[comp.label].values());\n sort.sort((a, b) => {\n return a.mesh.position.distanceTo(this.userWorldPosition) - b.mesh.position.distanceTo(this.userWorldPosition);\n });\n for (const mrPlane of sort) {\n if (mrPlane.occupied) {\n continue;\n }\n if (comp.label && comp.label != mrPlane.label) {\n continue;\n }\n if (comp.orientation && comp.orientation != mrPlane.orientation) {\n continue;\n }\n mrPlane.occupied = true;\n\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n frame.createAnchor(this.matrix4ToXRRigidTransform(mrPlane.mesh.matrixWorld), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n this.anchoringQueue.delete(entity);\n if (!this.planeManager.planeDictionary[comp.label].has(mrPlane)) {\n return;\n }\n if (entity.anchor) {\n return;\n }\n entity.anchor = anchor;\n entity.plane = mrPlane;\n entity.dispatchEvent(new CustomEvent('anchored', { bubbles: true }));\n if (comp.occlusion == false) {\n mrPlane.mesh.visible = false;\n }\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n return;\n }\n }\n\n originalAnchorMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n anchorForwardVector = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(0, 0, 0.03);\n rotationMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n adjustedMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n\n /**\n * @function\n * @description converts the provided XRRigidTransform to a Matrix4 and adjusts it to ensure\n * that it's y-axis is pointing directly up and it's z-axis is facing inward\n * @param {object} xrRigidTransform - a THREE.js transformation matrix that we want to adjust\n * @param {boolean} origin - true if this is positioned at the origin or not (handles special case of div-0).\n * @returns {object} a new adjusted THREE.js Matrix4\n */\n adjustTransform(xrRigidTransform, origin = false) {\n // Create a Three.js Quaternion for the XRRigidTransform's orientation\n let quaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion(xrRigidTransform.orientation.x, xrRigidTransform.orientation.y, xrRigidTransform.orientation.z, xrRigidTransform.orientation.w);\n\n // Create a Three.js Vector for the up direction\n let upVector = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(0, 1, 0);\n\n // Apply the quaternion to the up direction\n let transformedUp = upVector.clone().applyQuaternion(quaternion);\n\n // Calculate the rotation needed to align the transformed up direction with the global up direction\n let correctionQuaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion().setFromUnitVectors(transformedUp, upVector);\n\n // Apply the correction to the original quaternion\n quaternion.premultiply(correctionQuaternion);\n\n // Create a new Three.js Vector3 for the position\n let position = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(xrRigidTransform.position.x, xrRigidTransform.position.y, xrRigidTransform.position.z);\n\n if (!origin) {\n position.sub(this.originPosition);\n }\n\n this.originalAnchorMatrix.compose(position, quaternion, new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(1, 1, 1));\n this.rotationMatrix.extractRotation(this.originalAnchorMatrix);\n\n this.anchorForwardVector.applyMatrix4(this.rotationMatrix);\n this.adjustedMatrix.makeTranslation(this.anchorForwardVector.x, this.anchorForwardVector.y, this.anchorForwardVector.y);\n this.anchorForwardVector.set(0, 0, 0.03);\n this.adjustedMatrix.multiply(this.originalAnchorMatrix);\n\n return this.adjustedMatrix;\n }\n\n /**\n * @function\n * @description Converts the provided matrix4 into a webXR xompatible XRRigidTransform\n * @param {object} matrix4 - the matrix we want to convert to a XRRigidTransform\n * @returns {object} xrRigidTransform - the converted representation of the param matrix4\n */\n matrix4ToXRRigidTransform(matrix4) {\n // Extract the translation component from the Matrix4\n const position = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n position.setFromMatrixPosition(matrix4);\n\n // Extract the rotation component from the Matrix4\n const quaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion();\n quaternion.setFromRotationMatrix(matrix4);\n\n // Create a DOMPointInit for the position\n const positionInit = { x: position.x, y: position.y, z: position.z, w: 1 };\n\n // Create a DOMPointInit for the orientation (quaternion)\n const orientationInit = { x: quaternion.x, y: quaternion.y, z: quaternion.z, w: quaternion.w };\n\n // Create and return the XRRigidTransform\n return new XRRigidTransform(positionInit, orientationInit);\n }\n\n /**\n * @function\n * @description Multiplies an xr rigid transform by the provided quaternion\n * @param {object} quaternion - the quaternion we want to multiply with the xrRigidTransform\n * @param {object} xrRigidTransform - the second part of the multiplication we are looking to perform.\n * @returns {object} xrRigidTransform - the output of the quaternion * xrRigidTransform in the form of an xrRigidTransform\n */\n multiplyQuaternionWithXRRigidTransform(quaternion, xrRigidTransform) {\n // Create a Three.js Quaternion for the XRRigidTransform's orientation\n let transformQuaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion(\n xrRigidTransform.orientation.x,\n xrRigidTransform.orientation.y,\n xrRigidTransform.orientation.z,\n xrRigidTransform.orientation.w\n );\n\n // Multiply the quaternions\n transformQuaternion.multiply(quaternion);\n\n // Create a new XRRigidTransform with the multiplied orientation and original position\n let newPosition = xrRigidTransform.position;\n let newOrientation = new DOMPointReadOnly(transformQuaternion.x, transformQuaternion.y, transformQuaternion.z, transformQuaternion.w);\n\n return new XRRigidTransform(newPosition, newOrientation);\n }\n}\n\n\n//# sourceURL=webpack://mrjs/./src/core/componentSystems/AnchorSystem.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AnchorSystem: () => (/* binding */ AnchorSystem)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var mrjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mrjs */ \"./src/index.js\");\n/* harmony import */ var mrjs_core_MREntity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mrjs/core/MREntity */ \"./src/core/MREntity.js\");\n/* harmony import */ var mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! mrjs/core/MRSystem */ \"./src/core/MRSystem.js\");\n/* harmony import */ var mrjs_dataManagers_MRPlaneManager__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! mrjs/dataManagers/MRPlaneManager */ \"./src/dataManagers/MRPlaneManager.js\");\n\n\n\n\n\n\n\n\n/**\n * @class AnchorSystem\n * @classdesc creates and manages WebXR anchors in the MR scene.\n * @augments MRSystem\n */\nclass AnchorSystem extends mrjs_core_MRSystem__WEBPACK_IMPORTED_MODULE_2__.MRSystem {\n /**\n * @class\n * @description AnchorSystem's default constructor including setting up event listeners for XR initialization, user interaction, and the MRPlaneManager\n */\n constructor() {\n super();\n this.sourceRequest = false;\n this.source;\n this.currentEntity = null;\n this.tempMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n\n this.planeManager = new mrjs_dataManagers_MRPlaneManager__WEBPACK_IMPORTED_MODULE_3__.MRPlaneManager(this.app.scene, this.app.dataset.occlusion);\n this.anchoringQueue = new Set();\n\n this.hitResults;\n\n this.userWorldPosition = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n this.cameraForward = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n this.pinchDistance = 0;\n\n this.axisSwapQuat = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion().setFromAxisAngle(new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(1, 0, 0), -(3 * Math.PI) / 2);\n\n this.hand = null;\n\n this.snapDistance = 0.6;\n\n this.scale = 1;\n\n let existing = document.querySelectorAll('[data-comp-anchor]');\n\n this.originPosition = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n\n for (const entity of existing) {\n this.attachedComponent(entity);\n this.registry.add(entity);\n }\n\n this.app.addEventListener('enterxr', () => {\n if (this.sourceRequest == false) {\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestReferenceSpace('viewer').then((viewerSpace) => {\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestHitTestSource({ space: viewerSpace }).then((source) => {\n this.source = source;\n });\n });\n\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.addEventListener('end', () => {\n this.sourceRequest = false;\n this.source = null;\n this.hand = null;\n });\n\n this.sourceRequest = true;\n }\n });\n\n this.app.addEventListener('exitxr', () => {\n this.deleteAnchor(this.app);\n this.app.origin.matrix.copy(new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4());\n });\n\n document.addEventListener('selectstart', (event) => {\n if (this.currentEntity == null || (this.hand && this.hand != event.detail.handedness)) {\n return;\n }\n if (!event.detail) {\n return;\n }\n this.hand = event.detail.handedness;\n });\n\n document.addEventListener('selectmoved', (event) => {\n if (this.currentEntity && this.hand == event.detail.handedness) {\n this.userWorldPosition.setFromMatrixPosition(this.app.camera.matrixWorld);\n this.cameraForward.setFromMatrixPosition(this.app.user.forward.matrixWorld);\n\n this.pinchDistance = this.cameraForward.distanceTo(event.detail.position);\n this.scale = Math.exp(2 * this.pinchDistance);\n this.app.anchor.position.z = this.app.user.forward.position.z * this.scale;\n this.app.anchor.lookAt(this.userWorldPosition);\n }\n });\n\n document.addEventListener('selectend', (event) => {\n if (this.currentEntity == null || this.hand == null || this.hand != event.detail.handedness) {\n return;\n }\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n frame.createAnchor(this.matrix4ToXRRigidTransform(this.currentEntity.object3D.matrixWorld), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n this.currentEntity.anchor = anchor;\n this.anchoringQueue.delete(this.currentEntity);\n this.currentEntity = null;\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n this.hand = null;\n });\n }\n\n /**\n * @function\n * @description This update function maintains the transforms of anchored entities.\n * This overrides any other transform values set on the element when in mixed reality.\n * @param {number} deltaTime - given timestep to be used for any feature changes\n * @param {object} frame - given frame information to be used for any feature changes\n */\n update(deltaTime, frame) {\n if (mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.isPresenting) {\n if (this.currentEntity) {\n this.floating(frame);\n }\n\n if (!this.app.anchor) {\n this.setAppOrigin();\n } else {\n this.updateOrigin(frame);\n }\n }\n\n for (const entity of this.registry) {\n if (mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.isPresenting) {\n let anchorComp = entity.components.get('anchor');\n if (entity.anchor == null && !this.anchoringQueue.has(entity)) {\n entity.object3D.matrixWorldAutoUpdate = false;\n this.createAnchor(entity, anchorComp);\n } else if (entity.anchor) {\n let pose = frame.getPose(entity.anchor.anchorSpace, mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace);\n let transform = this.multiplyQuaternionWithXRRigidTransform(this.axisSwapQuat, pose.transform);\n\n entity.object3D.matrix.copy(this.adjustTransform(transform));\n } else {\n this.createAnchor(entity, anchorComp);\n }\n } else if (entity.anchor) {\n entity.object3D.matrix.copy(entity.object3D.userData.originalMatrix);\n this.deleteAnchor(entity);\n }\n }\n }\n\n /**\n * @function\n * @description Called when the entity component is initialized\n * @param {object} entity - the entity being attached/initialized.\n */\n attachedComponent(entity) {\n entity.object3D.userData.originalMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n entity.object3D.userData.originalMatrix.copy(entity.object3D.matrixWorld);\n entity.object3D.matrixAutoUpdate = false;\n }\n\n /**\n * @function\n * @description Called when the entity component is updated\n * @param {object} entity - the entity being updated based on the component.\n */\n updatedComponent(entity) {\n // delete before creating a new one.\n this.deleteAnchor(entity);\n // // These cases can be managed instantly\n // this.createAnchor(entity, comp);\n }\n\n /**\n * @function\n * @description Called when the entity component is detached\n * @param {object} entity - the entity being updated based on the component being detached.\n */\n detachedComponent(entity) {\n entity.object3D.matrixAutoUpdate = true;\n this.deleteAnchor(entity);\n }\n\n /**\n * @function\n * @description deletes anchors from the scene and removes all references to the anchored plane (if any)\n * @param {object} entity - the entity whose anchor is being deleted.\n */\n deleteAnchor(entity) {\n if (entity.plane) {\n entity.plane.occupied = false;\n entity.plane.mesh.visible = true;\n entity.plane = null;\n }\n entity.anchor = null;\n entity.dispatchEvent(new CustomEvent('anchorremoved', { bubbles: true }));\n }\n\n /**\n * @function\n * @description creates the anchor specified by the data-anchor-comp\n * @param {object} entity - the entity whose anchor is being created.\n * @param {object} comp - the data component with a type value that represents the string 'fixed', 'plane', 'floating', etc\n */\n createAnchor(entity, comp) {\n switch (comp.type) {\n case 'fixed':\n this.fixed(entity);\n break;\n case 'plane':\n this.plane(entity, comp);\n break;\n case 'floating':\n this.currentEntity = entity;\n this.anchoringQueue.add(entity);\n break;\n default:\n break;\n }\n }\n\n /**\n * @function\n * @description Sets the origin of the MRApp being touched by all systems to allow anchoring to position\n * itself properly.\n */\n setAppOrigin() {\n if (!mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.isPresenting) {\n return;\n }\n let originMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n originMatrix.copyPosition(this.app.user.forward.matrixWorld);\n frame.createAnchor(this.matrix4ToXRRigidTransform(originMatrix), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n this.app.origin.matrixAutoUpdate = false;\n this.app.anchor = anchor;\n this.app.dispatchEvent(new CustomEvent('anchored', { bubbles: true }));\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n }\n\n /**\n * @function\n * @description Updates the origin of the MRApp being touched by all systems to allow anchoring to position.\n * @param {object} frame - given frame information to be used for any feature changes (from the update(..) loop)\n */\n updateOrigin(frame) {\n let pose = frame.getPose(this.app.anchor.anchorSpace, mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace);\n let transform = this.multiplyQuaternionWithXRRigidTransform(this.axisSwapQuat, pose.transform);\n\n this.app.origin.matrix.copy(this.adjustTransform(transform, true));\n\n this.originPosition.setFromMatrixPosition(this.app.origin.matrixWorld);\n }\n\n /**\n * @function\n * @description Anchors the given entity half a meter in front of the users position at launch.\n * @param {object} entity - the entity being positioned.\n */\n fixed(entity) {\n this.anchoringQueue.add(entity);\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n frame.createAnchor(this.matrix4ToXRRigidTransform(this.app.user.forward.matrixWorld), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n entity.anchor = anchor;\n entity.dispatchEvent(new CustomEvent('anchored', { bubbles: true }));\n this.anchoringQueue.delete(entity);\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n }\n\n /**\n * @function\n * @description Creates an anchor at the position specified by the user,\n * either floating in front of them or pinned to the scene mesh\n * @param {object} frame - given frame information to be used for any feature changes (from the update(..) loop)\n */\n floating(frame) {\n this.hitResults = frame.getHitTestResults(this.source);\n const hit = this.hitResults[0];\n const pose = hit?.getPose(mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace);\n\n if (pose && this.userWorldPosition.distanceTo(pose.transform.position) < this.snapDistance * this.scale) {\n let transform = this.multiplyQuaternionWithXRRigidTransform(this.axisSwapQuat, pose.transform);\n this.currentEntity.object3D.matrix.copy(this.adjustTransform(transform));\n } else {\n this.currentEntity.object3D.matrix.copy(this.app.anchor.matrixWorld);\n }\n }\n\n /**\n * @function\n * @description Anchors the provided entity to the nearest unoccupied plane that meets the given orientation and label.\n * each plane is currently limited to one anchor for simplicity.\n * @param {object} entity - the entity being anchored by this function.\n * @param {object} comp - the data-component to determine the orientation and label of the associated plane\n */\n plane(entity, comp) {\n this.anchoringQueue.add(entity);\n this.userWorldPosition.setFromMatrixPosition(this.app.user.forward.matrixWorld);\n let sort = Array.from(this.planeManager.planeDictionary[comp.label].values());\n sort.sort((a, b) => {\n return a.mesh.position.distanceTo(this.userWorldPosition) - b.mesh.position.distanceTo(this.userWorldPosition);\n });\n for (const mrPlane of sort) {\n if (mrPlane.occupied) {\n continue;\n }\n if (comp.label && comp.label != mrPlane.label) {\n continue;\n }\n if (comp.orientation && comp.orientation != mrPlane.orientation) {\n continue;\n }\n mrPlane.occupied = true;\n\n mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.session.requestAnimationFrame((t, frame) => {\n frame.createAnchor(this.matrix4ToXRRigidTransform(mrPlane.mesh.matrixWorld), mrjs__WEBPACK_IMPORTED_MODULE_0__.mrjsUtils.xr.referenceSpace).then(\n (anchor) => {\n this.anchoringQueue.delete(entity);\n if (!this.planeManager.planeDictionary[comp.label].has(mrPlane)) {\n return;\n }\n if (entity.anchor) {\n return;\n }\n entity.anchor = anchor;\n entity.plane = mrPlane;\n entity.dispatchEvent(new CustomEvent('anchored', { bubbles: true }));\n if (comp.occlusion == false) {\n mrPlane.mesh.visible = false;\n }\n },\n (error) => {\n console.error('Could not create anchor: ' + error);\n }\n );\n });\n return;\n }\n }\n\n originalAnchorMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n anchorForwardVector = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(0, 0, 0.03);\n rotationMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n adjustedMatrix = new three__WEBPACK_IMPORTED_MODULE_4__.Matrix4();\n\n /**\n * @function\n * @description converts the provided XRRigidTransform to a Matrix4 and adjusts it to ensure\n * that it's y-axis is pointing directly up and it's z-axis is facing inward\n * @param {object} xrRigidTransform - a THREE.js transformation matrix that we want to adjust\n * @param {boolean} origin - true if this is positioned at the origin or not (handles special case of div-0).\n * @returns {object} a new adjusted THREE.js Matrix4\n */\n adjustTransform(xrRigidTransform, origin = false) {\n // Create a Three.js Quaternion for the XRRigidTransform's orientation\n let quaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion(xrRigidTransform.orientation.x, xrRigidTransform.orientation.y, xrRigidTransform.orientation.z, xrRigidTransform.orientation.w);\n\n // Create a Three.js Vector for the up direction\n let upVector = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(0, 1, 0);\n\n // Apply the quaternion to the up direction\n let transformedUp = upVector.clone().applyQuaternion(quaternion);\n\n // Calculate the rotation needed to align the transformed up direction with the global up direction\n let correctionQuaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion().setFromUnitVectors(transformedUp, upVector);\n\n // Apply the correction to the original quaternion\n quaternion.premultiply(correctionQuaternion);\n\n // Create a new Three.js Vector3 for the position\n let position = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(xrRigidTransform.position.x, xrRigidTransform.position.y, xrRigidTransform.position.z);\n\n if (!origin) {\n position.sub(this.originPosition);\n }\n\n this.originalAnchorMatrix.compose(position, quaternion, new three__WEBPACK_IMPORTED_MODULE_4__.Vector3(1, 1, 1));\n this.rotationMatrix.extractRotation(this.originalAnchorMatrix);\n\n this.anchorForwardVector.applyMatrix4(this.rotationMatrix);\n this.adjustedMatrix.makeTranslation(this.anchorForwardVector.x, this.anchorForwardVector.y, this.anchorForwardVector.y);\n this.anchorForwardVector.set(0, 0, 0.03);\n this.adjustedMatrix.multiply(this.originalAnchorMatrix);\n\n return this.adjustedMatrix;\n }\n\n /**\n * @function\n * @description Converts the provided matrix4 into a webXR xompatible XRRigidTransform\n * @param {object} matrix4 - the matrix we want to convert to a XRRigidTransform\n * @returns {object} xrRigidTransform - the converted representation of the param matrix4\n */\n matrix4ToXRRigidTransform(matrix4) {\n // Extract the translation component from the Matrix4\n const position = new three__WEBPACK_IMPORTED_MODULE_4__.Vector3();\n position.setFromMatrixPosition(matrix4);\n\n // Extract the rotation component from the Matrix4\n const quaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion();\n quaternion.setFromRotationMatrix(matrix4);\n\n // Create a DOMPointInit for the position\n const positionInit = { x: position.x, y: position.y, z: position.z, w: 1 };\n\n // Create a DOMPointInit for the orientation (quaternion)\n const orientationInit = { x: quaternion.x, y: quaternion.y, z: quaternion.z, w: quaternion.w };\n\n // Create and return the XRRigidTransform\n return new XRRigidTransform(positionInit, orientationInit);\n }\n\n /**\n * @function\n * @description Multiplies an xr rigid transform by the provided quaternion\n * @param {object} quaternion - the quaternion we want to multiply with the xrRigidTransform\n * @param {object} xrRigidTransform - the second part of the multiplication we are looking to perform.\n * @returns {object} xrRigidTransform - the output of the quaternion * xrRigidTransform in the form of an xrRigidTransform\n */\n multiplyQuaternionWithXRRigidTransform(quaternion, xrRigidTransform) {\n // Create a Three.js Quaternion for the XRRigidTransform's orientation\n let transformQuaternion = new three__WEBPACK_IMPORTED_MODULE_4__.Quaternion(\n xrRigidTransform.orientation.x,\n xrRigidTransform.orientation.y,\n xrRigidTransform.orientation.z,\n xrRigidTransform.orientation.w\n );\n\n // Multiply the quaternions\n transformQuaternion.multiply(quaternion);\n\n // Create a new XRRigidTransform with the multiplied orientation and original position\n let newPosition = xrRigidTransform.position;\n let newOrientation = new DOMPointReadOnly(transformQuaternion.x, transformQuaternion.y, transformQuaternion.z, transformQuaternion.w);\n\n return new XRRigidTransform(newPosition, newOrientation);\n }\n}\n\n\n//# sourceURL=webpack://mrjs/./src/core/componentSystems/AnchorSystem.js?"); /***/ }),