MikaFil commited on
Commit
e0e7fb0
·
verified ·
1 Parent(s): cb4ead5

Update viewer_2.js

Browse files
Files changed (1) hide show
  1. viewer_2.js +280 -288
viewer_2.js CHANGED
@@ -1,6 +1,46 @@
1
- // viewer_2.js
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- let pc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  export let app = null;
5
  let cameraEntity = null;
6
  let glbEntity = null;
@@ -14,7 +54,7 @@ let glbUrl;
14
 
15
  let matTransparent = null;
16
 
17
- // Utility: Recursive entity traversal
18
  function traverse(entity, callback) {
19
  callback(entity);
20
  if (entity.children) {
@@ -23,313 +63,265 @@ function traverse(entity, callback) {
23
  }
24
 
25
  export async function initializeViewer(config, instanceId) {
26
- if (viewerInitialized) {
27
- console.log("Viewer already initialized.");
28
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
- try {
31
- console.log("Initializing viewer for instance:", instanceId, config);
32
-
33
- glbUrl = config.glb_url;
34
- minZoom = 0.2;
35
- maxZoom = 2;
36
- minAngle = -Infinity;
37
- maxAngle = Infinity;
38
- minAzimuth = -Infinity;
39
- maxAzimuth = Infinity;
40
- minPivotY = 0;
41
- minY = -10;
42
-
43
- modelX = 0;
44
- modelY = 0;
45
- modelZ = 0;
46
- modelScale = 1;
47
- modelRotationX = 0;
48
- modelRotationY = 0;
49
- modelRotationZ = 0;
50
-
51
- chosenCameraX = 0;
52
- chosenCameraY = 0;
53
- chosenCameraZ = 1;
54
-
55
- // ---- DOM Elements ----
56
- const canvasId = 'canvas-' + instanceId;
57
- const progressDialog = document.getElementById('progress-dialog-' + instanceId);
58
- const progressIndicator = document.getElementById('progress-indicator-' + instanceId);
59
- const viewerContainer = document.getElementById('viewer-container-' + instanceId);
60
-
61
- if (!viewerContainer) {
62
- console.error("viewerContainer not found!", 'viewer-container-' + instanceId);
63
- return;
64
- }
65
- if (!progressDialog) {
66
- console.error("progressDialog not found!", 'progress-dialog-' + instanceId);
67
- }
68
-
69
- let oldCanvas = document.getElementById(canvasId);
70
- if (oldCanvas) {
71
- oldCanvas.remove();
72
- console.log("Old canvas removed");
73
- }
74
 
75
- const canvas = document.createElement('canvas');
76
- canvas.id = canvasId;
77
- canvas.className = 'ply-canvas';
78
- canvas.style.width = "100%";
79
- canvas.style.height = "100%";
80
- canvas.setAttribute('tabindex', '0');
81
- viewerContainer.insertBefore(canvas, progressDialog);
82
-
83
- canvas.style.touchAction = "none";
84
- canvas.style.webkitTouchCallout = "none";
85
- canvas.addEventListener('gesturestart', e => e.preventDefault());
86
- canvas.addEventListener('gesturechange', e => e.preventDefault());
87
- canvas.addEventListener('gestureend', e => e.preventDefault());
88
- canvas.addEventListener('dblclick', e => e.preventDefault());
89
- canvas.addEventListener('touchstart', e => { if (e.touches.length > 1) e.preventDefault(); }, { passive: false });
90
- canvas.addEventListener('wheel', (e) => { e.preventDefault(); }, { passive: false });
91
-
92
- if (progressDialog) progressDialog.style.display = 'block';
93
-
94
- // ---- Load PlayCanvas ----
95
- if (!pc) {
96
- try {
97
- pc = await import("https://esm.run/playcanvas");
98
- window.pc = pc;
99
- console.log("PlayCanvas loaded:", pc.version || pc);
100
- } catch (err) {
101
- console.error("Failed to import PlayCanvas:", err);
102
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  }
104
- }
105
-
106
- // ---- Create Graphics Device ----
107
- let device;
108
- try {
109
- device = await pc.createGraphicsDevice(canvas, {
110
- deviceTypes: ["webgl2", "webgl1"],
111
- glslangUrl: "https://playcanvas.vercel.app/static/lib/glslang/glslang.js",
112
- twgslUrl: "https://playcanvas.vercel.app/static/lib/twgsl/twgsl.js",
113
- antialias: false
114
- });
115
- device.maxPixelRatio = Math.min(window.devicePixelRatio, 2);
116
- console.log("Graphics device created:", device);
117
- } catch (err) {
118
- console.error("Failed to create graphics device:", err);
119
- return;
120
- }
121
-
122
- // ---- Create AppOptions ----
123
- const opts = new pc.AppOptions();
124
- opts.graphicsDevice = device;
125
- opts.mouse = new pc.Mouse(canvas);
126
- opts.touch = new pc.TouchDevice(canvas);
127
-
128
- opts.componentSystems = [
129
- pc.RenderComponentSystem,
130
- pc.CameraComponentSystem,
131
- pc.LightComponentSystem,
132
- pc.ScriptComponentSystem,
133
- pc.GSplatComponentSystem,
134
- pc.CollisionComponentSystem,
135
- pc.RigidbodyComponentSystem
136
- ];
137
- opts.resourceHandlers = [
138
- pc.TextureHandler,
139
- pc.ContainerHandler,
140
- pc.ScriptHandler,
141
- pc.GSplatHandler
142
- ];
143
-
144
- // ---- Initialize AppBase ----
145
- try {
146
- app = new pc.AppBase(canvas);
147
- await app.init(opts);
148
- console.log("AppBase initialized");
149
- } catch (err) {
150
- console.error("Failed to initialize AppBase:", err);
151
- return;
152
- }
153
 
154
- app.setCanvasFillMode(pc.FILLMODE_NONE);
155
- app.setCanvasResolution(pc.RESOLUTION_AUTO);
156
 
157
- // ---- Resize observer ----
158
- try {
159
- resizeObserver = new ResizeObserver(entries => {
160
- entries.forEach(entry => {
161
- app.resizeCanvas(entry.contentRect.width, entry.contentRect.height);
162
- });
163
- });
164
- resizeObserver.observe(viewerContainer);
165
- window.addEventListener('resize', () => app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight));
166
- app.on('destroy', () => resizeObserver.disconnect());
167
- console.log("Resize observer set");
168
- } catch (err) {
169
- console.error("Resize observer error:", err);
170
- }
171
 
172
- // ---- ASSET LOADING ----
173
- const assets = {
174
- orbit: new pc.Asset('script', 'script', { url: "https://mikafil-viewer-glb.static.hf.space/orbit-camera.js" }),
175
- glb: new pc.Asset('glb', 'container', { url: glbUrl }),
176
- hdr: new pc.Asset(
177
- 'hdr-env-atlas', 'texture',
178
- { url: 'https://playcanvas.vercel.app/static/assets/cubemaps/helipad-env-atlas.png' },
179
- { type: pc.TEXTURETYPE_RGBP, mipmaps: false }
180
- ),
181
- ao_map: new pc.Asset('color', 'texture', { url: 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/emit_map_2k.png' }),
182
- op_map: new pc.Asset('color', 'texture', { url: 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/op_map_2k.png' }),
183
- thickness_map: new pc.Asset('color', 'texture', { url: 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/thickness_map_2k.png' })
184
- };
185
-
186
- for (const key in assets) app.assets.add(assets[key]);
187
- console.log("Assets added to app.assets");
188
-
189
- // ---- ASSET LOADER ----
190
- const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
191
-
192
- loader.load(() => {
193
- try {
194
- app.start();
195
- if (progressDialog) progressDialog.style.display = 'none';
196
- console.log("Assets loaded, app started");
197
-
198
- app.scene.envAtlas = assets.hdr.resource;
199
- app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, -90, 0);
200
- app.scene.skyboxIntensity = 4;
201
- app.scene.skyboxMip = 0;
202
-
203
- // Reorder depth layer
204
- const depthLayer = app.scene.layers.getLayerById(pc.LAYERID_DEPTH);
205
- app.scene.layers.remove(depthLayer);
206
- app.scene.layers.insertOpaque(depthLayer, 2);
207
-
208
- // Add GLB entity
209
- glbEntity = assets.glb.resource.instantiateRenderEntity();
210
- app.root.addChild(glbEntity);
211
- console.log("GLB entity added:", glbEntity);
212
-
213
- // Prepare transparent material
214
- const ao = assets.ao_map.resource;
215
- matTransparent = new pc.StandardMaterial();
216
- matTransparent.blendType = pc.BLEND_NORMAL;
217
- matTransparent.diffuse = new pc.Color(1, 1, 1);
218
- matTransparent.specular = new pc.Color(0.01, 0.01, 0.01);
219
- matTransparent.gloss = 1;
220
- matTransparent.metalness = 0;
221
- matTransparent.useMetalness = true;
222
- matTransparent.useDynamicRefraction = true;
223
- matTransparent.depthWrite = true;
224
- matTransparent.refraction = 0.8;
225
- matTransparent.refractionIndex = 1;
226
- matTransparent.thickness = 0.02;
227
- // matTransparent.thicknessMap = thickness; // Add as needed
228
- // matTransparent.opacityMap = op; // Add as needed
229
- matTransparent.opacity = 0.97;
230
- matTransparent.emissive = new pc.Color(1, 1, 1);
231
- matTransparent.emissiveMap = ao;
232
- matTransparent.emissiveIntensity = 0.1;
233
- matTransparent.update();
234
-
235
- traverse(glbEntity, node => {
236
- if (node.render && node.render.meshInstances) {
237
- for (let mi of node.render.meshInstances) {
238
- mi.material = matTransparent;
239
- }
240
- }
241
- });
242
 
243
- glbEntity.setPosition(modelX, modelY, modelZ);
244
- glbEntity.setLocalScale(modelScale, modelScale, modelScale);
245
- glbEntity.setLocalEulerAngles(modelRotationX, modelRotationY, modelRotationZ);
246
-
247
- // Camera setup
248
- cameraEntity = new pc.Entity('camera');
249
- cameraEntity.addComponent('camera');
250
- cameraEntity.setPosition(chosenCameraX, chosenCameraY, chosenCameraZ);
251
- cameraEntity.lookAt(glbEntity.getPosition());
252
- cameraEntity.addComponent('script');
253
- cameraEntity.camera.requestSceneColorMap(true);
254
-
255
- cameraEntity.script.create('orbitCamera', {
256
- attributes: {
257
- focusEntity: glbEntity,
258
- inertiaFactor: 0.2,
259
- distanceMax: maxZoom,
260
- distanceMin: minZoom,
261
- pitchAngleMax: maxAngle,
262
- pitchAngleMin: minAngle,
263
- yawAngleMax: maxAzimuth,
264
- yawAngleMin: minAzimuth,
265
- minY: minY,
266
- frameOnStart: false
267
- }
268
- });
269
- cameraEntity.script.create('orbitCameraInputMouse');
270
- cameraEntity.script.create('orbitCameraInputTouch');
271
- app.root.addChild(cameraEntity);
272
 
273
- app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
274
 
275
- app.once('update', () => {
276
- console.log("First update: calling resetViewerCamera()");
277
- resetViewerCamera();
 
 
 
 
 
 
 
 
 
 
 
278
  });
279
-
280
- // Tooltips support
281
- try {
282
- if (config.tooltips_url) {
283
- import('./tooltips.js').then(tooltipsModule => {
284
- tooltipsModule.initializeTooltips({
285
- app,
286
- cameraEntity,
287
- glbEntity,
288
- tooltipsUrl: config.tooltips_url,
289
- defaultVisible: !!config.showTooltipsDefault,
290
- moveDuration: config.tooltipMoveDuration || 0.6
291
- });
292
- console.log("Tooltips loaded");
293
- }).catch(e => {
294
- console.error("Tooltips import error:", e);
295
- });
296
- }
297
- } catch (e) {
298
- console.error("Tooltips setup error:", e);
299
- }
300
-
301
- viewerInitialized = true;
302
- console.log("Viewer fully initialized");
303
- } catch (e) {
304
- console.error("Error during asset loader callback:", e);
305
  }
306
- });
 
 
 
 
 
307
 
308
- } catch (e) {
309
- console.error("Error in initializeViewer (outer):", e);
310
- }
311
  }
312
 
313
  export function resetViewerCamera() {
 
314
  try {
315
- if (!cameraEntity || !glbEntity || !app) {
316
- console.warn("resetViewerCamera: missing cameraEntity, glbEntity, or app", { cameraEntity, glbEntity, app });
317
- return;
318
- }
319
  const orbitCam = cameraEntity.script.orbitCamera;
320
- if (!orbitCam) {
321
- console.warn("resetViewerCamera: orbitCamera script missing");
322
- return;
323
- }
324
 
325
  const modelPos = glbEntity.getPosition();
326
- console.log("Resetting camera. Model position:", modelPos);
327
  const tempEnt = new pc.Entity();
328
  tempEnt.setPosition(chosenCameraX, chosenCameraY, chosenCameraZ);
329
  tempEnt.lookAt(modelPos);
330
 
331
  const dist = new pc.Vec3().sub2(
332
- new pc.Vec3(chosenCameraX, chosenCameraY, chosenCameraZ),
333
  modelPos
334
  ).length();
335
 
@@ -358,8 +350,8 @@ export function resetViewerCamera() {
358
  if (orbitCam._updatePosition) orbitCam._updatePosition();
359
 
360
  tempEnt.destroy();
361
- console.log("Camera reset complete.");
362
  } catch (e) {
363
- console.error("resetViewerCamera error:", e);
364
  }
365
  }
 
 
1
+ /*(function(){
2
+ let logDiv = document.createElement('div');
3
+ logDiv.style.position = 'fixed';
4
+ logDiv.style.bottom = '0';
5
+ logDiv.style.left = '0';
6
+ logDiv.style.maxHeight = '40vh';
7
+ logDiv.style.width = '100vw';
8
+ logDiv.style.overflow = 'auto';
9
+ logDiv.style.background = 'rgba(0,0,0,0.85)';
10
+ logDiv.style.color = '#fff';
11
+ logDiv.style.fontSize = '12px';
12
+ logDiv.style.zIndex = '99999';
13
+ logDiv.style.pointerEvents = 'none';
14
+ logDiv.style.fontFamily = 'monospace';
15
+ document.body.appendChild(logDiv);
16
+
17
+ function printLog(msg, color) {
18
+ let el = document.createElement('div');
19
+ el.style.color = color || '#fff';
20
+ el.textContent = msg;
21
+ logDiv.appendChild(el);
22
+ logDiv.scrollTop = logDiv.scrollHeight;
23
+ }
24
 
25
+ let origLog = console.log;
26
+ console.log = function(...args){
27
+ printLog('[LOG] ' + args.map(String).join(' '), '#0f0');
28
+ origLog.apply(console, args);
29
+ };
30
+ let origErr = console.error;
31
+ console.error = function(...args){
32
+ printLog('[ERR] ' + args.map(String).join(' '), '#f55');
33
+ origErr.apply(console, args);
34
+ };
35
+ window.onerror = function(msg, src, lineno, colno, error){
36
+ printLog('[ERR] ' + msg + ' at ' + src + ':' + lineno, '#f55');
37
+ };
38
+ })();*/
39
+
40
+ // viewer.js
41
+ // ==============================
42
+
43
+ let pc;
44
  export let app = null;
45
  let cameraEntity = null;
46
  let glbEntity = null;
 
54
 
55
  let matTransparent = null;
56
 
57
+ // RECURSIVE ENTITY TRAVERSAL
58
  function traverse(entity, callback) {
59
  callback(entity);
60
  if (entity.children) {
 
63
  }
64
 
65
  export async function initializeViewer(config, instanceId) {
66
+ if (viewerInitialized) return;
67
+
68
+ glbUrl = config.glb_url;
69
+ minZoom = 0.2;
70
+ maxZoom = 2;
71
+ minAngle = -Infinity;
72
+ maxAngle = Infinity;
73
+ minAzimuth = -Infinity;
74
+ maxAzimuth = Infinity;
75
+ minPivotY = 0;
76
+ minY = -10;
77
+
78
+ modelX = 0;
79
+ modelY = 0;
80
+ modelZ = 0;
81
+ modelScale = 1;
82
+ modelRotationX = 0;
83
+ modelRotationY = 0;
84
+ modelRotationZ = 0;
85
+
86
+ chosenCameraX = 0;
87
+ chosenCameraY = 0;
88
+ chosenCameraZ = 1;
89
+
90
+ const canvasId = 'canvas-' + instanceId;
91
+ const progressDialog = document.getElementById('progress-dialog-' + instanceId);
92
+ const progressIndicator = document.getElementById('progress-indicator-' + instanceId);
93
+ const viewerContainer = document.getElementById('viewer-container-' + instanceId);
94
+
95
+ let oldCanvas = document.getElementById(canvasId);
96
+ if (oldCanvas) oldCanvas.remove();
97
+
98
+ const canvas = document.createElement('canvas');
99
+ canvas.id = canvasId;
100
+ canvas.className = 'ply-canvas';
101
+ canvas.style.width = "100%";
102
+ canvas.style.height = "100%";
103
+ canvas.setAttribute('tabindex', '0');
104
+ viewerContainer.insertBefore(canvas, progressDialog);
105
+
106
+ canvas.style.touchAction = "none";
107
+ canvas.style.webkitTouchCallout = "none";
108
+ canvas.addEventListener('gesturestart', e => e.preventDefault());
109
+ canvas.addEventListener('gesturechange', e => e.preventDefault());
110
+ canvas.addEventListener('gestureend', e => e.preventDefault());
111
+ canvas.addEventListener('dblclick', e => e.preventDefault());
112
+ canvas.addEventListener('touchstart', e => { if (e.touches.length > 1) e.preventDefault(); }, { passive: false });
113
+
114
+ // --- The following line attaches mouse wheel suppression to canvas only ---
115
+ canvas.addEventListener('wheel', (e) => {
116
+ e.preventDefault(); // Only block page scroll if mouse is over viewer
117
+ }, { passive: false });
118
+
119
+ progressDialog.style.display = 'block';
120
+
121
+ if (!pc) {
122
+ pc = await import("https://esm.run/playcanvas");
123
+ window.pc = pc;
124
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
+ // Create app first
127
+ const device = await pc.createGraphicsDevice(canvas, {
128
+ deviceTypes: ["webgl2", "webgl1"],
129
+ glslangUrl: "https://playcanvas.vercel.app/static/lib/glslang/glslang.js",
130
+ twgslUrl: "https://playcanvas.vercel.app/static/lib/twgsl/twgsl.js",
131
+ antialias: false
132
+ });
133
+ device.maxPixelRatio = Math.min(window.devicePixelRatio, 2);
134
+
135
+ const opts = new pc.AppOptions();
136
+ opts.graphicsDevice = device;
137
+ // Attach input only to canvas
138
+ opts.mouse = new pc.Mouse(canvas);
139
+ opts.touch = new pc.TouchDevice(canvas);
140
+ opts.componentSystems = [
141
+ pc.RenderComponentSystem,
142
+ pc.CameraComponentSystem,
143
+ pc.LightComponentSystem,
144
+ pc.ScriptComponentSystem,
145
+ pc.GSplatComponentSystem,
146
+ pc.CollisionComponentSystem,
147
+ pc.RigidbodyComponentSystem
148
+ ];
149
+ opts.resourceHandlers = [
150
+ pc.TextureHandler,
151
+ pc.ContainerHandler,
152
+ pc.ScriptHandler,
153
+ pc.GSplatHandler
154
+ ];
155
+
156
+
157
+ ///////// APP comme dans exemple ///////
158
+ ////////////////////////////////////////
159
+ app = new pc.Application(canvas, opts);
160
+ //app = new pc.AppBase(canvas);
161
+ //app.init(opts);
162
+
163
+ app.setCanvasFillMode(pc.FILLMODE_NONE);
164
+ app.setCanvasResolution(pc.RESOLUTION_AUTO);
165
+
166
+ resizeObserver = new ResizeObserver(entries => {
167
+ entries.forEach(entry => {
168
+ app.resizeCanvas(entry.contentRect.width, entry.contentRect.height);
169
+ });
170
+ });
171
+ resizeObserver.observe(viewerContainer);
172
+
173
+ window.addEventListener('resize', () => app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight));
174
+ app.on('destroy', () => resizeObserver.disconnect());
175
+
176
+ // Assets after app exists
177
+ const assets = {
178
+ orbit: new pc.Asset('script', 'script', { url: "https://mikafil-viewer-glb.static.hf.space/orbit-camera.js" }),
179
+ glb: new pc.Asset('glb', 'container', { url: glbUrl }),
180
+ hdr: new pc.Asset(
181
+ 'hdr-env-atlas', 'texture',
182
+ {url: 'https://playcanvas.vercel.app/static/assets/cubemaps/helipad-env-atlas.png'},
183
+ { type: pc.TEXTURETYPE_RGBP, mipmaps: false }
184
+ ),
185
+ ao_map: new pc.Asset('color', 'texture', { url: 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/emit_map_2k.png' }),
186
+ op_map: new pc.Asset('color', 'texture', { url: 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/op_map_2k.png' }),
187
+ thickness_map: new pc.Asset('color', 'texture', { url: 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/thickness_map_2k.png' })
188
+ };
189
+
190
+ for (const key in assets) app.assets.add(assets[key]);
191
+
192
+
193
+ const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
194
+ loader.load(() => {
195
+ app.start();
196
+ progressDialog.style.display = 'none';
197
+
198
+ app.scene.envAtlas = assets.hdr.resource;
199
+ app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, -90, 0);
200
+ app.scene.skyboxIntensity = 4;
201
+ app.scene.skyboxMip = 0;
202
+
203
+ // Reorder depth layer for transmission
204
+ const depthLayer = app.scene.layers.getLayerById(pc.LAYERID_DEPTH);
205
+ app.scene.layers.remove(depthLayer);
206
+ app.scene.layers.insertOpaque(depthLayer, 2);
207
+
208
+
209
+ // --- Add the GLB entity ---
210
+ glbEntity = assets.glb.resource.instantiateRenderEntity();
211
+ app.root.addChild(glbEntity);
212
+
213
+ // 2. Materials for main model & tube
214
+ const ao = assets.ao_map.resource;
215
+ //const op = assets.op_map.resource;
216
+ //const thickness = assets.thickness_map.resource;
217
+
218
+ // mat transparent
219
+ matTransparent = new pc.StandardMaterial();
220
+ matTransparent.blendType = pc.BLEND_NORMAL;
221
+ matTransparent.diffuse = new pc.Color(1, 1, 1);
222
+ matTransparent.specular = new pc.Color(0.01, 0.01, 0.01);
223
+ matTransparent.gloss = 1;
224
+ matTransparent.metalness = 0;
225
+ matTransparent.useMetalness = true;
226
+ matTransparent.useDynamicRefraction = true;
227
+ matTransparent.depthWrite = true;
228
+ matTransparent.refraction= 0.8;
229
+ matTransparent.refractionIndex = 1;
230
+ matTransparent.thickness = 0.02;
231
+ //matTransparent.thicknessMap = thickness;
232
+ //matTransparent.opacityMap = op;
233
+ //matTransparent.opacityMapChannel = "r";
234
+ matTransparent.opacity = 0.97;
235
+ matTransparent.emissive = new pc.Color(1, 1, 1);
236
+ matTransparent.emissiveMap = ao;
237
+ matTransparent.emissiveIntensity = 0.1;
238
+ matTransparent.update();
239
+
240
+ traverse(glbEntity, node => {
241
+ if (node.render && node.render.meshInstances) {
242
+ for (let mi of node.render.meshInstances) {
243
+ mi.material = matTransparent;
244
+ }
245
  }
246
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
 
 
248
 
249
+ glbEntity.setPosition(modelX, modelY, modelZ);
250
+ glbEntity.setLocalScale(modelScale, modelScale, modelScale);
251
+ glbEntity.setLocalEulerAngles(modelRotationX, modelRotationY, modelRotationZ);
 
 
 
 
 
 
 
 
 
 
 
252
 
253
+ cameraEntity = new pc.Entity('camera');
254
+ // PURE WHITE BACKGROUND
255
+ cameraEntity.addComponent('camera'); // White RGBA
256
+ cameraEntity.setPosition(chosenCameraX, chosenCameraY, chosenCameraZ);
257
+ cameraEntity.lookAt(glbEntity.getPosition());
258
+ cameraEntity.addComponent('script');
259
+
260
+ cameraEntity.camera.requestSceneColorMap(true);
261
+
262
+ // === MAIN FIX: Pass ALL relevant attributes including minY ===
263
+ cameraEntity.script.create('orbitCamera', {
264
+ attributes: {
265
+ focusEntity: glbEntity,
266
+ inertiaFactor: 0.2,
267
+ distanceMax: maxZoom,
268
+ distanceMin: minZoom,
269
+ pitchAngleMax: maxAngle,
270
+ pitchAngleMin: minAngle,
271
+ yawAngleMax: maxAzimuth,
272
+ yawAngleMin: minAzimuth,
273
+ minY: minY,
274
+ frameOnStart: false
275
+ }
276
+ });
277
+ cameraEntity.script.create('orbitCameraInputMouse');
278
+ cameraEntity.script.create('orbitCameraInputTouch');
279
+ app.root.addChild(cameraEntity);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
 
281
+ app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
 
283
+ app.once('update', () => resetViewerCamera());
284
 
285
+ // Tooltips supported if tooltips_url set
286
+ try {
287
+ if (config.tooltips_url) {
288
+ import('./tooltips.js').then(tooltipsModule => {
289
+ tooltipsModule.initializeTooltips({
290
+ app,
291
+ cameraEntity,
292
+ glbEntity,
293
+ tooltipsUrl: config.tooltips_url,
294
+ defaultVisible: !!config.showTooltipsDefault,
295
+ moveDuration: config.tooltipMoveDuration || 0.6
296
+ });
297
+ }).catch(e => {
298
+ // Tooltips optional: fail silently if missing
299
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  }
301
+ } catch (e) {
302
+ // Tooltips optional, fail silently
303
+ }
304
+
305
+ viewerInitialized = true;
306
+ });
307
 
 
 
 
308
  }
309
 
310
  export function resetViewerCamera() {
311
+ console.log(glbEntity.getPosition());
312
  try {
313
+ if (!cameraEntity || !glbEntity || !app) return;
 
 
 
314
  const orbitCam = cameraEntity.script.orbitCamera;
315
+ if (!orbitCam) return;
 
 
 
316
 
317
  const modelPos = glbEntity.getPosition();
318
+ console.log(modelPos);
319
  const tempEnt = new pc.Entity();
320
  tempEnt.setPosition(chosenCameraX, chosenCameraY, chosenCameraZ);
321
  tempEnt.lookAt(modelPos);
322
 
323
  const dist = new pc.Vec3().sub2(
324
+ new pc.Vec3(chosenCamearaX, chosenCameraY, chosenCameraZ),
325
  modelPos
326
  ).length();
327
 
 
350
  if (orbitCam._updatePosition) orbitCam._updatePosition();
351
 
352
  tempEnt.destroy();
 
353
  } catch (e) {
354
+ // Silent fail
355
  }
356
  }
357
+