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
}

这个完整示例演示了:

  1. 粒子系统物理模拟(使用SIMD加速)
  2. 几何变换(使用Rotor进行旋转)
  3. 批量光线与球体相交检测

要运行此示例,确保在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);
}

性能建议

  1. 尽量使用批量操作而不是单个操作
  2. 重用已分配的矩阵和向量
  3. 考虑使用f32而不是f64以获得更好的SIMD加速效果
  4. 对性能关键代码使用#[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);
    }
}

这个示例展示了如何:

  1. 定义3D立方体的顶点
  2. 创建缩放、旋转和平移变换
  3. 组合这些变换
  4. 将变换应用到所有顶点上

输出将显示原始顶点和变换后的顶点坐标,展示了3D变换的效果。

回到顶部