zincjs 2.4.1-beta.2 → 2.4.1-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zincjs",
3
- "version": "2.4.1-beta.2",
3
+ "version": "2.4.1-beta.3",
4
4
  "description": "ZincJS (Web-based-Zinc-Visualisation)",
5
5
  "type": "module",
6
6
  "main": "build/zinc.js",
@@ -1,13 +1,63 @@
1
- import * as THREE from 'three/webgpu';
2
1
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
3
2
  import { Geometry } from '../primitives/geometry';
4
3
  import { Lines } from '../primitives/lines';
5
4
  import { Pointset } from '../primitives/pointset';
5
+ import { applyMorphColorNode } from '../tsl/morphColorMaterial';
6
6
 
7
7
  const GLTFToZincJSLoader = function () {
8
8
 
9
9
  const _this = this;
10
10
 
11
+ /*
12
+ * glTF stores morph targets as offsets from the base attribute and
13
+ * GLTFLoader keeps them that way (morphTargetsRelative), but zinc expects
14
+ * absolute morph targets. GLTFLoader also only keeps the target names in
15
+ * morphTargetDictionary, while zinc builds its animation clip from the
16
+ * attribute names, so copy the names back onto the attributes.
17
+ */
18
+ const convertMorphTargets = (object) => {
19
+ const geometry = object.geometry;
20
+ if (!geometry || !geometry.morphAttributes) return;
21
+ const names = [];
22
+ if (object.morphTargetDictionary) {
23
+ for (const key in object.morphTargetDictionary) {
24
+ names[object.morphTargetDictionary[key]] = key;
25
+ }
26
+ }
27
+ for (const attributeName in geometry.morphAttributes) {
28
+ const base = geometry.attributes[attributeName];
29
+ geometry.morphAttributes[attributeName].forEach((attribute, i) => {
30
+ if (geometry.morphTargetsRelative && base) {
31
+ const array = attribute.array;
32
+ const baseArray = base.array;
33
+ const length = Math.min(array.length, baseArray.length);
34
+ for (let j = 0; j < length; j++) {
35
+ array[j] += baseArray[j];
36
+ }
37
+ attribute.needsUpdate = true;
38
+ }
39
+ if (names[i] !== undefined) attribute.name = names[i];
40
+ });
41
+ }
42
+ geometry.morphTargetsRelative = false;
43
+ }
44
+
45
+ /*
46
+ * Zinc renders colour morphs with its own colorNode (see geometry.js and
47
+ * lines.js), so swap it into the materials GLTFLoader created. Without it
48
+ * the colours stay at the first frame.
49
+ */
50
+ const applyMorphColourMaterial = (object) => {
51
+ const setup = (material) => {
52
+ //Same as geometry.js - vertexColors would multiply the blend by the
53
+ //static colour attribute.
54
+ material.vertexColors = false;
55
+ return applyMorphColorNode(material);
56
+ };
57
+ object.material = Array.isArray(object.material) ?
58
+ object.material.map(setup) : setup(object.material);
59
+ }
60
+
11
61
  this.parseGLTFObjects = (object, region, depth, finishCallback) => {
12
62
  let childRegion = region;
13
63
  if (depth !== 0) {
@@ -36,10 +86,14 @@ const GLTFToZincJSLoader = function () {
36
86
  let localTimeEnabled = false;
37
87
  let localMorphColour = false;
38
88
  if (object.geometry && object.geometry.morphAttributes) {
89
+ convertMorphTargets(object);
39
90
  localTimeEnabled = object.geometry.morphAttributes.position ? true : false;
40
91
  localMorphColour = object.geometry.morphAttributes.color ? true : false;
41
92
  }
42
- zincGeometry.setMesh(object.clone(), localTimeEnabled, localMorphColour);
93
+ const mesh = object.clone();
94
+ if (localMorphColour && !zincGeometry.isPointset)
95
+ applyMorphColourMaterial(mesh);
96
+ zincGeometry.setMesh(mesh, localTimeEnabled, localMorphColour);
43
97
  const morph = zincGeometry.getMorph();
44
98
  zincGeometry.groupName = morph.name;
45
99
  morph.matrixAutoUpdate = true;
@@ -234,7 +234,7 @@ function createDataTexture(data, width, height, depth, isRGB) {
234
234
  if (!isRGB) {
235
235
  dataTexture.format = THREE.RedFormat;
236
236
  }
237
- dataTexture.colorSpace = THREE.SRGBColorSpace;
237
+ dataTexture.colorSpace = THREE.NoColorSpace;
238
238
  dataTexture.minFilter = THREE.NearestFilter;
239
239
  dataTexture.magFilter = THREE.NearestFilter;
240
240
  dataTexture.needsUpdate = true;
@@ -244,7 +244,7 @@ function createDataTexture(data, width, height, depth, isRGB) {
244
244
  function createTextureArray(sources) {
245
245
  if (sources?.data) {
246
246
  const tArray = new TextureArray();
247
- const dataTexutre = new createDataTexture(
247
+ const dataTexutre = createDataTexture(
248
248
  sources.data, sources.width, sources.height, sources.depth);
249
249
  tArray.setDataTexture(dataTexutre);
250
250
  tArray.size = {
@@ -1,6 +1,6 @@
1
1
  import * as THREE from 'three/webgpu';
2
2
  import { toBufferGeometry } from '../utilities';
3
- import { applyMorphColorNode } from '../tls/morphColorMaterial';
3
+ import { applyMorphColorNode } from '../tsl/morphColorMaterial';
4
4
  import { ZincObject} from './zincObject';
5
5
 
6
6
  const createMeshForGeometry = (geometryIn, materialIn, options) => {
@@ -27,6 +27,7 @@ const Glyph = function (geometry, materialIn, idIn, glyphsetIn) {
27
27
  let labelString = undefined;
28
28
  this.isGlyph = true;
29
29
  let _position = [0, 0, 0];
30
+ let _colour = undefined;
30
31
 
31
32
  /**
32
33
  * Create a glyph using mesh
@@ -72,7 +73,9 @@ const Glyph = function (geometry, materialIn, idIn, glyphsetIn) {
72
73
  /**
73
74
  * Display label with the choosen colour. It will replace the current
74
75
  * label.
75
- * @param {THREE.Color} colour - Colour for the label.
76
+ * @param {THREE.Color} colour - Colour to fall back to for the label if
77
+ * this glyph doesn't already have its own colour (see setColour()/
78
+ * getColour()) - e.g. genuinely no colour data at all for this glyphset.
76
79
  */
77
80
  this.showLabel = (colour) => {
78
81
  if (label) {
@@ -82,7 +85,7 @@ const Glyph = function (geometry, materialIn, idIn, glyphsetIn) {
82
85
  label = undefined;
83
86
  }
84
87
  if (labelString && (typeof labelString === 'string' || labelString instanceof String)) {
85
- label = new Label(labelString, colour);
88
+ label = new Label(labelString, _colour || colour);
86
89
  label.setPosition(_position[0], _position[1], _position[2]);
87
90
  const sprite = label.getSprite();
88
91
  sprite.material.alphaTest = 0.5;
@@ -158,20 +161,31 @@ const Glyph = function (geometry, materialIn, idIn, glyphsetIn) {
158
161
  }
159
162
 
160
163
  /**
161
- * Set the color of the glyph and its label.
164
+ * Set the color of the glyph and its label. Remembered (see showLabel())
165
+ * so a label created/recreated later - e.g. by Glyphset.showLabel(),
166
+ * which otherwise only has a single shared material colour to fall back
167
+ * on - starts out with this glyph's own correct colour rather than that
168
+ * shared one.
162
169
  *
163
170
  * @param {THREE.Color} color - Colour to be set.
164
171
  */
165
172
  this.setColour = (color) => {
173
+ _colour = color ? color.clone() : undefined;
166
174
  if (label)
167
175
  label.setColour(color);
168
176
  if (this.secondaryMesh && this.secondaryMesh.material)
169
- this.secondaryMesh.material.color = colour;
177
+ this.secondaryMesh.material.color = color;
170
178
  if (this.geometry) {
171
179
  this.geometry.colorsNeedUpdate = true;
172
180
  }
173
181
  }
174
182
 
183
+ /**
184
+ * Get the last colour set via setColour(), if any.
185
+ * @return {THREE.Color|undefined}
186
+ */
187
+ this.getColour = () => _colour;
188
+
175
189
  /**
176
190
  * Clear and free its memory.
177
191
  */