From 0d8a5f93d36a89ce19b40a709e23a5ef39c2b7ad Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Mon, 12 Oct 2026 20:51:41 +0200 Subject: [PATCH] sky: add Keplerian planets as colored larger points --- vendor/clouds3d.js | 109 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index f94b997..efa5181 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -5607,6 +5607,97 @@ function decodePlaneVerts() { // band (low-frequency by nature) stays a baked equirect texture. var skyTexCanvas = null, skyTexture = null, skyTexGl = null; 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) ? Math.max(0.2, Number(window.CONFIG.stars.brightness)) : 1.6; // 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 // outside [-1,1] and clip every single point away '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;', '}' ].join('\n'); @@ -6349,6 +6446,16 @@ window.clouds3dRender = function(target) { gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE); 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.enable(gl.DEPTH_TEST); gl.depthMask(true);