tiny.rig.JointClip
Defined in tiny.rig.
API (14)
Actions
Public operations.
check: Checks every channel against the key slices and the joint and slot counts it will be sampled into.period: Seconds from the first key to the first key again, for a loop.position: The keys on either side oftime.sample: The local transforms attime:restwhere no channel applies.selectParts: Each part channel's choice attime, written to its slot.span: Seconds from the first key to the last.
Fields and members
Public fields and members.
Source
Source: fun/rig/src/clip.zig:71
zig
pub const JointClip = struct { /// Keys per second. rate: f32, /// Keys in every channel that is not constant. frames: u32, interpolation: Interpolation = .linear, channels: []const Channel, rotations: []const Quat = &.{}, translations: []const Vec3 = &.{}, part_channels: []const PartChannel = &.{}, choices: []const u8 = &.{}, /// Checks every channel against the key slices and the joint and slot /// counts it will be sampled into. Sampling assumes a clip that passed. pub fn check(clip: JointClip, joint_count: usize, slot_count: usize) Error!void { if (!std.math.isFinite(clip.rate) or !(clip.rate > 0)) return error.InvalidRate; if (clip.frames == 0) return error.InvalidFrames; for (clip.channels) |channel| { if (channel.joint >= joint_count) return error.InvalidTarget; const keys = switch (channel.target) { .rotation => clip.rotations.len, .translation => clip.translations.len, }; try checkKeys(clip.frames, channel.first, channel.count, keys); } for (clip.part_channels) |channel| { if (channel.slot >= slot_count) return error.InvalidTarget; try checkKeys(clip.frames, channel.first, channel.count, clip.choices.len); } } /// Seconds from the first key to the first key again, for a loop. pub fn period(clip: JointClip) f64 { return @as(f64, @floatFromInt(clip.frames)) / clip.rate; } /// Seconds from the first key to the last. pub fn span(clip: JointClip) f64 { return @as(f64, @floatFromInt(clip.frames - 1)) / clip.rate; } /// The keys on either side of `time`. A time within /// `time.boundary_tolerance` of a key counts as on it, so sampling at /// `k / rate` returns key `k` exactly. pub fn position(clip: JointClip, time: f64, loop: bool) Position { assert(clip.frames > 0); assert(std.math.isFinite(time)); const frames: f64 = @floatFromInt(clip.frames); var key = time * clip.rate; var base: f64 = undefined; if (loop) { key = @mod(key, frames); base = time_position.floorSnapped(key); if (base >= frames) { base -= frames; key -= frames; } } else { key = std.math.clamp(key, 0, frames - 1); base = time_position.floorSnapped(key); } const lower: u32 = @intFromFloat(base); assert(lower < clip.frames); const upper = if (lower + 1 < clip.frames) lower + 1 else if (loop) 0 else lower; const fraction: f32 = switch (clip.interpolation) { .step => 0, .linear => @floatCast(std.math.clamp(key - base, 0, 1)), }; return .{ .lower = lower, .upper = upper, .fraction = @min(fraction, 1 - std.math.floatEps(f32)), }; } /// The local transforms at `time`: `rest` where no channel applies. pub fn sample( clip: JointClip, time: f64, loop: bool, rest: []const Transform, local: []Transform, ) void { assert(local.len == rest.len); @memcpy(local, rest); const at = clip.position(time, loop); for (clip.channels) |channel| { assert(channel.joint < local.len); const lower = channel.first + if (channel.count == 1) 0 else at.lower; const upper = channel.first + if (channel.count == 1) 0 else at.upper; const joint = &local[channel.joint]; switch (channel.target) { .rotation => joint.rotation = rotationAt( clip.rotations[lower], clip.rotations[upper], at.fraction, ), .translation => joint.translation = translationAt( clip.translations[lower], clip.translations[upper], at.fraction, ), } } } /// Each part channel's choice at `time`, written to its slot. Slots /// without a channel keep what `choices` held. pub fn selectParts(clip: JointClip, time: f64, loop: bool, choices: []u8) void { const at = clip.position(time, loop); for (clip.part_channels) |channel| { assert(channel.slot < choices.len); const key = channel.first + if (channel.count == 1) 0 else at.lower; choices[channel.slot] = clip.choices[key]; } }};Source: fun/rig/src/root.zig:36
zig
pub const JointClip = clip.JointClip;Audit
| Definitions | 7 |
|---|---|
| Public names | 7 |
| Members | 8 |
| Version | 26.7.0 |
| Revision | daab053ee433 |