MikaFil commited on
Commit
75ec593
·
verified ·
1 Parent(s): 27b1d7a

Update viewer.js

Browse files
Files changed (1) hide show
  1. viewer.js +46 -18
viewer.js CHANGED
@@ -1,5 +1,4 @@
1
  // viewer.js
2
- // ==============================
3
 
4
  let pc; // will hold the PlayCanvas module once imported
5
  export let app = null;
@@ -13,15 +12,20 @@ let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minPivotY, min
13
  let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
14
  let plyUrl, glbUrl;
15
 
 
 
 
 
 
 
 
 
16
  /**
17
  * initializeViewer(config, instanceId)
18
  */
19
  export async function initializeViewer(config, instanceId) {
20
  if (viewerInitialized) return;
21
 
22
- const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
23
- const isMobile = isIOS || /Android/i.test(navigator.userAgent);
24
-
25
  // 1. Read config
26
  plyUrl = config.ply_url;
27
  glbUrl = config.glb_url;
@@ -49,9 +53,10 @@ export async function initializeViewer(config, instanceId) {
49
  const cameraYPhone = (config.cameraYPhone !== undefined) ? parseFloat(config.cameraYPhone) : cameraY;
50
  const cameraZPhone = (config.cameraZPhone !== undefined) ? parseFloat(config.cameraZPhone) : (cameraZ * 1.5);
51
 
52
- chosenCameraX = isMobile ? cameraXPhone : cameraX;
53
- chosenCameraY = isMobile ? cameraYPhone : cameraY;
54
- chosenCameraZ = isMobile ? cameraZPhone : cameraZ;
 
55
 
56
  // 2. Grab DOM
57
  const canvasId = 'canvas-' + instanceId;
@@ -89,16 +94,21 @@ export async function initializeViewer(config, instanceId) {
89
  if (!pc) {
90
  pc = await import("https://esm.run/playcanvas");
91
  window.pc = pc;
 
92
  }
93
 
94
  try {
95
  // 6. Setup device & app
 
96
  const device = await pc.createGraphicsDevice(canvas, {
97
  deviceTypes: ["webgl2"],
98
  glslangUrl: "https://playcanvas.vercel.app/static/lib/glslang/glslang.js",
99
  twgslUrl: "https://playcanvas.vercel.app/static/lib/twgsl/twgsl.js",
100
- antialias: false
 
 
101
  });
 
102
  device.maxPixelRatio = Math.min(window.devicePixelRatio, 2);
103
 
104
  const opts = new pc.AppOptions();
@@ -124,8 +134,8 @@ export async function initializeViewer(config, instanceId) {
124
  app = new pc.Application(canvas, opts);
125
  app.setCanvasFillMode(pc.FILLMODE_NONE);
126
  app.setCanvasResolution(pc.RESOLUTION_AUTO);
127
- //app.scene.exposure = 0.5;
128
- //app.scene.toneMapping = pc.TONEMAP_ACES;
129
 
130
  // Attach ResizeObserver to keep canvas in sync with container size
131
  resizeObserver = new ResizeObserver(entries => {
@@ -157,9 +167,12 @@ export async function initializeViewer(config, instanceId) {
157
 
158
  const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
159
  let lastProg = 0;
160
- assets.model.on('load', () => progressDialog.style.display = 'none');
 
 
 
161
  assets.model.on('error', err => {
162
- console.error("Error loading PLY file:", err);
163
  progressDialog.innerHTML = <p style="color: red">Error loading model: ${err}</p>;
164
  });
165
 
@@ -175,6 +188,7 @@ export async function initializeViewer(config, instanceId) {
175
  }, 100);
176
 
177
  loader.load(async () => {
 
178
  app.start();
179
  app.scene.envAtlas = assets.hdr.resource;
180
 
@@ -185,6 +199,7 @@ export async function initializeViewer(config, instanceId) {
185
  modelEntity.setLocalEulerAngles(modelRotationX, modelRotationY, modelRotationZ);
186
  modelEntity.setLocalScale(modelScale, modelScale, modelScale);
187
  app.root.addChild(modelEntity);
 
188
 
189
  // Light
190
  const dirLight = new pc.Entity('Cascaded Light');
@@ -208,8 +223,11 @@ export async function initializeViewer(config, instanceId) {
208
  app.root.addChild(dirLight);
209
 
210
  // Gallery GLB
211
- const galleryEntity = assets.galerie.resource.instantiateRenderEntity();
212
- app.root.addChild(galleryEntity);
 
 
 
213
 
214
  // Camera setup
215
  cameraEntity = new pc.Entity('camera');
@@ -217,7 +235,6 @@ export async function initializeViewer(config, instanceId) {
217
  clearColor: config.canvas_background
218
  ? parseInt(config.canvas_background.substr(1, 2), 16) / 255
219
  : 0,
220
- //toneMapping: pc.TONEMAP_ACES
221
  });
222
  cameraEntity.setPosition(chosenCameraX, chosenCameraY, chosenCameraZ);
223
  cameraEntity.lookAt(modelEntity.getPosition());
@@ -239,8 +256,8 @@ export async function initializeViewer(config, instanceId) {
239
  });
240
  cameraEntity.script.create('orbitCameraInputMouse', {
241
  attributes: {
242
- orbitSensitivity: isMobile ? 0.6 : 0.3,
243
- distanceSensitivity: isMobile ? 0.5 : 0.4
244
  }
245
  });
246
  if (cameraEntity.script.orbitCameraInputMouse) {
@@ -253,9 +270,13 @@ export async function initializeViewer(config, instanceId) {
253
  }
254
  });
255
  app.root.addChild(cameraEntity);
 
256
 
257
  // Reset & constrain updates
258
- app.once('update', () => resetViewerCamera());
 
 
 
259
  app.on('update', dt => {
260
  if (cameraEntity) {
261
  const pos = cameraEntity.getPosition();
@@ -263,6 +284,11 @@ export async function initializeViewer(config, instanceId) {
263
  cameraEntity.setPosition(pos.x, minY, pos.z);
264
  }
265
  }
 
 
 
 
 
266
  });
267
 
268
  // Final resize
@@ -285,9 +311,11 @@ export async function initializeViewer(config, instanceId) {
285
 
286
  progressDialog.style.display = 'none';
287
  viewerInitialized = true;
 
288
  });
289
 
290
  } catch (error) {
 
291
  console.error("Error initializing PlayCanvas viewer:", error);
292
  progressDialog.innerHTML = <p style="color: red">Error loading viewer: ${error.message}</p>;
293
  }
 
1
  // viewer.js
 
2
 
3
  let pc; // will hold the PlayCanvas module once imported
4
  export let app = null;
 
12
  let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
13
  let plyUrl, glbUrl;
14
 
15
+ // iOS & Safari detection
16
+ function isIOS() {
17
+ return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
18
+ }
19
+ function isSafari() {
20
+ return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
21
+ }
22
+
23
  /**
24
  * initializeViewer(config, instanceId)
25
  */
26
  export async function initializeViewer(config, instanceId) {
27
  if (viewerInitialized) return;
28
 
 
 
 
29
  // 1. Read config
30
  plyUrl = config.ply_url;
31
  glbUrl = config.glb_url;
 
53
  const cameraYPhone = (config.cameraYPhone !== undefined) ? parseFloat(config.cameraYPhone) : cameraY;
54
  const cameraZPhone = (config.cameraZPhone !== undefined) ? parseFloat(config.cameraZPhone) : (cameraZ * 1.5);
55
 
56
+ const mobile = isIOS() || /Android/i.test(navigator.userAgent);
57
+ chosenCameraX = mobile ? cameraXPhone : cameraX;
58
+ chosenCameraY = mobile ? cameraYPhone : cameraY;
59
+ chosenCameraZ = mobile ? cameraZPhone : cameraZ;
60
 
61
  // 2. Grab DOM
62
  const canvasId = 'canvas-' + instanceId;
 
94
  if (!pc) {
95
  pc = await import("https://esm.run/playcanvas");
96
  window.pc = pc;
97
+ alert('[viewer.js] PlayCanvas module loaded.');
98
  }
99
 
100
  try {
101
  // 6. Setup device & app
102
+ alert('[viewer.js] Creating graphics device...');
103
  const device = await pc.createGraphicsDevice(canvas, {
104
  deviceTypes: ["webgl2"],
105
  glslangUrl: "https://playcanvas.vercel.app/static/lib/glslang/glslang.js",
106
  twgslUrl: "https://playcanvas.vercel.app/static/lib/twgsl/twgsl.js",
107
+ antialias: false,
108
+ preserveDrawingBuffer: isIOS() || isSafari() ? true : false,
109
+ alpha: false
110
  });
111
+ alert('[viewer.js] Graphics device created!');
112
  device.maxPixelRatio = Math.min(window.devicePixelRatio, 2);
113
 
114
  const opts = new pc.AppOptions();
 
134
  app = new pc.Application(canvas, opts);
135
  app.setCanvasFillMode(pc.FILLMODE_NONE);
136
  app.setCanvasResolution(pc.RESOLUTION_AUTO);
137
+
138
+ alert('[viewer.js] PlayCanvas application created!');
139
 
140
  // Attach ResizeObserver to keep canvas in sync with container size
141
  resizeObserver = new ResizeObserver(entries => {
 
167
 
168
  const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
169
  let lastProg = 0;
170
+ assets.model.on('load', () => {
171
+ progressDialog.style.display = 'none';
172
+ alert('[viewer.js] PLY/GSplat asset loaded!');
173
+ });
174
  assets.model.on('error', err => {
175
+ alert('[viewer.js] Error loading model: ' + err);
176
  progressDialog.innerHTML = <p style="color: red">Error loading model: ${err}</p>;
177
  });
178
 
 
188
  }, 100);
189
 
190
  loader.load(async () => {
191
+ alert('[viewer.js] All assets loaded; starting app.');
192
  app.start();
193
  app.scene.envAtlas = assets.hdr.resource;
194
 
 
199
  modelEntity.setLocalEulerAngles(modelRotationX, modelRotationY, modelRotationZ);
200
  modelEntity.setLocalScale(modelScale, modelScale, modelScale);
201
  app.root.addChild(modelEntity);
202
+ alert('[viewer.js] Model entity added to scene!');
203
 
204
  // Light
205
  const dirLight = new pc.Entity('Cascaded Light');
 
223
  app.root.addChild(dirLight);
224
 
225
  // Gallery GLB
226
+ if (assets.galerie && assets.galerie.resource) {
227
+ const galleryEntity = assets.galerie.resource.instantiateRenderEntity();
228
+ app.root.addChild(galleryEntity);
229
+ alert('[viewer.js] GLB entity added to scene!');
230
+ }
231
 
232
  // Camera setup
233
  cameraEntity = new pc.Entity('camera');
 
235
  clearColor: config.canvas_background
236
  ? parseInt(config.canvas_background.substr(1, 2), 16) / 255
237
  : 0,
 
238
  });
239
  cameraEntity.setPosition(chosenCameraX, chosenCameraY, chosenCameraZ);
240
  cameraEntity.lookAt(modelEntity.getPosition());
 
256
  });
257
  cameraEntity.script.create('orbitCameraInputMouse', {
258
  attributes: {
259
+ orbitSensitivity: mobile ? 0.6 : 0.3,
260
+ distanceSensitivity: mobile ? 0.5 : 0.4
261
  }
262
  });
263
  if (cameraEntity.script.orbitCameraInputMouse) {
 
270
  }
271
  });
272
  app.root.addChild(cameraEntity);
273
+ alert('[viewer.js] Camera entity added to scene!');
274
 
275
  // Reset & constrain updates
276
+ app.once('update', () => {
277
+ alert('[viewer.js] First app update! Resetting camera.');
278
+ resetViewerCamera();
279
+ });
280
  app.on('update', dt => {
281
  if (cameraEntity) {
282
  const pos = cameraEntity.getPosition();
 
284
  cameraEntity.setPosition(pos.x, minY, pos.z);
285
  }
286
  }
287
+ // Diagnostics: Only show once
288
+ if (!window._pcFirstUpdate) {
289
+ window._pcFirstUpdate = true;
290
+ alert('[viewer.js] Entered update/render loop!');
291
+ }
292
  });
293
 
294
  // Final resize
 
311
 
312
  progressDialog.style.display = 'none';
313
  viewerInitialized = true;
314
+ alert('[viewer.js] Viewer fully initialized and running!');
315
  });
316
 
317
  } catch (error) {
318
+ alert("[viewer.js] Error initializing PlayCanvas viewer: " + error.message);
319
  console.error("Error initializing PlayCanvas viewer:", error);
320
  progressDialog.innerHTML = <p style="color: red">Error loading viewer: ${error.message}</p>;
321
  }