@srsergio/taptapp-ar 1.0.24 → 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,81 +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)
162
- // Controller uses inputHeight / 2 (sensor's vertical dimension) as the baseline.
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; // Mapping Sensor frame to Portrait Screen frame
186
- }
187
- // 7. Scale calculation (Robust Method)
188
- // Instead of detecting intrinsic width (unstable), we force a base CSS width
189
- // and calculate the scale to match the marker's projected screen width.
190
- const BASE_CSS_WIDTH = 1000;
168
+ // Final Scale
191
169
  const matrixScale = Math.sqrt(mVT[0][0] ** 2 + mVT[1][0] ** 2);
192
- const perspectiveScale = (f / tz) * scaleX;
193
- // Target pixel width on screen = markerW * matrixScale * perspectiveScale
194
- const targetScreenWidth = markerW * matrixScale * perspectiveScale;
195
- const finalScale = (targetScreenWidth / BASE_CSS_WIDTH) * this.scaleMultiplier;
170
+ const finalScale = (f / tz) * perspectiveScale * matrixScale * this.scaleMultiplier;
196
171
  // Apply
197
- this.overlay.style.width = `${BASE_CSS_WIDTH}px`;
172
+ this.overlay.style.width = `${markerW}px`;
198
173
  this.overlay.style.height = 'auto';
199
174
  this.overlay.style.position = 'absolute';
200
175
  this.overlay.style.transformOrigin = 'center center';
201
176
  this.overlay.style.left = '0';
202
177
  this.overlay.style.top = '0';
203
178
  this.overlay.style.transform = `
204
- translate(${screenX}px, ${screenY}px)
205
- translate(-50%, -50%)
206
- scale(${finalScale})
207
- rotate(${rotation}rad)
208
- `;
179
+ translate(${screenX}px, ${screenY}px)
180
+ translate(-50%, -50%)
181
+ scale(${finalScale})
182
+ rotate(${rotation}rad)
183
+ `;
209
184
  }
210
185
  }
211
186
  export { SimpleAR };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@srsergio/taptapp-ar",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "description": "AR Compiler for Node.js and Browser",
5
5
  "repository": {
6
6
  "type": "git",
@@ -156,91 +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)
192
- // Controller uses inputHeight / 2 (sensor's vertical dimension) as the baseline.
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; // Mapping Sensor frame to Portrait Screen frame
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 (Robust Method)
221
- // Instead of detecting intrinsic width (unstable), we force a base CSS width
222
- // and calculate the scale to match the marker's projected screen width.
223
- const BASE_CSS_WIDTH = 1000;
202
+ // Final Scale
224
203
  const matrixScale = Math.sqrt(mVT[0][0] ** 2 + mVT[1][0] ** 2);
225
- const perspectiveScale = (f / tz) * scaleX;
226
-
227
- // Target pixel width on screen = markerW * matrixScale * perspectiveScale
228
- const targetScreenWidth = markerW * matrixScale * perspectiveScale;
229
- const finalScale = (targetScreenWidth / BASE_CSS_WIDTH) * this.scaleMultiplier;
204
+ const finalScale = (f / tz) * perspectiveScale * matrixScale * this.scaleMultiplier;
230
205
 
231
206
  // Apply
232
- this.overlay.style.width = `${BASE_CSS_WIDTH}px`;
207
+ this.overlay.style.width = `${markerW}px`;
233
208
  this.overlay.style.height = 'auto';
234
209
  this.overlay.style.position = 'absolute';
235
210
  this.overlay.style.transformOrigin = 'center center';
236
211
  this.overlay.style.left = '0';
237
212
  this.overlay.style.top = '0';
238
213
  this.overlay.style.transform = `
239
- translate(${screenX}px, ${screenY}px)
240
- translate(-50%, -50%)
241
- scale(${finalScale})
242
- rotate(${rotation}rad)
243
- `;
214
+ translate(${screenX}px, ${screenY}px)
215
+ translate(-50%, -50%)
216
+ scale(${finalScale})
217
+ rotate(${rotation}rad)
218
+ `;
244
219
  }
245
220
  }
246
221