1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 08:37:37 +03:00
This commit is contained in:
Anton Afanasyeu
2026-06-05 22:11:38 +02:00
parent a656f40922
commit cd2e69ad6b
12 changed files with 368 additions and 62 deletions

View File

@@ -118,10 +118,7 @@ function bakeEquirectangular(compositeData, mercatorFlatImg) {
rgba = sampleMercatorFlat(mercCtx, lon, lat);
}
} else {
rgba = sampleMercatorFlat(mercCtx, lon, lat);
if (rgba[3] < 16) {
rgba = [OCEAN_FALLBACK.r, OCEAN_FALLBACK.g, OCEAN_FALLBACK.b, 255];
}
rgba = [OCEAN_FALLBACK.r, OCEAN_FALLBACK.g, OCEAN_FALLBACK.b, 255];
}
const p = (j * EQ_WIDTH + i) * 4;
@@ -139,30 +136,60 @@ function bakeEquirectangular(compositeData, mercatorFlatImg) {
function drawEquirectSlice(ctx, eqCanvas, rotation, dx, dy, diam) {
const w = eqCanvas.width;
const h = eqCanvas.height;
const offsetPx = ((rotation / (2 * Math.PI)) % 1) * w;
const ox = ((offsetPx % w) + w) % w;
const ox = ((rotation / (2 * Math.PI)) * w % w + w) % w;
const destX = dx - diam * 0.5;
const destY = dy - diam * 0.5;
ctx.save();
ctx.beginPath();
ctx.arc(dx, dy, diam * 0.5, 0, Math.PI * 2);
ctx.clip();
ctx.drawImage(eqCanvas, -ox, 0, w, h, dx - diam * 0.5, dy - diam * 0.5, diam, diam);
ctx.drawImage(eqCanvas, w - ox, 0, w, h, dx - diam * 0.5 + diam, dy - diam * 0.5, diam, diam);
const slice1w = w - ox;
const destSlice1 = diam * (slice1w / w);
ctx.drawImage(eqCanvas, ox, 0, slice1w, h, destX, destY, destSlice1, diam);
if (ox > 0.5) {
ctx.drawImage(eqCanvas, 0, 0, ox, h, destX + destSlice1, destY, diam - destSlice1, diam);
}
ctx.restore();
}
function rotateY(x, y, z, rotY) {
return {
x: x * Math.cos(rotY) + z * Math.sin(rotY),
y,
z: -x * Math.sin(rotY) + z * Math.cos(rotY),
};
}
function strokeParallel(ctx, cx, cy, r, latRad, rotY, strokeStyle, lineWidth) {
const pts = [];
for (let i = 0; i <= 64; i++) {
const lon = -Math.PI + (i / 64) * 2 * Math.PI;
const cosLat = Math.cos(latRad);
const p = rotateY(cosLat * Math.sin(lon), Math.sin(latRad), cosLat * Math.cos(lon), rotY);
if (p.z > 0.04) {
pts.push({ x: cx + p.x * r, y: cy - p.y * r });
}
}
if (pts.length < 2) return;
ctx.beginPath();
ctx.moveTo(pts[0].x, pts[0].y);
for (let k = 1; k < pts.length; k++) ctx.lineTo(pts[k].x, pts[k].y);
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
ctx.stroke();
}
function strokeMeridian(ctx, cx, cy, r, lonRad, rotY, strokeStyle, lineWidth) {
const pts = [];
for (let i = 0; i <= 64; i++) {
const lat = -Math.PI / 2 + (i / 64) * Math.PI;
const cosLat = Math.cos(lat);
let x = cosLat * Math.sin(lonRad);
let y = Math.sin(lat);
let z = cosLat * Math.cos(lonRad);
const x2 = x * Math.cos(rotY) + z * Math.sin(rotY);
const z2 = -x * Math.sin(rotY) + z * Math.cos(rotY);
if (z2 > 0.04) {
pts.push({ x: cx + x2 * r, y: cy - y * r });
const p = rotateY(cosLat * Math.sin(lonRad), Math.sin(lat), cosLat * Math.cos(lonRad), rotY);
if (p.z > 0.04) {
pts.push({ x: cx + p.x * r, y: cy - p.y * r });
}
}
if (pts.length < 2) return;
@@ -190,26 +217,16 @@ function drawGridOverlay(ctx, rect, rotY) {
equatorGrad.addColorStop(0.5, 'rgba(219,231,246,0.88)');
equatorGrad.addColorStop(1, 'rgba(31,44,64,0.74)');
ctx.beginPath();
ctx.ellipse(cx, cy, r * 0.99, r * 0.034, 0, 0, 2 * Math.PI);
ctx.strokeStyle = equatorGrad;
ctx.lineWidth = Math.max(2, rect.scale * 0.007);
ctx.stroke();
const poleRy = r * 0.12;
ctx.beginPath();
ctx.ellipse(cx, cy - r * 0.52, r * 0.82, poleRy, 0, 0, 2 * Math.PI);
ctx.strokeStyle = 'rgba(231,236,243,0.72)';
ctx.lineWidth = Math.max(1.5, rect.scale * 0.0055);
ctx.stroke();
ctx.beginPath();
ctx.ellipse(cx, cy + r * 0.52, r * 0.82, poleRy, 0, 0, 2 * Math.PI);
ctx.stroke();
const meridianStroke = 'rgba(238,245,255,0.92)';
const primeStroke = 'rgba(238,245,255,0.98)';
const parallelStroke = 'rgba(231,236,243,0.72)';
const lw = Math.max(2.5, rect.scale * 0.008);
const lwPrime = Math.max(3, rect.scale * 0.0095);
const lwThin = Math.max(1.5, rect.scale * 0.0055);
strokeParallel(ctx, cx, cy, r, 0, rotY, equatorGrad, Math.max(2, rect.scale * 0.007));
strokeParallel(ctx, cx, cy, r, Math.PI * 0.25, rotY, parallelStroke, lwThin);
strokeParallel(ctx, cx, cy, r, -Math.PI * 0.25, rotY, parallelStroke, lwThin);
for (let lonDeg = -150; lonDeg <= 150; lonDeg += 30) {
const lon = (lonDeg * Math.PI) / 180;
@@ -330,7 +347,13 @@ export async function mountHubGlobe(stage, opts) {
ctx.clearRect(0, 0, px, px);
drawEquirectSlice(ctx, eqCanvas, rotation, cx, cy, r * 2);
drawGridOverlay(ctx, drawRect, rotation);
drawRim(ctx, composite.canvas, cx, cy, r, rim, rect.scale * dpr);
ctx.save();
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(10,14,20,0.55)';
ctx.lineWidth = Math.max(2, rect.scale * dpr * 0.006);
ctx.stroke();
ctx.restore();
};
const onPointerDown = (ev) => {