Update to Parry 0.18 (#770)
* update to parry ~main * use traverse_depth_first * add example to test intersection * rely on upstream PR rather than local * re-enable profiler_ui for examples * rely on official parry repository * chore: switch back to the published version of parry * chore: update changelog * chore: remove dead code * fix compilation of rapier3d-meshloader and rapier3d-urdf * chore: cargo fmt --------- Co-authored-by: Sébastien Crozet <sebcrozet@dimforge.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
- `InteractionGroups` default value for `memberships` is now `GROUP_1` (#706)
|
||||
- `ImpulseJointSet::get_mut` has a new parameter `wake_up: bool`, to wake up connected bodies.
|
||||
- Removed unmaintained `instant` in favor of `web-time`. This effectively removes the `wasm-bindgen` transitive dependency as it's no longer needed.
|
||||
- Significantly improve performances of `QueryPipeline::intersection_with_shape`.
|
||||
|
||||
## v0.22.0 (20 July 2024)
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn init_world(testbed: &mut Testbed) {
|
||||
|
||||
let rigid_body = RigidBodyBuilder::fixed();
|
||||
let handle = bodies.insert(rigid_body);
|
||||
let collider = ColliderBuilder::trimesh(vertices, indices);
|
||||
let collider = ColliderBuilder::trimesh(vertices, indices).unwrap();
|
||||
colliders.insert_with_parent(collider, handle, &mut bodies);
|
||||
|
||||
/*
|
||||
|
||||
@@ -68,7 +68,7 @@ vec_map = { version = "0.8", optional = true }
|
||||
web-time = { version = "1.1", optional = true }
|
||||
num-traits = "0.2"
|
||||
nalgebra = "0.33"
|
||||
parry2d-f64 = "0.17.0"
|
||||
parry2d-f64 = "0.18.0"
|
||||
simba = "0.9"
|
||||
approx = "0.5"
|
||||
rayon = { version = "1", optional = true }
|
||||
|
||||
@@ -68,7 +68,7 @@ vec_map = { version = "0.8", optional = true }
|
||||
web-time = { version = "1.1", optional = true }
|
||||
num-traits = "0.2"
|
||||
nalgebra = "0.33"
|
||||
parry2d = "0.17.0"
|
||||
parry2d = "0.18.0"
|
||||
simba = "0.9"
|
||||
approx = "0.5"
|
||||
rayon = { version = "1", optional = true }
|
||||
|
||||
@@ -71,7 +71,7 @@ vec_map = { version = "0.8", optional = true }
|
||||
web-time = { version = "1.1", optional = true }
|
||||
num-traits = "0.2"
|
||||
nalgebra = "0.33"
|
||||
parry3d-f64 = "0.17.0"
|
||||
parry3d-f64 = "0.18.0"
|
||||
simba = "0.9"
|
||||
approx = "0.5"
|
||||
rayon = { version = "1", optional = true }
|
||||
|
||||
@@ -27,6 +27,6 @@ wavefront = ["mesh-loader/obj"]
|
||||
[dependencies]
|
||||
thiserror = "1.0.61"
|
||||
profiling = "1.0"
|
||||
mesh-loader = { version = "0.1.12", optional = true }
|
||||
mesh-loader = "0.1.12"
|
||||
|
||||
rapier3d = { version = "0.22", path = "../rapier3d" }
|
||||
|
||||
@@ -19,9 +19,11 @@ license = "Apache-2.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
stl = ["dep:rapier3d-meshloader", "rapier3d-meshloader/stl"]
|
||||
collada = ["dep:rapier3d-meshloader", "rapier3d-meshloader/collada"]
|
||||
wavefront = ["dep:rapier3d-meshloader", "rapier3d-meshloader/wavefront"]
|
||||
stl = ["dep:rapier3d-meshloader", "rapier3d-meshloader/stl", "__meshloader_is_enabled"]
|
||||
collada = ["dep:rapier3d-meshloader", "rapier3d-meshloader/collada", "__meshloader_is_enabled"]
|
||||
wavefront = ["dep:rapier3d-meshloader", "rapier3d-meshloader/wavefront", "__meshloader_is_enabled"]
|
||||
## Private feature for detecting when meshloader is enabled by any of the file type features above.
|
||||
__meshloader_is_enabled = []
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
|
||||
@@ -37,7 +37,6 @@ use rapier3d::{
|
||||
geometry::{Collider, ColliderBuilder, ColliderHandle, ColliderSet, SharedShape, TriMeshFlags},
|
||||
math::{Isometry, Point, Real, Vector},
|
||||
na,
|
||||
prelude::MeshConverter,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
@@ -462,7 +461,7 @@ fn urdf_to_rigid_body(options: &UrdfLoaderOptions, inertial: &Inertial) -> Rigid
|
||||
|
||||
fn urdf_to_colliders(
|
||||
options: &UrdfLoaderOptions,
|
||||
mesh_dir: &Path,
|
||||
_mesh_dir: &Path, // Unused if none of the meshloader features is enabled.
|
||||
geometry: &Geometry,
|
||||
origin: &Pose,
|
||||
) -> Vec<Collider> {
|
||||
@@ -496,14 +495,20 @@ fn urdf_to_colliders(
|
||||
Geometry::Sphere { radius } => {
|
||||
colliders.push(SharedShape::ball(*radius as Real));
|
||||
}
|
||||
#[cfg(not(feature = "__meshloader_is_enabled"))]
|
||||
Geometry::Mesh { .. } => {
|
||||
log::error!("Mesh loading is disabled by default. Enable one of the format features (`stl`, `collada`, `wavefront`) of `rapier3d-urdf` for mesh support.");
|
||||
}
|
||||
#[cfg(feature = "__meshloader_is_enabled")]
|
||||
Geometry::Mesh { filename, scale } => {
|
||||
let full_path = mesh_dir.join(filename);
|
||||
let full_path = _mesh_dir.join(filename);
|
||||
let scale = scale
|
||||
.map(|s| Vector::new(s[0] as Real, s[1] as Real, s[2] as Real))
|
||||
.unwrap_or_else(|| Vector::<Real>::repeat(1.0));
|
||||
|
||||
let Ok(loaded_mesh) = rapier3d_meshloader::load_from_path(
|
||||
full_path,
|
||||
&MeshConverter::TriMeshWithFlags(options.trimesh_flags),
|
||||
&rapier3d::prelude::MeshConverter::TriMeshWithFlags(options.trimesh_flags),
|
||||
scale,
|
||||
) else {
|
||||
return Vec::new();
|
||||
|
||||
@@ -71,7 +71,7 @@ vec_map = { version = "0.8", optional = true }
|
||||
web-time = { version = "1.1", optional = true }
|
||||
num-traits = "0.2"
|
||||
nalgebra = "0.33"
|
||||
parry3d = "0.17.0"
|
||||
parry3d = "0.18.0"
|
||||
simba = "0.9"
|
||||
approx = "0.5"
|
||||
rayon = { version = "1", optional = true }
|
||||
|
||||
@@ -34,12 +34,12 @@ default = ["dim2"]
|
||||
dim2 = []
|
||||
parallel = ["rapier/parallel", "num_cpus"]
|
||||
other-backends = ["wrapped2d"]
|
||||
profiling = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
profiler_ui = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
# See https://github.com/dimforge/rapier/issues/760.
|
||||
unstable-puffin-pr-235 = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["parallel", "profiling"]
|
||||
features = ["parallel", "profiler_ui"]
|
||||
|
||||
[lints.clippy]
|
||||
needless_lifetimes = "allow"
|
||||
|
||||
@@ -34,12 +34,12 @@ default = ["dim2"]
|
||||
dim2 = []
|
||||
parallel = ["rapier/parallel", "num_cpus"]
|
||||
other-backends = ["wrapped2d"]
|
||||
profiling = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
profiler_ui = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
# See https://github.com/dimforge/rapier/issues/760.
|
||||
unstable-puffin-pr-235 = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["parallel", "other-backends", "profiling"]
|
||||
features = ["parallel", "other-backends", "profiler_ui"]
|
||||
|
||||
[lints.clippy]
|
||||
needless_lifetimes = "allow"
|
||||
|
||||
@@ -36,12 +36,12 @@ rust.unexpected_cfgs = { level = "warn", check-cfg = [
|
||||
default = ["dim3"]
|
||||
dim3 = []
|
||||
parallel = ["rapier/parallel", "num_cpus"]
|
||||
profiling = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
profiler_ui = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
# See https://github.com/dimforge/rapier/issues/760.
|
||||
unstable-puffin-pr-235 = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["parallel", "profiling"]
|
||||
features = ["parallel", "profiler_ui"]
|
||||
|
||||
[lints.clippy]
|
||||
needless_lifetimes = "allow"
|
||||
|
||||
@@ -34,12 +34,12 @@ default = ["dim3"]
|
||||
dim3 = []
|
||||
parallel = ["rapier/parallel", "num_cpus"]
|
||||
other-backends = ["physx", "physx-sys", "glam"]
|
||||
profiling = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
profiler_ui = ["dep:puffin_egui", "profiling/profile-with-puffin"]
|
||||
# See https://github.com/dimforge/rapier/issues/760.
|
||||
unstable-puffin-pr-235 = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["parallel", "other-backends", "profiling"]
|
||||
features = ["parallel", "other-backends", "profiler_ui"]
|
||||
|
||||
[lints.clippy]
|
||||
needless_lifetimes = "allow"
|
||||
|
||||
@@ -20,7 +20,7 @@ usvg = "0.14"
|
||||
|
||||
[dependencies.rapier_testbed2d]
|
||||
path = "../crates/rapier_testbed2d"
|
||||
features = ["profiling"]
|
||||
features = ["profiler_ui"]
|
||||
|
||||
[dependencies.rapier2d]
|
||||
path = "../crates/rapier2d"
|
||||
|
||||
@@ -16,6 +16,7 @@ mod convex_polygons2;
|
||||
mod damping2;
|
||||
mod debug_box_ball2;
|
||||
mod debug_compression2;
|
||||
mod debug_intersection2;
|
||||
mod debug_total_overlap2;
|
||||
mod debug_vertical_column2;
|
||||
mod drum2;
|
||||
@@ -99,6 +100,7 @@ pub fn main() {
|
||||
("Joint motor position", joint_motor_position2::init_world),
|
||||
("(Debug) box ball", debug_box_ball2::init_world),
|
||||
("(Debug) compression", debug_compression2::init_world),
|
||||
("(Debug) intersection", debug_intersection2::init_world),
|
||||
("(Debug) total overlap", debug_total_overlap2::init_world),
|
||||
(
|
||||
"(Debug) vertical column",
|
||||
|
||||
64
examples2d/debug_intersection2.rs
Normal file
64
examples2d/debug_intersection2.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use rapier2d::prelude::*;
|
||||
use rapier_testbed2d::Testbed;
|
||||
|
||||
pub fn init_world(testbed: &mut Testbed) {
|
||||
/*
|
||||
* World
|
||||
*/
|
||||
let mut bodies = RigidBodySet::new();
|
||||
let mut colliders = ColliderSet::new();
|
||||
let impulse_joints = ImpulseJointSet::new();
|
||||
let multibody_joints = MultibodyJointSet::new();
|
||||
|
||||
let rad = 1.0;
|
||||
let collider = ColliderBuilder::ball(rad);
|
||||
|
||||
let count = 100;
|
||||
for x in 0..count {
|
||||
for y in 0..count {
|
||||
let rigid_body = RigidBodyBuilder::fixed().translation(vector![
|
||||
(x as f32 - count as f32 / 2.0) * rad * 3.0,
|
||||
(y as f32 - count as f32 / 2.0) * rad * 3.0
|
||||
]);
|
||||
let handle = bodies.insert(rigid_body);
|
||||
colliders.insert_with_parent(collider.clone(), handle, &mut bodies);
|
||||
testbed.set_initial_body_color(
|
||||
handle,
|
||||
[
|
||||
x as f32 / count as f32,
|
||||
(count - y) as f32 / count as f32,
|
||||
0.5,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the testbed.
|
||||
*/
|
||||
testbed.set_world(bodies, colliders, impulse_joints, multibody_joints);
|
||||
testbed.look_at(point![0.0, 0.0], 50.0);
|
||||
|
||||
testbed.add_callback(move |graphics, physics, _, run| {
|
||||
let slow_time = run.timestep_id as f32 / 3.0;
|
||||
let intersection = physics.query_pipeline.intersection_with_shape(
|
||||
&physics.bodies,
|
||||
&physics.colliders,
|
||||
&Isometry::translation(slow_time.cos() * 10.0, slow_time.sin() * 10.0),
|
||||
&Ball::new(rad / 2.0),
|
||||
QueryFilter::default(),
|
||||
);
|
||||
|
||||
if let Some(graphics) = graphics {
|
||||
for (handle, _) in physics.bodies.iter() {
|
||||
graphics.set_body_color(handle, [0.5, 0.5, 0.5]);
|
||||
}
|
||||
if let Some(intersection) = intersection {
|
||||
let collider = physics.colliders.get(intersection).unwrap();
|
||||
let body_handle = collider.parent().unwrap();
|
||||
|
||||
graphics.set_body_color(body_handle, [1.0, 0.0, 0.0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -85,6 +85,7 @@ pub fn init_world(testbed: &mut Testbed) {
|
||||
|
||||
for k in 0..5 {
|
||||
let collider = ColliderBuilder::trimesh(vertices.clone(), indices.clone())
|
||||
.unwrap()
|
||||
.contact_skin(0.2);
|
||||
let rigid_body = RigidBodyBuilder::dynamic()
|
||||
.translation(vector![ith as f32 * 8.0 - 20.0, 20.0 + k as f32 * 11.0])
|
||||
|
||||
@@ -23,7 +23,7 @@ bincode = "1"
|
||||
|
||||
[dependencies.rapier_testbed3d]
|
||||
path = "../crates/rapier_testbed3d"
|
||||
features = ["profiling"]
|
||||
features = ["profiler_ui"]
|
||||
|
||||
[dependencies.rapier3d]
|
||||
path = "../crates/rapier3d"
|
||||
|
||||
@@ -48,7 +48,7 @@ pub fn init_world(testbed: &mut Testbed) {
|
||||
|
||||
let rigid_body = RigidBodyBuilder::fixed().translation(vector![0.0, 0.0, 0.0]);
|
||||
let handle = bodies.insert(rigid_body);
|
||||
let collider = ColliderBuilder::trimesh(vtx, idx);
|
||||
let collider = ColliderBuilder::trimesh(vtx, idx).expect("Could not create trimesh collider.");
|
||||
colliders.insert_with_parent(collider, handle, &mut bodies);
|
||||
testbed.set_initial_body_color(handle, [0.3, 0.3, 0.3]);
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ pub fn do_init_world(testbed: &mut Testbed, use_convex_decomposition: bool) {
|
||||
} else {
|
||||
// SharedShape::trimesh(vertices, indices)
|
||||
SharedShape::trimesh_with_flags(vertices, indices, TriMeshFlags::FIX_INTERNAL_EDGES)
|
||||
.unwrap()
|
||||
};
|
||||
shapes.push(decomposed_shape);
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ pub fn init_world(testbed: &mut Testbed) {
|
||||
vertices,
|
||||
indices,
|
||||
TriMeshFlags::MERGE_DUPLICATE_VERTICES,
|
||||
);
|
||||
)
|
||||
.unwrap();
|
||||
colliders.insert_with_parent(collider, handle, &mut bodies);
|
||||
|
||||
/*
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::pipeline::{ActiveEvents, ActiveHooks};
|
||||
use crate::prelude::ColliderEnabled;
|
||||
use na::Unit;
|
||||
use parry::bounding_volume::{Aabb, BoundingVolume};
|
||||
use parry::shape::{Shape, TriMeshFlags};
|
||||
use parry::shape::{Shape, TriMeshBuilderError, TriMeshFlags};
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
use crate::geometry::HeightFieldFlags;
|
||||
@@ -685,8 +685,11 @@ impl ColliderBuilder {
|
||||
}
|
||||
|
||||
/// Initializes a collider builder with a triangle mesh shape defined by its vertex and index buffers.
|
||||
pub fn trimesh(vertices: Vec<Point<Real>>, indices: Vec<[u32; 3]>) -> Self {
|
||||
Self::new(SharedShape::trimesh(vertices, indices))
|
||||
pub fn trimesh(
|
||||
vertices: Vec<Point<Real>>,
|
||||
indices: Vec<[u32; 3]>,
|
||||
) -> Result<Self, TriMeshBuilderError> {
|
||||
Ok(Self::new(SharedShape::trimesh(vertices, indices)?))
|
||||
}
|
||||
|
||||
/// Initializes a collider builder with a triangle mesh shape defined by its vertex and index buffers and
|
||||
@@ -695,8 +698,10 @@ impl ColliderBuilder {
|
||||
vertices: Vec<Point<Real>>,
|
||||
indices: Vec<[u32; 3]>,
|
||||
flags: TriMeshFlags,
|
||||
) -> Self {
|
||||
Self::new(SharedShape::trimesh_with_flags(vertices, indices, flags))
|
||||
) -> Result<Self, TriMeshBuilderError> {
|
||||
Ok(Self::new(SharedShape::trimesh_with_flags(
|
||||
vertices, indices, flags,
|
||||
)?))
|
||||
}
|
||||
|
||||
/// Initializes a collider builder with a shape converted from the given triangle mesh index
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use parry::bounding_volume;
|
||||
use parry::math::{Isometry, Point, Real};
|
||||
use parry::shape::{Cuboid, SharedShape, TriMeshFlags};
|
||||
use parry::shape::{Cuboid, SharedShape, TriMeshBuilderError, TriMeshFlags};
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
use parry::transformation::vhacd::VHACDParameters;
|
||||
@@ -17,6 +17,9 @@ pub enum MeshConverterError {
|
||||
/// The convex hull calculation carried out by the [`MeshConverter::ConvexHull`] failed.
|
||||
#[error("convex-hull computation failed")]
|
||||
ConvexHullFailed,
|
||||
/// The TriMesh building failed.
|
||||
#[error("TriMesh building failed")]
|
||||
TriMeshBuilderError(TriMeshBuilderError),
|
||||
}
|
||||
|
||||
/// Determines how meshes (generally when loaded from a file) are converted into Rapier colliders.
|
||||
@@ -61,9 +64,11 @@ impl MeshConverter {
|
||||
) -> Result<(SharedShape, Isometry<Real>), MeshConverterError> {
|
||||
let mut transform = Isometry::identity();
|
||||
let shape = match self {
|
||||
MeshConverter::TriMesh => SharedShape::trimesh(vertices, indices),
|
||||
MeshConverter::TriMesh => SharedShape::trimesh(vertices, indices)
|
||||
.map_err(MeshConverterError::TriMeshBuilderError)?,
|
||||
MeshConverter::TriMeshWithFlags(flags) => {
|
||||
SharedShape::trimesh_with_flags(vertices, indices, *flags)
|
||||
.map_err(MeshConverterError::TriMeshBuilderError)?
|
||||
}
|
||||
MeshConverter::Obb => {
|
||||
let (pose, cuboid) = parry::utils::obb(&vertices);
|
||||
|
||||
@@ -480,20 +480,17 @@ impl QueryPipeline {
|
||||
filter: QueryFilter,
|
||||
) -> Option<ColliderHandle> {
|
||||
let pipeline_shape = self.as_composite_shape(bodies, colliders, filter);
|
||||
#[allow(deprecated)]
|
||||
// TODO: replace this with IntersectionCompositeShapeShapeVisitor when it
|
||||
// can return the shape part id.
|
||||
let mut visitor =
|
||||
parry::query::details::IntersectionCompositeShapeShapeBestFirstVisitor::new(
|
||||
&*self.query_dispatcher,
|
||||
shape_pos,
|
||||
&pipeline_shape,
|
||||
shape,
|
||||
);
|
||||
let mut visitor = parry::query::details::IntersectionCompositeShapeShapeVisitor::new(
|
||||
&*self.query_dispatcher,
|
||||
shape_pos,
|
||||
&pipeline_shape,
|
||||
shape,
|
||||
);
|
||||
|
||||
self.qbvh
|
||||
.traverse_best_first(&mut visitor)
|
||||
.map(|h| (h.1 .0))
|
||||
self.qbvh.traverse_depth_first(&mut visitor);
|
||||
visitor.found_intersection
|
||||
}
|
||||
|
||||
/// Find the projection of a point on the closest collider.
|
||||
|
||||
@@ -249,7 +249,7 @@ impl TestbedApp {
|
||||
}
|
||||
|
||||
pub fn run_with_init(mut self, mut init: impl FnMut(&mut App)) {
|
||||
#[cfg(feature = "profiling")]
|
||||
#[cfg(feature = "profiler_ui")]
|
||||
puffin_egui::puffin::set_scopes_on(true);
|
||||
|
||||
let mut args = env::args();
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn update_ui(
|
||||
harness: &mut Harness,
|
||||
debug_render: &mut DebugRenderPipelineResource,
|
||||
) {
|
||||
#[cfg(feature = "profiling")]
|
||||
#[cfg(feature = "profiler_ui")]
|
||||
{
|
||||
let window = egui::Window::new("Profiling");
|
||||
let window = window.default_open(false);
|
||||
|
||||
Reference in New Issue
Block a user