diff options
| author | Crozet Sébastien <developer@crozet.re> | 2021-01-20 15:15:03 +0100 |
|---|---|---|
| committer | Crozet Sébastien <developer@crozet.re> | 2021-01-20 15:15:33 +0100 |
| commit | e2006599a8fa90090393ff4fed326ee78fd7c0b7 (patch) | |
| tree | d7a016f7197095b5984ab0651ea2650959af421a /examples3d/convex_decomposition3.rs | |
| parent | 87b56c38b6e98ec6420ef4a3026fb5093c40185a (diff) | |
| download | rapier-e2006599a8fa90090393ff4fed326ee78fd7c0b7.tar.gz rapier-e2006599a8fa90090393ff4fed326ee78fd7c0b7.tar.bz2 rapier-e2006599a8fa90090393ff4fed326ee78fd7c0b7.zip | |
Add 3D convex decomposition example.
Diffstat (limited to 'examples3d/convex_decomposition3.rs')
| -rw-r--r-- | examples3d/convex_decomposition3.rs | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/examples3d/convex_decomposition3.rs b/examples3d/convex_decomposition3.rs new file mode 100644 index 0000000..2e35f43 --- /dev/null +++ b/examples3d/convex_decomposition3.rs @@ -0,0 +1,134 @@ +use kiss3d::loader::obj; +use na::{Isometry3, Point3, Translation3}; +use rapier3d::cdl::bounding_volume::{self, BoundingVolume}; +use rapier3d::cdl::transformation::vhacd::{VHACDParameters, VHACD}; +use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet}; +use rapier3d::geometry::{ColliderBuilder, ColliderSet, ColliderShape}; +use rapier_testbed3d::Testbed; +use std::path::Path; + +/* + * NOTE: The `r` macro is only here to convert from f64 to the `N` scalar type. + * This simplifies experimentation with various scalar types (f32, fixed-point numbers, etc.) + */ +pub fn init_world(testbed: &mut Testbed) { + /* + * World + */ + let mut bodies = RigidBodySet::new(); + let mut colliders = ColliderSet::new(); + let joints = JointSet::new(); + + /* + * Ground + */ + let ground_size = 50.0; + let ground_height = 0.1; + + let rigid_body = RigidBodyBuilder::new_static() + .translation(0.0, -ground_height, 0.0) + .build(); + let handle = bodies.insert(rigid_body); + let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size).build(); + colliders.insert(collider, handle, &mut bodies); + + /* + * Create the convex decompositions. + */ + let geoms = models(); + let ngeoms = geoms.len(); + let width = (ngeoms as f32).sqrt() as usize; + let num_duplications = 4; + let shift = 5.0f32; + + for (igeom, obj_path) in geoms.into_iter().enumerate() { + let deltas = na::one(); + let mtl_path = Path::new(""); + + let mut compound_parts = Vec::new(); + println!("Parsing and decomposing: {}", obj_path); + let obj = obj::parse_file(&Path::new(&obj_path), &mtl_path, ""); + + if let Ok(model) = obj { + let meshes: Vec<_> = model + .into_iter() + .map(|mesh| mesh.1.to_trimesh().unwrap()) + .collect(); + + // Compute the size of the model, to scale it and have similar size for everything. + let mut aabb = + bounding_volume::details::point_cloud_aabb(&deltas, &meshes[0].coords[..]); + + for mesh in meshes[1..].iter() { + aabb.merge(&bounding_volume::details::point_cloud_aabb( + &deltas, + &mesh.coords[..], + )); + } + + let center = aabb.center().coords; + let diag = (aabb.maxs - aabb.mins).norm(); + + for mut trimesh in meshes.into_iter() { + trimesh.translate_by(&Translation3::from(-center)); + trimesh.scale_by_scalar(6.0 / diag); + + let params = VHACDParameters::default(); + let vertices = &trimesh.coords; + let indices = &trimesh.indices.unwrap_unified(); + let vhacd = VHACD::decompose(¶ms, vertices, indices, true); + + for (vertices, indices) in vhacd.compute_exact_convex_hulls(vertices, indices) { + if let Some(convex) = ColliderShape::convex_mesh(vertices, &indices) { + compound_parts.push(convex); + } + } + } + + // let compound = ColliderShape::compound(compound_parts); + + for k in 1..num_duplications + 1 { + let x = (igeom % width) as f32 * shift; + let y = (igeom / width) as f32 * shift + 4.0; + let z = k as f32 * shift; + + let body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); + let handle = bodies.insert(body); + + for part in &compound_parts { + let collider = ColliderBuilder::new(part.clone()).build(); + colliders.insert(collider, handle, &mut bodies); + } + } + } + } + + /* + * Set up the testbed. + */ + testbed.set_world(bodies, colliders, joints); + testbed.look_at(Point3::new(100.0, 100.0, 100.0), Point3::origin()); +} + +fn models() -> Vec<String> { + vec![ + "media/models/camel_decimated.obj".to_string(), + "media/models/chair.obj".to_string(), + "media/models/cup_decimated.obj".to_string(), + "media/models/dilo_decimated.obj".to_string(), + "media/models/feline_decimated.obj".to_string(), + "media/models/genus3_decimated.obj".to_string(), + "media/models/hand2_decimated.obj".to_string(), + "media/models/hand_decimated.obj".to_string(), + "media/models/hornbug.obj".to_string(), + "media/models/octopus_decimated.obj".to_string(), + "media/models/rabbit_decimated.obj".to_string(), + "media/models/rust_logo.obj".to_string(), + "media/models/rust_logo_simplified.obj".to_string(), + "media/models/screwdriver_decimated.obj".to_string(), + "media/models/table.obj".to_string(), + "media/models/tstTorusModel.obj".to_string(), + // "media/models/tstTorusModel2.obj".to_string(), + // "media/models/tstTorusModel3.obj".to_string(), + ] +} |
