zincjs 2.4.1-beta.4 → 2.4.1-beta.6

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.
@@ -1,6 +1,7 @@
1
1
  import * as THREE from 'three/webgpu';
2
2
  import { Glyph } from './glyph';
3
3
  import { ZincObject } from './zincObject';
4
+ import { updateWorldMatrixFromAncestors } from '../utilities';
4
5
  import { JSONLoader } from '../loaders/JSONLoader';
5
6
  import { createGlyphTransformCompute, dispatchAndReadbackGlyphTransform, readbackGlyphTransform } from '../tsl/glyphTransform';
6
7
  import { createGlyphInstancedMaterial } from '../tsl/glyphRenderMaterial';
@@ -71,6 +72,9 @@ const Glyphset = function () {
71
72
  // for ACCURATE_RESYNC_DEBOUNCE_MS of quiet.
72
73
  let accurateResyncTimer = undefined;
73
74
  const ACCURATE_RESYNC_DEBOUNCE_MS = 500;
75
+ //Set to false when the static (non morphing) transformation needs to be
76
+ //re-applied, e.g. after a scale change.
77
+ let staticTransformationApplied = false;
74
78
  for (let i = 0; i < 8; i++) {
75
79
  _points[i] = new THREE.Vector3();
76
80
  }
@@ -443,6 +447,7 @@ const Glyphset = function () {
443
447
  * completely unchanged downstream.
444
448
  */
445
449
  const applyGlyphComputeResult = (result) => {
450
+ this.requestRender();
446
451
  const matrixArray = this.morph.instanceMatrix.array;
447
452
  const updateLabels = this.canShowLabel();
448
453
  for (let i = 0; i < numberOfVertices; i++) {
@@ -543,6 +548,7 @@ const Glyphset = function () {
543
548
  * all, bouding box will not be updated.
544
549
  */
545
550
  const dispatchGlyphComputeFast = (bottom_frame, top_frame, proportion) => {
551
+ this.requestRender();
546
552
  const renderer = this.region?.getScene?.()?.getRenderer?.();
547
553
  if (!renderer) return false;
548
554
  glyphCompute.uniforms.bottomFrame.value = bottom_frame;
@@ -666,8 +672,13 @@ const Glyphset = function () {
666
672
  current_axis3s = axis3s["0"];
667
673
  current_scales = scales["0"];
668
674
  }
669
- updateGlyphsetTransformation(current_positions, current_axis1s, current_axis2s, current_axis3s,
670
- current_scales);
675
+ //Colour only morphing does not change the transformation, skip it
676
+ //unless it is out of date.
677
+ if (morphVertices || !staticTransformationApplied) {
678
+ updateGlyphsetTransformation(current_positions, current_axis1s, current_axis2s, current_axis3s,
679
+ current_scales);
680
+ staticTransformationApplied = !morphVertices;
681
+ }
671
682
  if (colors != undefined) {
672
683
  if (morphColours) {
673
684
  const bottom_colors = colors[bottom_frame.toString()];
@@ -713,6 +724,7 @@ const Glyphset = function () {
713
724
  * Display the label of the glyphs in the glyphset.
714
725
  */
715
726
  this.showLabel = () => {
727
+ this.requestRender();
716
728
  if (glyphList?.length) {
717
729
  labelsOn = true;
718
730
  for (let i = 0; i < glyphList.length; i++) {
@@ -725,6 +737,7 @@ const Glyphset = function () {
725
737
  * Hide label with the choosen colour.
726
738
  */
727
739
  this.hideLabel = () => {
740
+ this.requestRender();
728
741
  for (let i = 0; i < glyphList.length; i++) {
729
742
  glyphList[i].hideLabel();
730
743
  }
@@ -804,6 +817,7 @@ const Glyphset = function () {
804
817
  //Update the transformation of the glyphs.
805
818
  updateGlyphsetTransformation(positions["0"], axis1s["0"],
806
819
  axis2s["0"], axis3s["0"], scales["0"]);
820
+ staticTransformationApplied = true;
807
821
  if (colors != undefined) {
808
822
  updateGlyphsetHexColors(colors["0"], !!(glyphCompute && glyphCompute.outputs.color));
809
823
  }
@@ -819,6 +833,7 @@ const Glyphset = function () {
819
833
  * @param {Glyph} Glyph to be added.
820
834
  */
821
835
  this.addCustomGlyph = glyph => {
836
+ this.requestRender();
822
837
  if (glyph.isGlyph)
823
838
  glyphList.push(glyph);
824
839
  this.ready = true;
@@ -832,6 +847,7 @@ const Glyphset = function () {
832
847
  * @param {Number} id of the mesh.
833
848
  */
834
849
  this.addMeshAsGlyph = (mesh, id) => {
850
+ this.requestRender();
835
851
  if (mesh.isMesh) {
836
852
  const glyph = new Glyph(undefined, undefined, id, this);
837
853
  glyph.fromMesh(mesh);
@@ -944,8 +960,7 @@ const Glyphset = function () {
944
960
  if (this.morph && this.ready && this.morph.visible) {
945
961
  if (glyphCompute && !boundsAreExact && allFramesBoundingBox) {
946
962
  this.cachedBoundingBox.copy(allFramesBoundingBox);
947
- this.morph.updateWorldMatrix(true, true);
948
- this.cachedBoundingBox.applyMatrix4(this.morph.matrixWorld);
963
+ this.cachedBoundingBox.applyMatrix4(updateWorldMatrixFromAncestors(this.morph));
949
964
  return this.cachedBoundingBox;
950
965
  }
951
966
  if (this.boundingBoxUpdateRequired) {
@@ -962,8 +977,7 @@ const Glyphset = function () {
962
977
  }
963
978
  if (_boundingBox3) {
964
979
  this.cachedBoundingBox.copy(_boundingBox3);
965
- this.morph.updateWorldMatrix(true, true);
966
- this.cachedBoundingBox.applyMatrix4(this.morph.matrixWorld);
980
+ this.cachedBoundingBox.applyMatrix4(updateWorldMatrixFromAncestors(this.morph));
967
981
  this.boundingBoxUpdateRequired = false;
968
982
  } else
969
983
  return undefined;
@@ -979,6 +993,7 @@ const Glyphset = function () {
979
993
  * @param {Number} time - Can be any value between 0 to duration.
980
994
  */
981
995
  this.setMorphTime = time => {
996
+ this.requestRender();
982
997
  if (time > this.duration)
983
998
  this.inbuildTime = this.duration;
984
999
  else if (0 > time)
@@ -1027,8 +1042,7 @@ const Glyphset = function () {
1027
1042
  const renderer = this.region?.getScene?.()?.getRenderer?.();
1028
1043
  if (!renderer) return;
1029
1044
  renderer.compute(glyphCompute.compute);
1030
- const colorResult = new Float32Array(
1031
- await renderer.getArrayBufferAsync(glyphCompute.outputs.color.value));
1045
+ const colorResult = (await readbackGlyphTransform(renderer, glyphCompute)).color;
1032
1046
  // setColorAt(0, ...) is only here to lazily allocate instanceColor the
1033
1047
  // same way the stock InstancedMesh API would; the loop below overwrites
1034
1048
  // every instance (including 0) with the real snapshot right after.
@@ -1062,7 +1076,9 @@ const Glyphset = function () {
1062
1076
  * @return {THREE.Box3}.
1063
1077
  */
1064
1078
  this.setScaleAll = function(scale) {
1079
+ this.requestRender();
1065
1080
  this.globalScale = scale;
1081
+ staticTransformationApplied = false;
1066
1082
  updateMorphGlyphsets(false);
1067
1083
  }
1068
1084
 
@@ -1098,12 +1114,13 @@ const Glyphset = function () {
1098
1114
  /**
1099
1115
  * Update the glyphsets if required the render.
1100
1116
  */
1101
- this.render = (delta, playAnimation, options) => {
1117
+ this.render = (delta, playAnimation, cameraControls, options) => {
1102
1118
  if (glyphCompute && !renderBuffersInitialized) {
1103
1119
  const renderer = this.region?.getScene?.()?.getRenderer?.();
1104
1120
  if (renderer) {
1105
1121
  renderer.compute(glyphCompute.compute);
1106
1122
  renderBuffersInitialized = true;
1123
+ this.requestRender();
1107
1124
  }
1108
1125
  }
1109
1126
  if (playAnimation == true) {
@@ -1,6 +1,9 @@
1
- import * as THREE from 'three/webgpu';
2
- import SpriteTextModule from 'three-spritetext';
3
- const SpriteText = SpriteTextModule.default || SpriteTextModule;
1
+ import {
2
+ applyTextSpriteTextureSettings,
3
+ createTextSprite,
4
+ releaseTextSprite,
5
+ setTextSpriteHeight,
6
+ } from '../textSprite';
4
7
 
5
8
  /**
6
9
  * Bitmap labels, this is used with {@link Glyph} to
@@ -21,25 +24,16 @@ const Label = function (textIn, colourIn) {
21
24
  let size = 1.0;
22
25
  let fontWeight = 500;
23
26
  const textHeight = 0.012;
24
- if (colourIn)
25
- sprite = new SpriteText(text, textHeight, colourIn.getStyle());
26
- else
27
- sprite = new SpriteText(text, textHeight);
28
- sprite.fontFace = "Asap";
29
- sprite.fontSize = 90;
30
- sprite.fontWeight = fontWeight;
31
- const canvasTexture = sprite.material.map; // Snag the canvas texture generated by the library
32
- sprite.material = new THREE.SpriteNodeMaterial({
33
- map: canvasTexture,
34
- });
35
- sprite.material.map.generateMipmaps = true;
36
- sprite.material.map.anisotropy = 4;
37
- sprite.material.minFilter = THREE.LinearMipmapLinearFilter; // Smooth downscaling
38
- sprite.material.magFilter = THREE.LinearFilter;
39
- sprite.material.sizeAttenuation = false;
27
+ //The canvas resolution is chosen from the size of the text on screen
28
+ sprite = createTextSprite(text, textHeight,
29
+ colourIn ? colourIn.getStyle() : undefined, "Asap", fontWeight);
40
30
  sprite.center.x = -0.05;
41
31
  sprite.center.y = 0;
42
-
32
+ //SpriteText replaces the texture whenever the text, colour or size
33
+ //changes, the settings need to be re-applied to the new texture.
34
+ const applyTextureSettings = () => {
35
+ applyTextSpriteTextureSettings(sprite);
36
+ }
43
37
 
44
38
 
45
39
  /**
@@ -78,7 +72,13 @@ const Label = function (textIn, colourIn) {
78
72
  */
79
73
  this.setColour = colourIn => {
80
74
  if (colourIn) {
81
- sprite.color = colourIn.getStyle();
75
+ //Changing the colour redraws the canvas and creates a new texture,
76
+ //only do it when the colour has changed.
77
+ const style = colourIn.getStyle();
78
+ if (style !== sprite.color) {
79
+ sprite.color = style;
80
+ applyTextureSettings();
81
+ }
82
82
  colour = colourIn;
83
83
  }
84
84
  }
@@ -111,7 +111,8 @@ const Label = function (textIn, colourIn) {
111
111
  */
112
112
  this.setSize = sizeIn => {
113
113
  if (sizeIn > 0.0) {
114
- sprite.textHeight = textHeight * sizeIn;
114
+ //Redraw at the resolution matching the new size
115
+ setTextSpriteHeight(sprite, textHeight * sizeIn);
115
116
  size = sizeIn;
116
117
  }
117
118
  }
@@ -124,6 +125,7 @@ const Label = function (textIn, colourIn) {
124
125
  this.setFontWeight = fontWeightIn => {
125
126
  if (fontWeightIn && fontWeightIn !== fontWeight) {
126
127
  sprite.fontWeight = fontWeightIn;
128
+ applyTextureSettings();
127
129
  fontWeight = fontWeightIn;
128
130
  }
129
131
  }
@@ -149,9 +151,10 @@ const Label = function (textIn, colourIn) {
149
151
  sprite._canvas.height = 1;
150
152
  }
151
153
  sprite.text = textIn;
152
- sprite.textHeight = textHeight * size;
154
+ setTextSpriteHeight(sprite, textHeight * size);
153
155
  text = textIn;
154
156
  if (sprite.material && sprite.material.map) {
157
+ applyTextureSettings();
155
158
  sprite.material.map.needsUpdate = true;
156
159
  }
157
160
  }
@@ -170,7 +173,19 @@ const Label = function (textIn, colourIn) {
170
173
  * Free up the memory
171
174
  */
172
175
  this.dispose = () => {
173
- //sprite.dispose();
176
+ if (sprite) {
177
+ releaseTextSprite(sprite);
178
+ sprite.removeFromParent();
179
+ if (sprite.material) {
180
+ sprite.material.map?.dispose();
181
+ sprite.material.dispose();
182
+ }
183
+ //Release the canvas memory
184
+ if (sprite._canvas) {
185
+ sprite._canvas.width = 0;
186
+ sprite._canvas.height = 0;
187
+ }
188
+ }
174
189
  }
175
190
 
176
191
  /**
@@ -53,6 +53,7 @@ const Lines = function () {
53
53
  * @param {Number} width - Width of the lines.
54
54
  */
55
55
  this.setWidth = width => {
56
+ this.requestRender();
56
57
  if (this.morph && this.morph.material) {
57
58
  this.morph.material.linewidth = width;
58
59
  this.morph.material.needsUpdate = true;
@@ -67,6 +68,7 @@ const Lines = function () {
67
68
  * @param {Number} colour - A hex value of the colour for the points
68
69
  */
69
70
  this.addLines = (coords, colour) => {
71
+ this.requestRender();
70
72
  if (coords && coords.length > 0) {
71
73
  const geometry = this.addVertices(coords);
72
74
  let mesh = this.getMorph();
@@ -16,7 +16,70 @@ import { LineSegmentsGeometry } from '../three/line/LineSegmentsGeometry';
16
16
  const Lines2 = function () {
17
17
  Lines.call(this);
18
18
  this.isLines2 = true;
19
- let positions = new Array(300);
19
+ //Shared with the GPU buffer of the mesh, edits are made in place
20
+ let positions = new Float32Array(300);
21
+
22
+ //Grow the positions array if required, returns true if it has
23
+ //been reallocated.
24
+ const ensureCapacity = (length) => {
25
+ if (length > positions.length) {
26
+ //Each segment has two vertices, six values
27
+ const capacity = Math.ceil(Math.max(positions.length * 2, length) / 6) * 6;
28
+ const newPositions = new Float32Array(capacity);
29
+ newPositions.set(positions);
30
+ positions = newPositions;
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+
36
+ //Fill the unused part of the array with degenerate segments at coord
37
+ const fillUnused = (start, coord) => {
38
+ for (let index = start; index + 2 < positions.length; index += 3) {
39
+ positions[index] = coord[0];
40
+ positions[index + 1] = coord[1];
41
+ positions[index + 2] = coord[2];
42
+ }
43
+ }
44
+
45
+ //Update the line distances without allocating new buffers
46
+ const updateLineDistances = (mesh) => {
47
+ const geometry = mesh.geometry;
48
+ const distanceStart = geometry.attributes.instanceDistanceStart;
49
+ const instanceStart = geometry.attributes.instanceStart;
50
+ if (!distanceStart || distanceStart.data.array.length !== instanceStart.count * 2) {
51
+ mesh.computeLineDistances();
52
+ return;
53
+ }
54
+ const distances = distanceStart.data.array;
55
+ let total = 0;
56
+ for (let i = 0; i < instanceStart.count; i++) {
57
+ const offset = i * 6;
58
+ const dx = positions[offset + 3] - positions[offset];
59
+ const dy = positions[offset + 4] - positions[offset + 1];
60
+ const dz = positions[offset + 5] - positions[offset + 2];
61
+ distances[i * 2] = total;
62
+ total += Math.sqrt(dx * dx + dy * dy + dz * dz);
63
+ distances[i * 2 + 1] = total;
64
+ }
65
+ distanceStart.data.needsUpdate = true;
66
+ }
67
+
68
+ //Upload the positions after they have been changed
69
+ const updatePositions = (mesh, reallocated) => {
70
+ const instanceStart = mesh.geometry.getAttribute('instanceStart');
71
+ if (reallocated || !instanceStart || instanceStart.data.array !== positions) {
72
+ //Only happens when the capacity has been increased
73
+ mesh.geometry.setPositions(positions);
74
+ mesh.computeLineDistances();
75
+ } else {
76
+ instanceStart.data.needsUpdate = true;
77
+ updateLineDistances(mesh);
78
+ mesh.geometry.computeBoundingBox();
79
+ mesh.geometry.computeBoundingSphere();
80
+ }
81
+ this.boundingBoxUpdateRequired = true;
82
+ }
20
83
 
21
84
  /**
22
85
  * Create the line segements using geometry and material.
@@ -47,6 +110,7 @@ const Lines2 = function () {
47
110
  * @param {Number} width - Width of the lines.
48
111
  */
49
112
  this.setWidth = width => {
113
+ this.requestRender();
50
114
  if (this.morph && this.morph.material) {
51
115
  this.morph.material.linewidth = width;
52
116
  this.morph.material.needsUpdate = true;
@@ -57,12 +121,14 @@ const Lines2 = function () {
57
121
  * Add new vertices into the array
58
122
  */
59
123
  this.addVertices = function(coords) {
124
+ this.requestRender();
60
125
  if (coords && coords.length) {
61
126
  let mesh = this.getMorph();
62
127
  if (!mesh) {
63
128
  this.drawRange = 0;
64
129
  }
65
130
  let index = this.drawRange * 3;
131
+ const reallocated = ensureCapacity(index + coords.length * 3);
66
132
  coords.forEach(coord => {
67
133
  positions[index++] = coord[0];
68
134
  positions[index++] = coord[1];
@@ -71,19 +137,12 @@ const Lines2 = function () {
71
137
  });
72
138
  //fill the rest of the array.
73
139
  if (!mesh) {
74
- while (index < 300) {
75
- positions[index++] = coords[0][0];
76
- positions[index++] = coords[0][1];
77
- positions[index++] = coords[0][2];
140
+ fillUnused(index, coords[0]);
141
+ } else {
142
+ if (reallocated) {
143
+ fillUnused(index, coords[0]);
78
144
  }
79
- }
80
-
81
- if (mesh) {
82
- mesh.geometry.setPositions(positions);
83
- mesh.computeLineDistances();
84
- mesh.geometry.computeBoundingBox();
85
- mesh.geometry.computeBoundingSphere();
86
- this.boundingBoxUpdateRequired = true;
145
+ updatePositions(mesh, reallocated);
87
146
  }
88
147
  }
89
148
  return positions;
@@ -117,6 +176,7 @@ const Lines2 = function () {
117
176
  * Edit Vertice in index.
118
177
  */
119
178
  this.editVertices = function(coords, i) {
179
+ this.requestRender();
120
180
  if (coords && coords.length) {
121
181
  let mesh = this.getMorph();
122
182
  const maxIndex = i + coords.length - 1;
@@ -130,17 +190,8 @@ const Lines2 = function () {
130
190
  positions[index++] = coord[1];
131
191
  positions[index++] = coord[2];
132
192
  });
133
- index = this.drawRange * 3;
134
- while (index < 300) {
135
- positions[index++] = coords[0][0];
136
- positions[index++] = coords[0][1];
137
- positions[index++] = coords[0][2];
138
- }
139
- mesh.geometry.setPositions(positions);
140
- mesh.computeLineDistances();
141
- mesh.geometry.computeBoundingBox();
142
- mesh.geometry.computeBoundingSphere();
143
- this.boundingBoxUpdateRequired = true;
193
+ fillUnused(this.drawRange * 3, coords[0]);
194
+ updatePositions(mesh, false);
144
195
  }
145
196
  }
146
197
  return positions;
@@ -154,6 +205,7 @@ const Lines2 = function () {
154
205
  * @param {Number} colour - A hex value of the colour for the points
155
206
  */
156
207
  this.addLines = (coords, colour) => {
208
+ this.requestRender();
157
209
  if (coords && coords.length > 0) {
158
210
  this.addVertices(coords);
159
211
  let mesh = this.getMorph();
@@ -1,5 +1,5 @@
1
1
  import * as THREE from 'three/webgpu';
2
- import { toBufferGeometry, updateMorphColorAttribute } from '../utilities';
2
+ import { keepIndexType, toBufferGeometry, updateMorphColorAttribute } from '../utilities';
3
3
  import { LineSegments } from '../three/line/LineSegments';
4
4
 
5
5
  /**
@@ -34,6 +34,7 @@ const LOD = function (parent) {
34
34
  */
35
35
  this.addLevel = (object, distanceIn) => {
36
36
  if (object) {
37
+ keepIndexType(object.geometry);
37
38
  const distance = Math.abs(distanceIn);
38
39
  let l;
39
40
  for (l = 0; l < this.levels.length; l++) {
@@ -59,6 +60,7 @@ const LOD = function (parent) {
59
60
  */
60
61
  this.levelLoaded = (object, distanceIn) => {
61
62
  if (object) {
63
+ keepIndexType(object.geometry);
62
64
  const distance = Math.abs(distanceIn);
63
65
  for (let l = 0; l < this.levels.length; l++) {
64
66
  if (distance === this.levels[l].distance) {
@@ -70,6 +72,7 @@ const LOD = function (parent) {
70
72
  }
71
73
  }
72
74
  this.checkTransparentMesh();
75
+ this._parent?.requestRender?.();
73
76
  }
74
77
  }
75
78
 
@@ -288,10 +291,13 @@ const LOD = function (parent) {
288
291
  this._material = material;
289
292
  if (this._secondaryMaterial) {
290
293
  this._secondaryMaterial.dispose();
294
+ this._secondaryMaterial = undefined;
295
+ }
296
+ if (material.transparent || this.levels.some((level) => level.secondaryMesh)) {
297
+ this._secondaryMaterial = material.clone()
298
+ this._secondaryMaterial.side = THREE.FrontSide;
299
+ this._secondaryMaterial.transparent = true;
291
300
  }
292
- this._secondaryMaterial = material.clone()
293
- this._secondaryMaterial.side = THREE.FrontSide;
294
- this._secondaryMaterial.transparent = true;
295
301
  this.levels.forEach((level) => {
296
302
  if (level.morph) {
297
303
  level.morph.material = this._material;
@@ -384,6 +390,7 @@ const LOD = function (parent) {
384
390
  if (this._currentLevel != visibleIndex) {
385
391
  this._currentLevel = visibleIndex;
386
392
  this.checkTransparentMesh();
393
+ this._parent?.requestRender?.();
387
394
  }
388
395
  }
389
396
  }
@@ -2,9 +2,11 @@ import * as THREE from 'three/webgpu';
2
2
  import myImage from '../assets/mapMarker.svg';
3
3
  import { createNewSpriteText } from '../utilities';
4
4
  import { ZincObject } from './zincObject';
5
+ import { requestRenderAll } from '../renderRequests';
6
+ import { releaseTextSprite } from '../textSprite';
5
7
 
6
8
  const textureLoader = new THREE.TextureLoader();
7
- const texture = textureLoader.load(myImage);
9
+ const texture = textureLoader.load(myImage, requestRenderAll);
8
10
  texture.colorSpace = THREE.SRGBColorSpace;
9
11
  const size = [0.02, 0.03, 1];
10
12
  const spriteMaterial = new THREE.SpriteMaterial({
@@ -153,6 +155,7 @@ const Marker = function(zincObject) {
153
155
  userImage.crossOrigin = "anonymous"
154
156
  userImage.onload = () => {
155
157
  this.setImageForUserSprite(userImage, size);
158
+ this.parent?.requestRender?.();
156
159
  };
157
160
  userImage.src = url;
158
161
  } else {
@@ -173,6 +176,7 @@ const Marker = function(zincObject) {
173
176
  sprite = undefined;
174
177
  }
175
178
  if (label) {
179
+ releaseTextSprite(label);
176
180
  label.material.map.dispose();
177
181
  label.material.dispose();
178
182
  label = undefined;
@@ -188,6 +192,7 @@ const Marker = function(zincObject) {
188
192
  //remove label
189
193
  if (label) {
190
194
  this.morph.remove(label);
195
+ releaseTextSprite(label);
191
196
  label.material.map.dispose();
192
197
  label.material.dispose();
193
198
  label = undefined;
@@ -1,10 +1,12 @@
1
1
  import * as THREE from 'three/webgpu';
2
2
  import { ZincObject } from './zincObject';
3
+ import { requestRenderAll } from '../renderRequests';
4
+ import { releaseTextSprite } from '../textSprite';
3
5
  import mapMarkerOrange from '../assets/mapMarkerOrange.svg';
4
6
  import { createNewSpriteText } from '../utilities';
5
7
 
6
8
  const textureLoader = new THREE.TextureLoader();
7
- const texture = textureLoader.load(mapMarkerOrange);
9
+ const texture = textureLoader.load(mapMarkerOrange, requestRenderAll);
8
10
  texture.colorSpace = THREE.SRGBColorSpace;
9
11
  const size = [0.02, 0.03, 1];
10
12
  const spriteMaterial = new THREE.SpriteMaterial({
@@ -96,6 +98,7 @@ const MarkerCluster = function(sceneIn) {
96
98
  if (sprite.label === undefined || (number !== sprite.number)) {
97
99
  if (sprite.label) {
98
100
  sprite.group.remove(sprite.label);
101
+ releaseTextSprite(sprite.label);
99
102
  sprite.label.material.map.dispose();
100
103
  sprite.label.material.dispose();
101
104
  }
@@ -178,6 +181,7 @@ const MarkerCluster = function(sceneIn) {
178
181
  let clusters = [];
179
182
  getCluster({...this.markers}, clusters);
180
183
  drawClusters(clusters);
184
+ scene?.invalidate?.();
181
185
  start = Date.now();
182
186
  this.markerUpdateRequired = false;
183
187
  }