zincjs 2.4.1-beta.4 → 2.4.1-beta.5
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 +10 -0
- package/build/zinc.js +5 -5
- package/build/zinc.js.map +1 -1
- package/package.json +1 -1
- package/src/controls.js +71 -49
- package/src/loaders/primitivesLoader.js +59 -16
- package/src/minimap.js +48 -13
- package/src/primitives/geometry.js +2 -0
- package/src/primitives/glyph.js +11 -1
- package/src/primitives/glyphset.js +25 -7
- package/src/primitives/label.js +39 -24
- package/src/primitives/lines.js +2 -0
- package/src/primitives/lines2.js +76 -24
- package/src/primitives/lod.js +11 -4
- package/src/primitives/marker.js +6 -1
- package/src/primitives/markerCluster.js +5 -1
- package/src/primitives/pointset.js +33 -28
- package/src/primitives/textureSlides.js +19 -3
- package/src/primitives/textureVolume.js +2 -0
- package/src/primitives/tubeLines.js +4 -0
- package/src/primitives/zincObject.js +76 -10
- package/src/region.js +85 -35
- package/src/renderRequests.js +20 -0
- package/src/renderer.js +81 -9
- package/src/scene.js +132 -22
- package/src/sceneExporter.js +4 -0
- package/src/sceneLoader.js +58 -19
- package/src/textSprite.js +211 -0
- package/src/utilities.js +147 -47
|
@@ -2,7 +2,7 @@ import * as THREE from 'three/webgpu';
|
|
|
2
2
|
import { Label } from './label';
|
|
3
3
|
import { InstancedPoints } from '../three/InstancedPoints';
|
|
4
4
|
import { ZincObject } from './zincObject';
|
|
5
|
-
import { getCircularTexture, toBufferGeometry } from '../utilities';
|
|
5
|
+
import { getCircularTexture, toBufferGeometry, updateWorldMatrixFromAncestors } from '../utilities';
|
|
6
6
|
import { createInstancedPointsMaterial } from '../tsl/pointsMaterial';
|
|
7
7
|
|
|
8
8
|
//Maximum number of points a programmatically built (addPoints) Pointset can
|
|
@@ -124,27 +124,26 @@ const Pointset = function () {
|
|
|
124
124
|
if (morphVertices) {
|
|
125
125
|
const bottomPositions = positionFrames[bottomFrame];
|
|
126
126
|
const topPositions = positionFrames[topFrame];
|
|
127
|
+
//pointPositions shares its array with instancePosition
|
|
127
128
|
const positions = mesh.pointPositions;
|
|
128
129
|
const length = activeCount * 3;
|
|
129
130
|
for (let i = 0; i < length; i++) {
|
|
130
131
|
positions[i] = proportion * bottomPositions[i] + (1 - proportion) * topPositions[i];
|
|
131
132
|
}
|
|
132
|
-
|
|
133
|
-
instancePosition.array.set(positions.subarray(0, length));
|
|
134
|
-
instancePosition.needsUpdate = true;
|
|
133
|
+
mesh.geometry.getAttribute('instancePosition').needsUpdate = true;
|
|
135
134
|
this.boundingBoxUpdateRequired = true;
|
|
136
135
|
}
|
|
137
136
|
if (morphColours && colorFrames) {
|
|
138
137
|
const bottomColors = colorFrames[Math.min(bottomFrame, colorFrames.length - 1)];
|
|
139
138
|
const topColors = colorFrames[Math.min(topFrame, colorFrames.length - 1)];
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
if (!mesh.instanceColor) {
|
|
140
|
+
mesh.setColorAt(0, _tempColor);
|
|
141
|
+
}
|
|
142
|
+
//Write the blended colours straight into the instance colours
|
|
143
|
+
const colors = mesh.instanceColor.array;
|
|
144
|
+
const length = activeCount * 3;
|
|
145
|
+
for (let i = 0; i < length; i++) {
|
|
146
|
+
colors[i] = proportion * bottomColors[i] + (1 - proportion) * topColors[i];
|
|
148
147
|
}
|
|
149
148
|
mesh.instanceColor.needsUpdate = true;
|
|
150
149
|
}
|
|
@@ -188,14 +187,13 @@ const Pointset = function () {
|
|
|
188
187
|
|
|
189
188
|
const mesh = new InstancedPoints(quadGeometry, material, numberOfPoints);
|
|
190
189
|
mesh.count = numberOfPoints;
|
|
191
|
-
mesh.pointPositions = new Float32Array(numberOfPoints * 3);
|
|
192
|
-
mesh.pointPositions.set(positionFrames[0]);
|
|
193
|
-
mesh.userData = this;
|
|
194
|
-
this.drawRange = numberOfPoints;
|
|
195
|
-
|
|
196
190
|
const instancePosition = quadGeometry.getAttribute('instancePosition');
|
|
197
191
|
instancePosition.array.set(positionFrames[0]);
|
|
198
192
|
instancePosition.needsUpdate = true;
|
|
193
|
+
//Share the array to avoid keeping and updating two copies
|
|
194
|
+
mesh.pointPositions = instancePosition.array;
|
|
195
|
+
mesh.userData = this;
|
|
196
|
+
this.drawRange = numberOfPoints;
|
|
199
197
|
|
|
200
198
|
const initialColorFrame = colorFrames ? colorFrames[0] : extractStaticColorFrame(geometry);
|
|
201
199
|
if (initialColorFrame) {
|
|
@@ -230,7 +228,8 @@ const Pointset = function () {
|
|
|
230
228
|
label.setPosition(coord[0], coord[1], coord[2]);
|
|
231
229
|
const sprite = label.getSprite();
|
|
232
230
|
sprite.material.sizeAttenuation = false;
|
|
233
|
-
|
|
231
|
+
//Only discard fully transparent pixels to keep the smooth edges
|
|
232
|
+
sprite.material.alphaTest = 0.05;
|
|
234
233
|
sprite.material.transparent = true;
|
|
235
234
|
sprite.material.depthWrite = false;
|
|
236
235
|
sprite.material.depthTest = labelDepthTest;
|
|
@@ -261,6 +260,7 @@ const Pointset = function () {
|
|
|
261
260
|
* @param {Number} colour - A hex value of the colour for the points
|
|
262
261
|
*/
|
|
263
262
|
this.addPoints = (coords, labels, colour) => {
|
|
263
|
+
this.requestRender();
|
|
264
264
|
if (coords && coords.length > 0) {
|
|
265
265
|
let mesh = this.getMorph();
|
|
266
266
|
let current = this.drawRange;
|
|
@@ -272,7 +272,7 @@ const Pointset = function () {
|
|
|
272
272
|
material.color.set(colour);
|
|
273
273
|
material.alphaTest = 0.5;
|
|
274
274
|
mesh = new InstancedPoints(quadGeometry, material, DEFAULT_CAPACITY);
|
|
275
|
-
mesh.pointPositions =
|
|
275
|
+
mesh.pointPositions = quadGeometry.getAttribute('instancePosition').array;
|
|
276
276
|
mesh.count = 0;
|
|
277
277
|
mesh.userData = this;
|
|
278
278
|
this.setMorph(mesh);
|
|
@@ -281,9 +281,6 @@ const Pointset = function () {
|
|
|
281
281
|
coords.forEach(coord => {
|
|
282
282
|
if (this.drawRange < DEFAULT_CAPACITY) {
|
|
283
283
|
instancePosition.setXYZ(this.drawRange, coord[0], coord[1], coord[2]);
|
|
284
|
-
mesh.pointPositions[this.drawRange * 3] = coord[0];
|
|
285
|
-
mesh.pointPositions[this.drawRange * 3 + 1] = coord[1];
|
|
286
|
-
mesh.pointPositions[this.drawRange * 3 + 2] = coord[2];
|
|
287
284
|
this.drawRange++;
|
|
288
285
|
}
|
|
289
286
|
});
|
|
@@ -311,6 +308,7 @@ const Pointset = function () {
|
|
|
311
308
|
* @param {Number} hex - hex value of color to be set
|
|
312
309
|
*/
|
|
313
310
|
this.setColourHex = function(hex) {
|
|
311
|
+
this.requestRender();
|
|
314
312
|
this._lod._material.color.setHex(hex);
|
|
315
313
|
if (this._lod._secondaryMaterial) {
|
|
316
314
|
this._lod._secondaryMaterial.color.setHex(hex);
|
|
@@ -328,6 +326,7 @@ const Pointset = function () {
|
|
|
328
326
|
* @param {THREE.Color} colour - colour to be set
|
|
329
327
|
*/
|
|
330
328
|
this.setColour = (colour) => {
|
|
329
|
+
this.requestRender();
|
|
331
330
|
this._lod.setColour(colour);
|
|
332
331
|
for (let i = 0; i < labelSets.length; i++) {
|
|
333
332
|
if (labelSets[i]) {
|
|
@@ -343,6 +342,7 @@ const Pointset = function () {
|
|
|
343
342
|
* should be on or off.
|
|
344
343
|
*/
|
|
345
344
|
this.setLabelDepthTest = (flag) => {
|
|
345
|
+
this.requestRender();
|
|
346
346
|
labelDepthTest = flag;
|
|
347
347
|
for (let i = 0; i < labelSets.length; i++) {
|
|
348
348
|
if (labelSets[i]) {
|
|
@@ -357,6 +357,7 @@ const Pointset = function () {
|
|
|
357
357
|
* @param {Number} fontWeightIn - Default value is 700
|
|
358
358
|
*/
|
|
359
359
|
this.setLabelFontWeight = (fontWeightIn) => {
|
|
360
|
+
this.requestRender();
|
|
360
361
|
fontWeight = fontWeightIn;
|
|
361
362
|
for (let i = 0; i < labelSets.length; i++) {
|
|
362
363
|
if (labelSets[i]) {
|
|
@@ -372,6 +373,7 @@ const Pointset = function () {
|
|
|
372
373
|
* value is 1.
|
|
373
374
|
*/
|
|
374
375
|
this.setLabelSize = (size) => {
|
|
376
|
+
this.requestRender();
|
|
375
377
|
labelSize = size;
|
|
376
378
|
for (let i = 0; i < labelSets.length; i++) {
|
|
377
379
|
if (labelSets[i]) {
|
|
@@ -386,6 +388,7 @@ const Pointset = function () {
|
|
|
386
388
|
* @param {boolean} flag - default value is true
|
|
387
389
|
*/
|
|
388
390
|
this.displayLabels = (flag) => {
|
|
391
|
+
this.requestRender();
|
|
389
392
|
labelVisibility = flag;
|
|
390
393
|
for (let i = 0; i < labelSets.length; i++) {
|
|
391
394
|
if (labelSets[i]) {
|
|
@@ -399,6 +402,7 @@ const Pointset = function () {
|
|
|
399
402
|
* @param {Number} size - size to be set.
|
|
400
403
|
*/
|
|
401
404
|
this.setSize = size => {
|
|
405
|
+
this.requestRender();
|
|
402
406
|
if (this.morph && this.morph.material) {
|
|
403
407
|
this.morph.material.size = size;
|
|
404
408
|
this.morph.material.userData.uniforms.pointSize.value = size;
|
|
@@ -413,6 +417,7 @@ const Pointset = function () {
|
|
|
413
417
|
* should be on or off.
|
|
414
418
|
*/
|
|
415
419
|
this.setSizeAttenuation = flag => {
|
|
420
|
+
this.requestRender();
|
|
416
421
|
if (this.morph && this.morph.material) {
|
|
417
422
|
this.morph.material.sizeAttenuation = flag;
|
|
418
423
|
this.morph.material.userData.uniforms.sizeAttenuation.value = flag ? 1 : 0;
|
|
@@ -438,6 +443,7 @@ const Pointset = function () {
|
|
|
438
443
|
* Edit Vertice in index.
|
|
439
444
|
*/
|
|
440
445
|
this.editVertices = function(coords, i) {
|
|
446
|
+
this.requestRender();
|
|
441
447
|
if (coords && coords.length) {
|
|
442
448
|
const mesh = this.getMorph();
|
|
443
449
|
const maxIndex = i + coords.length - 1;
|
|
@@ -452,9 +458,6 @@ const Pointset = function () {
|
|
|
452
458
|
label.setPosition(coord[0], coord[1], coord[2]);
|
|
453
459
|
}
|
|
454
460
|
instancePosition.setXYZ(index, coord[0], coord[1], coord[2]);
|
|
455
|
-
mesh.pointPositions[index * 3] = coord[0];
|
|
456
|
-
mesh.pointPositions[index * 3 + 1] = coord[1];
|
|
457
|
-
mesh.pointPositions[index * 3 + 2] = coord[2];
|
|
458
461
|
//Keep the base frame consistent for any pointset that also
|
|
459
462
|
//happens to be time varying.
|
|
460
463
|
if (positionFrames[0]) {
|
|
@@ -474,6 +477,7 @@ const Pointset = function () {
|
|
|
474
477
|
* Delete a vertex in index.
|
|
475
478
|
*/
|
|
476
479
|
this.deleteVertices = function(index) {
|
|
480
|
+
this.requestRender();
|
|
477
481
|
const mesh = this.getMorph();
|
|
478
482
|
if (!mesh || 0 > index || index >= this.drawRange) {
|
|
479
483
|
return this.drawRange;
|
|
@@ -481,7 +485,8 @@ const Pointset = function () {
|
|
|
481
485
|
const instancePosition = mesh.geometry.getAttribute('instancePosition');
|
|
482
486
|
const end = this.drawRange - 1;
|
|
483
487
|
instancePosition.array.copyWithin(index * 3, (index + 1) * 3, this.drawRange * 3);
|
|
484
|
-
mesh.pointPositions
|
|
488
|
+
if (mesh.pointPositions !== instancePosition.array)
|
|
489
|
+
mesh.pointPositions.copyWithin(index * 3, (index + 1) * 3, this.drawRange * 3);
|
|
485
490
|
if (mesh.instanceColor) {
|
|
486
491
|
mesh.instanceColor.array.copyWithin(index * 3, (index + 1) * 3, this.drawRange * 3);
|
|
487
492
|
mesh.instanceColor.needsUpdate = true;
|
|
@@ -560,8 +565,7 @@ const Pointset = function () {
|
|
|
560
565
|
if (this.boundingBoxUpdateRequired) {
|
|
561
566
|
this._b1.setFromArray(mesh.pointPositions.subarray(0, this.drawRange * 3));
|
|
562
567
|
this.cachedBoundingBox.copy(this._b1);
|
|
563
|
-
|
|
564
|
-
this.cachedBoundingBox.applyMatrix4(mesh.matrixWorld);
|
|
568
|
+
this.cachedBoundingBox.applyMatrix4(updateWorldMatrixFromAncestors(mesh));
|
|
565
569
|
this.cachedBoundingBox.getCenter(this.center);
|
|
566
570
|
this.radius = this.center.distanceTo(this.cachedBoundingBox.max);
|
|
567
571
|
this.boundingBoxUpdateRequired = false;
|
|
@@ -586,6 +590,7 @@ const Pointset = function () {
|
|
|
586
590
|
* @param {Number} time - Can be any value between 0 to duration.
|
|
587
591
|
*/
|
|
588
592
|
this.setMorphTime = time => {
|
|
593
|
+
this.requestRender();
|
|
589
594
|
if (time > this.duration) {
|
|
590
595
|
this.inbuildTime = this.duration;
|
|
591
596
|
} else if (0 > time) {
|
|
@@ -2,6 +2,7 @@ import * as THREE from 'three/webgpu';
|
|
|
2
2
|
//import * as shader from '../shaders/textureSlide.js';
|
|
3
3
|
import { createWebGPUMaterial } from '../tsl/textureSlides.js';
|
|
4
4
|
import { TexturePrimitive } from './texturePrimitive';
|
|
5
|
+
import { updateWorldMatrixFromAncestors } from '../utilities';
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
const cloneData3DTexture = (sourceTex) => {
|
|
@@ -73,6 +74,7 @@ const TextureSlides = function (textureIn) {
|
|
|
73
74
|
* @param {SLIDE_SETTINGS} slideSettings - An array to each slide settings.
|
|
74
75
|
*/
|
|
75
76
|
this.createSlides = slideSettings => {
|
|
77
|
+
this.requestRender();
|
|
76
78
|
slideSettings.forEach(slide => this.createSlide(slide));
|
|
77
79
|
}
|
|
78
80
|
|
|
@@ -123,6 +125,7 @@ const TextureSlides = function (textureIn) {
|
|
|
123
125
|
* @param {SLIDE_SETTINGS} settings - s.
|
|
124
126
|
*/
|
|
125
127
|
this.modifySlideSettings = (settings) => {
|
|
128
|
+
this.requestRender();
|
|
126
129
|
if (settings && settings.id &&
|
|
127
130
|
settings.id in idTextureMap &&
|
|
128
131
|
idTextureMap[settings.id]) {
|
|
@@ -139,6 +142,7 @@ const TextureSlides = function (textureIn) {
|
|
|
139
142
|
* created mesh's id.
|
|
140
143
|
*/
|
|
141
144
|
this.createSlide = settings => {
|
|
145
|
+
this.requestRender();
|
|
142
146
|
if (this.texture && this.texture.isTextureArray && this.texture.isReady()) {
|
|
143
147
|
if (settings && settings.direction && settings.value !== undefined) {
|
|
144
148
|
const geometry = new THREE.PlaneGeometry(1, 1);
|
|
@@ -238,6 +242,7 @@ const TextureSlides = function (textureIn) {
|
|
|
238
242
|
* @param {Slide} slide - Slide to be remvoed
|
|
239
243
|
*/
|
|
240
244
|
this.removeSlide = slide => {
|
|
245
|
+
this.requestRender();
|
|
241
246
|
if (slide) {
|
|
242
247
|
this.removeSlideWithId(slide.id);
|
|
243
248
|
}
|
|
@@ -249,6 +254,7 @@ const TextureSlides = function (textureIn) {
|
|
|
249
254
|
* @param {Number} id - id of slide to be remvoed
|
|
250
255
|
*/
|
|
251
256
|
this.removeSlideWithId = id => {
|
|
257
|
+
this.requestRender();
|
|
252
258
|
if (this.morph && id in idTextureMap && idTextureMap[id]) {
|
|
253
259
|
if (this.morph.getObjectById(id)) {
|
|
254
260
|
const slide = idTextureMap[id];
|
|
@@ -333,14 +339,14 @@ const TextureSlides = function (textureIn) {
|
|
|
333
339
|
expandBoxWithSettings(this.cachedBoundingBox, slide.material.userData.uniforms,
|
|
334
340
|
vector);
|
|
335
341
|
});
|
|
336
|
-
this.
|
|
337
|
-
this.cachedBoundingBox.applyMatrix4(this.morph.matrixWorld);
|
|
342
|
+
this.cachedBoundingBox.applyMatrix4(updateWorldMatrixFromAncestors(this.morph));
|
|
338
343
|
this.boundingBoxUpdateRequired = false;
|
|
339
344
|
}
|
|
340
345
|
return this.cachedBoundingBox;
|
|
341
346
|
}
|
|
342
347
|
|
|
343
348
|
this.applyTransformation = (rotation, position, scale) => {
|
|
349
|
+
this.requestRender();
|
|
344
350
|
const matrix = new THREE.Matrix4();
|
|
345
351
|
matrix.set(
|
|
346
352
|
rotation[0],
|
|
@@ -369,6 +375,7 @@ const TextureSlides = function (textureIn) {
|
|
|
369
375
|
}
|
|
370
376
|
|
|
371
377
|
this.setRenderOrder = (order) => {
|
|
378
|
+
this.requestRender();
|
|
372
379
|
//multiilayers
|
|
373
380
|
this.morph.renderOrder = order;
|
|
374
381
|
}
|
|
@@ -394,6 +401,7 @@ const TextureSlides = function (textureIn) {
|
|
|
394
401
|
}
|
|
395
402
|
|
|
396
403
|
this.showEdges = (color) => {
|
|
404
|
+
this.requestRender();
|
|
397
405
|
if (!edgesLine) {
|
|
398
406
|
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
|
|
399
407
|
geometry.translate(0.5, 0.5, 0.5);
|
|
@@ -408,6 +416,7 @@ const TextureSlides = function (textureIn) {
|
|
|
408
416
|
|
|
409
417
|
|
|
410
418
|
this.setUniformsValue = (name, val) => {
|
|
419
|
+
this.requestRender();
|
|
411
420
|
this.morph.children.forEach((mesh) => {
|
|
412
421
|
const material = mesh.material;
|
|
413
422
|
if (material.userData.uniforms) {
|
|
@@ -422,6 +431,7 @@ const TextureSlides = function (textureIn) {
|
|
|
422
431
|
}
|
|
423
432
|
|
|
424
433
|
this.discardAlphaPixel = (flag) => {
|
|
434
|
+
this.requestRender();
|
|
425
435
|
discardAlpha = flag;
|
|
426
436
|
this.setUniformsValue("discardAlpha", discardAlpha);
|
|
427
437
|
}
|
|
@@ -431,6 +441,7 @@ const TextureSlides = function (textureIn) {
|
|
|
431
441
|
}
|
|
432
442
|
|
|
433
443
|
this.setBrightness = (brightnessIn) => {
|
|
444
|
+
this.requestRender();
|
|
434
445
|
brightness = brightnessIn;
|
|
435
446
|
this.setUniformsValue("brightness", brightness);
|
|
436
447
|
}
|
|
@@ -440,6 +451,7 @@ const TextureSlides = function (textureIn) {
|
|
|
440
451
|
}
|
|
441
452
|
|
|
442
453
|
this.setContrast = (contrastIn) => {
|
|
454
|
+
this.requestRender();
|
|
443
455
|
if (contrast >= 0 ) {
|
|
444
456
|
contrast = contrastIn;
|
|
445
457
|
this.setUniformsValue("contrast", contrast);
|
|
@@ -451,6 +463,7 @@ const TextureSlides = function (textureIn) {
|
|
|
451
463
|
}
|
|
452
464
|
|
|
453
465
|
this.setNumberOfChannels = (numbersIn) => {
|
|
466
|
+
this.requestRender();
|
|
454
467
|
nChannels = numbersIn;
|
|
455
468
|
this.setUniformsValue("nChannels", nChannels);
|
|
456
469
|
}
|
|
@@ -460,6 +473,7 @@ const TextureSlides = function (textureIn) {
|
|
|
460
473
|
}
|
|
461
474
|
|
|
462
475
|
this.setMask = (maskTextureIn) => {
|
|
476
|
+
this.requestRender();
|
|
463
477
|
maskTexture = maskTextureIn;
|
|
464
478
|
maskEnabled = maskTexture ? true : false;
|
|
465
479
|
this.morph.children.forEach((mesh) => {
|
|
@@ -475,6 +489,7 @@ const TextureSlides = function (textureIn) {
|
|
|
475
489
|
}
|
|
476
490
|
|
|
477
491
|
this.hideEdges = () => {
|
|
492
|
+
this.requestRender();
|
|
478
493
|
if (edgesLine) {
|
|
479
494
|
edgesLine.visible = false;
|
|
480
495
|
}
|
|
@@ -513,6 +528,7 @@ const TextureSlides = function (textureIn) {
|
|
|
513
528
|
* Update the glyphsets if required the render.
|
|
514
529
|
*/
|
|
515
530
|
this.setMorphTime = (time) => {
|
|
531
|
+
this.requestRender();
|
|
516
532
|
let newTime = time;
|
|
517
533
|
if (time > this.duration)
|
|
518
534
|
newTime = this.duration;
|
|
@@ -529,7 +545,7 @@ const TextureSlides = function (textureIn) {
|
|
|
529
545
|
/**
|
|
530
546
|
* Update the glyphsets if required the render.
|
|
531
547
|
*/
|
|
532
|
-
this.render = (delta, playAnimation, options) => {
|
|
548
|
+
this.render = (delta, playAnimation, cameraControls, options) => {
|
|
533
549
|
//console.log("render", delta, playAnimation, this.textureList)
|
|
534
550
|
if (playAnimation == true && this.timeEnabled &&
|
|
535
551
|
this.textureList.length > 1) {
|
|
@@ -17,6 +17,8 @@ const TextureSlides = function (textureIn) {
|
|
|
17
17
|
TexturePrimitive.call(this, textureIn);
|
|
18
18
|
this.isTextureVolume = true;
|
|
19
19
|
const textureSettings = [];
|
|
20
|
+
//Map of mesh id to slide mesh
|
|
21
|
+
const idTextureMap = {};
|
|
20
22
|
this.morph = new THREE.Group();
|
|
21
23
|
this.group = this.morph;
|
|
22
24
|
this.morph.userData = this;
|
|
@@ -44,6 +44,7 @@ const TubeLines = function () {
|
|
|
44
44
|
* @param {Number} width - Width of the lines.
|
|
45
45
|
*/
|
|
46
46
|
this.setWidth = width => {
|
|
47
|
+
this.requestRender();
|
|
47
48
|
if (this.morph && this.morph.material) {
|
|
48
49
|
this.morph.material.linewidth = width;
|
|
49
50
|
this.morph.material.needsUpdate = true;
|
|
@@ -58,6 +59,7 @@ const TubeLines = function () {
|
|
|
58
59
|
* can be any value between from 0 to 1.0.
|
|
59
60
|
*/
|
|
60
61
|
this.setAlpha = function (alpha) {
|
|
62
|
+
this.requestRender();
|
|
61
63
|
let mesh = this.getMorph();
|
|
62
64
|
mesh.material.opacity = alpha;
|
|
63
65
|
mesh.material.transparent = alpha < 1.0;
|
|
@@ -69,6 +71,7 @@ const TubeLines = function () {
|
|
|
69
71
|
* @param {Boolean} wireframe
|
|
70
72
|
*/
|
|
71
73
|
this.setWireframe = (wireframe) => {
|
|
74
|
+
this.requestRender();
|
|
72
75
|
let mesh = this.getMorph();
|
|
73
76
|
mesh.material.wireframe = wireframe;
|
|
74
77
|
}
|
|
@@ -80,6 +83,7 @@ const TubeLines = function () {
|
|
|
80
83
|
* @param {Integer} radialSegments The number of segments that make up the cross-section.
|
|
81
84
|
*/
|
|
82
85
|
this.setTubeLines = (radius, radialSegments) => {
|
|
86
|
+
this.requestRender();
|
|
83
87
|
if (radius && radialSegments) {
|
|
84
88
|
const { geometryIn } = dataIn;
|
|
85
89
|
let mesh = this.getMorph();
|
|
@@ -115,7 +115,15 @@ ZincObject.prototype.getRegion = function() {
|
|
|
115
115
|
*
|
|
116
116
|
* @return {Object}
|
|
117
117
|
*/
|
|
118
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Request the scene to draw the next frame, this is used when render on
|
|
120
|
+
* demand is enabled. See {@link Renderer#setRenderOnDemand}.
|
|
121
|
+
*/
|
|
122
|
+
ZincObject.prototype.requestRender = function() {
|
|
123
|
+
this.region?.getScene?.()?.invalidate?.();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
ZincObject.prototype.getMorph = function() {
|
|
119
127
|
const morph = this._lod.getCurrentMorph();
|
|
120
128
|
return morph ? morph : this.morph;
|
|
121
129
|
}
|
|
@@ -159,6 +167,7 @@ ZincObject.prototype.checkTransparentMesh = function() {
|
|
|
159
167
|
* time dependent.
|
|
160
168
|
*/
|
|
161
169
|
ZincObject.prototype.setMesh = function(mesh, localTimeEnabled, localMorphColour) {
|
|
170
|
+
this.requestRender();
|
|
162
171
|
//Note: we assume all layers are consistent with time frame
|
|
163
172
|
//Thus adding them to the same animation group should work.
|
|
164
173
|
//This step is only required for the primary (level 0) mesh.
|
|
@@ -267,6 +276,7 @@ ZincObject.prototype.getCurrentTime = function() {
|
|
|
267
276
|
* @param {Number} time - Can be any value between 0 to duration.
|
|
268
277
|
*/
|
|
269
278
|
ZincObject.prototype.setMorphTime = function(time) {
|
|
279
|
+
this.requestRender();
|
|
270
280
|
let timeChanged = false;
|
|
271
281
|
if (this.clipAction) {
|
|
272
282
|
const ratio = time / this.duration;
|
|
@@ -293,7 +303,8 @@ ZincObject.prototype.setMorphTime = function(time) {
|
|
|
293
303
|
}
|
|
294
304
|
}
|
|
295
305
|
if (timeChanged) {
|
|
296
|
-
this.
|
|
306
|
+
if (this.hasMorphPositions())
|
|
307
|
+
this.boundingBoxUpdateRequired = true;
|
|
297
308
|
this._lod.updateMorphColorAttribute(true);
|
|
298
309
|
if (this.timeEnabled)
|
|
299
310
|
this.markerUpdateRequired = true;
|
|
@@ -325,6 +336,7 @@ ZincObject.prototype.getVisibility = function() {
|
|
|
325
336
|
* @param {Boolean} visible - a boolean flag indicate the visibility to be set
|
|
326
337
|
*/
|
|
327
338
|
ZincObject.prototype.setVisibility = function(visible) {
|
|
339
|
+
this.requestRender();
|
|
328
340
|
if (visible !== this.visible) {
|
|
329
341
|
this.visible = visible;
|
|
330
342
|
this.group.visible = visible;
|
|
@@ -340,6 +352,7 @@ ZincObject.prototype.setVisibility = function(visible) {
|
|
|
340
352
|
* can be any value between from 0 to 1.0.
|
|
341
353
|
*/
|
|
342
354
|
ZincObject.prototype.setAlpha = function(alpha) {
|
|
355
|
+
this.requestRender();
|
|
343
356
|
const material = this._lod._material;
|
|
344
357
|
let isTransparent = false;
|
|
345
358
|
if (alpha < 1.0)
|
|
@@ -357,6 +370,7 @@ ZincObject.prototype.setAlpha = function(alpha) {
|
|
|
357
370
|
* @param {Boolean} flag - Set frustrum culling on/off based on this flag.
|
|
358
371
|
*/
|
|
359
372
|
ZincObject.prototype.setFrustumCulled = function(flag) {
|
|
373
|
+
this.requestRender();
|
|
360
374
|
//multilayers - set for all layers
|
|
361
375
|
this._lod.setFrustumCulled(flag);
|
|
362
376
|
}
|
|
@@ -368,6 +382,7 @@ ZincObject.prototype.setFrustumCulled = function(flag) {
|
|
|
368
382
|
* @param {Boolean} vertexColors - Set display with vertex color on/off.
|
|
369
383
|
*/
|
|
370
384
|
ZincObject.prototype.setVertexColors = function(vertexColors) {
|
|
385
|
+
this.requestRender();
|
|
371
386
|
//multilayers - set for all
|
|
372
387
|
this._lod.setVertexColors(vertexColors);
|
|
373
388
|
|
|
@@ -390,6 +405,7 @@ ZincObject.prototype.getColour = function() {
|
|
|
390
405
|
* @param {THREE.Color} colour - Colour to be set for this geometry.
|
|
391
406
|
*/
|
|
392
407
|
ZincObject.prototype.setColour = function(colour) {
|
|
408
|
+
this.requestRender();
|
|
393
409
|
this._lod.setColour(colour);
|
|
394
410
|
}
|
|
395
411
|
|
|
@@ -399,6 +415,7 @@ ZincObject.prototype.setColour = function(colour) {
|
|
|
399
415
|
* @param {THREE.Color} colour - Colour to be set for this geometry.
|
|
400
416
|
*/
|
|
401
417
|
ZincObject.prototype.setGreyScale = function(flag) {
|
|
418
|
+
this.requestRender();
|
|
402
419
|
if (flag) {
|
|
403
420
|
if (!this.origColour) {
|
|
404
421
|
if (this._lod._material) {
|
|
@@ -439,6 +456,7 @@ ZincObject.prototype.getColourHex = function() {
|
|
|
439
456
|
* @param {String} hex - The colour value in hex form.
|
|
440
457
|
*/
|
|
441
458
|
ZincObject.prototype.setColourHex = function(hex) {
|
|
459
|
+
this.requestRender();
|
|
442
460
|
this._lod._material.color.setHex(hex);
|
|
443
461
|
if (this._lod._secondaryMaterial) {
|
|
444
462
|
this._lod._secondaryMaterial.color.setHex(hex);
|
|
@@ -451,6 +469,7 @@ ZincObject.prototype.setColourHex = function(hex) {
|
|
|
451
469
|
* @param {String} colour - The colour value in rgb form.
|
|
452
470
|
*/
|
|
453
471
|
ZincObject.prototype.setEmissiveRGB = function(colour) {
|
|
472
|
+
this.requestRender();
|
|
454
473
|
if (this._lod._material && this._lod._material.emissive) {
|
|
455
474
|
this._lod._material.emissive.setRGB(...colour);
|
|
456
475
|
}
|
|
@@ -466,6 +485,7 @@ ZincObject.prototype.setEmissiveRGB = function(colour) {
|
|
|
466
485
|
* @param {THREE.Material} material - Material to be set for this geometry.
|
|
467
486
|
*/
|
|
468
487
|
ZincObject.prototype.setMaterial = function(material) {
|
|
488
|
+
this.requestRender();
|
|
469
489
|
this._lod.setMaterial(material);
|
|
470
490
|
}
|
|
471
491
|
|
|
@@ -486,10 +506,8 @@ ZincObject.prototype.getClosestVertexIndex = function() {
|
|
|
486
506
|
let currentDistance = 0;
|
|
487
507
|
for (let i = 0; i < position.count; i++) {
|
|
488
508
|
this._v2.fromArray(position.array, i * 3);
|
|
489
|
-
currentDistance = this._v2.
|
|
490
|
-
if (distance == -1)
|
|
491
|
-
distance = currentDistance;
|
|
492
|
-
else if (distance > (currentDistance)) {
|
|
509
|
+
currentDistance = this._v2.distanceToSquared(this._v1);
|
|
510
|
+
if ((distance == -1) || (distance > currentDistance)) {
|
|
493
511
|
distance = currentDistance;
|
|
494
512
|
closestIndex = i;
|
|
495
513
|
}
|
|
@@ -592,6 +610,44 @@ ZincObject.prototype.markerIsRequired = function(options) {
|
|
|
592
610
|
return false;
|
|
593
611
|
}
|
|
594
612
|
|
|
613
|
+
//geometry -> whether its morph targets move the vertices
|
|
614
|
+
const morphPositionsCache = new WeakMap();
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Check if the vertices positions change over time, only then will
|
|
618
|
+
* the bounding box change during playback.
|
|
619
|
+
*
|
|
620
|
+
* @return {Boolean}
|
|
621
|
+
*/
|
|
622
|
+
ZincObject.prototype.hasMorphPositions = function() {
|
|
623
|
+
const geometry = this.getMorph()?.geometry;
|
|
624
|
+
const morphPositions = geometry?.morphAttributes?.position;
|
|
625
|
+
if (!morphPositions || morphPositions.length === 0)
|
|
626
|
+
return false;
|
|
627
|
+
const cached = morphPositionsCache.get(geometry);
|
|
628
|
+
if (cached && cached.morphPositions === morphPositions)
|
|
629
|
+
return cached.result;
|
|
630
|
+
//Colour only morphs use placeholder targets identical to the base
|
|
631
|
+
//positions, these never move the vertices.
|
|
632
|
+
const basePositions = geometry.getAttribute('position')?.array;
|
|
633
|
+
let result = false;
|
|
634
|
+
for (let i = 0; i < morphPositions.length && !result; i++) {
|
|
635
|
+
const array = morphPositions[i].array;
|
|
636
|
+
if (!basePositions || array.length !== basePositions.length) {
|
|
637
|
+
result = true;
|
|
638
|
+
} else if (array !== basePositions) {
|
|
639
|
+
for (let j = 0; j < array.length; j++) {
|
|
640
|
+
if (array[j] !== basePositions[j]) {
|
|
641
|
+
result = true;
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
morphPositionsCache.set(geometry, { morphPositions, result });
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
650
|
+
|
|
595
651
|
/**
|
|
596
652
|
* Update the marker's position and size based on current viewport.
|
|
597
653
|
*/
|
|
@@ -610,6 +666,7 @@ ZincObject.prototype.updateMarker = function(playAnimation, options) {
|
|
|
610
666
|
if (position) {
|
|
611
667
|
this.marker.setPosition(position.x, position.y, position.z);
|
|
612
668
|
this.markerUpdateRequired = false;
|
|
669
|
+
ndcToBeUpdated = true;
|
|
613
670
|
}
|
|
614
671
|
}
|
|
615
672
|
if (!this.marker.isEnabled()) {
|
|
@@ -627,8 +684,9 @@ ZincObject.prototype.updateMarker = function(playAnimation, options) {
|
|
|
627
684
|
} else {
|
|
628
685
|
this.marker.setDefaultSprite();
|
|
629
686
|
}
|
|
630
|
-
|
|
631
|
-
|
|
687
|
+
//Only update the screen position when the camera or the
|
|
688
|
+
//marker has moved, or the marker has just been enabled.
|
|
689
|
+
if (options && options.camera && ndcToBeUpdated) {
|
|
632
690
|
this.marker.updateNDC(options.camera.cameraObject);
|
|
633
691
|
options.markerCluster.markerUpdateRequired = true;
|
|
634
692
|
}
|
|
@@ -637,7 +695,7 @@ ZincObject.prototype.updateMarker = function(playAnimation, options) {
|
|
|
637
695
|
if (this.marker && this.marker.isEnabled()) {
|
|
638
696
|
this.marker.disable();
|
|
639
697
|
this.group.remove(this.marker.morph);
|
|
640
|
-
if (options
|
|
698
|
+
if (options?.markersList &&
|
|
641
699
|
(this.marker.uuid in options.markersList)) {
|
|
642
700
|
options.markerCluster.markerUpdateRequired = true;
|
|
643
701
|
delete options.markersList[this.marker.uuid];
|
|
@@ -661,6 +719,7 @@ ZincObject.prototype.initiateMorphColor = function() {
|
|
|
661
719
|
}
|
|
662
720
|
|
|
663
721
|
ZincObject.prototype.setRenderOrder = function(renderOrder) {
|
|
722
|
+
this.requestRender();
|
|
664
723
|
//multiilayers
|
|
665
724
|
this._lod.setRenderOrder(renderOrder);
|
|
666
725
|
}
|
|
@@ -699,6 +758,7 @@ ZincObject.prototype.getClosestVertexDOMElementCoords = function(scene) {
|
|
|
699
758
|
* @return {Boolean}
|
|
700
759
|
*/
|
|
701
760
|
ZincObject.prototype.setMarkerMode = function(mode, options) {
|
|
761
|
+
this.requestRender();
|
|
702
762
|
if (mode !== this.markerMode) {
|
|
703
763
|
if (mode === "on" || mode === "off") {
|
|
704
764
|
this.markerMode = mode;
|
|
@@ -733,7 +793,9 @@ ZincObject.prototype.render = function(delta, playAnimation,
|
|
|
733
793
|
}
|
|
734
794
|
//multilayers
|
|
735
795
|
if (this.visible && delta != 0) {
|
|
736
|
-
|
|
796
|
+
//Only vertices morphing can change the bounding box
|
|
797
|
+
if (this.hasMorphPositions())
|
|
798
|
+
this.boundingBoxUpdateRequired = true;
|
|
737
799
|
if (this.morphColour == 1) {
|
|
738
800
|
this._lod.updateMorphColorAttribute(true);
|
|
739
801
|
}
|
|
@@ -753,6 +815,7 @@ ZincObject.prototype.addLOD = function(loader, level, url, index, preload) {
|
|
|
753
815
|
* Add lod from an url into the lod object.
|
|
754
816
|
*/
|
|
755
817
|
ZincObject.prototype.addVertices = function(coords) {
|
|
818
|
+
this.requestRender();
|
|
756
819
|
let mesh = this.getMorph();
|
|
757
820
|
let geometry = undefined;
|
|
758
821
|
if (!mesh) {
|
|
@@ -780,6 +843,7 @@ ZincObject.prototype.addVertices = function(coords) {
|
|
|
780
843
|
* Add lod from an url into the lod object.
|
|
781
844
|
*/
|
|
782
845
|
ZincObject.prototype.deleteVertices = function(index) {
|
|
846
|
+
this.requestRender();
|
|
783
847
|
let mesh = this.getMorph();
|
|
784
848
|
if (mesh?.geometry && this.drawRange >= index) {
|
|
785
849
|
if (removeVertexAtIndex(mesh.geometry, index, true)) {
|
|
@@ -798,6 +862,7 @@ ZincObject.prototype.deleteVertices = function(index) {
|
|
|
798
862
|
* Set the objects position.
|
|
799
863
|
*/
|
|
800
864
|
ZincObject.prototype.setPosition = function(x, y, z) {
|
|
865
|
+
this.requestRender();
|
|
801
866
|
const group = this.getGroup();
|
|
802
867
|
if (group) {
|
|
803
868
|
group.position.set(x, y, z);
|
|
@@ -817,6 +882,7 @@ ZincObject.prototype.loadAdditionalSources = function(primitivesLoader, sources)
|
|
|
817
882
|
* Set the objects scale.
|
|
818
883
|
*/
|
|
819
884
|
ZincObject.prototype.setScaleAll = function(scale) {
|
|
885
|
+
this.requestRender();
|
|
820
886
|
const group = this.getGroup();
|
|
821
887
|
if (group) {
|
|
822
888
|
group.scale.set(scale, scale, scale);
|