aboutsummaryrefslogtreecommitdiff
path: root/examples3d/convex_decomposition3.rs
diff options
context:
space:
mode:
authorCrozet Sébastien <developer@crozet.re>2021-01-20 15:15:03 +0100
committerCrozet Sébastien <developer@crozet.re>2021-01-20 15:15:33 +0100
commite2006599a8fa90090393ff4fed326ee78fd7c0b7 (patch)
treed7a016f7197095b5984ab0651ea2650959af421a /examples3d/convex_decomposition3.rs
parent87b56c38b6e98ec6420ef4a3026fb5093c40185a (diff)
downloadrapier-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.rs134
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(&params, 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(),
+ ]
+}