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