Use more parallels towards the poles.

This commit is contained in:
Brandon Dyck 2024-07-22 22:29:39 -06:00
parent 01d421d47b
commit 65fb4f748f
2 changed files with 24 additions and 18 deletions

View File

@ -1,6 +1,3 @@
Make parallels denser at the poles where it makes a bigger difference
The south pole looks really good with very dense vertices.
The parallels should be the circles where the sphere would intersect with a series of concentric, evenly spaced cylinders.
Make the panning match the cursor
Enforce a minimum zoom that will keep the edges of the sphere from showing
This probably just needs simple math with the aspect and/or the viewport's diagonal length.
@ -18,3 +15,4 @@ Add licenses
Add instructions
Fix up code locality
Give the uniforms simpler names
Allow setting top and bottom angles in case the photo doesn't reach to the poles

View File

@ -1,19 +1,18 @@
"use strict";
(() => {
const makeSphere = (meridians = 3, parallels = 3) => {
const makeSphere = (meridians = 3, bandsPerHemisphere = 1) => {
const assert = (cond, msg) => { if (!cond) throw (msg ? msg : "failed assertion"); };
// The number of meridians dividing the sphere's surface.
// Two meridians would make an XZ plane.
if (meridians < 3) {
throw "meridians must be ≥ 3";
}
assert(meridians >= 3);
assert(Number.isInteger(meridians));
// The number of parallels, including the poles, dividing the sphere's surface.
// Two parallels would make a vertical line segment.
if (parallels < 3) {
// throw "parallels must be ≥ 3";
}
// The number of latitude bands comprising each hemisphere.
assert(bandsPerHemisphere >= 1);
assert(Number.isInteger(bandsPerHemisphere));
const radius = 1;
const parallels = bandsPerHemisphere * 2 + 1;
// The seam needs two of each vertex so we can map the texture correctly.
const vertices = new Float32Array((meridians + 1) * parallels * 5);
@ -21,15 +20,25 @@
const positionOffset = 0;
const textureCoordOffset = 3 * vertices.constructor.BYTES_PER_ELEMENT;
let verticesIdx = 0;
/*
In order to cut down on distortion at the poles, the parallels
are not at equal intervals of latitude. Instead, the parallels
describe the intersections of the (circum)sphere with a set of
concentric, evenly spaced, vertically oriented cylinders. This
makes the parallels denser towards the poles, in proportion to
how badly that density is needed at any given latitude.
*/
for (let p = 0; p < parallels; p++) {
const lat = Math.PI * (p / (parallels - 1) - 0.5);
const π = Math.PI;
const sin = Math.sin;
const lat = π * sin(π * (p - bandsPerHemisphere) / 2 / bandsPerHemisphere) / 2;
const y = Math.sin(lat);
for (let m = 0; m < meridians + 1; m++) {
const long = m * 2 * Math.PI / meridians;
const x = Math.cos(lat) * Math.sin(long) * radius;
const z = Math.cos(lat) * Math.cos(long) * radius;
const x = Math.cos(lat) * Math.sin(long);
const z = Math.cos(lat) * Math.cos(long);
const u = m / meridians;
const v = p / (parallels - 1);
const v = lat / π + 0.5;
vertices[verticesIdx++] = x;
vertices[verticesIdx++] = y;
@ -183,7 +192,6 @@
const minZoom = 1;
let zoom = 3;
viewer.addEventListener("wheel", (evt) => {
console.log(evt.deltaY);
zoom = Math.max(zoom * (1 - evt.deltaY * 0.005), minZoom);
evt.preventDefault();
});