MikaFil commited on
Commit
397bf7b
·
verified ·
1 Parent(s): 7523107

Update viewer.js

Browse files
Files changed (1) hide show
  1. viewer.js +47 -18
viewer.js CHANGED
@@ -8,6 +8,7 @@ export let app = null;
8
  let cameraEntity = null;
9
  let modelEntity = null;
10
  let viewerInitialized = false;
 
11
 
12
  let chosenCameraX, chosenCameraY, chosenCameraZ;
13
  let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minPivotY, minY;
@@ -26,19 +27,19 @@ export async function initializeViewer(config, instanceId) {
26
  // 1. Read config
27
  plyUrl = config.ply_url;
28
  glbUrl = config.glb_url;
29
- minZoom = parseFloat(config.minZoom || "1");
30
- maxZoom = parseFloat(config.maxZoom || "20");
31
- minAngle = parseFloat(config.minAngle || "-45");
32
- maxAngle = parseFloat(config.maxAngle || "90");
33
- minAzimuth = (config.minAzimuth !== undefined) ? parseFloat(config.minAzimuth) : -360;
34
- maxAzimuth = (config.maxAzimuth !== undefined) ? parseFloat(config.maxAzimuth) : 360;
35
- minPivotY = parseFloat(config.minPivotY || "0");
36
- minY = (config.minY !== undefined) ? parseFloat(config.minY) : 0;
37
-
38
- modelX = (config.modelX !== undefined) ? parseFloat(config.modelX) : 0;
39
- modelY = (config.modelY !== undefined) ? parseFloat(config.modelY) : 0;
40
- modelZ = (config.modelZ !== undefined) ? parseFloat(config.modelZ) : 0;
41
- modelScale = (config.modelScale !== undefined) ? parseFloat(config.modelScale) : 1;
42
  modelRotationX = (config.modelRotationX !== undefined) ? parseFloat(config.modelRotationX) : 0;
43
  modelRotationY = (config.modelRotationY !== undefined) ? parseFloat(config.modelRotationY) : 0;
44
  modelRotationZ = (config.modelRotationZ !== undefined) ? parseFloat(config.modelRotationZ) : 0;
@@ -55,7 +56,7 @@ export async function initializeViewer(config, instanceId) {
55
  chosenCameraZ = isMobile ? cameraZPhone : cameraZ;
56
 
57
  // 2. Grab DOM
58
- const canvasId = 'canvas-' + instanceId;
59
  const progressDialog = document.getElementById('progress-dialog-' + instanceId);
60
  const progressIndicator = document.getElementById('progress-indicator-' + instanceId);
61
  const viewerContainer = document.getElementById('viewer-container-' + instanceId);
@@ -128,8 +129,19 @@ export async function initializeViewer(config, instanceId) {
128
  app.scene.exposure = 0.5;
129
  app.scene.toneMapping = pc.TONEMAP_ACES;
130
 
 
 
 
 
 
 
 
 
 
 
 
131
  window.addEventListener('resize', () => {
132
- if (app) app.resizeCanvas(canvas.clientWidth, canvas.clientHeight);
133
  });
134
  app.on('destroy', () => {
135
  window.removeEventListener('resize', resizeCanvas);
@@ -168,6 +180,7 @@ export async function initializeViewer(config, instanceId) {
168
  app.start();
169
  app.scene.envAtlas = assets.hdr.resource;
170
 
 
171
  modelEntity = new pc.Entity('model');
172
  modelEntity.addComponent('gsplat', { asset: assets.model });
173
  modelEntity.setLocalPosition(modelX, modelY, modelZ);
@@ -175,6 +188,7 @@ export async function initializeViewer(config, instanceId) {
175
  modelEntity.setLocalScale(modelScale, modelScale, modelScale);
176
  app.root.addChild(modelEntity);
177
 
 
178
  const dirLight = new pc.Entity('Cascaded Light');
179
  dirLight.addComponent('light', {
180
  type: 'directional',
@@ -192,12 +206,14 @@ export async function initializeViewer(config, instanceId) {
192
  shadowType: pc.SHADOW_PCSS_32F,
193
  shadowDistance: 1000
194
  });
195
- app.root.addChild(dirLight);
196
  dirLight.setLocalEulerAngles(0, 0, 0);
 
197
 
 
198
  const galleryEntity = assets.galerie.resource.instantiateRenderEntity();
199
  app.root.addChild(galleryEntity);
200
 
 
201
  cameraEntity = new pc.Entity('camera');
202
  cameraEntity.addComponent('camera', {
203
  clearColor: config.canvas_background
@@ -240,16 +256,21 @@ export async function initializeViewer(config, instanceId) {
240
  });
241
  app.root.addChild(cameraEntity);
242
 
 
243
  app.once('update', () => resetViewerCamera());
244
  app.on('update', dt => {
245
  if (cameraEntity) {
246
  const pos = cameraEntity.getPosition();
247
- if (pos.y < minY) cameraEntity.setPosition(pos.x, minY, pos.z);
 
 
248
  }
249
  });
250
 
 
251
  app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
252
 
 
253
  try {
254
  const tooltipsModule = await import('./tooltips.js');
255
  tooltipsModule.initializeTooltips({
@@ -322,10 +343,18 @@ export function resetViewerCamera() {
322
 
323
  export function cleanupViewer() {
324
  if (app) {
325
- try { app.destroy(); } catch {}
 
 
326
  app = null;
327
  }
328
  cameraEntity = null;
329
  modelEntity = null;
330
  viewerInitialized = false;
 
 
 
 
 
 
331
  }
 
8
  let cameraEntity = null;
9
  let modelEntity = null;
10
  let viewerInitialized = false;
11
+ let resizeObserver = null;
12
 
13
  let chosenCameraX, chosenCameraY, chosenCameraZ;
14
  let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minPivotY, minY;
 
27
  // 1. Read config
28
  plyUrl = config.ply_url;
29
  glbUrl = config.glb_url;
30
+ minZoom = parseFloat(config.minZoom || "1");
31
+ maxZoom = parseFloat(config.maxZoom || "20");
32
+ minAngle = parseFloat(config.minAngle || "-45");
33
+ maxAngle = parseFloat(config.maxAngle || "90");
34
+ minAzimuth = (config.minAzimuth !== undefined) ? parseFloat(config.minAzimuth) : -360;
35
+ maxAzimuth = (config.maxAzimuth !== undefined) ? parseFloat(config.maxAzimuth) : 360;
36
+ minPivotY = parseFloat(config.minPivotY || "0");
37
+ minY = (config.minY !== undefined) ? parseFloat(config.minY) : 0;
38
+
39
+ modelX = (config.modelX !== undefined) ? parseFloat(config.modelX) : 0;
40
+ modelY = (config.modelY !== undefined) ? parseFloat(config.modelY) : 0;
41
+ modelZ = (config.modelZ !== undefined) ? parseFloat(config.modelZ) : 0;
42
+ modelScale = (config.modelScale !== undefined) ? parseFloat(config.modelScale) : 1;
43
  modelRotationX = (config.modelRotationX !== undefined) ? parseFloat(config.modelRotationX) : 0;
44
  modelRotationY = (config.modelRotationY !== undefined) ? parseFloat(config.modelRotationY) : 0;
45
  modelRotationZ = (config.modelRotationZ !== undefined) ? parseFloat(config.modelRotationZ) : 0;
 
56
  chosenCameraZ = isMobile ? cameraZPhone : cameraZ;
57
 
58
  // 2. Grab DOM
59
+ const canvasId = 'canvas-' + instanceId;
60
  const progressDialog = document.getElementById('progress-dialog-' + instanceId);
61
  const progressIndicator = document.getElementById('progress-indicator-' + instanceId);
62
  const viewerContainer = document.getElementById('viewer-container-' + instanceId);
 
129
  app.scene.exposure = 0.5;
130
  app.scene.toneMapping = pc.TONEMAP_ACES;
131
 
132
+ // Attach ResizeObserver to keep canvas in sync with container size
133
+ resizeObserver = new ResizeObserver(entries => {
134
+ for (const entry of entries) {
135
+ const { width, height } = entry.contentRect;
136
+ if (app) {
137
+ app.resizeCanvas(width, height);
138
+ }
139
+ }
140
+ });
141
+ resizeObserver.observe(viewerContainer);
142
+
143
  window.addEventListener('resize', () => {
144
+ if (app) app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
145
  });
146
  app.on('destroy', () => {
147
  window.removeEventListener('resize', resizeCanvas);
 
180
  app.start();
181
  app.scene.envAtlas = assets.hdr.resource;
182
 
183
+ // Model entity
184
  modelEntity = new pc.Entity('model');
185
  modelEntity.addComponent('gsplat', { asset: assets.model });
186
  modelEntity.setLocalPosition(modelX, modelY, modelZ);
 
188
  modelEntity.setLocalScale(modelScale, modelScale, modelScale);
189
  app.root.addChild(modelEntity);
190
 
191
+ // Light
192
  const dirLight = new pc.Entity('Cascaded Light');
193
  dirLight.addComponent('light', {
194
  type: 'directional',
 
206
  shadowType: pc.SHADOW_PCSS_32F,
207
  shadowDistance: 1000
208
  });
 
209
  dirLight.setLocalEulerAngles(0, 0, 0);
210
+ app.root.addChild(dirLight);
211
 
212
+ // Gallery GLB
213
  const galleryEntity = assets.galerie.resource.instantiateRenderEntity();
214
  app.root.addChild(galleryEntity);
215
 
216
+ // Camera setup
217
  cameraEntity = new pc.Entity('camera');
218
  cameraEntity.addComponent('camera', {
219
  clearColor: config.canvas_background
 
256
  });
257
  app.root.addChild(cameraEntity);
258
 
259
+ // Reset & constrain updates
260
  app.once('update', () => resetViewerCamera());
261
  app.on('update', dt => {
262
  if (cameraEntity) {
263
  const pos = cameraEntity.getPosition();
264
+ if (pos.y < minY) {
265
+ cameraEntity.setPosition(pos.x, minY, pos.z);
266
+ }
267
  }
268
  });
269
 
270
+ // Final resize
271
  app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
272
 
273
+ // Tooltips
274
  try {
275
  const tooltipsModule = await import('./tooltips.js');
276
  tooltipsModule.initializeTooltips({
 
343
 
344
  export function cleanupViewer() {
345
  if (app) {
346
+ try {
347
+ app.destroy();
348
+ } catch {}
349
  app = null;
350
  }
351
  cameraEntity = null;
352
  modelEntity = null;
353
  viewerInitialized = false;
354
+
355
+ // Disconnect the ResizeObserver to avoid leaks
356
+ if (resizeObserver) {
357
+ resizeObserver.disconnect();
358
+ resizeObserver = null;
359
+ }
360
  }