animsmith-core 0.4.2

Engine-agnostic data model, sampling, measurements, and checks for the animsmith animation-clip linter
Documentation

animsmith-core

Pre-1.0: Breaking changes are expected between minor releases. Pin dependency versions and review the release notes before upgrading.

Overview

animsmith-core is animsmith's engine-agnostic library crate. This README is a compact crates.io and repository index; the crate-root rustdoc owns the embedding flow, API status, extension points, and panic/error contracts.

Raw Source Facts and Dependency Closure

The core crate owns a bounded, format-neutral V1 vocabulary for importer- sensitive source evidence. Format crates can return an immutable LoadedSource that binds those facts and a bounded dependency closure to the exact primary bytes while lending read-only access to the normalized Document; into_document() deliberately discards both sidecars. The facts reuse the existing SourceSkeletonAssets projection instead of copying source node/skin authority. They describe AnimSmith loader evidence and availability, not engine support policy, target-importer policy, or a scale operation's private proof ledger. Complete, partial, and unavailable row coverage is explicit; a partial prefix proves presence only. V1 limits projection to 65,536 enumerable rows, 4,096 clips/takes, 4,096 resource declarations, 4,096 bytes per retained source string, 8 MiB of retained source strings, and traversal depth 128. Budget N+1 preserves the deterministic prefix and marks the affected set partial without turning a successful legacy load into an error.

DependencyClosureV1 maps that raw declaration prefix to the primary input, safe normalized external keys with exact byte identities, or typed refusal/unavailability. Each reference also carries its kind-derived, format-neutral loader-essential, nonessential, or target-only purpose without making a target-engine support claim. Only complete raw coverage with an identity for every declaration produces a closure identity. Core performs no filesystem I/O; format loaders capture sidecar bytes once from a trusted root while loading, never from the process working directory. V1 bounds capture to 4,096 declarations, 1,024 distinct external keys, 4,096 bytes and 128 components per key, 8 MiB aggregate normalization input, 64 MiB per external resource, and 256 MiB in aggregate. Unsafe spellings and host paths are not retained.

Shared runtime-node policy

Config::runtime_nodes is the engine-neutral selector authority for attachments, sockets, IK targets, and other runtime-facing source nodes. rest-world-scale consumes it; its older per-check node_selectors field is a compatibility alias and cannot be declared at the same time. An absent field or empty list means no policy. This added public field is an intentional pre-1.0 struct-literal break: exhaustive Config literals must add it or use ..Config::default().

Install

[dependencies]
animsmith-core = "0.4"
animsmith-gltf = "0.4"

Feature Flags

  • fixtures (off by default) — exposes animsmith_core::fixtures, the analytic walk-cycle and scale-reference builders shared with animsmith's own tests and example-asset generator. Adds no dependency: the walk-cycle builder takes its sine as a parameter, while the scale-reference builder is test support rather than a production rewrite path. Internal to the animsmith workspace and not part of the crate's stable API; downstream code should not depend on it.

The workspace MSRV is Rust 1.88.

Additional Skin-Influence Evidence

Primitive::additional_influence_sets carries independent presence metadata for secondary glTF JOINTS_n and WEIGHTS_n attributes. The measurement contract aggregates that metadata per source mesh and retains whether either side was unpaired on an individual primitive, so complementary declarations on different primitives are not reported as a clean pair. It intentionally does not retain secondary per-vertex payloads or change the primary four-influence skinning semantics.

Material and Image Measurement Evidence

AssetMeasurements records source-order material definitions, semantic texture bindings, texture-to-image identities, and bounded image inspection metadata when a loader supplies a source-resource sidecar. Its explicit material_resource_coverage distinguishes complete glTF/GLB evidence from an unavailable source-resource view in another loader. For glTF/GLB, complete is scoped to the documented core slots base_color, normal, metallic_roughness, occlusion, and emissive; extension-defined texture slots are not implied. Image records preserve declared MIME separately from a detected container and decoded dimensions, channel count, and color type; unavailable images instead carry a reason. This is descriptive source evidence, not an image acceptance, repair, resize, transcode, writer-preservation, conversion, or material-recipe policy.

Mesh-definition evidence also includes optional mesh-local finite-position bounds and an arithmetic vertex centroid. The centroid is descriptive source geometry evidence, not a center of mass, placement policy, or repaired pivot.

Skeleton Rest-Pose Evidence

When a loader supplies source skeleton identity, AssetMeasurements also records source-order nodes, per-skin joint lists and inverse-bind declaration state, and finite derived bind-domain matrices with typed unavailability. glTF retains exact accessor values; FBX records documented ufbx-normalized cluster bind projections and does not claim raw FBX payload preservation. Node-local TRS/matrix data, rest-world transforms, and mesh-local bind data remain distinct coordinate domains. This is generic evidence only: embedders choose required joints, comparison tolerances, canonical roots, and any retargeting or delivery policy.

Static Mesh Transform Baking

Embedders can opt into animsmith_core::bake_static_mesh_transforms to bake accumulated static rest transforms into mesh-local positions and inverse-transpose normalized normals. The operation returns a canonical identity-root document plus deterministic per-instance evidence. It validates the input fields the static operation consumes before constructing output, while raw source-projection evidence that it discards is intentionally irrelevant. It fails closed for animation, skinning, ambiguous mesh instancing, malformed data, reflections, and ill-conditioned transforms. Model-supported material factors and embedded base-color, normal, metallic-roughness, and occlusion textures are preserved.

Character Assembly Helpers

animsmith_core::assembly provides exact-name clip remapping onto an authoritative skeleton, named-bone track stripping, optional rest-pose channel completion for all or an explicit base-bone selection, deterministic quaternion hemisphere cleanup, and endpoint-key removal. It also plans and transactionally applies exact-name node-subtree projection while refusing live animation, mesh, and skin references. It rejects ambiguous or missing referenced names rather than guessing at a retargeting relationship. For a final-pose hold, use the existing animsmith_core::transform::hold_extend helper.

For recipe-v4 rest/bind integration, animsmith_core::scale also builds and compares versioned assembly basis records before remapping. Those records bind named parent topology, target paths, rests and orientations, helper layout, coordinate convention, effective target factors, explicit operation selectors, and factor. The same compiled plan supplies the pre-remap translation and CUBICSPLINE tangent factors; assembly does not own a second scale algorithm.

Constant-Track Pruning

animsmith_core::transform::prune_constant_tracks is an opt-in mechanical edit for redundant multi-key TRS tracks. It shares the built-in constant-track classifier, tests cumulative removals on the original clip's sample grid, and returns authored-order removed and retained records. Callers provide any bone IDs whose authored channels must remain; the function also refuses changes that alter sampled local TRS or model-space position/rotation, cannot be sampled safely, or would leave the clip without a writable track.

Skinned Bind-Pose Canonicalization

animsmith_core::canonicalize_skinned_bind_pose prepares an unanimated, skinned character base for a right-handed, Y-up metre delivery space. The caller declares the source-to-target affine coordinate transform; the operation rejects reflections, shear, non-uniform unit conversion, malformed skin data, and inverse binds that disagree with the input rest pose. It emits one identity scene root, private bind-world mesh copies with inverse-transpose normalized normals, remapped joints, and regenerated inverse bind matrices. Optional ground-and-centre placement uses the complete converted bind-pose bounds in a deterministic source-node order.

Scale Planning and Proof

animsmith_core::scale is the format-neutral boundary for two explicitly selected operations: whole-document linear-unit conversion and rest/bind hierarchy reparameterization. plan_scale compiles one immutable typed ledger from a validated Document and format capability facts. A format frontend rewrites its exact source representation, reloads those bytes, wraps the result with ScaleCandidate::from_document, and calls prove_scale, which derives its expectations independently from the writer.

Core deliberately exposes no production candidate builder and performs no file I/O or publication. The analytic builder under the non-default fixtures feature is test/calibration support only. See the scale workflow, embedding guide, and Appendix D of the workspace design.

More Details

License

Licensed under either the MIT license or the Apache License, Version 2.0, at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in animsmith by you is licensed as MIT OR Apache-2.0, without any additional terms or conditions.