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.
- package/README.md +27 -22
- package/build/zinc.js +2 -2
- package/build/zinc.js.map +1 -1
- package/package.json +4 -1
- package/src/controls.js +1332 -1241
- package/src/geometryCSG.js +111 -115
- package/src/glyphsetCSG.js +51 -55
- package/src/loaders/GLTFToZincJSLoader.js +31 -33
- package/src/loaders/JSONLoader.js +339 -449
- package/src/loaders/OBJLoader.js +654 -851
- package/src/loaders/STLLoader.js +271 -329
- package/src/loaders/niftiReader.js +90 -59
- package/src/loaders/primitivesLoader.js +55 -52
- package/src/minimap.js +63 -43
- package/src/primitives/geometry.js +40 -44
- package/src/primitives/glyph.js +16 -19
- package/src/primitives/glyphset.js +229 -185
- package/src/primitives/label.js +29 -31
- package/src/primitives/lines.js +20 -20
- package/src/primitives/lines2.js +33 -39
- package/src/primitives/lod.js +43 -43
- package/src/primitives/marker.js +31 -32
- package/src/primitives/markerCluster.js +32 -35
- package/src/primitives/pointset.js +86 -83
- package/src/primitives/texturePrimitive.js +9 -10
- package/src/primitives/textureSlides.js +84 -97
- package/src/primitives/textureVolume.js +46 -49
- package/src/primitives/tubeLines.js +108 -108
- package/src/primitives/zincObject.js +176 -184
- package/src/region.js +145 -155
- package/src/renderRequests.js +3 -3
- package/src/renderer.js +649 -629
- package/src/scene.js +502 -430
- package/src/sceneExporter.js +22 -17
- package/src/sceneLoader.js +542 -296
- package/src/shaders/rgbVolumeRender.js +11 -18
- package/src/shaders/textureArray.js +5 -12
- package/src/shaders/textureSlide.js +10 -17
- package/src/shaders/volumeRender.js +11 -18
- package/src/shaders/volumeRender_old.js +11 -18
- package/src/shaders/volumeTexture.js +7 -14
- package/src/textSprite.js +23 -19
- package/src/texture/texture.js +14 -15
- package/src/texture/textureArray.js +14 -16
- package/src/three/InstancedPoints.js +2 -9
- package/src/three/Loader.js +334 -315
- package/src/three/line/Line.js +165 -215
- package/src/three/line/LineSegments.js +40 -55
- package/src/three/line/LineSegments2.js +322 -366
- package/src/three/line/LineSegmentsGeometry.js +239 -280
- package/src/three-js-csg.js +260 -252
- package/src/tsl/glyphRenderMaterial.js +12 -3
- package/src/tsl/glyphTransform.js +51 -29
- package/src/tsl/textureSlides.js +23 -24
- package/src/utilities.js +309 -371
- package/src/videoHandler.js +76 -83
- package/src/workers/geometryCSG.worker.js +33 -36
- package/src/workers/geometryCSGInternal.js +39 -44
- package/src/zinc.js +4 -7
- 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
|
-
|
|
22
|
+
const stats = 0;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
let renderer = undefined;
|
|
25
|
+
let currentScene = undefined;
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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 (
|
|
161
|
-
|
|
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({
|
|
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
|
-
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
this.resetView = () => {
|
|
318
|
+
currentScene.resetView();
|
|
319
|
+
};
|
|
316
320
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
-
|
|
348
|
-
|
|
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
|
-
|
|
353
|
-
|
|
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
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
|
|
375
|
-
|
|
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
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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
|
-
|
|
390
|
-
|
|
391
|
-
|
|
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
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
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
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
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
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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
|
-
|
|
552
|
-
|
|
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
|
-
|
|
558
|
-
|
|
559
|
-
*/
|
|
560
|
-
this.setMorphsTime = time => {
|
|
561
|
-
currentScene.setMorphsTime(time);
|
|
562
|
-
}
|
|
549
|
+
this.getCurrentTime = () => {
|
|
550
|
+
return currentScene.getCurrentTime();
|
|
551
|
+
};
|
|
563
552
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
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
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
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
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
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
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
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
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
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
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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
|
-
|
|
662
|
-
|
|
663
|
-
|
|
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
|
-
|
|
673
|
-
|
|
674
|
-
|
|
688
|
+
this.forceContextLoss = () => {
|
|
689
|
+
// renderer.forceContextLoss();
|
|
690
|
+
};
|
|
675
691
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
692
|
+
this.forceContextRestore = () => {
|
|
693
|
+
// renderer.forceContextRestore();
|
|
694
|
+
};
|
|
679
695
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
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
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
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
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
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
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
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(
|
|
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
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
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 };
|