Skeleton¶
SimVX provides skeletal animation support through the Bone dataclass and Skeleton class. Together they define a bone hierarchy and compute joint matrices for GPU vertex skinning.
Bone¶
A Bone represents a single bone in the hierarchy:
Field |
Type |
Description |
|---|---|---|
|
|
Human-readable bone name |
|
|
Index of parent bone (-1 for root) |
|
|
Transforms from mesh space to bone-local space |
|
|
Default local-space transform relative to parent |
Skeleton¶
Skeleton holds an ordered list of bones and computes the final joint matrices used by the GPU skinning shader.
Creating a Skeleton¶
Bones must be ordered so that every parent appears before its children:
import numpy as np
from simvx.core import Bone, Skeleton
# Build a simple arm: root -> upper_arm -> forearm -> hand
bones = [
Bone(name="root", parent_index=-1),
Bone(name="upper_arm", parent_index=0,
local_transform=translate(0, 2, 0)),
Bone(name="forearm", parent_index=1,
local_transform=translate(0, 1.5, 0)),
Bone(name="hand", parent_index=2,
local_transform=translate(0, 1.0, 0)),
]
skeleton = Skeleton(bones)
print(skeleton.bone_count) # 4
Computing a Pose¶
Call compute_pose() to walk the hierarchy and produce joint matrices. Optionally override individual bone transforms:
# Default pose (uses each bone's local_transform)
skeleton.compute_pose()
# Animated pose — override forearm rotation
import math
animated = {
2: rotate((1, 0, 0), math.radians(45)) @ translate((0, 1.5, 0)), # forearm rotated 45 deg
}
skeleton.compute_pose(bone_transforms=animated)
Joint Matrices¶
After compute_pose(), the joint_matrices property returns a (bone_count, 4, 4) NumPy array. Each matrix is world_transform @ inverse_bind_matrix – ready to upload to an SSBO.
matrices = skeleton.joint_matrices # shape (4, 4, 4) for 4 bones
The vertex shader applies skinning by blending up to 4 joint matrices per vertex using bone weights:
vec4 skinned = vec4(0.0);
for (int i = 0; i < 4; i++) {
skinned += joint_matrices[bone_ids[i]] * vec4(position, 1.0) * bone_weights[i];
}
Finding Bones¶
Look up a bone index by name:
idx = skeleton.find_bone("forearm") # 2
idx = skeleton.find_bone("missing") # -1
API Reference¶
See simvx.core.skeleton for the complete skeleton API.