@srsergio/taptapp-ar 1.0.95 → 1.0.97

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.
package/README.md CHANGED
@@ -38,10 +38,11 @@
38
38
  - **Dynamic Scale Filtering (LOD)**: Runtime matching engine skips irrelevant octaves based on estimated scale.
39
39
  - **4-bit Packed Tracking Data**: Grayscale images are compressed to 4-bit depth, slashing file size.
40
40
  - **64-bit LSH Descriptors**: Optimized Locality Sensitive Hashing with XOR folding support.
41
- - 🧵 **High-Precision Tracking**: Now using **Float32** coordinate precision with sub-pixel resolution and stratified scale coverage.
41
+ - 🧵 **HD Precision Tracking**: Default resolution upgraded to **1280x960 (HD)** for superior sharpness on modern displays.
42
+ - ⚡ **Zero-Config JIT Compilation**: No need for offline tools. Just pass an image URL and the engine compiles it on the fly.
42
43
  - 📏 **Virtualized Scale Range**: Stable tracking from **20% (distant targets)** to **1000% (close-up)** using a single high-res keyframe.
43
44
  - ⚡ **Immediate AR Detection**: Optimized "warm-up" period (15 frames) with relaxed inlier thresholds (6 pts) for instant tracking lock.
44
- - 📦 **Framework Agnostic**: Includes wrappers for **A-Frame**, **Three.js**, and a raw **Controller** for custom engines.
45
+ - 📦 **Framework Agnostic**: Includes wrappers for **React**, **A-Frame**, **Three.js**, and a raw **Controller**.
45
46
  - 📉 **Ultra-Compact Files**: Output `.taar` files are now **~100KB** (vs ~380KB+ previously).
46
47
 
47
48
  ---
@@ -80,183 +81,84 @@ The latest version has been rigorously tested with an adaptive stress test (`rob
80
81
 
81
82
  ---
82
83
 
83
- ## 🖼️ Compiler Usage (Node.js & Web)
84
+ ## 🖼️ Compiler Usage (Automatic / JIT)
84
85
 
85
- The compiler is optimized to run in workers for maximum performance.
86
+ The new **TapTapp AR** engine handles compilation automatically in the browser (Just-In-Time). You likely **don't need** to use the offline compiler manually anymore.
86
87
 
87
- ```javascript
88
- import { OfflineCompiler } from '@srsergio/taptapp-ar';
88
+ Simply pass your image URL to the tracker, and it will compile it on the fly:
89
89
 
90
- const compiler = new OfflineCompiler();
90
+ ```typescript
91
+ // No compilation step needed!
92
+ const tracker = await startTracking({
93
+ targetSrc: './my-image.jpg' // Using a JPG/PNG directly
94
+ });
95
+ ```
91
96
 
92
- // Compile target image (provide grayscale pixel data)
93
- // Input: { width, height, data: Uint8Array }
94
- await compiler.compileImageTargets(
95
- [{ width, height, data: grayscaleUint8Array }],
96
- (progress) => console.log(`Compiling: ${progress}%`)
97
- );
97
+ However, if you still want to pre-compile for faster startup on low-end devices:
98
98
 
99
- // Export to high-efficiency binary format (Protocol V7)
100
- const binaryBuffer = compiler.exportData();
99
+ ```javascript
100
+ import { OfflineCompiler } from '@srsergio/taptapp-ar';
101
+ // ... same compiler code as before ...
101
102
  ```
102
103
 
103
104
  ---
104
105
 
105
106
  ## 🎥 Runtime Usage (AR Tracking)
106
107
 
107
- ### 1. Simple A-Frame Integration
108
- The easiest way to use TapTapp AR in a web app:
108
+ ### 1. The Easy Way: React Component ⚛️
109
109
 
110
- ```html
111
- <script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>
112
- <script src="path/to/@srsergio/taptapp-ar/dist/index.js"></script>
110
+ The simplest, zero-config way to add AR to your app:
113
111
 
114
- <a-scene taar-image="imageTargetSrc: ./targets.taar;">
115
- <a-camera position="0 0 0" look-controls="enabled: false"></a-camera>
116
- <a-entity taar-image-target="targetIndex: 0">
117
- <a-plane position="0 0 0" height="0.552" width="1"></a-plane>
118
- </a-entity>
119
- </a-scene>
120
- ```
112
+ ```tsx
113
+ import { TaptappAR } from '@srsergio/taptapp-ar/react';
121
114
 
122
- ### 2. High-Performance Three.js Wrapper
123
- For custom Three.js applications:
124
-
125
- ```javascript
126
- import { TaarThree } from '@srsergio/taptapp-ar';
127
-
128
- const taarThree = new TaarThree({
129
- container: document.querySelector("#container"),
130
- imageTargetSrc: './targets.taar',
131
- });
132
-
133
- const {renderer, scene, camera} = taarThree;
134
-
135
- const anchor = taarThree.addAnchor(0);
136
- // Add your 3D models to anchor.group
137
-
138
- await taarThree.start();
139
- renderer.setAnimationLoop(() => {
140
- renderer.render(scene, camera);
141
- });
115
+ export const MyARScene = () => (
116
+ <TaptappAR
117
+ config={{
118
+ targetImageSrc: "https://example.com/target.jpg", // Direct Image URL
119
+ videoSrc: "https://example.com/overlay.mp4", // Content to show
120
+ scale: 1.2
121
+ }}
122
+ />
123
+ );
142
124
  ```
143
125
 
144
- ### 3. Raw Controller (Advanced & Custom Engines)
145
- The `Controller` is the core engine of TapTapp AR. You can use it to build your own AR components or integrate tracking into custom 3D engines.
126
+ ### 2. The Powerful Way: `startTracking` API
146
127
 
147
- #### ⚙️ Controller Configuration
148
- | Property | Default | Description |
149
- | :--- | :--- | :--- |
150
- | `inputWidth` | **Required** | The width of the video or image source. |
151
- | `inputHeight` | **Required** | The height of the video or image source. |
152
- | `maxTrack` | `1` | Max number of images to track simultaneously. |
153
- | `warmupTolerance` | `5` | Frames of consistent detection needed to "lock" a target. |
154
- | `missTolerance` | `5` | Frames of missed detection before considering the target "lost". |
155
- | `filterMinCF` | `0.001` | Min cutoff frequency for the OneEuroFilter (reduces jitter). |
156
- | `filterBeta` | `1000` | Filter beta parameter (higher = more responsive, lower = smoother). |
157
- | `onUpdate` | `null` | Callback for tracking events (Found, Lost, ProcessDone). |
158
- | `debugMode` | `false` | If true, returns extra debug data (cropped images, feature points). |
159
- | `worker` | `null` | Pass a custom worker instance if using a specialized environment. |
160
-
161
- #### 🚀 Example: Tracking a Video Stream
162
- Ideal for real-time AR apps in the browser:
128
+ For vanilla JS or custom integrations, use the new high-level API:
163
129
 
164
- ```javascript
165
- import { Controller } from '@srsergio/taptapp-ar';
166
-
167
- const controller = new Controller({
168
- inputWidth: video.videoWidth,
169
- inputHeight: video.videoHeight,
170
- onUpdate: (data) => {
171
- if (data.type === 'updateMatrix') {
172
- const { targetIndex, worldMatrix } = data;
173
- if (worldMatrix) {
174
- console.log(`Target ${targetIndex} detected! Matrix:`, worldMatrix);
175
- // Apply worldMatrix (Float32Array[16]) to your 3D object
176
- } else {
177
- console.log(`Target ${targetIndex} lost.`);
178
- }
130
+ ```typescript
131
+ import { startTracking } from '@srsergio/taptapp-ar';
132
+
133
+ const tracker = await startTracking({
134
+ targetSrc: './assets/target.jpg', // No .taar needed!
135
+ container: document.getElementById('ar-container'),
136
+ overlay: document.getElementById('overlay-element'),
137
+
138
+ // Optional callbacks
139
+ callbacks: {
140
+ onFound: () => console.log("Target Found! 🎯"),
141
+ onLost: () => console.log("Target Lost 👋"),
142
+ onUpdate: (data) => {
143
+ console.log("Stability:", data.avgStability);
144
+ }
179
145
  }
180
- }
181
146
  });
182
147
 
183
- // Single target
184
- await controller.addImageTargets('./targets.taar');
185
-
186
- // OR multiple targets from different .taar files
187
- await controller.addImageTargets(['./target1.taar', './target2.taar', './target3.taar']);
188
- controller.processVideo(videoElement); // Starts the internal RAF loop
148
+ // Stop later
149
+ // tracker.stop();
189
150
  ```
190
151
 
191
- #### 📸 Example: One-shot Image Matching
192
- Use this for "Snap and Detect" features without a continuous video loop:
193
-
194
- ```javascript
195
- const controller = new Controller({ inputWidth: 1024, inputHeight: 1024 });
196
- await controller.addImageTargets('./targets.taar');
197
-
198
- // 1. Detect features in a static image
199
- const { featurePoints } = await controller.detect(canvasElement);
200
-
201
- // 2. Attempt to match against a specific target index
202
- const { targetIndex, modelViewTransform } = await controller.match(featurePoints, 0);
203
-
204
- if (targetIndex !== -1) {
205
- // Found a match! Use modelViewTransform for initial pose estimation
206
- }
207
- ```
152
+ ### 3. Advanced Integration (Three.js / A-Frame)
208
153
 
209
- ### 4. Vanilla JS (No Framework) 🍦
210
- The **simplest way** to use AR—no Three.js, no A-Frame. Just overlay an image on the tracked target.
154
+ We still provide wrappers for 3D engines if you need to render complex 3D models instead of DOM overlays.
211
155
 
156
+ #### Three.js Adapter
212
157
  ```javascript
213
- import { SimpleAR } from '@srsergio/taptapp-ar';
214
-
215
- const ar = new SimpleAR({
216
- container: document.getElementById('ar-container'),
217
- targetSrc: './my-target.taar', // Single URL or array: ['./a.taar', './b.taar']
218
- overlay: document.getElementById('my-overlay'),
219
- onFound: ({ targetIndex }) => console.log(`Target ${targetIndex} detected! 🎯`),
220
- onLost: ({ targetIndex }) => console.log(`Target ${targetIndex} lost 👋`)
221
- });
222
-
223
- await ar.start();
224
-
225
- // When done:
226
- ar.stop();
227
- ```
228
-
229
- #### 📁 Minimal HTML
230
- ```html
231
- <div id="ar-container" style="width: 100vw; height: 100vh;">
232
- <img id="my-overlay" src="./overlay.png"
233
- style="opacity: 0; z-index: 1; width: 200px; transition: opacity 0.3s;" />
234
- </div>
235
-
236
- <script type="module">
237
- import { SimpleAR } from '@srsergio/taptapp-ar';
238
-
239
- const ar = new SimpleAR({
240
- container: document.getElementById('ar-container'),
241
- targetSrc: './targets.taar',
242
- overlay: document.getElementById('my-overlay'),
243
- });
244
-
245
- ar.start();
246
- </script>
158
+ import { TaarThree } from '@srsergio/taptapp-ar';
159
+ // ... (standard Three.js integration)
247
160
  ```
248
161
 
249
- #### ⚙️ SimpleAR Options
250
- | Option | Required | Description |
251
- | :--- | :--- | :--- |
252
- | `container` | ✅ | DOM element where video + overlay render |
253
- | `targetSrc` | ✅ | URL to your `.taar` file |
254
- | `overlay` | ✅ | DOM element to position on the target |
255
- | `onFound` | ❌ | Callback when target is detected |
256
- | `onLost` | ❌ | Callback when target is lost |
257
- | `onUpdate` | ❌ | Called each frame with `{ targetIndex, worldMatrix }` |
258
- | `cameraConfig` | ❌ | Camera constraints (default: `{ facingMode: 'environment', width: 1280, height: 720 }`) |
259
-
260
162
  ---
261
163
 
262
164
  ## 🏗️ Protocol V11 (Nanite Virtualized Format)
package/dist/index.d.ts CHANGED
@@ -3,5 +3,5 @@ export * from "./react/TaptappAR.js";
3
3
  export * from "./react/use-ar.js";
4
4
  export * from "./compiler/offline-compiler.js";
5
5
  export { Controller } from "./runtime/controller.js";
6
- export { SimpleAR } from "./runtime/simple-ar.js";
6
+ export { createTracker, startTracking } from "./runtime/track.js";
7
7
  export * as protocol from "./core/protocol.js";
package/dist/index.js CHANGED
@@ -3,5 +3,5 @@ export * from "./react/TaptappAR.js";
3
3
  export * from "./react/use-ar.js";
4
4
  export * from "./compiler/offline-compiler.js";
5
5
  export { Controller } from "./runtime/controller.js";
6
- export { SimpleAR } from "./runtime/simple-ar.js";
6
+ export { createTracker, startTracking } from "./runtime/track.js";
7
7
  export * as protocol from "./core/protocol.js";
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
3
  import { useAR } from "./use-ar.js";
4
4
  export const TaptappAR = ({ config, className = "", showScanningOverlay = true, showErrorOverlay = true }) => {
5
- const { containerRef, overlayRef, status, toggleVideo, trackedPoints } = useAR(config);
5
+ const { containerRef, overlayRef, status, toggleVideo, trackedPoints, error } = useAR(config);
6
6
  // Simple heuristic to determine if it's a video or image
7
7
  // based on the presence of videoSrc and common extensions
8
8
  const isVideo = useMemo(() => {
@@ -12,7 +12,7 @@ export const TaptappAR = ({ config, className = "", showScanningOverlay = true,
12
12
  const url = config.videoSrc.toLowerCase().split('?')[0];
13
13
  return videoExtensions.some(ext => url.endsWith(ext)) || config.videoSrc.includes('video');
14
14
  }, [config.videoSrc]);
15
- return (_jsxs("div", { className: `taptapp-ar-wrapper ${className} ${status}`, style: { position: 'relative', width: '100%', height: '100%', overflow: 'hidden' }, children: [showScanningOverlay && status === "scanning" && (_jsx("div", { className: "taptapp-ar-overlay taptapp-ar-scanning", children: _jsxs("div", { className: "scanning-content", children: [_jsxs("div", { className: "scanning-frame", children: [_jsx("img", { className: "target-preview", src: config.targetImageSrc, alt: "Target", crossOrigin: "anonymous" }), _jsx("div", { className: "scanning-line" })] }), _jsx("p", { className: "scanning-text", children: "Apunta a la imagen para comenzar" })] }) })), showErrorOverlay && status === "error" && (_jsx("div", { className: "taptapp-ar-overlay taptapp-ar-error", children: _jsxs("div", { className: "error-content", children: [_jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), _jsx("p", { className: "error-title", children: "No se pudo iniciar AR" }), _jsx("p", { className: "error-text", children: "Verifica los permisos de c\u00E1mara" }), _jsx("button", { className: "retry-btn", onClick: () => window.location.reload(), children: "Reintentar" })] }) })), _jsx("div", { ref: containerRef, className: "taptapp-ar-container", onClick: toggleVideo, style: { width: '100%', height: '100%' }, children: isVideo ? (_jsx("video", { ref: overlayRef, className: "taptapp-ar-overlay-element", src: config.videoSrc, preload: "auto", loop: true, playsInline: true, muted: true, crossOrigin: "anonymous" })) : (_jsx("img", { ref: overlayRef, className: "taptapp-ar-overlay-element", src: config.videoSrc || config.targetImageSrc, crossOrigin: "anonymous", alt: "AR Overlay" })) }), trackedPoints.length > 0 && (_jsx("div", { className: "taptapp-ar-points-overlay", style: { opacity: status === "tracking" ? 1 : 0.6 }, children: trackedPoints
15
+ return (_jsxs("div", { className: `taptapp-ar-wrapper ${className} ${status}`, style: { position: 'relative', width: '100%', height: '100%', overflow: 'hidden' }, children: [showScanningOverlay && status === "scanning" && (_jsx("div", { className: "taptapp-ar-overlay taptapp-ar-scanning", children: _jsxs("div", { className: "scanning-content", children: [_jsxs("div", { className: "scanning-frame", children: [_jsx("img", { className: "target-preview", src: config.targetImageSrc, alt: "Target", crossOrigin: "anonymous" }), _jsx("div", { className: "scanning-line" })] }), _jsx("p", { className: "scanning-text", children: "Apunta a la imagen para comenzar" })] }) })), status === "compiling" && (_jsx("div", { className: "taptapp-ar-overlay taptapp-ar-compiling", style: { background: 'rgba(0,0,0,0.9)' }, children: _jsxs("div", { className: "scanning-content", children: [_jsx("div", { className: "loading-spinner" }), _jsx("p", { className: "scanning-text", style: { marginTop: '20px' }, children: "Preparando motor AR..." }), _jsx("p", { style: { fontSize: '0.8rem', opacity: 0.6 }, children: "Compilando imagen de referencia" })] }) })), showErrorOverlay && status === "error" && (_jsx("div", { className: "taptapp-ar-overlay taptapp-ar-error", children: _jsxs("div", { className: "error-content", children: [_jsx("span", { className: "error-icon", children: "\u26A0\uFE0F" }), _jsx("p", { className: "error-title", children: "No se pudo iniciar AR" }), _jsx("p", { className: "error-text", children: error || "Verifica los permisos de cámara" }), _jsx("button", { className: "retry-btn", onClick: () => window.location.reload(), children: "Reintentar" })] }) })), _jsx("div", { ref: containerRef, className: "taptapp-ar-container", onClick: toggleVideo, style: { width: '100%', height: '100%' }, children: isVideo ? (_jsx("video", { ref: overlayRef, className: "taptapp-ar-overlay-element", src: config.videoSrc, preload: "auto", loop: true, playsInline: true, muted: true, crossOrigin: "anonymous" })) : (_jsx("img", { ref: overlayRef, className: "taptapp-ar-overlay-element", src: config.videoSrc || config.targetImageSrc, crossOrigin: "anonymous", alt: "AR Overlay" })) }), trackedPoints.length > 0 && (_jsx("div", { className: "taptapp-ar-points-overlay", style: { opacity: status === "tracking" ? 1 : 0.6 }, children: trackedPoints
16
16
  .map((point, i) => {
17
17
  // 🚀 Reflex visualization of the engine's new sensitivity
18
18
  const isStable = point.stability > 0.3 && point.reliability > 0.2;
@@ -89,6 +89,17 @@ export const TaptappAR = ({ config, className = "", showScanningOverlay = true,
89
89
  font-weight: 500;
90
90
  letter-spacing: 0.5px;
91
91
  }
92
+ .loading-spinner {
93
+ width: 40px;
94
+ height: 40px;
95
+ border: 3px solid rgba(255,255,255,0.1);
96
+ border-radius: 50%;
97
+ border-top-color: #00e5ff;
98
+ animation: spin 1s ease-in-out infinite;
99
+ }
100
+ @keyframes spin {
101
+ to { transform: rotate(360deg); }
102
+ }
92
103
  .error-icon { font-size: 3rem; margin-bottom: 10px; }
93
104
  .error-title { font-size: 1.2rem; font-weight: bold; margin: 0; }
94
105
  .error-text { opacity: 0.8; margin: 5px 0 20px; }
@@ -104,12 +115,15 @@ export const TaptappAR = ({ config, className = "", showScanningOverlay = true,
104
115
  }
105
116
  .retry-btn:active { transform: scale(0.95); }
106
117
  .taptapp-ar-overlay-element {
107
- display: block;
108
- width: 100%;
118
+ display: none; /* Controlled by tracker */
119
+ position: absolute;
120
+ top: 0;
121
+ left: 0;
122
+ width: auto;
109
123
  height: auto;
110
- opacity: 0;
111
124
  pointer-events: none;
112
- transition: opacity 0.3s ease;
125
+ z-index: 10;
126
+ /* Will be positioned via matrix3d by track.ts */
113
127
  }
114
128
  .taptapp-ar-points-overlay {
115
129
  position: absolute;
@@ -1,7 +1,7 @@
1
1
  export interface ARConfig {
2
2
  cardId: string;
3
3
  targetImageSrc: string;
4
- targetTaarSrc: string;
4
+ targetTaarSrc?: string;
5
5
  videoSrc: string;
6
6
  videoWidth: number;
7
7
  videoHeight: number;
@@ -1,5 +1,5 @@
1
1
  import type { ARConfig } from "./types.js";
2
- export type ARStatus = "scanning" | "tracking" | "error";
2
+ export type ARStatus = "compiling" | "scanning" | "tracking" | "error";
3
3
  export interface TrackedPoint {
4
4
  x: number;
5
5
  y: number;
@@ -13,5 +13,6 @@ export interface UseARReturn {
13
13
  isPlaying: boolean;
14
14
  toggleVideo: () => Promise<void>;
15
15
  trackedPoints: TrackedPoint[];
16
+ error: string | null;
16
17
  }
17
18
  export declare const useAR: (config: ARConfig) => UseARReturn;
@@ -5,6 +5,7 @@ export const useAR = (config) => {
5
5
  const [status, setStatus] = useState("scanning");
6
6
  const [isPlaying, setIsPlaying] = useState(false);
7
7
  const [trackedPoints, setTrackedPoints] = useState([]);
8
+ const [error, setError] = useState(null);
8
9
  const arInstanceRef = useRef(null);
9
10
  const toggleVideo = useCallback(async () => {
10
11
  const overlay = overlayRef.current;
@@ -31,65 +32,70 @@ export const useAR = (config) => {
31
32
  const initAR = async () => {
32
33
  try {
33
34
  // Safe hybrid import for SSR + Speed
34
- const { SimpleAR } = await import("../runtime/simple-ar.js");
35
+ const { createTracker } = await import("../runtime/track.js");
35
36
  if (!isMounted)
36
37
  return;
37
- const instance = new SimpleAR({
38
+ setStatus("compiling");
39
+ const instance = await createTracker({
38
40
  container: containerRef.current,
39
- targetSrc: config.targetTaarSrc,
41
+ targetSrc: config.targetTaarSrc || config.targetImageSrc,
40
42
  overlay: overlayRef.current,
41
43
  scale: config.scale,
42
- debug: false,
43
- onUpdate: (data) => {
44
- const { screenCoords, reliabilities, stabilities } = data;
45
- if (screenCoords && reliabilities && stabilities) {
46
- const points = screenCoords.map((p, i) => ({
47
- x: p.x,
48
- y: p.y,
49
- reliability: reliabilities[i],
50
- stability: stabilities[i]
51
- }));
52
- setTrackedPoints(points);
53
- }
54
- },
55
- onFound: async ({ targetIndex }) => {
56
- console.log(`🎯 Target ${targetIndex} detected!`);
57
- if (!isMounted)
58
- return;
59
- setStatus("tracking");
60
- const overlay = overlayRef.current;
61
- if (overlay instanceof HTMLVideoElement) {
62
- try {
63
- await overlay.play();
64
- setIsPlaying(true);
44
+ debugMode: false,
45
+ callbacks: {
46
+ onUpdate: (data) => {
47
+ const { screenCoords, reliabilities, stabilities } = data;
48
+ if (screenCoords && reliabilities && stabilities) {
49
+ const points = screenCoords.map((p, i) => ({
50
+ x: p.x,
51
+ y: p.y,
52
+ reliability: reliabilities[i],
53
+ stability: stabilities[i]
54
+ }));
55
+ setTrackedPoints(points);
65
56
  }
66
- catch (err) {
67
- console.warn("Auto-play blocked:", err);
57
+ },
58
+ onFound: async ({ targetIndex }) => {
59
+ console.log(`🎯 Target ${targetIndex} detected!`);
60
+ if (!isMounted)
61
+ return;
62
+ setStatus("tracking");
63
+ const overlay = overlayRef.current;
64
+ if (overlay instanceof HTMLVideoElement) {
65
+ try {
66
+ await overlay.play();
67
+ setIsPlaying(true);
68
+ }
69
+ catch (err) {
70
+ console.warn("Auto-play blocked:", err);
71
+ }
72
+ }
73
+ },
74
+ onLost: ({ targetIndex }) => {
75
+ console.log(`👋 Target ${targetIndex} lost`);
76
+ if (!isMounted)
77
+ return;
78
+ setStatus("scanning");
79
+ setTrackedPoints([]);
80
+ const overlay = overlayRef.current;
81
+ if (overlay instanceof HTMLVideoElement) {
82
+ overlay.pause();
83
+ setIsPlaying(false);
68
84
  }
69
- }
70
- },
71
- onLost: ({ targetIndex }) => {
72
- console.log(`👋 Target ${targetIndex} lost`);
73
- if (!isMounted)
74
- return;
75
- setStatus("scanning");
76
- setTrackedPoints([]);
77
- const overlay = overlayRef.current;
78
- if (overlay instanceof HTMLVideoElement) {
79
- overlay.pause();
80
- setIsPlaying(false);
81
85
  }
82
86
  }
83
87
  });
84
88
  arInstanceRef.current = instance;
85
- await instance.start();
89
+ await instance.startCamera();
86
90
  if (isMounted)
87
91
  setStatus("scanning");
88
92
  }
89
93
  catch (err) {
90
- console.error("Failed to initialize AR:", err);
91
- if (isMounted)
94
+ console.error(" [TapTapp AR] Error durante la inicialización:", err);
95
+ if (isMounted) {
96
+ setError(err.message || String(err));
92
97
  setStatus("error");
98
+ }
93
99
  }
94
100
  };
95
101
  initAR();
@@ -98,13 +104,14 @@ export const useAR = (config) => {
98
104
  arInstanceRef.current?.stop();
99
105
  arInstanceRef.current = null;
100
106
  };
101
- }, [config.targetTaarSrc, config.scale]);
107
+ }, [config.targetTaarSrc, config.targetImageSrc, config.scale]);
102
108
  return {
103
109
  containerRef,
104
110
  overlayRef,
105
111
  status,
106
112
  isPlaying,
107
113
  toggleVideo,
108
- trackedPoints
114
+ trackedPoints,
115
+ error
109
116
  };
110
117
  };
@@ -1,4 +1,5 @@
1
1
  export * from "./controller.js";
2
- export * from "./simple-ar.js";
2
+ export * from "./bio-inspired-controller.js";
3
+ export * from "./track.js";
3
4
  export * from "./three.js";
4
5
  export * from "./aframe.js";
@@ -1,4 +1,5 @@
1
1
  export * from "./controller.js";
2
- export * from "./simple-ar.js";
2
+ export * from "./bio-inspired-controller.js";
3
+ export * from "./track.js";
3
4
  export * from "./three.js";
4
5
  export * from "./aframe.js";