# Planets — Systemdaten v1

Ein Sternensystem ist eine JSON-Datei. Die Anwendung lädt sie ohne Änderungen an Shadern oder Renderer. Im Menü „System bearbeiten / JSON“ kannst du Dateien importieren, Daten direkt bearbeiten, anwenden und als JSON exportieren. Das aktive System wird im Arbeitsspeicher gehalten; zum Aufbewahren exportieren. Ein neues System ersetzt das aktive erst nach erfolgreicher Prüfung. Lokale Textur-Uploads im Oberflächen-Explorer bleiben in dessen Sitzung und sind nicht automatisch im JSON-Export enthalten.

## Dateien und Zuständigkeiten

- `data/catalog.json`: auswählbare Beispieldateien; URLs relativ zum Katalog.
- `data/solar-system.json`: bisheriges Sonnensystem, inklusive Texturquellen.
- `data/binary-garden.json`: fiktives Doppelsternsystem mit Mond und Ringen.
- `data/system.schema.json`: JSON Schema Draft 2020-12 für Editor-Autovervollständigung.
- `js/model.js`: Laufzeitvalidierung, URL-Auflösung, Kepler-Bahnen, Hierarchie und Szenenausdehnung; unabhängig von Browser und GPU.
- `js/renderer.js`: WebGL-Ressourcen, Texturen, Licht, Ringe und Projektion; keine Körpernamen oder Sonnensystemdaten.
- `js/app.js`: Dateiauswahl, JSON-Editor, Import/Export, Kamera, Animation und Beschriftung.
- `js/camera.js`: Flyby-Übergänge und Fokusverfolgung; ein Canvas und ein WebGL-Kontext für alle Entfernungen.
- Nahansicht: hochauflösendes Mesh und Heightmap am selben Körper in `js/renderer.js`; kein zweiter Renderer.

## Minimales System

```json
{
  "schemaVersion": 1,
  "id": "my-system",
  "name": "Mein Sternensystem",
  "bodies": [
    {"id":"star-a","name":"Stern A","kind":"star","radius":1,"color":"#ffd29a"},
    {"id":"world-a","name":"Welt A","kind":"planet","radius":0.25,"color":"#75bca5",
     "orbit":{"parent":"star-a","semiMajorAxis":5,"periodYears":2,"eccentricity":0.1}}
  ]
}
```

## Grundregeln

`schemaVersion` ist `1`. `id`, `name` und `bodies` sind erforderlich. 1–256 Körper, mindestens ein Stern und ein sichtbarer Körper. Körper-IDs müssen eindeutig sein (`a-z`, `A-Z`, Ziffern, `_`, `-`, höchstens 80 Zeichen). Körper dürfen in beliebiger Reihenfolge stehen. Fehlende Eltern, Zyklen, NaN/unendliche oder außerhalb der Grenzen liegende Werte werden vor dem Laden abgewiesen. Unbekannte Felder werden vom Normalisierer verworfen. `description` und `sources: [{label,url}]` sind optional.

## Körper

| Feld | Bedeutung / Standard |
|---|---|
| `id`, `name` | Eindeutige technische ID und Anzeigename |
| `kind` | `star`, `planet`, `moon` oder `body`; nur `star` leuchtet selbst |
| `radius` | Sichtbarer Kugelradius, > 0 (0.001–10000) |
| `color` | `#RRGGBB`; Farbfüllung ohne Diffuse-Textur, außerdem Lichtfarbe bei Sternen |
| `visible` | Standard `true`. Mit `false` lassen sich unsichtbare Bahnknoten/Baryzentren definieren |
| `position` | `[x,y,z]`, Standard `[0,0,0]`; ohne Bahn feste Weltposition, mit Bahn zusätzlicher Offset relativ zum Elternkörper |
| `luminosity` | Relatives Lichtgewicht bei Sternen, Standard 1; kein physikalisches Strahlungsmodell |
| `spinPeriodYears` | Illustrative Eigenrotation in Erdjahren; Standard 0 (statisch), negative Werte drehen rückwärts |
| `spinPhaseDeg` | Eigenrotations-Startwinkel, Standard 0 |
| `textures.diffuse` | Optionale Farbtextur; fehlt sie, wird `color` verwendet |
| `textures.height` | Optionale Höhenkarte für die Oberflächenansicht |
| `heightScale` | Relative Reliefhöhe in der Oberflächenansicht, 0–0.2, Standard 0 |
| `orbit` | Optionale elliptische Bahn um einen anderen Körper |
| `rings` | Optional: `innerRadius`, `outerRadius`, `color`, `tiltDeg`; Radien größer als Körperradius |

## Bahnen und Einheiten

Alle Längen (Radius, Position, Halbachse, Ringe) verwenden dieselbe **frei gewählte Darstellungseinheit**. Keine versteckte AU/km-Umrechnung; physikalische Datensätze deshalb vorab auf eine gemeinsame Einheit bringen. Der enthaltene Sonnensystemdatensatz ist schematisch skaliert. Die Kamera passt sich automatisch an die Ausdehnung an.

Die Zeit ist immer in **Erdjahren**; der Temporegler zeigt Jahre pro realer Sekunde. `orbit.periodYears` und `orbit.semiMajorAxis` sind unabhängig eingegebene Werte, es wird keine Masse oder Kepler-III-Konstante abgeleitet.

Erforderliche Bahnfelder: `parent`, `semiMajorAxis` (>0), `periodYears` (>0). Optional: `eccentricity` (0–0.95), `inclinationDeg`, `ascendingNodeDeg`, `argumentOfPeriapsisDeg`, `phaseDeg` (alle Winkel Grad, Standard 0). `phaseDeg` ist die mittlere Anomalie bei Animationszeit 0. Die Kepler-Gleichung wird für gleichmäßige zeitliche Fortschritte gelöst. Die Basisbahnebene ist XZ, Y ist oben. Winkelkonvention: zuerst Argument des Perizentrums in XZ, dann Neigung, dann Knotenwinkel in XZ. Keine Ephemeriden oder Kalenderzeit.

Hierarchien sind erlaubt: Sterne um einen unsichtbaren Knoten, Planeten um Sterne/Knoten, Monde um Planeten. Nur vorgegebene Bahnen; keine N-Körper-Integration, Kollisionserkennung, Stabilitätsprüfung, Schatten oder gegenseitigen Bedeckungen. Doppelsterne brauchen einen expliziten unsichtbaren Knoten und passende Bahnparameter. Die Lichtdarstellung berücksichtigt je Körper höchstens die acht stärksten Sterne; die Gewichtung ist illustrativ.

## Texturen und Import

PNG, JPEG und WebP in equirektangularer 2:1-Projektion. Höhenkarten werden als 8-Bit-Bilddaten gelesen, nicht automatisch metrisch kalibriert. Texturen werden an das GPU-Limit angepasst. Systemübersicht und Nahansicht teilen dieselbe Szene. Heightmaps werden beim Fokussieren nachgeladen und bleiben am Körper; ein feineres Mesh (256/512/1024 Längssegmente) wird für den fokussierten Körper verwendet. Diffuse- und Höhenkarten sowie Relief-Einstellungen bleiben beim Zurückfliegen erhalten. Die Kamera folgt dem Körper bei weiterlaufender Systemzeit.

Bei gehosteten Systemdateien sind Texturpfade relativ zur **JSON-Datei**. Beim lokalen JSON-Import und im Editor sind relative Pfade relativ zur **App-Adresse** — der Browser kann keine beliebigen Geschwisterdateien neben einem importierten JSON lesen. Verwende daher gehostete URLs oder `data:image/png;base64,...`, `data:image/jpeg;base64,...`, `data:image/webp;base64,...`. Externe Hosts müssen CORS erlauben. Der Export enthält normalisierte absolute URLs; er bettet gehostete Bilder nicht automatisch ein. Fehlerhafte Texturen zeigen die Ersatzfarbe und einen Ladefehlerstatus.

Zum Hinzufügen eines mitgelieferten Systems die JSON-Datei und ihre Assets ablegen und einen Eintrag `{ "name": "…", "url": "my-system.json" }` in `data/catalog.json` ergänzen. Kein JavaScript anpassen.

## Infos und Wolken

Körper können `info: {summary, facts: [{label,value}]}` enthalten (maximal 12 Fakten). Die Nahansicht zeigt diese Daten rechts neben dem Körper; vorhandene Kinderkörper werden als auswählbare Begleiter angeboten. Die Darstellungseinheiten werden nicht als physikalische Größen ausgegeben.

`clouds: {texture, altitude, opacity, spinPeriodYears}` definiert eine transparente Wolkenhülle. `texture` ist eine equirektangulare Graustufenmaske (schwarz transparent, weiß Wolken), `altitude` der relative Höhenabstand (0.001–0.5), `opacity` 0–1. Die Hülle liegt über dem aktuell eingestellten Relief und rotiert unabhängig. Sie lässt sich im Oberflächen-Panel ausblenden. Kein meteorologisches Modell.

Bei Körperfokus wird auf 0.00001 Erdjahre pro realer Sekunde verlangsamt. Beim Rückflug oder Reset kehrt die vorherige Übersichtsgeschwindigkeit zurück; Pause bleibt Pause. Der Mond ist als eigener, anklickbarer Körper mit Erd-Parent und schematisch verkürztem Abstand enthalten.

## Physische Ausgangsdaten und Maßstab

`physical: {radiusKm, orbitKm}` speichert echte Radien und die große Halbachse der Bahn relativ zum Parent in Kilometern. Die ursprünglichen freien Szeneneinheiten bleiben daneben erhalten. Vollständig mit physischen Angaben versehene Systeme ohne feste Positionsoffsets erhalten drei Anzeigeprofile. Exporte behalten die physischen Ausgangsdaten; die Komprimierung wird erst in `js/scaling.js` auf einer Szenenkopie angewendet.

- Kompakt: Abstände mit Potenz 0.38, Radien mit 0.5.
- Ausgewogen (Standard): Abstände mit 0.55, Radien mit 0.65. Große Unterschiede bleiben deutlicher sichtbar. Enge Umläufe erhalten einen Mindestabstand; Monde werden relativ zum Radius des Parent skaliert.
- Echte Verhältnisse: gemeinsame lineare Umrechnung mit 8 Darstellungseinheiten pro AU für Radien und Bahnen. Planeten sind dadurch in der Gesamtansicht praktisch unsichtbar und müssen über Entdecken gewählt werden.

„Innere Bahnen ansehen“ fokussiert die Umgebung des zentralen Sterns für Umläufe bis 250 Millionen Kilometer. Zeiten werden beim Maßstabwechsel zurückgesetzt; lokale Textur-Uploads bleiben erhalten. Physikalische Zahlen in den Infokarten werden nicht komprimiert.

## Material und Licht

Optional: `material: {ocean: true, roughness: 0.28}`, `atmosphere: {color: "#79bbff", strength: 0.48}` und `textures.night`. Farbkarten werden für die Beleuchtung linearisiert und das Ergebnis mit einer ACES-Näherung plus Gamma ausgegeben. Wasserreflexionen verwenden eine aus der Farbkarte angenäherte Wassermaske. Atmosphärischer Rand und Sonnenleuchten sind analytische, für mobile Darstellung vereinfachte Effekte. Kein vollständiges volumetrisches Scattering, Raytracing oder Wettersystem. Nachttexturen werden auf der unbeleuchteten Seite eingeblendet. Ringe sind gebänderte Flächen mit einem analytischen Schatten des Parent; Bandstruktur bleibt illustrativ.

## Realistisches Erd-Preset und Hintergrund

Das Erd-Preset verwendet `heightScale: 0.0014` (ungefähr 9 km bei Erdradius 6378 km) und `clouds.altitude: 0.0028` (ungefähr 18 km). Die Höhenkarte ist eine unkalibrierte 8-Bit-Bildtextur; diese Höhen sind ein plausibler Darstellungsrahmen, keine geodätischen Messwerte. Bei künstlich verstärktem, tatsächlich geladenem Relief wird die Wolkenhülle nur so weit angehoben, dass sie über den Höhen liegt (Sicherheitsabstand 0.0006 Radius). Ohne geladene Heightmap wird sie nicht vom eingestellten Reliefregler angehoben.

`background: {texture, brightness, rotationDeg}` definiert eine equirektangulare 2:1-Skymap. Die enthaltene Milchstraßenkarte von Solar System Scope wird mit 4096×2048 Pixeln ausgeliefert (aus der 8K-Vorlage). Der Sky-Pass verwendet ausschließlich Kamerarotation, Bildformat und Projektionsverschiebung; keine Szenenposition oder Dolly-Entfernung. Die Orientierung ist für die Darstellung gewählt und nicht astronomisch zur Szenen-Ekliptik kalibriert. Der Hintergrund wird im vorhandenen WebGL-Kontext gezeichnet; die früheren CSS-Sterne entfallen. Unter Ansicht sind Sichtbarkeit und Helligkeit einstellbar.

## Animierte Sternoberfläche

`stellarSurface: {enabled, speed, granulation, activity, seed}` steuert die prozedurale Animation eines Sterns. Standard: `enabled: true`, `speed: 0.6`, `granulation: 0.45`, `activity: 0.18`, `seed: 1`. `speed` ist 0–4, Granulation/Aktivität jeweils 0–1, Seed 0–1000000. Das Modul arbeitet mit der bestehenden Farbtextur und kugelkontinuierlichem 3D-Rauschen; es benötigt kein Video, keine weiteren Bild-Downloads und keinen zweiten WebGL-Kontext.

Feine Granulation wird bei großer Entfernung gefiltert. Aktivitätszonen, lokale Texturverzerrung, Randabdunklung und ein sanft strukturierter Koronasaum sind illustrative Näherungen, keine Magnetohydrodynamik oder Aufnahme einer realen Sonnenaktivität. Die dekorative Animation folgt sichtbarer Echtzeit statt dem astronomischen Zeitraffer, damit sie im verlangsamten Fokus weiter erkennbar ist; globale Pause, Tab-Hintergrund und reduzierte Bewegung halten sie an. Die astronomische Eigenrotation bleibt separat durch `spinPeriodYears` definiert.

Die Sternanimation ist jetzt sichtbar strömend statt nur minimal flimmernd: latitudenabhängige Texturadvektion, niedrigere Belichtung und gröbere aufgelöste Granulation. Im Stern-Oberflächenpanel lassen sich Animation und Tempo einstellen. Eine ausdrücklich eingeschaltete Animation kann die Voreinstellung „Reduzierte Bewegung“ für diesen Körper überschreiben; globale Pause bleibt wirksam.

`npm run test:star-motion` rendert die tatsächlichen Shader mit Sonnenkarte in einen EGL-Framebuffer, vergleicht Frames im Abstand von zwei Sekunden und prüft eine feste Mindeständerung. Identische Zeitstempel müssen identische Bilder liefern. Benötigt EGL, NumPy und Pillow; Bilder landen in der ignorierten `.qa/`-Ablage. Diese Prüfung verifiziert Pixeländerung im Software-Renderer, nicht Leistung auf einem realen Smartphone.

## Fokusruhe und Wolkenabstand

Aktueller Standard beim Fokussieren: 0.00001 Erdjahre/s statt zuvor 0.01, also 1000-mal langsamer. Die dekorative Echtzeituhr für Sternoberfläche und Korona läuft im Fokus mit Faktor 0.08 weiter und kehrt beim Rückflug ohne Phasensprung zum normalen Fortschritt zurück. Globale Pause hält beide Uhren an.

Die Erd-Wolkenhülle liegt jetzt bei 0.0028 Radius; der Relief-Sicherheitsabstand beträgt 0.0006 Radius. Entscheidend gegen Clipping: Im Fokus verwenden Gelände und Wolken dasselbe feinere Kugelnetz. Der atmosphärische Saum hat eine schmale helle und eine weichere äußere Komponente; die Lichtseite wird stärker betont, die Nachtseite zurückgenommen. Die Höhenkarte bleibt unkalibriert, die optischen Effekte illustrativ.

## Korrigierte Atmosphärengeometrie

Planeten verwenden nun eine wirkliche 3D-Atmosphärenhülle statt des früheren zweidimensionalen Halo-Quads. Die Opazität hängt von der Strahlenlänge durch die Hülle und der Lichtrichtung ab; außerhalb des Randes läuft sie weich auf null. Die Hülle benutzt korrekte Szenentiefe, deaktiviert Tiefenschreiben beim transparenten Pass und teilt im Fokus das Detail-Mesh mit dem Planeten. Der separate optische Koronasaum bleibt nur für Sterne bestehen.

Das aktuelle Fokus-Tempo ist 0.00002 Jahre/s (doppelt so schnell wie die vorherige Einstellung); die dekorative Oberfläche läuft mit 0.16 der Echtzeituhr. Rückflug stellt das bisherige Übersichtstempo wieder her.

## Alpha Centauri

`data/alpha-centauri.json` enthält A, B und Proxima sowie die bestätigten Planeten Proxima b und d (Quellen: NASA Exoplanet Archive/NASA Science, abgerufen im November 2026). c und Kandidaten um A/B sind nicht als bestätigte Planeten dargestellt. Die Planetenradien sind Schätzungen und ihre Erscheinung ist unbekannt; dies steht direkt in den Infokarten. Sternoberflächen, Phasen und Bahnausrichtung sind illustrativ. Die Proxima-Außenbahn ist eine näherungsweise Literaturbahn, keine aktuelle Ephemeride.

A und B teilen einen unsichtbaren Schwerpunkt und dieselbe mittlere Anomalie; das Perizentrum von B ist um 180° gedreht. Physische baryzentrische Halbachsen wurden für das 23.3-AE-Paar mit angenäherten Massen 1.1/0.9 Sonnenmassen aufgeteilt; die Anzeige-Komprimierung verändert diese visuelle Proportion. Proxima umkreist diesen Schwerpunkt, b und d wiederum Proxima. Die Rückwirkung von Proxima auf das A/B-Zentrum wird im vereinfachten hierarchischen Bahnmodell vernachlässigt.

Optionales `overview: {members: ["id-a", "id-b"], label: "A/B-Paar"}` wählt einen kompakten Startausschnitt. IDs werden geprüft. „Gesamtes System ansehen“ unter Ansicht zeigt weiterhin alle Körper; es handelt sich um dieselbe Szene und denselben Datensatz. Neue Systeme benötigen keine Renderer-Anpassung.

## Prozedurale Photosphäre (v19)
`stellarSurface.temperatureK` (0–40000; Standard 0) steuert die angenäherte thermische Farbe. 0 verwendet die Datensatzfarbe. `cellScale` (6–240; Standard 48) legt die Anzahl der Zellgrößen pro Radius fest, keine beobachtete physikalische Granulengröße. `limbDarkening` (0–1; Standard 0.6) steuert die lineare Randverdunkelung. Die Darstellung arbeitet ohne Sonnen-Farbtextur: nahtlose 3D-Zellen, advektiertes Strömungsfeld, Flecken mit Kern/Penumbra und randbetonte Fackelgebiete. Kleine Bildschirmprojektionen filtern Granulation aus; Pause und reduzierte Bewegung frieren das Muster ein. Temperaturfarben sind eine RGB-Näherung mit fester Weißbalance/Belichtung, kein Spektralrenderer. Zellgrößen, Aktivität und Fleckenpositionen sind illustrative Parameter, keine rekonstruierten Beobachtungen. Die Korona bleibt vorerst beim bisherigen optischen Saum; räumliche Plasma-Bögen sind ein separater nächster Ausbauschritt.
