Rust线性插值库lerp的使用,高性能数值过渡与动画补间工具
Rust线性插值库lerp的使用,高性能数值过渡与动画补间工具
Lerp是一个用于线性插值和迭代的Rust库,自动实现大多数浮点兼容类型的线性插值功能。
基本使用
简单线性插值
use lerp::Lerp;
assert_eq!(3.0.lerp(5.0, 0.5), 4.0);
迭代插值
// 引入trait
use lerp::LerpIter;
// 在3.0和5.0之间均匀生成4个值
// 注意默认的开放迭代器不包括两端点
// 这使得链式插值迭代器更简单
let items: Vec<_> = 3.0_f64.lerp_iter(5.0, 4).collect();
assert_eq!(vec![3.0, 3.5, 4.0, 4.5], items);
// 闭合迭代器包含两端点
assert_eq!(vec![3.0, 5.0], 3.0.lerp_iter_closed(5.0, 2).collect::<Vec<_>>());
派生Lerp
该库还提供了derive宏(需要启用derive
特性),可以自动生成实现。
[dependencies]
lerp = { version = "0.4", features = ["derive"] }
use lerp::Lerp;
#[derive(Lerp, PartialEq, Debug)]
struct Data {
a: f64,
b: f64
}
assert_eq!(
Data { a: 0.0, b: 1.0 }.lerp(Data { a: 1.0, b: 0.0 }, 0.5),
Data { a: 0.5, b: 0.5 }
);
完整示例
use lerp::{Lerp, LerpIter};
fn main() {
// 基本线性插值
println!("3.0和5.0中间值是: {}", 3.0.lerp(5.0, 0.5));
// 动画补间示例
let start = 0.0;
let end = 100.0;
let steps = 10;
println!("\n从{}到{}的{}步动画值:", start, end, steps);
for value in start.lerp_iter(end, steps) {
println!("{:.1}", value);
}
// 自定义结构体插值
#[derive(Lerp, Debug)]
struct Position {
x: f32,
y: f32,
}
let pos1 = Position { x: 0.0, y: 10.0 };
let pos2 = Position { x: 100.0, y: 50.0 };
println!("\n位置过渡:");
for t in 0..=10 {
let t = t as f32 / 10.0;
let pos = pos1.lerp(pos2, t);
println!("t={:.1}: {:?}", t, pos);
}
}
安装
在Cargo.toml中添加:
[dependencies]
lerp = "0.5.0"
或者运行:
cargo add lerp
完整示例demo
基于上述内容,这里提供一个更完整的动画补间示例:
use lerp::{Lerp, LerpIter};
use std::thread;
use std::time::Duration;
#[derive(Lerp, Debug, Clone)]
struct Color {
r: f32,
g: f32,
b: f32,
}
fn main() {
// 数值过渡示例
println!("数值过渡示例:");
for value in 0.0_f32.lerp_iter(1.0, 5) {
println!("当前值: {:.2}", value);
}
// 颜色过渡动画
let start_color = Color { r: 1.0, g: 0.0, b: 0.0 }; // 红色
let end_color = Color { r: 0.0, g: 0.0, b: 1.0 }; // 蓝色
println!("\n颜色过渡动画:");
for t in 0..=10 {
let t = t as f32 / 10.0;
let color = start_color.lerp(&end_color, t);
println!("进度 {:.0}%: {:?}", t * 100.0, color);
thread::sleep(Duration::from_millis(200));
}
// 复杂结构体插值
#[derive(Lerp, Debug)]
struct Transform {
position: (f32, f32),
scale: f32,
rotation: f32,
}
let start = Transform {
position: (0.0, 0.0),
scale: 1.0,
rotation: 0.0,
};
let end = Transform {
position: (100.0, 50.0),
scale: 2.0,
rotation: 90.0,
};
println!("\n变换动画:");
for t in 0..=5 {
let t = t as f32 / 5.0;
let transform = start.lerp(&end, t);
println!("t={:.1}: {:?}", t, transform);
}
}
这个完整示例展示了:
- 基本的数值过渡
- 颜色结构的平滑过渡动画
- 复杂结构体的插值变换
- 使用lerp_iter进行迭代插值
- 派生Lerp trait在自定义结构体上的应用
1 回复
Rust线性插值库lerp的使用指南
介绍
lerp
是Rust中一个简单高效的线性插值库,用于在两个值之间进行平滑过渡计算。它特别适合用于动画、游戏开发、数据可视化和任何需要数值过渡的场景。
线性插值(Linear Interpolation)的基本公式是:
result = start + (end - start) * t
其中t通常在[0.0, 1.0]范围内变化。
安装
在Cargo.toml中添加依赖:
[dependencies]
lerp = "0.4.0"
基本用法
1. 数值插值
use lerp::Lerp;
fn main() {
let start = 0.0f32;
let end = 10.0f32;
// 在中间点插值
let middle = start.lerp(end, 0.5);
println!("中间值: {}", middle); // 输出: 5.0
// 25%位置插值
let quarter = start.lerp(end, 0.25);
println!("25%位置的值: {}", quarter); // 输出: 2.5
}
2. 颜色插值
use lerp::Lerp;
fn main() {
let red = (1.0, 0.0, 0.0); // RGB
let blue = (0.0, 0.0, 1.0);
// 从红色渐变到蓝色
let purple = red.lerp(blue, 0.5);
println!("紫色: {:?}", purple); // 输出: (0.5, 0.0, 0.5)
}
3. 向量插值
use lerp::Lerp;
use glam::Vec3; // 需要添加glam依赖
fn main() {
let start_pos = Vec3::new(0.0, 0.0, 0.0);
let end_pos = Vec3::new(10.0, 5.0, 0.0);
// 在30%位置插值
let current_pos = start_pos.lerp(end_pos, 0.3);
println!("当前位置: {:?}", current_pos); // 输出: Vec3(3.0, 1.5, 0.0)
}
高级特性
1. 范围映射
use lerp::{Lerp, remap};
fn main() {
// 将0.5从[0.0, 1.0]范围映射到[100.0, 200.0]范围
let value = remap(0.5, 极狐0.0..=1.0, 100.0..=200.0);
println!("映射后的值: {}", value); // 输出: 150.0
}
2. 缓动函数
use lerp::{Lerp, ease_in_out_quad};
fn main() {
let start = 0.0;
let end = 100.0;
let t = 0.7; // 原始进度
// 应用二次缓动函数
let eased_t = ease_in_out_quad(t);
let value = start.ler极狐p(end, eased_t);
println!("缓动后的值: {}", value);
}
3. 自定义类型插值
可以为自定义类型实现Lerp
trait:
use lerp::Lerp;
struct Point {
x: f32,
y: f32,
}
impl Lerp<f32> for Point {
fn lerp(self, other: Self, t: f32) -> Self {
Point {
x: self.x.lerp(other.x, t),
y: self.y.lerp(other.y, t),
}
}
}
fn main() {
let p1 = Point { x: 0.0, y: 0.0 };
let p2 = Point { x: 10.0, y: 20.0 };
let p_mid = p1.lerp(p2, 0.5);
println!("中点: ({}, {})", p_mid.x, p_mid.y); // 输出: (5.0, 10.0)
}
性能提示
lerp
库经过高度优化,对浮点运算特别友好- 对于大量插值计算,考虑使用SIMD优化
- 在游戏循环中,可以预计算(end - start)来避免重复计算
实际应用示例:平滑动画
use lerp::Lerp;
use std::time::{Instant, Duration};
struct Animation {
start_value: f32,
end_value: f32,
duration: Duration,
start_time: Instant,
}
impl Animation {
fn new(start: f32, end: f32, duration: Duration) -> Self {
Self {
start_value: start,
end_value: end,
duration,
start_time: Instant::now(),
}
}
fn current_value(&self) -> f32 {
let elapsed = self.start_time.elapsed();
let t = (elapsed.as_secs_f32() / self.duration.as_secs_f32()).min(1.0);
self.start_value.lerp(self.end_value, t)
}
}
fn main() {
let anim = Animation::new(0.0, 100.0, Duration::from_secs(2));
loop {
let value = anim.current_value();
println!("当前值: {}", value);
if value >= 100.0 {
break;
}
std::thread::sleep(Duration::from_millis(16)); // ~60fps
}
}
lerp
库是Rust生态中处理线性插值的高效工具,通过简单的API提供了强大的功能,特别适合游戏开发、UI动画和科学计算等场景。