@srsergio/taptapp-ar 1.0.19 → 1.0.21

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.
@@ -13,9 +13,9 @@ catch (e) {
13
13
  // Fallback for tests or other environments
14
14
  ControllerWorker = null;
15
15
  }
16
- const DEFAULT_FILTER_CUTOFF = 0.5; // Mayor cutoff para respuesta más rápida
17
- const DEFAULT_FILTER_BETA = 0.01; // Mucho menor beta para reducir el "lag" y la tembladera
18
- const DEFAULT_WARMUP_TOLERANCE = 5;
16
+ const DEFAULT_FILTER_CUTOFF = 0.1; // Menor cutoff para filtrar más ruidos cuando está quieto
17
+ const DEFAULT_FILTER_BETA = 0.01; // Beta bajo para suavizar movimientos rápidos
18
+ const DEFAULT_WARMUP_TOLERANCE = 8; // Más frames de calentamiento para asegurar estabilidad inicial
19
19
  const DEFAULT_MISS_TOLERANCE = 5;
20
20
  class Controller {
21
21
  constructor({ inputWidth, inputHeight, onUpdate = null, debugMode = false, maxTrack = 1, warmupTolerance = null, missTolerance = null, filterMinCF = null, filterBeta = null, worker = null, // Allow custom worker injection
@@ -14,7 +14,7 @@ import { gpuCompute } from "../utils/gpu-compute.js";
14
14
  const PYRAMID_MIN_SIZE = 4; // Reducido de 8 a 4 para exprimir al máximo la resolución
15
15
  // PYRAMID_MAX_OCTAVE ya no es necesario, el límite lo da PYRAMID_MIN_SIZE
16
16
  const NUM_BUCKETS_PER_DIMENSION = 8;
17
- const MAX_FEATURES_PER_BUCKET = 15; // Aumentado para mayor densidad de puntos tracking y estabilidad
17
+ const MAX_FEATURES_PER_BUCKET = 12; // Ajustado para un equilibrio óptimo entre densidad y estabilidad
18
18
  const ORIENTATION_NUM_BINS = 36;
19
19
  const FREAK_EXPANSION_FACTOR = 7.0;
20
20
  // Global GPU mode flag
@@ -15,10 +15,11 @@
15
15
  * await ar.start();
16
16
  */
17
17
  export class SimpleAR {
18
- constructor({ container, targetSrc, overlay, onFound, onLost, onUpdate, cameraConfig, }: {
18
+ constructor({ container, targetSrc, overlay, scale, onFound, onLost, onUpdate, cameraConfig, }: {
19
19
  container: any;
20
20
  targetSrc: any;
21
21
  overlay: any;
22
+ scale?: number | undefined;
22
23
  onFound?: null | undefined;
23
24
  onLost?: null | undefined;
24
25
  onUpdate?: null | undefined;
@@ -31,6 +32,7 @@ export class SimpleAR {
31
32
  container: any;
32
33
  targetSrc: any;
33
34
  overlay: any;
35
+ scaleMultiplier: number;
34
36
  onFound: any;
35
37
  onLost: any;
36
38
  onUpdateCallback: any;
@@ -16,10 +16,12 @@ import { Controller } from "./controller.js";
16
16
  * await ar.start();
17
17
  */
18
18
  class SimpleAR {
19
- constructor({ container, targetSrc, overlay, onFound = null, onLost = null, onUpdate = null, cameraConfig = { facingMode: 'environment', width: 1280, height: 720 }, }) {
19
+ constructor({ container, targetSrc, overlay, scale = 1.0, // Multiplicador de escala personalizado
20
+ onFound = null, onLost = null, onUpdate = null, cameraConfig = { facingMode: 'environment', width: 1280, height: 720 }, }) {
20
21
  this.container = container;
21
22
  this.targetSrc = targetSrc;
22
23
  this.overlay = overlay;
24
+ this.scaleMultiplier = scale;
23
25
  this.onFound = onFound;
24
26
  this.onLost = onLost;
25
27
  this.onUpdateCallback = onUpdate;
@@ -150,28 +152,32 @@ class SimpleAR {
150
152
  const scaleX = displayW / videoW;
151
153
  const scaleY = displayH / videoH;
152
154
  // Project the center of the marker (markerW/2, markerH/2, 0) into camera space
153
- // Marker coordinates are pixels from top-left.
154
155
  const tx = mVT[0][0] * (markerW / 2) + mVT[0][1] * (markerH / 2) + mVT[0][3];
155
156
  const ty = mVT[1][0] * (markerW / 2) + mVT[1][1] * (markerH / 2) + mVT[1][3];
156
157
  const tz = mVT[2][0] * (markerW / 2) + mVT[2][1] * (markerH / 2) + mVT[2][3];
157
158
  // focal length (roughly 45 degrees FOV match Controller.js)
158
159
  const f = videoH / 2 / Math.tan((45.0 * Math.PI / 180) / 2);
159
160
  // Perspective projection to screen space
160
- const screenX = offsetX + (videoW / 2 + (tx * f / -tz)) * scaleX;
161
- const screenY = offsetY + (videoH / 2 - (ty * f / -tz)) * scaleY;
162
- // Use the first row of mVT to determine rotation and base scale component
163
- // Since marker coordinates are in pixels, mVT[0][0] and mVT[0][1] are unitless scale factors
161
+ // Using + for both since t is relative to principal point and Y is down in screen coords.
162
+ const screenX = offsetX + (videoW / 2 + (tx * f / tz)) * scaleX;
163
+ const screenY = offsetY + (videoH / 2 + (ty * f / tz)) * scaleY;
164
+ // Rotation calculation: atan2(y, x) of world X-axis in camera space
164
165
  const rotation = Math.atan2(mVT[1][0], mVT[0][0]);
165
166
  const matrixScale = Math.sqrt(mVT[0][0] ** 2 + mVT[1][0] ** 2);
166
- // Perspective scale: how much larger/smaller the object is based on distance (tz)
167
- // Correct scale should make a marker-width sized element cover the marker.
168
- const perspectiveScale = (f / -tz) * scaleX;
169
- // The overlay element has its own width in CSS pixels (e.g. 200px)
170
- const overlayCSSWidth = parseFloat(this.overlay.style.width) || 200;
171
- // Final scale = (Target Width in Pixels on screen) / (Overlay CSS Width)
172
- // matrixScale is usually ~1.0 if tracking is rigid
173
- const finalScale = (matrixScale * markerW * perspectiveScale) / overlayCSSWidth;
174
- // Apply transform
167
+ // Perspective scale: 1 world pixel = (f/tz) screen pixels
168
+ const perspectiveScale = (f / tz) * scaleX;
169
+ // Detect overlay intrinsic size
170
+ const intrinsicWidth = (this.overlay instanceof HTMLVideoElement)
171
+ ? this.overlay.videoWidth
172
+ : (this.overlay instanceof HTMLImageElement ? this.overlay.naturalWidth : 0);
173
+ // Final scale = (Target Width in Pixels on screen) / (Overlay Intrinsic Width) * scaleMultiplier
174
+ const baseScale = intrinsicWidth > 0
175
+ ? (matrixScale * markerW * perspectiveScale) / intrinsicWidth
176
+ : 1.0;
177
+ const finalScale = baseScale * this.scaleMultiplier;
178
+ // Ensure element doesn't have CSS width that interferes with scaling
179
+ this.overlay.style.width = 'auto';
180
+ this.overlay.style.height = 'auto';
175
181
  this.overlay.style.position = 'absolute';
176
182
  this.overlay.style.transformOrigin = 'center center';
177
183
  this.overlay.style.left = '0';
@@ -180,7 +186,7 @@ class SimpleAR {
180
186
  translate(${screenX}px, ${screenY}px)
181
187
  translate(-50%, -50%)
182
188
  scale(${finalScale})
183
- rotate(${-rotation}rad)
189
+ rotate(${rotation}rad)
184
190
  `;
185
191
  }
186
192
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@srsergio/taptapp-ar",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "AR Compiler for Node.js and Browser",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,10 +15,11 @@ try {
15
15
  ControllerWorker = null;
16
16
  }
17
17
 
18
- const DEFAULT_FILTER_CUTOFF = 0.5; // Mayor cutoff para respuesta más rápida
19
- const DEFAULT_FILTER_BETA = 0.01; // Mucho menor beta para reducir el "lag" y la tembladera
18
+ const DEFAULT_FILTER_CUTOFF = 0.1; // Menor cutoff para filtrar más ruidos cuando está quieto
19
+ const DEFAULT_FILTER_BETA = 0.01; // Beta bajo para suavizar movimientos rápidos
20
+
21
+ const DEFAULT_WARMUP_TOLERANCE = 8; // Más frames de calentamiento para asegurar estabilidad inicial
20
22
 
21
- const DEFAULT_WARMUP_TOLERANCE = 5;
22
23
  const DEFAULT_MISS_TOLERANCE = 5;
23
24
 
24
25
  class Controller {
@@ -18,7 +18,8 @@ const PYRAMID_MIN_SIZE = 4; // Reducido de 8 a 4 para exprimir al máximo la res
18
18
 
19
19
 
20
20
  const NUM_BUCKETS_PER_DIMENSION = 8;
21
- const MAX_FEATURES_PER_BUCKET = 15; // Aumentado para mayor densidad de puntos tracking y estabilidad
21
+ const MAX_FEATURES_PER_BUCKET = 12; // Ajustado para un equilibrio óptimo entre densidad y estabilidad
22
+
22
23
 
23
24
  const ORIENTATION_NUM_BINS = 36;
24
25
  const FREAK_EXPANSION_FACTOR = 7.0;
@@ -21,6 +21,7 @@ class SimpleAR {
21
21
  container,
22
22
  targetSrc,
23
23
  overlay,
24
+ scale = 1.0, // Multiplicador de escala personalizado
24
25
  onFound = null,
25
26
  onLost = null,
26
27
  onUpdate = null,
@@ -29,6 +30,7 @@ class SimpleAR {
29
30
  this.container = container;
30
31
  this.targetSrc = targetSrc;
31
32
  this.overlay = overlay;
33
+ this.scaleMultiplier = scale;
32
34
  this.onFound = onFound;
33
35
  this.onLost = onLost;
34
36
  this.onUpdateCallback = onUpdate;
@@ -178,7 +180,6 @@ class SimpleAR {
178
180
  const scaleY = displayH / videoH;
179
181
 
180
182
  // Project the center of the marker (markerW/2, markerH/2, 0) into camera space
181
- // Marker coordinates are pixels from top-left.
182
183
  const tx = mVT[0][0] * (markerW / 2) + mVT[0][1] * (markerH / 2) + mVT[0][3];
183
184
  const ty = mVT[1][0] * (markerW / 2) + mVT[1][1] * (markerH / 2) + mVT[1][3];
184
185
  const tz = mVT[2][0] * (markerW / 2) + mVT[2][1] * (markerH / 2) + mVT[2][3];
@@ -187,26 +188,32 @@ class SimpleAR {
187
188
  const f = videoH / 2 / Math.tan((45.0 * Math.PI / 180) / 2);
188
189
 
189
190
  // Perspective projection to screen space
190
- const screenX = offsetX + (videoW / 2 + (tx * f / -tz)) * scaleX;
191
- const screenY = offsetY + (videoH / 2 - (ty * f / -tz)) * scaleY;
191
+ // Using + for both since t is relative to principal point and Y is down in screen coords.
192
+ const screenX = offsetX + (videoW / 2 + (tx * f / tz)) * scaleX;
193
+ const screenY = offsetY + (videoH / 2 + (ty * f / tz)) * scaleY;
192
194
 
193
- // Use the first row of mVT to determine rotation and base scale component
194
- // Since marker coordinates are in pixels, mVT[0][0] and mVT[0][1] are unitless scale factors
195
+ // Rotation calculation: atan2(y, x) of world X-axis in camera space
195
196
  const rotation = Math.atan2(mVT[1][0], mVT[0][0]);
196
197
  const matrixScale = Math.sqrt(mVT[0][0] ** 2 + mVT[1][0] ** 2);
197
198
 
198
- // Perspective scale: how much larger/smaller the object is based on distance (tz)
199
- // Correct scale should make a marker-width sized element cover the marker.
200
- const perspectiveScale = (f / -tz) * scaleX;
199
+ // Perspective scale: 1 world pixel = (f/tz) screen pixels
200
+ const perspectiveScale = (f / tz) * scaleX;
201
201
 
202
- // The overlay element has its own width in CSS pixels (e.g. 200px)
203
- const overlayCSSWidth = parseFloat(this.overlay.style.width) || 200;
202
+ // Detect overlay intrinsic size
203
+ const intrinsicWidth = (this.overlay instanceof HTMLVideoElement)
204
+ ? this.overlay.videoWidth
205
+ : (this.overlay instanceof HTMLImageElement ? this.overlay.naturalWidth : 0);
204
206
 
205
- // Final scale = (Target Width in Pixels on screen) / (Overlay CSS Width)
206
- // matrixScale is usually ~1.0 if tracking is rigid
207
- const finalScale = (matrixScale * markerW * perspectiveScale) / overlayCSSWidth;
207
+ // Final scale = (Target Width in Pixels on screen) / (Overlay Intrinsic Width) * scaleMultiplier
208
+ const baseScale = intrinsicWidth > 0
209
+ ? (matrixScale * markerW * perspectiveScale) / intrinsicWidth
210
+ : 1.0;
208
211
 
209
- // Apply transform
212
+ const finalScale = baseScale * this.scaleMultiplier;
213
+
214
+ // Ensure element doesn't have CSS width that interferes with scaling
215
+ this.overlay.style.width = 'auto';
216
+ this.overlay.style.height = 'auto';
210
217
  this.overlay.style.position = 'absolute';
211
218
  this.overlay.style.transformOrigin = 'center center';
212
219
  this.overlay.style.left = '0';
@@ -215,7 +222,7 @@ class SimpleAR {
215
222
  translate(${screenX}px, ${screenY}px)
216
223
  translate(-50%, -50%)
217
224
  scale(${finalScale})
218
- rotate(${-rotation}rad)
225
+ rotate(${rotation}rad)
219
226
  `;
220
227
  }
221
228
  }