Rust 3D碰撞检测库parry3d的使用,parry3d提供高性能的3D几何形状碰撞检测与物理模拟功能

crates.io


2D Documentation | 3D Documentation | User Guide


什么是Parry?

Parry是一套2维和3维几何与碰撞检测库。 这些库包括parry2dparry3dparry2d-f64parry3d-f64。它们由 Dimforge组织使用Rust编程语言编写。它永远免费 且开源!我们定期在我们的博客上更新我们的进展。

资源与讨论

  • Dimforge:查看我们正在开发的所有开源项目!关注我们的公告 在我们的博客上。
  • 用户指南:(进行中)通过阅读官方用户指南学习在您的项目中使用Parry。
  • Discord:来和我们聊天,获取帮助,提出功能建议,在Discord上!
// 完整示例代码:使用parry3d进行3D碰撞检测
use parry3d::math::Vector;
use parry3d::shape::{Ball, Cuboid};
use parry3d::query::details::ContactManifold;

fn main() {
    // 创建一个球体,半径为1.0
    let ball = Ball::new(1.0);
    
    // 创建一个立方体,半尺寸为(1.0, 1.0, 1.0)
    let cuboid = Cuboid::new(Vector::new(1.0, 1.0, 1.0));
    
    // 定义球体的位置和方向(单位四元数表示无旋转)
    let ball_pos = Vector::new(0.0, 0.0, 0.0);
    let ball_rot = Vector::zeros(); // 无旋转
    
    // 定义立方体的位置和方向
    let cuboid_pos = Vector::new(2.0, 0.0, 0.0); // 在x轴上偏移2个单位
    let cuboid_rot = Vector::zeros(); // 无旋转
    
    // 检测碰撞
    let contact = parry3d::query::contact(
        &ball_pos, &ball_rot, &ball,
        &cuboid_pos, &cuboid_rot, &cuboid,
        0.0 // 预测距离
    );
    
    // 输出碰撞结果
    match contact {
        Some(contact) => {
            println!("碰撞检测到!");
            println!("碰撞点: {:?}", contact.point1);
            println!("法向量: {:?}", contact.normal1);
            println!("穿透深度: {}", contact.dist);
        }
        None => {
            println!("未检测到碰撞");
        }
    }
}
// 完整示例代码:使用parry2d进行2D碰撞检测
use parry2d::math::Vector;
use parry2d::shape::{Ball, Cuboid};
use parry2d::query::contact;

fn main() {
    // 创建一个圆形,半径为1.0
    let circle = Ball::new(1.0);
    
    // 创建一个矩形,半尺寸为(1.0, 1.0)
    let rectangle = Cuboid::new(Vector::new(1.0, 1.0));
    
    // 定义圆形的位置和角度(无旋转)
    let circle_pos = Vector::new(0.0, 0.0);
    let circle_rot = 0.0; // 无旋转
    
    // 定义矩形的位置和角度
    let rectangle_pos = Vector::new(1.5, 0.0); // 在x轴上偏移1.5个单位
    let rectangle_rot = 0.0; // 无旋转
    
    // 检测碰撞
    let contact = contact(
        &circle_pos, &circle_rot, &circle,
        &rectangle_pos, &rectangle_rot, &rectangle,
        0.0 // 预测距离
    );
    
    // 输出碰撞结果
    match contact {
        Some(contact) => {
            println!("2D碰撞检测到!");
            println!("碰撞点: {:?}", contact.point1);
            println!("法向量: {:?}", contact.normal1);
            println!("穿透深度: {}", contact.dist);
        }
        None => {
            println!("未检测到2D碰撞");
        }
    }
}

1 回复

parry3d:高性能Rust 3D碰撞检测与物理模拟库

简介

parry3d是一个专为Rust语言设计的高性能3D碰撞检测和物理模拟库。它提供了多种几何形状的碰撞检测、接触点计算、距离查询以及物理模拟功能,特别适合游戏开发、机器人仿真和计算机图形学应用。

主要特性

  • 支持多种3D几何形状(球体、立方体、胶囊体、凸多面体等)
  • 高效的碰撞检测算法
  • 精确的接触点生成
  • 距离和最近点计算
  • 连续碰撞检测(CCD)
  • 物理模拟集成

安装方法

在Cargo.toml中添加依赖:

[dependencies]
parry3d = "0.13"
nalgebra = "0.32"

基础使用方法

1. 基本碰撞检测

use parry3d::query;
use parry3d::shape::{Ball, Cuboid};
use nalgebra::Vector3;

fn main() {
    // 创建几何形状
    let ball = Ball::new(1.0);
    let cube = Cuboid::new(Vector3::new(1.0, 1.0, 1.0));
    
    // 设置变换
    let ball_pos = na::Isometry3::translation(0.0, 0.0, 0.0);
    let cube_pos = na::Isometry3::translation(2.0, 0.0, 0.0);
    
    // 检测碰撞
    let collision = query::contact(
        &ball_pos,
        &ball,
        &cube_pos,
        &cube,
        0.0
    );
    
    if let Some(contact) = collision {
        println!("碰撞发生!穿透深度: {}", contact.dist);
    }
}

2. 距离计算

use parry3d::query::distance;

fn compute_distance() {
    let sphere1 = Ball::new(1.0);
    let sphere2 = Ball::new(0.5);
    
    let pos1 = na::Isometry3::translation(0.0, 0.0, 0.0);
    let pos2 = na::Isometry3::translation(3.0, 0.0, 0.0);
    
    let dist = distance(&pos1, &sphere1, &pos2, &sphere2).unwrap();
    println!("两球体距离: {}", dist);
}

3. 物理模拟集成示例

use parry3d::dynamics::{RigidBody, RigidBodySet};
use parry3d::geometry::{Collider, ColliderSet};
use parry3d::pipeline::PhysicsPipeline;

fn physics_simulation() {
    let mut rigid_bodies = RigidBodySet::new();
    let mut colliders = ColliderSet::new();
    let mut pipeline = PhysicsPipeline::new();
    
    // 创建刚体
    let rigid_body = RigidBody::new_dynamic(
        na::Isometry3::identity(),
        Vector3::zeros(),
        Vector3::zeros(),
        1.0
    );
    let handle = rigid_bodies.insert(rigid_body);
    
    // 添加碰撞体
    let collider = Collider::new(Ball::new(0.5));
    colliders.insert(collider, handle, &mut rigid_bodies);
}

高级功能

连续碰撞检测

use parry3d::query::time_of_impact;

fn ccd_example() {
    let shape = Ball::new(0.5);
    let pos1 = na::Isometry3::translation(0.0, 0.0, 0.0);
    let pos2 = na::Isometry3::translation(10.0, 0.0, 0.0);
    
    let toi = time_of_impact(
        &pos1,
        &Vector3::x() * 10.0, // 速度
        &shape,
        &pos2,
        &Vector3::zeros(),
        &shape,
        1.0
    );
    
    if let Some(time) = toi {
        println!("碰撞将在 {} 秒后发生", time);
    }
}

完整示例demo

use parry3d::query::{contact, distance, time_of_impact};
use parry3d::shape::{Ball, Cuboid};
use parry3d::dynamics::{RigidBody, RigidBodySet};
use parry3d::geometry::{Collider, ColliderSet};
use parry3d::pipeline::PhysicsPipeline;
use nalgebra::{Vector3, Isometry3};

fn main() {
    // 示例1: 基本碰撞检测
    println!("=== 基本碰撞检测示例 ===");
    let ball = Ball::new(1.0);
    let cube = Cuboid::new(Vector3::new(1.0, 1.0, 1.0));
    
    let ball_pos = Isometry3::translation(0.0, 0.0, 0.0);
    let cube_pos = Isometry3::translation(2.0, 0.0, 0.0);
    
    let collision = contact(&ball_pos, &ball, &cube_pos, &cube, 0.0);
    if let Some(contact) = collision {
        println!("碰撞发生!穿透深度: {}", contact.dist);
    } else {
        println!("未发生碰撞");
    }

    // 示例2: 距离计算
    println!("\n=== 距离计算示例 ===");
    let sphere1 = Ball::new(1.0);
    let sphere2 = Ball::new(0.5);
    
    let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
    let pos2 = Isometry3::translation(3.0, 0.0, 0.0);
    
    if let Ok(dist) = distance(&pos1, &sphere1, &pos2, &sphere2) {
        println!("两球体距离: {}", dist);
    }

    // 示例3: 连续碰撞检测
    println!("\n=== 连续碰撞检测示例 ===");
    let shape = Ball::new(0.5);
    let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
    let pos2 = Isometry3::translation(10.0, 0.0, 0.0);
    
    let toi = time_of_impact(
        &pos1,
        &Vector3::x() * 10.0,
        &shape,
        &pos2,
        &Vector3::zeros(),
        &shape,
        1.0
    );
    
    if let Some(time) = toi {
        println!("碰撞将在 {} 秒后发生", time);
    }

    // 示例4: 物理模拟集成
    println!("\n=== 物理模拟集成示例 ===");
    let mut rigid_bodies = RigidBodySet::new();
    let mut colliders = ColliderSet::new();
    let mut pipeline = PhysicsPipeline::new();
    
    // 创建动态刚体
    let rigid_body = RigidBody::new_dynamic(
        Isometry3::identity(),
        Vector3::zeros(),
        Vector3::zeros(),
        1.0
    );
    let handle = rigid_bodies.insert(rigid_body);
    
    // 添加球体碰撞体
    let collider = Collider::new(Ball::new(0.5));
    colliders.insert(collider, handle, &mut rigid_bodies);
    
    println!("物理场景创建完成,包含 {} 个刚体", rigid_bodies.len());
}

性能建议

  • 对于静态几何体,使用Collider缓存查询结果
  • 批量处理碰撞检测以提高性能
  • 合理使用空间划分数据结构进行优化

注意事项

  • 确保正确管理几何形状的生命周期
  • 注意数值精度问题,特别是在处理小尺寸物体时
  • 定期更新到最新版本以获得性能改进和bug修复

parry3d提供了强大而灵活的3D碰撞检测功能,通过合理的API设计和高效的算法实现,能够满足大多数3D应用的物理模拟需求。

回到顶部