@srsergio/taptapp-ar 1.0.23 → 1.0.25

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.
@@ -131,82 +131,56 @@ class SimpleAR {
131
131
  return;
132
132
  const [markerW, markerH] = this.markerDimensions[targetIndex];
133
133
  const containerRect = this.container.getBoundingClientRect();
134
- // 1. Raw Video Dimensions (Sensor Frame)
135
134
  const videoW = this.video.videoWidth;
136
135
  const videoH = this.video.videoHeight;
137
- // 2. Detect if screen orientation is different from video buffer
138
136
  const isPortrait = containerRect.height > containerRect.width;
139
137
  const isVideoLandscape = videoW > videoH;
140
138
  const needsRotation = isPortrait && isVideoLandscape;
141
- // Effective dimensions of the display buffer
142
- const effectiveBufferW = needsRotation ? videoH : videoW;
143
- const effectiveBufferH = needsRotation ? videoW : videoH;
144
- const containerAspect = containerRect.width / containerRect.height;
145
- const bufferAspect = effectiveBufferW / effectiveBufferH;
146
- let displayW, displayH, offsetX, offsetY;
147
- if (containerAspect > bufferAspect) {
148
- displayW = containerRect.width;
149
- displayH = containerRect.width / bufferAspect;
150
- offsetX = 0;
151
- offsetY = (containerRect.height - displayH) / 2;
152
- }
153
- else {
154
- displayH = containerRect.height;
155
- displayW = containerRect.height * bufferAspect;
156
- offsetX = (containerRect.width - displayW) / 2;
157
- offsetY = 0;
158
- }
159
- const scaleX = displayW / effectiveBufferW;
160
- const scaleY = displayH / effectiveBufferH;
161
- // 3. Focal Length (MUST match Controller.js projection)
162
- // Controller.js uses inputHeight / 2 as the vertical reference.
139
+ // The tracker uses 1280x720. Focal length is based on 720 (sensor height).
163
140
  const f = videoH / 2 / Math.tan((45.0 * Math.PI / 180) / 2);
164
- // 4. Project marker center into camera space
141
+ // Project Center of the marker into camera space
165
142
  const tx = mVT[0][0] * (markerW / 2) + mVT[0][1] * (markerH / 2) + mVT[0][3];
166
143
  const ty = mVT[1][0] * (markerW / 2) + mVT[1][1] * (markerH / 2) + mVT[1][3];
167
144
  const tz = mVT[2][0] * (markerW / 2) + mVT[2][1] * (markerH / 2) + mVT[2][3];
168
- // 5. Map Camera coordinates to Screen coordinates
169
- let screenX, screenY;
145
+ let screenX, screenY, rotation, perspectiveScale;
170
146
  if (needsRotation) {
171
- // Mapping Sensor coordinates to Rotated Screen coordinates
172
- // Sensor +X -> Screen +Y
173
- // Sensor +Y -> Screen -X (relative to logical center)
174
- screenX = offsetX + (effectiveBufferW / 2 + (ty * f / tz)) * scaleX;
175
- screenY = offsetY + (effectiveBufferH / 2 - (tx * f / tz)) * scaleY;
147
+ // PORTRAIT MOBILE:
148
+ // Browser rotates 1280 (W) -> vertical, 720 (H) -> horizontal
149
+ const scale = containerRect.height / videoW;
150
+ const displayW = videoH * scale;
151
+ const offsetX = (containerRect.width - displayW) / 2;
152
+ // Mapping: Buffer +X (Right) -> Screen +Y (Down), Buffer +Y (Down) -> Screen -X (Left)
153
+ screenX = offsetX + (displayW / 2 - (ty * f / tz) * scale);
154
+ screenY = (containerRect.height / 2 + (tx * f / tz) * scale);
155
+ rotation = Math.atan2(mVT[1][0], mVT[0][0]) - Math.PI / 2;
156
+ perspectiveScale = scale;
176
157
  }
177
158
  else {
178
- screenX = offsetX + (effectiveBufferW / 2 + (tx * f / tz)) * scaleX;
179
- screenY = offsetY + (effectiveBufferH / 2 + (ty * f / tz)) * scaleY;
159
+ // LANDSCAPE / LAPTOP:
160
+ const scale = containerRect.width / videoW;
161
+ const displayH = videoH * scale;
162
+ const offsetY = (containerRect.height - displayH) / 2;
163
+ screenX = (containerRect.width / 2 + (tx * f / tz) * scale);
164
+ screenY = offsetY + (displayH / 2 + (ty * f / tz) * scale);
165
+ rotation = Math.atan2(mVT[1][0], mVT[0][0]);
166
+ perspectiveScale = scale;
180
167
  }
181
- // 6. Rotation: sync with CSS transform
182
- //atan2 gives angle of world X-axis in camera space.
183
- let rotation = Math.atan2(mVT[1][0], mVT[0][0]);
184
- if (needsRotation) {
185
- rotation += Math.PI / 2; // Compensate for the 90deg rotation of the video element
186
- }
187
- // 7. Scale calculation
168
+ // Final Scale
188
169
  const matrixScale = Math.sqrt(mVT[0][0] ** 2 + mVT[1][0] ** 2);
189
- const perspectiveScale = (f / tz) * scaleX;
190
- const intrinsicWidth = (this.overlay instanceof HTMLVideoElement)
191
- ? this.overlay.videoWidth
192
- : (this.overlay instanceof HTMLImageElement ? this.overlay.naturalWidth : 0);
193
- const baseScale = intrinsicWidth > 0
194
- ? (matrixScale * markerW * perspectiveScale) / intrinsicWidth
195
- : 1.0;
196
- const finalScale = baseScale * this.scaleMultiplier;
197
- // Apply transform
198
- this.overlay.style.width = 'auto';
170
+ const finalScale = (f / tz) * perspectiveScale * matrixScale * this.scaleMultiplier;
171
+ // Apply
172
+ this.overlay.style.width = `${markerW}px`;
199
173
  this.overlay.style.height = 'auto';
200
174
  this.overlay.style.position = 'absolute';
201
175
  this.overlay.style.transformOrigin = 'center center';
202
176
  this.overlay.style.left = '0';
203
177
  this.overlay.style.top = '0';
204
178
  this.overlay.style.transform = `
205
- translate(${screenX}px, ${screenY}px)
206
- translate(-50%, -50%)
207
- scale(${finalScale})
208
- rotate(${rotation}rad)
209
- `;
179
+ translate(${screenX}px, ${screenY}px)
180
+ translate(-50%, -50%)
181
+ scale(${finalScale})
182
+ rotate(${rotation}rad)
183
+ `;
210
184
  }
211
185
  }
212
186
  export { SimpleAR };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@srsergio/taptapp-ar",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "AR Compiler for Node.js and Browser",
5
5
  "repository": {
6
6
  "type": "git",
@@ -156,94 +156,66 @@ class SimpleAR {
156
156
  const [markerW, markerH] = this.markerDimensions[targetIndex];
157
157
  const containerRect = this.container.getBoundingClientRect();
158
158
 
159
- // 1. Raw Video Dimensions (Sensor Frame)
160
159
  const videoW = this.video.videoWidth;
161
160
  const videoH = this.video.videoHeight;
162
161
 
163
- // 2. Detect if screen orientation is different from video buffer
164
162
  const isPortrait = containerRect.height > containerRect.width;
165
163
  const isVideoLandscape = videoW > videoH;
166
164
  const needsRotation = isPortrait && isVideoLandscape;
167
165
 
168
- // Effective dimensions of the display buffer
169
- const effectiveBufferW = needsRotation ? videoH : videoW;
170
- const effectiveBufferH = needsRotation ? videoW : videoH;
171
-
172
- const containerAspect = containerRect.width / containerRect.height;
173
- const bufferAspect = effectiveBufferW / effectiveBufferH;
174
-
175
- let displayW, displayH, offsetX, offsetY;
176
- if (containerAspect > bufferAspect) {
177
- displayW = containerRect.width;
178
- displayH = containerRect.width / bufferAspect;
179
- offsetX = 0;
180
- offsetY = (containerRect.height - displayH) / 2;
181
- } else {
182
- displayH = containerRect.height;
183
- displayW = containerRect.height * bufferAspect;
184
- offsetX = (containerRect.width - displayW) / 2;
185
- offsetY = 0;
186
- }
187
-
188
- const scaleX = displayW / effectiveBufferW;
189
- const scaleY = displayH / effectiveBufferH;
190
-
191
- // 3. Focal Length (MUST match Controller.js projection)
192
- // Controller.js uses inputHeight / 2 as the vertical reference.
166
+ // The tracker uses 1280x720. Focal length is based on 720 (sensor height).
193
167
  const f = videoH / 2 / Math.tan((45.0 * Math.PI / 180) / 2);
194
168
 
195
- // 4. Project marker center into camera space
169
+ // Project Center of the marker into camera space
196
170
  const tx = mVT[0][0] * (markerW / 2) + mVT[0][1] * (markerH / 2) + mVT[0][3];
197
171
  const ty = mVT[1][0] * (markerW / 2) + mVT[1][1] * (markerH / 2) + mVT[1][3];
198
172
  const tz = mVT[2][0] * (markerW / 2) + mVT[2][1] * (markerH / 2) + mVT[2][3];
199
173
 
200
- // 5. Map Camera coordinates to Screen coordinates
201
- let screenX, screenY;
174
+ let screenX, screenY, rotation, perspectiveScale;
175
+
202
176
  if (needsRotation) {
203
- // Mapping Sensor coordinates to Rotated Screen coordinates
204
- // Sensor +X -> Screen +Y
205
- // Sensor +Y -> Screen -X (relative to logical center)
206
- screenX = offsetX + (effectiveBufferW / 2 + (ty * f / tz)) * scaleX;
207
- screenY = offsetY + (effectiveBufferH / 2 - (tx * f / tz)) * scaleY;
177
+ // PORTRAIT MOBILE:
178
+ // Browser rotates 1280 (W) -> vertical, 720 (H) -> horizontal
179
+ const scale = containerRect.height / videoW;
180
+ const displayW = videoH * scale;
181
+ const offsetX = (containerRect.width - displayW) / 2;
182
+
183
+ // Mapping: Buffer +X (Right) -> Screen +Y (Down), Buffer +Y (Down) -> Screen -X (Left)
184
+ screenX = offsetX + (displayW / 2 - (ty * f / tz) * scale);
185
+ screenY = (containerRect.height / 2 + (tx * f / tz) * scale);
186
+
187
+ rotation = Math.atan2(mVT[1][0], mVT[0][0]) - Math.PI / 2;
188
+ perspectiveScale = scale;
208
189
  } else {
209
- screenX = offsetX + (effectiveBufferW / 2 + (tx * f / tz)) * scaleX;
210
- screenY = offsetY + (effectiveBufferH / 2 + (ty * f / tz)) * scaleY;
211
- }
190
+ // LANDSCAPE / LAPTOP:
191
+ const scale = containerRect.width / videoW;
192
+ const displayH = videoH * scale;
193
+ const offsetY = (containerRect.height - displayH) / 2;
212
194
 
213
- // 6. Rotation: sync with CSS transform
214
- //atan2 gives angle of world X-axis in camera space.
215
- let rotation = Math.atan2(mVT[1][0], mVT[0][0]);
216
- if (needsRotation) {
217
- rotation += Math.PI / 2; // Compensate for the 90deg rotation of the video element
195
+ screenX = (containerRect.width / 2 + (tx * f / tz) * scale);
196
+ screenY = offsetY + (displayH / 2 + (ty * f / tz) * scale);
197
+
198
+ rotation = Math.atan2(mVT[1][0], mVT[0][0]);
199
+ perspectiveScale = scale;
218
200
  }
219
201
 
220
- // 7. Scale calculation
202
+ // Final Scale
221
203
  const matrixScale = Math.sqrt(mVT[0][0] ** 2 + mVT[1][0] ** 2);
222
- const perspectiveScale = (f / tz) * scaleX;
223
-
224
- const intrinsicWidth = (this.overlay instanceof HTMLVideoElement)
225
- ? this.overlay.videoWidth
226
- : (this.overlay instanceof HTMLImageElement ? this.overlay.naturalWidth : 0);
204
+ const finalScale = (f / tz) * perspectiveScale * matrixScale * this.scaleMultiplier;
227
205
 
228
- const baseScale = intrinsicWidth > 0
229
- ? (matrixScale * markerW * perspectiveScale) / intrinsicWidth
230
- : 1.0;
231
-
232
- const finalScale = baseScale * this.scaleMultiplier;
233
-
234
- // Apply transform
235
- this.overlay.style.width = 'auto';
206
+ // Apply
207
+ this.overlay.style.width = `${markerW}px`;
236
208
  this.overlay.style.height = 'auto';
237
209
  this.overlay.style.position = 'absolute';
238
210
  this.overlay.style.transformOrigin = 'center center';
239
211
  this.overlay.style.left = '0';
240
212
  this.overlay.style.top = '0';
241
213
  this.overlay.style.transform = `
242
- translate(${screenX}px, ${screenY}px)
243
- translate(-50%, -50%)
244
- scale(${finalScale})
245
- rotate(${rotation}rad)
246
- `;
214
+ translate(${screenX}px, ${screenY}px)
215
+ translate(-50%, -50%)
216
+ scale(${finalScale})
217
+ rotate(${rotation}rad)
218
+ `;
247
219
  }
248
220
  }
249
221