sky: add Keplerian planets as colored larger points

This commit is contained in:
Richard Zink committed 2026-10-12 20:51:41 +02:00
1 parent dd36976712
commit 0d8a5f93d3
1 file changed
+108 -1
+108 -1
View File
@@ -5607,6 +5607,97 @@ function decodePlaneVerts() {
// band (low-frequency by nature) stays a baked equirect texture. // band (low-frequency by nature) stays a baked equirect texture.
var skyTexCanvas = null, skyTexture = null, skyTexGl = null; var skyTexCanvas = null, skyTexture = null, skyTexGl = null;
var skyPts = null; // { prog, vbo, count, a0, a1, u: {...} } var skyPts = null; // { prog, vbo, count, a0, a1, u: {...} }
var planetVbo = null, planetCount = 0, planetNextT = 0;
var DEG = Math.PI / 180;
var PLANET_ELEMENTS = [
{ name: 'Mercury', a: 0.387098, e: 0.205630, i: 7.005, N: 48.331, w: 29.124, M0: 177.453, P: 87.969,
mag0: 1.0, color: [0.72, 0.68, 0.62], sizeCode: -8.0, bright: 0.75 },
{ name: 'Venus', a: 0.723332, e: 0.006773, i: 3.395, N: 76.680, w: 54.884, M0: 50.115, P: 224.701,
mag0: -4.0, color: [1.00, 0.95, 0.82], sizeCode: -10.0, bright: 1.15 },
{ name: 'Mars', a: 1.523679, e: 0.093400, i: 1.850, N: 49.558, w: 286.502, M0: 355.453, P: 686.980,
mag0: -1.5, color: [0.92, 0.45, 0.28], sizeCode: -8.0, bright: 0.85 },
{ name: 'Jupiter', a: 5.20260, e: 0.048498, i: 1.303, N: 100.464, w: 273.867, M0: 20.020, P: 4332.589,
mag0: -9.4, color: [0.95, 0.82, 0.62], sizeCode: -10.0, bright: 1.10 },
{ name: 'Saturn', a: 9.55491, e: 0.055546, i: 2.489, N: 113.665, w: 339.392, M0: 317.020, P: 10759.22,
mag0: -8.9, color: [0.96, 0.88, 0.68], sizeCode: -9.0, bright: 0.90 },
{ name: 'Uranus', a: 19.21845, e: 0.047318, i: 0.773, N: 74.006, w: 96.999, M0: 142.239, P: 30685.4,
mag0: -7.1, color: [0.55, 0.85, 0.92], sizeCode: -6.5, bright: 0.45 },
{ name: 'Neptune', a: 30.11039, e: 0.008606, i: 1.770, N: 131.784, w: 273.187, M0: 256.228, P: 60189,
mag0: -6.9, color: [0.35, 0.55, 0.95], sizeCode: -6.5, bright: 0.40 },
{ name: 'Pluto', a: 39.482, e: 0.2488, i: 17.14, N: 110.30, w: 113.83, M0: 14.86, P: 90560,
mag0: -1.0, color: [0.70, 0.62, 0.55], sizeCode: -5.5, bright: 0.18 }
];
var EARTH_ELEMENTS = { a: 1.000000, e: 0.016709, i: 0.000, N: 0.0, w: 102.947, M0: 100.464, P: 365.256 };
function planetKeplerE(Mdeg, e) {
var M = ((Mdeg % 360) + 360) % 360;
var Mr = M * DEG;
var E = Mr;
for (var k = 0; k < 8; k++) {
E = E - (E - e * Math.sin(E) - Mr) / (1 - e * Math.cos(E));
}
return E;
}
function planetHeliocentric(p, d) {
var n = 360 / p.P;
var M = p.M0 + n * d;
var E = planetKeplerE(M, p.e);
var v = Math.atan2(Math.sqrt(1 - p.e * p.e) * Math.sin(E), Math.cos(E) - p.e);
var r = p.a * (1 - p.e * Math.cos(E));
var u = v + p.w * DEG;
var N = p.N * DEG;
var i = p.i * DEG;
var x = r * (Math.cos(N) * Math.cos(u) - Math.sin(N) * Math.sin(u) * Math.cos(i));
var y = r * (Math.sin(N) * Math.cos(u) * Math.cos(i) + Math.cos(N) * Math.sin(u));
var z = r * Math.sin(u) * Math.sin(i);
return [x, y, z];
}
function updatePlanetPoints(gl, date) {
if (!gl || !date) return;
var d = (date.getTime() - Date.UTC(2000, 0, 1, 12, 0, 0)) / 86400000;
var earth = planetHeliocentric(EARTH_ELEMENTS, d);
var data = new Float32Array(PLANET_ELEMENTS.length * 8);
var di = 0, count = 0;
var sLat = SKY_SIN_LAT, cLat = SKY_COS_LAT;
var eps = 23.43928 * DEG;
var ceps = Math.cos(eps), seps = Math.sin(eps);
for (var pi = 0; pi < PLANET_ELEMENTS.length; pi++) {
var p = PLANET_ELEMENTS[pi];
var helio = planetHeliocentric(p, d);
var gx = helio[0] - earth[0];
var gy = helio[1] - earth[1];
var gz = helio[2] - earth[2];
var rGeo = Math.sqrt(gx * gx + gy * gy + gz * gz);
var rSun = Math.sqrt(helio[0] * helio[0] + helio[1] * helio[1] + helio[2] * helio[2]);
if (!(rGeo > 1e-6)) continue;
var ex = gx;
var ey = gy * ceps - gz * seps;
var ez = gy * seps + gz * ceps;
var el = Math.sqrt(ex * ex + ey * ey + ez * ez) || 1;
var ra = Math.atan2(ey, ex);
var dec = Math.asin(Math.max(-1, Math.min(1, ez / el)));
var cd = Math.cos(dec), sd = Math.sin(dec);
var cr = Math.cos(ra), sr = Math.sin(ra);
var dx = cd * cr;
var dy = sLat * sd + cLat * cd * sr;
var dz = cLat * sd - sLat * cd * sr;
// Approximate apparent magnitude from absolute magnitude and distances.
// The clamp keeps inner planets from becoming absurdly bright because
// this simplified model ignores phase angle.
var mag = p.mag0 !== undefined ? p.mag0 : -1.0;
mag = mag + 5 * Math.log10(Math.max(1e-6, rGeo * rSun));
mag = Math.max(-5.0, Math.min(16.0, mag));
var bright = p.bright * Math.max(0.12, Math.min(1.25, Math.pow(2.512, -mag * 0.35)));
data[di++] = dx; data[di++] = dy; data[di++] = dz; data[di++] = p.sizeCode;
data[di++] = p.color[0]; data[di++] = p.color[1]; data[di++] = p.color[2];
data[di++] = bright;
count++;
}
if (!planetVbo) planetVbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, planetVbo);
gl.bufferData(gl.ARRAY_BUFFER, data.subarray(0, di), gl.STREAM_DRAW);
planetCount = count;
}
var STAR_BRIGHT = (((window.CONFIG && window.CONFIG.stars) || {}).brightness !== undefined) var STAR_BRIGHT = (((window.CONFIG && window.CONFIG.stars) || {}).brightness !== undefined)
? Math.max(0.2, Number(window.CONFIG.stars.brightness)) : 1.6; ? Math.max(0.2, Number(window.CONFIG.stars.brightness)) : 1.6;
// Star frame phase. The rotation is driven by real local sidereal time // Star frame phase. The rotation is driven by real local sidereal time
@@ -5655,7 +5746,13 @@ var SKYPTS_VERT = [
// finite radius (inside the far plane): w=0 would put z_ndc just // finite radius (inside the far plane): w=0 would put z_ndc just
// outside [-1,1] and clip every single point away // outside [-1,1] and clip every single point away
'gl_Position = uMVP * vec4(rp * 88.0, 1.0);', 'gl_Position = uMVP * vec4(rp * 88.0, 1.0);',
'gl_PointSize = clamp((7.2 - aSd.w) * 0.60 * uSizeScale, 1.4, 9.0);', 'float baseSize;',
'if (aSd.w < -5.0) {',
'baseSize = (14.0 - aSd.w) * 0.72;',
'} else {',
'baseSize = (7.2 - aSd.w) * 0.60;',
'}',
'gl_PointSize = clamp(baseSize * uSizeScale, 1.4, 20.0);',
'vC = aScol;', 'vC = aScol;',
'}' '}'
].join('\n'); ].join('\n');
@@ -6349,6 +6446,16 @@ window.clouds3dRender = function(target) {
gl.enable(gl.BLEND); gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE); gl.blendFunc(gl.ONE, gl.ONE);
gl.drawArrays(gl.POINTS, 0, skyPts.count); gl.drawArrays(gl.POINTS, 0, skyPts.count);
if (now - planetNextT > 30) {
updatePlanetPoints(gl, window.__currentSceneDate || new Date());
planetNextT = now;
}
if (planetCount && planetVbo) {
gl.bindBuffer(gl.ARRAY_BUFFER, planetVbo);
gl.vertexAttribPointer(skyPts.a0, 4, gl.FLOAT, false, 32, 0);
gl.vertexAttribPointer(skyPts.a1, 4, gl.FLOAT, false, 32, 16);
gl.drawArrays(gl.POINTS, 0, planetCount);
}
gl.disable(gl.BLEND); gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST); gl.enable(gl.DEPTH_TEST);
gl.depthMask(true); gl.depthMask(true);