# Optional authored Person

`objects/people/authored/index.js` supplies `AuthoredPerson` and the asynchronous
`loadAuthoredAssets` loader. The regular `objects/people/index.js` entry keeps the
procedural `Person` default. Import the authored entry explicitly; it extends the
existing Person pose/movement interface and uses a separate authored visual rig.

```js
import * as api from './engine/index.js';
import {AuthoredPerson, loadAuthoredAssets} from './objects/people/authored/index.js';

const assets = await loadAuthoredAssets({signal}); // Local files; preload once.
const person = new AuthoredPerson(api, {
  assets, ageGroup:'adult', female:false, bodyType:'regular',
  height:1.76, clothing:'beach', rashguard:true, detail:0
});
scene.add(person.root);
person.setPose('wave').update(dt, time);
```

Construction does not require the DOM. It requires the injected `THREE`, `ObjectState`, `OBJECT_PROTOCOL` and `random` services; actual drawing requires an engine renderer. The loader requires the standard `fetch` and `URL` globals.

The loader fetches explicit files beneath `authored/assets`, plus the target
filenames listed in `authored/assets/targets/index.json`. It makes no external
network request and uses no runtime AI. Serve the copied engine and object folder
as local ES modules. `baseURL` can override the local asset directory; `signal`
cancels fetching. `includeTargets:false` loads the neutral source data for
lower-level inspection; normal AuthoredPerson constructors require the matched
shape targets. Preloaded assets may be shared by many synchronous constructors.

## Interface and shape controls

AuthoredPerson retains the common object properties, transforms, `update`,
`getBounds`, `serialize`, `restore`, and `dispose`, and Person's `setPose`,
`walkTo`, `moveTo`, `stop`, `setGaze`, `lookAt`, `getHandPosition`, `reach`,
`setHeight`, `setBodyType`, `setAppearance`, `setExpression`, `setHair`, and `blink`.
Wrist queries and reach operate on the rendered source rig. Bounds include the
current authored skin pose and head accessories, excluding the hidden bone driver.

Additional options/methods:

| Name | Meaning |
| --- | --- |
| `assets` | Required result of `loadAuthoredAssets`; omitted from serialization |
| `detail` / constructor `subdivisions` | 0 retains the authored control mesh; 1 applies one Catmull–Clark level |
| `setDetail(0\|1)` | Rebuilds visual geometry at the requested detail, retaining pose and transforms |
| `getStats()` | Total visible geometry/mesh counts, full influence counts and texture bytes, source shape selection, and shared-palette counters |
| `faceShadows` | Defaults to false at detail0 and true at detail1; eyes/teeth/tongue remain visible and receive shadows, while this controls their extra shadow casts |
| `swimwear` | Beach clothing: `bikini`, `onePiece`, `rashguard`, or `trunks`. Default adult women use bikini, adult men use trunks; explicit rashguard remains supported. Children always retain rashguard plus shorts. |
| `trunkLength` | Fraction of source hip-to-knee distance, `.25`–`.70`; default `.55`. Affects shorts/trunks. |
| `eyeColor` | Optional Three.js color input for the iris |
| `setHairColor(value)` | Accepts a six-digit CSS hex color or RGB integer, rebuilds owned appearance so hair and eyebrows match, and retains style, pose, body/clothing settings and transforms. Serialized as `properties.hair`. |
| `appliedPose` | Last actual pose applied, including temporary walk/run overrides from movement |
| `geometrySource:'authored'` | Serialized selector for consumers choosing the optional constructor |

Adults support the existing slim/regular/bigger controls using matched source
weight targets. Source weight is `clamp(.5 + (build - 1) * .7, .05, .95)`, with
linear interpolation from the verified zero-delta regular target toward the
matching min/max weight target. The default build values are `.77`, `1`, `1.38`.
The child driver's build values are normalized by its existing `.8` age factor.
Male/female adult and child baselines are separate source targets. The two target
families are additive; full male and female baselines are never stacked.

Child regular shapes are available. Matching child slim/bigger targets could not
be retrieved; those requests throw a missing-source-target error rather than
applying adult deltas to a child. The inspection fixture disables those choices.
The retained source filename category is part of provenance, not an inferred
identity or a runtime demographic classifier. Skin/hair colors remain independent
appearance controls.

Reconstruct saved objects with the preloaded bundle:

```js
const saved = person.serialize();
const restored = new AuthoredPerson(api, {assets, ...saved.properties});
restored.restore(saved);
```

The internal `actor` remains the existing skeletal pose driver; its unused face,
mesh, materials and skin-palette resources are released. The displayed visual
controller is `person.authored`. Applications should use the public wrist/bounds
methods rather than treating the internal driver mesh as the rendered body.

## Source geometry, rig and deformation

The package includes verified CC0 graphical data, not MakeHuman application code.
The OBJ, skeleton, weights, face pose units and shape targets are local assets with
embedded license headers and per-file retrieval provenance. See
`docs/ANATOMY_RIG_DATA.md` and `docs/licenses/PEOPLE_AUTHORED_ASSETS.md` for source
records and retrieval limitations.

The independent OBJ importer preserves UV seams and original vertex correspondence.
Subdivision retains sparse original-vertex stencils, applying the same operation
to geometry and skin weights. `originalIndex` identifies retained control vertices;
generated vertices use -1 and their full `geometry.userData.sourceStencils` mapping.
The source joints are averages of declared original-vertex sets. Bone parents and
roll planes define 163 deterministic rest frames; no anatomical anchors are guessed.

The authored rest pose differs from the procedural driver. Retargeting aligns
source upper-arm, forearm, hand, thigh and shin directions to the corresponding
driver rest directions, then applies current driver rotations through source rest
frames. Existing API left/right behavior is preserved explicitly: its negative-X
left side maps to the source's `.R` bones, and positive-X right to `.L`.

Source weights are normalized. All influences are retained in a per-mesh vertex
texture; the four-weight compatibility attributes are not the rendered weighting.
Subdivision/garment clipping can produce 14 influences per vertex. Color, depth,
distance shadows and CPU skin queries use the full list. Dual quaternions handle
rigid/uniform-scale transforms; negative/nonuniform scale selects full-influence
matrix skinning. Morph/data changes happen before binding and preserve source
indices.

One reference-counted bone palette is shared by all meshes of an actor. Exact bone
world-matrix and inverse-bind comparisons skip unchanged decompositions and uploads.
`getStats().palette` reports checks, refreshes, decompositions, texture version and
live references. Grounding retains its previous offset and avoids resetting then
reapplying the same translation each frame. It keeps every selected sole vertex,
groups identical full influence lists, and evaluates support Y directly from each
group transform. This avoids redundant quaternion blending and cancelling
inverse-bind/world transformations. Palette checks run once at the end of the
owned visual-tree update; standalone mesh updates remain supported. The visual tree is updated after pose
retargeting rather than while the hidden driver is still being posed.

## Clothing, face and resources

Beach shirts/shorts are cut from the source clothing helper. Waist and cuffs use
source spinal/arm/leg landmarks, and clipped vertices interpolate all skin weights
and source stencils. Arm-weighted helper faces are excluded from shorts, preventing
the wrist fragments found during inspection. Adult shirtless variants retain the
authored body surface; children and female variants retain top coverage. Casual
mode currently uses the full source clothing helper.

Conservative per-mesh pose spheres enable frustum culling; exact posed bounding
boxes are still computed on request. The source skull, nose, lips, ears, sockets and hands remain intact. Source BVH pose
units drive brow, cheek, eyelid, mouth and jaw motion. The BVH's inferred Z-up basis
is converted as `(x,y,z) → (x,z,-y)` and rotations are conjugated through source rest
frames; fitted reference-shape offsets are not applied. Happy/surprised/focused/
talking controls combine these named pose units. The palette also captures the
resulting facial bone changes. Initial expressions are applied even when animation
is paused, and automatic blink timing varies by seed. Iris surfaces, pupils, oral backing and local material
variation are package additions. Hair/accessories fit the source head independently.

Each visual instance owns geometry, influence textures, materials and accessories;
shared palette ownership ends with its last mesh. Disposal is idempotent. Failed
hair creation disposes the already-created authored body. Preloaded source arrays
are immutable shared data and are not per-instance GPU resources.

## Verification status

`tests/authored-person.html` is the permanent close inspection/API fixture. It
provides adult/child variants, build, detail, pose, expression, gaze, reach,
locomotion, restoration and resource checks. The original procedural fixture remains
available separately. Visual checks and numeric checks are reported separately.

The initial source/adapter checks covered eight age/sex/build variants and 56 poses
with finite bounds. Reachable targets across adult/child variants, both hands and
four poses agreed with rendered wrist joints within `8e-15 m`. Targets beyond arm
length are clamped. Root's actual 16-person beach run measured maximum volleyball
wrist error `2.8623e-13 m` and minimum terrain gap `0.007998 m` over 80 samples.

The full-scene validation/profile work is recorded separately from object-only
checks. An earlier combined object/renderer/shell profile measured 30.70 ms median
CPU (39.50 ms p95) and 7.309 ms median GPU (12.320 ms p95) across 120 samples at
High quality, CSS 2048 × 919, drawing buffer 2560 × 1148. It retained 693 render
calls and 2,419,596 rendered triangles across passes. The initial authored run was
116.10 ms CPU median; that improvement combined palette and pose work,
culling, reduced interior-face shadow casting, render-pass matrix reuse, close
shadow coverage and shell scheduling. It is not an isolated object benchmark.

The shell updates nearby actors at full rate and staggers distant/offscreen
animation at 18/6 Hz. Explicit moving targets and zero-delta inspections force
updates. The object API itself always applies the requested update; this policy
belongs to scene choreography. These timings describe the measured desktop, not a
device-independent frame-rate guarantee.

Permanent `tests/authored-person.test.mjs` passes 43 checks covering movement,
actual wrist targets, source expressions/gaze/blinking, appearance/detail rebuilds,
serialization, rejected inputs, resource ownership, support projection, culling
bounds and palette refresh behavior. All 51 tracked GPU resources disposed exactly
once. Eighty support comparisons across detail/age/pose/uniform/nonuniform/mirrored
transforms agree with the full skinning path within `1.61e-15 m`. Posed bounding-box
corners remain inside their conservative spheres (maximum radius ratio 0.626).
An additional full-vertex audit checked 7,880,760 pose/vertex combinations.

After a translated high-detail child is constructed, Float32 grounding may make
one additional initialization refinement (measured maximum `1.11e-7 m`). The
regression explicitly checks convergence, then requires zero further palette
refreshes/decompositions for unchanged poses. External root, bone and inverse-bind
edits still refresh the shared palette. The reclined-to-walking regression checks
grounding against `appliedPose`, preserving normal movement overrides.

Final close browser checks covered adult male/female builds, both child baselines,
clothed and shirtless shoulder poses, moving wave/crouch/volley, front/side/three-
quarter views, hair, expressions, actual wrist alignment, restoration and cleanup.
The browser reported 51 tracked resources and 51 disposal events, with no runtime
or shader warnings/errors. The temporary inspection tab was closed.

Remaining close-up limits are explicit: teeth currently use the core helper proxy
geometry, which can appear as a flat wedge when the mouth opens. The mouth lining
and tongue are present; hiding the teeth in the inspection fixture distinguishes
that proxy from a background hole. Skin color/roughness and hair are generated; no
verified photographic skin UV atlas is included. Child slim/bigger targets remain
unavailable, and casual clothing currently uses the full helper suit.


## Frozen release verification: v020-final3

The frozen `tests/authored-beach.html?revision=v020-final3&close=1` run passed all
seven integration checks on 2026-09-07. All 16 authored participants and seven
inspection locations rendered; 80 pose/support samples remained finite. Maximum
volleyball wrist error was `2.71813e-13 m`, minimum terrain gap was `0.007997995 m`,
and the offscreen walking target error was `2.27374e-13 m`. Repeated scene
replacement returned to identical retained GPU counts in both cycles: one geometry
and seven textures. This closes the previous full-scene cleanup regression with
the production shadow-material lifecycle guard. No runtime or shader errors were
reported.

The subsequent non-instrumented profile used High quality, CSS 2048 × 919, buffer
2560 × 1148, shadow extents 18/85/320, 30 warm-up frames and 120 measured frames.
CPU time was **46.00 ms median / 62.20 ms p95**. GPU time was **8.9845 ms median /
61.7370 ms p95**, with all 120 timer-query samples valid. The scene submitted 693
render calls and 2,419,596 triangles across passes; initial load took 12.207 seconds.
This frozen run was slower and more variable than the earlier engineering profile;
the cause was not established. The current measurement is retained rather than
substituting the earlier faster result.

Evidence: integration result
and profile. These records
retain all check details and aggregate measurements, omitting repeated per-person
statistics. No runtime or fixture code was changed for this verification.

## Final rendering optimization

The later stable-shadow-material engine revision removes repeated shared shader-variant work. In the same 16-person High-quality court fixture it measured 7.10 ms median CPU and 6.05 ms median GPU, with unchanged 693 draws / 2,419,596 rendered triangles. See profile. The slower final3 measurement above is retained as history, not the latest result. The packaged final4 workshop was also directly inspected with authored people and close shadows; behavior and lifecycle suites pass.


## Beach poses, swimwear and towel contact

`kneel` replaces the squat in the two sandcastle-building roles. Source joints,
clipped garment weights and the existing wrist IK remain unchanged. Adult women
in the choreography wear one-piece swimsuits or broad bandeau bikinis; children
retain rashguards. Men's trunks vary in length and color. Swimwear is clipped
from the existing source garment using breast/rib/hip anchors. Arm boundaries
interpolate skin influence values rather than deleting entire triangles.

`sunbatheGround` and `prone` use a support sampler over the whole deformed body,
with resting shoulders/elbows, hips/legs and neck angles. This matters because a
low hand can otherwise set the global minimum and lift the torso. The corrected
counter-bent elbows preserve back/hip or abdomen support. Ground support is in the
person root's local plane; the application aligns both towels and actors to the
local sand normal. The poses do not simulate soft tissue or towel compression.
Small spaces beneath the lumbar curve or upper chest remain anatomically expected.

The beach adds ten static adults on separate inland towels: seven face-up and
three face-down. There are now 26 people, including the existing four children.
The added group skips per-frame rig animation; paused inspection refreshes it,
and explicit walking targets still advance. `staticSunbathers` is returned by
`createBeachActivities`, and `drySunbathers` supplies its inspection view.

Focused verification for this change:

- `tests/beach-resting.test.mjs`: 25 assertions covering grounded poses on a
  sloping plane, garment selection and full normalized weights, reachable kneeling
  wrist, serialization/disposal, and dry production-terrain placement. The lowest
  sampled towel-area corner is 1.7706 metres above water.
- `tests/beach-resting-contact.test.mjs`: 60 contact assertions across male/female
  slim, regular and bigger adults, in both lying poses. Supine back/hips, hands,
  feet and head, or prone abdomen, forearms, hands, feet and head each have a
  support-region minimum within 25 mm of the support plane. This tests multiple
  regions, not just the single lowest body vertex.
- `tests/beach-resting.html`: 8 Chrome checks with all 26 actors. The visible
  low-angle and three-quarter views confirmed the correction to floating torso
  poses, clothing coverage, kneeling support and separate towel placement.
  Animated sand play and existing volleyball contacts were inspected. No browser
  warnings or errors were observed; the temporary tab was closed.

Exact results are in `docs/verification/beach-resting-source.json`,
`beach-resting-contact.json`, and `beach-resting-browser.json`. This was a bounded
pose/clothing pass; accepted body, face and hair geometry was not redesigned,
and no broad performance profile was repeated.
