@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,358 +1 @@
1
- /**
2
- * Bio-Inspired Controller Adapter
3
- *
4
- * Wraps the standard Controller with Bio-Inspired Perception capabilities.
5
- * Provides significant performance improvements while maintaining API compatibility.
6
- *
7
- * Key features:
8
- * - Foveal attention: Processes only regions of interest at full resolution
9
- * - Predictive coding: Skips processing when scene is static
10
- * - Saccadic sampling: Strategic "glances" at high-saliency regions
11
- *
12
- * Usage:
13
- * ```javascript
14
- * import { BioInspiredController } from './bio-inspired-controller.js';
15
- *
16
- * const controller = new BioInspiredController({
17
- * inputWidth: 640,
18
- * inputHeight: 480,
19
- * onUpdate: (data) => console.log(data),
20
- * bioInspired: {
21
- * enabled: true,
22
- * aggressiveSkipping: true,
23
- * }
24
- * });
25
- * ```
26
- */
27
- import { Controller } from './controller.js';
28
- import { BioInspiredEngine } from '../core/perception/index.js';
29
- /**
30
- * Bio-Inspired Controller
31
- *
32
- * Extends the standard Controller with bio-inspired perception capabilities.
33
- */
34
- class BioInspiredController extends Controller {
35
- bioEngine = null;
36
- bioEnabled = true;
37
- bioMetricsInterval = null;
38
- lastBioResult = null;
39
- constructor(options) {
40
- super(options);
41
- const bioOptions = options.bioInspired || {};
42
- this.bioEnabled = bioOptions.enabled !== false;
43
- if (this.bioEnabled) {
44
- // Initialize Bio-Inspired Engine
45
- const bioConfig = {};
46
- if (bioOptions.foveaRadiusRatio !== undefined) {
47
- bioConfig.FOVEA_RADIUS_RATIO = bioOptions.foveaRadiusRatio;
48
- }
49
- if (bioOptions.maxSaccades !== undefined) {
50
- bioConfig.MAX_SACCADES_PER_FRAME = bioOptions.maxSaccades;
51
- }
52
- if (bioOptions.aggressiveSkipping !== undefined) {
53
- bioConfig.ENABLE_SKIP_FRAMES = bioOptions.aggressiveSkipping;
54
- if (bioOptions.aggressiveSkipping) {
55
- bioConfig.CHANGE_THRESHOLD = 0.03; // More aggressive
56
- }
57
- }
58
- this.bioEngine = new BioInspiredEngine(options.inputWidth, options.inputHeight, bioConfig);
59
- }
60
- }
61
- /**
62
- * Override processVideo to add bio-inspired perception
63
- */
64
- processVideo(input) {
65
- if (!this.bioEnabled || !this.bioEngine) {
66
- return super.processVideo(input);
67
- }
68
- if (this.processingVideo)
69
- return;
70
- this.processingVideo = true;
71
- // Reset tracking states
72
- this.trackingStates = [];
73
- for (let i = 0; i < (this.markerDimensions?.length || 0); i++) {
74
- this.trackingStates.push({
75
- showing: false,
76
- isTracking: false,
77
- currentModelViewTransform: null,
78
- trackCount: 0,
79
- trackMiss: 0,
80
- });
81
- }
82
- const startProcessing = async () => {
83
- while (this.processingVideo) {
84
- const inputData = this.inputLoader.loadInput(input);
85
- // Get current tracking state for bio engine
86
- const activeTracking = this.trackingStates.find(s => s.isTracking);
87
- const trackingState = activeTracking ? {
88
- isTracking: true,
89
- activeOctave: activeTracking.lastOctaveIndex, // Tracked octave index
90
- worldMatrix: activeTracking.currentModelViewTransform
91
- ? this._flattenMatrix(activeTracking.currentModelViewTransform)
92
- : null
93
- } : null;
94
- // Process through bio-inspired engine
95
- const bioResult = this.bioEngine.process(inputData, trackingState || undefined);
96
- this.lastBioResult = bioResult;
97
- // If bio engine says we can skip, use prediction
98
- if (bioResult.skipped && activeTracking?.isTracking) {
99
- // Use predicted state
100
- this._handleSkippedFrame(activeTracking, bioResult);
101
- }
102
- else {
103
- // Normal processing with attention regions
104
- await this._processWithAttention(input, inputData, bioResult);
105
- }
106
- // Wait for next frame
107
- if (typeof requestAnimationFrame !== 'undefined') {
108
- await new Promise(requestAnimationFrame);
109
- }
110
- else {
111
- await new Promise(resolve => setTimeout(resolve, 16));
112
- }
113
- }
114
- };
115
- startProcessing();
116
- }
117
- /**
118
- * Handle a skipped frame using prediction
119
- * @private
120
- */
121
- _handleSkippedFrame(trackingState, bioResult) {
122
- // Use predicted matrix
123
- if (bioResult.prediction && bioResult.prediction.worldMatrix) {
124
- trackingState.currentModelViewTransform = this._unflattenMatrix(bioResult.prediction.worldMatrix);
125
- }
126
- // Notify with skipped status
127
- const worldMatrix = trackingState.currentModelViewTransform
128
- ? this._glModelViewMatrix(trackingState.currentModelViewTransform, 0)
129
- : null;
130
- this.onUpdate?.({
131
- type: 'updateMatrix',
132
- targetIndex: 0,
133
- worldMatrix: worldMatrix ? this.featureManager.applyWorldMatrixFilters(0, worldMatrix, { stability: 0.9 }) : null,
134
- skipped: true,
135
- bioMetrics: this.bioEngine?.getMetrics(),
136
- });
137
- this.onUpdate?.({ type: 'processDone' });
138
- }
139
- /**
140
- * Process frame using bio-inspired attention regions
141
- * @private
142
- */
143
- async _processWithAttention(input, inputData, bioResult) {
144
- const nTracking = this.trackingStates.reduce((acc, s) => acc + (s.isTracking ? 1 : 0), 0);
145
- // Detection phase - use primary attention region for efficiency
146
- if (nTracking < this.maxTrack) {
147
- const matchingIndexes = this.trackingStates
148
- .map((s, i) => ({ state: s, index: i }))
149
- .filter(({ state, index }) => !state.isTracking &&
150
- (this.interestedTargetIndex === -1 || this.interestedTargetIndex === index))
151
- .map(({ index }) => index);
152
- if (matchingIndexes.length > 0) {
153
- // Use full input for detection (bio engine already optimized upstream processing)
154
- const { targetIndex: matchedTargetIndex, modelViewTransform, featurePoints } = await this._detectAndMatch(inputData, matchingIndexes, bioResult.octavesToProcess || null);
155
- if (matchedTargetIndex !== -1) {
156
- this.trackingStates[matchedTargetIndex].isTracking = true;
157
- this.trackingStates[matchedTargetIndex].currentModelViewTransform = modelViewTransform;
158
- // Update bio engine fovea to focus on detected target
159
- if (bioResult.attentionRegions?.[0]) {
160
- this.bioEngine?.reset();
161
- }
162
- }
163
- this.onUpdate?.({ type: 'featurePoints', featurePoints });
164
- }
165
- }
166
- // Tracking phase
167
- for (let i = 0; i < this.trackingStates.length; i++) {
168
- const trackingState = this.trackingStates[i];
169
- if (trackingState.isTracking) {
170
- const result = await this._trackAndUpdate(inputData, trackingState.currentModelViewTransform, i);
171
- if (!result || !result.modelViewTransform) {
172
- trackingState.isTracking = false;
173
- trackingState.screenCoords = result?.screenCoords || [];
174
- trackingState.reliabilities = result?.reliabilities || [];
175
- trackingState.stabilities = result?.stabilities || [];
176
- }
177
- else {
178
- trackingState.currentModelViewTransform = result.modelViewTransform;
179
- trackingState.screenCoords = result.screenCoords;
180
- trackingState.reliabilities = result.reliabilities;
181
- trackingState.stabilities = result.stabilities;
182
- trackingState.deformedMesh = result.deformedMesh;
183
- }
184
- }
185
- const wasShowing = trackingState.showing;
186
- trackingState.showing = this.featureManager.shouldShow(i, trackingState.isTracking);
187
- if (wasShowing && !trackingState.showing) {
188
- trackingState.trackingMatrix = null;
189
- this.featureManager.notifyUpdate({ type: 'reset', targetIndex: i });
190
- }
191
- // Emit update
192
- if (trackingState.showing || trackingState.screenCoords?.length > 0 || (wasShowing && !trackingState.showing)) {
193
- const worldMatrix = trackingState.showing
194
- ? this._glModelViewMatrix(trackingState.currentModelViewTransform, i)
195
- : null;
196
- let finalMatrix = null;
197
- if (worldMatrix) {
198
- const stabilities = trackingState.stabilities || [];
199
- const avgStability = stabilities.length > 0
200
- ? stabilities.reduce((a, b) => a + b, 0) / stabilities.length
201
- : 0;
202
- finalMatrix = this.featureManager.applyWorldMatrixFilters(i, worldMatrix, { stability: avgStability });
203
- trackingState.trackingMatrix = finalMatrix;
204
- const isInputRotated = input.width === this.inputHeight && input.height === this.inputWidth;
205
- if (isInputRotated) {
206
- const rotationFeature = this.featureManager.getFeature('auto-rotation');
207
- if (rotationFeature) {
208
- finalMatrix = rotationFeature.rotate(finalMatrix);
209
- }
210
- }
211
- }
212
- this.onUpdate?.({
213
- type: 'updateMatrix',
214
- targetIndex: i,
215
- worldMatrix: finalMatrix,
216
- modelViewTransform: trackingState.currentModelViewTransform,
217
- screenCoords: trackingState.screenCoords,
218
- reliabilities: trackingState.reliabilities,
219
- stabilities: trackingState.stabilities,
220
- deformedMesh: trackingState.deformedMesh,
221
- bioMetrics: this.bioEngine?.getMetrics(),
222
- foveaCenter: bioResult.foveaCenter,
223
- pixelsSaved: bioResult.pixelsSaved,
224
- });
225
- }
226
- }
227
- this.onUpdate?.({ type: 'processDone' });
228
- }
229
- /**
230
- * Detect and match features, optionally limited to specific octaves
231
- */
232
- async _detectAndMatch(inputData, targetIndexes, octavesToProcess = null) {
233
- // 🚀 NANITE-STYLE: Estimate scale for filtered matching
234
- let predictedScale = undefined;
235
- for (const state of this.trackingStates) {
236
- if (state.isTracking && state.currentModelViewTransform) {
237
- const m = state.currentModelViewTransform;
238
- predictedScale = Math.sqrt(m[0][0] ** 2 + m[1][0] ** 2 + m[2][0] ** 2);
239
- break;
240
- }
241
- }
242
- const { targetIndex, modelViewTransform, screenCoords, worldCoords, featurePoints } = await this._workerMatch(null, // No feature points, worker will detect from inputData
243
- targetIndexes, inputData, predictedScale, octavesToProcess);
244
- return { targetIndex, modelViewTransform, screenCoords, worldCoords, featurePoints };
245
- }
246
- /**
247
- * Communicate with worker for matching phase
248
- */
249
- _workerMatch(featurePoints, targetIndexes, inputData = null, expectedScale, octavesToProcess = null) {
250
- return new Promise((resolve) => {
251
- if (!this.worker) {
252
- // If no feature points but we have input data, detect first
253
- let fpPromise;
254
- if (!featurePoints && inputData) {
255
- fpPromise = Promise.resolve(this.fullDetector.detect(inputData, { octavesToProcess }).featurePoints);
256
- }
257
- else {
258
- fpPromise = Promise.resolve(featurePoints);
259
- }
260
- fpPromise.then(fp => {
261
- this._matchOnMainThread(fp, targetIndexes, expectedScale).then(resolve);
262
- }).catch(() => resolve({ targetIndex: -1 }));
263
- return;
264
- }
265
- const timeout = setTimeout(() => {
266
- this.workerMatchDone = null;
267
- resolve({ targetIndex: -1 });
268
- }, 1000);
269
- this.workerMatchDone = (data) => {
270
- clearTimeout(timeout);
271
- this.workerMatchDone = null;
272
- resolve(data);
273
- };
274
- if (inputData) {
275
- this.worker.postMessage({ type: "match", inputData, targetIndexes, octavesToProcess, expectedScale });
276
- }
277
- else {
278
- this.worker.postMessage({ type: "match", featurePoints: featurePoints, targetIndexes, expectedScale });
279
- }
280
- });
281
- }
282
- /**
283
- * Override _trackAndUpdate to capture active octave for the next frame's orchestration
284
- */
285
- async _trackAndUpdate(inputData, lastModelViewTransform, targetIndex) {
286
- const result = await super._trackAndUpdate(inputData, lastModelViewTransform, targetIndex);
287
- if (result && result.octaveIndex !== undefined) {
288
- this.trackingStates[targetIndex].lastOctaveIndex = result.octaveIndex;
289
- }
290
- return result;
291
- }
292
- /**
293
- * Flatten a 3x4 matrix to Float32Array
294
- * @private
295
- */
296
- _flattenMatrix(matrix) {
297
- const result = new Float32Array(16);
298
- for (let i = 0; i < 3; i++) {
299
- for (let j = 0; j < 4; j++) {
300
- result[i * 4 + j] = matrix[i][j];
301
- }
302
- }
303
- result[12] = 0;
304
- result[13] = 0;
305
- result[14] = 0;
306
- result[15] = 1;
307
- return result;
308
- }
309
- /**
310
- * Unflatten Float32Array to 3x4 matrix
311
- * @private
312
- */
313
- _unflattenMatrix(flat) {
314
- return [
315
- [flat[0], flat[1], flat[2], flat[3]],
316
- [flat[4], flat[5], flat[6], flat[7]],
317
- [flat[8], flat[9], flat[10], flat[11]],
318
- ];
319
- }
320
- /**
321
- * Get bio-inspired engine metrics
322
- */
323
- getBioMetrics() {
324
- return this.bioEngine?.getMetrics() || null;
325
- }
326
- /**
327
- * Get last bio processing result
328
- */
329
- getLastBioResult() {
330
- return this.lastBioResult;
331
- }
332
- /**
333
- * Enable/disable bio-inspired processing dynamically
334
- */
335
- setBioEnabled(enabled) {
336
- this.bioEnabled = enabled;
337
- if (enabled && !this.bioEngine) {
338
- this.bioEngine = new BioInspiredEngine(this.inputWidth, this.inputHeight);
339
- }
340
- }
341
- /**
342
- * Configure bio-inspired engine at runtime
343
- */
344
- configureBio(options) {
345
- this.bioEngine?.configure(options);
346
- }
347
- /**
348
- * Override dispose to clean up bio engine
349
- */
350
- dispose() {
351
- super.dispose();
352
- this.bioEngine = null;
353
- if (this.bioMetricsInterval) {
354
- clearInterval(this.bioMetricsInterval);
355
- }
356
- }
357
- }
358
- export { BioInspiredController };
1
+ import{Controller as e}from"./controller.js";import{BioInspiredEngine as t}from"../core/perception/index.js";class i extends e{bioEngine=null;bioEnabled=!0;bioMetricsInterval=null;lastBioResult=null;constructor(e){super(e);const i=e.bioInspired||{};if(this.bioEnabled=!1!==i.enabled,this.bioEnabled){const r={};void 0!==i.foveaRadiusRatio&&(r.FOVEA_RADIUS_RATIO=i.foveaRadiusRatio),void 0!==i.maxSaccades&&(r.MAX_SACCADES_PER_FRAME=i.maxSaccades),void 0!==i.aggressiveSkipping&&(r.ENABLE_SKIP_FRAMES=i.aggressiveSkipping,i.aggressiveSkipping&&(r.CHANGE_THRESHOLD=.03)),this.bioEngine=new t(e.inputWidth,e.inputHeight,r)}}processVideo(e){if(!this.bioEnabled||!this.bioEngine)return super.processVideo(e);if(!this.processingVideo){this.processingVideo=!0,this.trackingStates=[];for(let e=0;e<(this.markerDimensions?.length||0);e++)this.trackingStates.push({showing:!1,isTracking:!1,currentModelViewTransform:null,trackCount:0,trackMiss:0});(async()=>{for(;this.processingVideo;){const t=this.inputLoader.loadInput(e),i=this.trackingStates.find(e=>e.isTracking),r=i?{isTracking:!0,activeOctave:i.lastOctaveIndex,worldMatrix:i.currentModelViewTransform?this._flattenMatrix(i.currentModelViewTransform):null}:null,s=this.bioEngine.process(t,r||void 0);this.lastBioResult=s,s.skipped&&i?.isTracking?this._handleSkippedFrame(i,s):await this._processWithAttention(e,t,s),"undefined"!=typeof requestAnimationFrame?await new Promise(requestAnimationFrame):await new Promise(e=>setTimeout(e,16))}})()}}_handleSkippedFrame(e,t){t.prediction&&t.prediction.worldMatrix&&(e.currentModelViewTransform=this._unflattenMatrix(t.prediction.worldMatrix));const i=e.currentModelViewTransform?this._glModelViewMatrix(e.currentModelViewTransform,0):null;this.onUpdate?.({type:"updateMatrix",targetIndex:0,worldMatrix:i?this.featureManager.applyWorldMatrixFilters(0,i,{stability:.9}):null,skipped:!0,bioMetrics:this.bioEngine?.getMetrics()}),this.onUpdate?.({type:"processDone"})}async _processWithAttention(e,t,i){if(this.trackingStates.reduce((e,t)=>e+(t.isTracking?1:0),0)<this.maxTrack){const e=this.trackingStates.map((e,t)=>({state:e,index:t})).filter(({state:e,index:t})=>!e.isTracking&&(-1===this.interestedTargetIndex||this.interestedTargetIndex===t)).map(({index:e})=>e);if(e.length>0){const{targetIndex:r,modelViewTransform:s,featurePoints:n}=await this._detectAndMatch(t,e,i.octavesToProcess||null);-1!==r&&(this.trackingStates[r].isTracking=!0,this.trackingStates[r].currentModelViewTransform=s,i.attentionRegions?.[0]&&this.bioEngine?.reset()),this.onUpdate?.({type:"featurePoints",featurePoints:n})}}for(let r=0;r<this.trackingStates.length;r++){const s=this.trackingStates[r];if(s.isTracking){const e=await this._trackAndUpdate(t,s.currentModelViewTransform,r);e&&e.modelViewTransform?(s.currentModelViewTransform=e.modelViewTransform,s.screenCoords=e.screenCoords,s.reliabilities=e.reliabilities,s.stabilities=e.stabilities,s.deformedMesh=e.deformedMesh):(s.isTracking=!1,s.screenCoords=e?.screenCoords||[],s.reliabilities=e?.reliabilities||[],s.stabilities=e?.stabilities||[])}const n=s.showing;if(s.showing=this.featureManager.shouldShow(r,s.isTracking),n&&!s.showing&&(s.trackingMatrix=null,this.featureManager.notifyUpdate({type:"reset",targetIndex:r})),s.showing||s.screenCoords?.length>0||n&&!s.showing){const t=s.showing?this._glModelViewMatrix(s.currentModelViewTransform,r):null;let n=null;if(t){const i=s.stabilities||[],a=i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0;if(n=this.featureManager.applyWorldMatrixFilters(r,t,{stability:a}),s.trackingMatrix=n,e.width===this.inputHeight&&e.height===this.inputWidth){const e=this.featureManager.getFeature("auto-rotation");e&&(n=e.rotate(n))}}this.onUpdate?.({type:"updateMatrix",targetIndex:r,worldMatrix:n,modelViewTransform:s.currentModelViewTransform,screenCoords:s.screenCoords,reliabilities:s.reliabilities,stabilities:s.stabilities,deformedMesh:s.deformedMesh,bioMetrics:this.bioEngine?.getMetrics(),foveaCenter:i.foveaCenter,pixelsSaved:i.pixelsSaved})}}this.onUpdate?.({type:"processDone"})}async _detectAndMatch(e,t,i=null){let r;for(const e of this.trackingStates)if(e.isTracking&&e.currentModelViewTransform){const t=e.currentModelViewTransform;r=Math.sqrt(t[0][0]**2+t[1][0]**2+t[2][0]**2);break}const{targetIndex:s,modelViewTransform:n,screenCoords:a,worldCoords:o,featurePoints:l}=await this._workerMatch(null,t,e,r,i);return{targetIndex:s,modelViewTransform:n,screenCoords:a,worldCoords:o,featurePoints:l}}_workerMatch(e,t,i=null,r,s=null){return new Promise(n=>{if(!this.worker){let a;return a=!e&&i?Promise.resolve(this.fullDetector.detect(i,{octavesToProcess:s}).featurePoints):Promise.resolve(e),void a.then(e=>{this._matchOnMainThread(e,t,r).then(n)}).catch(()=>n({targetIndex:-1}))}const a=setTimeout(()=>{this.workerMatchDone=null,n({targetIndex:-1})},1e3);this.workerMatchDone=e=>{clearTimeout(a),this.workerMatchDone=null,n(e)},i?this.worker.postMessage({type:"match",inputData:i,targetIndexes:t,octavesToProcess:s,expectedScale:r}):this.worker.postMessage({type:"match",featurePoints:e,targetIndexes:t,expectedScale:r})})}async _trackAndUpdate(e,t,i){const r=await super._trackAndUpdate(e,t,i);return r&&void 0!==r.octaveIndex&&(this.trackingStates[i].lastOctaveIndex=r.octaveIndex),r}_flattenMatrix(e){const t=new Float32Array(16);for(let i=0;i<3;i++)for(let r=0;r<4;r++)t[4*i+r]=e[i][r];return t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}_unflattenMatrix(e){return[[e[0],e[1],e[2],e[3]],[e[4],e[5],e[6],e[7]],[e[8],e[9],e[10],e[11]]]}getBioMetrics(){return this.bioEngine?.getMetrics()||null}getLastBioResult(){return this.lastBioResult}setBioEnabled(e){this.bioEnabled=e,e&&!this.bioEngine&&(this.bioEngine=new t(this.inputWidth,this.inputHeight))}configureBio(e){this.bioEngine?.configure(e)}dispose(){super.dispose(),this.bioEngine=null,this.bioMetricsInterval&&clearInterval(this.bioMetricsInterval)}}export{i as BioInspiredController};