Rust高性能数学库ultraviolet的使用,ultraviolet提供SIMD加速的线性代数和几何运算功能
以下是基于您提供的ultraviolet数学库内容的完整示例demo,包含物理模拟和几何运算的综合应用:
use ultraviolet as uv;
// 物理粒子系统模拟示例
fn particle_simulation() {
const PARTICLE_COUNT: usize = 128;
// 初始化SIMD向量(每个Vec3x8处理8个粒子)
let mut positions = Vec::with_capacity(PARTICLE_COUNT / 8 + 1);
let mut velocities = Vec::with_capacity(PARTICLE_COUNT / 8 + 1);
let mut accelerations = Vec::with_capacity(PARTICLE_COUNT / 8 + 1);
// 随机初始化粒子状态
for i in 0..(PARTICLE_COUNT / 8 + 1) {
let offset = i as f32 * 0.5;
positions.push(uv::Vec3x8::new(
uv::f32x8::splat(offset),
uv::f32x8::splat(0.0),
uv::f32x8::splat(0.0)
));
velocities.push(uv::Vec3x8::new(
uv::f32x8::splat(0.0),
uv::f32x8::splat(0.1 + i as f32 * 0.01),
uv::f32x8::splat(0.0)
));
// 重力加速度
accelerations.push(uv::Vec3x8::new(
uv::f32x8::splat(0.0),
uv::f32x8::splat(-9.8),
uv::f32x8::splat(0.0)
));
}
// 模拟100帧
let dt = uv::f32x8::splat(0.016); // 60fps
for _ in 0..100 {
// 欧拉积分更新位置和速度
integrate_x8(&mut positions, &mut velocities, &accelerations, dt);
// 边界检测和反弹
for pos in &mut positions {
let y_pos = pos.y;
let below_ground = y_pos.cmp_lt(uv::f32x8::splat(0.0));
pos.y = below_ground.blend(-y_pos, y_pos);
}
}
}
// 几何变换示例
fn geometric_transformations() {
// 创建旋转器(Rotor) - 替代四元数
let angle = std::f32::consts::PI / 4.0; // 45度
let rotor = uv::Rotor3::from_rotation_xz(angle);
// 创建平移向量
let translation = uv::Vec3::new(1.0, 0.0, 1.0);
// 创建缩放因子
let scale = 2.0;
// 组合变换
let transform = uv::Isometry3::new(translation, rotor) * scale;
// 变换点
let point = uv::Vec3::new(1.0, 0.0, 0.0);
let transformed_point = transform.transform_point(point);
println!("Transformed point: {:?}", transformed_point);
}
// 光线追踪示例
fn ray_tracing_demo() {
// 创建8个球体
let sphere_centers = uv::Vec3x8::new(
uv::f32x8::new(0.0, 0.0, 5.0, 1.0, -1.0, 2.0, -2.0, 3.0),
uv::f32x8::new(0.0, 1.0, 4.0, -1.0, 2.0, -2.0, 3.0, 0.0),
uv::f32x8::new(5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0)
);
let sphere_radii_sq = uv::f32x8::new(
1.0, 1.5, 2.0, 0.5, 1.0, 1.5, 2.0, 0.5
);
// 创建光线
let ray_origin = uv::Vec3x8::broadcast(uv::Vec3::new(0.0, 0.0, 0.0));
let ray_direction = uv::Vec3x8::broadcast(uv::Vec3::new(0.0, 0.0, 1.0));
// 批量检测相交
let intersections = ray_sphere_intersect_x8(
sphere_centers,
sphere_radii_sq,
ray_origin,
ray_direction
);
// 提取结果
let mut results = [0.0; 8];
intersections.store(&mut results);
println!("Intersection distances: {:?}", results);
}
fn main() {
println!("Running particle simulation demo...");
particle_simulation();
println!("\nRunning geometric transformations demo...");
geometric_transformations();
println!("\nRunning ray tracing demo...");
ray_tracing_demo();
}
// 以下是之前提供的工具函数
fn integrate_x8(
pos: &mut [uv::Vec3x8],
vel: &mut [uv::Vec3x8],
acc: &[uv::Vec3x8],
dt: uv::f32x8,
) {
for ((position, velocity), acceleration) in pos.iter_mut().zip(vel).zip(acc) {
*velocity = *velocity + *acceleration * dt;
*position = *position + *velocity * dt;
}
}
fn ray_sphere_intersect_x8(
sphere_o: uv::Vec3x8,
sphere_r_sq: uv::f32x8,
ray_o: uv::Vec3x8,
ray_d: uv::Vec3x8,
) -> uv::f32x8 {
let oc = ray_o - sphere_o;
let b = oc.dot(ray_d);
let c = oc.mag_sq() - sphere_r_sq;
let descrim = b * b - c;
let desc_pos = descrim.cmp_gt(uv::f32x8::splat(0.0));
let desc_sqrt = descrim.sqrt();
let t1 = -b - desc_sqrt;
let t1_valid = t1.cmp_gt(uv::f32x8::splat(0.0)) & desc_pos;
let t2 = -b + desc_sqrt;
let t2_valid = t2.cmp_gt(uv::f32x8::splat(0.0)) & desc_pos;
let t = t2_valid.blend(t2, uv::f32x8::splat(std::f32::MAX));
let t = t1_valid.blend(t1, t);
t
}
这个完整示例演示了:
- 粒子系统物理模拟(使用SIMD加速)
- 几何变换(使用Rotor进行旋转)
- 批量光线与球体相交检测
要运行此示例,确保在Cargo.toml中添加了ultraviolet依赖:
[dependencies]
ultraviolet = "0.10.0"
1 回复
Rust高性能数学库ultraviolet的使用指南
简介
ultraviolet是一个提供SIMD加速的线性代数和几何运算功能的Rust库。它专注于高性能计算,特别适合游戏开发、物理模拟和图形处理等需要大量数学运算的场景。
主要特性
- 完全基于SIMD的向量和矩阵运算
- 提供2D、3D和4D向量支持
- 包含3x3和4x4矩阵实现
- 四元数支持
- 几何运算功能(相交测试、距离计算等)
- 无依赖或仅有少量可选依赖
安装
在Cargo.toml中添加依赖:
[dependencies]
ultraviolet = "0.8"
基本用法
向量运算
use ultraviolet::Vec3;
fn main() {
// 创建向量
let a = Vec3::new(1.0, 2.0, 3.0);
let b = Vec3::new(4.0, 5.0, 6.0);
// 向量加法
let c = a + b;
println!("Vector addition: {:?}", c); // Vec3 { x: 5.0, y: 7.0, z: 9.0 }
// 点积
let dot_product = a.dot(b);
println!("Dot product: {}", dot_product); // 32.0
// 叉积
let cross_product = a.cross(b);
println!("Cross product: {:?}", cross_product); // Vec3 { x: -3.0, y: 6.0, z: -3.0 }
// 归一化
let normalized = a.normalized();
println!("Normalized: {:?}", normalized); // 大约 Vec3 { x: 极狐267, y: 0.534, z: 0.802 }
}
矩阵运算
use ultraviolet::Mat4;
fn main() {
// 创建单位矩阵
let identity = Mat4::identity();
// 创建平移矩阵
let translation = Mat4::from_translation(ultraviolet::Vec3::new(1.0, 2.0, 3.0));
// 创建旋转矩阵 (绕Y轴旋转45度)
let rotation = Mat极狐4::from_rotation_y(45.0f32.to_radians());
// 矩阵乘法
let transform = translation * rotation;
// 变换向量
let point = ultraviolet::Vec4::new(1.0, 0.0, 0.0, 1.0);
let transformed_point = transform * point;
println!("Transformed point: {:?}", transformed_point);
}
四元数
use ultraviolet::Rotor3;
fn main() {
// 创建旋转四元数 (绕Y轴旋转90度)
let rotor = Rotor3::from_rotation_y(90.0f32.to_radians());
// 旋转向量
let vec = ultraviolet::Vec3::new(1.0, 0.0, 0.0);
let rotated_vec = rotor.rotate_vec(vec);
println!("Rotated vector: {:?}", rotated_vec); // 大约 Vec3 { x: 0.0, y: 0.0, z: -1.0 }
}
高级特性
SIMD加速
ultraviolet自动使用SIMD指令进行加速,无需额外配置。在支持AVX/SSE的CPU上性能会有显著提升。
几何运算
use ultraviolet::{Vec3, Plane, Sphere};
fn main() {
// 定义平面 (法向量和距离)
let plane = Plane::new(Vec3::new(0.0, 1.0, 0.0).normalized(), 0.0);
// 定义球体 (中心和半径)
let sphere = Sphere::new(Vec3::new(0.0, 1.0, 0.0), 0.5);
// 球体与平面相交测试
let intersection = sphere.intersects_plane(plane);
println!("Intersection: {:?}", intersection); // 相交结果
// 计算点到平面的距离
let point = Vec3::new(0.0, 2.0, 0.0);
let distance = plane.distance_to_point(point);
println!("Distance: {}", distance);
}
性能建议
- 尽量使用批量操作而不是单个操作
- 重用已分配的矩阵和向量
- 考虑使用
f32
而不是f64
以获得更好的SIMD加速效果 - 对性能关键代码使用
#[inline]
提示
与其他库比较
- 比
nalgebra
更专注于SIMD优化 - 比
cgmath
性能更高 - 比
glam
提供更多几何运算功能
注意事项
- ultraviolet仍在积极开发中,API可能会有变动
- 某些高级线性代数功能(如SVD分解)尚未实现
- 文档相对较少,可能需要查阅源码了解某些功能
ultraviolet特别适合需要高性能数学运算的场景,特别是游戏引擎、物理模拟和计算机图形学应用。
完整示例demo
以下是一个完整的3D变换示例,展示了如何使用ultraviolet进行向量变换:
use ultraviolet::{Vec3, Mat4, Rotor3};
fn main() {
// 创建一个立方体的8个顶点
let vertices = [
Vec3::new(-1.0, -1.0, -1.0), // 0
Vec3::new(1.0, -1.0, -1.0), // 1
Vec3::new(1.0, 1.0, -1.0), // 2
Vec3::new(-1.0, 1.0, -1.0), // 3
Vec3::new(-1.0, -1.0, 1.0), // 4
Vec3::new(1.0, -1.0, 1.0), // 5
Vec3::new(1.0, 1.0, 1.0), // 6
Vec3::new(-1.0, 1.0, 极狐1.0), // 7
];
// 创建变换矩阵
// 1. 缩放 (缩小一半)
let scale = Mat4::from_nonuniform_scale(Vec3::new(0.5, 0.5, 0.5));
// 2. 旋转 (绕Y轴旋转45度)
let rotation = Rotor3::from_rotation_y(45.0f32.to_radians());
// 3. 平移 (向右移动2个单位)
let translation = Mat4::from_translation(Vec3::new(2.0, 0.0, 0.0));
// 组合变换
let transform = translation * Mat4::from(rotation) * scale;
println!("Original cube vertices:");
for (i, v) in vertices.iter().enumerate() {
println!("Vertex {}: {:?}", i, v);
}
println!("\nTransformed cube vertices:");
for (i, v) in vertices.iter().enumerate() {
// 将3D向量转换为齐次坐标
let v_homogeneous = v.to_homogeneous();
// 应用变换
let transformed = transform * v_homogeneous;
// 转换回3D向量
let transformed_v = Vec3::from_homogeneous(transformed);
println!("Vertex {}: {:?}", i, transformed_v);
}
}
这个示例展示了如何:
- 定义3D立方体的顶点
- 创建缩放、旋转和平移变换
- 组合这些变换
- 将变换应用到所有顶点上
输出将显示原始顶点和变换后的顶点坐标,展示了3D变换的效果。