@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.
- package/dist/compiler/simple-ar.js +29 -54
- package/package.json +1 -1
- package/src/compiler/simple-ar.js +33 -58
|
@@ -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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
169
|
-
let screenX, screenY;
|
|
145
|
+
let screenX, screenY, rotation, perspectiveScale;
|
|
170
146
|
if (needsRotation) {
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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
|
-
//
|
|
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
|
|
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 = `${
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
@@ -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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
201
|
-
|
|
174
|
+
let screenX, screenY, rotation, perspectiveScale;
|
|
175
|
+
|
|
202
176
|
if (needsRotation) {
|
|
203
|
-
//
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
210
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
//
|
|
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
|
|
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 = `${
|
|
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
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
|