Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

blank: fix z-sorting — no bias on edges/particles, keys drawn after loop

- Remove z-bias from edges and particles (use actual z for natural sorting)
- Keyboard keys drawn after sorted loop (always on top of base, no z-fighting)
- Fixes wireframe lines poking through solid faces

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+17 -14
+17 -14
system/public/aesthetic.computer/disks/blank.mjs
··· 256 256 const kbBR = project([hw - kbInset, -0.001, 2 * hd - kbInset * 3]); 257 257 const ke1x = kbTR[0] - kbTL[0], ke1y = kbTR[1] - kbTL[1]; 258 258 const ke2x = kbBL[0] - kbTL[0], ke2y = kbBL[1] - kbTL[1]; 259 - if (ke1x * ke2y - ke1y * ke2x < 0) { 259 + // Store keyboard data to draw after sorted loop (always on top of base) 260 + let kbVisible = ke1x * ke2y - ke1y * ke2x < 0; 261 + const kbKeys = []; 262 + if (kbVisible) { 260 263 const rows = ["QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM"]; 261 264 const lerp = (a, b, t) => a + (b - a) * t; 262 265 for (let r = 0; r < rows.length; r++) { ··· 266 269 for (let k = 0; k < row.length; k++) { 267 270 const u0 = indent + (k + 0.15) / row.length * (1 - indent * 2); 268 271 const u1 = indent + (k + 0.85) / row.length * (1 - indent * 2); 269 - // Per-key z from interpolated depth 270 - const keyMidT = (t0 + t1) / 2; 271 - const keyMidU = (u0 + u1) / 2; 272 - const keyZ = lerp(lerp(kbTL[2], kbTR[2], keyMidU), lerp(kbBL[2], kbBR[2], keyMidU), keyMidT); 273 - drawList.push({ 274 - z: keyZ - 0.05, // slightly in front of base face 272 + kbKeys.push({ 275 273 type: "key", 276 274 pts: [ 277 275 [lerp(lerp(kbTL[0], kbTR[0], u0), lerp(kbBL[0], kbBR[0], u0), t0), ··· 293 291 const addEdges = (proj, edgeOffset) => { 294 292 halfEdges.forEach(([a, b], i) => { 295 293 const z = (proj[a][2] + proj[b][2]) / 2; 296 - drawList.push({ z: z - 0.1, type: "edge", proj, a, b, i, edgeOffset }); 294 + drawList.push({ z, type: "edge", proj, a, b, i, edgeOffset }); 297 295 }); 298 296 }; 299 297 addEdges(projBase, 0); ··· 310 308 const allVerts = [...projBase, ...projLid]; 311 309 for (const hv of hingeVerts) allVerts.push(...hv.map(project)); 312 310 allVerts.forEach(([px, py, pz], i) => { 313 - drawList.push({ z: pz - 0.15, type: "particle", px, py, i }); 311 + drawList.push({ z: pz, type: "particle", px, py, i }); 314 312 }); 315 313 316 314 // Sort back-to-front (highest z = farthest = draw first) ··· 325 323 ink(floor(color[0] * shade * tint[0]), floor(color[1] * shade * tint[1]), floor(color[2] * shade * tint[2])); 326 324 tri(proj[a][0], proj[a][1], proj[b][0], proj[b][1], proj[c][0], proj[c][1]); 327 325 tri(proj[a][0], proj[a][1], proj[c][0], proj[c][1], proj[d][0], proj[d][1]); 328 - } else if (item.type === "key") { 329 - const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = item.pts; 330 - ink(keyColor[0], keyColor[1], keyColor[2]); 331 - tri(x0, y0, x1, y1, x2, y2); 332 - tri(x0, y0, x2, y2, x3, y3); 333 326 } else if (item.type === "edge") { 334 327 const { proj, a, b, i, edgeOffset } = item; 335 328 const brightness = 0.55 + item.z * 0.15; ··· 350 343 const pColor = particleColors[(item.i + floor(frame * 0.04)) % particleColors.length]; 351 344 const flicker = 0.6 + sin(frame * 0.1 + item.i * 1.3) * 0.4; 352 345 ink(...pColor, floor(flicker * 150)).box(item.px - 1, item.py - 1, 2, 2); 346 + } 347 + } 348 + 349 + // ⌨️ Keyboard keys — drawn after z-sorted loop, always on top of base 350 + if (kbVisible) { 351 + for (const key of kbKeys) { 352 + const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = key.pts; 353 + ink(keyColor[0], keyColor[1], keyColor[2]); 354 + tri(x0, y0, x1, y1, x2, y2); 355 + tri(x0, y0, x2, y2, x3, y3); 353 356 } 354 357 } 355 358