SOURCE / PINNED RELEASE
Made of little things.
Safe Sand · Material studies
- Release
- 9101a9cd9fb4…
- Author-recorded commit
- 75d98e1b8edb…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-7682e55a791
Archive hash verified: 6c8ddabeb31100e1…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// A bounded orthographic orbit. World x points right, y down, height up.
export class TrayCamera {
constructor() { this.pitch = 0; this.yaw = 0; }
set(pitch, yaw) {
this.pitch = Math.max(-35, Math.min(35, Number.isFinite(pitch) ? pitch : 0));
this.yaw = Math.max(-35, Math.min(35, Number.isFinite(yaw) ? yaw : 0));
}
basis() {
const p = this.pitch * Math.PI / 180, y = this.yaw * Math.PI / 180;
return [Math.sin(p), Math.cos(p), Math.sin(y), Math.cos(y)];
}
scale(world) {
const [sp, cp, sy, cy] = this.basis();
const fit = Math.max(1, Math.abs(cy) + Math.abs(sy * sp) * world[1] / world[0], Math.abs(cp));
return fit * (1 + 0.12 * Math.max(Math.abs(this.pitch), Math.abs(this.yaw)) / 35);
}
rotate([x, y, z]) {
const [sp, cp, sy, cy] = this.basis();
return [cy * x + sy * (sp * y + cp * z), cp * y - sp * z, -sy * x + cy * (sp * y + cp * z)];
}
project(x, y, z, world) {
const p = this.rotate([x - world[0] / 2, world[1] / 2 - y, z]);
const scale = this.scale(world);
return [0.5 + p[0] / (world[0] * scale), 0.5 - p[1] / (world[1] * scale), p[2]];
}
unproject(u, v, world) {
const [sp, cp, sy, cy] = this.basis(), scale = this.scale(world);
const Y = (0.5 - v) * world[1] * scale / cp;
const X = ((u - 0.5) * world[0] * scale - sy * sp * Y) / cy;
return [X + world[0] / 2, world[1] / 2 - Y];
}
}
