Add anchored zodiac artwork

This commit is contained in:
vini 2026-07-19 14:12:11 -03:00
parent 3df13f9a0c
commit 16dfd792ce
16 changed files with 97 additions and 3 deletions

View file

@ -1219,6 +1219,17 @@ const ctx = canvas.getContext('2d');
let obsLat = -24.72, obsLon = -53.74; // Toledo-PR; sobrescrito pela config
let showConstellations = false;
const constellationArtImages = new Map();
if (typeof CONSTELLATIONS !== 'undefined') {
for (const constellation of CONSTELLATIONS) {
if (!constellation.art) continue;
const img = new Image();
img.onload = () => projectSky();
img.onerror = () => console.error('[skeledance] falha na arte de ' + constellation.name);
img.src = constellation.art.file;
constellationArtImages.set(constellation.id, img);
}
}
const VIEW_AZ = 90; // centro da tela olha para o LESTE — a tela física do
// usuário está voltada p/ leste, então o wallpaper age
// como janela: estrelas nascem subindo dentro da cena
@ -1400,8 +1411,62 @@ function renderMilkyWay(lstDeg, glareOn) {
return true;
}
/* Resolve a transformação afim que prende três pixels da ilustração às suas
três estrelas Hipparcos projetadas. */
function constellationArtTransform(source, target) {
const [p1, p2, p3] = source;
const [q1, q2, q3] = target;
const den = p1[0] * (p2[1] - p3[1]) + p2[0] * (p3[1] - p1[1]) +
p3[0] * (p1[1] - p2[1]);
if (Math.abs(den) < 1e-6) return null;
const solve = (v1, v2, v3) => ({
x: (v1 * (p2[1] - p3[1]) + v2 * (p3[1] - p1[1]) +
v3 * (p1[1] - p2[1])) / den,
y: (v1 * (p3[0] - p2[0]) + v2 * (p1[0] - p3[0]) +
v3 * (p2[0] - p1[0])) / den,
t: (v1 * (p2[0] * p3[1] - p3[0] * p2[1]) +
v2 * (p3[0] * p1[1] - p1[0] * p3[1]) +
v3 * (p1[0] * p2[1] - p2[0] * p1[1])) / den,
});
const x = solve(q1.x, q2.x, q3.x);
const y = solve(q1.y, q2.y, q3.y);
return [x.x, y.x, x.y, y.y, x.t, y.t];
}
function drawConstellationArt(c, constellation, lst, W, horizonPx) {
const art = constellation.art;
const img = constellationArtImages.get(constellation.id);
if (!art || !img || !img.complete || !img.naturalWidth) return;
const target = art.anchors.map(anchor => {
const aa = altAz(anchor.sky[0], anchor.sky[1], lst);
const daz = ((aa.az - VIEW_AZ) % 360 + 540) % 360 - 180;
return {
x: (0.5 + daz / FOV_AZ) * W,
y: horizonPx * (1 - aa.alt / ALT_TOP),
alt: aa.alt,
};
});
if (target.every(p => p.alt < -8) || target.every(p => p.alt > ALT_TOP + 8)) return;
const matrix = constellationArtTransform(
art.anchors.map(anchor => anchor.pos), target
);
if (!matrix || matrix.some(v => !Number.isFinite(v))) return;
c.save();
c.beginPath();
c.rect(0, 0, W, horizonPx);
c.clip();
c.globalCompositeOperation = 'screen';
c.globalAlpha = 0.19;
c.setTransform(...matrix);
c.drawImage(img, 0, 0, art.size[0], art.size[1]);
c.restore();
}
/* Figuras convencionais dos 12 signos zodiacais, ancoradas em RA/Dec J2000.
São desenhadas antes das estrelas para os pontos reais ficarem por cima. */
Arte, linhas e estrelas reais ficam sobrepostas nesta ordem. */
function drawConstellations(c, lst, W, H, horizonPx) {
if (!showConstellations || typeof CONSTELLATIONS === 'undefined') return;
const rankAlpha = [0, 0.52, 0.38, 0.25];
@ -1412,6 +1477,9 @@ function drawConstellations(c, lst, W, H, horizonPx) {
c.lineJoin = 'round';
c.shadowColor = 'rgba(60,185,255,0.65)';
c.shadowBlur = 7;
for (const constellation of CONSTELLATIONS) {
drawConstellationArt(c, constellation, lst, W, horizonPx);
}
for (const constellation of CONSTELLATIONS) {
const rank = Math.max(1, Math.min(3, constellation.rank || 3));
c.strokeStyle = `rgba(105,205,255,${rankAlpha[rank]})`;