zincjs 2.4.0 → 2.4.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/zinc.js +3 -486
- package/build/zinc.js.map +1 -1
- package/package.json +6 -7
- package/src/controls.js +1 -1
- package/src/geometryCSG.js +1 -1
- package/src/glyphsetCSG.js +1 -1
- package/src/loaders/GLTFToZincJSLoader.js +1 -1
- package/src/loaders/JSONLoader.js +216 -371
- package/src/loaders/OBJLoader.js +1 -1
- package/src/loaders/STLLoader.js +1 -1
- package/src/loaders/niftiReader.js +6 -4
- package/src/loaders/primitivesLoader.js +7 -9
- package/src/minimap.js +1 -1
- package/src/primitives/geometry.js +11 -29
- package/src/primitives/glyph.js +1 -1
- package/src/primitives/glyphset.js +2 -4
- package/src/primitives/label.js +1 -1
- package/src/primitives/lines.js +12 -5
- package/src/primitives/lines2.js +4 -8
- package/src/primitives/lod.js +9 -3
- package/src/primitives/marker.js +1 -1
- package/src/primitives/markerCluster.js +1 -1
- package/src/primitives/pointset.js +368 -52
- package/src/primitives/textureSlides.js +59 -16
- package/src/primitives/textureVolume.js +1 -1
- package/src/primitives/tubeLines.js +20 -3
- package/src/primitives/zincObject.js +13 -1
- package/src/region.js +1 -1
- package/src/renderer.js +36 -17
- package/src/scene.js +20 -8
- package/src/sceneLoader.js +1 -1
- package/src/shaders/rgbVolumeRender.js +1 -1
- package/src/shaders/textureSlide.js +1 -1
- package/src/texture/texture.js +1 -1
- package/src/texture/textureArray.js +9 -2
- package/src/three/GLTFExporter.js +55 -2
- package/src/three/InstancedPoints.js +73 -0
- package/src/three/Loader.js +1 -1
- package/src/three/line/Line.js +1 -1
- package/src/three/line/LineSegments.js +1 -1
- package/src/three/line/LineSegments2.js +24 -39
- package/src/three/line/LineSegmentsGeometry.js +1 -1
- package/src/tls/morphColorMaterial.js +65 -0
- package/src/tls/pointsMaterial.js +79 -0
- package/src/tls/textureSlides.js +126 -0
- package/src/utilities.js +47 -70
- package/src/videoHandler.js +1 -2
- package/src/workers/geometryCSG.worker.js +1 -1
- package/src/workers/geometryCSGInternal.js +1 -1
- package/src/zinc.js +1 -1
- package/vite.config.js +3 -1
- package/src/primitives/augmentShader.js +0 -45
- package/src/three/Geometry.js +0 -2176
- package/src/three/Points.js +0 -224
- package/src/three/line/LineMaterial.js +0 -726
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
1
|
+
import * as THREE from 'three/webgpu';
|
|
2
2
|
import { mergeGeometries } from '../utilities';
|
|
3
3
|
import { ZincObject } from './zincObject';
|
|
4
4
|
|
|
@@ -31,7 +31,7 @@ const TubeLines = function () {
|
|
|
31
31
|
this.createLineSegment = (geometryIn, materialIn, options) => {
|
|
32
32
|
if (geometryIn && materialIn) {
|
|
33
33
|
dataIn = { geometryIn, materialIn, options };
|
|
34
|
-
const geometry = getTubeLinesGeometry(geometryIn
|
|
34
|
+
const geometry = getTubeLinesGeometry(extractVertices(geometryIn));
|
|
35
35
|
const material = new THREE.MeshStandardMaterial({ color: materialIn.color });
|
|
36
36
|
const mesh = new THREE.Mesh(geometry, material);
|
|
37
37
|
this.setMesh(mesh, options.localTimeEnabled, options.localMorphColour);
|
|
@@ -86,10 +86,27 @@ const TubeLines = function () {
|
|
|
86
86
|
mesh.geometry.dispose();
|
|
87
87
|
|
|
88
88
|
geometryConfig = Object.assign(geometryConfig, { radius, radialSegments });
|
|
89
|
-
mesh.geometry = getTubeLinesGeometry(geometryIn
|
|
89
|
+
mesh.geometry = getTubeLinesGeometry(extractVertices(geometryIn));
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Read the position attribute of a BufferGeometry into an array of
|
|
95
|
+
* THREE.Vector3, since TubeGeometry/CatmullRomCurve3/LineCurve3 need
|
|
96
|
+
* actual Vector3 instances to work with, not a flat typed array.
|
|
97
|
+
*
|
|
98
|
+
* @param {THREE.BufferGeometry} geometry
|
|
99
|
+
* @returns {Array}
|
|
100
|
+
*/
|
|
101
|
+
const extractVertices = (geometry) => {
|
|
102
|
+
const position = geometry.getAttribute('position');
|
|
103
|
+
const vertices = [];
|
|
104
|
+
for (let i = 0; i < position.count; i++) {
|
|
105
|
+
vertices.push(new THREE.Vector3().fromBufferAttribute(position, i));
|
|
106
|
+
}
|
|
107
|
+
return vertices;
|
|
108
|
+
}
|
|
109
|
+
|
|
93
110
|
/**
|
|
94
111
|
* Get merged geometry from list of geometry vertices
|
|
95
112
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
1
|
+
import * as THREE from 'three/webgpu';
|
|
2
2
|
import {
|
|
3
3
|
createBufferGeometry,
|
|
4
4
|
getBoundingBox,
|
|
@@ -183,6 +183,10 @@ ZincObject.prototype.setMesh = function(mesh, localTimeEnabled, localMorphColour
|
|
|
183
183
|
this.clipAction.loop = THREE.LoopRepeat;
|
|
184
184
|
this.clipAction.clampWhenFinished = true;
|
|
185
185
|
this.clipAction.play();
|
|
186
|
+
//Evaluate the clip immediately so morphTargetInfluences reflects
|
|
187
|
+
//time 0 right away, rather than staying at its all-zero default
|
|
188
|
+
//until the first mixer.update() from playback/setMorphTime.
|
|
189
|
+
this.mixer.update(0);
|
|
186
190
|
}
|
|
187
191
|
}
|
|
188
192
|
}
|
|
@@ -200,6 +204,14 @@ ZincObject.prototype.setMesh = function(mesh, localTimeEnabled, localMorphColour
|
|
|
200
204
|
geometry.setAttribute('morphTarget1', geometry.getAttribute( 'position' ) );
|
|
201
205
|
}
|
|
202
206
|
}
|
|
207
|
+
if (this.morphColour) {
|
|
208
|
+
//Make sure morphColor0/morphColor1 exist before this mesh is ever
|
|
209
|
+
//rendered. WebGPU builds its pipeline against whatever attributes the
|
|
210
|
+
//geometry has at first render, and adding these two afterwards doesn't
|
|
211
|
+
//get picked up by an already-built pipeline - the object would render
|
|
212
|
+
//black forever after, since the colour shader can no longer see them.
|
|
213
|
+
this.initiateMorphColor();
|
|
214
|
+
}
|
|
203
215
|
this.boundingBoxUpdateRequired = true;
|
|
204
216
|
}
|
|
205
217
|
|
package/src/region.js
CHANGED
package/src/renderer.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
2
|
-
//import { WebGPURenderer } from 'three/webgpu';
|
|
1
|
+
import * as THREE from 'three/webgpu';
|
|
3
2
|
import { ResizeSensor } from 'css-element-queries';
|
|
4
3
|
import { Scene } from './scene';
|
|
5
4
|
/**
|
|
@@ -24,7 +23,7 @@ const Renderer = function (containerIn) {
|
|
|
24
23
|
let currentScene = undefined;
|
|
25
24
|
|
|
26
25
|
//myGezincGeometriestains a tuple of the threejs mesh, timeEnabled, morphColour flag, unique id and morph
|
|
27
|
-
const clock = new THREE.
|
|
26
|
+
const clock = new THREE.Timer();
|
|
28
27
|
this.playAnimation = true;
|
|
29
28
|
/* default animation update rate, rate is 1000 and duration
|
|
30
29
|
is default to 6000, 6s to finish a full animation */
|
|
@@ -77,8 +76,9 @@ const Renderer = function (containerIn) {
|
|
|
77
76
|
*/
|
|
78
77
|
this.onWindowResize = () => {
|
|
79
78
|
currentScene.onWindowResize();
|
|
80
|
-
|
|
81
|
-
const
|
|
79
|
+
//Give it a miniumum size of 1 x 1
|
|
80
|
+
const width = this.getDrawingWidth() || 1;
|
|
81
|
+
const height = this.getDrawingHeight() || 1;
|
|
82
82
|
if (renderer != undefined) {
|
|
83
83
|
let localRect = undefined;
|
|
84
84
|
if (container) {
|
|
@@ -109,7 +109,7 @@ const Renderer = function (containerIn) {
|
|
|
109
109
|
/**
|
|
110
110
|
* Initialise the renderer and its visualisations.
|
|
111
111
|
*/
|
|
112
|
-
this.initialiseVisualisation = parameters => {
|
|
112
|
+
this.initialiseVisualisation = async (parameters) => {
|
|
113
113
|
if (!isInitialised) {
|
|
114
114
|
parameters = parameters || {};
|
|
115
115
|
if (parameters['antialias'] === undefined) {
|
|
@@ -131,11 +131,26 @@ const Renderer = function (containerIn) {
|
|
|
131
131
|
container = undefined;
|
|
132
132
|
canvas = parameters["canvas"];
|
|
133
133
|
}
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
//
|
|
134
|
+
//WebGPURenderer otherwise requests a device with the default
|
|
135
|
+
//maxTextureArrayLayers (256 on many adapters), which is too low for
|
|
136
|
+
//some currnetly sypported scaffold. We will request the highest possible
|
|
137
|
+
//on the device
|
|
138
|
+
if (parameters.device === undefined && parameters.requiredLimits === undefined &&
|
|
139
|
+
typeof navigator !== 'undefined' && navigator.gpu) {
|
|
140
|
+
try {
|
|
141
|
+
const adapter = await navigator.gpu.requestAdapter({ powerPreference: parameters.powerPreference });
|
|
142
|
+
if (adapter) {
|
|
143
|
+
parameters.requiredLimits = { maxTextureArrayLayers: adapter.limits.maxTextureArrayLayers };
|
|
144
|
+
}
|
|
145
|
+
} catch (err) {
|
|
146
|
+
//Fall through and let WebGPURenderer's own adapter/device request
|
|
147
|
+
//use its defaults.
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
renderer = new THREE.WebGPURenderer(parameters);
|
|
151
|
+
await renderer.init();
|
|
137
152
|
|
|
138
|
-
renderer = new THREE.WebGLRenderer(parameters);
|
|
153
|
+
//renderer = new THREE.WebGLRenderer(parameters);
|
|
139
154
|
if (container !== undefined) {
|
|
140
155
|
container.appendChild( renderer.domElement );
|
|
141
156
|
}
|
|
@@ -208,10 +223,10 @@ const Renderer = function (containerIn) {
|
|
|
208
223
|
* @return {Zinc.Scene}
|
|
209
224
|
*/
|
|
210
225
|
this.getSceneByName = name => {
|
|
211
|
-
|
|
212
|
-
|
|
226
|
+
return sceneMap[name];
|
|
227
|
+
}
|
|
213
228
|
|
|
214
|
-
|
|
229
|
+
/*
|
|
215
230
|
* Create a new scene with the provided name if scene with the same name exists,
|
|
216
231
|
* return undefined.
|
|
217
232
|
*
|
|
@@ -244,6 +259,10 @@ const Renderer = function (containerIn) {
|
|
|
244
259
|
logoSprite.position.set(calculatedWidth, calculatedHeight, 1 );
|
|
245
260
|
}
|
|
246
261
|
}
|
|
262
|
+
return sceneMap[name];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
247
266
|
};
|
|
248
267
|
|
|
249
268
|
const updateOrthoCamera = () => {
|
|
@@ -341,7 +360,6 @@ const Renderer = function (containerIn) {
|
|
|
341
360
|
*/
|
|
342
361
|
this.stopAnimate = () => {
|
|
343
362
|
if (isRendering) {
|
|
344
|
-
clock.stop();
|
|
345
363
|
isRendering = false;
|
|
346
364
|
}
|
|
347
365
|
}
|
|
@@ -351,7 +369,7 @@ const Renderer = function (containerIn) {
|
|
|
351
369
|
*/
|
|
352
370
|
this.animate = () => {
|
|
353
371
|
if (!isRendering) {
|
|
354
|
-
clock.
|
|
372
|
+
clock.reset();
|
|
355
373
|
isRendering = true;
|
|
356
374
|
runAnimation();
|
|
357
375
|
}
|
|
@@ -549,6 +567,7 @@ const Renderer = function (containerIn) {
|
|
|
549
567
|
sensor = new ResizeSensor(canvas, this.onWindowResize);
|
|
550
568
|
}
|
|
551
569
|
}
|
|
570
|
+
clock.update();
|
|
552
571
|
const delta = clock.getDelta();
|
|
553
572
|
currentScene.renderGeometries(playRate, delta, this.playAnimation);
|
|
554
573
|
for(let i = 0; i < additionalActiveScenes.length; i++) {
|
|
@@ -573,11 +592,11 @@ const Renderer = function (containerIn) {
|
|
|
573
592
|
}
|
|
574
593
|
|
|
575
594
|
this.forceContextLoss = () => {
|
|
576
|
-
|
|
595
|
+
// renderer.forceContextLoss();
|
|
577
596
|
}
|
|
578
597
|
|
|
579
598
|
this.forceContextRestore= () => {
|
|
580
|
-
|
|
599
|
+
// renderer.forceContextRestore();
|
|
581
600
|
}
|
|
582
601
|
|
|
583
602
|
/**
|
package/src/scene.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
1
|
+
import * as THREE from 'three/webgpu';
|
|
2
2
|
import { CameraControls, StereoEffect } from './controls';
|
|
3
3
|
import { LineSegments } from './three/line/LineSegments';
|
|
4
4
|
import { MarkerCluster } from './primitives/markerCluster';
|
|
5
5
|
import { Minimap } from './minimap';
|
|
6
6
|
import { Region } from './region';
|
|
7
|
-
import {
|
|
7
|
+
import { InstancedPoints } from './three/InstancedPoints';
|
|
8
8
|
import { SceneExporter } from './sceneExporter';
|
|
9
9
|
import { SceneLoader } from './sceneLoader';
|
|
10
10
|
import { Viewport } from './controls';
|
|
11
|
+
import { createPointQuadGeometry } from './primitives/pointset';
|
|
12
|
+
import { createInstancedPointsMaterial } from './tls/pointsMaterial';
|
|
11
13
|
import {
|
|
12
14
|
createBufferGeometry,
|
|
13
15
|
createNewSpriteText,
|
|
@@ -1233,12 +1235,22 @@ const Scene = function (containerIn, rendererIn) {
|
|
|
1233
1235
|
* with clearTemporaryPrimitives method.
|
|
1234
1236
|
*/
|
|
1235
1237
|
this.addTemporaryPoints = (coords, colour) => {
|
|
1236
|
-
const geometry =
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
material.
|
|
1241
|
-
|
|
1238
|
+
const geometry = createPointQuadGeometry(coords.length);
|
|
1239
|
+
const material = createInstancedPointsMaterial(getCircularTexture());
|
|
1240
|
+
material.color.set(colour);
|
|
1241
|
+
material.size = 15;
|
|
1242
|
+
material.userData.uniforms.pointSize.value = 15;
|
|
1243
|
+
material.alphaTest = 0.5;
|
|
1244
|
+
const point = new InstancedPoints(geometry, material, coords.length);
|
|
1245
|
+
point.pointPositions = new Float32Array(coords.length * 3);
|
|
1246
|
+
const instancePosition = geometry.getAttribute('instancePosition');
|
|
1247
|
+
coords.forEach((coord, index) => {
|
|
1248
|
+
instancePosition.setXYZ(index, coord[0], coord[1], coord[2]);
|
|
1249
|
+
point.pointPositions[index * 3] = coord[0];
|
|
1250
|
+
point.pointPositions[index * 3 + 1] = coord[1];
|
|
1251
|
+
point.pointPositions[index * 3 + 2] = coord[2];
|
|
1252
|
+
});
|
|
1253
|
+
instancePosition.needsUpdate = true;
|
|
1242
1254
|
tempGroup.add(point);
|
|
1243
1255
|
return point;
|
|
1244
1256
|
}
|
package/src/sceneLoader.js
CHANGED
package/src/texture/texture.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
1
|
+
import * as THREE from 'three/webgpu';
|
|
2
2
|
import { Texture } from './texture';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -12,8 +12,15 @@ import { Texture } from './texture';
|
|
|
12
12
|
const TextureArray = function () {
|
|
13
13
|
Texture.call(this);
|
|
14
14
|
this.isTextureArray = true;
|
|
15
|
+
this.imageData = undefined;
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
this.setDataTexture = (dataTexture) => {
|
|
19
|
+
this.impl = dataTexture;
|
|
20
|
+
console.log("setDataTexture", dataTexture);
|
|
21
|
+
this.imageData = dataTexture.image.data;
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
/**
|
|
18
25
|
* Read images from an array containg src locations.
|
|
19
26
|
*
|
|
@@ -48,7 +55,7 @@ const TextureArray = function () {
|
|
|
48
55
|
length += data.length;
|
|
49
56
|
});
|
|
50
57
|
|
|
51
|
-
this.impl = new THREE.
|
|
58
|
+
this.impl = new THREE.Data3DTexture(fullArray, w, h, d);
|
|
52
59
|
this.size = {
|
|
53
60
|
width: w,
|
|
54
61
|
height: h,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BufferAttribute,
|
|
3
|
+
BufferGeometry,
|
|
3
4
|
ClampToEdgeWrapping,
|
|
4
5
|
DoubleSide,
|
|
5
6
|
InterpolateDiscrete,
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
RepeatWrapping,
|
|
20
21
|
Scene,
|
|
21
22
|
Vector3
|
|
22
|
-
} from 'three';
|
|
23
|
+
} from 'three/webgpu';
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class GLTFExporter {
|
|
@@ -1291,6 +1292,48 @@ class GLTFWriter {
|
|
|
1291
1292
|
|
|
1292
1293
|
}
|
|
1293
1294
|
|
|
1295
|
+
/**
|
|
1296
|
+
* A Pointset's {@link InstancedPoints} draws every point as an instance of a
|
|
1297
|
+
* small camera facing quad - its `geometry` only carries that quad, the
|
|
1298
|
+
* actual point positions/colours live in `pointPositions`/`instanceColor`.
|
|
1299
|
+
* Temporarily substitute a plain points geometry built from that data (and
|
|
1300
|
+
* flag the object as `isPoints`) so the regular POINTS export path below
|
|
1301
|
+
* produces a correct round trip, then return a function that restores the
|
|
1302
|
+
* object to its original state.
|
|
1303
|
+
*
|
|
1304
|
+
* @param {InstancedPoints} object Object to substitute the geometry of
|
|
1305
|
+
* @return {Function} Restores `object` to its pre-substitution state
|
|
1306
|
+
*/
|
|
1307
|
+
substituteInstancedPointsGeometry( object ) {
|
|
1308
|
+
|
|
1309
|
+
const count = object.count;
|
|
1310
|
+
const geometry = new BufferGeometry();
|
|
1311
|
+
geometry.setAttribute( 'position',
|
|
1312
|
+
new BufferAttribute( object.pointPositions.slice( 0, count * 3 ), 3 ) );
|
|
1313
|
+
|
|
1314
|
+
if ( object.instanceColor ) {
|
|
1315
|
+
|
|
1316
|
+
geometry.setAttribute( 'color',
|
|
1317
|
+
new BufferAttribute( object.instanceColor.array.slice( 0, count * 3 ), 3 ) );
|
|
1318
|
+
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
const originalGeometry = object.geometry;
|
|
1322
|
+
const originalIsPoints = object.isPoints;
|
|
1323
|
+
|
|
1324
|
+
object.geometry = geometry;
|
|
1325
|
+
object.isPoints = true;
|
|
1326
|
+
|
|
1327
|
+
return function () {
|
|
1328
|
+
|
|
1329
|
+
object.geometry = originalGeometry;
|
|
1330
|
+
object.isPoints = originalIsPoints;
|
|
1331
|
+
geometry.dispose();
|
|
1332
|
+
|
|
1333
|
+
};
|
|
1334
|
+
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1294
1337
|
/**
|
|
1295
1338
|
* Process mesh
|
|
1296
1339
|
* @param {THREE.Mesh} mesh Mesh to process
|
|
@@ -1887,10 +1930,20 @@ class GLTFWriter {
|
|
|
1887
1930
|
|
|
1888
1931
|
this.serializeUserData( object, nodeDef );
|
|
1889
1932
|
|
|
1890
|
-
if ( object.isMesh || object.isLine || object.isPoints ) {
|
|
1933
|
+
if ( object.isMesh || object.isLine || object.isPoints || object.isInstancedPoints ) {
|
|
1934
|
+
|
|
1935
|
+
let restoreInstancedPoints;
|
|
1936
|
+
|
|
1937
|
+
if ( object.isInstancedPoints ) {
|
|
1938
|
+
|
|
1939
|
+
restoreInstancedPoints = this.substituteInstancedPointsGeometry( object );
|
|
1940
|
+
|
|
1941
|
+
}
|
|
1891
1942
|
|
|
1892
1943
|
const meshIndex = this.processMesh( object );
|
|
1893
1944
|
|
|
1945
|
+
if ( restoreInstancedPoints ) restoreInstancedPoints();
|
|
1946
|
+
|
|
1894
1947
|
if ( meshIndex !== null ) nodeDef.mesh = meshIndex;
|
|
1895
1948
|
|
|
1896
1949
|
} else if ( object.isCamera ) {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InstancedMesh,
|
|
3
|
+
Matrix4,
|
|
4
|
+
Ray,
|
|
5
|
+
Vector3,
|
|
6
|
+
} from 'three/webgpu';
|
|
7
|
+
|
|
8
|
+
const _inverseMatrix = /*@__PURE__*/ new Matrix4();
|
|
9
|
+
const _ray = /*@__PURE__*/ new Ray();
|
|
10
|
+
const _position = /*@__PURE__*/ new Vector3();
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* An {@link THREE.InstancedMesh} used to draw a {@link Pointset}. Every
|
|
14
|
+
* instance is a small quad billboarded towards the camera on the GPU (see
|
|
15
|
+
* {@link createInstancedPointsMaterial}), so the usual matrix/geometry based
|
|
16
|
+
* raycasting and bounding logic performed by `THREE.InstancedMesh` does not
|
|
17
|
+
* apply - the true, already time-blended location of every point is instead
|
|
18
|
+
* kept in `pointPositions` (local space) and used here directly, mirroring
|
|
19
|
+
* the distance-to-point approach the legacy `THREE.Points` override used.
|
|
20
|
+
*/
|
|
21
|
+
class InstancedPoints extends InstancedMesh {
|
|
22
|
+
|
|
23
|
+
constructor(geometry, material, count) {
|
|
24
|
+
super(geometry, material, count);
|
|
25
|
+
this.type = 'InstancedPoints';
|
|
26
|
+
this.isInstancedPoints = true;
|
|
27
|
+
this.frustumCulled = false;
|
|
28
|
+
this.pointSize = 10;
|
|
29
|
+
this.sizePerPixel = 1;
|
|
30
|
+
//Flat [x0, y0, z0, x1, y1, z1, ...] array of the current, already
|
|
31
|
+
//time-blended local positions of every active point.
|
|
32
|
+
this.pointPositions = new Float32Array(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
raycast(raycaster, intersects) {
|
|
36
|
+
const matrixWorld = this.matrixWorld;
|
|
37
|
+
const threshold = raycaster.params.Points ? raycaster.params.Points.threshold : 1;
|
|
38
|
+
const count = this.count;
|
|
39
|
+
const positions = this.pointPositions;
|
|
40
|
+
|
|
41
|
+
if (!count || !positions || positions.length < count * 3) return;
|
|
42
|
+
|
|
43
|
+
_inverseMatrix.copy(matrixWorld).invert();
|
|
44
|
+
_ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix);
|
|
45
|
+
|
|
46
|
+
const averageScale = (this.scale.x + this.scale.y + this.scale.z) / 3;
|
|
47
|
+
const localThreshold = threshold / averageScale * this.pointSize * this.sizePerPixel;
|
|
48
|
+
const localThresholdSq = localThreshold * localThreshold;
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < count; i++) {
|
|
51
|
+
_position.fromArray(positions, i * 3);
|
|
52
|
+
const rayPointDistanceSq = _ray.distanceSqToPoint(_position);
|
|
53
|
+
if (rayPointDistanceSq < localThresholdSq) {
|
|
54
|
+
const intersectPoint = new Vector3();
|
|
55
|
+
_ray.closestPointToPoint(_position, intersectPoint);
|
|
56
|
+
intersectPoint.applyMatrix4(matrixWorld);
|
|
57
|
+
const distance = raycaster.ray.origin.distanceTo(intersectPoint);
|
|
58
|
+
if (distance < raycaster.near || distance > raycaster.far) continue;
|
|
59
|
+
intersects.push({
|
|
60
|
+
distance: distance,
|
|
61
|
+
distanceToRay: Math.sqrt(rayPointDistanceSq),
|
|
62
|
+
point: intersectPoint,
|
|
63
|
+
index: i,
|
|
64
|
+
face: null,
|
|
65
|
+
object: this,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { InstancedPoints };
|
package/src/three/Loader.js
CHANGED
package/src/three/line/Line.js
CHANGED
|
@@ -8,12 +8,11 @@ import {
|
|
|
8
8
|
Mesh,
|
|
9
9
|
Sphere,
|
|
10
10
|
Vector3,
|
|
11
|
-
Vector4
|
|
12
|
-
|
|
11
|
+
Vector4,
|
|
12
|
+
Line2NodeMaterial,
|
|
13
|
+
Vector2
|
|
14
|
+
} from 'three/webgpu';
|
|
13
15
|
import { LineSegmentsGeometry } from './LineSegmentsGeometry.js';
|
|
14
|
-
import { LineMaterial } from './LineMaterial.js';
|
|
15
|
-
|
|
16
|
-
const _viewport = new Vector4();
|
|
17
16
|
|
|
18
17
|
const _start = new Vector3();
|
|
19
18
|
const _end = new Vector3();
|
|
@@ -30,6 +29,7 @@ const _closestPoint = new Vector3();
|
|
|
30
29
|
const _box = new Box3();
|
|
31
30
|
const _sphere = new Sphere();
|
|
32
31
|
const _clipToWorldVector = new Vector4();
|
|
32
|
+
const _viewport = new Vector4();
|
|
33
33
|
|
|
34
34
|
let _ray, _lineWidth;
|
|
35
35
|
|
|
@@ -94,10 +94,10 @@ function raycastWorldUnits( lineSegments, intersects ) {
|
|
|
94
94
|
function raycastScreenSpace( lineSegments, camera, intersects ) {
|
|
95
95
|
|
|
96
96
|
const projectionMatrix = camera.projectionMatrix;
|
|
97
|
-
const material = lineSegments.material;
|
|
98
|
-
const resolution = material.resolution;
|
|
99
97
|
const matrixWorld = lineSegments.matrixWorld;
|
|
100
98
|
|
|
99
|
+
const resolution = lineSegments._resolution;
|
|
100
|
+
|
|
101
101
|
const geometry = lineSegments.geometry;
|
|
102
102
|
const instanceStart = geometry.attributes.instanceStart;
|
|
103
103
|
const instanceEnd = geometry.attributes.instanceEnd;
|
|
@@ -231,22 +231,11 @@ function raycastScreenSpace( lineSegments, camera, intersects ) {
|
|
|
231
231
|
* to be in world units. {@link Line2} extends this object, forming a polyline instead of individual
|
|
232
232
|
* segments.
|
|
233
233
|
*
|
|
234
|
-
* This module can only be used with {@link
|
|
235
|
-
* import the class from `lines/
|
|
236
|
-
*
|
|
237
|
-
* ```js
|
|
238
|
-
* const geometry = new LineSegmentsGeometry();
|
|
239
|
-
* geometry.setPositions( positions );
|
|
240
|
-
* geometry.setColors( colors );
|
|
241
|
-
*
|
|
242
|
-
* const material = new LineMaterial( { linewidth: 5, vertexColors: true } };
|
|
243
|
-
*
|
|
244
|
-
* const lineSegments = new LineSegments2( geometry, material );
|
|
245
|
-
* scene.add( lineSegments );
|
|
246
|
-
* ```
|
|
234
|
+
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
|
|
235
|
+
* import the class from `lines/LineSegments2.js`.
|
|
247
236
|
*
|
|
248
237
|
* @augments Mesh
|
|
249
|
-
* @three_import import { LineSegments2 } from 'three/addons/lines/LineSegments2.js';
|
|
238
|
+
* @three_import import { LineSegments2 } from 'three/addons/lines/webgpu/LineSegments2.js';
|
|
250
239
|
*/
|
|
251
240
|
class LineSegments2 extends Mesh {
|
|
252
241
|
|
|
@@ -254,9 +243,9 @@ class LineSegments2 extends Mesh {
|
|
|
254
243
|
* Constructs a new wide line.
|
|
255
244
|
*
|
|
256
245
|
* @param {LineSegmentsGeometry} [geometry] - The line geometry.
|
|
257
|
-
* @param {
|
|
246
|
+
* @param {Line2NodeMaterial} [material] - The line material.
|
|
258
247
|
*/
|
|
259
|
-
constructor( geometry = new LineSegmentsGeometry(), material = new
|
|
248
|
+
constructor( geometry = new LineSegmentsGeometry(), material = new Line2NodeMaterial( { color: Math.random() * 0xffffff } ) ) {
|
|
260
249
|
|
|
261
250
|
super( geometry, material );
|
|
262
251
|
|
|
@@ -271,6 +260,8 @@ class LineSegments2 extends Mesh {
|
|
|
271
260
|
|
|
272
261
|
this.type = 'LineSegments2';
|
|
273
262
|
|
|
263
|
+
this._resolution = new Vector2();
|
|
264
|
+
|
|
274
265
|
}
|
|
275
266
|
|
|
276
267
|
/**
|
|
@@ -309,6 +300,13 @@ class LineSegments2 extends Mesh {
|
|
|
309
300
|
|
|
310
301
|
}
|
|
311
302
|
|
|
303
|
+
onBeforeRender( renderer ) {
|
|
304
|
+
|
|
305
|
+
renderer.getViewport( _viewport );
|
|
306
|
+
this._resolution.set( _viewport.z, _viewport.w );
|
|
307
|
+
|
|
308
|
+
}
|
|
309
|
+
|
|
312
310
|
/**
|
|
313
311
|
* Computes intersection points between a casted ray and this instance.
|
|
314
312
|
*
|
|
@@ -328,7 +326,7 @@ class LineSegments2 extends Mesh {
|
|
|
328
326
|
|
|
329
327
|
// early out if no resolution has been set (line was not rendered yet)
|
|
330
328
|
|
|
331
|
-
if ( worldUnits === false && ( this.
|
|
329
|
+
if ( worldUnits === false && ( this._resolution.x === 0 || this._resolution.y === 0 ) ) {
|
|
332
330
|
|
|
333
331
|
return;
|
|
334
332
|
|
|
@@ -362,7 +360,7 @@ class LineSegments2 extends Mesh {
|
|
|
362
360
|
} else {
|
|
363
361
|
|
|
364
362
|
const distanceToSphere = Math.max( camera.near, _sphere.distanceToPoint( _ray.origin ) );
|
|
365
|
-
sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere,
|
|
363
|
+
sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere, this._resolution );
|
|
366
364
|
|
|
367
365
|
}
|
|
368
366
|
|
|
@@ -392,7 +390,7 @@ class LineSegments2 extends Mesh {
|
|
|
392
390
|
} else {
|
|
393
391
|
|
|
394
392
|
const distanceToBox = Math.max( camera.near, _box.distanceToPoint( _ray.origin ) );
|
|
395
|
-
boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox,
|
|
393
|
+
boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox, this._resolution );
|
|
396
394
|
|
|
397
395
|
}
|
|
398
396
|
|
|
@@ -416,19 +414,6 @@ class LineSegments2 extends Mesh {
|
|
|
416
414
|
|
|
417
415
|
}
|
|
418
416
|
|
|
419
|
-
onBeforeRender( renderer ) {
|
|
420
|
-
|
|
421
|
-
const uniforms = this.material.uniforms;
|
|
422
|
-
|
|
423
|
-
if ( uniforms && uniforms.resolution ) {
|
|
424
|
-
|
|
425
|
-
renderer.getViewport( _viewport );
|
|
426
|
-
this.material.uniforms.resolution.value.set( _viewport.z, _viewport.w );
|
|
427
|
-
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
|
|
432
417
|
}
|
|
433
418
|
|
|
434
419
|
export { LineSegments2 };
|