zincjs 3.0.2 → 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/scene.js +8 -1
- 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/scene.js
CHANGED
|
@@ -704,7 +704,14 @@ const Scene = function (containerIn, rendererIn) {
|
|
|
704
704
|
//Clusters are recalculated during the walk
|
|
705
705
|
(markerCluster.isEnabled() && markerCluster.markerUpdateRequired)
|
|
706
706
|
) {
|
|
707
|
-
rootRegion.renderGeometries(
|
|
707
|
+
rootRegion.renderGeometries(
|
|
708
|
+
playRate,
|
|
709
|
+
delta,
|
|
710
|
+
playAnimation,
|
|
711
|
+
cameraControls,
|
|
712
|
+
options,
|
|
713
|
+
true,
|
|
714
|
+
);
|
|
708
715
|
}
|
|
709
716
|
} else if (!sharedCamera && zincCameraControls.update(0)) {
|
|
710
717
|
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,
|