entangled-worlds-orbiters-shared 6.0.1 → 6.0.2
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/world/cloudShell.d.ts +8 -0
- package/dist/world/cloudShell.js +23 -4
- package/dist/world/worldNormal.js +11 -2
- package/dist/world/worldTexture.js +11 -2
- package/package.json +1 -1
- package/src/world/cloudShell.ts +23 -5
- package/src/world/worldNormal.ts +9 -2
- package/src/world/worldTexture.ts +9 -2
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* The cloud texture could not be loaded (offline, gone from the CDN, or not decodable). Its own type
|
|
4
|
+
* so the world builders can drop just the clouds on THIS failure and still let any other error out.
|
|
5
|
+
* `cause` is what the loader threw.
|
|
6
|
+
*/
|
|
7
|
+
export declare class CloudTextureError extends Error {
|
|
8
|
+
constructor(url: string, cause: unknown);
|
|
9
|
+
}
|
|
2
10
|
/**
|
|
3
11
|
* `baseGeometry` is cloned for the shell; when absent a sphere is built from `baseRadius` (0.5) and
|
|
4
12
|
* the segment counts (64 × 64). Defaults: `color` 0xffffff, `opacity` 0.6, `speed` 0.015.
|
package/dist/world/cloudShell.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { loadTexture } from '../loaders/bodyTextureLoader.js';
|
|
3
|
+
/**
|
|
4
|
+
* The cloud texture could not be loaded (offline, gone from the CDN, or not decodable). Its own type
|
|
5
|
+
* so the world builders can drop just the clouds on THIS failure and still let any other error out.
|
|
6
|
+
* `cause` is what the loader threw.
|
|
7
|
+
*/
|
|
8
|
+
export class CloudTextureError extends Error {
|
|
9
|
+
constructor(url, cause) {
|
|
10
|
+
super(`Cloud texture could not be loaded: ${url}`, { cause });
|
|
11
|
+
this.name = 'CloudTextureError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
3
14
|
// Texture-only clouds material (alpha mask + tint), UV-scrolled
|
|
4
15
|
async function makeTextureMaterial({ color = 0xffffff, opacity = 0.6, textureUrl, speed = 0.015, renderer = null, } = {}) {
|
|
5
16
|
// Diffuse-only (Lambert): the star's key light costs no specular pass.
|
|
@@ -15,7 +26,14 @@ async function makeTextureMaterial({ color = 0xffffff, opacity = 0.6, textureUrl
|
|
|
15
26
|
if (textureUrl) {
|
|
16
27
|
// Thread the owning view's renderer: KTX2 cloud textures must transcode against the caller's
|
|
17
28
|
// context, not the global fallback (which shared-renderer pages don't publish at all).
|
|
18
|
-
|
|
29
|
+
let tex;
|
|
30
|
+
try {
|
|
31
|
+
tex = await loadTexture(textureUrl, { renderer });
|
|
32
|
+
}
|
|
33
|
+
catch (cause) {
|
|
34
|
+
mat.dispose();
|
|
35
|
+
throw new CloudTextureError(textureUrl, cause);
|
|
36
|
+
}
|
|
19
37
|
tex.wrapS = THREE.RepeatWrapping;
|
|
20
38
|
tex.wrapT = THREE.RepeatWrapping;
|
|
21
39
|
// Use linear space for alpha masks if available
|
|
@@ -48,9 +66,7 @@ async function makeTextureMaterial({ color = 0xffffff, opacity = 0.6, textureUrl
|
|
|
48
66
|
* the segment counts (64 × 64). Defaults: `color` 0xffffff, `opacity` 0.6, `speed` 0.015.
|
|
49
67
|
*/
|
|
50
68
|
export async function createCloudShell({ baseGeometry, baseRadius = 0.5, widthSegments = 64, heightSegments = 64, textureUrl = '/assets/texture/2k_earth_clouds.jpg', color = 0xffffff, opacity = 0.6, speed = 0.015, renderer = null, } = {}) {
|
|
51
|
-
|
|
52
|
-
? baseGeometry.clone()
|
|
53
|
-
: new THREE.SphereGeometry(baseRadius, widthSegments, heightSegments);
|
|
69
|
+
// The texture first: when it cannot be loaded this throws before any geometry exists to leak.
|
|
54
70
|
const material = await makeTextureMaterial({
|
|
55
71
|
color,
|
|
56
72
|
opacity,
|
|
@@ -58,6 +74,9 @@ export async function createCloudShell({ baseGeometry, baseRadius = 0.5, widthSe
|
|
|
58
74
|
speed,
|
|
59
75
|
renderer,
|
|
60
76
|
});
|
|
77
|
+
const geom = baseGeometry
|
|
78
|
+
? baseGeometry.clone()
|
|
79
|
+
: new THREE.SphereGeometry(baseRadius, widthSegments, heightSegments);
|
|
61
80
|
const mesh = new THREE.Mesh(geom, material);
|
|
62
81
|
const s = 1.001; // fixed scale
|
|
63
82
|
mesh.scale.set(s, s, s);
|
|
@@ -3,7 +3,7 @@ import * as THREE from 'three';
|
|
|
3
3
|
import { EARTH_RADIUS_UNITS } from './worldTexture.js';
|
|
4
4
|
import { applyFlagsToMaterial } from '../utils/materials.js';
|
|
5
5
|
import { getLightFresnel } from '../core/lightFresnel.js';
|
|
6
|
-
import { createCloudShell } from './cloudShell.js';
|
|
6
|
+
import { CloudTextureError, createCloudShell } from './cloudShell.js';
|
|
7
7
|
import { resolvePublicUrl } from '../config/env.js';
|
|
8
8
|
/**
|
|
9
9
|
* Create a simple sphere using THREE.MeshNormalMaterial.
|
|
@@ -51,8 +51,17 @@ glowScale = 1.18, glowRimHex = 0x66ccff, glowFacingHex = 0x000000, glowBias = 0.
|
|
|
51
51
|
opacity: cloudsOpacity,
|
|
52
52
|
speed: cloudsSpeed,
|
|
53
53
|
renderer,
|
|
54
|
+
}).catch((e) => {
|
|
55
|
+
// Clouds are an optional layer: a texture that cannot be loaded (offline, or gone from the
|
|
56
|
+
// CDN) costs the clouds, never the planet — the same way a failed surface texture does. Only
|
|
57
|
+
// that: any other error building the shell is a bug and still fails the build.
|
|
58
|
+
if (!(e instanceof CloudTextureError))
|
|
59
|
+
throw e;
|
|
60
|
+
console.warn('[worldNormal] Failed to load clouds, drawing the world without them:', e.cause);
|
|
61
|
+
return null;
|
|
54
62
|
});
|
|
55
|
-
|
|
63
|
+
if (cloudMesh)
|
|
64
|
+
mesh.add(cloudMesh);
|
|
56
65
|
}
|
|
57
66
|
return mesh;
|
|
58
67
|
}
|
|
@@ -2,7 +2,7 @@ import * as THREE from 'three';
|
|
|
2
2
|
import { loadTexture } from '../loaders/bodyTextureLoader.js';
|
|
3
3
|
import { applyFlagsToMaterial } from '../utils/materials.js';
|
|
4
4
|
import { getLightFresnel } from '../core/lightFresnel.js';
|
|
5
|
-
import { createCloudShell } from './cloudShell.js';
|
|
5
|
+
import { CloudTextureError, createCloudShell } from './cloudShell.js';
|
|
6
6
|
import { resolvePublicUrl } from '../config/env.js';
|
|
7
7
|
// Debug tag so you can verify the loaded file version in console
|
|
8
8
|
export const WORLD_TEXTURE_DEBUG_TAG = 'WT:vFlipGeom-r3@2025-10-28T17:22:00Z';
|
|
@@ -287,8 +287,17 @@ cloudsEnabled = false, cloudsTextureUrl = '/assets/texture/2k_earth_clouds.jpg',
|
|
|
287
287
|
opacity: cloudsOpacity,
|
|
288
288
|
speed: cloudsSpeed,
|
|
289
289
|
renderer,
|
|
290
|
+
}).catch((e) => {
|
|
291
|
+
// Clouds are an optional layer: a texture that cannot be loaded (offline, or gone from the
|
|
292
|
+
// CDN) costs the clouds, never the planet — the same way a failed surface texture does. Only
|
|
293
|
+
// that: any other error building the shell is a bug and still fails the build.
|
|
294
|
+
if (!(e instanceof CloudTextureError))
|
|
295
|
+
throw e;
|
|
296
|
+
console.warn('[worldTexture] Failed to load clouds, drawing the world without them:', e.cause);
|
|
297
|
+
return null;
|
|
290
298
|
});
|
|
291
|
-
|
|
299
|
+
if (cloudMesh)
|
|
300
|
+
mesh.add(cloudMesh);
|
|
292
301
|
}
|
|
293
302
|
// Optionally add glow as a child of the mesh so it follows transforms
|
|
294
303
|
if (glow) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "entangled-worlds-orbiters-shared",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "Shared library for entangled worlds orbiters - contains core world rendering, moons system, and UI components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/src/world/cloudShell.ts
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { loadTexture } from '../loaders/bodyTextureLoader.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The cloud texture could not be loaded (offline, gone from the CDN, or not decodable). Its own type
|
|
6
|
+
* so the world builders can drop just the clouds on THIS failure and still let any other error out.
|
|
7
|
+
* `cause` is what the loader threw.
|
|
8
|
+
*/
|
|
9
|
+
export class CloudTextureError extends Error {
|
|
10
|
+
constructor(url: string, cause: unknown) {
|
|
11
|
+
super(`Cloud texture could not be loaded: ${url}`, { cause });
|
|
12
|
+
this.name = 'CloudTextureError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
// Texture-only clouds material (alpha mask + tint), UV-scrolled
|
|
5
17
|
async function makeTextureMaterial({
|
|
6
18
|
color = 0xffffff,
|
|
@@ -29,7 +41,13 @@ async function makeTextureMaterial({
|
|
|
29
41
|
if (textureUrl) {
|
|
30
42
|
// Thread the owning view's renderer: KTX2 cloud textures must transcode against the caller's
|
|
31
43
|
// context, not the global fallback (which shared-renderer pages don't publish at all).
|
|
32
|
-
|
|
44
|
+
let tex: THREE.Texture;
|
|
45
|
+
try {
|
|
46
|
+
tex = await loadTexture(textureUrl, { renderer });
|
|
47
|
+
} catch (cause) {
|
|
48
|
+
mat.dispose();
|
|
49
|
+
throw new CloudTextureError(textureUrl, cause);
|
|
50
|
+
}
|
|
33
51
|
tex.wrapS = THREE.RepeatWrapping;
|
|
34
52
|
tex.wrapT = THREE.RepeatWrapping;
|
|
35
53
|
// Use linear space for alpha masks if available
|
|
@@ -84,10 +102,7 @@ export async function createCloudShell({
|
|
|
84
102
|
speed?: number | undefined;
|
|
85
103
|
renderer?: THREE.WebGLRenderer | null | undefined;
|
|
86
104
|
} = {}) {
|
|
87
|
-
|
|
88
|
-
? baseGeometry.clone()
|
|
89
|
-
: new THREE.SphereGeometry(baseRadius, widthSegments, heightSegments);
|
|
90
|
-
|
|
105
|
+
// The texture first: when it cannot be loaded this throws before any geometry exists to leak.
|
|
91
106
|
const material = await makeTextureMaterial({
|
|
92
107
|
color,
|
|
93
108
|
opacity,
|
|
@@ -95,6 +110,9 @@ export async function createCloudShell({
|
|
|
95
110
|
speed,
|
|
96
111
|
renderer,
|
|
97
112
|
});
|
|
113
|
+
const geom = baseGeometry
|
|
114
|
+
? baseGeometry.clone()
|
|
115
|
+
: new THREE.SphereGeometry(baseRadius, widthSegments, heightSegments);
|
|
98
116
|
|
|
99
117
|
const mesh = new THREE.Mesh(geom, material);
|
|
100
118
|
const s = 1.001; // fixed scale
|
package/src/world/worldNormal.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as THREE from 'three';
|
|
|
3
3
|
import { EARTH_RADIUS_UNITS } from './worldTexture.js';
|
|
4
4
|
import { applyFlagsToMaterial } from '../utils/materials.js';
|
|
5
5
|
import { getLightFresnel } from '../core/lightFresnel.js';
|
|
6
|
-
import { createCloudShell } from './cloudShell.js';
|
|
6
|
+
import { CloudTextureError, createCloudShell } from './cloudShell.js';
|
|
7
7
|
import { resolvePublicUrl } from '../config/env.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -89,8 +89,15 @@ export async function makeNormalSphere({
|
|
|
89
89
|
opacity: cloudsOpacity,
|
|
90
90
|
speed: cloudsSpeed,
|
|
91
91
|
renderer,
|
|
92
|
+
}).catch((e: unknown) => {
|
|
93
|
+
// Clouds are an optional layer: a texture that cannot be loaded (offline, or gone from the
|
|
94
|
+
// CDN) costs the clouds, never the planet — the same way a failed surface texture does. Only
|
|
95
|
+
// that: any other error building the shell is a bug and still fails the build.
|
|
96
|
+
if (!(e instanceof CloudTextureError)) throw e;
|
|
97
|
+
console.warn('[worldNormal] Failed to load clouds, drawing the world without them:', e.cause);
|
|
98
|
+
return null;
|
|
92
99
|
});
|
|
93
|
-
mesh.add(cloudMesh);
|
|
100
|
+
if (cloudMesh) mesh.add(cloudMesh);
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
return mesh;
|
|
@@ -2,7 +2,7 @@ import * as THREE from 'three';
|
|
|
2
2
|
import { loadTexture } from '../loaders/bodyTextureLoader.js';
|
|
3
3
|
import { applyFlagsToMaterial } from '../utils/materials.js';
|
|
4
4
|
import { getLightFresnel } from '../core/lightFresnel.js';
|
|
5
|
-
import { createCloudShell } from './cloudShell.js';
|
|
5
|
+
import { CloudTextureError, createCloudShell } from './cloudShell.js';
|
|
6
6
|
import { resolvePublicUrl } from '../config/env.js';
|
|
7
7
|
|
|
8
8
|
// Debug tag so you can verify the loaded file version in console
|
|
@@ -374,8 +374,15 @@ export async function makeSphere({
|
|
|
374
374
|
opacity: cloudsOpacity,
|
|
375
375
|
speed: cloudsSpeed,
|
|
376
376
|
renderer,
|
|
377
|
+
}).catch((e: unknown) => {
|
|
378
|
+
// Clouds are an optional layer: a texture that cannot be loaded (offline, or gone from the
|
|
379
|
+
// CDN) costs the clouds, never the planet — the same way a failed surface texture does. Only
|
|
380
|
+
// that: any other error building the shell is a bug and still fails the build.
|
|
381
|
+
if (!(e instanceof CloudTextureError)) throw e;
|
|
382
|
+
console.warn('[worldTexture] Failed to load clouds, drawing the world without them:', e.cause);
|
|
383
|
+
return null;
|
|
377
384
|
});
|
|
378
|
-
mesh.add(cloudMesh);
|
|
385
|
+
if (cloudMesh) mesh.add(cloudMesh);
|
|
379
386
|
}
|
|
380
387
|
|
|
381
388
|
// Optionally add glow as a child of the mesh so it follows transforms
|