pub struct KfaSprite {
pub limbs: Vec<Sprite>,
pub hinges: Vec<Hinge>,
pub hinge_sort: Vec<usize>,
pub kfaval: Vec<i16>,
pub p: [f32; 3],
pub s: [f32; 3],
pub h: [f32; 3],
pub f: [f32; 3],
pub frmval: Vec<Vec<i16>>,
pub seq: Vec<Seq>,
pub kfatim: i32,
pub okfatim: i32,
}Expand description
One animated KFA sprite — bones + hinges + per-bone live animation values.
The host owns one of these per animated model, updates kfaval[]
over time, and passes it to roxlap-core’s draw_kfa_sprite each
frame. Construction is data-only (this crate); rendering is in
roxlap-core.
Fields§
§limbs: Vec<Sprite>One crate::sprite::Sprite per bone. Limb i’s
(s, h, f, p) is computed per frame by the renderer from
the parent’s transform + hinge math; the kv6 field holds
the bone’s kv6 mesh and never changes.
hinges: Vec<Hinge>Bone hierarchy. Mirror of voxlap’s kfatype.hinge[].
hinge_sort: Vec<usize>Topological sort of bone indices — populated once at construction, used by the renderer’s per-frame loop.
kfaval: Vec<i16>Per-bone animation value. Voxlap’s vx5.kfaval[]. Q15
angle (full circle = 65536). Host updates per frame.
p: [f32; 3]World-space anchor of the root limb’s hinge.p[0]. The
root limb is positioned so hinge.p[0] lands at this
point given the world basis below.
s: [f32; 3]World-space basis for the root limb. Mirror of
vx5sprite.{s, h, f} for the root.
h: [f32; 3]§f: [f32; 3]§frmval: Vec<Vec<i16>>Animation keyframe table — frmval[frame][hinge], Q15 angles.
Mirror of kfatype.frmval. Empty until Self::set_animation;
an empty table makes Self::animsprite a no-op so hosts that
poke kfaval directly keep working.
seq: Vec<Seq>Animation sequence — ordered (tim, frm) keyframes. Mirror of
kfatype.seq. tim is an absolute timestamp (ms); frm is a
frame index into frmval, or !target
(bitwise-NOT, hence negative) for a jump/loop to seq entry
target.
kfatim: i32Current animation time (ms) — voxlap’s vx5sprite.kfatim.
Advanced by Self::animsprite.
okfatim: i32Previous animation time (ms) — voxlap’s vx5sprite.okfatim,
used to cross-fade when the active sequence entry is itself a
blend marker (seq[z].frm < 0). Host sets it when switching
animations; Self::animsprite never writes it.
Implementations§
Source§impl KfaSprite
impl KfaSprite
Sourcepub fn new(
limbs: Vec<Sprite>,
hinges: Vec<Hinge>,
root_pos: [f32; 3],
) -> KfaSprite
pub fn new( limbs: Vec<Sprite>, hinges: Vec<Hinge>, root_pos: [f32; 3], ) -> KfaSprite
Build a KFA sprite from a list of (Sprite, Hinge) bones.
limbs.len() must equal hinges.len(). The first bone with
parent < 0 is the root.
kfaval is initialised to all zeros; the host should set
per-bone angles before / between render calls.
§Panics
Panics if limbs.len() != hinges.len().
Sourcepub fn set_animation(&mut self, frmval: Vec<Vec<i16>>, seq: Vec<Seq>)
pub fn set_animation(&mut self, frmval: Vec<Vec<i16>>, seq: Vec<Seq>)
Attach an animation curve — the frmval + seq tables parsed
from a Kfa. After this, Self::animsprite drives
kfaval from playback time instead of the host
poking individual bones.
Sourcepub fn animsprite(&mut self, ti: i32)
pub fn animsprite(&mut self, ti: i32)
Advance the animation by ti milliseconds and recompute every
child bone’s kfaval — a faithful port of
voxlap’s animsprite (voxlap5.c:11125).
Walks the sequence forward from the current
kfatim (honouring !target jump/loop
entries), then piecewise-linearly interpolates the two bracketing
keyframes per hinge. Interpolation is angle-wrap-aware: a free
hinge (vmin == vmax) takes the shortest path, a limited hinge
winds in its allowed direction. When the active entry is itself a
blend marker (seq[z].frm < 0), the pose cross-fades from the
okfatim-derived frame.
No-op when no animation curve is attached (see
Self::set_animation).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for KfaSprite
impl RefUnwindSafe for KfaSprite
impl Send for KfaSprite
impl Sync for KfaSprite
impl Unpin for KfaSprite
impl UnsafeUnpin for KfaSprite
impl UnwindSafe for KfaSprite
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more