Rust物理引擎库rapier2d的使用:高性能2D碰撞检测与刚体模拟的Rust实现
Rust物理引擎库rapier2d的使用:高性能2D碰撞检测与刚体模拟的Rust实现
Rapier是一套用于游戏、动画和机器人技术的2D和3D物理引擎。这些库包括rapier2d
、rapier3d
、rapier2d-f64
和rapier3d-f64
。它们由Rust编程语言编写,由Dimforge组织开发。它永远免费且开源!
什么是Rapier?
Rapier是一套用于游戏、动画和机器人技术的2D和3D物理引擎。
快速开始
使用Rapier的最简单方法是:
- 阅读用户指南
- 运行示例:
cargo run --release --bin all_examples2
和cargo run --release --bin all_examples3
- 在Discord上寻求帮助,或在GitHub上提出问题
完整示例代码
use rapier2d::prelude::*;
use rapier2d::dynamics::RigidBodyBuilder;
use rapier2d::geometry::ColliderBuilder;
fn main() {
// 初始化物理世界
let gravity = vector![0.0, -9.81];
let mut physics_pipeline = PhysicsPipeline::new();
let mut integration_parameters = IntegrationParameters::default();
let mut island_manager = IslandManager::new();
let mut broad_phase = BroadPhase::new();
let mut narrow_phase = NarrowPhase::new();
let mut rigid_body_set = RigidBodySet::new();
let mut collider_set = ColliderSet::new();
let mut impulse_joint_set = ImpulseJointSet::new();
let mut multibody_joint_set = MultibodyJointSet::new();
// 创建地面
let ground_size = 10.0;
let ground_height = 0.1;
let ground_rigid_body = RigidBodyBuilder::fixed()
.translation(vector![0.0, -ground_height])
.build();
let ground_handle = rigid_body_set.insert(ground_rigid_body);
let ground_collider = ColliderBuilder::cuboid(ground_size, ground_height)
.build();
collider_set.insert_with_parent(ground_collider, ground_handle, &mut rigid_body_set);
// 创建一个下落的球体
let ball_radius = 0.5;
let ball_rigid_body = RigidBodyBuilder::dynamic()
.translation(vector![0.0, 3.0])
.build();
let ball_handle = rigid_body_set.insert(ball_rigid_body);
let ball_collider = ColliderBuilder::ball(ball_radius)
.restitution(0.7) // 设置弹性系数
.build();
collider_set.insert_with_parent(ball_collider, ball_handle, &mut rigid_body_set);
// 模拟100步物理
for _ in 0..100 {
physics_pipeline.step(
&gravity,
&integration_parameters,
&mut island_manager,
&mut broad_phase,
&mut narrow_phase,
&mut rigid_body_set,
&mut collider_set,
&mut impulse_joint_set,
&mut multibody_joint_set,
&(),
&(),
);
// 获取球体位置
let ball = rigid_body_set.get(ball_handle).unwrap();
println!("Ball position: ({}, {})", ball.translation().x, ball.translation().y);
}
}
示例说明
- 首先创建物理世界,包括重力、碰撞检测等组件
- 创建一个固定的地面刚体和碰撞体
- 创建一个动态的球体刚体和碰撞体,并设置弹性系数
- 进行100步物理模拟,每步打印球体的位置
这个示例展示了Rapier的基本用法,包括:
- 创建刚体(RigidBody)
- 创建碰撞体(Collider)
- 设置物理属性(如弹性系数)
- 进行物理模拟
安装
在项目目录中运行以下Cargo命令:
cargo add rapier2d
或在Cargo.toml中添加:
rapier2d = "0.27.0"
类别
- WebAssembly
- 科学
- 模拟
- 游戏开发
- 数学
扩展示例:多物体碰撞模拟
use rapier2d::prelude::*;
use rapier2d::dynamics::RigidBodyBuilder;
use rapier2d::geometry::ColliderBuilder;
fn main() {
// 初始化物理世界
let gravity = vector![0.0, -9.81];
let mut physics_pipeline = PhysicsPipeline::new();
let mut integration_parameters = IntegrationParameters::default();
let mut island_manager = IslandManager::new();
let mut broad_phase = BroadPhase::new();
let mut narrow_phase = NarrowPhase::new();
let mut rigid_body_set = RigidBodySet::new();
let mut collider_set = ColliderSet::new();
let mut impulse_joint_set = ImpulseJointSet::new();
let mut multibody_joint_set = MultibodyJointSet::new();
// 创建地面
let ground_size = 20.0;
let ground_height = 0.5;
let ground_rigid_body = RigidBodyBuilder::fixed()
.translation(vector![0.0, -ground_height])
.build();
let ground_handle = rigid_body_set.insert(ground_rigid_body);
let ground_collider = ColliderBuilder::cuboid(ground_size, ground_height)
.restitution(0.5)
.friction(0.7)
.build();
collider_set.insert_with_parent(ground_collider, ground_handle, &mut rigid_body_set);
// 创建多个随机下落的物体
for i in 0..10 {
let shape_type = i % 3;
let radius = 0.3 + (i as f32 * 0.05) as f64;
let x_pos = (i as f64 - 5.0) * 1.5;
let body = RigidBodyBuilder::dynamic()
.translation(vector![x_pos, 5.0 + i as f64 * 0.5])
.build();
let handle = rigid_body_set.insert(body);
// 创建不同类型的碰撞体
let collider = match shape_type {
0 => ColliderBuilder::ball(radius),
1 => ColliderBuilder::cuboid(radius, radius),
_ => ColliderBuilder::capsule_y(radius, radius * 0.5),
}
.restitution(0.3 + i as f64 * 0.05)
.friction(0.5)
.build();
collider_set.insert_with_parent(collider, handle, &mut rigid_body_set);
}
// 模拟200步物理
for step in 0..200 {
physics_pipeline.step(
&gravity,
&integration_parameters,
&mut island_manager,
&mut broad_phase,
&mut narrow_phase,
&mut rigid_body_set,
&mut collider_set,
&mut impulse_joint_set,
&mut multibody_joint_set,
&(),
&(),
);
// 每10步打印一次所有物体的位置
if step % 10 == 0 {
println!("Step {}", step);
for (_, body) in rigid_body_set.iter() {
println!("Object at: ({:.2}, {:.2})",
body.translation().x,
body.translation().y);
}
}
}
}
这个扩展示例展示了:
- 创建包含多种形状的物理场景
- 设置不同的物理属性(弹性、摩擦系数)
- 批量创建物体并管理它们
- 更详细的模拟输出
您可以根据需要调整参数,如重力大小、物体数量、形状类型等,来创建不同的物理模拟场景。
1 回复
Rust物理引擎库rapier2d的使用:高性能2D碰撞检测与刚体模拟的Rust实现
以下是基于rapier2d的完整示例demo,展示了一个简单的物理模拟场景:
use rapier2d::prelude::*;
use std::f32::consts::PI;
fn main() {
// 1. 初始化物理世界
let gravity = vector![0.0, -9.81]; // 重力加速度
let mut physics_pipeline = PhysicsPipeline::new();
let integration_parameters = IntegrationParameters {
dt: 1.0 / 60.0, // 每帧时间步长
..Default::default()
};
let mut physics_world = PhysicsWorld::new(gravity);
let mut collider_set = ColliderSet::new();
let mut rigid_body_set = RigidBodySet::new();
let mut joint_set = JointSet::new();
// 2. 创建地面(静态刚体)
let ground_size = 50.0;
let ground_pos = Isometry::translation(0.0, -10.0);
let ground_shape = SharedShape::cuboid(ground_size, 1.0);
let ground_collider = ColliderBuilder::new(ground_shape).build();
collider_set.insert_with_parent(ground_collider, RigidBodyHandle::invalid(), &mut rigid_body_set);
// 3. 创建动态刚体(球体)
let ball_radius = 1.0;
let ball_pos = Isometry::translation(0.0, 3.0);
let ball_shape = SharedShape::ball(ball_radius);
let ball_collider = ColliderBuilder::new(ball_shape)
.restitution(0.7) // 弹性系数
.friction(0.5) // 摩擦系数
.build();
let ball_body = RigidBodyBuilder::dynamic()
.translation(0.0, 3.0)
.linvel(5.0, 0.0) // 初始水平速度
.build();
let ball_body_handle = rigid_body_set.insert(ball_body);
collider_set.insert_with_parent(ball_collider, ball_body_handle, &mut rigid_body_set);
// 4. 创建多边形刚体
let poly_body = RigidBodyBuilder::dynamic()
.translation(5.0, 5.0)
.rotation(PI / 4.0) // 旋转45度
.build();
let poly_body_handle = rigid_body_set.insert(poly_body);
let poly_points = [
point![-1.0, -1.0],
point![1.0, -1.0],
point![1.0, 1.0],
point![-1.0, 1.0],
];
let poly_shape = SharedShape::convex_hull(&poly_points).unwrap();
let poly_collider = ColliderBuilder::new(poly_shape)
.restitution(0.3)
.build();
collider_set.insert_with_parent(poly_collider, poly_body_handle, &mut rigid_body_set);
// 5. 模拟循环
for _ in 0..300 {
// 执行物理模拟
physics_pipeline.step(
&gravity,
&integration_parameters,
&mut physics_world,
&mut collider_set,
&mut rigid_body_set,
&mut joint_set,
&mut (),
&mut (),
);
// 获取球体位置
if let Some(ball_body) = rigid_body_set.get(ball_body_handle) {
let position = ball_body.position();
println!("Ball position: x={:.2}, y={:.2}", position.translation.x, position.translation.y);
}
// 碰撞检测
let mut collision_events = Vec::new();
physics_world.collision_events(&mut collision_events);
for event in collision_events {
match event {
CollisionEvent::Started(h1, h2) => {
println!("碰撞开始: {:?} 和 {:?}", h1, h2);
}
CollisionEvent::Stopped(h1, h2) => {
println!("碰撞结束: {:?} 和 {:?}", h1, h2);
}
}
}
}
}
这个完整示例演示了:
- 初始化物理世界并设置重力
- 创建静态地面刚体
- 创建一个带有初始速度的动态球体
- 创建一个旋转的多边形刚体
- 运行300步物理模拟
- 每步输出球体位置
- 检测并输出碰撞事件
要运行此示例,请确保在Cargo.toml中添加了rapier2d依赖:
[dependencies]
rapier2d = "0.17"
这个示例展示了rapier2d的核心功能,包括刚体创建、碰撞检测和物理模拟。你可以根据需要扩展这个基础示例,添加更多刚体、关节或自定义碰撞行为。