Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

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

blank: auto-correct face normals to point outward from box center

- Compute box center, then flip any normal that points inward
- Works correctly for both base (y goes +) and lid (y goes -)
- No more wrong-direction normals from inconsistent vertex ordering
- Fixes faces disappearing or back faces showing through

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

+19 -7
+19 -7
system/public/aesthetic.computer/disks/blank.mjs
··· 239 239 240 240 const addFaces = (verts3d, proj, color, tag) => { 241 241 const frontFaces = new Set(); 242 + // Compute box center for outward normal correction 243 + let cx3 = 0, cy3 = 0, cz3 = 0; 244 + for (const v of verts3d) { cx3 += v[0]; cy3 += v[1]; cz3 += v[2]; } 245 + cx3 /= verts3d.length; cy3 /= verts3d.length; cz3 /= verts3d.length; 246 + 242 247 for (let fi = 0; fi < faceQuads.length; fi++) { 243 248 const [a, b, c, d] = faceQuads[fi]; 249 + // Face center 250 + const fcx = (verts3d[a][0] + verts3d[b][0] + verts3d[c][0] + verts3d[d][0]) / 4; 251 + const fcy = (verts3d[a][1] + verts3d[b][1] + verts3d[c][1] + verts3d[d][1]) / 4; 252 + const fcz = (verts3d[a][2] + verts3d[b][2] + verts3d[c][2] + verts3d[d][2]) / 4; 244 253 // 3D face normal via cross product of two edges 245 - const e1 = [verts3d[b][0] - verts3d[a][0], verts3d[b][1] - verts3d[a][1], verts3d[b][2] - verts3d[a][2]]; 246 - const e2 = [verts3d[d][0] - verts3d[a][0], verts3d[d][1] - verts3d[a][1], verts3d[d][2] - verts3d[a][2]]; 247 - const nx = e1[1] * e2[2] - e1[2] * e2[1]; 248 - const ny = e1[2] * e2[0] - e1[0] * e2[2]; 249 - const nz = e1[0] * e2[1] - e1[1] * e2[0]; 250 - // Dot with view direction — positive = facing camera 254 + const e1x = verts3d[b][0] - verts3d[a][0], e1y = verts3d[b][1] - verts3d[a][1], e1z = verts3d[b][2] - verts3d[a][2]; 255 + const e2x = verts3d[d][0] - verts3d[a][0], e2y = verts3d[d][1] - verts3d[a][1], e2z = verts3d[d][2] - verts3d[a][2]; 256 + let nx = e1y * e2z - e1z * e2y; 257 + let ny = e1z * e2x - e1x * e2z; 258 + let nz = e1x * e2y - e1y * e2x; 259 + // Ensure normal points OUTWARD (away from box center) 260 + const outDot = nx * (fcx - cx3) + ny * (fcy - cy3) + nz * (fcz - cz3); 261 + if (outDot < 0) { nx = -nx; ny = -ny; nz = -nz; } 262 + // Dot with view direction — negative = faces camera (opposes view dir) 251 263 const dot = nx * viewDirX + ny * viewDirY + nz * viewDirZ; 252 - if (dot >= 0) continue; // normal faces away from camera → back-facing 264 + if (dot >= 0) continue; // faces away from camera → skip 253 265 frontFaces.add(fi); 254 266 const z = (proj[a][2] + proj[b][2] + proj[c][2] + proj[d][2]) / 4; 255 267 drawList.push({ z, type: "face", proj, verts: [a, b, c, d], color, tag });