MOUTH & TEETH STUDIO 3.0.0 Guide for people and agents SPECIES AND PART LIBRARIES 128 complete profiles, 29 independent tooth sets, 18 tongues and 18 gum/jaw sets. Human detailed anatomy exposes the new flesh, crown and tissue surface controls. New empty recipes and new pages start with Human32 and natural smooth materials. Search by species, family or ID. Living, Prehistoric and Fantasy filters change the visible choices. Nine legacy starting IDs remain available. Choose a profile, then Apply whole mouth or Apply teeth only. Each apply is one undo action. New random mouth chooses from the selected family or era using the draw seed. All omits the filter. A selection alone never changes the asset. Whole mouth starts fresh, preserves texture resolution and retains category locks. Keep art style preserves the style category, including part overrides. The chosen profile supplies its natural anatomical texture palette. Teeth only changes the teeth category, fitting crown dimensions to the current jaw width; shape, tongue, textures, style and profile metadata remain unchanged. The library shows reference counts, current rendered counts, notes and sources. Counts exclude outlines and include every enabled visible replacement/palatal tooth. Hidden groups report zero visible teeth. Reference counts are not a claim about the edited recipe. Dimensions are artistic starting values, not clinical. Rabbit: 14 outer upper + 2 inner peg teeth = 16 upper, 12 lower. Python: 36 outer upper + 32 palatal upper = 68 upper, 36 lower. Shark: three visible rows of 26 upper/24 lower = 150, 50 in the front row. Horse40 includes canines, excludes optional wolf teeth; individual counts vary. Alligator76, python104 and dolphin88 are representative variable-count profiles. Cow/sheep/goat/deer have an actual upper dental pad and no upper front teeth. Macaw and tortoise have zero teeth and distinct hooked/grazing keratin shells. Separate teeth, tongue and gum preset menus apply only that category. Choose a preset and click its Apply button; each is one undo action. Other categories and the species identity remain unchanged. Native part dimensions, when supplied, are used for fitting. Inspect fit after mixing parts from different species. Fantasy profiles are artist-designed. Prehistoric profiles are representative authoring reconstructions: exact counts and soft tissues are often uncertain. Reference notes and source URLs accompany complete profiles. Goose keratin serrations, cephalopod radular hooks and armored jaw plates use editable tooth-like meshes; their counts describe authored structures, not vertebrate teeth. The library labels these separately. Preserve anatomy keeps kinds, slots, counts, rows, placement/gaps, pad and beak type. Variation band sets the spread: Subtle, Natural, Bold or Wild. Natural is the default. Stronger bands broaden dimensions while retaining the protected dentition. Turn Preserve anatomy off for freeform experiments. Whole-mouth variation preserves the chosen art style; Style scope still varies style explicitly. Category locks apply to Vary, including selected-tooth scope. Explicit sliders, tooth type, position, label and recipe edits remain available. Canonical crowns emerge at the gum surface; legacy custom rows retain their original attachment. Gnawing incisors curve backward and grazing cheek teeth form packed grinding batteries. Every slot remains independently editable. New random mouth is an explicit new profile choice; Vary keeps the current one. Browser examples after ready: MouthStudio.setPreset("cat",{scope:"mouth",preserveStyle:false}); MouthStudio.setPreset("horse",{scope:"teeth"}); MouthStudio.randomPreset({seed:174,strength:.35,preserveStyle:false}); MouthStudio.setTooth("upper-r0-t3",{kind:"canine",archPosition:.22,label:"My canine"}); MouthStudio.setConfig({preserveAnatomy:false}); // enable freeform variation Use listPresets() for all IDs, full recipe data, reference counts and source URLs. Open /tools/mouth/. Wait for "Ready" or "Recipe ready". Choose Shape, Teeth, Tongue, Textures, Style or Studio. Every numeric module field has a real range slider and a numeric input with the same bounds and step. Checkboxes control real visibility or geometry options. Changes coalesce after 120 ms. Invalid changes retain the last good recipe and preview. Drag to orbit; scroll/pinch to zoom. Front, Side and Fit reposition the camera. Rest/Open edit shape.jawOpenDeg. Lower geometry rotates once about jawHinge; commissures already posed by the shape module are not rotated again. The rear connectors are thin recessed membranes. shape.cornerFlesh is their half-thickness in meters: .00025-.002, default .00075. Depth no longer follows lip size. Old recipes with legal larger values (up to .065) normalize to .002; other fields are preserved. Random generation uses the new thin bounds. Voxel/grid/reduction/outline geometry styling does not inflate these two connectors; material, toon and pixel styling still applies. Other parts retain their full geometry style controls. Reloading 3.0.0 loads versioned modules. Studio contains geometry detail, geometry seed, group visibility and category randomization locks. Solo isolates the active anatomical part; Restore restores the visibility saved before solo. Module visibility toggles remain independent. Select teeth by clicking geometry or choosing a stable slot, including absent slots. Individual edits are sparse overrides. Tooth present=true restores a seeded missing slot. Clear overrides returns every value to jaw inheritance. Upper/lower count and rows do not renumber existing IDs. Style target selects global settings or inherited shape/teeth/tongue overrides. Clear target override restores global style for that group. Vary whole mouth and the direct Shape, Teeth, Tongue, Textures and Style buttons are always visible above Seeded variation. Vary selected tooth is in Individual tooth and stays disabled until a slot is selected. All these buttons and Generate variation use the same Variation seed, Strength and Studio category locks. Scopes: all,shape,teeth,tongue,textures, style,tooth. Selected-tooth randomization respects the teeth lock. After a successful UI action the draw seed advances (2147483646 wraps to 1). The same recipe, draw seed and options give the same result. Non-target and locked categories are unchanged; the draw seed does not change config.seed. Each changed result is one undo action. Locked/zero-strength no-ops add none. Undo/redo holds at most 50 recipes, never texture maps. Legacy starting recipes remain in the Mouth library. Seed/scope/strength remain in Seeded variation. Automation can click [data-random-scope="all"] or the shape/teeth/tongue/textures/ style/tooth equivalents. These attributes identify the direct buttons. Texture resolution is actual shared atlas size: 640,720,1024,1536,2048,3072,4096. There is no automatic downscale. 4096 allocates 192 MiB for three raw RGBA maps. Geometry-only changes reuse one bounded atlas cache. Quality presets set real geometry detail and shared map size. They do not replace art style. The readout shows actual detail, map size and triangle count. Detailed uses 4096 maps; use a smaller quality or map size to reduce memory. Art style is explicit: Source, Sculpted, Organic, Faceted, Low-poly or Stylized. Sculpt crease, organic bulge, facet planes, low-poly amount, stylize amount and edge hardness are independent refinements with global and part overrides. Source mode with zero refinements retains authored mesh positions. Reduction must preserve closed surfaces; an unsafe reduction can be rejected or skipped. New geometry controls include gum scallop/recession/ridge, palate ridges, lip Cupid bow/wrinkles; tooth fluting/bulge/neck pinch/fang groove; tongue bulbous tip/cupping/edge ruffle/dorsal fold/papilla length. These change real meshes. Tooth forms add needle, saber, leaf, spade, crushing and trident crowns. Surface controls add enamel perikymata/translucency, gum mottling/stipple, lip dryness, tongue coating, cavity rugae/moisture. Translucency here is a painted surface cue, not a claim of volumetric tooth optics. The preview draws on changes and during orbit damping, then stops when idle. No model weights, inference service or AI tokens are needed for authoring. Part material colors are tints, default white; Textures owns anatomical colors. Part/style roughness factors multiply anatomical roughness maps. Preview uses PBR albedo, tangent normal and ORM with studio reflections. Lighting, exposure, background, camera and selection highlight are viewing aids. Download textured GLB embeds actual PNG albedo, normal and ORM. Export part uses the same pipeline. PNG download exports one complete shared atlas. Save/load recipes uses nested schemaVersion:2 JSON, up to 256 KiB. Recipes stay in this page unless you explicitly send them to the HTTP API. SCALE AND MODEL Coordinates: meters, +Y up, +Z forward. shape.jawOpenDeg is degrees. Consult schema() or GET schema for every nested field, default, bound and step. Unknown keys, unsafe prototype keys, accessors and nonfinite values are rejected. Named parts and a local jaw hinge hierarchy come from the model; no skin rig. Detail controls actual exported subdivisions. Preview ceiling: 500,000 triangles; game/export ceiling: 1,500,000. Default detail is 0.35. Ceilings are not targets. Extreme controls can intersect. Warnings include neutral flesh and posed tooth/tongue AABB broad-phase overlaps; they are not exact collision proofs. Real voxel/faceted geometry comes from the style module and is exported. Flat-shading hints produce actual split vertices and face normals. Outline hints produce reversed, expanded hull geometry. Cel bands are baked directional vertex colors, preserved in GLB COLOR_0; they are not a runtime toon shader. Clearcoat, transmission and volume use standard glTF extensions. Atlas UVs are remapped once. Raw row 0 is UV v=0 and PNG row 0. Albedo is sRGB; normal/ORM are linear. No mipmaps are generated across anatomical tile gutters. ORM R=occlusion, G=roughness; B is a unit mask multiplied by material metallicity. BROWSER API (available as window.MouthStudio) getState() -> ready,previewReady,version,config,metrics,error,previewError,busy, selectedTooth,undoCount,redoCount; returned recipe data is copied. schema() -> configSchema,defaults,fields,toothFields,styleOverrideKey,units. listPresets() -> new + legacy catalog with family,description,config, expectedUpper/Lower/Total,sourceUrls,nativeWidth/Length,notes. setConfig(patch) -> state; recursively merges nested objects; arrays replace. setPreset(id,{scope="mouth",preserveStyle=false}) -> state; reset() -> Human32. listPartPresets("teeth"|"tongue"|"gums") -> independent part catalog. setPartPreset(scope,id) -> state; apply one part with one undo step. randomPreset({seed,strength=.35,preserveStyle=false,variationBand="natural",family}) -> state. family is a catalog family or living,prehistoric,fantasy; omit for all species. randomize({scope="all",seed,strength=.35,locks={},toothId,variationBand="natural"}) -> state. variationBand is subtle,natural,bold,wild. Scopes: all,shape,teeth,tongue,textures,style,tooth. For tooth, toothId defaults to selectedTooth. Explicit toothId needs no selection. locks temporarily overrides recipe category locks for this call; saved flags stay. undo(), redo() -> state. setVisibility("shape"|"teeth"|"tongue",boolean) -> state. solo(group), solo(null) -> state. selectTooth(stableID|null) -> state. setTooth(stableID,patch), clearTooth(stableID=selectedTooth) -> state. clearPartStyle("shape"|"teeth"|"tongue") -> state. exportGLB(tier="game") -> Uint8Array; synchronous GEOMETRY-ONLY compatibility API. exportTexturedGLB({tier="game"}) -> Promise, embedded PNG maps. exportPart(groupOrExactPartName,{tier="game"}) -> Promise. exportPNG("baseColor"|"albedo"|"normal"|"orm") -> Promise. Exports return bytes and do not initiate downloads. Browser PNG encoding uses Canvas/OffscreenCanvas; no server rendering capability is claimed. getInstructions() -> brief instructions and guide path. Wait for getState().ready or document's "mouthstudio:ready" event. A missing WebGL preview still permits recipes, PNG and pure-model GLB export. Exports temporarily lock mutation. SDK errors throw/reject; UI errors are visible. Example (browser console after ready): const s = window.MouthStudio; s.setConfig({shape:{jawOpenDeg:35},tongue:{curl:.3},textures:{resolution:"2048"}}); s.randomize({scope:"all",seed:174,strength:.35,locks:{teeth:true}}); s.randomize({scope:"tongue",seed:175,strength:.35}); s.selectTooth("upper-r0-t3"); s.setTooth("upper-r0-t3",{length:.055,molar:0,tusk:.8}); s.randomize({scope:"tooth",seed:176,strength:.35}); // selected slot s.randomize({scope:"tooth",toothId:"lower-r0-t2",seed:177,strength:.35}); s.undo(); // restore the recipe before the last changed randomization const bytes = await s.exportPart("teeth"); const fullRecipe = s.getState().config; fullRecipe.shape.jawOpenDeg = 20; s.setConfig(fullRecipe); // full recipe; setConfig({tongue:{curl:.4}}) is a part patch STATELESS HTTP API Base: /api/game-assets/mouth/ GET schema -> version, configSchema, defaults, limits, requestSchemas, tiers. GET presets -> version, presets. GET part-presets -> version, scopes: {teeth:[...],tongue:[...],gums:[...]}. POST part-preset -> version, config. Body: {"config":{},"scope":"tongue","id":"an ID from GET part-presets"} config, scope and id are required. Scope is teeth, tongue or gums. POST preset -> version, config. Body: {"config":{},"id":"cat","scope":"mouth","preserveStyle":false} scope is "mouth" or "teeth"; scope/preserveStyle may be omitted. POST random-preset -> version, config. Body: {"config":{},"options":{"seed":174,"strength":0.35,"preserveStyle":false}} options may be omitted; seed,strength,preserveStyle,variationBand,family accepted. POST validate -> version, normalized full config. POST recipe -> normalized downloadable schemaVersion:2 JSON. POST randomize -> version, config. Body: {"config":{...},"options":{...}}. POST generate -> version, tier, config, units, up, forward, parts, landmarks, metrics. Geometry arrays in generate are ordinary numeric JSON arrays. POST export.glb -> GEOMETRY-ONLY model/gltf-binary, X-Mouth-Export: geometry-only. No PNG maps are embedded by HTTP export. Use the browser SDK for textured GLB. POST requires Content-Type: application/json and at most 262144 UTF-8 body bytes. generate/export.glb accept {"config":{...},"tier":"preview"|"game"}. validate/recipe accept only {"config":{...}}. randomize accepts {"config":{...},"options":{...}}; options may be omitted. Unknown wrapper keys are rejected. generate defaults to preview; export.glb defaults to game. Config keys/types/bounds come from model.js validation; unknown keys are rejected. Errors: 400 bad recipe/JSON, 405 method, 413 size, 415 content type, 422 geometry limits, 500 unexpected generation failure. The dispatcher returns 404 for unknown mouth/eye endpoints. The HTTP API requires no authentication, account, API key, token or credentials. No cookies, server recipe storage or GPU are required. HTTP RECIPE AND RANDOMIZATION EXAMPLES Config can be partial: missing fields use defaults. HTTP requests do not merge with a previous request or the browser editor. To preserve an existing mouth, send its full recipe and change only the intended category. Validate first. Supported scopes: all,shape,teeth,tongue,textures,style,tooth. options.seed is a safe integer; strength is 0..1 (default .35). Recipe locks apply unless options.locks overrides those category flags for the current call. Locks are shape,teeth,tongue,textures,style; saved flags stay intact. Non-target and locked categories stay unchanged. Tooth scope respects teeth. HTTP scope:"tooth" requires options.toothId, e.g. "upper-r0-t3". Browser SDK toothId may be omitted after selectTooth(); HTTP has no selection. Whole mouth, with teeth locked (partial recipe; defaults fill other fields): POST /api/game-assets/mouth/randomize Content-Type: application/json {"config":{"shape":{"jawOpenDeg":35}},"options":{"scope":"all","seed":174,"strength":0.35,"locks":{"teeth":true}}} Tongue only; other categories remain unchanged: POST /api/game-assets/mouth/randomize Content-Type: application/json {"config":{"tongue":{"curl":0.3}},"options":{"scope":"tongue","seed":175,"strength":0.35,"locks":{"shape":true,"teeth":true}}} A single stable tooth slot (no browser selection is needed over HTTP): POST /api/game-assets/mouth/randomize Content-Type: application/json {"config":{},"options":{"scope":"tooth","seed":176,"strength":0.35,"locks":{"teeth":false},"toothId":"upper-r0-t3"}} Partial recipe editing, normalized into a full recipe: POST /api/game-assets/mouth/validate Content-Type: application/json {"config":{"shape":{"jawOpenDeg":35},"tongue":{"curl":0.3}}} POST /api/game-assets/mouth/generate Content-Type: application/json {"config":{"shape":{"jawOpenDeg":35},"tongue":{"curl":0.3}},"tier":"preview"} Full recipe editing and generation (same-origin browser JavaScript): async function postMouth(route, body) { const response = await fetch("/api/game-assets/mouth/" + route, { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(body) }); const data = await response.json(); if (!response.ok) throw new Error(response.status + ": " + data.error.message); return data; } const checkedPart = await postMouth("validate", { config: {shape:{jawOpenDeg:35}, tongue:{curl:0.3}} }); const fullRecipe = structuredClone(checkedPart.config); // For an existing mouth, start with its saved full recipe instead. fullRecipe.tongue.curl = 0.5; const checkedFull = await postMouth("validate", {config:fullRecipe}); const geometry = await postMouth("generate", { config:checkedFull.config, tier:"preview" }); // All other categories in checkedFull.config survive this tongue edit. Use a full recipe with any randomization scope, then keep the returned config: const varied = await postMouth("randomize", { config:checkedFull.config, options:{scope:"textures",seed:177,strength:0.35,locks:{teeth:true}} }); const nextRecipe = varied.config; Geometry-only server GLB bytes from that recipe: const glbResponse = await fetch("/api/game-assets/mouth/export.glb", { method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify({config:nextRecipe,tier:"game"}) }); if (!glbResponse.ok) { const failure = await glbResponse.json(); throw new Error(glbResponse.status + ": " + failure.error.message); } const glbBytes = new Uint8Array(await glbResponse.arrayBuffer()); // No texture images are embedded here. Browser PBR export: // await MouthStudio.exportTexturedGLB({tier:"game"}); // That browser export uses the editor's recipe; setConfig(nextRecipe) to load it. The complete POST body, including wrapper/options, must fit 256 KiB (262144 UTF-8 bytes). Failures return {"error":{"code":"...","message":"..."}} and a non-2xx status; inspect response.ok before using config or GLB bytes. Keep the last good full recipe locally and replace it only after success. A rejected HTTP request does not change the editor. SDK errors throw/reject; UI failures display an error and retain the last good recipe and preview. Failed UI randomization leaves its draw seed unchanged. PER-TOOTH RECIPE FORMAT teeth.upper.overrides and teeth.lower.overrides are sparse arrays, at most 256 entries per jaw. Example: {"id":"upper-r0-t3","enabled":true,"kind":"canine","archPosition":0.22,"label":"Left canine","length":0.012,"wear":0.2,"color":"#ffffff"} IDs use upper/lower-r0..3-t0..63. Override fields are schema().toothFields. Count, rows, spacing, rowOffset and missing remain jaw controls. Overrides for inactive slots survive count changes. Missing slots retain their original IDs. archPosition is normalized arc length: back-left 0, front .5, back-right 1. Kinds: custom,incisor,canine,premolar,molar,carnassial,selenodont,hypsodont, rodent-incisor,conical,recurved,serrated,tusk,peg. Type and position are explicit selected-tooth controls. molarCuspCount is an integer 2..6. Slot labels allow at most 80 characters. Configs retain nested schemaVersion:2. LEGACY MIGRATION AND PURE MODULE API Flat v1 recipes and setConfig({jawOpenDeg:35}) remain accepted through an explicit mapping. Tooth enums become continuous morphology contributions; old colors become atlas base colors. Current module limits clamp migrated values, with up to 64 teeth per row. Migration is not byte-identical v1 geometry. Old procedural validation/build remain available as validateLegacyConfig and buildLegacyMouth for root's compatibility checks. Complete old schema2 recipes without profileId use BASE_DEFAULTS, profileId "custom" and freeform variation, preserving existing dimensions and behavior. Flat schema1 recipes migrate from BASE_DEFAULTS; empty config uses Human32. model.js exports VERSION,DEFAULTS,BASE_DEFAULTS,FIELDS,PRESETS,MOUTH_PRESETS, getSchema,validateConfig,applyPreset,randomPresetConfig,mergeConfig, migrateLegacyConfig,randomizeConfig,editTooth,clearToothOverride, buildMouth,exportGLB,exportTexturedGLB,exportPNG and bounded atlas cache helpers. Module normalizers/builders retain their own immutable APIs and ownership. INTEGRATION Root mounts handleGameAssetApi(request,env,ctx) before existing asset fallback. It returns null outside /api/game-assets/{mouth,eye}; namespace handlers own endpoints. Local HTTP serving must resolve the Three import map under /vendor and ES modules as JavaScript. Version 3.0.0 uses versioned app/module URLs and retains thin connector protection. The live HTTP schema describes current controls, wrappers and limits. ANATOMY REFERENCES The catalog attaches these supplied references to individual profiles: https://www.merckmanuals.com/home/multimedia/image/identifying-the-permanent-adult-teeth https://www.merckvetmanual.com/multimedia/table/dental-formulas-of-various-animal-species https://academic.oup.com/mspecies/article/50/967/119/5104903 https://www.nps.gov/yell/learn/yellowstone-grizzly-bear-facts.htm https://pmc.ncbi.nlm.nih.gov/articles/PMC7128658/ https://vetmed.tennessee.edu/wp-content/uploads/sites/4/AC2023_Proceedings.pdf https://nationalzoo.si.edu/animals/american-alligator https://animals.sandiegozoo.org/animals/python https://www.floridamuseum.ufl.edu/science/anatomy-of-a-burmese-python/ https://www.floridamuseum.ufl.edu/discover-fish/species-profiles/white-shark/ https://seaworld.org/animals/all-about/bottlenose-dolphin/characteristics/ https://nationalzoo.si.edu/animals/news/meet-our-cool-creep-aldabra-tortoises https://animals.sandiegozoo.org/animals/macaw https://home.nps.gov/yell/learn/nature/wolf.htm https://www.depts.ttu.edu/nsrl/mammals-of-texas-online-edition/Accounts_Artiodactyla/Odocoileus_virginianus.php Geometry detail controls source sampling. Polygon reduction at zero preserves the sampled mesh unless the shared safety budget requires a lower allowance; there is no extra automatic reduction from the detail slider.