Social & Economy

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);