Sonnensystem verbessert

This commit is contained in:
2026-04-09 19:34:44 +02:00
parent 0f13c46a65
commit e5252e082f
+215 -6
View File
@@ -271,6 +271,7 @@ const AU_IN_KM = 149597870.7;
const DISPLAY_SCALE = 34;
const USER_MINOR_PLANETS = <?= json_encode($trackedMinorplanetsForJs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
const JUPITER_MIN_VISIBLE_SIZE = 1.42;
const MOON_DISPLAY_DISTANCE_MULTIPLIER = 2200;
const PLANETS = [
{ key: 'Mercury', label: 'Merkur', color: '#aeb7c4', emissive: '#29303a', size: 0.34, type: 'Gesteinsplanet', roughness: 0.95, metalness: 0.00, glow: false, texture: 'images/planets/merkur_1024.jpg' },
@@ -283,6 +284,18 @@ const PLANETS = [
{ key: 'Neptune', label: 'Neptun', color: '#4f78f0', emissive: '#101b46', size: 0.92, type: 'Eisriese', roughness: 0.92, metalness: 0.00, glow: true, texture: 'images/planets/neptun_1024.jpg' },
{ key: 'Pluto', label: 'Pluto', color: '#c5b090', emissive: '#3c2f20', size: 0.26, type: 'Zwergplanet', roughness: 0.95, metalness: 0.00, glow: false, texture: 'images/planets/pluto_1024.jpg' }
];
const MOON = {
key: 'Moon',
label: 'Mond',
color: '#d7d7d7',
emissive: '#2d2d30',
size: 0.17,
type: 'Mond',
roughness: 0.96,
metalness: 0.00,
texture: 'images/moons/moon_1024.jpg',
orbitalPeriodDays: 27.321661,
};
const stageWrap = document.getElementById('solarStageWrap');
const canvas = document.getElementById('solarCanvas');
@@ -320,6 +333,9 @@ let raycaster;
let pointer;
let eclipticGroup;
let rotationEqjToEcl;
let moonMesh = null;
let moonOrbitLine = null;
let moonLabelElement = null;
let minorPlanetOrbitLine = null;
let minorPlanetMesh = null;
let minorPlanetLabelElement = null;
@@ -480,6 +496,75 @@ function toDisplayPosition(position) {
);
}
function toDisplayDirection(vector) {
return new THREE.Vector3(
vector.x,
vector.z,
-vector.y
);
}
function getPlanetRotationState(key, date) {
try {
const axisInfo = AstronomyEngine.RotationAxis(getPlanetBodyKey(key), date);
if (!axisInfo || !axisInfo.north) {
return null;
}
const northEqj = axisInfo.north;
const northEcl = rotationEqjToEcl
? AstronomyEngine.RotateVector(rotationEqjToEcl, northEqj)
: northEqj;
const northDisplay = toDisplayDirection(northEcl).normalize();
if (!Number.isFinite(northDisplay.lengthSq()) || northDisplay.lengthSq() < 1e-12) {
return null;
}
return {
northDisplay,
spinRad: THREE.MathUtils.degToRad(Number(axisInfo.spin) || 0),
};
} catch (error) {
return null;
}
}
function getMoonGeoPosition(date) {
const astroTime = AstronomyEngine.MakeTime(date);
const vectorEqj = AstronomyEngine.GeoVector('Moon', astroTime, true);
const vectorEcl = rotationEqjToEcl
? AstronomyEngine.RotateVector(rotationEqjToEcl, vectorEqj)
: vectorEqj;
const radiusAu = Math.hypot(vectorEcl.x, vectorEcl.y, vectorEcl.z);
return { x: vectorEcl.x, y: vectorEcl.y, z: vectorEcl.z, r: radiusAu };
}
function getMoonHelioPosition(date) {
const earthPosition = getHelioPosition('Earth', date);
const moonGeoPosition = getMoonGeoPosition(date);
return {
x: earthPosition.x + moonGeoPosition.x,
y: earthPosition.y + moonGeoPosition.y,
z: earthPosition.z + moonGeoPosition.z,
r: Math.hypot(
earthPosition.x + moonGeoPosition.x,
earthPosition.y + moonGeoPosition.y,
earthPosition.z + moonGeoPosition.z
),
};
}
function getMoonDisplayPosition(date) {
const earthHelioPosition = getHelioPosition('Earth', date);
const earthDisplayPosition = toDisplayPosition(earthHelioPosition);
const moonGeoPosition = getMoonGeoPosition(date);
const moonGeoDisplayOffset = toDisplayDirection(moonGeoPosition)
.multiplyScalar(MOON_DISPLAY_DISTANCE_MULTIPLIER);
return earthDisplayPosition.clone().add(moonGeoDisplayOffset);
}
function refreshCurrentDateUi() {
currentDateLabel.textContent = formatDisplayDate(simDate);
datePicker.value = formatDateInput(simDate);
@@ -608,6 +693,83 @@ function buildLabels() {
labelsLayer.appendChild(label);
labelElements.set(planet.key, label);
});
moonLabelElement = document.createElement('div');
moonLabelElement.className = 'solarsystem-planet-label';
moonLabelElement.textContent = MOON.label;
moonLabelElement.style.color = MOON.color;
moonLabelElement.hidden = true;
labelsLayer.appendChild(moonLabelElement);
}
function ensureMoonObjects() {
if (moonMesh && moonOrbitLine) {
return;
}
const moonTex = textureLoader.load(MOON.texture);
moonTex.colorSpace = THREE.SRGBColorSpace;
moonMesh = new THREE.Mesh(
new THREE.SphereGeometry(MOON.size, 28, 28),
new THREE.MeshStandardMaterial({
color: 0xffffff,
map: moonTex,
emissive: new THREE.Color(MOON.emissive),
emissiveIntensity: 0.05,
roughness: MOON.roughness,
metalness: MOON.metalness,
})
);
moonMesh.castShadow = true;
moonMesh.receiveShadow = true;
moonMesh.userData.baseScale = 1;
moonMesh.userData.minScaleMultiplier = 1;
scene.add(moonMesh);
moonOrbitLine = new THREE.Line(
new THREE.BufferGeometry(),
new THREE.LineBasicMaterial({
color: new THREE.Color(MOON.color),
transparent: true,
opacity: 0.55,
})
);
moonOrbitLine.visible = showOrbits;
scene.add(moonOrbitLine);
}
function rebuildMoonOrbitLine() {
ensureMoonObjects();
const positions = [];
const steps = 180;
for (let step = 0; step <= steps; step += 1) {
const offsetDays = (step / steps) * MOON.orbitalPeriodDays;
const date = new Date(simDate.getTime() + offsetDays * 86400000);
const display = getMoonDisplayPosition(date);
positions.push(display.x, display.y, display.z);
}
moonOrbitLine.geometry.dispose();
moonOrbitLine.geometry = new THREE.BufferGeometry();
moonOrbitLine.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
moonOrbitLine.visible = showOrbits;
}
function updateMoonVisual() {
ensureMoonObjects();
const display = getMoonDisplayPosition(simDate);
moonMesh.position.copy(display);
const rotationState = getPlanetRotationState('Moon', simDate);
if (rotationState) {
moonMesh.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), rotationState.northDisplay);
moonMesh.rotateY(rotationState.spinRad);
}
moonOrbitLine.visible = showOrbits;
}
function ensureMinorPlanetObjects() {
@@ -783,7 +945,7 @@ function updateMinorPlanetVisual() {
const display = toDisplayPosition(heliocentric);
minorPlanetMesh.visible = true;
minorPlanetMesh.position.copy(display);
minorPlanetMesh.rotation.y += 0.01;
minorPlanetMesh.rotation.y = (simDate.getTime() / 1000) * 0.0002;
minorPlanetOrbitLine.visible = showOrbits;
if (focusedMinorPlanetId === selectedMinorPlanetId) {
@@ -839,6 +1001,8 @@ function rebuildOrbitLine(planet) {
function createPlanetMesh(planet) {
const group = new THREE.Group();
const axisGroup = new THREE.Group();
const spinGroup = new THREE.Group();
const matParams = {
emissive: new THREE.Color(planet.emissive),
emissiveIntensity: 0.12,
@@ -862,7 +1026,8 @@ function createPlanetMesh(planet) {
);
mesh.castShadow = true;
mesh.receiveShadow = true;
group.add(mesh);
spinGroup.add(mesh);
axisGroup.add(spinGroup);
if (planet.key === 'Saturn') {
@@ -898,13 +1063,18 @@ function createPlanetMesh(planet) {
);
ring.castShadow = true;
ring.receiveShadow = true;
ring.rotation.x = Math.PI * 0.43;
group.add(ring);
ring.rotation.x = Math.PI / 2;
axisGroup.add(ring);
}
group.add(axisGroup);
group.userData.planetKey = planet.key;
group.userData.baseScale = 1;
group.userData.minScaleMultiplier = Math.max(JUPITER_MIN_VISIBLE_SIZE / Math.max(planet.size, 0.001), 1);
group.userData.axisGroup = axisGroup;
group.userData.spinGroup = spinGroup;
group.userData.surfaceMesh = mesh;
scene.add(group);
planetMeshes.set(planet.key, group);
createOrbitLine(planet);
@@ -935,6 +1105,7 @@ function createEclipticPlane() {
}
function updatePlanetPositions() {
const upAxis = new THREE.Vector3(0, 1, 0);
PLANETS.forEach((planet) => {
const meshGroup = planetMeshes.get(planet.key);
if (!meshGroup) {
@@ -944,7 +1115,14 @@ function updatePlanetPositions() {
const heliocentric = getHelioPosition(planet.key, simDate);
const display = toDisplayPosition(heliocentric);
meshGroup.position.copy(display);
meshGroup.children[0].rotation.y += 0.004;
const axisGroup = meshGroup.userData.axisGroup;
const spinGroup = meshGroup.userData.spinGroup;
const rotationState = getPlanetRotationState(planet.key, simDate);
if (axisGroup && spinGroup && rotationState) {
axisGroup.quaternion.setFromUnitVectors(upAxis, rotationState.northDisplay);
spinGroup.rotation.y = rotationState.spinRad;
}
});
}
@@ -968,6 +1146,10 @@ function updateBodyDisplayScales() {
applyMinimumDisplayScale(group, 180, 6);
});
if (moonMesh) {
applyMinimumDisplayScale(moonMesh, 220, 10);
}
if (minorPlanetMesh && minorPlanetMesh.visible) {
applyMinimumDisplayScale(minorPlanetMesh, 220, 10);
}
@@ -997,6 +1179,20 @@ function updateLabels() {
label.style.top = `${(-projected.y * 0.5 + 0.5) * stageWrap.clientHeight}px`;
});
if (moonLabelElement && moonMesh) {
moonLabelElement.hidden = !showLabels;
if (!moonLabelElement.hidden) {
const projectedMoon = moonMesh.position.clone().project(camera);
if (projectedMoon.z > 1) {
moonLabelElement.style.opacity = '0';
} else {
moonLabelElement.style.opacity = '1';
moonLabelElement.style.left = `${(projectedMoon.x * 0.5 + 0.5) * stageWrap.clientWidth}px`;
moonLabelElement.style.top = `${(-projectedMoon.y * 0.5 + 0.5) * stageWrap.clientHeight}px`;
}
}
}
if (!minorPlanetLabelElement || !minorPlanetMesh) {
return;
}
@@ -1027,7 +1223,10 @@ function pickPlanet(clientX, clientY) {
const meshes = [];
planetMeshes.forEach((group, key) => {
meshes.push({ key, mesh: group.children[0] });
const surfaceMesh = group.userData.surfaceMesh;
if (surfaceMesh) {
meshes.push({ key, mesh: surfaceMesh });
}
});
const hits = raycaster.intersectObjects(meshes.map((item) => item.mesh), false);
@@ -1140,6 +1339,9 @@ function attachUiHandlers() {
if (minorPlanetOrbitLine) {
minorPlanetOrbitLine.visible = showOrbits && !!getMinorPlanetMeta(selectedMinorPlanetId);
}
if (moonOrbitLine) {
moonOrbitLine.visible = showOrbits;
}
});
btnLabels.addEventListener('click', () => {
@@ -1194,6 +1396,7 @@ function animate() {
}
updatePlanetPositions();
updateMoonVisual();
updateMinorPlanetVisual();
// Aim shadow light from sun toward Saturn
@@ -1231,6 +1434,9 @@ function animate() {
const planet = PLANETS[(orbitRefreshCursor / 90) % PLANETS.length | 0];
rebuildOrbitLine(planet);
}
if (playing && orbitRefreshCursor % 45 === 0) {
rebuildMoonOrbitLine();
}
renderer.render(scene, camera);
}
@@ -1344,6 +1550,7 @@ async function initSolarSystem() {
buildLabels();
PLANETS.forEach(createPlanetMesh);
ensureMoonObjects();
ensureMinorPlanetObjects();
attachPointerControls();
attachUiHandlers();
@@ -1351,6 +1558,8 @@ async function initSolarSystem() {
refreshCurrentDateUi();
resizeRenderer();
updatePlanetPositions();
rebuildMoonOrbitLine();
updateMoonVisual();
rebuildMinorPlanetOrbit(null);
updateCamera();
overlay.hidden = true;