MikaFil commited on
Commit
1daadf3
·
verified ·
1 Parent(s): a0f3f3f

Update viewer_ar.js

Browse files
Files changed (1) hide show
  1. viewer_ar.js +70 -69
viewer_ar.js CHANGED
@@ -1,6 +1,7 @@
1
  /* script_ar.js — AR PlayCanvas + GLB HuggingFace
2
  - Chargeur PlayCanvas robuste (ESM -> UMD avec fallbacks + timeout)
3
  - WebXR AR Hit Test, placement auto, drag + rotation Y (2 doigts)
 
4
  - Aucune dépendance externe autre que PlayCanvas et le GLB
5
  */
6
 
@@ -222,13 +223,17 @@
222
  return;
223
  }
224
 
225
- // --- Démarrage AR ---
226
  const activateAR = () => {
227
  if (!app.xr.isAvailable(pc.XRTYPE_AR)) {
228
  message("AR immersive indisponible sur cet appareil.");
229
  return;
230
  }
231
  camera.camera.startXr(pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, {
 
 
 
 
232
  callback: (err) => {
233
  if (err) message(`Échec du démarrage AR : ${err.message}`);
234
  }
@@ -279,7 +284,7 @@
279
  });
280
 
281
  // =========================
282
- // --- Interactions + DEBUG
283
  // =========================
284
  let isDragging = false; // déplacement du modèle
285
  let rotateMode = false; // rotation 2 doigts (tactile) ou souris
@@ -296,13 +301,6 @@
296
  isDragging = false;
297
  }
298
 
299
- // ===== Rotation 2 doigts (incrémentale) =====
300
- let lastTwoFingerAngle = null; // radians
301
- const RAD2DEG = 180 / Math.PI;
302
-
303
- // --- DEBUG: alerte une seule fois au début d'un geste 2 doigts ---
304
- let rotationAlertShown = false;
305
-
306
  // Déplacement (input XR) — ne démarre que si pas de 2 doigts
307
  app.xr.input.on("add", (inputSource) => {
308
  inputSource.on("selectstart", () => {
@@ -332,78 +330,75 @@
332
  });
333
  });
334
 
335
- // ===== Gestes tactiles (avec alerte debug) =====
336
- if (app.touch) {
337
- const touches = new Map(); // id -> {x,y}
338
-
339
- const twoFingerAngle = () => {
340
- if (touches.size < 2) return null;
341
- const it = touches.values();
342
- const a = it.next().value;
343
- const b = it.next().value;
344
- return Math.atan2(b.y - a.y, b.x - a.x);
345
- };
346
-
347
- app.touch.on("touchstart", (e) => {
348
- for (const t of e.touches) touches.set(t.id, { x: t.x, y: t.y });
349
-
350
- if (touches.size >= 2) {
351
- multiTouchActive = true;
352
- rotateMode = true;
353
- cancelAllTransientHitTests();
354
- lastTwoFingerAngle = twoFingerAngle();
355
-
356
- // --- DEBUG ALERT ---
357
- if (!rotationAlertShown) {
358
- rotationAlertShown = true;
359
- console.log("[AR] Rotation 2 doigts détectée — touches:", Array.from(touches.keys()), "count:", touches.size);
360
- try { alert("Rotation à 2 doigts détectée"); } catch(_) {}
361
- }
362
- }
363
- });
364
-
365
- app.touch.on("touchmove", (e) => {
366
- for (const t of e.touches) {
367
- if (touches.has(t.id)) touches.set(t.id, { x: t.x, y: t.y });
368
- }
369
 
370
- if (rotateMode && multiTouchActive && modelRoot.enabled && touches.size >= 2) {
371
- const ang = twoFingerAngle();
372
- if (ang !== null && lastTwoFingerAngle !== null) {
373
- let delta = ang - lastTwoFingerAngle; // radians
374
- if (delta > Math.PI) delta -= 2 * Math.PI;
375
- if (delta < -Math.PI) delta += 2 * Math.PI;
376
 
377
- const eul = modelRoot.getEulerAngles();
378
- modelRoot.setEulerAngles(eul.x, eul.y + (delta * RAD2DEG), eul.z);
 
 
 
 
 
 
379
 
380
- lastTwoFingerAngle = ang;
381
- }
 
 
382
  }
383
- });
 
 
 
 
 
 
 
 
 
 
384
 
385
- app.touch.on("touchend", (e) => {
386
- for (const t of e.changedTouches) touches.delete(t.id);
387
 
388
- if (touches.size < 2) {
389
- rotateMode = false;
390
- multiTouchActive = false;
391
- lastTwoFingerAngle = null;
392
- rotationAlertShown = false; // reset pour le prochain geste
393
  }
394
- });
 
 
 
395
 
396
- app.touch.on("touchcancel", () => {
397
- touches.clear();
 
398
  rotateMode = false;
399
  multiTouchActive = false;
400
  lastTwoFingerAngle = null;
401
- rotationAlertShown = false; // reset
402
- cancelAllTransientHitTests();
403
- });
404
- }
405
 
406
- // Souris : déplacement (clic gauche maintenu) & rotation (clic droit ou Shift+clic gauche)
 
 
 
 
 
 
 
 
407
  app.mouse.on("mousedown", (e) => {
408
  if (!app.xr.active || !placedOnce) return;
409
 
@@ -453,6 +448,12 @@
453
  lastTwoFingerAngle = null;
454
  rotationAlertShown = false;
455
  cancelAllTransientHitTests();
 
 
 
 
 
 
456
  });
457
 
458
  app.xr.on(`available:${pc.XRTYPE_AR}`, (available) => {
 
1
  /* script_ar.js — AR PlayCanvas + GLB HuggingFace
2
  - Chargeur PlayCanvas robuste (ESM -> UMD avec fallbacks + timeout)
3
  - WebXR AR Hit Test, placement auto, drag + rotation Y (2 doigts)
4
+ - DOM Overlay activé pour capter les touches en AR
5
  - Aucune dépendance externe autre que PlayCanvas et le GLB
6
  */
7
 
 
223
  return;
224
  }
225
 
226
+ // --- Démarrage AR (MODIF: activer DOM Overlay & features) ---
227
  const activateAR = () => {
228
  if (!app.xr.isAvailable(pc.XRTYPE_AR)) {
229
  message("AR immersive indisponible sur cet appareil.");
230
  return;
231
  }
232
  camera.camera.startXr(pc.XRTYPE_AR, pc.XRSPACE_LOCALFLOOR, {
233
+ // IMPORTANT: activer l'overlay DOM pour recevoir les events tactiles en AR
234
+ domOverlay: { root: document.body }, // <-- MODIF
235
+ requiredFeatures: ["hit-test", "dom-overlay"], // <-- MODIF (hit-test déjà géré mais ok)
236
+ optionalFeatures: ["plane-detection"], // <-- MODIF (facultatif)
237
  callback: (err) => {
238
  if (err) message(`Échec du démarrage AR : ${err.message}`);
239
  }
 
284
  });
285
 
286
  // =========================
287
+ // --- Interactions
288
  // =========================
289
  let isDragging = false; // déplacement du modèle
290
  let rotateMode = false; // rotation 2 doigts (tactile) ou souris
 
301
  isDragging = false;
302
  }
303
 
 
 
 
 
 
 
 
304
  // Déplacement (input XR) — ne démarre que si pas de 2 doigts
305
  app.xr.input.on("add", (inputSource) => {
306
  inputSource.on("selectstart", () => {
 
330
  });
331
  });
332
 
333
+ // =========================
334
+ // --- Gestes tactiles NATIFS via DOM Overlay (MODIF)
335
+ // =========================
336
+ // On n'utilise PAS app.touch ici : on écoute le canvas en DOM Overlay XR
337
+ const RAD2DEG = 180 / Math.PI;
338
+ let lastTwoFingerAngle = null;
339
+ let rotationAlertShown = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
+ function getAngleTwoTouches(touches) {
342
+ if (touches.length < 2) return null;
343
+ const t0 = touches[0], t1 = touches[1];
344
+ return Math.atan2(t1.clientY - t0.clientY, t1.clientX - t0.clientX);
345
+ }
 
346
 
347
+ // Démarre un geste : si 2 doigts, activer rotation et couper la translation
348
+ const onTouchStart = (e) => {
349
+ if (!app.xr.active) return; // on s'intéresse seulement au mode AR
350
+ if (e.touches.length >= 2) {
351
+ multiTouchActive = true;
352
+ rotateMode = true;
353
+ cancelAllTransientHitTests();
354
+ lastTwoFingerAngle = getAngleTwoTouches(e.touches);
355
 
356
+ if (!rotationAlertShown) {
357
+ rotationAlertShown = true;
358
+ console.log("[AR] Rotation 2 doigts détectée — touches:", e.touches.length);
359
+ try { alert("Rotation à 2 doigts détectée"); } catch(_) {}
360
  }
361
+ }
362
+ };
363
+
364
+ const onTouchMove = (e) => {
365
+ if (!app.xr.active) return;
366
+ if (rotateMode && multiTouchActive && modelRoot.enabled && e.touches.length >= 2) {
367
+ const ang = getAngleTwoTouches(e.touches);
368
+ if (ang !== null && lastTwoFingerAngle !== null) {
369
+ let delta = ang - lastTwoFingerAngle;
370
+ if (delta > Math.PI) delta -= 2 * Math.PI;
371
+ if (delta < -Math.PI) delta += 2 * Math.PI;
372
 
373
+ const eul = modelRoot.getEulerAngles();
374
+ modelRoot.setEulerAngles(eul.x, eul.y + (delta * RAD2DEG), eul.z);
375
 
376
+ lastTwoFingerAngle = ang;
 
 
 
 
377
  }
378
+ // empêcher le scroll/zoom navigateur & gestes par défaut
379
+ e.preventDefault();
380
+ }
381
+ };
382
 
383
+ const onTouchEnd = (e) => {
384
+ if (!app.xr.active) return;
385
+ if (e.touches.length < 2) {
386
  rotateMode = false;
387
  multiTouchActive = false;
388
  lastTwoFingerAngle = null;
389
+ rotationAlertShown = false;
390
+ }
391
+ };
 
392
 
393
+ // IMPORTANT : listeners non-passifs pour pouvoir appeler preventDefault
394
+ canvas.addEventListener("touchstart", onTouchStart, { passive: false });
395
+ canvas.addEventListener("touchmove", onTouchMove, { passive: false });
396
+ canvas.addEventListener("touchend", onTouchEnd, { passive: false });
397
+ canvas.addEventListener("touchcancel", onTouchEnd, { passive: false });
398
+
399
+ // =========================
400
+ // Souris (pour desktop)
401
+ // =========================
402
  app.mouse.on("mousedown", (e) => {
403
  if (!app.xr.active || !placedOnce) return;
404
 
 
448
  lastTwoFingerAngle = null;
449
  rotationAlertShown = false;
450
  cancelAllTransientHitTests();
451
+
452
+ // Nettoyage des listeners DOM (au cas où)
453
+ canvas.removeEventListener("touchstart", onTouchStart);
454
+ canvas.removeEventListener("touchmove", onTouchMove);
455
+ canvas.removeEventListener("touchend", onTouchEnd);
456
+ canvas.removeEventListener("touchcancel", onTouchEnd);
457
  });
458
 
459
  app.xr.on(`available:${pc.XRTYPE_AR}`, (available) => {