MikaFil commited on
Commit
e787d24
·
verified ·
1 Parent(s): 016ce08

Update viewer_ar.js

Browse files
Files changed (1) hide show
  1. viewer_ar.js +76 -53
viewer_ar.js CHANGED
@@ -1,4 +1,5 @@
1
- /* script_ar.js — AR PlayCanvas + GLB HuggingFace
 
2
  - Hit-test AR (HORIZONTAUX uniquement) + placement + drag (XR)
3
  - Slider custom Yaw (360° en haut → 0° en bas), knob centré, rail plein
4
  - Blocage total des interactions scène quand on touche le slider
@@ -7,14 +8,22 @@
7
  */
8
 
9
  (function () {
10
- const GLB_URL = "https://huggingface.co/datasets/MikaFil/viewer_gs/resolve/main/AR/tests/danae_no_metallic.glb";
11
-
12
- // ===== PlayCanvas version fixée =====
13
- const PC_VERSION = "2.11.7";
14
- const PC_URLS = {
15
- esm: ["https://cdn.jsdelivr.net/npm/playcanvas@" + PC_VERSION + "/build/playcanvas.min.mjs"],
16
- umd: ["https://cdn.jsdelivr.net/npm/playcanvas@" + PC_VERSION + "/build/playcanvas.min.js"]
17
- };
 
 
 
 
 
 
 
 
18
 
19
  function timeout(ms) {
20
  return new Promise(function (_res, rej) {
@@ -22,6 +31,26 @@
22
  });
23
  }
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  async function loadPlayCanvasRobust(opts) {
26
  opts = opts || {};
27
  var esmFirst = (typeof opts.esmFirst === "boolean") ? opts.esmFirst : true;
@@ -39,9 +68,7 @@
39
  if (!window.pc) window.pc = ns;
40
  return window.pc;
41
  }
42
- } catch (e) {
43
- // continue
44
- }
45
  }
46
  throw new Error("ESM failed");
47
  }
@@ -62,9 +89,7 @@
62
  timeout(loadTimeoutMs)
63
  ]);
64
  if (window.pc && window.pc.Application) return window.pc;
65
- } catch (e) {
66
- // continue
67
- }
68
  }
69
  throw new Error("UMD failed");
70
  }
@@ -145,8 +170,16 @@
145
  return p;
146
  }
147
 
148
- // ===== Boot =====
149
  (async function () {
 
 
 
 
 
 
 
 
150
  try {
151
  await loadPlayCanvasRobust({ esmFirst: true, loadTimeoutMs: 15000 });
152
  } catch (e) {
@@ -154,11 +187,13 @@
154
  message("Impossible de charger PlayCanvas (réseau/CDN). Réessaie plus tard.");
155
  return;
156
  }
157
- initARApp();
 
 
158
  })();
159
 
160
  // ===== App =====
161
- function initARApp() {
162
  var pc = window.pc;
163
  var canvas = ensureCanvas();
164
  var ui = ensureSliderUI();
@@ -223,19 +258,19 @@
223
  var BLOB_SIZE = 0.4;
224
  var BLOB_OFFSET_Y = 0.005;
225
 
226
- function makeBlobTexture(app, size = 256) {
227
- const cvs = document.createElement('canvas');
 
228
  cvs.width = cvs.height = size;
229
- const ctx = cvs.getContext('2d');
230
-
231
- const r = size * 0.45;
232
- const grd = ctx.createRadialGradient(size/2, size/2, r*0.2, size/2, size/2, r);
233
  grd.addColorStop(0, 'rgba(0,0,0,0.5)'); // centre sombre
234
- grd.addColorStop(1, 'rgba(0,0,0,0.0)'); // bords transparents
235
  ctx.fillStyle = grd;
236
  ctx.fillRect(0, 0, size, size);
237
-
238
- const tex = new pc.Texture(app.graphicsDevice, {
239
  width: size,
240
  height: size,
241
  format: pc.PIXELFORMAT_R8_G8_B8_A8,
@@ -247,44 +282,32 @@
247
  return tex;
248
  }
249
 
250
-
251
  function createBlobShadowAt(pos, rot) {
252
- const tex = makeBlobTexture(app, 256);
253
-
254
- const blobMat = new pc.StandardMaterial();
255
- // Couleur noire (ombre)
256
- blobMat.diffuse.set(0, 0, 0);
257
-
258
- // >>> CLÉ : utiliser l’alpha de la texture pour la transparence
259
  blobMat.opacity = 1.0;
260
- blobMat.opacityMap = tex; // on se sert du canal A
261
  blobMat.opacityMapChannel = 'a';
262
-
263
- // Pas besoin d’éclairage sur une “ombre peinte”
264
  blobMat.useLighting = false;
265
-
266
- // Mélange standard + pas d’écriture dans le depth (évite de masquer le modèle)
267
- blobMat.blendType = pc.BLEND_NORMAL; // (si halos bizarres, essayer PREMULTIPLIED)
268
  blobMat.depthWrite = false;
269
-
270
- // Optionnel: adoucir un poil le tri/transpa
271
- blobMat.alphaTest = 0; // on ne découpe pas “dur”, on laisse le gradient
272
  blobMat.update();
273
-
274
- const e = new pc.Entity("BlobShadow");
275
  e.addComponent("render", { type: "plane", castShadows: false, receiveShadows: false });
276
  e.render.material = blobMat;
277
-
278
- // Place légèrement au-dessus du sol pour éviter le z-fighting
279
  e.setPosition(pos.x, pos.y + BLOB_OFFSET_Y, pos.z);
280
- e.setRotation(rot); // suit le plan horizontal détecté
281
  e.setLocalScale(BLOB_SIZE, 1, BLOB_SIZE);
282
-
283
  app.root.addChild(e);
284
  return e;
285
  }
286
 
287
-
288
  // Euler base
289
  var baseEulerX = 0, baseEulerZ = 0;
290
 
@@ -311,14 +334,14 @@
311
  if (rotLikePlane) blob.setRotation(rotLikePlane);
312
  }
313
 
314
- // Chargement GLB
315
  app.assets.loadFromUrl(GLB_URL, "container", function (err, asset) {
316
  if (err) { console.error(err); message("Échec du chargement du modèle GLB."); return; }
317
  var instance = asset.resource.instantiateRenderEntity({ castShadows: true, receiveShadows: false });
318
  modelRoot.addChild(instance);
319
  modelRoot.setLocalScale(1, 1, 1);
320
 
321
- // Fix matériaux
322
  var renders = instance.findComponents('render');
323
  for (var ri = 0; ri < renders.length; ri++) {
324
  var r = renders[ri];
 
1
+ /* script_ar.js — AR PlayCanvas + GLB HuggingFace (GLB via config.json)
2
+ - Lit config.json (data-config) => { "glb_url": "..." }
3
  - Hit-test AR (HORIZONTAUX uniquement) + placement + drag (XR)
4
  - Slider custom Yaw (360° en haut → 0° en bas), knob centré, rail plein
5
  - Blocage total des interactions scène quand on touche le slider
 
8
  */
9
 
10
  (function () {
11
+ // ===== Récup config.json depuis data-config =====
12
+ function findConfigUrl() {
13
+ var el = document.currentScript || null;
14
+ if (!el) {
15
+ var scripts = document.getElementsByTagName('script');
16
+ for (var i = scripts.length - 1; i >= 0; i--) {
17
+ if (scripts[i].getAttribute && scripts[i].getAttribute('data-config')) {
18
+ el = scripts[i];
19
+ break;
20
+ }
21
+ }
22
+ }
23
+ if (!el) return null;
24
+ var url = el.getAttribute('data-config');
25
+ return url || null;
26
+ }
27
 
28
  function timeout(ms) {
29
  return new Promise(function (_res, rej) {
 
31
  });
32
  }
33
 
34
+ async function loadConfigJson(url) {
35
+ if (!url) return null;
36
+ try {
37
+ var resp = await fetch(url, { cache: 'no-store' });
38
+ if (!resp.ok) throw new Error("HTTP " + resp.status);
39
+ var json = await resp.json();
40
+ return json;
41
+ } catch (e) {
42
+ console.error("Erreur chargement config.json:", e);
43
+ return null;
44
+ }
45
+ }
46
+
47
+ // ===== PlayCanvas version fixée =====
48
+ var PC_VERSION = "2.11.7";
49
+ var PC_URLS = {
50
+ esm: ["https://cdn.jsdelivr.net/npm/playcanvas@" + PC_VERSION + "/build/playcanvas.min.mjs"],
51
+ umd: ["https://cdn.jsdelivr.net/npm/playcanvas@" + PC_VERSION + "/build/playcanvas.min.js"]
52
+ };
53
+
54
  async function loadPlayCanvasRobust(opts) {
55
  opts = opts || {};
56
  var esmFirst = (typeof opts.esmFirst === "boolean") ? opts.esmFirst : true;
 
68
  if (!window.pc) window.pc = ns;
69
  return window.pc;
70
  }
71
+ } catch (e) { /* continue */ }
 
 
72
  }
73
  throw new Error("ESM failed");
74
  }
 
89
  timeout(loadTimeoutMs)
90
  ]);
91
  if (window.pc && window.pc.Application) return window.pc;
92
+ } catch (e) { /* continue */ }
 
 
93
  }
94
  throw new Error("UMD failed");
95
  }
 
170
  return p;
171
  }
172
 
173
+ // ===== Boot : charge config.json => GLB_URL => PlayCanvas => App =====
174
  (async function () {
175
+ // 1) Lire la config (glb_url)
176
+ var cfgUrl = findConfigUrl();
177
+ var cfg = await loadConfigJson(cfgUrl);
178
+ var GLB_URL = (cfg && typeof cfg.glb_url === "string" && cfg.glb_url) ?
179
+ cfg.glb_url :
180
+ "https://huggingface.co/datasets/MikaFil/viewer_gs/resolve/main/AR/tests/danae_no_metallic.glb";
181
+
182
+ // 2) Charger PlayCanvas
183
  try {
184
  await loadPlayCanvasRobust({ esmFirst: true, loadTimeoutMs: 15000 });
185
  } catch (e) {
 
187
  message("Impossible de charger PlayCanvas (réseau/CDN). Réessaie plus tard.");
188
  return;
189
  }
190
+
191
+ // 3) Lancer l'app avec l'URL lue
192
+ initARApp(GLB_URL);
193
  })();
194
 
195
  // ===== App =====
196
+ function initARApp(GLB_URL) {
197
  var pc = window.pc;
198
  var canvas = ensureCanvas();
199
  var ui = ensureSliderUI();
 
258
  var BLOB_SIZE = 0.4;
259
  var BLOB_OFFSET_Y = 0.005;
260
 
261
+ function makeBlobTexture(app, size) {
262
+ size = size || 256;
263
+ var cvs = document.createElement('canvas');
264
  cvs.width = cvs.height = size;
265
+ var ctx = cvs.getContext('2d');
266
+ var r = size * 0.45;
267
+ var grd = ctx.createRadialGradient(size/2, size/2, r*0.2, size/2, size/2, r);
 
268
  grd.addColorStop(0, 'rgba(0,0,0,0.5)'); // centre sombre
269
+ grd.addColorStop(1, 'rgba(0,0,0,0.0)'); // bords transparents
270
  ctx.fillStyle = grd;
271
  ctx.fillRect(0, 0, size, size);
272
+
273
+ var tex = new pc.Texture(app.graphicsDevice, {
274
  width: size,
275
  height: size,
276
  format: pc.PIXELFORMAT_R8_G8_B8_A8,
 
282
  return tex;
283
  }
284
 
 
285
  function createBlobShadowAt(pos, rot) {
286
+ var tex = makeBlobTexture(app, 256);
287
+
288
+ var blobMat = new pc.StandardMaterial();
289
+ blobMat.diffuse = new pc.Color(0, 0, 0);
 
 
 
290
  blobMat.opacity = 1.0;
291
+ blobMat.opacityMap = tex; // utilise alpha pour la transparence
292
  blobMat.opacityMapChannel = 'a';
 
 
293
  blobMat.useLighting = false;
294
+ blobMat.blendType = pc.BLEND_NORMAL;
 
 
295
  blobMat.depthWrite = false;
296
+ blobMat.alphaTest = 0;
 
 
297
  blobMat.update();
298
+
299
+ var e = new pc.Entity("BlobShadow");
300
  e.addComponent("render", { type: "plane", castShadows: false, receiveShadows: false });
301
  e.render.material = blobMat;
302
+
 
303
  e.setPosition(pos.x, pos.y + BLOB_OFFSET_Y, pos.z);
304
+ e.setRotation(rot);
305
  e.setLocalScale(BLOB_SIZE, 1, BLOB_SIZE);
306
+
307
  app.root.addChild(e);
308
  return e;
309
  }
310
 
 
311
  // Euler base
312
  var baseEulerX = 0, baseEulerZ = 0;
313
 
 
334
  if (rotLikePlane) blob.setRotation(rotLikePlane);
335
  }
336
 
337
+ // Chargement GLB (depuis config.json)
338
  app.assets.loadFromUrl(GLB_URL, "container", function (err, asset) {
339
  if (err) { console.error(err); message("Échec du chargement du modèle GLB."); return; }
340
  var instance = asset.resource.instantiateRenderEntity({ castShadows: true, receiveShadows: false });
341
  modelRoot.addChild(instance);
342
  modelRoot.setLocalScale(1, 1, 1);
343
 
344
+ // Fix matériaux (anti-objets trop sombres)
345
  var renders = instance.findComponents('render');
346
  for (var ri = 0; ri < renders.length; ri++) {
347
  var r = renders[ri];