Skip to main content

ParticleSkin

Struct ParticleSkin 

Source
pub struct ParticleSkin { /* private fields */ }
Expand description

A particle cloud’s attachment to a skeleton.

Built once from the cloud’s rest positions and reused for every frame after that. Holds one Bind per particle and nothing else: the rest positions stay with the caller, because the caller already has them and copying a hundred thousand of them twice would be the most expensive thing here.

Implementations§

Source§

impl ParticleSkin

Source

pub fn new() -> ParticleSkin

An empty skin.

Source

pub fn len(&self) -> usize

How many particles this skin covers.

Source

pub fn is_empty(&self) -> bool

Source

pub fn bind_of(&self, i: usize) -> Option<Bind>

The binding for one particle.

Source

pub fn from_binds(binds: Vec<Bind>) -> ParticleSkin

Build a skin from explicit bindings.

Source

pub fn bind_nearest( points: &[Vec3], skeleton: &Skeleton, falloff: f32, ) -> ParticleSkin

Attach every point to the bones nearest it.

points are in the skeleton’s bind-pose space. falloff is how far beyond the closest bone a second bone may be and still take a share of the particle, in the same units as the points: it is the width of the soft band around each joint, so a value near a limb’s thickness gives a joint that bends and a value of zero gives a rigid, shearing one.

Bones with no children still bind — a hand, a head, the end of a tail — using a short stub along the direction they came from, so the tip of a limb is not left orphaned to whatever happens to be nearest.

Source

pub fn bind_grouped( points: &[Vec3], skeleton: &Skeleton, falloff: f32, groups: &[u16], group_bones: &[Vec<BoneId>], ) -> ParticleSkin

Attach every point to the nearest of the bones it is allowed to use.

Proximity on its own is not enough for a cloud that was sculpted rather than modelled. A figure holding a two-handed sword has the blade up beside its head at rest, so the nearest bone to most of the weapon is the skull: bind by distance alone and swinging the arm leaves the sword behind while nodding drags it around. The caller knows which parts of the sculpt are the weapon, the cloak, the legs — that knowledge is what groups carries.

groups[i] names which entry of group_bones point i may bind to. A group that is empty, or an index past the end, falls back to the whole skeleton, so a caller that forgets to classify something still gets a particle that moves with the body rather than one left in mid-air.

Source

pub fn apply( &self, skeleton: &Skeleton, pose: &Pose, rest: &[Vec3], out: &mut Vec<Vec3>, )

Move a cloud into a pose.

rest are the same points the skin was bound from and out receives the posed positions; out is resized to match. Both may be the same length as the skin or shorter — a cloud that has grown since it was bound leaves its extra particles where they are rather than panicking, because a figure gaining matter mid-animation is a real thing that happens here and is not worth crashing over.

Linear blend skinning: the classic artefact is that a joint under heavy twist loses volume. At the scale one particle occupies that is not visible, and the springs downstream hide what is left of it.

Source

pub fn apply_with(&self, matrices: &[Mat4], rest: &[Vec3], out: &mut Vec<Vec3>)

The same, against matrices the caller already has.

Building the matrices walks the whole hierarchy and inverts a matrix per bone. That is nothing next to skinning a hundred thousand particles, but it is pure waste when positions and normals are both being skinned against the same pose — which is every frame, for every figure.

Source

pub fn skin_one(p: Vec3, bind: &Bind, matrices: &[Mat4]) -> Vec3

Where one point goes, given the skinning matrices for a pose.

Exposed because a caller often needs a single position — where a hand is, so an effect can be thrown from it — without posing the whole cloud.

Source

pub fn apply_normals( &self, skeleton: &Skeleton, pose: &Pose, rest: &[Vec3], out: &mut Vec<Vec3>, )

Turn a cloud’s surface normals to match a pose.

Lighting here is per particle against a real normal, so a normal left pointing where the bone used to be is an arm that bends while its shading stays behind — which reads as the limb going flat exactly when it moves. Uses the dominant bone rather than blending: a normal is a direction, blending two of them needs a renormalise, and across a joint the difference is a fraction of a degree on a particle a few pixels wide.

Source

pub fn apply_normals_with( &self, matrices: &[Mat4], rest: &[Vec3], out: &mut Vec<Vec3>, )

The same, against matrices the caller already has.

Source

pub fn skinning_matrices(skeleton: &Skeleton, pose: &Pose) -> Vec<Mat4>

The matrices that take a point from bind space to posed space.

One per bone, in bone-index order. Split out so a caller posing several clouds against the same skeleton computes them once.

Trait Implementations§

Source§

impl Clone for ParticleSkin

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ParticleSkin

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ParticleSkin

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

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

Convert &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)

Convert &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
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more