@srsergio/taptapp-ar 1.0.101 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/compiler/node-worker.js +1 -197
  2. package/dist/compiler/offline-compiler.js +1 -207
  3. package/dist/core/constants.js +1 -38
  4. package/dist/core/detector/crop-detector.js +1 -88
  5. package/dist/core/detector/detector-lite.js +1 -455
  6. package/dist/core/detector/freak.js +1 -89
  7. package/dist/core/estimation/estimate.js +1 -16
  8. package/dist/core/estimation/estimator.js +1 -30
  9. package/dist/core/estimation/morph-refinement.js +1 -116
  10. package/dist/core/estimation/non-rigid-refine.js +1 -70
  11. package/dist/core/estimation/pnp-solver.js +1 -109
  12. package/dist/core/estimation/refine-estimate.js +1 -311
  13. package/dist/core/estimation/utils.js +1 -67
  14. package/dist/core/features/auto-rotation-feature.js +1 -30
  15. package/dist/core/features/crop-detection-feature.js +1 -26
  16. package/dist/core/features/feature-base.js +1 -1
  17. package/dist/core/features/feature-manager.js +1 -55
  18. package/dist/core/features/one-euro-filter-feature.js +1 -44
  19. package/dist/core/features/temporal-filter-feature.js +1 -57
  20. package/dist/core/image-list.js +1 -54
  21. package/dist/core/input-loader.js +1 -87
  22. package/dist/core/matching/hamming-distance.js +1 -66
  23. package/dist/core/matching/hdc.js +1 -102
  24. package/dist/core/matching/hierarchical-clustering.js +1 -130
  25. package/dist/core/matching/hough.js +1 -170
  26. package/dist/core/matching/matcher.js +1 -66
  27. package/dist/core/matching/matching.js +1 -401
  28. package/dist/core/matching/ransacHomography.js +1 -132
  29. package/dist/core/perception/bio-inspired-engine.js +1 -232
  30. package/dist/core/perception/foveal-attention.js +1 -280
  31. package/dist/core/perception/index.js +1 -17
  32. package/dist/core/perception/predictive-coding.js +1 -278
  33. package/dist/core/perception/saccadic-controller.js +1 -269
  34. package/dist/core/perception/saliency-map.js +1 -254
  35. package/dist/core/perception/scale-orchestrator.js +1 -68
  36. package/dist/core/protocol.js +1 -254
  37. package/dist/core/tracker/extract-utils.js +1 -29
  38. package/dist/core/tracker/extract.js +1 -306
  39. package/dist/core/tracker/tracker.js +1 -352
  40. package/dist/core/utils/cumsum.js +1 -37
  41. package/dist/core/utils/delaunay.js +1 -125
  42. package/dist/core/utils/geometry.js +1 -101
  43. package/dist/core/utils/gpu-compute.js +1 -231
  44. package/dist/core/utils/homography.js +1 -138
  45. package/dist/core/utils/images.js +1 -108
  46. package/dist/core/utils/lsh-binarizer.js +1 -37
  47. package/dist/core/utils/lsh-direct.js +1 -76
  48. package/dist/core/utils/projection.js +1 -51
  49. package/dist/core/utils/randomizer.js +1 -25
  50. package/dist/core/utils/worker-pool.js +1 -89
  51. package/dist/index.js +1 -7
  52. package/dist/libs/one-euro-filter.js +1 -70
  53. package/dist/react/TaptappAR.js +1 -151
  54. package/dist/react/types.js +1 -16
  55. package/dist/react/use-ar.js +1 -118
  56. package/dist/runtime/aframe.js +1 -272
  57. package/dist/runtime/bio-inspired-controller.js +1 -358
  58. package/dist/runtime/controller.js +1 -592
  59. package/dist/runtime/controller.worker.js +1 -93
  60. package/dist/runtime/index.js +1 -5
  61. package/dist/runtime/three.js +1 -304
  62. package/dist/runtime/track.js +1 -381
  63. package/package.json +9 -3
@@ -1,93 +1 @@
1
- import { Matcher } from "../core/matching/matcher.js";
2
- import { Estimator } from "../core/estimation/estimator.js";
3
- import { Tracker } from "../core/tracker/tracker.js";
4
- import { DetectorLite } from "../core/detector/detector-lite.js";
5
- let matchingDataList = null;
6
- let debugMode = false;
7
- let matcher = null;
8
- let estimator = null;
9
- let tracker = null;
10
- let detector = null;
11
- onmessage = (msg) => {
12
- const { data } = msg;
13
- switch (data.type) {
14
- case "setup":
15
- matchingDataList = data.matchingDataList;
16
- debugMode = data.debugMode;
17
- matcher = new Matcher(data.inputWidth, data.inputHeight, debugMode);
18
- estimator = new Estimator(data.projectionTransform);
19
- if (data.trackingDataList && data.markerDimensions) {
20
- tracker = new Tracker(data.markerDimensions, data.trackingDataList, data.projectionTransform, data.inputWidth, data.inputHeight, debugMode);
21
- }
22
- detector = new DetectorLite(data.inputWidth, data.inputHeight, {
23
- useLSH: true,
24
- maxFeaturesPerBucket: 24
25
- });
26
- break;
27
- case "match":
28
- const interestedTargetIndexes = data.targetIndexes;
29
- let matchedTargetIndex = -1;
30
- let matchedModelViewTransform = null;
31
- let matchedScreenCoords = null;
32
- let matchedWorldCoords = null;
33
- let matchedDebugExtra = null;
34
- // New: If the worker received image data, run detector here too
35
- let featurePoints = data.featurePoints;
36
- if (data.inputData) {
37
- const detectionResult = detector.detect(data.inputData, { octavesToProcess: data.octavesToProcess });
38
- featurePoints = detectionResult.featurePoints;
39
- }
40
- for (let i = 0; i < interestedTargetIndexes.length; i++) {
41
- const matchingIndex = interestedTargetIndexes[i];
42
- const { keyframeIndex, screenCoords, worldCoords, debugExtra } = matcher.matchDetection(matchingDataList[matchingIndex], featurePoints, data.expectedScale);
43
- matchedDebugExtra = debugExtra;
44
- if (keyframeIndex !== -1) {
45
- const modelViewTransform = estimator.estimate({ screenCoords, worldCoords });
46
- if (modelViewTransform) {
47
- matchedTargetIndex = matchingIndex;
48
- matchedModelViewTransform = modelViewTransform;
49
- matchedScreenCoords = screenCoords;
50
- matchedWorldCoords = worldCoords;
51
- }
52
- break;
53
- }
54
- }
55
- postMessage({
56
- type: "matchDone",
57
- targetIndex: matchedTargetIndex,
58
- modelViewTransform: matchedModelViewTransform,
59
- screenCoords: matchedScreenCoords,
60
- worldCoords: matchedWorldCoords,
61
- featurePoints: featurePoints,
62
- debugExtra: matchedDebugExtra,
63
- });
64
- break;
65
- case "track":
66
- const { inputData: trackInput, lastModelViewTransform, targetIndex } = data;
67
- const trackResult = tracker.track(trackInput, lastModelViewTransform, targetIndex);
68
- postMessage({
69
- type: "trackDone",
70
- targetIndex,
71
- ...trackResult
72
- });
73
- break;
74
- case "trackUpdate":
75
- const { modelViewTransform, worldCoords, screenCoords, stabilities } = data;
76
- const finalModelViewTransform = estimator.refineEstimate({
77
- initialModelViewTransform: modelViewTransform,
78
- worldCoords,
79
- screenCoords,
80
- stabilities, // Stability-based weights
81
- });
82
- postMessage({
83
- type: "trackUpdateDone",
84
- modelViewTransform: finalModelViewTransform,
85
- });
86
- break;
87
- case "dispose":
88
- close();
89
- break;
90
- default:
91
- throw new Error(`Invalid message type '${data.type}'`);
92
- }
93
- };
1
+ import{Matcher as e}from"../core/matching/matcher.js";import{Estimator as t}from"../core/estimation/estimator.js";import{Tracker as r}from"../core/tracker/tracker.js";import{DetectorLite as o}from"../core/detector/detector-lite.js";let s=null,a=!1,n=null,i=null,c=null,d=null;onmessage=l=>{const{data:m}=l;switch(m.type){case"setup":s=m.matchingDataList,a=m.debugMode,n=new e(m.inputWidth,m.inputHeight,a),i=new t(m.projectionTransform),m.trackingDataList&&m.markerDimensions&&(c=new r(m.markerDimensions,m.trackingDataList,m.projectionTransform,m.inputWidth,m.inputHeight,a)),d=new o(m.inputWidth,m.inputHeight,{useLSH:!0,maxFeaturesPerBucket:24});break;case"match":const l=m.targetIndexes;let p=-1,u=null,g=null,f=null,k=null,w=m.featurePoints;m.inputData&&(w=d.detect(m.inputData,{octavesToProcess:m.octavesToProcess}).featurePoints);for(let e=0;e<l.length;e++){const t=l[e],{keyframeIndex:r,screenCoords:o,worldCoords:a,debugExtra:c}=n.matchDetection(s[t],w,m.expectedScale);if(k=c,-1!==r){const e=i.estimate({screenCoords:o,worldCoords:a});e&&(p=t,u=e,g=o,f=a);break}}postMessage({type:"matchDone",targetIndex:p,modelViewTransform:u,screenCoords:g,worldCoords:f,featurePoints:w,debugExtra:k});break;case"track":const{inputData:h,lastModelViewTransform:D,targetIndex:b}=m,C=c.track(h,D,b);postMessage({type:"trackDone",targetIndex:b,...C});break;case"trackUpdate":const{modelViewTransform:x,worldCoords:T,screenCoords:y,stabilities:j}=m,I=i.refineEstimate({initialModelViewTransform:x,worldCoords:T,screenCoords:y,stabilities:j});postMessage({type:"trackUpdateDone",modelViewTransform:I});break;case"dispose":close();break;default:throw new Error(`Invalid message type '${m.type}'`)}};
@@ -1,5 +1 @@
1
- export * from "./controller.js";
2
- export * from "./bio-inspired-controller.js";
3
- export * from "./track.js";
4
- export * from "./three.js";
5
- export * from "./aframe.js";
1
+ export*from"./controller.js";export*from"./bio-inspired-controller.js";export*from"./track.js";export*from"./three.js";export*from"./aframe.js";
@@ -1,304 +1 @@
1
- import { Matrix4, Vector3, Quaternion, Scene, WebGLRenderer, PerspectiveCamera, Group, sRGBEncoding, } from "three";
2
- import { CSS3DRenderer } from "three/addons/renderers/CSS3DRenderer.js";
3
- import { Controller } from "./controller.js";
4
- import { UI } from "../ui/ui.js";
5
- const cssScaleDownMatrix = new Matrix4();
6
- cssScaleDownMatrix.compose(new Vector3(), new Quaternion(), new Vector3(0.001, 0.001, 0.001));
7
- const invisibleMatrix = new Matrix4().set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
8
- export class TaarThree {
9
- constructor({ container, imageTargetSrc, maxTrack, uiLoading = "yes", uiScanning = "yes", uiError = "yes", filterMinCF = null, filterBeta = null, warmupTolerance = null, missTolerance = null, userDeviceId = null, environmentDeviceId = null, }) {
10
- this.container = container;
11
- this.imageTargetSrc = imageTargetSrc;
12
- this.maxTrack = maxTrack;
13
- this.filterMinCF = filterMinCF;
14
- this.filterBeta = filterBeta;
15
- this.warmupTolerance = warmupTolerance;
16
- this.missTolerance = missTolerance;
17
- this.ui = new UI({ uiLoading, uiScanning, uiError });
18
- this.userDeviceId = userDeviceId;
19
- this.environmentDeviceId = environmentDeviceId;
20
- this.shouldFaceUser = false;
21
- this.scene = new Scene();
22
- this.cssScene = new Scene();
23
- this.renderer = new WebGLRenderer({ antialias: true, alpha: true });
24
- this.cssRenderer = new CSS3DRenderer({ antialias: true });
25
- this.renderer.outputEncoding = sRGBEncoding;
26
- this.renderer.setPixelRatio(window.devicePixelRatio);
27
- this.camera = new PerspectiveCamera();
28
- this.anchors = [];
29
- this.renderer.domElement.style.position = "absolute";
30
- this.cssRenderer.domElement.style.position = "absolute";
31
- this.container.appendChild(this.renderer.domElement);
32
- this.container.appendChild(this.cssRenderer.domElement);
33
- window.addEventListener("resize", this.resize.bind(this));
34
- }
35
- async start() {
36
- this.ui.showLoading();
37
- await this._startVideo();
38
- await this._startAR();
39
- }
40
- stop() {
41
- this.controller.stopProcessVideo();
42
- const tracks = this.video.srcObject.getTracks();
43
- tracks.forEach(function (track) {
44
- track.stop();
45
- });
46
- this.video.remove();
47
- }
48
- switchCamera() {
49
- this.shouldFaceUser = !this.shouldFaceUser;
50
- this.stop();
51
- this.start();
52
- }
53
- addAnchor(targetIndex) {
54
- const group = new Group();
55
- group.visible = false;
56
- group.matrixAutoUpdate = false;
57
- const anchor = {
58
- group,
59
- targetIndex,
60
- onTargetFound: null,
61
- onTargetLost: null,
62
- onTargetUpdate: null,
63
- css: false,
64
- visible: false,
65
- };
66
- this.anchors.push(anchor);
67
- this.scene.add(group);
68
- return anchor;
69
- }
70
- addCSSAnchor(targetIndex) {
71
- const group = new Group();
72
- group.visible = false;
73
- group.matrixAutoUpdate = false;
74
- const anchor = {
75
- group,
76
- targetIndex,
77
- onTargetFound: null,
78
- onTargetLost: null,
79
- onTargetUpdate: null,
80
- css: true,
81
- visible: false,
82
- };
83
- this.anchors.push(anchor);
84
- this.cssScene.add(group);
85
- return anchor;
86
- }
87
- _startVideo() {
88
- return new Promise((resolve) => {
89
- this.video = document.createElement("video");
90
- this.video.setAttribute("autoplay", "");
91
- this.video.setAttribute("muted", "");
92
- this.video.setAttribute("playsinline", "");
93
- this.video.style.position = "absolute";
94
- this.video.style.top = "0px";
95
- this.video.style.left = "0px";
96
- this.video.style.zIndex = "-2";
97
- this.container.appendChild(this.video);
98
- if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
99
- this.ui.showCompatibility();
100
- reject();
101
- return;
102
- }
103
- const constraints = {
104
- audio: false,
105
- video: {},
106
- };
107
- if (this.shouldFaceUser) {
108
- if (this.userDeviceId) {
109
- constraints.video.deviceId = { exact: this.userDeviceId };
110
- }
111
- else {
112
- constraints.video.facingMode = "user";
113
- }
114
- }
115
- else {
116
- if (this.environmentDeviceId) {
117
- constraints.video.deviceId = { exact: this.environmentDeviceId };
118
- }
119
- else {
120
- constraints.video.facingMode = "environment";
121
- }
122
- }
123
- navigator.mediaDevices
124
- .getUserMedia(constraints)
125
- .then((stream) => {
126
- this.video.addEventListener("loadedmetadata", () => {
127
- this.video.setAttribute("width", this.video.videoWidth);
128
- this.video.setAttribute("height", this.video.videoHeight);
129
- resolve();
130
- });
131
- this.video.srcObject = stream;
132
- })
133
- .catch((err) => {
134
- console.log("getUserMedia error", err);
135
- reject();
136
- });
137
- });
138
- }
139
- _startAR() {
140
- return new Promise(async (resolve) => {
141
- const video = this.video;
142
- this.controller = new Controller({
143
- inputWidth: video.videoWidth,
144
- inputHeight: video.videoHeight,
145
- filterMinCF: this.filterMinCF,
146
- filterBeta: this.filterBeta,
147
- warmupTolerance: this.warmupTolerance,
148
- missTolerance: this.missTolerance,
149
- maxTrack: this.maxTrack,
150
- onUpdate: (data) => {
151
- if (data.type === "updateMatrix") {
152
- const { targetIndex, worldMatrix } = data;
153
- for (let i = 0; i < this.anchors.length; i++) {
154
- if (this.anchors[i].targetIndex === targetIndex) {
155
- if (this.anchors[i].css) {
156
- this.anchors[i].group.children.forEach((obj) => {
157
- obj.element.style.visibility = worldMatrix === null ? "hidden" : "visible";
158
- });
159
- }
160
- else {
161
- this.anchors[i].group.visible = worldMatrix !== null;
162
- }
163
- if (worldMatrix !== null) {
164
- let m = new Matrix4();
165
- m.elements = [...worldMatrix];
166
- m.multiply(this.postMatrixs[targetIndex]);
167
- if (this.anchors[i].css) {
168
- m.multiply(cssScaleDownMatrix);
169
- }
170
- this.anchors[i].group.matrix = m;
171
- }
172
- else {
173
- this.anchors[i].group.matrix = invisibleMatrix;
174
- }
175
- if (this.anchors[i].visible && worldMatrix === null) {
176
- this.anchors[i].visible = false;
177
- if (this.anchors[i].onTargetLost) {
178
- this.anchors[i].onTargetLost();
179
- }
180
- }
181
- if (!this.anchors[i].visible && worldMatrix !== null) {
182
- this.anchors[i].visible = true;
183
- if (this.anchors[i].onTargetFound) {
184
- this.anchors[i].onTargetFound();
185
- }
186
- }
187
- if (this.anchors[i].onTargetUpdate) {
188
- this.anchors[i].onTargetUpdate();
189
- }
190
- }
191
- }
192
- let isAnyVisible = this.anchors.reduce((acc, anchor) => {
193
- return acc || anchor.visible;
194
- }, false);
195
- if (isAnyVisible) {
196
- this.ui.hideScanning();
197
- }
198
- else {
199
- this.ui.showScanning();
200
- }
201
- }
202
- },
203
- });
204
- this.resize();
205
- const { dimensions: imageTargetDimensions } = await this.controller.addImageTargets(this.imageTargetSrc);
206
- this.postMatrixs = [];
207
- for (let i = 0; i < imageTargetDimensions.length; i++) {
208
- const position = new Vector3();
209
- const quaternion = new Quaternion();
210
- const scale = new Vector3();
211
- const [markerWidth, markerHeight] = imageTargetDimensions[i];
212
- position.x = markerWidth / 2;
213
- position.y = markerWidth / 2 + (markerHeight - markerWidth) / 2;
214
- scale.x = markerWidth;
215
- scale.y = markerWidth;
216
- scale.z = markerWidth;
217
- const postMatrix = new Matrix4();
218
- postMatrix.compose(position, quaternion, scale);
219
- this.postMatrixs.push(postMatrix);
220
- }
221
- this.controller.dummyRun(this.video);
222
- this.ui.hideLoading();
223
- this.ui.showScanning();
224
- this.controller.processVideo(this.video);
225
- resolve();
226
- });
227
- }
228
- resize() {
229
- const { renderer, cssRenderer, camera, container, video } = this;
230
- if (!video)
231
- return;
232
- this.video.setAttribute("width", this.video.videoWidth);
233
- this.video.setAttribute("height", this.video.videoHeight);
234
- let vw, vh; // display css width, height
235
- const videoRatio = video.videoWidth / video.videoHeight;
236
- const containerRatio = container.clientWidth / container.clientHeight;
237
- if (videoRatio > containerRatio) {
238
- vh = container.clientHeight;
239
- vw = vh * videoRatio;
240
- }
241
- else {
242
- vw = container.clientWidth;
243
- vh = vw / videoRatio;
244
- }
245
- const proj = this.controller.getProjectionMatrix();
246
- // TODO: move this logic to controller
247
- // Handle when phone is rotated, video width and height are swapped
248
- const inputRatio = this.controller.inputWidth / this.controller.inputHeight;
249
- let inputAdjust;
250
- if (inputRatio > containerRatio) {
251
- inputAdjust = this.video.width / this.controller.inputWidth;
252
- }
253
- else {
254
- inputAdjust = this.video.height / this.controller.inputHeight;
255
- }
256
- let videoDisplayHeight;
257
- let videoDisplayWidth;
258
- if (inputRatio > containerRatio) {
259
- videoDisplayHeight = container.clientHeight;
260
- videoDisplayHeight *= inputAdjust;
261
- }
262
- else {
263
- videoDisplayWidth = container.clientWidth;
264
- videoDisplayHeight =
265
- (videoDisplayWidth / this.controller.inputWidth) * this.controller.inputHeight;
266
- videoDisplayHeight *= inputAdjust;
267
- }
268
- let fovAdjust = container.clientHeight / videoDisplayHeight;
269
- // const fov = 2 * Math.atan(1 / proj[5] / vh * container.clientHeight) * 180 / Math.PI; // vertical fov
270
- const fov = (2 * Math.atan((1 / proj[5]) * fovAdjust) * 180) / Math.PI; // vertical fov
271
- const near = proj[14] / (proj[10] - 1.0);
272
- const far = proj[14] / (proj[10] + 1.0);
273
- camera.fov = fov;
274
- camera.near = near;
275
- camera.far = far;
276
- camera.aspect = container.clientWidth / container.clientHeight;
277
- camera.updateProjectionMatrix();
278
- video.style.top = -(vh - container.clientHeight) / 2 + "px";
279
- video.style.left = -(vw - container.clientWidth) / 2 + "px";
280
- video.style.width = vw + "px";
281
- video.style.height = vh + "px";
282
- const canvas = renderer.domElement;
283
- const cssCanvas = cssRenderer.domElement;
284
- canvas.style.position = "absolute";
285
- canvas.style.left = 0;
286
- canvas.style.top = 0;
287
- canvas.style.width = container.clientWidth + "px";
288
- canvas.style.height = container.clientHeight + "px";
289
- cssCanvas.style.position = "absolute";
290
- cssCanvas.style.left = 0;
291
- cssCanvas.style.top = 0;
292
- cssCanvas.style.width = container.clientWidth + "px";
293
- cssCanvas.style.height = container.clientHeight + "px";
294
- renderer.setSize(container.clientWidth, container.clientHeight);
295
- cssRenderer.setSize(container.clientWidth, container.clientHeight);
296
- }
297
- }
298
- if (!window.TAAR) {
299
- window.TAAR = {};
300
- }
301
- if (!window.TAAR.IMAGE) {
302
- window.TAAR.IMAGE = {};
303
- }
304
- window.TAAR.IMAGE.TaarThree = TaarThree;
1
+ import{Matrix4 as e,Vector3 as t,Quaternion as i,Scene as s,WebGLRenderer as n,PerspectiveCamera as o,Group as r,sRGBEncoding as h}from"three";import{CSS3DRenderer as a}from"three/addons/renderers/CSS3DRenderer.js";import{Controller as l}from"./controller.js";import{UI as d}from"../ui/ui.js";const c=new e;c.compose(new t,new i,new t(.001,.001,.001));const u=(new e).set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1);export class TaarThree{constructor({container:e,imageTargetSrc:t,maxTrack:i,uiLoading:r="yes",uiScanning:l="yes",uiError:c="yes",filterMinCF:u=null,filterBeta:v=null,warmupTolerance:p=null,missTolerance:g=null,userDeviceId:m=null,environmentDeviceId:w=null}){this.container=e,this.imageTargetSrc=t,this.maxTrack=i,this.filterMinCF=u,this.filterBeta=v,this.warmupTolerance=p,this.missTolerance=g,this.ui=new d({uiLoading:r,uiScanning:l,uiError:c}),this.userDeviceId=m,this.environmentDeviceId=w,this.shouldFaceUser=!1,this.scene=new s,this.cssScene=new s,this.renderer=new n({antialias:!0,alpha:!0}),this.cssRenderer=new a({antialias:!0}),this.renderer.outputEncoding=h,this.renderer.setPixelRatio(window.devicePixelRatio),this.camera=new o,this.anchors=[],this.renderer.domElement.style.position="absolute",this.cssRenderer.domElement.style.position="absolute",this.container.appendChild(this.renderer.domElement),this.container.appendChild(this.cssRenderer.domElement),window.addEventListener("resize",this.resize.bind(this))}async start(){this.ui.showLoading(),await this._startVideo(),await this._startAR()}stop(){this.controller.stopProcessVideo(),this.video.srcObject.getTracks().forEach(function(e){e.stop()}),this.video.remove()}switchCamera(){this.shouldFaceUser=!this.shouldFaceUser,this.stop(),this.start()}addAnchor(e){const t=new r;t.visible=!1,t.matrixAutoUpdate=!1;const i={group:t,targetIndex:e,onTargetFound:null,onTargetLost:null,onTargetUpdate:null,css:!1,visible:!1};return this.anchors.push(i),this.scene.add(t),i}addCSSAnchor(e){const t=new r;t.visible=!1,t.matrixAutoUpdate=!1;const i={group:t,targetIndex:e,onTargetFound:null,onTargetLost:null,onTargetUpdate:null,css:!0,visible:!1};return this.anchors.push(i),this.cssScene.add(t),i}_startVideo(){return new Promise(e=>{if(this.video=document.createElement("video"),this.video.setAttribute("autoplay",""),this.video.setAttribute("muted",""),this.video.setAttribute("playsinline",""),this.video.style.position="absolute",this.video.style.top="0px",this.video.style.left="0px",this.video.style.zIndex="-2",this.container.appendChild(this.video),!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia)return this.ui.showCompatibility(),void reject();const t={audio:!1,video:{}};this.shouldFaceUser?this.userDeviceId?t.video.deviceId={exact:this.userDeviceId}:t.video.facingMode="user":this.environmentDeviceId?t.video.deviceId={exact:this.environmentDeviceId}:t.video.facingMode="environment",navigator.mediaDevices.getUserMedia(t).then(t=>{this.video.addEventListener("loadedmetadata",()=>{this.video.setAttribute("width",this.video.videoWidth),this.video.setAttribute("height",this.video.videoHeight),e()}),this.video.srcObject=t}).catch(e=>{console.log("getUserMedia error",e),reject()})})}_startAR(){return new Promise(async s=>{const n=this.video;this.controller=new l({inputWidth:n.videoWidth,inputHeight:n.videoHeight,filterMinCF:this.filterMinCF,filterBeta:this.filterBeta,warmupTolerance:this.warmupTolerance,missTolerance:this.missTolerance,maxTrack:this.maxTrack,onUpdate:t=>{if("updateMatrix"===t.type){const{targetIndex:i,worldMatrix:s}=t;for(let t=0;t<this.anchors.length;t++)if(this.anchors[t].targetIndex===i){if(this.anchors[t].css?this.anchors[t].group.children.forEach(e=>{e.element.style.visibility=null===s?"hidden":"visible"}):this.anchors[t].group.visible=null!==s,null!==s){let n=new e;n.elements=[...s],n.multiply(this.postMatrixs[i]),this.anchors[t].css&&n.multiply(c),this.anchors[t].group.matrix=n}else this.anchors[t].group.matrix=u;this.anchors[t].visible&&null===s&&(this.anchors[t].visible=!1,this.anchors[t].onTargetLost&&this.anchors[t].onTargetLost()),this.anchors[t].visible||null===s||(this.anchors[t].visible=!0,this.anchors[t].onTargetFound&&this.anchors[t].onTargetFound()),this.anchors[t].onTargetUpdate&&this.anchors[t].onTargetUpdate()}this.anchors.reduce((e,t)=>e||t.visible,!1)?this.ui.hideScanning():this.ui.showScanning()}}}),this.resize();const{dimensions:o}=await this.controller.addImageTargets(this.imageTargetSrc);this.postMatrixs=[];for(let s=0;s<o.length;s++){const n=new t,r=new i,h=new t,[a,l]=o[s];n.x=a/2,n.y=a/2+(l-a)/2,h.x=a,h.y=a,h.z=a;const d=new e;d.compose(n,r,h),this.postMatrixs.push(d)}this.controller.dummyRun(this.video),this.ui.hideLoading(),this.ui.showScanning(),this.controller.processVideo(this.video),s()})}resize(){const{renderer:e,cssRenderer:t,camera:i,container:s,video:n}=this;if(!n)return;let o,r;this.video.setAttribute("width",this.video.videoWidth),this.video.setAttribute("height",this.video.videoHeight);const h=n.videoWidth/n.videoHeight,a=s.clientWidth/s.clientHeight;h>a?(r=s.clientHeight,o=r*h):(o=s.clientWidth,r=o/h);const l=this.controller.getProjectionMatrix(),d=this.controller.inputWidth/this.controller.inputHeight;let c,u,v;c=d>a?this.video.width/this.controller.inputWidth:this.video.height/this.controller.inputHeight,d>a?(u=s.clientHeight,u*=c):(v=s.clientWidth,u=v/this.controller.inputWidth*this.controller.inputHeight,u*=c);let p=s.clientHeight/u;const g=2*Math.atan(1/l[5]*p)*180/Math.PI,m=l[14]/(l[10]-1),w=l[14]/(l[10]+1);i.fov=g,i.near=m,i.far=w,i.aspect=s.clientWidth/s.clientHeight,i.updateProjectionMatrix(),n.style.top=-(r-s.clientHeight)/2+"px",n.style.left=-(o-s.clientWidth)/2+"px",n.style.width=o+"px",n.style.height=r+"px";const T=e.domElement,x=t.domElement;T.style.position="absolute",T.style.left=0,T.style.top=0,T.style.width=s.clientWidth+"px",T.style.height=s.clientHeight+"px",x.style.position="absolute",x.style.left=0,x.style.top=0,x.style.width=s.clientWidth+"px",x.style.height=s.clientHeight+"px",e.setSize(s.clientWidth,s.clientHeight),t.setSize(s.clientWidth,s.clientHeight)}}window.TAAR||(window.TAAR={}),window.TAAR.IMAGE||(window.TAAR.IMAGE={}),window.TAAR.IMAGE.TaarThree=TaarThree;