zincjs 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +27 -22
  2. package/build/zinc.js +2 -2
  3. package/build/zinc.js.map +1 -1
  4. package/package.json +4 -1
  5. package/src/controls.js +1332 -1241
  6. package/src/geometryCSG.js +111 -115
  7. package/src/glyphsetCSG.js +51 -55
  8. package/src/loaders/GLTFToZincJSLoader.js +31 -33
  9. package/src/loaders/JSONLoader.js +339 -449
  10. package/src/loaders/OBJLoader.js +654 -851
  11. package/src/loaders/STLLoader.js +271 -329
  12. package/src/loaders/niftiReader.js +90 -59
  13. package/src/loaders/primitivesLoader.js +55 -52
  14. package/src/minimap.js +63 -43
  15. package/src/primitives/geometry.js +40 -44
  16. package/src/primitives/glyph.js +16 -19
  17. package/src/primitives/glyphset.js +229 -185
  18. package/src/primitives/label.js +29 -31
  19. package/src/primitives/lines.js +20 -20
  20. package/src/primitives/lines2.js +33 -39
  21. package/src/primitives/lod.js +43 -43
  22. package/src/primitives/marker.js +31 -32
  23. package/src/primitives/markerCluster.js +32 -35
  24. package/src/primitives/pointset.js +86 -83
  25. package/src/primitives/texturePrimitive.js +9 -10
  26. package/src/primitives/textureSlides.js +84 -97
  27. package/src/primitives/textureVolume.js +46 -49
  28. package/src/primitives/tubeLines.js +108 -108
  29. package/src/primitives/zincObject.js +176 -184
  30. package/src/region.js +145 -155
  31. package/src/renderRequests.js +3 -3
  32. package/src/renderer.js +649 -629
  33. package/src/scene.js +502 -430
  34. package/src/sceneExporter.js +22 -17
  35. package/src/sceneLoader.js +542 -296
  36. package/src/shaders/rgbVolumeRender.js +11 -18
  37. package/src/shaders/textureArray.js +5 -12
  38. package/src/shaders/textureSlide.js +10 -17
  39. package/src/shaders/volumeRender.js +11 -18
  40. package/src/shaders/volumeRender_old.js +11 -18
  41. package/src/shaders/volumeTexture.js +7 -14
  42. package/src/textSprite.js +23 -19
  43. package/src/texture/texture.js +14 -15
  44. package/src/texture/textureArray.js +14 -16
  45. package/src/three/InstancedPoints.js +2 -9
  46. package/src/three/Loader.js +334 -315
  47. package/src/three/line/Line.js +165 -215
  48. package/src/three/line/LineSegments.js +40 -55
  49. package/src/three/line/LineSegments2.js +322 -366
  50. package/src/three/line/LineSegmentsGeometry.js +239 -280
  51. package/src/three-js-csg.js +260 -252
  52. package/src/tsl/glyphRenderMaterial.js +12 -3
  53. package/src/tsl/glyphTransform.js +51 -29
  54. package/src/tsl/textureSlides.js +23 -24
  55. package/src/utilities.js +309 -371
  56. package/src/videoHandler.js +76 -83
  57. package/src/workers/geometryCSG.worker.js +33 -36
  58. package/src/workers/geometryCSGInternal.js +39 -44
  59. package/src/zinc.js +4 -7
  60. package/vite.config.js +7 -7
package/src/renderer.js CHANGED
@@ -17,139 +17,136 @@ import { setGlyphComputeSupported } from './tsl/glyphTransform';
17
17
  * @return {Renderer}
18
18
  */
19
19
  const Renderer = function (containerIn) {
20
+ let container = containerIn;
20
21
 
21
- let container = containerIn;
22
+ const stats = 0;
22
23
 
23
- const stats = 0;
24
+ let renderer = undefined;
25
+ let currentScene = undefined;
24
26
 
25
- let renderer = undefined;
26
- let currentScene = undefined;
27
-
28
- //myGezincGeometriestains a tuple of the threejs mesh, timeEnabled, morphColour flag, unique id and morph
29
- const clock = new THREE.Timer();
30
- this.playAnimation = true;
27
+ //myGezincGeometriestains a tuple of the threejs mesh, timeEnabled, morphColour flag, unique id and morph
28
+ const clock = new THREE.Timer();
29
+ this.playAnimation = true;
31
30
  /* default animation update rate, rate is 1000 and duration
32
31
  is default to 6000, 6s to finish a full animation */
33
- let playRate = 1000;
34
- let preRenderCallbackFunctions = {};
35
- let preRenderCallbackFunctions_id = 0;
36
- let postRenderCallbackFunctions = {};
37
- let postRenderCallbackFunctions_id = 0;
38
- let contextLostCallbackFunctions = {};
39
- let contextLostCallbackFunctions_id = 0;
40
- let contextRestoredCallbackFunctions = {};
41
- let contextRestoredCallbackFunctions_id = 0;
42
- let animated_id = undefined;
43
- let cameraOrtho = undefined, sceneOrtho = undefined, logoSprite = undefined;
44
- let sceneMap = [];
45
- let additionalActiveScenes = [];
46
- let scenesGroup = new THREE.Group();
47
- let canvas = undefined;
32
+ let playRate = 1000;
33
+ let preRenderCallbackFunctions = {};
34
+ let preRenderCallbackFunctions_id = 0;
35
+ let postRenderCallbackFunctions = {};
36
+ let postRenderCallbackFunctions_id = 0;
37
+ let contextLostCallbackFunctions = {};
38
+ let contextLostCallbackFunctions_id = 0;
39
+ let contextRestoredCallbackFunctions = {};
40
+ let contextRestoredCallbackFunctions_id = 0;
41
+ let cameraOrtho = undefined,
42
+ sceneOrtho = undefined,
43
+ logoSprite = undefined;
44
+ let sceneMap = [];
45
+ let additionalActiveScenes = [];
46
+ let scenesGroup = new THREE.Group();
47
+ let canvas = undefined;
48
48
  let sensor = undefined;
49
49
  let isRendering = false;
50
- let isInitialised = false;
51
- const _this = this;
52
- const currentSize = [0, 0];
53
- const currentOffset = [0, 0];
54
- //Render on demand is opt-in, when enabled the scene is only drawn when
55
- //something has changed.
56
- let renderOnDemand = false;
57
- let needsRender = true;
58
- const requestRender = () => {
59
- needsRender = true;
60
- }
61
- //Camera of the current scene shared with additional active scenes
62
- const sharedCamera = { controls: undefined, updated: false };
63
-
64
- this.getDrawingWidth = () => {
65
- if (container) {
66
- return container.clientWidth;
67
- } else if (canvas)
68
- if (typeof canvas.clientWidth !== 'undefined')
69
- return Math.round(canvas.clientWidth);
70
- else
71
- return Math.round(canvas.width);
72
- return 0;
73
- }
74
-
75
- this.getDrawingHeight = () => {
76
- if (container) {
77
- return container.clientHeight;
78
- } else if (canvas)
79
- if (typeof canvas.clientHeight !== 'undefined')
80
- return Math.round(canvas.clientHeight);
81
- else
82
- return Math.round(canvas.height);
83
- return 0;
84
- }
50
+ let isInitialised = false;
51
+ const _this = this;
52
+ const currentSize = [0, 0];
53
+ const currentOffset = [0, 0];
54
+ //Render on demand is opt-in, when enabled the scene is only drawn when
55
+ //something has changed.
56
+ let renderOnDemand = false;
57
+ let needsRender = true;
58
+ const requestRender = () => {
59
+ needsRender = true;
60
+ };
61
+ //Camera of the current scene shared with additional active scenes
62
+ const sharedCamera = { controls: undefined, updated: false };
63
+
64
+ this.getDrawingWidth = () => {
65
+ if (container) {
66
+ return container.clientWidth;
67
+ } else if (canvas)
68
+ if (typeof canvas.clientWidth !== 'undefined') return Math.round(canvas.clientWidth);
69
+ else return Math.round(canvas.width);
70
+ return 0;
71
+ };
72
+
73
+ this.getDrawingHeight = () => {
74
+ if (container) {
75
+ return container.clientHeight;
76
+ } else if (canvas)
77
+ if (typeof canvas.clientHeight !== 'undefined') return Math.round(canvas.clientHeight);
78
+ else return Math.round(canvas.height);
79
+ return 0;
80
+ };
85
81
 
86
- /**
87
- * Call this to resize the renderer, this is normally call automatically.
88
- */
89
- this.onWindowResize = () => {
90
- needsRender = true;
91
- currentScene.onWindowResize();
92
- //Give it a miniumum size of 1 x 1
93
- const width = this.getDrawingWidth() || 1;
94
- const height = this.getDrawingHeight() || 1;
95
- if (renderer != undefined) {
96
- let localRect = undefined;
97
- if (container) {
98
- localRect = container.getBoundingClientRect();
99
- renderer.setSize(width, height);
100
- } else if (canvas) {
101
- if (typeof canvas.getBoundingClientRect !== 'undefined') {
102
- localRect = canvas.getBoundingClientRect();
103
- canvas.width = width;
104
- canvas.height = height;
105
- renderer.setSize(width, height, false);
106
- } else {
107
- renderer.setSize(width, height, false);
108
-
109
- }
110
- }
111
- if (localRect) {
112
- currentOffset[0] = localRect.left;
113
- currentOffset[1] = localRect.top;
114
- }
115
- const target = new THREE.Vector2();
116
- renderer.getSize(target);
117
- currentSize[0] = target.x;
118
- currentSize[1] = target.y;
119
- //Text sprites are drawn at the resolution they occupy on screen
120
- const fov = currentScene?.camera?.fov;
121
- if (fov) {
122
- setTextPixelsPerUnit(currentSize[1] * renderer.getPixelRatio() /
123
- (2 * Math.tan(fov * Math.PI / 360)));
124
- }
125
- }
126
- }
82
+ /**
83
+ * Call this to resize the renderer, this is normally call automatically.
84
+ */
85
+ this.onWindowResize = () => {
86
+ needsRender = true;
87
+ currentScene.onWindowResize();
88
+ //Give it a miniumum size of 1 x 1
89
+ const width = this.getDrawingWidth() || 1;
90
+ const height = this.getDrawingHeight() || 1;
91
+ if (renderer != undefined) {
92
+ let localRect = undefined;
93
+ if (container) {
94
+ localRect = container.getBoundingClientRect();
95
+ renderer.setSize(width, height);
96
+ } else if (canvas) {
97
+ if (typeof canvas.getBoundingClientRect !== 'undefined') {
98
+ localRect = canvas.getBoundingClientRect();
99
+ canvas.width = width;
100
+ canvas.height = height;
101
+ renderer.setSize(width, height, false);
102
+ } else {
103
+ renderer.setSize(width, height, false);
104
+ }
105
+ }
106
+ if (localRect) {
107
+ currentOffset[0] = localRect.left;
108
+ currentOffset[1] = localRect.top;
109
+ }
110
+ const target = new THREE.Vector2();
111
+ renderer.getSize(target);
112
+ currentSize[0] = target.x;
113
+ currentSize[1] = target.y;
114
+ //Text sprites are drawn at the resolution they occupy on screen
115
+ const fov = currentScene?.camera?.fov;
116
+ if (fov) {
117
+ setTextPixelsPerUnit(
118
+ (currentSize[1] * renderer.getPixelRatio()) / (2 * Math.tan((fov * Math.PI) / 360)),
119
+ );
120
+ }
121
+ }
122
+ };
127
123
 
128
- /**
129
- * Initialise the renderer and its visualisations.
130
- */
131
- this.initialiseVisualisation = async (parameters) => {
132
- if (!isInitialised) {
133
- parameters = parameters || {};
134
- if (parameters['antialias'] === undefined) {
135
- let onMobile = false;
136
- try {
137
- if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
138
- onMobile = true;
139
- }
140
- }
141
- catch(err) {
142
- onMobile = false;
143
- }
144
- if (onMobile)
145
- parameters['antialias'] = false;
146
- else
147
- parameters['antialias'] = true;
148
- }
149
- if (parameters["canvas"]) {
150
- container = undefined;
151
- canvas = parameters["canvas"];
152
- }
124
+ /**
125
+ * Initialise the renderer and its visualisations.
126
+ */
127
+ this.initialiseVisualisation = async (parameters) => {
128
+ if (!isInitialised) {
129
+ parameters = parameters || {};
130
+ if (parameters['antialias'] === undefined) {
131
+ let onMobile = false;
132
+ try {
133
+ if (
134
+ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
135
+ navigator.userAgent,
136
+ )
137
+ ) {
138
+ onMobile = true;
139
+ }
140
+ } catch (err) {
141
+ onMobile = false;
142
+ }
143
+ if (onMobile) parameters['antialias'] = false;
144
+ else parameters['antialias'] = true;
145
+ }
146
+ if (parameters['canvas']) {
147
+ container = undefined;
148
+ canvas = parameters['canvas'];
149
+ }
153
150
  //WebGPURenderer otherwise requests a device with the default
154
151
  //maxTextureArrayLayers (256 on many adapters), which is too low for
155
152
  //some currnetly sypported scaffold, and the default
@@ -157,13 +154,20 @@ const Renderer = function (containerIn) {
157
154
  //transform compute pass only needs two storage buffers, the higher
158
155
  //limit is kept as headroom. We will request the highest possible on
159
156
  //the device for both.
160
- if (parameters.device === undefined && parameters.requiredLimits === undefined &&
161
- typeof navigator !== 'undefined' && navigator.gpu) {
157
+ if (
158
+ parameters.device === undefined &&
159
+ parameters.requiredLimits === undefined &&
160
+ typeof navigator !== 'undefined' &&
161
+ navigator.gpu
162
+ ) {
162
163
  try {
163
- const adapter = await navigator.gpu.requestAdapter({ powerPreference: parameters.powerPreference });
164
+ const adapter = await navigator.gpu.requestAdapter({
165
+ powerPreference: parameters.powerPreference,
166
+ });
164
167
  if (adapter) {
165
168
  parameters.requiredLimits = {
166
169
  maxTextureArrayLayers: adapter.limits.maxTextureArrayLayers,
170
+ maxTextureDimension2D: adapter.limits.maxTextureDimension2D,
167
171
  maxStorageBuffersPerShaderStage: adapter.limits.maxStorageBuffersPerShaderStage,
168
172
  };
169
173
  }
@@ -172,127 +176,127 @@ const Renderer = function (containerIn) {
172
176
  //use its defaults.
173
177
  }
174
178
  }
175
- renderer = new THREE.WebGPURenderer(parameters);
179
+ renderer = new THREE.WebGPURenderer(parameters);
176
180
  await renderer.init();
181
+ //animate() may have been called before the renderer was ready
182
+ if (isRendering) renderer.setAnimationLoop(this.render);
177
183
  //GPU glyph animation requires the WebGPU backend, the WebGL fallback
178
184
  //cannot index storage buffers freely.
179
185
  setGlyphComputeSupported(renderer.backend?.isWebGPUBackend === true);
180
186
 
181
187
  //renderer = new THREE.WebGLRenderer(parameters);
182
- if (container !== undefined) {
183
- container.appendChild( renderer.domElement );
184
- }
185
- renderer.setClearColor( 0xffffff, 1);
186
- if (canvas && canvas.style) {
187
- canvas.style.height = "100%";
188
- canvas.style.width = "100%";
189
- }
190
- const domCanvas = renderer.domElement;
191
- domCanvas.addEventListener("webglcontextlost", onContextLost, false);
192
- domCanvas.addEventListener("webglcontextrestored", onContextRestored, false);
193
-
194
- renderer.autoClear = false;
195
- const scene = this.createScene("default");
196
- this.setCurrentScene(scene);
197
- onRenderRequest(requestRender);
198
- isInitialised = true;
199
- }
200
- }
188
+ if (container !== undefined) {
189
+ container.appendChild(renderer.domElement);
190
+ }
191
+ renderer.setClearColor(0xffffff, 1);
192
+ if (canvas && canvas.style) {
193
+ canvas.style.height = '100%';
194
+ canvas.style.width = '100%';
195
+ }
196
+ const domCanvas = renderer.domElement;
197
+ domCanvas.addEventListener('webglcontextlost', onContextLost, false);
198
+ domCanvas.addEventListener('webglcontextrestored', onContextRestored, false);
199
+
200
+ renderer.autoClear = false;
201
+ const scene = this.createScene('default');
202
+ this.setCurrentScene(scene);
203
+ onRenderRequest(requestRender);
204
+ isInitialised = true;
205
+ }
206
+ };
201
207
 
202
- const onContextLost = event => {
208
+ const onContextLost = (event) => {
203
209
  event.preventDefault();
204
210
  for (let key of Object.keys(preRenderCallbackFunctions)) {
205
211
  if (contextLostCallbackFunctions.hasOwnProperty(key)) {
206
212
  contextLostCallbackFunctions[key].call();
207
213
  }
208
214
  }
209
- }
215
+ };
210
216
 
211
- const onContextRestored = event => {
217
+ const onContextRestored = (event) => {
212
218
  event.preventDefault();
213
219
  for (let key of Object.keys(preRenderCallbackFunctions)) {
214
220
  if (contextRestoredCallbackFunctions.hasOwnProperty(key)) {
215
221
  contextRestoredCallbackFunctions[key].call();
216
222
  }
217
223
  }
218
- }
224
+ };
219
225
 
220
- /**
221
- * Get the current scene on display.
222
- * @return {Zinc.Scene};
223
- */
224
- this.getCurrentScene = () => {
225
- return currentScene;
226
- }
226
+ /**
227
+ * Get the current scene on display.
228
+ * @return {Zinc.Scene};
229
+ */
230
+ this.getCurrentScene = () => {
231
+ return currentScene;
232
+ };
227
233
 
228
- /**
229
- * Set the current scene on display.
230
- *
231
- * @param {Zinc.Scene} sceneIn - The scene to be set, only scene created by this instance
232
- * of ZincRenderer is supported currently.
233
- */
234
- this.setCurrentScene = sceneIn => {
235
- if (sceneIn) {
236
- this.removeActiveScene(sceneIn);
237
- const oldScene = currentScene;
238
- currentScene = sceneIn;
239
- if (oldScene) {
240
- oldScene.setInteractiveControlEnable(false);
241
- }
242
- currentScene.setInteractiveControlEnable(true);
243
- currentScene.setAdditionalScenesGroup(scenesGroup);
244
- needsRender = true;
245
- this.onWindowResize();
246
- }
247
- }
234
+ /**
235
+ * Set the current scene on display.
236
+ *
237
+ * @param {Zinc.Scene} sceneIn - The scene to be set, only scene created by this instance
238
+ * of ZincRenderer is supported currently.
239
+ */
240
+ this.setCurrentScene = (sceneIn) => {
241
+ if (sceneIn) {
242
+ this.removeActiveScene(sceneIn);
243
+ const oldScene = currentScene;
244
+ currentScene = sceneIn;
245
+ if (oldScene) {
246
+ oldScene.setInteractiveControlEnable(false);
247
+ }
248
+ currentScene.setInteractiveControlEnable(true);
249
+ currentScene.setAdditionalScenesGroup(scenesGroup);
250
+ needsRender = true;
251
+ this.onWindowResize();
252
+ }
253
+ };
248
254
 
249
- /**
250
- * Return scene with the matching name if scene with that name has been created.
251
- *
252
- * @param {String} name - Name to match
253
- * @return {Zinc.Scene}
254
- */
255
- this.getSceneByName = name => {
255
+ /**
256
+ * Return scene with the matching name if scene with that name has been created.
257
+ *
258
+ * @param {String} name - Name to match
259
+ * @return {Zinc.Scene}
260
+ */
261
+ this.getSceneByName = (name) => {
256
262
  return sceneMap[name];
257
- }
263
+ };
258
264
 
259
265
  /*
260
- * Create a new scene with the provided name if scene with the same name exists,
261
- * return undefined.
262
- *
263
- * @param {String} name - Name of the scene to be created.
264
- * @return {Zinc.Scene}
265
- */
266
- this.createScene = name => {
267
- if (sceneMap[name] != undefined){
268
- return undefined;
269
- } else {
270
- let new_scene = undefined;
271
- if (canvas)
272
- new_scene = new Scene(canvas, renderer);
273
- else
274
- new_scene = new Scene(container, renderer);
275
- sceneMap[name] = new_scene;
276
- new_scene.sceneName = name;
277
- return new_scene;
278
- }
279
- }
280
-
281
- const updateOrthoScene = () => {
282
- if (logoSprite != undefined) {
283
- const material = logoSprite.material;
284
- if (material.map) {
285
- const width = this.getDrawingWidth();
286
- const height = this.getDrawingHeight();
287
- const calculatedWidth = (width - material.map.image.width)/2;
288
- const calculatedHeight = (-height + material.map.image.height)/2;
289
- logoSprite.position.set(calculatedWidth, calculatedHeight, 1 );
290
- }
291
- }
292
- return sceneMap[name];
293
- }
266
+ * Create a new scene with the provided name if scene with the same name exists,
267
+ * return undefined.
268
+ *
269
+ * @param {String} name - Name of the scene to be created.
270
+ * @return {Zinc.Scene}
271
+ */
272
+ this.createScene = (name) => {
273
+ if (sceneMap[name] != undefined) {
274
+ return undefined;
275
+ } else {
276
+ let new_scene = undefined;
277
+ if (canvas) new_scene = new Scene(canvas, renderer);
278
+ else new_scene = new Scene(container, renderer);
279
+ sceneMap[name] = new_scene;
280
+ new_scene.sceneName = name;
281
+ return new_scene;
282
+ }
283
+ };
284
+
285
+ const updateOrthoScene = () => {
286
+ if (logoSprite != undefined) {
287
+ const material = logoSprite.material;
288
+ if (material.map) {
289
+ const width = this.getDrawingWidth();
290
+ const height = this.getDrawingHeight();
291
+ const calculatedWidth = (width - material.map.image.width) / 2;
292
+ const calculatedHeight = (-height + material.map.image.height) / 2;
293
+ logoSprite.position.set(calculatedWidth, calculatedHeight, 1);
294
+ }
295
+ }
296
+ return sceneMap[name];
297
+ };
294
298
 
295
- /**
299
+ /**
296
300
  };
297
301
 
298
302
  const updateOrthoCamera = () => {
@@ -310,445 +314,454 @@ const Renderer = function (containerIn) {
310
314
  /**
311
315
  * Reset the viewport of the current scene to its original state.
312
316
  */
313
- this.resetView = () => {
314
- currentScene.resetView();
315
- }
317
+ this.resetView = () => {
318
+ currentScene.resetView();
319
+ };
316
320
 
317
- /**
318
- * Adjust zoom distance to include all primitives in scene and also the additional scenes
319
- * but the lookat direction and up vectors will remain constant.
320
- */
321
- this.viewAll = () => {
322
- if (currentScene) {
323
- const boundingBox = currentScene.getBoundingBox();
324
- if (boundingBox) {
325
- for(let i = 0; i < additionalActiveScenes.length; i++) {
326
- const boundingBox2 = additionalActiveScenes[i].getBoundingBox();
327
- if (boundingBox2) {
328
- boundingBox.union(boundingBox2);
329
- }
330
- }
331
- currentScene.viewAllWithBoundingBox(boundingBox);
332
- }
333
- }
334
- }
335
-
336
- /**
337
- * Load a legacy model(s) format with the provided URLs and parameters. This only loads the geometry
338
- * without any of the metadata. Therefore, extra parameters should be provided. This should be
339
- * called from {@link Zinc.Scene}.
340
- *
341
- * @deprecated
342
- */
343
- this.loadModelsURL = (urls, colours, opacities, timeEnabled, morphColour, finishCallback) => {
344
- currentScene.loadModelsURL(urls, colours, opacities, timeEnabled, morphColour, finishCallback);
345
- }
321
+ /**
322
+ * Adjust zoom distance to include all primitives in scene and also the additional scenes
323
+ * but the lookat direction and up vectors will remain constant.
324
+ */
325
+ this.viewAll = () => {
326
+ if (currentScene) {
327
+ const boundingBox = currentScene.getBoundingBox();
328
+ if (boundingBox) {
329
+ for (let i = 0; i < additionalActiveScenes.length; i++) {
330
+ const boundingBox2 = additionalActiveScenes[i].getBoundingBox();
331
+ if (boundingBox2) {
332
+ boundingBox.union(boundingBox2);
333
+ }
334
+ }
335
+ currentScene.viewAllWithBoundingBox(boundingBox);
336
+ }
337
+ }
338
+ };
346
339
 
347
- const loadView = viewData => {
348
- currentScene.loadView(viewData);
349
- };
340
+ /**
341
+ * Load a legacy model(s) format with the provided URLs and parameters. This only loads the geometry
342
+ * without any of the metadata. Therefore, extra parameters should be provided. This should be
343
+ * called from {@link Zinc.Scene}.
344
+ *
345
+ * @deprecated
346
+ */
347
+ this.loadModelsURL = (urls, colours, opacities, timeEnabled, morphColour, finishCallback) => {
348
+ currentScene.loadModelsURL(urls, colours, opacities, timeEnabled, morphColour, finishCallback);
349
+ };
350
350
 
351
- /**
352
- * Load the viewport from an external location provided by the url. This should be
353
- * called from {@link Zinc.Scene};
354
- * @param {String} URL - address to the file containing viewport information.
355
- * @deprecated
356
- */
357
- this.loadViewURL = url => {
358
- currentScene.loadViewURL(url);
359
- }
351
+ const loadView = (viewData) => {
352
+ currentScene.loadView(viewData);
353
+ };
360
354
 
361
- /**
362
- * Load a legacy file format containing the viewport and its model file from an external
363
- * location provided by the url. Use the new metadata format with
364
- * {@link Zinc.Scene#loadMetadataURL} instead. This should be
365
- * called from {@link Zinc.Scene};
366
- *
367
- * @param {String} URL - address to the file containing viewport and model information.
368
- * @deprecated
369
- */
370
- this.loadFromViewURL = (jsonFilePrefix, finishCallback) => {
371
- currentScene.loadFromViewURL(jsonFilePrefix, finishCallback);
372
- }
355
+ /**
356
+ * Load the viewport from an external location provided by the url. This should be
357
+ * called from {@link Zinc.Scene};
358
+ * @param {String} URL - address to the file containing viewport information.
359
+ * @deprecated
360
+ */
361
+ this.loadViewURL = (url) => {
362
+ currentScene.loadViewURL(url);
363
+ };
373
364
 
374
- this.updateDirectionalLight = () => {
375
- currentScene.updateDirectionalLight();
376
- }
365
+ /**
366
+ * Load a legacy file format containing the viewport and its model file from an external
367
+ * location provided by the url. Use the new metadata format with
368
+ * {@link Zinc.Scene#loadMetadataURL} instead. This should be
369
+ * called from {@link Zinc.Scene};
370
+ *
371
+ * @param {String} URL - address to the file containing viewport and model information.
372
+ * @deprecated
373
+ */
374
+ this.loadFromViewURL = (jsonFilePrefix, finishCallback) => {
375
+ currentScene.loadFromViewURL(jsonFilePrefix, finishCallback);
376
+ };
377
377
 
378
- let runAnimation = () => {
379
- if (isRendering) {
380
- animated_id = requestAnimationFrame( runAnimation );
381
- this.render();
382
- } else {
383
- cancelAnimationFrame(animated_id);
384
- animated_id = undefined;
385
- }
386
- }
378
+ this.updateDirectionalLight = () => {
379
+ currentScene.updateDirectionalLight();
380
+ };
387
381
 
388
- /**
389
- * Stop the animation and renderer to get into the render loop.
390
- */
391
- this.stopAnimate = () => {
382
+ /**
383
+ * Stop the animation and renderer to get into the render loop.
384
+ */
385
+ this.stopAnimate = () => {
392
386
  if (isRendering) {
393
387
  isRendering = false;
388
+ renderer?.setAnimationLoop(null);
394
389
  }
395
- }
390
+ };
396
391
 
397
- /**
398
- * Start the animation and begin the rendering loop.
399
- */
400
- this.animate = () => {
392
+ /**
393
+ * Start the animation and begin the rendering loop.
394
+ */
395
+ this.animate = () => {
401
396
  if (!isRendering) {
402
397
  clock.reset();
403
398
  isRendering = true;
404
399
  needsRender = true;
405
- runAnimation();
400
+ //WebGPURenderer always runs its own requestAnimationFrame loop which
401
+ //updates the node frame and the per frame info, render from that loop
402
+ //instead of running a second one.
403
+ renderer?.setAnimationLoop(this.render);
406
404
  }
407
- }
408
-
409
- const prevTime = Date.now();
410
-
411
- /**
412
- * Add a callback function which will be called when the gl context is lost.
413
- * @param {Function} callbackFunction - callbackFunction to be added.
414
- *
415
- * @return {Number}
416
- */
417
- this.addContextLostCallbackFunction = callbackFunction => {
418
- contextLostCallbackFunctions_id = contextLostCallbackFunctions_id + 1;
419
- contextLostCallbackFunctions[contextLostCallbackFunctions_id] = callbackFunction;
420
- return contextLostCallbackFunctions_id;
421
- }
405
+ };
422
406
 
423
- /**
424
- * Remove a callback function that is previously added to the renderer.
425
- * @param {Number} id - identifier of the previously added callback function.
426
- */
427
- this.removeContextLostCallbackFunction = id => {
428
- if (id in contextLostCallbackFunctions) {
429
- delete contextLostCallbackFunctions[id];
430
- }
431
- }
407
+ const prevTime = Date.now();
432
408
 
433
- /**
434
- * Add a callback function which will be called when the gl context is restored.
435
- * @param {Function} callbackFunction - callbackFunction to be added.
436
- *
437
- * @return {Number}
438
- */
439
- this.addContextRestoredCallbackFunction = callbackFunction => {
440
- contextRestoredCallbackFunctions_id = contextRestoredCallbackFunctions_id + 1;
441
- contextRestoredCallbackFunctions[contextRestoredCallbackFunctions_id] = callbackFunction;
442
- return contextRestoredCallbackFunctions_id;
443
- }
409
+ /**
410
+ * Add a callback function which will be called when the gl context is lost.
411
+ * @param {Function} callbackFunction - callbackFunction to be added.
412
+ *
413
+ * @return {Number}
414
+ */
415
+ this.addContextLostCallbackFunction = (callbackFunction) => {
416
+ contextLostCallbackFunctions_id = contextLostCallbackFunctions_id + 1;
417
+ contextLostCallbackFunctions[contextLostCallbackFunctions_id] = callbackFunction;
418
+ return contextLostCallbackFunctions_id;
419
+ };
444
420
 
445
- /**
446
- * Remove a callback function that is previously added to the renderer.
447
- * @param {Number} id - identifier of the previously added callback function.
448
- */
449
- this.removeContextRestoredCallbackFunction = id => {
450
- if (id in contextRestoredCallbackFunctions_id) {
451
- delete contextRestoredCallbackFunctions_id[id];
452
- }
453
- }
421
+ /**
422
+ * Remove a callback function that is previously added to the renderer.
423
+ * @param {Number} id - identifier of the previously added callback function.
424
+ */
425
+ this.removeContextLostCallbackFunction = (id) => {
426
+ if (id in contextLostCallbackFunctions) {
427
+ delete contextLostCallbackFunctions[id];
428
+ }
429
+ };
454
430
 
455
- /**
456
- * Add a callback function which will be called everytime before the renderer renders its scene.
457
- * @param {Function} callbackFunction - callbackFunction to be added.
458
- *
459
- * @return {Number}
460
- */
461
- this.addPreRenderCallbackFunction = callbackFunction => {
462
- preRenderCallbackFunctions_id = preRenderCallbackFunctions_id + 1;
463
- preRenderCallbackFunctions[preRenderCallbackFunctions_id] = callbackFunction;
464
- return preRenderCallbackFunctions_id;
465
- }
431
+ /**
432
+ * Add a callback function which will be called when the gl context is restored.
433
+ * @param {Function} callbackFunction - callbackFunction to be added.
434
+ *
435
+ * @return {Number}
436
+ */
437
+ this.addContextRestoredCallbackFunction = (callbackFunction) => {
438
+ contextRestoredCallbackFunctions_id = contextRestoredCallbackFunctions_id + 1;
439
+ contextRestoredCallbackFunctions[contextRestoredCallbackFunctions_id] = callbackFunction;
440
+ return contextRestoredCallbackFunctions_id;
441
+ };
466
442
 
467
- /**
468
- * Remove a callback function that is previously added to the scene.
469
- * @param {Number} id - identifier of the previously added callback function.
470
- */
471
- this.removePreRenderCallbackFunction = id => {
472
- if (id in preRenderCallbackFunctions) {
473
- delete preRenderCallbackFunctions[id];
474
- }
475
- }
443
+ /**
444
+ * Remove a callback function that is previously added to the renderer.
445
+ * @param {Number} id - identifier of the previously added callback function.
446
+ */
447
+ this.removeContextRestoredCallbackFunction = (id) => {
448
+ if (id in contextRestoredCallbackFunctions_id) {
449
+ delete contextRestoredCallbackFunctions_id[id];
450
+ }
451
+ };
476
452
 
477
- /**
478
- * Add a callback function which will be called everytime after the renderer renders its scene.
479
- * @param {Function} callbackFunction - callbackFunction to be added.
480
- *
481
- * @return {Number}
482
- */
483
- this.addPostRenderCallbackFunction = callbackFunction => {
484
- postRenderCallbackFunctions_id = postRenderCallbackFunctions_id + 1;
485
- postRenderCallbackFunctions[postRenderCallbackFunctions_id] = callbackFunction;
486
- return postRenderCallbackFunctions_id;
487
- }
453
+ /**
454
+ * Add a callback function which will be called everytime before the renderer renders its scene.
455
+ * @param {Function} callbackFunction - callbackFunction to be added.
456
+ *
457
+ * @return {Number}
458
+ */
459
+ this.addPreRenderCallbackFunction = (callbackFunction) => {
460
+ preRenderCallbackFunctions_id = preRenderCallbackFunctions_id + 1;
461
+ preRenderCallbackFunctions[preRenderCallbackFunctions_id] = callbackFunction;
462
+ return preRenderCallbackFunctions_id;
463
+ };
488
464
 
489
- /**
490
- * Remove a callback function that is previously added to the scene.
491
- * @param {Number} id - identifier of the previously added callback function.
492
- */
493
- this.removePostRenderCallbackFunction = id => {
494
- if (id in postRenderCallbackFunctions) {
495
- delete postRenderCallbackFunctions[id];
496
- }
497
- }
465
+ /**
466
+ * Remove a callback function that is previously added to the scene.
467
+ * @param {Number} id - identifier of the previously added callback function.
468
+ */
469
+ this.removePreRenderCallbackFunction = (id) => {
470
+ if (id in preRenderCallbackFunctions) {
471
+ delete preRenderCallbackFunctions[id];
472
+ }
473
+ };
498
474
 
499
- /**
500
- * Get the current play rate, playrate affects how fast an animated object animates.
501
- * Also see {@link Zinc.Scene#duration}.
502
- */
503
- this.getPlayRate = () => {
504
- return playRate;
505
- }
475
+ /**
476
+ * Add a callback function which will be called everytime after the renderer renders its scene.
477
+ * @param {Function} callbackFunction - callbackFunction to be added.
478
+ *
479
+ * @return {Number}
480
+ */
481
+ this.addPostRenderCallbackFunction = (callbackFunction) => {
482
+ postRenderCallbackFunctions_id = postRenderCallbackFunctions_id + 1;
483
+ postRenderCallbackFunctions[postRenderCallbackFunctions_id] = callbackFunction;
484
+ return postRenderCallbackFunctions_id;
485
+ };
506
486
 
507
- /**
508
- * Set the current play rate, playrate affects how fast an animated object animates.
509
- * @param {Number} PlayRateIn - value to set the playrate to.
510
- * Also see {@link Zinc.Scene#duration}.
511
- */
512
- this.setPlayRate = playRateIn => {
513
- playRate = playRateIn;
514
- needsRender = true;
515
- }
487
+ /**
488
+ * Remove a callback function that is previously added to the scene.
489
+ * @param {Number} id - identifier of the previously added callback function.
490
+ */
491
+ this.removePostRenderCallbackFunction = (id) => {
492
+ if (id in postRenderCallbackFunctions) {
493
+ delete postRenderCallbackFunctions[id];
494
+ }
495
+ };
516
496
 
517
- /**
518
- * Enable or disable render on demand, it is disabled by default.
519
- * When enabled, the scenes are only drawn when something has changed,
520
- * e.g. camera movement, animation, loading and changes made through
521
- * the Zinc APIs. Call {@link Renderer#invalidate} after modifying
522
- * THREE.js objects directly or after changing the THREE.js renderer,
523
- * e.g. setClearColor.
524
- * Pre-render callbacks are called on every frame, post-render callbacks
525
- * are only called when the scenes are drawn.
526
- *
527
- * @param {Boolean} flag - Enable or disable render on demand.
528
- */
529
- this.setRenderOnDemand = flag => {
530
- renderOnDemand = flag ? true : false;
531
- needsRender = true;
532
- }
497
+ /**
498
+ * Get the current play rate, playrate affects how fast an animated object animates.
499
+ * Also see {@link Zinc.Scene#duration}.
500
+ */
501
+ this.getPlayRate = () => {
502
+ return playRate;
503
+ };
533
504
 
534
- /**
535
- * Check if render on demand is enabled.
536
- *
537
- * @return {Boolean}
538
- */
539
- this.isRenderOnDemand = () => {
540
- return renderOnDemand;
541
- }
505
+ /**
506
+ * Set the current play rate, playrate affects how fast an animated object animates.
507
+ * @param {Number} PlayRateIn - value to set the playrate to.
508
+ * Also see {@link Zinc.Scene#duration}.
509
+ */
510
+ this.setPlayRate = (playRateIn) => {
511
+ playRate = playRateIn;
512
+ needsRender = true;
513
+ };
542
514
 
543
- /**
544
- * Request the scenes to be drawn on the next frame, this is only
545
- * required when render on demand is enabled.
546
- */
547
- this.invalidate = () => {
548
- needsRender = true;
549
- }
515
+ /**
516
+ * Enable or disable render on demand, it is disabled by default.
517
+ * When enabled, the scenes are only drawn when something has changed,
518
+ * e.g. camera movement, animation, loading and changes made through
519
+ * the Zinc APIs. Call {@link Renderer#invalidate} after modifying
520
+ * THREE.js objects directly or after changing the THREE.js renderer,
521
+ * e.g. setClearColor.
522
+ * Pre-render callbacks are called on every frame, post-render callbacks
523
+ * are only called when the scenes are drawn.
524
+ *
525
+ * @param {Boolean} flag - Enable or disable render on demand.
526
+ */
527
+ this.setRenderOnDemand = (flag) => {
528
+ renderOnDemand = flag ? true : false;
529
+ needsRender = true;
530
+ };
550
531
 
551
- this.getCurrentTime = () => {
552
- return currentScene.getCurrentTime();
553
- }
532
+ /**
533
+ * Check if render on demand is enabled.
534
+ *
535
+ * @return {Boolean}
536
+ */
537
+ this.isRenderOnDemand = () => {
538
+ return renderOnDemand;
539
+ };
554
540
 
541
+ /**
542
+ * Request the scenes to be drawn on the next frame, this is only
543
+ * required when render on demand is enabled.
544
+ */
545
+ this.invalidate = () => {
546
+ needsRender = true;
547
+ };
555
548
 
556
- /**
557
- * Get the current play rate, playrate affects how fast an animated object animates.
558
- * Also see {@link Zinc.Scene#duration}.
559
- */
560
- this.setMorphsTime = time => {
561
- currentScene.setMorphsTime(time);
562
- }
549
+ this.getCurrentTime = () => {
550
+ return currentScene.getCurrentTime();
551
+ };
563
552
 
564
- /**
565
- * Get {Zinc.Geoemtry} by its id. This should be called from {@link Zinc.Scene};
566
- *
567
- * @depreacted
568
- * @return {Zinc.Geometry}
569
- */
570
- this.getZincGeometryByID = id => {
571
- return currentScene.getZincGeometryByID(id);
572
- }
553
+ /**
554
+ * Get the current play rate, playrate affects how fast an animated object animates.
555
+ * Also see {@link Zinc.Scene#duration}.
556
+ */
557
+ this.setMorphsTime = (time) => {
558
+ currentScene.setMorphsTime(time);
559
+ };
573
560
 
574
- /**
575
- * Add {Three.Object} to the current scene.
576
- */
577
- this.addToScene = object => {
578
- currentScene.addObject(object)
579
- }
561
+ /**
562
+ * Get {Zinc.Geoemtry} by its id. This should be called from {@link Zinc.Scene};
563
+ *
564
+ * @depreacted
565
+ * @return {Zinc.Geometry}
566
+ */
567
+ this.getZincGeometryByID = (id) => {
568
+ return currentScene.getZincGeometryByID(id);
569
+ };
580
570
 
581
- /**
582
- * Add {Three.Object} to the ortho scene, objects added to the ortho scene are rendered in
583
- * normalised coordinates and overlay on top of current scene.
584
- *
585
- */
586
- this.addToOrthoScene = object => {
587
- if (sceneOrtho == undefined)
588
- sceneOrtho = new THREE.Scene();
589
- if (cameraOrtho == undefined) {
590
- const width = this.getDrawingWidth();
591
- const height = this.getDrawingHeight();
592
- cameraOrtho = new THREE.OrthographicCamera( -width / 2,
593
- width / 2, height/ 2, -height / 2, 1, 10 );
594
- cameraOrtho.position.z = 10;
595
- }
596
- sceneOrtho.add(object)
597
- needsRender = true;
598
- }
599
-
600
- const createHUDSprites = logoSprite => {
601
- return texture => {
602
- texture.needsUpdate = true;
603
- const material = new THREE.SpriteMaterial( { map: texture } );
604
- const imagewidth = material.map.image.width;
605
- const imageheight = material.map.image.height;
606
- logoSprite.material = material;
607
- logoSprite.scale.set( imagewidth, imageheight, 1 );
608
- const width = this.getDrawingWidth();
609
- const height = this.getDrawingHeight();
610
- logoSprite.position.set( (width - imagewidth)/2, (-height + imageheight)/2, 1 );
611
- this.addToOrthoScene(logoSprite);
612
- };
613
- };
571
+ /**
572
+ * Add {Three.Object} to the current scene.
573
+ */
574
+ this.addToScene = (object) => {
575
+ currentScene.addObject(object);
576
+ };
614
577
 
615
- this.addLogo = () => {
616
- logoSprite = new THREE.Sprite();
617
- const logo = THREE.ImageUtils.loadTexture(
618
- "images/abi_big_logo_transparent_small.png", undefined, createHUDSprites(logoSprite));
619
- }
578
+ /**
579
+ * Add {Three.Object} to the ortho scene, objects added to the ortho scene are rendered in
580
+ * normalised coordinates and overlay on top of current scene.
581
+ *
582
+ */
583
+ this.addToOrthoScene = (object) => {
584
+ if (sceneOrtho == undefined) sceneOrtho = new THREE.Scene();
585
+ if (cameraOrtho == undefined) {
586
+ const width = this.getDrawingWidth();
587
+ const height = this.getDrawingHeight();
588
+ cameraOrtho = new THREE.OrthographicCamera(
589
+ -width / 2,
590
+ width / 2,
591
+ height / 2,
592
+ -height / 2,
593
+ 1,
594
+ 10,
595
+ );
596
+ cameraOrtho.position.z = 10;
597
+ }
598
+ sceneOrtho.add(object);
599
+ needsRender = true;
600
+ };
601
+
602
+ const createHUDSprites = (logoSprite) => {
603
+ return (texture) => {
604
+ texture.needsUpdate = true;
605
+ const material = new THREE.SpriteMaterial({ map: texture });
606
+ const imagewidth = material.map.image.width;
607
+ const imageheight = material.map.image.height;
608
+ logoSprite.material = material;
609
+ logoSprite.scale.set(imagewidth, imageheight, 1);
610
+ const width = this.getDrawingWidth();
611
+ const height = this.getDrawingHeight();
612
+ logoSprite.position.set((width - imagewidth) / 2, (-height + imageheight) / 2, 1);
613
+ this.addToOrthoScene(logoSprite);
614
+ };
615
+ };
616
+
617
+ this.addLogo = () => {
618
+ logoSprite = new THREE.Sprite();
619
+ const logo = THREE.ImageUtils.loadTexture(
620
+ 'images/abi_big_logo_transparent_small.png',
621
+ undefined,
622
+ createHUDSprites(logoSprite),
623
+ );
624
+ };
620
625
 
621
- /**
622
- * Render the current and all additional scenes. It will first update all geometries and glyphsets
623
- * in scenes, clear depth buffer and render the ortho scene, call the preRenderCallbackFunctions stack
624
- * , render the scenes then postRenderCallback.
625
- */
626
- this.render = () => {
627
- if (!sensor) {
628
- if (container) {
629
- if (container.clientWidth > 0 && container.clientHeight > 0) {
630
- sensor = new ResizeSensor(container, this.onWindowResize);
631
- }
632
- } else if (canvas) {
633
- if (canvas.width > 0 && canvas.height > 0)
634
- sensor = new ResizeSensor(canvas, this.onWindowResize);
635
- }
636
- }
626
+ /**
627
+ * Render the current and all additional scenes. It will first update all geometries and glyphsets
628
+ * in scenes, clear depth buffer and render the ortho scene, call the preRenderCallbackFunctions stack
629
+ * , render the scenes then postRenderCallback.
630
+ */
631
+ this.render = () => {
632
+ if (!sensor) {
633
+ if (container) {
634
+ if (container.clientWidth > 0 && container.clientHeight > 0) {
635
+ sensor = new ResizeSensor(container, this.onWindowResize);
636
+ }
637
+ } else if (canvas) {
638
+ if (canvas.width > 0 && canvas.height > 0)
639
+ sensor = new ResizeSensor(canvas, this.onWindowResize);
640
+ }
641
+ }
637
642
  clock.update();
638
- const delta = clock.getDelta();
639
- let changed = currentScene.renderGeometries(playRate, delta, this.playAnimation);
640
- if (additionalActiveScenes.length > 0) {
641
- //Additional scenes are displayed with the current scene's camera
642
- sharedCamera.controls = currentScene.getZincCameraControls();
643
- sharedCamera.updated = currentScene.isCameraUpdated();
644
- }
645
- for(let i = 0; i < additionalActiveScenes.length; i++) {
646
- const sceneItem = additionalActiveScenes[i];
647
- if (sceneItem.renderGeometries(playRate, delta, this.playAnimation, sharedCamera))
648
- changed = true;
649
- }
643
+ const delta = clock.getDelta();
644
+ //Objects are only updated on every frame when render on demand is off
645
+ //or the renderer itself has requested a frame, e.g. on resize
646
+ const forceUpdate = !renderOnDemand || needsRender;
647
+ let changed = currentScene.renderGeometries(
648
+ playRate,
649
+ delta,
650
+ this.playAnimation,
651
+ undefined,
652
+ forceUpdate,
653
+ );
654
+ if (additionalActiveScenes.length > 0) {
655
+ //Additional scenes are displayed with the current scene's camera
656
+ sharedCamera.controls = currentScene.getZincCameraControls();
657
+ sharedCamera.updated = currentScene.isCameraUpdated();
658
+ }
659
+ for (let i = 0; i < additionalActiveScenes.length; i++) {
660
+ const sceneItem = additionalActiveScenes[i];
661
+ if (
662
+ sceneItem.renderGeometries(playRate, delta, this.playAnimation, sharedCamera, forceUpdate)
663
+ )
664
+ changed = true;
665
+ }
650
666
  for (let key in preRenderCallbackFunctions) {
651
667
  if (preRenderCallbackFunctions.hasOwnProperty(key)) {
652
668
  preRenderCallbackFunctions[key].call();
653
669
  }
654
670
  }
655
- //Pre-render callbacks may have requested a frame
656
- if (renderOnDemand && !changed && !needsRender) {
657
- return;
658
- }
659
- needsRender = false;
671
+ //Pre-render callbacks may have requested a frame
672
+ if (renderOnDemand && !changed && !needsRender) {
673
+ return;
674
+ }
675
+ needsRender = false;
660
676
  currentScene.render(renderer);
661
- if (cameraOrtho != undefined && sceneOrtho != undefined) {
662
- renderer.clearDepth();
663
- renderer.render( sceneOrtho, cameraOrtho );
664
- }
677
+ if (cameraOrtho != undefined && sceneOrtho != undefined) {
678
+ renderer.clearDepth();
679
+ renderer.render(sceneOrtho, cameraOrtho);
680
+ }
665
681
  for (let key in postRenderCallbackFunctions) {
666
682
  if (postRenderCallbackFunctions.hasOwnProperty(key)) {
667
683
  postRenderCallbackFunctions[key].call();
668
684
  }
669
685
  }
670
- }
686
+ };
671
687
 
672
- this.forceContextLoss = () => {
673
- // renderer.forceContextLoss();
674
- }
688
+ this.forceContextLoss = () => {
689
+ // renderer.forceContextLoss();
690
+ };
675
691
 
676
- this.forceContextRestore= () => {
677
- // renderer.forceContextRestore();
678
- }
692
+ this.forceContextRestore = () => {
693
+ // renderer.forceContextRestore();
694
+ };
679
695
 
680
- /**
681
- * Get the internal {@link Three.Renderer}, to gain access to ThreeJS APIs.
682
- */
683
- this.getThreeJSRenderer = () => {
684
- return renderer;
685
- }
696
+ /**
697
+ * Get the internal {@link Three.Renderer}, to gain access to ThreeJS APIs.
698
+ */
699
+ this.getThreeJSRenderer = () => {
700
+ return renderer;
701
+ };
686
702
 
687
- /**
688
- * Check if a scene is currently active.
689
- * @param {Zinc.Scene} sceneIn - Scene to check if it is currently
690
- * rendered.
691
- */
692
- this.isSceneActive = sceneIn => {
693
- if (currentScene === sceneIn) {
694
- return true;
695
- } else {
696
- for(let i = 0; i < additionalActiveScenes.length; i++) {
697
- const sceneItem = additionalActiveScenes[i];
698
- if (sceneItem === sceneIn)
699
- return true;
700
- }
701
- }
702
- return false;
703
- }
703
+ /**
704
+ * Check if a scene is currently active.
705
+ * @param {Zinc.Scene} sceneIn - Scene to check if it is currently
706
+ * rendered.
707
+ */
708
+ this.isSceneActive = (sceneIn) => {
709
+ if (currentScene === sceneIn) {
710
+ return true;
711
+ } else {
712
+ for (let i = 0; i < additionalActiveScenes.length; i++) {
713
+ const sceneItem = additionalActiveScenes[i];
714
+ if (sceneItem === sceneIn) return true;
715
+ }
716
+ }
717
+ return false;
718
+ };
704
719
 
705
- /**
706
- * Add additional active scene for rendering, this scene will also be rendered but
707
- * viewport of the currentScene will be used.
708
- * @param {Zinc.Scene} additionalScene - Scene to be added to the rendering.
709
- */
710
- this.addActiveScene = additionalScene => {
711
- if (!this.isSceneActive(additionalScene)) {
712
- additionalActiveScenes.push(additionalScene);
713
- scenesGroup.add(additionalScene.getThreeJSScene());
714
- needsRender = true;
715
- }
716
- }
720
+ /**
721
+ * Add additional active scene for rendering, this scene will also be rendered but
722
+ * viewport of the currentScene will be used.
723
+ * @param {Zinc.Scene} additionalScene - Scene to be added to the rendering.
724
+ */
725
+ this.addActiveScene = (additionalScene) => {
726
+ if (!this.isSceneActive(additionalScene)) {
727
+ additionalActiveScenes.push(additionalScene);
728
+ scenesGroup.add(additionalScene.getThreeJSScene());
729
+ needsRender = true;
730
+ }
731
+ };
717
732
 
718
- /**
719
- * Remove a currenrtly active scene from the renderer, this scene will also be rendered but
720
- * viewport of the currentScene will be used.
721
- * @param {Zinc.Scene} additionalScene - Scene to be removed from rendering.
722
- */
723
- this.removeActiveScene = additionalScene => {
724
- for(let i = 0; i < additionalActiveScenes.length; i++) {
725
- const sceneItem = additionalActiveScenes[i];
726
- if (sceneItem === additionalScene) {
727
- additionalActiveScenes.splice(i, 1);
728
- scenesGroup.remove(additionalScene.getThreeJSScene());
729
- needsRender = true;
730
- return;
731
- }
732
- }
733
- }
733
+ /**
734
+ * Remove a currenrtly active scene from the renderer, this scene will also be rendered but
735
+ * viewport of the currentScene will be used.
736
+ * @param {Zinc.Scene} additionalScene - Scene to be removed from rendering.
737
+ */
738
+ this.removeActiveScene = (additionalScene) => {
739
+ for (let i = 0; i < additionalActiveScenes.length; i++) {
740
+ const sceneItem = additionalActiveScenes[i];
741
+ if (sceneItem === additionalScene) {
742
+ additionalActiveScenes.splice(i, 1);
743
+ scenesGroup.remove(additionalScene.getThreeJSScene());
744
+ needsRender = true;
745
+ return;
746
+ }
747
+ }
748
+ };
734
749
 
735
- /**
736
- * Clear all additional scenes from rendering except for curentScene.
737
- */
738
- this.clearAllActiveScene = () => {
739
- for (let i = 0; i < additionalActiveScenes.length; i++) {
740
- scenesGroup.remove(additionalActiveScenes[i].getThreeJSScene());
741
- }
742
- additionalActiveScenes.splice(0,additionalActiveScenes.length);
743
- needsRender = true;
744
- }
750
+ /**
751
+ * Clear all additional scenes from rendering except for curentScene.
752
+ */
753
+ this.clearAllActiveScene = () => {
754
+ for (let i = 0; i < additionalActiveScenes.length; i++) {
755
+ scenesGroup.remove(additionalActiveScenes[i].getThreeJSScene());
756
+ }
757
+ additionalActiveScenes.splice(0, additionalActiveScenes.length);
758
+ needsRender = true;
759
+ };
745
760
 
746
761
  /**
747
762
  * Dispose all memory allocated, this will effetively destroy all scenes.
748
763
  */
749
764
  this.dispose = () => {
750
- if (isRendering)
751
- cancelAnimationFrame(animated_id);
752
765
  for (const key in sceneMap) {
753
766
  if (sceneMap.hasOwnProperty(key)) {
754
767
  sceneMap[key].clearAll();
@@ -769,37 +782,44 @@ const Renderer = function (containerIn) {
769
782
  cameraOrtho = undefined;
770
783
  sceneOrtho = undefined;
771
784
  logoSprite = undefined;
772
- const scene = this.createScene("default");
785
+ const scene = this.createScene('default');
773
786
  this.setCurrentScene(scene);
774
787
  sensor = undefined;
775
788
  offRenderRequest(requestRender);
776
789
  renderer?.dispose();
777
- }
790
+ };
778
791
 
779
- /**
780
- * Transition from the current viewport to the endingScene's viewport in the specified duration.
781
- *
782
- * @param {Zinc.Scene} endingScene - Viewport of this scene will be used as the destination.
783
- * @param {Number} duration - Amount of time to transition from current viewport to the
784
- * endingScene's viewport.
785
- */
786
- this.transitionScene = (endingScene, duration) => {
787
- if (currentScene) {
788
- const currentCamera = currentScene.getZincCameraControls();
789
- const boundingBox = endingScene.getBoundingBox();
790
- if (boundingBox) {
791
- const radius = boundingBox.min.distanceTo(boundingBox.max)/2.0;
792
- const centreX = (boundingBox.min.x + boundingBox.max.x) / 2.0;
793
- const centreY = (boundingBox.min.y + boundingBox.max.y) / 2.0;
794
- const centreZ = (boundingBox.min.z + boundingBox.max.z) / 2.0;
795
- const clip_factor = 4.0;
796
- const endingViewport = currentCamera.getViewportFromCentreAndRadius(centreX, centreY, centreZ, radius, 40, radius * clip_factor );
797
- const startingViewport = currentCamera.getCurrentViewport();
798
- currentCamera.cameraTransition(startingViewport, endingViewport, duration);
799
- currentCamera.enableCameraTransition();
800
- }
801
- }
802
- }
792
+ /**
793
+ * Transition from the current viewport to the endingScene's viewport in the specified duration.
794
+ *
795
+ * @param {Zinc.Scene} endingScene - Viewport of this scene will be used as the destination.
796
+ * @param {Number} duration - Amount of time to transition from current viewport to the
797
+ * endingScene's viewport.
798
+ */
799
+ this.transitionScene = (endingScene, duration) => {
800
+ if (currentScene) {
801
+ const currentCamera = currentScene.getZincCameraControls();
802
+ const boundingBox = endingScene.getBoundingBox();
803
+ if (boundingBox) {
804
+ const radius = boundingBox.min.distanceTo(boundingBox.max) / 2.0;
805
+ const centreX = (boundingBox.min.x + boundingBox.max.x) / 2.0;
806
+ const centreY = (boundingBox.min.y + boundingBox.max.y) / 2.0;
807
+ const centreZ = (boundingBox.min.z + boundingBox.max.z) / 2.0;
808
+ const clip_factor = 4.0;
809
+ const endingViewport = currentCamera.getViewportFromCentreAndRadius(
810
+ centreX,
811
+ centreY,
812
+ centreZ,
813
+ radius,
814
+ 40,
815
+ radius * clip_factor,
816
+ );
817
+ const startingViewport = currentCamera.getCurrentViewport();
818
+ currentCamera.cameraTransition(startingViewport, endingViewport, duration);
819
+ currentCamera.enableCameraTransition();
820
+ }
821
+ }
822
+ };
803
823
 
804
824
  /**
805
825
  * Check if the renderer is running on the WebGL 2 fallback backend.
@@ -809,7 +829,7 @@ const Renderer = function (containerIn) {
809
829
  */
810
830
  this.isWebGL2 = () => {
811
831
  return renderer?.backend?.isWebGLBackend === true;
812
- }
832
+ };
813
833
 
814
834
  /**
815
835
  * Check if the renderer is running on the WebGPU backend.
@@ -818,7 +838,7 @@ const Renderer = function (containerIn) {
818
838
  */
819
839
  this.isWebGPU = () => {
820
840
  return renderer?.backend?.isWebGPUBackend === true;
821
- }
841
+ };
822
842
  };
823
843
 
824
- export { Renderer };
844
+ export { Renderer };