@polarfront-lab/ionian 1.2.0 → 1.4.0
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/dist/index.d.ts +14 -5
- package/dist/ionian.iife.js +1 -1
- package/dist/ionian.iife.js.map +1 -1
- package/dist/ionian.js +247 -168
- package/dist/ionian.js.map +1 -1
- package/package.json +2 -3
package/dist/ionian.js
CHANGED
|
@@ -83,6 +83,125 @@ function clamp(value, min, max) {
|
|
|
83
83
|
value = Math.max(value, min);
|
|
84
84
|
return value;
|
|
85
85
|
}
|
|
86
|
+
class AssetService {
|
|
87
|
+
constructor(eventEmitter) {
|
|
88
|
+
__publicField(this, "serviceState", "created");
|
|
89
|
+
__publicField(this, "eventEmitter");
|
|
90
|
+
__publicField(this, "meshes", /* @__PURE__ */ new Map());
|
|
91
|
+
__publicField(this, "textures", /* @__PURE__ */ new Map());
|
|
92
|
+
__publicField(this, "gltfLoader", new GLTFLoader());
|
|
93
|
+
__publicField(this, "textureLoader", new THREE.TextureLoader());
|
|
94
|
+
__publicField(this, "dracoLoader", new DRACOLoader());
|
|
95
|
+
__publicField(this, "solidColorTexture", new THREE.DataTexture(new Uint8Array([127, 127, 127, 255]), 1, 1, THREE.RGBAFormat));
|
|
96
|
+
this.eventEmitter = eventEmitter;
|
|
97
|
+
this.dracoLoader.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.7/");
|
|
98
|
+
this.gltfLoader.setDRACOLoader(this.dracoLoader);
|
|
99
|
+
this.updateServiceState("ready");
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Registers an asset.
|
|
103
|
+
* @param id - The ID of the asset.
|
|
104
|
+
* @param item - The asset to set.
|
|
105
|
+
*/
|
|
106
|
+
register(id, item) {
|
|
107
|
+
item.name = id;
|
|
108
|
+
if (item instanceof THREE.Mesh) {
|
|
109
|
+
const prev = this.meshes.get(id);
|
|
110
|
+
if (prev) disposeMesh(prev);
|
|
111
|
+
this.meshes.set(id, item);
|
|
112
|
+
} else {
|
|
113
|
+
const prev = this.textures.get(id);
|
|
114
|
+
if (prev) prev.dispose();
|
|
115
|
+
this.textures.set(id, item);
|
|
116
|
+
}
|
|
117
|
+
this.eventEmitter.emit("assetRegistered", { id });
|
|
118
|
+
}
|
|
119
|
+
setSolidColor(color) {
|
|
120
|
+
this.changeColor(color);
|
|
121
|
+
}
|
|
122
|
+
getSolidColorTexture() {
|
|
123
|
+
return this.solidColorTexture;
|
|
124
|
+
}
|
|
125
|
+
getMesh(id) {
|
|
126
|
+
return this.meshes.get(id) ?? null;
|
|
127
|
+
}
|
|
128
|
+
getMatcap(id) {
|
|
129
|
+
const texture = this.textures.get(id);
|
|
130
|
+
if (!texture) this.eventEmitter.emit("invalidRequest", { message: `texture with id "${id}" not found. using solid color texture instead...` });
|
|
131
|
+
return texture ?? this.solidColorTexture;
|
|
132
|
+
}
|
|
133
|
+
getMeshIDs() {
|
|
134
|
+
return Array.from(this.meshes.keys());
|
|
135
|
+
}
|
|
136
|
+
getTextureIDs() {
|
|
137
|
+
return Array.from(this.textures.keys());
|
|
138
|
+
}
|
|
139
|
+
getMeshes() {
|
|
140
|
+
return Array.from(this.meshes.values());
|
|
141
|
+
}
|
|
142
|
+
getTextures() {
|
|
143
|
+
return Array.from(this.textures.values());
|
|
144
|
+
}
|
|
145
|
+
hasMatcap(id) {
|
|
146
|
+
return this.textures.has(id);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Loads a mesh asynchronously.
|
|
150
|
+
* @param id - The ID of the mesh.
|
|
151
|
+
* @param url - The URL of the mesh.
|
|
152
|
+
* @param options - Optional parameters.
|
|
153
|
+
* @returns The loaded mesh or null.
|
|
154
|
+
*/
|
|
155
|
+
async loadMeshAsync(id, url, options = {}) {
|
|
156
|
+
const gltf = await this.gltfLoader.loadAsync(url);
|
|
157
|
+
try {
|
|
158
|
+
if (options.meshName) {
|
|
159
|
+
const mesh = gltf.scene.getObjectByName(options.meshName);
|
|
160
|
+
this.register(id, mesh);
|
|
161
|
+
return mesh;
|
|
162
|
+
} else {
|
|
163
|
+
const mesh = gltf.scene.children[0];
|
|
164
|
+
this.register(id, mesh);
|
|
165
|
+
return mesh;
|
|
166
|
+
}
|
|
167
|
+
} catch (error) {
|
|
168
|
+
this.eventEmitter.emit("invalidRequest", { message: `failed to load mesh: ${id}. ${error}` });
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Loads a texture asynchronously.
|
|
174
|
+
* @param id - The ID of the texture.
|
|
175
|
+
* @param url - The URL of the texture.
|
|
176
|
+
* @returns The loaded texture or null.
|
|
177
|
+
*/
|
|
178
|
+
async loadTextureAsync(id, url) {
|
|
179
|
+
try {
|
|
180
|
+
const texture = await this.textureLoader.loadAsync(url);
|
|
181
|
+
this.register(id, texture);
|
|
182
|
+
return texture;
|
|
183
|
+
} catch (error) {
|
|
184
|
+
this.eventEmitter.emit("invalidRequest", { message: `failed to load texture: ${id}. ${error}` });
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
dispose() {
|
|
189
|
+
this.updateServiceState("disposed");
|
|
190
|
+
this.meshes.forEach((mesh) => disposeMesh(mesh));
|
|
191
|
+
this.meshes.clear();
|
|
192
|
+
this.textures.forEach((texture) => texture.dispose());
|
|
193
|
+
this.textures.clear();
|
|
194
|
+
}
|
|
195
|
+
changeColor(color) {
|
|
196
|
+
const actual = new THREE.Color(color);
|
|
197
|
+
this.solidColorTexture = new THREE.DataTexture(new Uint8Array([actual.r, actual.g, actual.b, 255]), 1, 1, THREE.RGBAFormat);
|
|
198
|
+
this.solidColorTexture.needsUpdate = true;
|
|
199
|
+
}
|
|
200
|
+
updateServiceState(serviceState) {
|
|
201
|
+
this.serviceState = serviceState;
|
|
202
|
+
this.eventEmitter.emit("serviceStateUpdated", { type: "asset", state: serviceState });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
86
205
|
const _face = new Triangle();
|
|
87
206
|
const _color = new Vector3();
|
|
88
207
|
const _uva = new Vector2(), _uvb = new Vector2(), _uvc = new Vector2();
|
|
@@ -295,8 +414,8 @@ const instanceFragmentShader = `
|
|
|
295
414
|
varying vec2 vUv;
|
|
296
415
|
uniform sampler2D uTexture;
|
|
297
416
|
|
|
298
|
-
uniform sampler2D
|
|
299
|
-
uniform sampler2D
|
|
417
|
+
uniform sampler2D uOriginTexture;
|
|
418
|
+
uniform sampler2D uDestinationTexture;
|
|
300
419
|
|
|
301
420
|
uniform float uProgress;
|
|
302
421
|
varying vec3 vNormal;
|
|
@@ -307,8 +426,8 @@ void main() {
|
|
|
307
426
|
vec3 y = cross( viewDir, x );
|
|
308
427
|
vec2 uv = vec2( dot( x, vNormal ), dot( y, vNormal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks
|
|
309
428
|
|
|
310
|
-
vec4 sourceMatcap = texture2D(
|
|
311
|
-
vec4 targetMatcap = texture2D(
|
|
429
|
+
vec4 sourceMatcap = texture2D( uOriginTexture, uv );
|
|
430
|
+
vec4 targetMatcap = texture2D( uDestinationTexture, uv );
|
|
312
431
|
|
|
313
432
|
vec4 matcap = mix(sourceMatcap, targetMatcap, uProgress);
|
|
314
433
|
gl_FragColor = matcap;
|
|
@@ -368,32 +487,36 @@ class InstancedMeshManager {
|
|
|
368
487
|
__publicField(this, "size");
|
|
369
488
|
__publicField(this, "mesh");
|
|
370
489
|
__publicField(this, "matcapMaterial");
|
|
371
|
-
__publicField(this, "fallbackMaterial");
|
|
372
490
|
__publicField(this, "fallbackGeometry");
|
|
373
|
-
__publicField(this, "
|
|
491
|
+
__publicField(this, "uniforms");
|
|
492
|
+
__publicField(this, "originColor");
|
|
493
|
+
__publicField(this, "destinationColor");
|
|
374
494
|
__publicField(this, "geometries");
|
|
375
495
|
__publicField(this, "uvRefsCache");
|
|
376
496
|
__publicField(this, "previousScale");
|
|
377
497
|
this.size = initialSize;
|
|
378
|
-
this.materials = /* @__PURE__ */ new Map();
|
|
379
498
|
this.geometries = /* @__PURE__ */ new Map();
|
|
380
499
|
this.uvRefsCache = /* @__PURE__ */ new Map();
|
|
381
500
|
this.previousScale = { x: 1, y: 1, z: 1 };
|
|
501
|
+
this.originColor = "grey";
|
|
502
|
+
this.destinationColor = "grey";
|
|
503
|
+
this.uniforms = {
|
|
504
|
+
uTime: { value: 0 },
|
|
505
|
+
uProgress: { value: 0 },
|
|
506
|
+
uTexture: { value: null },
|
|
507
|
+
uVelocity: { value: null },
|
|
508
|
+
uOriginTexture: { value: null },
|
|
509
|
+
uDestinationTexture: { value: null }
|
|
510
|
+
};
|
|
382
511
|
this.matcapMaterial = new THREE.ShaderMaterial({
|
|
383
|
-
uniforms:
|
|
384
|
-
uTime: { value: 0 },
|
|
385
|
-
uProgress: { value: 0 },
|
|
386
|
-
uTexture: { value: null },
|
|
387
|
-
uVelocity: { value: null },
|
|
388
|
-
uSourceMatcap: { value: null },
|
|
389
|
-
uTargetMatcap: { value: null }
|
|
390
|
-
},
|
|
512
|
+
uniforms: this.uniforms,
|
|
391
513
|
vertexShader: instanceVertexShader,
|
|
392
514
|
fragmentShader: instanceFragmentShader
|
|
393
515
|
});
|
|
394
|
-
this.
|
|
516
|
+
this.setOriginColor(this.originColor);
|
|
517
|
+
this.setDestinationColor(this.destinationColor);
|
|
395
518
|
this.fallbackGeometry = new THREE.BoxGeometry(1e-3, 1e-3, 1e-3);
|
|
396
|
-
this.mesh = this.createInstancedMesh(initialSize, this.fallbackGeometry, this.
|
|
519
|
+
this.mesh = this.createInstancedMesh(initialSize, this.fallbackGeometry, this.matcapMaterial);
|
|
397
520
|
}
|
|
398
521
|
/**
|
|
399
522
|
* Gets the instanced mesh.
|
|
@@ -417,10 +540,12 @@ class InstancedMeshManager {
|
|
|
417
540
|
* @param matcap The matcap texture to set.
|
|
418
541
|
*/
|
|
419
542
|
setOriginMatcap(matcap) {
|
|
420
|
-
this.
|
|
543
|
+
this.disposeSolidColorOriginTexture();
|
|
544
|
+
this.matcapMaterial.uniforms.uOriginTexture.value = matcap;
|
|
421
545
|
}
|
|
422
546
|
setDestinationMatcap(matcap) {
|
|
423
|
-
this.
|
|
547
|
+
this.disposeSolidColorDestinationTexture();
|
|
548
|
+
this.matcapMaterial.uniforms.uDestinationTexture.value = matcap;
|
|
424
549
|
}
|
|
425
550
|
setProgress(float) {
|
|
426
551
|
float = Math.max(0, float);
|
|
@@ -438,16 +563,6 @@ class InstancedMeshManager {
|
|
|
438
563
|
useMatcapMaterial() {
|
|
439
564
|
this.mesh.material = this.matcapMaterial;
|
|
440
565
|
}
|
|
441
|
-
/**
|
|
442
|
-
* Use the specified material for the instanced mesh.
|
|
443
|
-
* @param id The ID of the material to use.
|
|
444
|
-
*/
|
|
445
|
-
useMaterial(id) {
|
|
446
|
-
const material = this.materials.get(id);
|
|
447
|
-
if (material) {
|
|
448
|
-
this.mesh.material = material;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
566
|
/**
|
|
452
567
|
* Use the specified geometry for the instanced mesh.
|
|
453
568
|
* @param id The ID of the geometry to use.
|
|
@@ -490,10 +605,11 @@ class InstancedMeshManager {
|
|
|
490
605
|
dispose() {
|
|
491
606
|
this.mesh.dispose();
|
|
492
607
|
this.geometries.forEach((geometry) => geometry.dispose());
|
|
493
|
-
this.
|
|
608
|
+
this.disposeSolidColorOriginTexture();
|
|
609
|
+
this.disposeSolidColorDestinationTexture();
|
|
610
|
+
this.matcapMaterial.dispose();
|
|
494
611
|
this.uvRefsCache.clear();
|
|
495
612
|
this.geometries.clear();
|
|
496
|
-
this.materials.clear();
|
|
497
613
|
}
|
|
498
614
|
/**
|
|
499
615
|
* Registers a geometry.
|
|
@@ -507,7 +623,7 @@ class InstancedMeshManager {
|
|
|
507
623
|
return;
|
|
508
624
|
}
|
|
509
625
|
}
|
|
510
|
-
const uvRefs = this.
|
|
626
|
+
const uvRefs = this.createUVRefs(this.size);
|
|
511
627
|
geometry.setAttribute("uvRef", uvRefs);
|
|
512
628
|
this.geometries.set(id, geometry);
|
|
513
629
|
if (this.mesh.geometry === previous) {
|
|
@@ -515,30 +631,22 @@ class InstancedMeshManager {
|
|
|
515
631
|
}
|
|
516
632
|
previous == null ? void 0 : previous.dispose();
|
|
517
633
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
if (this.mesh.material === previous) {
|
|
531
|
-
this.mesh.material = material;
|
|
532
|
-
}
|
|
533
|
-
this.materials.set(id, material);
|
|
534
|
-
previous == null ? void 0 : previous.dispose();
|
|
634
|
+
setOriginColor(color) {
|
|
635
|
+
this.disposeSolidColorOriginTexture();
|
|
636
|
+
this.originColor = color;
|
|
637
|
+
this.uniforms.uOriginTexture.value = this.createSolidColorDataTexture(color);
|
|
638
|
+
}
|
|
639
|
+
setDestinationColor(color) {
|
|
640
|
+
this.disposeSolidColorDestinationTexture();
|
|
641
|
+
this.destinationColor = color;
|
|
642
|
+
this.uniforms.uDestinationTexture.value = this.createSolidColorDataTexture(color);
|
|
535
643
|
}
|
|
536
644
|
/**
|
|
537
645
|
* Gets the UV references for the specified size.
|
|
538
646
|
* @param size The size for which to generate UV references.
|
|
539
647
|
* @returns The UV references.
|
|
540
648
|
*/
|
|
541
|
-
|
|
649
|
+
createUVRefs(size) {
|
|
542
650
|
const cached = this.uvRefsCache.get(size);
|
|
543
651
|
if (cached) {
|
|
544
652
|
return cached;
|
|
@@ -564,10 +672,50 @@ class InstancedMeshManager {
|
|
|
564
672
|
*/
|
|
565
673
|
createInstancedMesh(size, geometry, material) {
|
|
566
674
|
geometry = geometry || this.fallbackGeometry;
|
|
567
|
-
geometry.setAttribute("uvRef", this.
|
|
675
|
+
geometry.setAttribute("uvRef", this.createUVRefs(size));
|
|
568
676
|
const count = size * size;
|
|
569
677
|
return new THREE.InstancedMesh(geometry, material, count);
|
|
570
678
|
}
|
|
679
|
+
createSolidColorDataTexture(color, size = 16) {
|
|
680
|
+
const col = new THREE.Color(color);
|
|
681
|
+
const width = size;
|
|
682
|
+
const height = size;
|
|
683
|
+
const data = new Uint8Array(width * height * 4);
|
|
684
|
+
const r = Math.floor(col.r * 255);
|
|
685
|
+
const g = Math.floor(col.g * 255);
|
|
686
|
+
const b = Math.floor(col.b * 255);
|
|
687
|
+
for (let i = 0; i < width * height; i++) {
|
|
688
|
+
const index = i * 4;
|
|
689
|
+
data[index] = r;
|
|
690
|
+
data[index + 1] = g;
|
|
691
|
+
data[index + 2] = b;
|
|
692
|
+
data[index + 3] = 255;
|
|
693
|
+
}
|
|
694
|
+
const texture = new THREE.DataTexture(data, width, height, THREE.RGBAFormat);
|
|
695
|
+
texture.type = THREE.UnsignedByteType;
|
|
696
|
+
texture.wrapS = THREE.RepeatWrapping;
|
|
697
|
+
texture.wrapT = THREE.RepeatWrapping;
|
|
698
|
+
texture.minFilter = THREE.NearestFilter;
|
|
699
|
+
texture.magFilter = THREE.NearestFilter;
|
|
700
|
+
texture.needsUpdate = true;
|
|
701
|
+
return texture;
|
|
702
|
+
}
|
|
703
|
+
disposeSolidColorOriginTexture() {
|
|
704
|
+
if (this.originColor) {
|
|
705
|
+
this.originColor = null;
|
|
706
|
+
if (this.uniforms.uOriginTexture.value) {
|
|
707
|
+
this.uniforms.uOriginTexture.value.dispose();
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
disposeSolidColorDestinationTexture() {
|
|
712
|
+
if (this.destinationColor) {
|
|
713
|
+
this.destinationColor = null;
|
|
714
|
+
if (this.uniforms.uDestinationTexture.value) {
|
|
715
|
+
this.uniforms.uDestinationTexture.value.dispose();
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
571
719
|
}
|
|
572
720
|
class IntersectionService {
|
|
573
721
|
/**
|
|
@@ -1335,122 +1483,6 @@ class TransitionService {
|
|
|
1335
1483
|
this.eventEmitter.emit("transitionFinished", { type });
|
|
1336
1484
|
}
|
|
1337
1485
|
}
|
|
1338
|
-
class AssetService {
|
|
1339
|
-
constructor(eventEmitter) {
|
|
1340
|
-
__publicField(this, "serviceState", "created");
|
|
1341
|
-
__publicField(this, "eventEmitter");
|
|
1342
|
-
__publicField(this, "meshes", /* @__PURE__ */ new Map());
|
|
1343
|
-
__publicField(this, "textures", /* @__PURE__ */ new Map());
|
|
1344
|
-
__publicField(this, "gltfLoader", new GLTFLoader());
|
|
1345
|
-
__publicField(this, "textureLoader", new THREE.TextureLoader());
|
|
1346
|
-
__publicField(this, "dracoLoader", new DRACOLoader());
|
|
1347
|
-
__publicField(this, "solidColorTexture", new THREE.DataTexture(new Uint8Array([127, 127, 127, 255]), 1, 1, THREE.RGBAFormat));
|
|
1348
|
-
this.eventEmitter = eventEmitter;
|
|
1349
|
-
this.dracoLoader.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.7/");
|
|
1350
|
-
this.gltfLoader.setDRACOLoader(this.dracoLoader);
|
|
1351
|
-
this.updateServiceState("ready");
|
|
1352
|
-
}
|
|
1353
|
-
/**
|
|
1354
|
-
* Registers an asset.
|
|
1355
|
-
* @param id - The ID of the asset.
|
|
1356
|
-
* @param item - The asset to set.
|
|
1357
|
-
*/
|
|
1358
|
-
register(id, item) {
|
|
1359
|
-
item.name = id;
|
|
1360
|
-
if (item instanceof THREE.Mesh) {
|
|
1361
|
-
const prev = this.meshes.get(id);
|
|
1362
|
-
if (prev) disposeMesh(prev);
|
|
1363
|
-
this.meshes.set(id, item);
|
|
1364
|
-
} else {
|
|
1365
|
-
const prev = this.textures.get(id);
|
|
1366
|
-
if (prev) prev.dispose();
|
|
1367
|
-
this.textures.set(id, item);
|
|
1368
|
-
}
|
|
1369
|
-
this.eventEmitter.emit("assetRegistered", { id });
|
|
1370
|
-
}
|
|
1371
|
-
setSolidColor(color) {
|
|
1372
|
-
this.changeColor(color);
|
|
1373
|
-
}
|
|
1374
|
-
getSolidColorTexture() {
|
|
1375
|
-
return this.solidColorTexture;
|
|
1376
|
-
}
|
|
1377
|
-
getMesh(id) {
|
|
1378
|
-
return this.meshes.get(id) ?? null;
|
|
1379
|
-
}
|
|
1380
|
-
getMatcap(id) {
|
|
1381
|
-
const texture = this.textures.get(id);
|
|
1382
|
-
if (!texture) this.eventEmitter.emit("invalidRequest", { message: `texture with id "${id}" not found. using solid color texture instead...` });
|
|
1383
|
-
return texture ?? this.solidColorTexture;
|
|
1384
|
-
}
|
|
1385
|
-
getMeshIDs() {
|
|
1386
|
-
return Array.from(this.meshes.keys());
|
|
1387
|
-
}
|
|
1388
|
-
getTextureIDs() {
|
|
1389
|
-
return Array.from(this.textures.keys());
|
|
1390
|
-
}
|
|
1391
|
-
getMeshes() {
|
|
1392
|
-
return Array.from(this.meshes.values());
|
|
1393
|
-
}
|
|
1394
|
-
getTextures() {
|
|
1395
|
-
return Array.from(this.textures.values());
|
|
1396
|
-
}
|
|
1397
|
-
/**
|
|
1398
|
-
* Loads a mesh asynchronously.
|
|
1399
|
-
* @param id - The ID of the mesh.
|
|
1400
|
-
* @param url - The URL of the mesh.
|
|
1401
|
-
* @param options - Optional parameters.
|
|
1402
|
-
* @returns The loaded mesh or null.
|
|
1403
|
-
*/
|
|
1404
|
-
async loadMeshAsync(id, url, options = {}) {
|
|
1405
|
-
const gltf = await this.gltfLoader.loadAsync(url);
|
|
1406
|
-
try {
|
|
1407
|
-
if (options.meshName) {
|
|
1408
|
-
const mesh = gltf.scene.getObjectByName(options.meshName);
|
|
1409
|
-
this.register(id, mesh);
|
|
1410
|
-
return mesh;
|
|
1411
|
-
} else {
|
|
1412
|
-
const mesh = gltf.scene.children[0];
|
|
1413
|
-
this.register(id, mesh);
|
|
1414
|
-
return mesh;
|
|
1415
|
-
}
|
|
1416
|
-
} catch (error) {
|
|
1417
|
-
this.eventEmitter.emit("invalidRequest", { message: `failed to load mesh: ${id}. ${error}` });
|
|
1418
|
-
return null;
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
/**
|
|
1422
|
-
* Loads a texture asynchronously.
|
|
1423
|
-
* @param id - The ID of the texture.
|
|
1424
|
-
* @param url - The URL of the texture.
|
|
1425
|
-
* @returns The loaded texture or null.
|
|
1426
|
-
*/
|
|
1427
|
-
async loadTextureAsync(id, url) {
|
|
1428
|
-
try {
|
|
1429
|
-
const texture = await this.textureLoader.loadAsync(url);
|
|
1430
|
-
this.register(id, texture);
|
|
1431
|
-
return texture;
|
|
1432
|
-
} catch (error) {
|
|
1433
|
-
this.eventEmitter.emit("invalidRequest", { message: `failed to load texture: ${id}. ${error}` });
|
|
1434
|
-
return null;
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
dispose() {
|
|
1438
|
-
this.updateServiceState("disposed");
|
|
1439
|
-
this.meshes.forEach((mesh) => disposeMesh(mesh));
|
|
1440
|
-
this.meshes.clear();
|
|
1441
|
-
this.textures.forEach((texture) => texture.dispose());
|
|
1442
|
-
this.textures.clear();
|
|
1443
|
-
}
|
|
1444
|
-
changeColor(color) {
|
|
1445
|
-
const actual = new THREE.Color(color);
|
|
1446
|
-
this.solidColorTexture = new THREE.DataTexture(new Uint8Array([actual.r, actual.g, actual.b, 255]), 1, 1, THREE.RGBAFormat);
|
|
1447
|
-
this.solidColorTexture.needsUpdate = true;
|
|
1448
|
-
}
|
|
1449
|
-
updateServiceState(serviceState) {
|
|
1450
|
-
this.serviceState = serviceState;
|
|
1451
|
-
this.eventEmitter.emit("serviceStateUpdated", { type: "asset", state: serviceState });
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
1486
|
class ParticlesEngine {
|
|
1455
1487
|
/**
|
|
1456
1488
|
* Creates a new ParticlesEngine instance.
|
|
@@ -1543,6 +1575,30 @@ class ParticlesEngine {
|
|
|
1543
1575
|
this.engineState.destinationMatcapID = matcapID;
|
|
1544
1576
|
this.instancedMeshManager.setDestinationMatcap(this.assetService.getMatcap(matcapID));
|
|
1545
1577
|
}
|
|
1578
|
+
setOriginColor(color, override = false) {
|
|
1579
|
+
if (override) this.eventEmitter.emit("transitionCancelled", { type: "matcap" });
|
|
1580
|
+
this.instancedMeshManager.setOriginColor(color);
|
|
1581
|
+
}
|
|
1582
|
+
setDestinationColor(color, override = false) {
|
|
1583
|
+
if (override) this.eventEmitter.emit("transitionCancelled", { type: "matcap" });
|
|
1584
|
+
this.instancedMeshManager.setDestinationColor(color);
|
|
1585
|
+
}
|
|
1586
|
+
setOriginTexture(id, override = false) {
|
|
1587
|
+
if (override) this.eventEmitter.emit("transitionCancelled", { type: "matcap" });
|
|
1588
|
+
if (typeof id === "string" && this.assetService.hasMatcap(id)) {
|
|
1589
|
+
this.setOriginMatcap(id);
|
|
1590
|
+
} else {
|
|
1591
|
+
this.setOriginColor(id);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
setDestinationTexture(id, override = false) {
|
|
1595
|
+
if (override) this.eventEmitter.emit("transitionCancelled", { type: "matcap" });
|
|
1596
|
+
if (typeof id === "string" && this.assetService.hasMatcap(id)) {
|
|
1597
|
+
this.setDestinationMatcap(id);
|
|
1598
|
+
} else {
|
|
1599
|
+
this.setDestinationColor(id);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1546
1602
|
setMatcapProgress(progress, override = false) {
|
|
1547
1603
|
if (override) this.eventEmitter.emit("transitionCancelled", { type: "matcap" });
|
|
1548
1604
|
this.engineState.matcapTransitionProgress = progress;
|
|
@@ -1563,7 +1619,12 @@ class ParticlesEngine {
|
|
|
1563
1619
|
this.eventEmitter.emit("invalidRequest", { message: `Mesh with id "${this.engineState.destinationMeshID}" does not exist` });
|
|
1564
1620
|
return;
|
|
1565
1621
|
}
|
|
1566
|
-
this.dataTextureManager.getDataTexture(originMesh).then(
|
|
1622
|
+
this.dataTextureManager.getDataTexture(originMesh).then(
|
|
1623
|
+
(texture) => this.simulationRendererService.setOriginDataTexture({
|
|
1624
|
+
dataTexture: texture,
|
|
1625
|
+
textureSize: size
|
|
1626
|
+
})
|
|
1627
|
+
);
|
|
1567
1628
|
this.dataTextureManager.getDataTexture(destinationMesh).then(
|
|
1568
1629
|
(texture) => this.simulationRendererService.setDestinationDataTexture({
|
|
1569
1630
|
dataTexture: texture,
|
|
@@ -1636,6 +1697,24 @@ class ParticlesEngine {
|
|
|
1636
1697
|
}
|
|
1637
1698
|
);
|
|
1638
1699
|
}
|
|
1700
|
+
scheduleTextureTransition(origin, destination, options) {
|
|
1701
|
+
const easing = (options == null ? void 0 : options.easing) ?? linear;
|
|
1702
|
+
const duration = (options == null ? void 0 : options.duration) ?? 1e3;
|
|
1703
|
+
if (options == null ? void 0 : options.override) {
|
|
1704
|
+
this.eventEmitter.emit("transitionCancelled", { type: "matcap" });
|
|
1705
|
+
}
|
|
1706
|
+
this.transitionService.enqueue(
|
|
1707
|
+
"matcap",
|
|
1708
|
+
{ easing, duration },
|
|
1709
|
+
{
|
|
1710
|
+
onTransitionBegin: () => {
|
|
1711
|
+
this.setOriginTexture(origin);
|
|
1712
|
+
this.setDestinationTexture(destination);
|
|
1713
|
+
this.setMatcapProgress(0);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
);
|
|
1717
|
+
}
|
|
1639
1718
|
handleServiceStateUpdated({ type, state }) {
|
|
1640
1719
|
this.serviceStates[type] = state;
|
|
1641
1720
|
}
|