pub struct CharacterShape {
pub asset_id: AssetId,
pub target: Option<SkinnedMeshHandle>,
pub sliders: Vec<ShapeSlider>,
pub proportions: Vec<JointProportion>,
pub bake: bool,
}Expand description
Shape sliders and joint proportions applied to one SkinnedMesh.
Every characteristic of the shape is data on the mesh, not code: a slider drives one or two of the mesh’s morph targets, and a proportion scales or lengthens one joint of its skeleton. The deformation is static and sits under any Animation playing on the same mesh: clip morph tracks are added on top of the slider weights, and clip poses are re-proportioned every frame.
Sliders resolve to morph targets by name. A target named exactly
name is unipolar and receives the slider value clamped to [0, 1]. A
pair named name+ / name- is bipolar: a positive value drives name+,
a negative value drives name- by its magnitude. A slider with no matching
target is reported as a build warning and ignored.
Proportions resolve to joints by name. scale is uniform (the
skinning shaders transform normals with the plain joint matrix, so a
non-uniform scale would shade incorrectly) and propagates to the joint’s
descendants; length moves only the joint’s children along the bone, so a
longer thigh does not also stretch the shin. Proportions change the posed
skeleton, not the bind pose, so clips with translation tracks on the
affected joints fight them; keep such rigs rotation-only. When the mesh
declares a capsule, the capsule’s half-height follows the skeleton’s
height change and its radius follows the root joint’s scale.
target may name a CharacterModel as well as a
SkinnedMesh; the model’s emitted mesh is what the shape deforms.
Baking. With bake set, the build flattens the shape into its target:
the sliders’ deformation is applied to the vertices and the morph targets
dropped, the bind pose is rewritten through the proportions, the capsule
is resized, and this asset is consumed. The result is a plain SkinnedMesh
with no per-frame shape work, for characters that never change shape.
CharacterShape {
sliders: vec![ShapeSlider { name: "weight".into(), value: 0.5 }],
proportions: vec![JointProportion { joint: "spine".into(), scale: 1.1, length: 0.0 }],
..Default::default()
};Fields§
§asset_id: AssetIdAsset identity; injected via inject_name. Not part of args.
target: Option<SkinnedMeshHandle>The SkinnedMesh this shape deforms.
sliders: Vec<ShapeSlider>Named shape values, each resolved to the mesh’s morph targets.
proportions: Vec<JointProportion>Per-joint scale and length changes.
bake: boolFlatten the shape into the target mesh at build time and drop this asset, instead of deforming at runtime.
Implementations§
Source§impl CharacterShape
impl CharacterShape
Sourcepub fn resolve_sliders(&self, target_names: &[String]) -> ResolvedSliders
pub fn resolve_sliders(&self, target_names: &[String]) -> ResolvedSliders
Resolve sliders against target_names (the mesh’s morph targets in
target order). Several sliders naming the same target accumulate; the
result is clamped to [0, 1] per target.
Trait Implementations§
Source§impl Clone for CharacterShape
impl Clone for CharacterShape
Source§fn clone(&self) -> CharacterShape
fn clone(&self) -> CharacterShape
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Component for CharacterShape
impl Component for CharacterShape
Source§const NAME: &'static str = "CharacterShape"
const NAME: &'static str = "CharacterShape"
Source§fn inject_name(&mut self, id: AssetId)
fn inject_name(&mut self, id: AssetId)
Source§fn from_baked(bytes: &[u8]) -> Result<Self, CnResult>
fn from_baked(bytes: &[u8]) -> Result<Self, CnResult>
Source§fn inject_locator(&mut self, _locator: PayloadLocator)
fn inject_locator(&mut self, _locator: PayloadLocator)
Source§impl ComponentSlot for CharacterShape
impl ComponentSlot for CharacterShape
Source§const DISCRIMINANT: u8
const DISCRIMINANT: u8
ComponentId.