# Characters prototype: three routes Open `index.html` through a static web server. `?anim=Punch` starts with that animation. The header fields (name, race, class, gear, mood, style) feed all three columns. ## How it works - **(a) 3D base**: Quaternius RobotExpressive (CC0, rigged, 14 animations, 3 face morph targets: Angry, Surprised, Sad). Animation dropdown, expression slider (mood picks the morph target), class tint (swaps the main material colour). Shown as a turntable, as a round VTT token (3/4 top-down render clipped in a 2D canvas with a class-coloured ring) and on a 5-ft grid square with the model scaled to 1.8 m. - **(b) AI portrait**: mocked. Shows the prompt built from the character data, the request it would send (OpenAI `gpt-image-1`, `images/generations`), rough costs and alternatives, and a placeholder. Nothing is called. - **(c) 3D pose to image model**: renders the posed model from the turntable's direction into four control images made in the browser: beauty render (img2img init), depth (MeshDepthMaterial), normals (MeshNormalMaterial) and edges (Sobel in JS on normals and depth). Shows the ComfyUI-style payload (SDXL or Flux + ControlNet depth + canny). The result is a placeholder; nothing is called. ## Good and bad - (a) Free, instant, animatable, consistent and scalable to any number of NPCs; tokens and grid views come for free. But it looks like a game asset, and variety needs a modular kit (swappable heads, armour, weapons on hand bones). The robot here is a stand-in; a real version needs humanoid base meshes per race/size (Quaternius has CC0 modular fantasy characters). - (b) By far the best-looking portraits for the least work. Weak on consistency (the same character drifts between images) and every image costs money and goes to a third party. - (c) Combines both: the 3D pose fixes composition, scale and framing; the image model supplies the art. Needs an open model with ControlNet (own GPU, rented GPU, or a hosted ComfyUI/Replicate workflow) and the most plumbing. gpt-image-1 can take the render only as a loose reference image. ## What it costs to make real (roughly; verify prices) - (a) Developer time only; CC0 assets. - (b) gpt-image-1 1024x1024: about $0.01 / $0.04 / $0.17 per image at low / medium / high quality (from memory, check the current price list). Hosted Flux/SDXL: roughly $0.003-0.03 per image. Local: a GPU with 8-24 GB VRAM, no per-image fee; this server has none. - (c) Same per-image cost as hosted SDXL/Flux plus GPU time for ControlNet; or a rented GPU at roughly $0.5-2 an hour. - AI 3D characters (Meshy, Tripo): an option for unique 3D models from a portrait; pricing and licence unknown, check first. Auto-rigging is still hit and miss. ## Licensing RobotExpressive: CC0 (see `assets/quaternius/README.md`). Image model outputs: under the provider's terms (OpenAI assigns output rights to the user; check others, and check model licences such as Flux dev's non-commercial terms for self-hosting). The ProFantasy Token Treasury tokens Jasper bought could cover 2D tokens right away, but whether its licence allows use by an AI tool and by other users of the app is unconfirmed: check before relying on it. ## Fit in the project A character row gets `portrait_url` (AI image, made once and on request), `token_url` (cropped from the portrait, or a 3D render, or a Token Treasury token) and optionally `model: { source, ref, params: { tint, parts, scale } }` for 3D scenes. Recommendation: start with (b) for portraits plus tokens cropped from them, with the first portrait kept as the reference for consistency; add (a) only when the map or combat view goes 3D, and (c) only if many consistent poses per character turn out to be wanted.