bilca commited on
Commit
5652ad2
·
verified ·
1 Parent(s): 5d4c056

Update index_2.js

Browse files
Files changed (1) hide show
  1. index_2.js +101 -86
index_2.js CHANGED
@@ -21,52 +21,68 @@
21
  let controlsInstance = null;
22
  let initialCameraPosition = null;
23
  let initialCameraRotation = null;
 
 
24
 
25
  // Generate a unique identifier for this widget instance.
26
  const instanceId = Math.random().toString(36).substr(2, 8);
27
 
28
  // Read configuration values from the JSON file.
29
- var gifUrl = config.gif_url;
30
- var plyUrl = config.ply_url;
31
- var minZoom = parseFloat(config.minZoom || "0");
32
- var maxZoom = parseFloat(config.maxZoom || "20");
33
- var minAngle = parseFloat(config.minAngle || "0");
34
- var maxAngle = parseFloat(config.maxAngle || "360");
35
- var minAzimuth = config.minAzimuth !== undefined ? parseFloat(config.minAzimuth) : -Infinity;
36
- var maxAzimuth = config.maxAzimuth !== undefined ? parseFloat(config.maxAzimuth) : Infinity;
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  // Determine the aspect ratio.
39
- var aspectPercent = "100%";
40
  if (config.aspect) {
41
  if (config.aspect.indexOf(":") !== -1) {
42
- var parts = config.aspect.split(":");
43
- var w = parseFloat(parts[0]);
44
- var h = parseFloat(parts[1]);
45
  if (!isNaN(w) && !isNaN(h) && w > 0) {
46
  aspectPercent = (h / w * 100) + "%";
47
  }
48
  } else {
49
- var aspectValue = parseFloat(config.aspect);
50
  if (!isNaN(aspectValue) && aspectValue > 0) {
51
  aspectPercent = (100 / aspectValue) + "%";
52
  }
53
  }
54
  } else {
55
- var parentContainer = scriptTag.parentNode;
56
- var containerWidth = parentContainer.offsetWidth;
57
- var containerHeight = parentContainer.offsetHeight;
58
  if (containerWidth > 0 && containerHeight > 0) {
59
  aspectPercent = (containerHeight / containerWidth * 100) + "%";
60
  }
61
  }
62
 
63
- // Detect if the device is iOS.
64
- var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
65
- // Also detect Android devices.
66
- const isMobile = isIOS || /Android/i.test(navigator.userAgent);
67
-
68
  // Inject CSS styles into the document head, scoped with the unique id.
69
- var styleEl = document.createElement('style');
70
  styleEl.textContent = `
71
  /* Widget container styling */
72
  #ply-widget-container-${instanceId} {
@@ -192,7 +208,7 @@
192
  document.head.appendChild(styleEl);
193
 
194
  // Create the widget container and set its inner HTML.
195
- var widgetContainer = document.createElement('div');
196
  widgetContainer.id = 'ply-widget-container-' + instanceId;
197
  widgetContainer.innerHTML = `
198
  <!-- GIF Preview Container -->
@@ -217,17 +233,17 @@
217
  scriptTag.parentNode.appendChild(widgetContainer);
218
 
219
  // Grab element references.
220
- var gifPreview = document.getElementById('gif-preview-container-' + instanceId);
221
- var viewerContainer = document.getElementById('viewer-container-' + instanceId);
222
- var previewImage = document.getElementById('preview-image-' + instanceId);
223
- var closeBtn = document.getElementById('close-btn-' + instanceId);
224
- var fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
225
- var helpToggle = document.getElementById('help-toggle-' + instanceId);
226
- var resetCameraBtn = document.getElementById('reset-camera-btn-' + instanceId);
227
- var menuContent = document.getElementById('menu-content-' + instanceId);
228
- var canvas = document.getElementById('canvas-' + instanceId);
229
- var progressDialog = document.getElementById('progress-dialog-' + instanceId);
230
- var progressIndicator = document.getElementById('progress-indicator-' + instanceId);
231
 
232
  // Set help instructions based on device type.
233
  if (isMobile) {
@@ -317,85 +333,84 @@
317
  menuContent.style.display = (menuContent.style.display === 'block') ? 'none' : 'block';
318
  });
319
 
320
- resetCameraBtn.addEventListener('click', function() {
 
321
  console.log("Reset camera button clicked.");
322
  if (cameraInstance && initialCameraPosition && initialCameraRotation) {
 
323
  cameraInstance.position = initialCameraPosition.clone();
324
  cameraInstance.rotation = initialCameraRotation.clone();
325
  if (typeof cameraInstance.update === 'function') {
326
  cameraInstance.update();
327
  }
328
- if (controlsInstance && typeof controlsInstance.update === 'function') {
329
- controlsInstance.update();
 
330
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331
  }
332
  });
333
 
334
  // --- Initialize the 3D PLY Viewer ---
335
  async function initializeViewer() {
336
- const SPLAT = await import("https://bilca-gsplat-library.static.hf.space/dist/index.js");
 
337
  progressDialog.style.display = 'block';
338
  const renderer = new SPLAT.WebGLRenderer(canvas);
339
  const scene = new SPLAT.Scene();
340
 
341
- // --- Compute the initial camera position based on device type ---
342
- let camPosArray;
343
- if (isMobile && config.cameraPositionPhone && Array.isArray(config.cameraPositionPhone) && config.cameraPositionPhone.length === 3) {
344
- camPosArray = config.cameraPositionPhone;
345
- } else if (config.cameraPositionComputer && Array.isArray(config.cameraPositionComputer) && config.cameraPositionComputer.length === 3) {
346
- camPosArray = config.cameraPositionComputer;
347
- } else {
348
- // Fallback to a default position if none provided.
349
- camPosArray = [1, 1, 5];
350
- }
351
- const camPos = new SPLAT.Vector3(camPosArray[0], camPosArray[1], camPosArray[2]);
352
-
353
- // --- Compute orbit parameters (alpha, beta, radius) using target = (0,0,0) ---
354
- const target = new SPLAT.Vector3(0, 0, 0);
355
- const dx = camPos.x - target.x;
356
- const dy = camPos.y - target.y;
357
- const dz = camPos.z - target.z;
358
- const computedRadius = Math.sqrt(dx * dx + dy * dy + dz * dz);
359
- // Note: OrbitControls expects: camera.y = target.y - radius*sin(beta)
360
- // Thus, beta is computed as:
361
- const computedBeta = -Math.asin(dy / computedRadius);
362
- // And for alpha, using:
363
- // camera.x = target.x + radius*sin(alpha)*cos(beta)
364
- // camera.z = target.z - radius*cos(alpha)*cos(beta)
365
- const computedAlpha = Math.atan2(dx, -dz);
366
-
367
- // Construct the camera using the computed position.
368
- const camera = new SPLAT.Camera(undefined, camPos);
369
-
370
- // Construct OrbitControls using the computed alpha, beta, and radius.
371
- const controls = new SPLAT.OrbitControls(
372
  camera,
373
  canvas,
374
- computedAlpha,
375
- computedBeta,
376
- computedRadius,
377
  true,
378
- target
 
 
 
379
  );
380
 
381
  cameraInstance = camera;
382
- controlsInstance = controls;
383
- // Save the initial state for the reset button.
384
  initialCameraPosition = camera.position.clone();
385
  initialCameraRotation = camera.rotation.clone();
386
 
387
  canvas.style.background = "#FEFEFD";
388
- controls.maxZoom = maxZoom;
389
- controls.minZoom = minZoom;
390
- controls.minAngle = minAngle;
391
- controls.maxAngle = maxAngle;
392
- controls.minAzimuth = minAzimuth;
393
- controls.maxAzimuth = maxAzimuth;
394
-
395
- // Set panSpeed: 0.5 on mobile, 1.2 on computer.
396
- controls.panSpeed = isMobile ? 0.5 : 1.2;
397
 
398
- controls.update();
399
 
400
  try {
401
  await SPLAT.PLYLoader.LoadAsync(
@@ -412,7 +427,7 @@
412
  }
413
 
414
  const frame = () => {
415
- controls.update();
416
  renderer.render(scene, camera);
417
  requestAnimationFrame(frame);
418
  };
 
21
  let controlsInstance = null;
22
  let initialCameraPosition = null;
23
  let initialCameraRotation = null;
24
+ // We'll save the imported SPLAT module here so we can reuse it later.
25
+ let SPLAT = null;
26
 
27
  // Generate a unique identifier for this widget instance.
28
  const instanceId = Math.random().toString(36).substr(2, 8);
29
 
30
  // Read configuration values from the JSON file.
31
+ const gifUrl = config.gif_url;
32
+ const plyUrl = config.ply_url;
33
+ const minZoom = parseFloat(config.minZoom || "0");
34
+ const maxZoom = parseFloat(config.maxZoom || "20");
35
+ const minAngle = parseFloat(config.minAngle || "0");
36
+ const maxAngle = parseFloat(config.maxAngle || "360");
37
+ const minAzimuth = config.minAzimuth !== undefined ? parseFloat(config.minAzimuth) : -Infinity;
38
+ const maxAzimuth = config.maxAzimuth !== undefined ? parseFloat(config.maxAzimuth) : Infinity;
39
 
40
+ // Read initial orbit parameters for desktop.
41
+ const initAlphaDesktop = config.initAlpha !== undefined ? parseFloat(config.initAlpha) : 0.5;
42
+ const initBetaDesktop = config.initBeta !== undefined ? parseFloat(config.initBeta) : 0.5;
43
+ const initRadiusDesktop = config.initRadius !== undefined ? parseFloat(config.initRadius) : 5;
44
+ // Read initial orbit parameters for phone.
45
+ const initAlphaPhone = config.initAlphaPhone !== undefined ? parseFloat(config.initAlphaPhone) : initAlphaDesktop;
46
+ const initBetaPhone = config.initBetaPhone !== undefined ? parseFloat(config.initBetaPhone) : initBetaDesktop;
47
+ const initRadiusPhone = config.initRadiusPhone !== undefined ? parseFloat(config.initRadiusPhone) : initRadiusDesktop;
48
+
49
+ // Detect if the device is iOS.
50
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
51
+ // Also detect Android devices.
52
+ const isMobile = isIOS || /Android/i.test(navigator.userAgent);
53
+
54
+ // Choose the appropriate initial orbit values based on device type.
55
+ const chosenInitAlpha = isMobile ? initAlphaPhone : initAlphaDesktop;
56
+ const chosenInitBeta = isMobile ? initBetaPhone : initBetaDesktop;
57
+ const chosenInitRadius = isMobile ? initRadiusPhone : initRadiusDesktop;
58
+
59
  // Determine the aspect ratio.
60
+ let aspectPercent = "100%";
61
  if (config.aspect) {
62
  if (config.aspect.indexOf(":") !== -1) {
63
+ const parts = config.aspect.split(":");
64
+ const w = parseFloat(parts[0]);
65
+ const h = parseFloat(parts[1]);
66
  if (!isNaN(w) && !isNaN(h) && w > 0) {
67
  aspectPercent = (h / w * 100) + "%";
68
  }
69
  } else {
70
+ const aspectValue = parseFloat(config.aspect);
71
  if (!isNaN(aspectValue) && aspectValue > 0) {
72
  aspectPercent = (100 / aspectValue) + "%";
73
  }
74
  }
75
  } else {
76
+ const parentContainer = scriptTag.parentNode;
77
+ const containerWidth = parentContainer.offsetWidth;
78
+ const containerHeight = parentContainer.offsetHeight;
79
  if (containerWidth > 0 && containerHeight > 0) {
80
  aspectPercent = (containerHeight / containerWidth * 100) + "%";
81
  }
82
  }
83
 
 
 
 
 
 
84
  // Inject CSS styles into the document head, scoped with the unique id.
85
+ const styleEl = document.createElement('style');
86
  styleEl.textContent = `
87
  /* Widget container styling */
88
  #ply-widget-container-${instanceId} {
 
208
  document.head.appendChild(styleEl);
209
 
210
  // Create the widget container and set its inner HTML.
211
+ const widgetContainer = document.createElement('div');
212
  widgetContainer.id = 'ply-widget-container-' + instanceId;
213
  widgetContainer.innerHTML = `
214
  <!-- GIF Preview Container -->
 
233
  scriptTag.parentNode.appendChild(widgetContainer);
234
 
235
  // Grab element references.
236
+ const gifPreview = document.getElementById('gif-preview-container-' + instanceId);
237
+ const viewerContainer = document.getElementById('viewer-container-' + instanceId);
238
+ const previewImage = document.getElementById('preview-image-' + instanceId);
239
+ const closeBtn = document.getElementById('close-btn-' + instanceId);
240
+ const fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
241
+ const helpToggle = document.getElementById('help-toggle-' + instanceId);
242
+ const resetCameraBtn = document.getElementById('reset-camera-btn-' + instanceId);
243
+ const menuContent = document.getElementById('menu-content-' + instanceId);
244
+ const canvas = document.getElementById('canvas-' + instanceId);
245
+ const progressDialog = document.getElementById('progress-dialog-' + instanceId);
246
+ const progressIndicator = document.getElementById('progress-indicator-' + instanceId);
247
 
248
  // Set help instructions based on device type.
249
  if (isMobile) {
 
333
  menuContent.style.display = (menuContent.style.display === 'block') ? 'none' : 'block';
334
  });
335
 
336
+ // Modified reset button: re-creates the OrbitControls with the original parameters.
337
+ resetCameraBtn.addEventListener('click', async function() {
338
  console.log("Reset camera button clicked.");
339
  if (cameraInstance && initialCameraPosition && initialCameraRotation) {
340
+ // Reset camera position and rotation.
341
  cameraInstance.position = initialCameraPosition.clone();
342
  cameraInstance.rotation = initialCameraRotation.clone();
343
  if (typeof cameraInstance.update === 'function') {
344
  cameraInstance.update();
345
  }
346
+ // Dispose of the current controls.
347
+ if (controlsInstance && typeof controlsInstance.dispose === 'function') {
348
+ controlsInstance.dispose();
349
  }
350
+ // Re-create OrbitControls with the original chosen parameters.
351
+ controlsInstance = new SPLAT.OrbitControls(
352
+ cameraInstance,
353
+ canvas,
354
+ 0.5, // default alpha fallback
355
+ 0.5, // default beta fallback
356
+ 5, // default radius fallback
357
+ true,
358
+ new SPLAT.Vector3(),
359
+ chosenInitAlpha,
360
+ chosenInitBeta,
361
+ chosenInitRadius
362
+ );
363
+ controlsInstance.maxZoom = maxZoom;
364
+ controlsInstance.minZoom = minZoom;
365
+ controlsInstance.minAngle = minAngle;
366
+ controlsInstance.maxAngle = maxAngle;
367
+ controlsInstance.minAzimuth = minAzimuth;
368
+ controlsInstance.maxAzimuth = maxAzimuth;
369
+ controlsInstance.panSpeed = isMobile ? 0.5 : 1.2;
370
+ controlsInstance.update();
371
  }
372
  });
373
 
374
  // --- Initialize the 3D PLY Viewer ---
375
  async function initializeViewer() {
376
+ // Import SPLAT and store it globally.
377
+ SPLAT = await import("https://bilca-gsplat-library.static.hf.space/dist/index.js");
378
  progressDialog.style.display = 'block';
379
  const renderer = new SPLAT.WebGLRenderer(canvas);
380
  const scene = new SPLAT.Scene();
381
 
382
+ // Construct the camera (no custom position since it's no longer in the JSON).
383
+ const camera = new SPLAT.Camera();
384
+
385
+ // Construct OrbitControls with the chosen initial orbit parameters.
386
+ controlsInstance = new SPLAT.OrbitControls(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  camera,
388
  canvas,
389
+ 0.5, // default alpha fallback
390
+ 0.5, // default beta fallback
391
+ 5, // default radius fallback
392
  true,
393
+ new SPLAT.Vector3(),
394
+ chosenInitAlpha,
395
+ chosenInitBeta,
396
+ chosenInitRadius
397
  );
398
 
399
  cameraInstance = camera;
400
+ // Save the initial camera state (after controls are created)
 
401
  initialCameraPosition = camera.position.clone();
402
  initialCameraRotation = camera.rotation.clone();
403
 
404
  canvas.style.background = "#FEFEFD";
405
+ controlsInstance.maxZoom = maxZoom;
406
+ controlsInstance.minZoom = minZoom;
407
+ controlsInstance.minAngle = minAngle;
408
+ controlsInstance.maxAngle = maxAngle;
409
+ controlsInstance.minAzimuth = minAzimuth;
410
+ controlsInstance.maxAzimuth = maxAzimuth;
411
+ controlsInstance.panSpeed = isMobile ? 0.5 : 1.2;
 
 
412
 
413
+ controlsInstance.update();
414
 
415
  try {
416
  await SPLAT.PLYLoader.LoadAsync(
 
427
  }
428
 
429
  const frame = () => {
430
+ controlsInstance.update();
431
  renderer.render(scene, camera);
432
  requestAnimationFrame(frame);
433
  };