diff --git a/designs/renox-as-planet/versions/blue/README.md b/designs/renox-as-planet/versions/blue/README.md deleted file mode 100644 index 19b2e0c..0000000 --- a/designs/renox-as-planet/versions/blue/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Renox as a planet: blue - -![Renox as a planet](logo.png) - -The word **Renox** is the planet. The script uses [opentype.js](https://github.com/opentypejs/opentype.js) to turn the word, set in Unbounded Black, into vector outlines, and splits every curve into many short segments. It then wraps each point around a 3D sphere with an orthographic projection. That way the letters curve over the globe and get squeezed toward its edges like real continents. Stacked shells raise the letters off the surface, and gradients light the whole planet from one light source. Clouds, an ice cap, an atmosphere glow, a few islands, a ring and a moon finish it off. [resvg](https://github.com/thx/resvg-js) renders the PNGs. - -```sh -bun install -bun run build -``` - -| file | what | -| --- | --- | -| `logo.svg` / `logo.png` | on a deep-space background | -| `logo-transparent.svg` / `logo-transparent.png` | planet only, transparent background | - -The settings at the top of `index.js` control the camera tilt (`T`), how far the word wraps around the planet (`SPAN`), how high the letters rise (`RISE`), the letter spacing (`TRACK`), the light direction (`L`) and the ring bands (`RINGS`). diff --git a/designs/renox-as-planet/versions/blue/bun.lock b/designs/renox-as-planet/versions/blue/bun.lock deleted file mode 100644 index cd729d5..0000000 --- a/designs/renox-as-planet/versions/blue/bun.lock +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lockfileVersion": 2, - "configVersion": 1, - "workspaces": { - "": { - "name": "logo", - "dependencies": { - "@fontsource/unbounded": "^5.3.0", - "@resvg/resvg-js": "^2.6.2", - "opentype.js": "^2.0.0", - }, - }, - }, - "packages": { - "@fontsource/unbounded": ["@fontsource/unbounded@5.3.0", "", {}, "sha512-pPD6hsTnjoQRr6pCsqMHbHBfauB4LZygCNQEUJHu+CO2wzDFHqELEFSG7sTwo5Z5Gr4q3OK0fIILOXBJDv6lcw=="], - - "@resvg/resvg-js": ["@resvg/resvg-js@2.6.2", "", { "optionalDependencies": { "@resvg/resvg-js-android-arm-eabi": "2.6.2", "@resvg/resvg-js-android-arm64": "2.6.2", "@resvg/resvg-js-darwin-arm64": "2.6.2", "@resvg/resvg-js-darwin-x64": "2.6.2", "@resvg/resvg-js-linux-arm-gnueabihf": "2.6.2", "@resvg/resvg-js-linux-arm64-gnu": "2.6.2", "@resvg/resvg-js-linux-arm64-musl": "2.6.2", "@resvg/resvg-js-linux-x64-gnu": "2.6.2", "@resvg/resvg-js-linux-x64-musl": "2.6.2", "@resvg/resvg-js-win32-arm64-msvc": "2.6.2", "@resvg/resvg-js-win32-ia32-msvc": "2.6.2", "@resvg/resvg-js-win32-x64-msvc": "2.6.2" } }, "sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q=="], - - "@resvg/resvg-js-android-arm-eabi": ["@resvg/resvg-js-android-arm-eabi@2.6.2", "", { "os": "android", "cpu": "arm" }, "sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA=="], - - "@resvg/resvg-js-android-arm64": ["@resvg/resvg-js-android-arm64@2.6.2", "", { "os": "android", "cpu": "arm64" }, "sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ=="], - - "@resvg/resvg-js-darwin-arm64": ["@resvg/resvg-js-darwin-arm64@2.6.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A=="], - - "@resvg/resvg-js-darwin-x64": ["@resvg/resvg-js-darwin-x64@2.6.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw=="], - - "@resvg/resvg-js-linux-arm-gnueabihf": ["@resvg/resvg-js-linux-arm-gnueabihf@2.6.2", "", { "os": "linux", "cpu": "arm" }, "sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw=="], - - "@resvg/resvg-js-linux-arm64-gnu": ["@resvg/resvg-js-linux-arm64-gnu@2.6.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg=="], - - "@resvg/resvg-js-linux-arm64-musl": ["@resvg/resvg-js-linux-arm64-musl@2.6.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg=="], - - "@resvg/resvg-js-linux-x64-gnu": ["@resvg/resvg-js-linux-x64-gnu@2.6.2", "", { "os": "linux", "cpu": "x64" }, "sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw=="], - - "@resvg/resvg-js-linux-x64-musl": ["@resvg/resvg-js-linux-x64-musl@2.6.2", "", { "os": "linux", "cpu": "x64" }, "sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ=="], - - "@resvg/resvg-js-win32-arm64-msvc": ["@resvg/resvg-js-win32-arm64-msvc@2.6.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ=="], - - "@resvg/resvg-js-win32-ia32-msvc": ["@resvg/resvg-js-win32-ia32-msvc@2.6.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w=="], - - "@resvg/resvg-js-win32-x64-msvc": ["@resvg/resvg-js-win32-x64-msvc@2.6.2", "", { "os": "win32", "cpu": "x64" }, "sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ=="], - - "opentype.js": ["opentype.js@2.0.0", "", { "bin": { "ot": "bin/ot" } }, "sha512-kCyjv6xdDY1W/jLWZ/L3QhhTlKUqDZMQ5+Jdlw12b3dXkKNpYBqqlMMj0YDQPShWFTMwgZI1hG14kN3XUDSg/A=="], - } -} diff --git a/designs/renox-as-planet/versions/blue/index.js b/designs/renox-as-planet/versions/blue/index.js deleted file mode 100644 index 45386fa..0000000 --- a/designs/renox-as-planet/versions/blue/index.js +++ /dev/null @@ -1,144 +0,0 @@ -// Renox as a planet: the word's glyph outlines are wrapped onto a sphere as raised -// continents, then lit, given an atmosphere, clouds, an ice cap and a ring. -import opentype from 'opentype.js' -import { Resvg } from '@resvg/resvg-js' -import { readFileSync, writeFileSync } from 'fs' - -const at = p => new URL(p, import.meta.url) -const fb = readFileSync(at('node_modules/@fontsource/unbounded/files/unbounded-latin-900-normal.woff')) -const font = opentype.parse(fb.buffer.slice(fb.byteOffset, fb.byteOffset + fb.byteLength)) - -const { sin, cos, hypot, ceil, min, max, PI } = Math -const D = PI / 180, S = 1200, C = S / 2, R = 300 -const T = 18 * D // camera elevation above the equator -const SPAN = 66 * D // half the longitude the word wraps around -const LAT = T // word latitude, puts it dead centre of the disc -const RISE = .03 // continent height as a fraction of R -const TRACK = 4 // letter spacing in em/100 -const L = (v => v.map(c => c / hypot(...v)))([-.55, .62, .56]) // light, view space -const RINGS = [[1.3, 1.37, .25], [1.39, 1.58, .7], [1.61, 1.64, .3], [1.67, 1.8, .5], [1.82, 1.85, .22]] -const n = v => +v.toFixed(1) -const rnd = (s => () => (s = (s * 16807) % 2147483647) / 2147483647)(7) - -// lon/lat on a sphere of radius r -> screen [x, y, depth] (depth > 0 faces the camera) -const P = (lon, lat, r = 1) => { - const x = cos(lat) * sin(lon), y = sin(lat), z = cos(lat) * cos(lon) - return [C + R * r * x, C - R * r * (y * cos(T) - z * sin(T)), y * sin(T) + z * cos(T)] -} -const poly = pts => 'M' + pts.map(([x, y]) => n(x) + ' ' + n(y)).join('L') - -// lay out the word, then flatten every outline into dense polylines so straight -// strokes bend properly once they are wrapped round the sphere -const cmds = [] -const gs = font.stringToGlyphs('RENOX') -gs.reduce((x, g, i) => { - cmds.push(...g.getPath(x, 0, 100).commands) - return x + (g.advanceWidth + (gs[i + 1] ? font.getKerningValue(g, gs[i + 1]) : 0)) / font.unitsPerEm * 100 + TRACK -}, 0) -const bez = (q, t) => q.length < 2 ? q[0] : bez(q.slice(1).map((v, i) => [q[i][0] + (v[0] - q[i][0]) * t, q[i][1] + (v[1] - q[i][1]) * t]), t) -const outlines = [] -let cur, p -for (const c of cmds) { - if (c.type == 'Z') continue - const q = [p, c.x1 != null && [c.x1, c.y1], c.x2 != null && [c.x2, c.y2], [c.x, c.y]].filter(Boolean) - if (c.type == 'M') outlines.push(cur = [[c.x, c.y]]) - else for (let i = 1, k = max(2, ceil(q.slice(1).reduce((s, v, j) => s + hypot(v[0] - q[j][0], v[1] - q[j][1]), 0))); i <= k; i++) cur.push(bez(q, i / k)) - p = [c.x, c.y] -} -const xs = outlines.flat().map(v => v[0]), ys = outlines.flat().map(v => v[1]) -const xm = (min(...xs) + max(...xs)) / 2, ym = (min(...ys) + max(...ys)) / 2 -const k = SPAN / ((max(...xs) - min(...xs)) / 2) -const word = r => outlines.map(o => poly(o.map(([x, y]) => P((x - xm) * k, LAT + (ym - y) * k * cos(LAT), r))) + 'Z').join('') + islands(r) - -// clouds: soft streaks drifting along latitudes, kept clear of the word -const clouds = Array.from({ length: 16 }, () => { - const lat = (rnd() < .5 ? -46 + rnd() * 32 : 40 + rnd() * 20) * D, lon = (rnd() * 240 - 120) * D, len = (18 + rnd() * 36) * D - const amp = (rnd() - .5) * 5 * D, w = n(4 + rnd() * 8), o = .2 + rnd() * .25 - const pts = Array.from({ length: 48 }, (_, i) => P(lon + len * i / 47, lat + amp * sin(i / 47 * PI), 1 + RISE * 1.2)).filter(v => v[2] > .1) - return pts.length > 3 ? `` : '' -}).join('') - -// islands: a small archipelago so the letters read as continents -const isles = [[-50, 45, 2.4], [44, 47, 1.7], [-38, -31, 3], [-24, -37, 1.3], [34, -34, 2.2], [50, -27, 1.2]] - .map(([lon, lat, rad]) => [lon * D, lat * D, rad * D, rnd() * 9]) -const islands = r => isles.map(([lon, lat, rad, ph]) => poly(Array.from({ length: 48 }, (_, i) => { - const a = i / 48 * 2 * PI, q = rad * (1 + .2 * sin(3 * a + ph) + .1 * sin(5 * a + ph * 2)) - return P(lon + q * cos(a) / cos(lat), lat + q * sin(a), r) -})) + 'Z').join('') - -// relief: stack shells from the sea floor up to the plateau, darkest first -const mix = (a, b, t) => '#' + [0, 2, 4].map(i => n(parseInt(a.slice(i + 1, i + 3), 16) * (1 - t) + parseInt(b.slice(i + 1, i + 3), 16) * t) | 0).map(v => v.toString(16).padStart(2, '0')).join('') -const relief = Array.from({ length: 9 }, (_, i) => ``).join('') - -const cap = poly(Array.from({ length: 180 }, (_, i) => P(i * 2 * D, (75 + 1.6 * sin(i * 2 * D * 5) + .9 * sin(i * 2 * D * 13 + 1)) * D, 1 + RISE * .6))) + 'Z' - -const ring = ` - - ${RINGS.flatMap(([a, b, o], _, __, m = ceil((b - a) / .005)) => Array.from({ length: m }, (_, i) => { - const r = a + (b - a) * (i + .5) / m - return `` - })).join('')} - ` - -const stars = Array.from({ length: 170 }, () => { - const x = n(rnd() * S), y = n(rnd() * S), r = rnd() ** 3 * 2.2 + .5, o = n(.25 + rnd() * .75) - return r > 2.1 - ? `` - : `` -}).join('') - -const lx = n(C + L[0] * R * .62), ly = n(C - L[1] * R * .62) -const svg = bg => ` - - - - - - - - - - - - - - - - - - - - - -${bg ? ` - - -${stars}` : ''} - - - - - - - - - - - - - ${relief} - - - ${clouds} - - - - -${ring} -` - -for (const [name, bg] of [['logo', 1], ['logo-transparent', 0]]) { - const s = svg(bg) - writeFileSync(at(name + '.svg'), s) - writeFileSync(at(name + '.png'), new Resvg(s, { fitTo: { mode: 'width', value: 2048 }, background: bg ? '#030210' : undefined }).render().asPng()) -} diff --git a/designs/renox-as-planet/versions/blue/logo-transparent.png b/designs/renox-as-planet/versions/blue/logo-transparent.png deleted file mode 100644 index 84ad5f0..0000000 Binary files a/designs/renox-as-planet/versions/blue/logo-transparent.png and /dev/null differ diff --git a/designs/renox-as-planet/versions/blue/logo-transparent.svg b/designs/renox-as-planet/versions/blue/logo-transparent.svg deleted file mode 100644 index 2efbf62..0000000 --- a/designs/renox-as-planet/versions/blue/logo-transparent.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/designs/renox-as-planet/versions/blue/logo.png b/designs/renox-as-planet/versions/blue/logo.png deleted file mode 100644 index 981af6a..0000000 Binary files a/designs/renox-as-planet/versions/blue/logo.png and /dev/null differ diff --git a/designs/renox-as-planet/versions/blue/logo.svg b/designs/renox-as-planet/versions/blue/logo.svg deleted file mode 100644 index ea906a0..0000000 --- a/designs/renox-as-planet/versions/blue/logo.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/designs/renox-as-planet/versions/blue/package.json b/designs/renox-as-planet/versions/blue/package.json deleted file mode 100644 index 00067d5..0000000 --- a/designs/renox-as-planet/versions/blue/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "renox-as-planet-blue", - "private": true, - "type": "module", - "description": "Renox as a planet, blue ocean version", - "scripts": { - "build": "bun index.js" - }, - "dependencies": { - "@fontsource/unbounded": "^5.3.0", - "@resvg/resvg-js": "^2.6.2", - "opentype.js": "^2.0.0" - } -}