entangled-worlds-orbiters-shared 1.0.1 → 1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "entangled-worlds-orbiters-shared",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
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": "src/index.js",
@@ -18,12 +18,10 @@ let configPromise = null;
18
18
  */
19
19
  export async function loadTextureConfig(configUrl = DEFAULT_CONFIG_URL, useCache = true) {
20
20
  if (useCache && cachedConfig) {
21
- console.log('[TextureConfig] Using cached config');
22
21
  return cachedConfig;
23
22
  }
24
23
 
25
24
  if (configPromise) {
26
- console.log('[TextureConfig] Using in-flight request');
27
25
  return configPromise;
28
26
  }
29
27
 
@@ -31,7 +29,6 @@ export async function loadTextureConfig(configUrl = DEFAULT_CONFIG_URL, useCache
31
29
  try {
32
30
  // Resolve config URL against public base if it's a relative path
33
31
  const resolvedConfigUrl = /^https?:\/\//i.test(configUrl) ? configUrl : resolvePublicUrl(configUrl);
34
- console.log('[TextureConfig] Loading from:', resolvedConfigUrl);
35
32
  const response = await fetch(resolvedConfigUrl);
36
33
 
37
34
  if (!response.ok) {
@@ -46,19 +43,12 @@ export async function loadTextureConfig(configUrl = DEFAULT_CONFIG_URL, useCache
46
43
  }
47
44
 
48
45
  cachedConfig = config;
49
- console.log('[TextureConfig] Loaded successfully:', {
50
- version: config.version,
51
- categories: Object.keys(config.textures),
52
- lastUpdated: config.lastUpdated
53
- });
54
-
55
46
  return config;
56
47
  } catch (error) {
57
48
  console.error('[TextureConfig] Failed to load config:', error);
58
49
 
59
50
  // If primary URL fails and it's not already the fallback, try fallback
60
51
  if (configUrl !== FALLBACK_CONFIG_URL) {
61
- console.log('[TextureConfig] Trying fallback endpoint...');
62
52
  try {
63
53
  return await loadTextureConfig(FALLBACK_CONFIG_URL, false);
64
54
  } catch (fallbackError) {
@@ -51,7 +51,6 @@ export async function loadGLB(url, { retries = 3, signal, onProgress, applyFlags
51
51
  child.material.emissive.setHex(0x888888);
52
52
  child.material.emissiveMap = child.material.map;
53
53
  child.material.emissiveIntensity = 1.0;
54
- console.log('✅ KTX2 texture loaded:', child.material.map.constructor.name, `${child.material.map.image.width}x${child.material.map.image.height}`);
55
54
  }
56
55
  child.material.needsUpdate = true;
57
56
  child.castShadow = false;
@@ -64,16 +64,6 @@ export async function generateMoons({
64
64
  return Math.random(); // Use regular random if no seed
65
65
  };
66
66
 
67
- // Log the seed being used for debugging
68
- if (debug) {
69
- console.log('[Moons] Using seed for deterministic positioning:', {
70
- originalSeed: seed,
71
- seedValue: seedValue,
72
- seedType: typeof seed,
73
- isSeeded: seedValue !== null
74
- });
75
- }
76
-
77
67
  const moonGeometry = new THREE.SphereGeometry(0.1, geometryWidthSegments, geometryHeightSegments);
78
68
 
79
69
  // Optional UV grid override
@@ -106,20 +96,16 @@ export async function generateMoons({
106
96
  // Resolve textureKey to absolute URL if it's relative
107
97
  if (textureKey && textureKey.startsWith('/')) {
108
98
  primaryTexture = `${HERBARIUM_BASE}${textureKey}`;
109
- if (debug) console.log('[Moons] Using custom texture key:', textureKey, '-> resolved:', primaryTexture);
110
99
  } else if (textureKey) {
111
100
  primaryTexture = textureKey; // already absolute
112
- if (debug) console.log('[Moons] Using absolute texture URL:', primaryTexture);
113
101
  }
114
102
 
115
103
  try {
116
104
  sharedTexture = await loadTexture(primaryTexture);
117
- if (debug) console.log('[Moons] Loaded texture from:', primaryTexture);
118
105
  } catch (eKTX) {
119
106
  if (debug) console.warn('[Moons] Primary texture failed, trying fallback:', eKTX);
120
107
  try {
121
108
  sharedTexture = await loadTexture(fallbackTexture);
122
- if (debug) console.log('[Moons] Fallback texture loaded from:', fallbackTexture);
123
109
  } catch (ePNG) {
124
110
  if (debug) console.warn('[Moons] Both primary and fallback texture loading failed');
125
111
  }
@@ -16,13 +16,11 @@ export class WorldManager {
16
16
  }
17
17
 
18
18
  setFlags(flags) {
19
- console.log('[WorldManager] setFlags:', flags);
20
19
  this.flags = { ...this.flags, ...flags };
21
20
  }
22
21
 
23
22
  disposeCurrent() {
24
23
  if (this.current) {
25
- console.log('[WorldManager] disposeCurrent:', this.current?.name || this.current);
26
24
  disposeObject3D(this.current);
27
25
  this.scene.remove(this.current);
28
26
  this.current = null;
@@ -36,39 +34,31 @@ export class WorldManager {
36
34
 
37
35
  async setMode(mode, args = {}) {
38
36
  const myToken = ++this.token;
39
- console.log('[WorldManager] setMode request:', { mode, args });
40
37
  this.onLoadStart?.();
41
38
  try {
42
39
  let obj;
43
40
 
44
41
  // Check for custom creators first
45
42
  if (this.customCreators.has(mode)) {
46
- console.log(`[WorldManager] -> custom creator for mode ${mode}`);
47
43
  obj = await this.customCreators.get(mode)({ flags: this.flags, ...args });
48
44
  } else if (mode === 2) {
49
- console.log('[WorldManager] -> makeGLB');
50
45
  obj = await makeGLB({ modelUrl: args.modelUrl, flags: this.flags });
51
46
  } else if (mode === 3) {
52
- console.log('[WorldManager] -> makeNormalSphere');
53
47
  obj = await makeNormalSphere({ flags: this.flags, ...args });
54
48
  } else {
55
- console.log('[WorldManager] -> makeSphere (textured)');
56
49
  obj = await makeSphere({ textureUrl: args.textureUrl, flags: this.flags, ...args });
57
50
  }
58
51
 
59
52
  if (this.token !== myToken) {
60
- console.log('[WorldManager] setMode superseded, abandoning result');
61
53
  return;
62
54
  }
63
55
  this.disposeCurrent();
64
56
  this.scene.add(obj);
65
57
  this.current = obj;
66
- console.log('[WorldManager] setMode applied. current:', obj?.name || obj);
67
58
 
68
59
  // If the object exposes a frame updater, run a render-time loop
69
60
  if (obj && obj.userData && typeof obj.userData.update === 'function' && window.__EW_RENDERER) {
70
61
  const updater = obj.userData.update;
71
- console.log('[WorldManager] update loop started for', obj.name || obj);
72
62
  const tick = () => {
73
63
  if (this.current === obj) {
74
64
  try {
@@ -77,8 +67,6 @@ export class WorldManager {
77
67
  console.warn('[WorldManager] update loop error:', e);
78
68
  }
79
69
  requestAnimationFrame(tick);
80
- } else {
81
- console.log('[WorldManager] update loop stopped (object replaced)');
82
70
  }
83
71
  };
84
72
  requestAnimationFrame(tick);
@@ -2,6 +2,9 @@
2
2
  import * as THREE from 'three';
3
3
  import { EARTH_RADIUS_UNITS } from './worldTexture.js';
4
4
  import { applyFlagsToMaterial } from '../utils/materials.js';
5
+ import { getLightFresnel } from '../core/lightFresnel.js';
6
+ import { createCloudShell } from './cloudShell.js';
7
+ import { resolvePublicUrl } from '../config/env.js';
5
8
 
6
9
  /**
7
10
  * Create a simple sphere using THREE.MeshNormalMaterial.
@@ -12,6 +15,18 @@ export async function makeNormalSphere({
12
15
  sphereWidthSegments,
13
16
  sphereHeightSegments,
14
17
  flags,
18
+ glow, // halo (glow) enabled
19
+ glowScale = 1.18,
20
+ glowRimHex = 0x66ccff,
21
+ glowFacingHex = 0x000000,
22
+ glowBias = 0.02,
23
+ glowFresnelScale = 1.0,
24
+ glowPower = 3.5,
25
+ cloudsEnabled,
26
+ cloudsTextureUrl = '/assets/texture/2k_earth_clouds.jpg',
27
+ cloudsColor = 0xffffff,
28
+ cloudsOpacity = 0.6,
29
+ cloudsSpeed = 0.015,
15
30
  } = {}) {
16
31
  const radius = typeof sphereRadius === 'number' ? Math.max(0.0001, sphereRadius) : EARTH_RADIUS_UNITS;
17
32
  const widthSegs = Number.isFinite(sphereWidthSegments) ? Math.max(3, Math.floor(sphereWidthSegments)) : 64;
@@ -21,5 +36,36 @@ export async function makeNormalSphere({
21
36
  if (flags) applyFlagsToMaterial(material, flags);
22
37
  const mesh = new THREE.Mesh(geometry, material);
23
38
  mesh.name = 'worldNormalSphere';
39
+
40
+ // Attach halo (glow) effect if enabled
41
+ if (glow) {
42
+ const fresnelMat = getLightFresnel({ rimHex: glowRimHex, facingHex: glowFacingHex });
43
+ fresnelMat.uniforms.fresnelBias.value = glowBias;
44
+ fresnelMat.uniforms.fresnelScale.value = glowFresnelScale;
45
+ fresnelMat.uniforms.fresnelPower.value = glowPower;
46
+
47
+ const glowGeom = geometry.clone();
48
+ const fresnelMesh = new THREE.Mesh(glowGeom, fresnelMat);
49
+ fresnelMesh.scale.set(glowScale, glowScale, glowScale);
50
+ fresnelMesh.renderOrder = 999;
51
+ fresnelMesh.name = 'worldNormalGlow';
52
+ mesh.add(fresnelMesh);
53
+ }
54
+
55
+ // Attach clouds effect if enabled
56
+ if (cloudsEnabled) {
57
+ const cloudMesh = await createCloudShell({
58
+ baseGeometry: geometry,
59
+ baseRadius: radius,
60
+ widthSegments: widthSegs,
61
+ heightSegments: heightSegs,
62
+ textureUrl: resolvePublicUrl(cloudsTextureUrl),
63
+ color: cloudsColor,
64
+ opacity: cloudsOpacity,
65
+ speed: cloudsSpeed,
66
+ });
67
+ mesh.add(cloudMesh);
68
+ }
69
+
24
70
  return mesh;
25
71
  }
@@ -109,10 +109,15 @@ export async function makeSphere({
109
109
  try {
110
110
  const tex = await loadTexture(chosenTexture);
111
111
  tex.colorSpace = THREE.SRGBColorSpace;
112
- tex.generateMipmaps = true;
113
112
  tex.anisotropy = 8;
114
113
  if (typeof flipY === 'boolean') tex.flipY = flipY;
115
114
 
115
+ // Only enable mipmaps for non-compressed, power-of-two textures
116
+ const isCompressed = tex.isCompressedTexture;
117
+ const img = tex.image;
118
+ const isPowerOfTwo = img && ((img.width & (img.width - 1)) === 0) && ((img.height & (img.height - 1)) === 0);
119
+ tex.generateMipmaps = !isCompressed && isPowerOfTwo;
120
+
116
121
  // Decide mapping approach
117
122
  let shouldMirrorDuplicate = mirrorDuplicateX;
118
123
  if (tex.image) {