SOURCE / PINNED RELEASE
Made of little things.
Body Journal
- Release
- e8049f8da4e2…
- Author-recorded commit
- 61c04bf0e8aa…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6c4554844c7
Archive hash verified: 4369d778da046a8b…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
import { MOUTH_MODEL } from './layers.js';
import type { Point3 } from './case.js';
export interface MouthPart {
id: string; label: string; part: string; kind: 'tooth' | 'tongue' | 'jaw'; jaw: 'upper' | 'lower'; fdi?: number;
vertices: number; triangles: number; positions: number; indices: number;
}
export interface MouthData { parts: MouthPart[]; head: Point3; hinge: Point3; buffer: ArrayBuffer; start: number }
export function decodeMouth(buffer: ArrayBuffer): MouthData {
const decoder = new TextDecoder(), view = new DataView(buffer);
if (decoder.decode(new Uint8Array(buffer, 0, 8)) !== 'BJMOUTH1') throw new Error('Unsupported mouth asset.');
const length = view.getUint32(8, true), start = 12 + length;
const meta = JSON.parse(decoder.decode(new Uint8Array(buffer, 12, length)));
if (meta.id !== MOUTH_MODEL || !Array.isArray(meta.parts) || meta.parts.length !== 32) throw new Error('Mouth version mismatch.');
return { parts: meta.parts, head: meta.head, hinge: meta.hinge, buffer, start };
}
