aether-avatar
Avatar system with skeletal animation, IK, and GPU skinning
The aether-avatar crate provides the full avatar pipeline for Aether, including skeletal animation, FABRIK inverse kinematics, blend shapes, lip-sync, level-of-detail, GPU skinning, and performance rating.
Overview
Avatars are the visual representation of players in virtual worlds. This crate handles every stage from tracking data to final rendered mesh:
- Skeletal animation with a state machine that blends between clips.
- FABRIK IK solver for mapping VR tracking points to full-body poses.
- Blend shapes for facial expressions, driven by GPU compute or CPU fallback.
- Lip-sync that maps audio input to viseme weights for mouth animation.
- LOD system with distance-based tier selection for rendering efficiency.
- GPU skinning with bone matrix palette upload.
- Performance rating that classifies avatars by polygon count, material count, and bone count.
Key Types
Skeleton
Defines the bone hierarchy for an avatar.
use aether_avatar::{Skeleton, Bone, IkTarget};
let skeleton = Skeleton::new(vec![
Bone { name: "hips".into(), parent: None },
Bone { name: "spine".into(), parent: Some(0) },
Bone { name: "head".into(), parent: Some(1) },
]);
FabrikSolver
Solves inverse kinematics using the FABRIK algorithm, mapping VR tracking points to joint rotations.
use aether_avatar::{FabrikSolver, FabrikConfig, FabrikResult};
let solver = FabrikSolver::new(FabrikConfig {
max_iterations: 10,
tolerance: 0.001,
});
let result: FabrikResult = solver.solve(&skeleton, &tracking_targets);
AnimationStateMachine
Manages animation state transitions with blending between clips.
use aether_avatar::{AnimationStateMachine, AnimationOutput};
let mut state_machine = AnimationStateMachine::new();
state_machine.set_state("walk");
let output: AnimationOutput = state_machine.evaluate(dt);
BlendShapeSet
A collection of blend shape targets for facial expression and body deformation.
use aether_avatar::{BlendShapeSet, BlendShapeTarget, BlendShapeWeights};
let mut weights = BlendShapeWeights::new(50); // 50 blend shapes
weights.set("smile", 0.8);
weights.set("blink_left", 1.0);
LipSyncConfig
Configures audio-driven lip-sync that maps microphone input to viseme blend shapes.
use aether_avatar::{LipSyncConfig, LipSyncFrame, VisemeCurve};
let config = LipSyncConfig {
smoothing: 0.3,
sensitivity: 1.0,
};
AvatarPerformanceRating
Classifies avatars into performance buckets based on mesh complexity.
use aether_avatar::{classify_avatar, AvatarMeshStats, AvatarRatingBucket};
let stats = AvatarMeshStats {
polygon_count: 15000,
material_count: 3,
bone_count: 75,
blend_shape_count: 50,
};
let rating = classify_avatar(&stats);
SkinningDispatch
Dispatches GPU skinning workloads with configurable method (GPU compute or vertex shader).
use aether_avatar::{SkinningDispatch, GpuSkinningConfig, SkinningMethod};
let config = GpuSkinningConfig {
method: SkinningMethod::ComputeShader,
max_bones: 128,
};
Usage Examples
Full-Body IK from VR Tracking
use aether_avatar::{
solve_six_point, TrackingFrame, TrackingSource, FullBodyPose,
BodyProportions, IkResult,
};
let tracking = TrackingFrame {
head: head_pose,
left_hand: left_controller_pose,
right_hand: right_controller_pose,
source: TrackingSource::SixPoint,
};
let proportions = BodyProportions::from_height(1.75);
let pose: IkResult = solve_six_point(&tracking, &proportions);
LOD Selection
use aether_avatar::{select_lod_tier, AvatarLodConfig, AvatarLodTier};
let config = AvatarLodConfig::default();
let tier: AvatarLodTier = select_lod_tier(distance_to_camera, &config);