zincjs 3.0.1 → 3.0.3
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/build/zinc.js +5 -5
- package/build/zinc.js.map +1 -1
- package/package.json +1 -1
- package/src/primitives/lod.js +49 -46
- package/src/primitives/marker.js +5 -0
- package/src/primitives/markerCluster.js +5 -0
- package/src/primitives/textureSlides.js +14 -0
- package/src/primitives/tubeLines.js +22 -45
- package/src/renderer.js +20 -15
- package/src/scene.js +34 -15
- package/src/utilities.js +43 -0
package/package.json
CHANGED
package/src/primitives/lod.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import * as THREE from 'three/webgpu';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
keepIndexType,
|
|
4
|
+
extractVertices,
|
|
5
|
+
getTubeLinesGeometry,
|
|
6
|
+
toBufferGeometry,
|
|
7
|
+
updateMorphColorAttribute,
|
|
8
|
+
} from '../utilities';
|
|
3
9
|
import { LineSegments } from '../three/line/LineSegments';
|
|
4
10
|
|
|
5
11
|
/**
|
|
@@ -28,6 +34,9 @@ const LOD = function (parent) {
|
|
|
28
34
|
this._parent = parent;
|
|
29
35
|
//Levels loaded after dispose are discarded
|
|
30
36
|
this._disposed = false;
|
|
37
|
+
this._dirty = true;
|
|
38
|
+
this._bandMin = 0;
|
|
39
|
+
this._bandMax = -1;
|
|
31
40
|
|
|
32
41
|
/*
|
|
33
42
|
* Add a level of LOD at the specified distance
|
|
@@ -224,7 +233,7 @@ const LOD = function (parent) {
|
|
|
224
233
|
const options = {
|
|
225
234
|
localTimeEnabled: this._parent.timeEnabled,
|
|
226
235
|
localMorphColour: this._parent.morphColour,
|
|
227
|
-
isLines: this._parent.isLines,
|
|
236
|
+
isLines: this._parent.isLines || this._parent.isTubeLines,
|
|
228
237
|
};
|
|
229
238
|
const geometry = toBufferGeometry(geometryIn, options);
|
|
230
239
|
let mesh = undefined;
|
|
@@ -232,6 +241,15 @@ const LOD = function (parent) {
|
|
|
232
241
|
mesh = new THREE.Mesh(geometry, material);
|
|
233
242
|
} else if (this._parent.isLines) {
|
|
234
243
|
mesh = new LineSegments(geometry, material);
|
|
244
|
+
} else if (this._parent.isTubeLines) {
|
|
245
|
+
const { radius, radialSegments, smooth } = this._parent.getGeometryConfig();
|
|
246
|
+
const tubeGeometry = getTubeLinesGeometry(
|
|
247
|
+
extractVertices(geometry),
|
|
248
|
+
radius,
|
|
249
|
+
radialSegments,
|
|
250
|
+
smooth,
|
|
251
|
+
);
|
|
252
|
+
mesh = new THREE.Mesh(tubeGeometry, material);
|
|
235
253
|
}
|
|
236
254
|
mesh.userData = this._parent;
|
|
237
255
|
mesh.renderOrder = this._renderOrder;
|
|
@@ -348,50 +366,35 @@ const LOD = function (parent) {
|
|
|
348
366
|
/* Update layers based on the */
|
|
349
367
|
this.update = (camera, center) => {
|
|
350
368
|
const levels = this.levels;
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
//and set the closest lod to true if
|
|
381
|
-
//none is found
|
|
382
|
-
if (visibleIndex > -1) {
|
|
383
|
-
levels[i].morph.visible = false;
|
|
384
|
-
} else {
|
|
385
|
-
levels[i].morph.visible = true;
|
|
386
|
-
visibleIndex = i;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (this._currentLevel != visibleIndex) {
|
|
391
|
-
this._currentLevel = visibleIndex;
|
|
392
|
-
this.checkTransparentMesh();
|
|
393
|
-
this._parent?.requestRender?.();
|
|
394
|
-
}
|
|
369
|
+
const l = levels.length;
|
|
370
|
+
if (l < 2) return;
|
|
371
|
+
const distance = camera.cameraObject.position.distanceTo(center);
|
|
372
|
+
|
|
373
|
+
// Still in the same band and nothing new has loaded
|
|
374
|
+
if (!this._dirty && distance >= this._bandMin && distance < this._bandMax) return;
|
|
375
|
+
this._dirty = false;
|
|
376
|
+
|
|
377
|
+
// Furthest level whose threshold has been passed (levels are sorted by distance)
|
|
378
|
+
let target = -1;
|
|
379
|
+
while (target + 1 < l && distance >= levels[target + 1].distance) target++;
|
|
380
|
+
this._bandMin = target >= 0 ? levels[target].distance : -Infinity;
|
|
381
|
+
this._bandMax = target + 1 < l ? levels[target + 1].distance : Infinity;
|
|
382
|
+
|
|
383
|
+
if (target > -1 && !levels[target].morph) this.loadLevel(target);
|
|
384
|
+
|
|
385
|
+
// Show the nearest loaded level at or below target, else the nearest loaded one above
|
|
386
|
+
let visible = -1;
|
|
387
|
+
for (let i = target; i >= 0 && visible < 0; i--) if (levels[i].morph) visible = i;
|
|
388
|
+
for (let i = target + 1; i < l && visible < 0; i++) if (levels[i].morph) visible = i;
|
|
389
|
+
|
|
390
|
+
for (let i = 0; i < l; i++) {
|
|
391
|
+
if (levels[i].morph) levels[i].morph.visible = i === visible;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (this._currentLevel !== visible) {
|
|
395
|
+
this._currentLevel = visible;
|
|
396
|
+
this.checkTransparentMesh();
|
|
397
|
+
this._parent?.requestRender?.();
|
|
395
398
|
}
|
|
396
399
|
};
|
|
397
400
|
|
package/src/primitives/marker.js
CHANGED
|
@@ -52,6 +52,9 @@ const Marker = function (zincObject) {
|
|
|
52
52
|
let initialise = () => {
|
|
53
53
|
sprite = new THREE.Sprite(spriteMaterial);
|
|
54
54
|
sprite.center.set(0.5, 0);
|
|
55
|
+
//Culling sphere ignores sizeAttenuation: false, it may cull sprite
|
|
56
|
+
//and label independently
|
|
57
|
+
sprite.frustumCulled = false;
|
|
55
58
|
this.morph.add(sprite);
|
|
56
59
|
this.morph.position.set(0, 0, 0);
|
|
57
60
|
this.morph.renderOrder = 10000;
|
|
@@ -133,6 +136,7 @@ const Marker = function (zincObject) {
|
|
|
133
136
|
}
|
|
134
137
|
userSprite = new THREE.Sprite(userMaterial);
|
|
135
138
|
userSprite.center.set(0.5, 0);
|
|
139
|
+
userSprite.frustumCulled = false;
|
|
136
140
|
userSprite.scale.set(size[0], size[1], size[2]);
|
|
137
141
|
userSprite.userData = this;
|
|
138
142
|
this.setUserSprite();
|
|
@@ -201,6 +205,7 @@ const Marker = function (zincObject) {
|
|
|
201
205
|
if (!label && numberIn) {
|
|
202
206
|
label = createNewSpriteText(numberIn, 0.012, 'black', 'Asap', 120, 700);
|
|
203
207
|
label.renderOrder = 10001;
|
|
208
|
+
label.frustumCulled = false;
|
|
204
209
|
this.morph.add(label);
|
|
205
210
|
}
|
|
206
211
|
number = numberIn;
|
|
@@ -74,6 +74,9 @@ const MarkerCluster = function (sceneIn) {
|
|
|
74
74
|
const sprite = new THREE.Sprite(spriteMaterial);
|
|
75
75
|
sprite.clusterIndex = index;
|
|
76
76
|
sprite.center.set(0.5, 0);
|
|
77
|
+
//Culling sphere ignores sizeAttenuation: false, it may cull sprite
|
|
78
|
+
//and label independently
|
|
79
|
+
sprite.frustumCulled = false;
|
|
77
80
|
sprite.position.set(0, 0, 0);
|
|
78
81
|
sprite.renderOrder = 10000;
|
|
79
82
|
sprite.scale.set(size[0], size[1], size[2]);
|
|
@@ -102,6 +105,7 @@ const MarkerCluster = function (sceneIn) {
|
|
|
102
105
|
}
|
|
103
106
|
sprite.label = createNewSpriteText(number, 0.012, 'black', 'Asap', 120, 700);
|
|
104
107
|
sprite.label.renderOrder = 10001;
|
|
108
|
+
sprite.label.frustumCulled = false;
|
|
105
109
|
sprite.number = number;
|
|
106
110
|
sprite.group.add(sprite.label);
|
|
107
111
|
}
|
|
@@ -177,6 +181,7 @@ const MarkerCluster = function (sceneIn) {
|
|
|
177
181
|
const current = Date.now();
|
|
178
182
|
if (current - start > 500) {
|
|
179
183
|
let clusters = [];
|
|
184
|
+
//Make a shallow copy of the markers array
|
|
180
185
|
getCluster({ ...this.markers }, clusters);
|
|
181
186
|
drawClusters(clusters);
|
|
182
187
|
scene?.invalidate?.();
|
|
@@ -336,6 +336,20 @@ const TextureSlides = function (textureIn) {
|
|
|
336
336
|
return this.cachedBoundingBox;
|
|
337
337
|
};
|
|
338
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Get the normalised coordinates of a point in world coordinates.
|
|
341
|
+
* The returned values can be used as the value of {@link SLIDE_SETTINGS}.
|
|
342
|
+
* Values within [0, 1] are inside the texture box.
|
|
343
|
+
*
|
|
344
|
+
* @param {Array} position - World coordinates [x, y, z].
|
|
345
|
+
* @return {Array} - Normalised coordinates [x, y, z].
|
|
346
|
+
*/
|
|
347
|
+
this.getPositionInBox = (position) => {
|
|
348
|
+
const matrix = updateWorldMatrixFromAncestors(this.morph).clone().invert();
|
|
349
|
+
const vector = new THREE.Vector3(...position).applyMatrix4(matrix);
|
|
350
|
+
return vector.toArray();
|
|
351
|
+
};
|
|
352
|
+
|
|
339
353
|
this.applyTransformation = (rotation, position, scale) => {
|
|
340
354
|
this.requestRender();
|
|
341
355
|
const matrix = new THREE.Matrix4();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as THREE from 'three/webgpu';
|
|
2
|
-
import {
|
|
2
|
+
import { extractVertices, getTubeLinesGeometry } from '../utilities';
|
|
3
3
|
import { ZincObject } from './zincObject';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -31,13 +31,27 @@ const TubeLines = function () {
|
|
|
31
31
|
this.createLineSegment = (geometryIn, materialIn, options) => {
|
|
32
32
|
if (geometryIn && materialIn) {
|
|
33
33
|
dataIn = { geometryIn, materialIn, options };
|
|
34
|
-
const
|
|
34
|
+
const { radius, radialSegments, smooth } = geometryConfig;
|
|
35
|
+
const geometry = getTubeLinesGeometry(
|
|
36
|
+
extractVertices(geometryIn),
|
|
37
|
+
radius,
|
|
38
|
+
radialSegments,
|
|
39
|
+
smooth,
|
|
40
|
+
);
|
|
35
41
|
const material = new THREE.MeshStandardMaterial({ color: materialIn.color });
|
|
36
42
|
const mesh = new THREE.Mesh(geometry, material);
|
|
37
43
|
this.setMesh(mesh, options.localTimeEnabled, options.localMorphColour);
|
|
38
44
|
}
|
|
39
45
|
};
|
|
40
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Return the settings used for creating the tube line.
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
this.getGeometryConfig = () => {
|
|
52
|
+
return geometryConfig;
|
|
53
|
+
};
|
|
54
|
+
|
|
41
55
|
/**
|
|
42
56
|
* Set the width for the lines.
|
|
43
57
|
*
|
|
@@ -90,50 +104,13 @@ const TubeLines = function () {
|
|
|
90
104
|
mesh.geometry.dispose();
|
|
91
105
|
|
|
92
106
|
geometryConfig = Object.assign(geometryConfig, { radius, radialSegments });
|
|
93
|
-
mesh.geometry = getTubeLinesGeometry(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
* THREE.Vector3, since TubeGeometry/CatmullRomCurve3/LineCurve3 need
|
|
100
|
-
* actual Vector3 instances to work with, not a flat typed array.
|
|
101
|
-
*
|
|
102
|
-
* @param {THREE.BufferGeometry} geometry
|
|
103
|
-
* @returns {Array}
|
|
104
|
-
*/
|
|
105
|
-
const extractVertices = (geometry) => {
|
|
106
|
-
const position = geometry.getAttribute('position');
|
|
107
|
-
const vertices = [];
|
|
108
|
-
for (let i = 0; i < position.count; i++) {
|
|
109
|
-
vertices.push(new THREE.Vector3().fromBufferAttribute(position, i));
|
|
110
|
-
}
|
|
111
|
-
return vertices;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Get merged geometry from list of geometry vertices
|
|
116
|
-
*
|
|
117
|
-
* @param {Array} vertices - An array of THREE.Vector3 vertices.
|
|
118
|
-
* @returns {Object}
|
|
119
|
-
*/
|
|
120
|
-
const getTubeLinesGeometry = (vertices) => {
|
|
121
|
-
const { radius, radialSegments, smooth } = geometryConfig;
|
|
122
|
-
let finalGeometry;
|
|
123
|
-
if (smooth) {
|
|
124
|
-
const curve = new THREE.CatmullRomCurve3(vertices);
|
|
125
|
-
finalGeometry = new THREE.TubeGeometry(curve, vertices.length, radius, radialSegments, false);
|
|
126
|
-
} else {
|
|
127
|
-
const geometries = [];
|
|
128
|
-
for (let i = 0; i + 1 < vertices.length; i = i + 2) {
|
|
129
|
-
const curve = new THREE.LineCurve3(vertices[i], vertices[i + 1]);
|
|
130
|
-
const tubeGeometry = new THREE.TubeGeometry(curve, 1, radius, radialSegments, false);
|
|
131
|
-
geometries.push(tubeGeometry);
|
|
132
|
-
}
|
|
133
|
-
finalGeometry = mergeGeometries(geometries, true);
|
|
134
|
-
geometries.forEach((g) => g.dispose());
|
|
107
|
+
mesh.geometry = getTubeLinesGeometry(
|
|
108
|
+
extractVertices(geometryIn),
|
|
109
|
+
radius,
|
|
110
|
+
radialSegments,
|
|
111
|
+
geometryConfig.smooth,
|
|
112
|
+
);
|
|
135
113
|
}
|
|
136
|
-
return finalGeometry;
|
|
137
114
|
};
|
|
138
115
|
};
|
|
139
116
|
|
package/src/renderer.js
CHANGED
|
@@ -38,7 +38,6 @@ const Renderer = function (containerIn) {
|
|
|
38
38
|
let contextLostCallbackFunctions_id = 0;
|
|
39
39
|
let contextRestoredCallbackFunctions = {};
|
|
40
40
|
let contextRestoredCallbackFunctions_id = 0;
|
|
41
|
-
let animated_id = undefined;
|
|
42
41
|
let cameraOrtho = undefined,
|
|
43
42
|
sceneOrtho = undefined,
|
|
44
43
|
logoSprite = undefined;
|
|
@@ -179,6 +178,8 @@ const Renderer = function (containerIn) {
|
|
|
179
178
|
}
|
|
180
179
|
renderer = new THREE.WebGPURenderer(parameters);
|
|
181
180
|
await renderer.init();
|
|
181
|
+
//animate() may have been called before the renderer was ready
|
|
182
|
+
if (isRendering) renderer.setAnimationLoop(this.render);
|
|
182
183
|
//GPU glyph animation requires the WebGPU backend, the WebGL fallback
|
|
183
184
|
//cannot index storage buffers freely.
|
|
184
185
|
setGlyphComputeSupported(renderer.backend?.isWebGPUBackend === true);
|
|
@@ -378,22 +379,13 @@ const Renderer = function (containerIn) {
|
|
|
378
379
|
currentScene.updateDirectionalLight();
|
|
379
380
|
};
|
|
380
381
|
|
|
381
|
-
let runAnimation = () => {
|
|
382
|
-
if (isRendering) {
|
|
383
|
-
animated_id = requestAnimationFrame(runAnimation);
|
|
384
|
-
this.render();
|
|
385
|
-
} else {
|
|
386
|
-
cancelAnimationFrame(animated_id);
|
|
387
|
-
animated_id = undefined;
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
|
|
391
382
|
/**
|
|
392
383
|
* Stop the animation and renderer to get into the render loop.
|
|
393
384
|
*/
|
|
394
385
|
this.stopAnimate = () => {
|
|
395
386
|
if (isRendering) {
|
|
396
387
|
isRendering = false;
|
|
388
|
+
renderer?.setAnimationLoop(null);
|
|
397
389
|
}
|
|
398
390
|
};
|
|
399
391
|
|
|
@@ -405,7 +397,10 @@ const Renderer = function (containerIn) {
|
|
|
405
397
|
clock.reset();
|
|
406
398
|
isRendering = true;
|
|
407
399
|
needsRender = true;
|
|
408
|
-
|
|
400
|
+
//WebGPURenderer always runs its own requestAnimationFrame loop which
|
|
401
|
+
//updates the node frame and the per frame info, render from that loop
|
|
402
|
+
//instead of running a second one.
|
|
403
|
+
renderer?.setAnimationLoop(this.render);
|
|
409
404
|
}
|
|
410
405
|
};
|
|
411
406
|
|
|
@@ -646,7 +641,16 @@ const Renderer = function (containerIn) {
|
|
|
646
641
|
}
|
|
647
642
|
clock.update();
|
|
648
643
|
const delta = clock.getDelta();
|
|
649
|
-
|
|
644
|
+
//Objects are only updated on every frame when render on demand is off
|
|
645
|
+
//or the renderer itself has requested a frame, e.g. on resize
|
|
646
|
+
const forceUpdate = !renderOnDemand || needsRender;
|
|
647
|
+
let changed = currentScene.renderGeometries(
|
|
648
|
+
playRate,
|
|
649
|
+
delta,
|
|
650
|
+
this.playAnimation,
|
|
651
|
+
undefined,
|
|
652
|
+
forceUpdate,
|
|
653
|
+
);
|
|
650
654
|
if (additionalActiveScenes.length > 0) {
|
|
651
655
|
//Additional scenes are displayed with the current scene's camera
|
|
652
656
|
sharedCamera.controls = currentScene.getZincCameraControls();
|
|
@@ -654,7 +658,9 @@ const Renderer = function (containerIn) {
|
|
|
654
658
|
}
|
|
655
659
|
for (let i = 0; i < additionalActiveScenes.length; i++) {
|
|
656
660
|
const sceneItem = additionalActiveScenes[i];
|
|
657
|
-
if (
|
|
661
|
+
if (
|
|
662
|
+
sceneItem.renderGeometries(playRate, delta, this.playAnimation, sharedCamera, forceUpdate)
|
|
663
|
+
)
|
|
658
664
|
changed = true;
|
|
659
665
|
}
|
|
660
666
|
for (let key in preRenderCallbackFunctions) {
|
|
@@ -756,7 +762,6 @@ const Renderer = function (containerIn) {
|
|
|
756
762
|
* Dispose all memory allocated, this will effetively destroy all scenes.
|
|
757
763
|
*/
|
|
758
764
|
this.dispose = () => {
|
|
759
|
-
if (isRendering) cancelAnimationFrame(animated_id);
|
|
760
765
|
for (const key in sceneMap) {
|
|
761
766
|
if (sceneMap.hasOwnProperty(key)) {
|
|
762
767
|
sceneMap[key].clearAll();
|
package/src/scene.js
CHANGED
|
@@ -624,11 +624,25 @@ const Scene = function (containerIn, rendererIn) {
|
|
|
624
624
|
* Update geometries and glyphsets based on the calculated time.
|
|
625
625
|
* @private
|
|
626
626
|
*/
|
|
627
|
-
this.renderGeometries = (playRate, delta, playAnimation, sharedCamera) => {
|
|
627
|
+
this.renderGeometries = (playRate, delta, playAnimation, sharedCamera, forceUpdate) => {
|
|
628
628
|
//Anything requested since the last frame
|
|
629
629
|
let changed = needsRender;
|
|
630
630
|
needsRender = false;
|
|
631
631
|
cameraUpdated = false;
|
|
632
|
+
//These are plain properties, check if they have changed before
|
|
633
|
+
//the objects are updated so markers are toggled on this frame
|
|
634
|
+
if (
|
|
635
|
+
lastDisplayState.displayMarkers !== this.displayMarkers ||
|
|
636
|
+
lastDisplayState.displayMinimap !== this.displayMinimap ||
|
|
637
|
+
lastDisplayState.displayMiniAxes !== this.displayMiniAxes ||
|
|
638
|
+
lastDisplayState.playAnimation !== playAnimation
|
|
639
|
+
) {
|
|
640
|
+
lastDisplayState.displayMarkers = this.displayMarkers;
|
|
641
|
+
lastDisplayState.displayMinimap = this.displayMinimap;
|
|
642
|
+
lastDisplayState.displayMiniAxes = this.displayMiniAxes;
|
|
643
|
+
lastDisplayState.playAnimation = playAnimation;
|
|
644
|
+
changed = true;
|
|
645
|
+
}
|
|
632
646
|
//Additional active scenes are displayed with the current scene's camera
|
|
633
647
|
const cameraControls = sharedCamera ? sharedCamera.controls : zincCameraControls;
|
|
634
648
|
//Reused on every frame to avoid allocations
|
|
@@ -680,25 +694,30 @@ const Scene = function (containerIn, rendererIn) {
|
|
|
680
694
|
zincCameraControls.calculateHeightPerPixelAtZeroDepth(getDrawingHeight());
|
|
681
695
|
}
|
|
682
696
|
}
|
|
683
|
-
|
|
697
|
+
//Walking every object is costly for large scenes, only do it when
|
|
698
|
+
//something may have changed, LOD and markers depend on the camera
|
|
699
|
+
if (
|
|
700
|
+
forceUpdate ||
|
|
701
|
+
changed ||
|
|
702
|
+
options.ndcToBeUpdated ||
|
|
703
|
+
playAnimation ||
|
|
704
|
+
//Clusters are recalculated during the walk
|
|
705
|
+
(markerCluster.isEnabled() && markerCluster.markerUpdateRequired)
|
|
706
|
+
) {
|
|
707
|
+
rootRegion.renderGeometries(
|
|
708
|
+
playRate,
|
|
709
|
+
delta,
|
|
710
|
+
playAnimation,
|
|
711
|
+
cameraControls,
|
|
712
|
+
options,
|
|
713
|
+
true,
|
|
714
|
+
);
|
|
715
|
+
}
|
|
684
716
|
} else if (!sharedCamera && zincCameraControls.update(0)) {
|
|
685
717
|
changed = true;
|
|
686
718
|
cameraUpdated = true;
|
|
687
719
|
}
|
|
688
720
|
}
|
|
689
|
-
//These are plain properties, check if they have changed
|
|
690
|
-
if (
|
|
691
|
-
lastDisplayState.displayMarkers !== this.displayMarkers ||
|
|
692
|
-
lastDisplayState.displayMinimap !== this.displayMinimap ||
|
|
693
|
-
lastDisplayState.displayMiniAxes !== this.displayMiniAxes ||
|
|
694
|
-
lastDisplayState.playAnimation !== playAnimation
|
|
695
|
-
) {
|
|
696
|
-
lastDisplayState.displayMarkers = this.displayMarkers;
|
|
697
|
-
lastDisplayState.displayMinimap = this.displayMinimap;
|
|
698
|
-
lastDisplayState.displayMiniAxes = this.displayMiniAxes;
|
|
699
|
-
lastDisplayState.playAnimation = playAnimation;
|
|
700
|
-
changed = true;
|
|
701
|
-
}
|
|
702
721
|
//The flag is only cleared when the minimap is drawn
|
|
703
722
|
if (this.minimapScissor.updateRequired && (this.displayMinimap || this.displayMiniAxes)) {
|
|
704
723
|
changed = true;
|
package/src/utilities.js
CHANGED
|
@@ -31,6 +31,23 @@ function createNewURL(target, reference) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Read the position attribute of a BufferGeometry into an array of
|
|
36
|
+
* THREE.Vector3, since TubeGeometry/CatmullRomCurve3/LineCurve3 need
|
|
37
|
+
* actual Vector3 instances to work with, not a flat typed array.
|
|
38
|
+
*
|
|
39
|
+
* @param {THREE.BufferGeometry} geometry
|
|
40
|
+
* @returns {Array}
|
|
41
|
+
*/
|
|
42
|
+
const extractVertices = (geometry) => {
|
|
43
|
+
const position = geometry.getAttribute('position');
|
|
44
|
+
const vertices = [];
|
|
45
|
+
for (let i = 0; i < position.count; i++) {
|
|
46
|
+
vertices.push(new THREE.Vector3().fromBufferAttribute(position, i));
|
|
47
|
+
}
|
|
48
|
+
return vertices;
|
|
49
|
+
};
|
|
50
|
+
|
|
34
51
|
/*
|
|
35
52
|
* Compute the world matrix of an object from its ancestors and return it.
|
|
36
53
|
* three.js only recomputes world matrices flagged by matrixWorldNeedsUpdate,
|
|
@@ -85,6 +102,30 @@ function getBoundingBox(mesh, cachedBox, b1, v1, v2) {
|
|
|
85
102
|
cachedBox.applyMatrix4(updateWorldMatrixFromAncestors(mesh));
|
|
86
103
|
}
|
|
87
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Create tube line geometry based on lines geometry, radius, segments and smooth.
|
|
107
|
+
*
|
|
108
|
+
* @param {Array} vertices - An array of THREE.Vector3 vertices.
|
|
109
|
+
* @returns {Object}
|
|
110
|
+
*/
|
|
111
|
+
function getTubeLinesGeometry(vertices, radius, radialSegments, smooth) {
|
|
112
|
+
let finalGeometry;
|
|
113
|
+
if (smooth) {
|
|
114
|
+
const curve = new THREE.CatmullRomCurve3(vertices);
|
|
115
|
+
finalGeometry = new THREE.TubeGeometry(curve, vertices.length, radius, radialSegments, false);
|
|
116
|
+
} else {
|
|
117
|
+
const geometries = [];
|
|
118
|
+
for (let i = 0; i + 1 < vertices.length; i = i + 2) {
|
|
119
|
+
const curve = new THREE.LineCurve3(vertices[i], vertices[i + 1]);
|
|
120
|
+
const tubeGeometry = new THREE.TubeGeometry(curve, 1, radius, radialSegments, false);
|
|
121
|
+
geometries.push(tubeGeometry);
|
|
122
|
+
}
|
|
123
|
+
finalGeometry = mergeGeometries(geometries, true);
|
|
124
|
+
geometries.forEach((g) => g.dispose());
|
|
125
|
+
}
|
|
126
|
+
return finalGeometry;
|
|
127
|
+
}
|
|
128
|
+
|
|
88
129
|
//Convenient function
|
|
89
130
|
function loadExternalFile(url, data, callback, errorCallback) {
|
|
90
131
|
// Set up an asynchronous request
|
|
@@ -908,8 +949,10 @@ export {
|
|
|
908
949
|
createBufferGeometry,
|
|
909
950
|
createNewSpriteText,
|
|
910
951
|
createNewURL,
|
|
952
|
+
extractVertices,
|
|
911
953
|
getBoundingBox,
|
|
912
954
|
getCircularTexture,
|
|
955
|
+
getTubeLinesGeometry,
|
|
913
956
|
keepIndexType,
|
|
914
957
|
updateWorldMatrixFromAncestors,
|
|
915
958
|
useStandardIndexType,
|