merge perihelion/m-selene → main: moon maps + tidal lock, gate green (fable)
BIN
assets/textures/1k_callisto.jpg
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
assets/textures/1k_charon.jpg
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
assets/textures/1k_europa.jpg
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
assets/textures/1k_ganymede.jpg
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
assets/textures/1k_io.jpg
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
assets/textures/1k_phobos.jpg
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
assets/textures/1k_titan.jpg
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
assets/textures/1k_triton.jpg
Normal file
|
After Width: | Height: | Size: 87 KiB |
@ -1,7 +1,9 @@
|
|||||||
# Texture credits
|
# Texture credits
|
||||||
|
|
||||||
All planet, moon, Sun, ring and starfield maps in this directory are from the
|
## `2k_*` planet, Sun, ring & starfield maps — Solar System Scope (CC BY 4.0)
|
||||||
**Solar System Scope** texture pack and are used under **CC BY 4.0**.
|
|
||||||
|
The **`2k_`** planet, Moon, Sun, ring and starfield maps in this directory are from
|
||||||
|
the **Solar System Scope** texture pack and are used under **CC BY 4.0**.
|
||||||
|
|
||||||
- Source: https://www.solarsystemscope.com/textures/
|
- Source: https://www.solarsystemscope.com/textures/
|
||||||
- License: Creative Commons Attribution 4.0 International (CC BY 4.0)
|
- License: Creative Commons Attribution 4.0 International (CC BY 4.0)
|
||||||
@ -28,6 +30,29 @@ Downloaded 2026-07-16 at 2k resolution:
|
|||||||
|
|
||||||
Attribution also appears in the app's HUD footer, as CC BY requires.
|
Attribution also appears in the app's HUD footer, as CC BY requires.
|
||||||
|
|
||||||
|
## `1k_*` moon maps — USGS Astrogeology / NASA (public domain)
|
||||||
|
|
||||||
|
Added wave 2 (PERIHELION · SELENE). Global equirectangular (simple-cylindrical)
|
||||||
|
mosaics from the **USGS Astrogeology Science Center** (`planetarymaps.usgs.gov`),
|
||||||
|
built from NASA mission imagery. USGS/NASA-produced planetary data are in the
|
||||||
|
**U.S. public domain** (no copyright asserted). Each was downloaded as a GeoTIFF
|
||||||
|
and downscaled to 1024×512 JPEG with `sips` (Europa re-encoded at q70 to stay
|
||||||
|
under budget). Downloaded 2026-07-16.
|
||||||
|
|
||||||
|
| File | Body | Mission / instrument | Source (USGS Astrogeology) | License |
|
||||||
|
|------|------|----------------------|----------------------------|---------|
|
||||||
|
| 1k_io.jpg | Io | Galileo SSI + Voyager, color-merge | `.../mosaic/Io_Galileo_SSI_Global_Mosaic_ClrMerge_1km.tif` | Public domain |
|
||||||
|
| 1k_europa.jpg | Europa | Voyager + Galileo SSI, global 500 m | `.../mosaic/Europa_Voyager_GalileoSSI_global_mosaic_500m.tif` | Public domain |
|
||||||
|
| 1k_ganymede.jpg | Ganymede | Voyager + Galileo SSI, global color 1435 m | `.../mosaic/Ganymede_Voyager_GalileoSSI_Global_ClrMosaic_1435m.tif` | Public domain |
|
||||||
|
| 1k_callisto.jpg | Callisto | Voyager + Galileo SSI, global 1 km | `.../mosaic/Callisto_Voyager_GalileoSSI_global_mosaic_1km.tif` | Public domain |
|
||||||
|
| 1k_titan.jpg | Titan | Cassini ISS, global mosaic (PIA19658), 4 km | `.../mosaic/Titan_ISS_P19658_Mosaic_Global_4km.tif` | Public domain |
|
||||||
|
| 1k_triton.jpg | Triton | Voyager 2, global color mosaic (gap-filled) 600 m | `.../mosaic/Triton_Voyager2_ClrMosaic_GlobalFill_600m.tif` | Public domain |
|
||||||
|
| 1k_charon.jpg | Charon | New Horizons LORRI/MVIC, global mosaic 300 m (Jul 2017) | `.../mosaic/Charon_NewHorizons_Global_Mosaic_300m_Jul2017_8bit.tif` | Public domain |
|
||||||
|
| 1k_phobos.jpg | Phobos | Mars Express HRSC-SRC, global mosaic 16 ppd | `.../mosaic/Phobos_ME_SRC_Mosaic_Global_16ppd.tif` | Public domain |
|
||||||
|
|
||||||
|
Host base URL: `https://planetarymaps.usgs.gov/mosaic/` (served from the USGS
|
||||||
|
`asc-pds-services` bucket). USGS terms: <https://www.usgs.gov/information-policies-and-instructions/copyrights-and-credits>.
|
||||||
|
|
||||||
**Truth boundary (brief §7b):** these are the *real data* textures — real worlds
|
**Truth boundary (brief §7b):** these are the *real data* textures — real worlds
|
||||||
get real maps. The stylized grimoire portraits in `../art/grimoire/` are the
|
get real maps. The stylized grimoire portraits in `../art/grimoire/` are the
|
||||||
*aesthetic* layer (generated art), kept visually and directorially separate.
|
*aesthetic* layer (generated art), kept visually and directorially separate.
|
||||||
|
|||||||
16
js/bodies.js
@ -62,18 +62,18 @@ export const BODIES = {
|
|||||||
parent: 'earth', moonOrbit: { aKm: 384400, periodDays: 27.322 } },
|
parent: 'earth', moonOrbit: { aKm: 384400, periodDays: 27.322 } },
|
||||||
|
|
||||||
phobos: { name: 'Phobos', type: 'moon', radiusKm: 11.27, color: '#8a7c6e',
|
phobos: { name: 'Phobos', type: 'moon', radiusKm: 11.27, color: '#8a7c6e',
|
||||||
texture: null, parent: 'mars', moonOrbit: { aKm: 9378, periodDays: 0.319 } },
|
texture: '1k_phobos.jpg', parent: 'mars', moonOrbit: { aKm: 9378, periodDays: 0.319 } },
|
||||||
deimos: { name: 'Deimos', type: 'moon', radiusKm: 6.2, color: '#9a8c7a',
|
deimos: { name: 'Deimos', type: 'moon', radiusKm: 6.2, color: '#9a8c7a',
|
||||||
texture: null, parent: 'mars', moonOrbit: { aKm: 23459, periodDays: 1.262 } },
|
texture: null, parent: 'mars', moonOrbit: { aKm: 23459, periodDays: 1.262 } },
|
||||||
|
|
||||||
io: { name: 'Io', type: 'moon', radiusKm: 1821.6, color: '#e8d24b',
|
io: { name: 'Io', type: 'moon', radiusKm: 1821.6, color: '#e8d24b',
|
||||||
texture: null, parent: 'jupiter', moonOrbit: { aKm: 421700, periodDays: 1.769 } },
|
texture: '1k_io.jpg', parent: 'jupiter', moonOrbit: { aKm: 421700, periodDays: 1.769 } },
|
||||||
europa: { name: 'Europa', type: 'moon', radiusKm: 1560.8, color: '#c9b79c',
|
europa: { name: 'Europa', type: 'moon', radiusKm: 1560.8, color: '#c9b79c',
|
||||||
texture: null, parent: 'jupiter', moonOrbit: { aKm: 671034, periodDays: 3.551 } },
|
texture: '1k_europa.jpg', parent: 'jupiter', moonOrbit: { aKm: 671034, periodDays: 3.551 } },
|
||||||
ganymede: { name: 'Ganymede', type: 'moon', radiusKm: 2634.1, color: '#9b8e7e',
|
ganymede: { name: 'Ganymede', type: 'moon', radiusKm: 2634.1, color: '#9b8e7e',
|
||||||
texture: null, parent: 'jupiter', moonOrbit: { aKm: 1070412, periodDays: 7.155 } },
|
texture: '1k_ganymede.jpg', parent: 'jupiter', moonOrbit: { aKm: 1070412, periodDays: 7.155 } },
|
||||||
callisto: { name: 'Callisto', type: 'moon', radiusKm: 2410.3, color: '#6b5f52',
|
callisto: { name: 'Callisto', type: 'moon', radiusKm: 2410.3, color: '#6b5f52',
|
||||||
texture: null, parent: 'jupiter', moonOrbit: { aKm: 1882709, periodDays: 16.689 } },
|
texture: '1k_callisto.jpg', parent: 'jupiter', moonOrbit: { aKm: 1882709, periodDays: 16.689 } },
|
||||||
|
|
||||||
mimas: { name: 'Mimas', type: 'moon', radiusKm: 198.2, color: '#c8c8c8',
|
mimas: { name: 'Mimas', type: 'moon', radiusKm: 198.2, color: '#c8c8c8',
|
||||||
texture: null, parent: 'saturn', moonOrbit: { aKm: 185539, periodDays: 0.942 } },
|
texture: null, parent: 'saturn', moonOrbit: { aKm: 185539, periodDays: 0.942 } },
|
||||||
@ -86,7 +86,7 @@ export const BODIES = {
|
|||||||
rhea: { name: 'Rhea', type: 'moon', radiusKm: 763.8, color: '#c4c4c4',
|
rhea: { name: 'Rhea', type: 'moon', radiusKm: 763.8, color: '#c4c4c4',
|
||||||
texture: null, parent: 'saturn', moonOrbit: { aKm: 527068, periodDays: 4.518 } },
|
texture: null, parent: 'saturn', moonOrbit: { aKm: 527068, periodDays: 4.518 } },
|
||||||
titan: { name: 'Titan', type: 'moon', radiusKm: 2574.7, color: '#d9a441',
|
titan: { name: 'Titan', type: 'moon', radiusKm: 2574.7, color: '#d9a441',
|
||||||
texture: null, parent: 'saturn', moonOrbit: { aKm: 1221870, periodDays: 15.945 } },
|
texture: '1k_titan.jpg', parent: 'saturn', moonOrbit: { aKm: 1221870, periodDays: 15.945 } },
|
||||||
iapetus: { name: 'Iapetus', type: 'moon', radiusKm: 734.5, color: '#8a7a5e',
|
iapetus: { name: 'Iapetus', type: 'moon', radiusKm: 734.5, color: '#8a7a5e',
|
||||||
texture: null, parent: 'saturn', moonOrbit: { aKm: 3560851, periodDays: 79.33 } },
|
texture: null, parent: 'saturn', moonOrbit: { aKm: 3560851, periodDays: 79.33 } },
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ export const BODIES = {
|
|||||||
|
|
||||||
// Triton is retrograde — encoded via the negative-period convention (brief §8).
|
// Triton is retrograde — encoded via the negative-period convention (brief §8).
|
||||||
triton: { name: 'Triton', type: 'moon', radiusKm: 1353.4, color: '#d6cfc4',
|
triton: { name: 'Triton', type: 'moon', radiusKm: 1353.4, color: '#d6cfc4',
|
||||||
texture: null, parent: 'neptune', moonOrbit: { aKm: 354759, periodDays: -5.877 } },
|
texture: '1k_triton.jpg', parent: 'neptune', moonOrbit: { aKm: 354759, periodDays: -5.877 } },
|
||||||
|
|
||||||
// ---- Pluto system (small-body epoch elements; texture-less spheres) ----
|
// ---- Pluto system (small-body epoch elements; texture-less spheres) ----
|
||||||
pluto: {
|
pluto: {
|
||||||
@ -114,7 +114,7 @@ export const BODIES = {
|
|||||||
w: 113.76329, ma: 14.86012204, epoch: 2451545.0 },
|
w: 113.76329, ma: 14.86012204, epoch: 2451545.0 },
|
||||||
},
|
},
|
||||||
charon: { name: 'Charon', type: 'moon', radiusKm: 606.0, color: '#b3a894',
|
charon: { name: 'Charon', type: 'moon', radiusKm: 606.0, color: '#b3a894',
|
||||||
texture: null, parent: 'pluto', moonOrbit: { aKm: 19591, periodDays: 6.387 } },
|
texture: '1k_charon.jpg', parent: 'pluto', moonOrbit: { aKm: 19591, periodDays: 6.387 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ordered planet ids (draw / menu order).
|
// Ordered planet ids (draw / menu order).
|
||||||
|
|||||||
@ -6,7 +6,8 @@
|
|||||||
// focus, to keep the wide view clean (brief §5).
|
// focus, to keep the wide view clean (brief §5).
|
||||||
|
|
||||||
export default function create(ctx) {
|
export default function create(ctx) {
|
||||||
const { THREE, scene, CONFIG, ui, scale, bodies, focus, toLocal, effectiveE, makeLabel, registerPick } = ctx;
|
const { THREE, scene, CONFIG, lib, ui, scale, bodies, focus, toLocal, effectiveE,
|
||||||
|
makeLabel, registerPick, loadTextureInto } = ctx;
|
||||||
|
|
||||||
const entries = [];
|
const entries = [];
|
||||||
for (const id in bodies) {
|
for (const id in bodies) {
|
||||||
@ -16,6 +17,7 @@ export default function create(ctx) {
|
|||||||
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 24, 16), mat);
|
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 24, 16), mat);
|
||||||
mesh.visible = true;
|
mesh.visible = true;
|
||||||
scene.add(mesh);
|
scene.add(mesh);
|
||||||
|
loadTextureInto(mat, b.texture); // NASA/USGS map when present; flat color otherwise (§7 fallback)
|
||||||
registerPick(mesh, id);
|
registerPick(mesh, id);
|
||||||
const lbl = makeLabel(mesh, b.name, 'body-label moon');
|
const lbl = makeLabel(mesh, b.name, 'body-label moon');
|
||||||
lbl.obj.visible = false; // CSS2DRenderer honors obj.visible (not div.style.display)
|
lbl.obj.visible = false; // CSS2DRenderer honors obj.visible (not div.style.display)
|
||||||
@ -34,6 +36,10 @@ export default function create(ctx) {
|
|||||||
if (!abs) continue;
|
if (!abs) continue;
|
||||||
toLocal(abs, e.mesh.position);
|
toLocal(abs, e.mesh.position);
|
||||||
e.mesh.scale.setScalar(scale.drawRadius(e.b.radiusKm, effectiveE(e.b.parent)));
|
e.mesh.scale.setScalar(scale.drawRadius(e.b.radiusKm, effectiveE(e.b.parent)));
|
||||||
|
// tidal lock: spin at the SAME signed orbital rate main.js positions by, so
|
||||||
|
// one face stays toward the parent (negative period → retrograde for free).
|
||||||
|
const theta = 2 * Math.PI * ((jd - lib.J2000_JD) / e.b.moonOrbit.periodDays);
|
||||||
|
e.mesh.rotation.y = theta + Math.PI;
|
||||||
const near = focus.id === e.b.parent || focus.id === e.id;
|
const near = focus.id === e.b.parent || focus.id === e.id;
|
||||||
e.lbl.obj.visible = show && near;
|
e.lbl.obj.visible = show && near;
|
||||||
e.lbl.div.classList.toggle('focused', e.id === focus.id);
|
e.lbl.div.classList.toggle('focused', e.id === focus.id);
|
||||||
|
|||||||