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.
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:
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.