Files
rapier/examples3d/dynamic_trimesh3.rs
2024-04-30 23:10:46 +02:00

147 lines
5.5 KiB
Rust

use obj::raw::object::Polygon;
use rapier3d::parry::bounding_volume;
use rapier3d::prelude::*;
use rapier_testbed3d::Testbed;
use std::fs::File;
use std::io::BufReader;
pub fn init_world(testbed: &mut Testbed) {
do_init_world(testbed, false);
}
pub fn do_init_world(testbed: &mut Testbed, use_convex_decomposition: bool) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let impulse_joints = ImpulseJointSet::new();
let multibody_joints = MultibodyJointSet::new();
/*
* Ground
*/
let ground_size = 50.0;
let ground_height = 0.1;
//// OPTION 1: floor made of a single big box.
// let rigid_body = RigidBodyBuilder::fixed().translation(vector![0.0, -ground_height, 0.0]);
// let handle = bodies.insert(rigid_body);
// let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size);
// colliders.insert_with_parent(collider, handle, &mut bodies);
//// OPTION 2: floor made of a wavy mesh.
let nsubdivs = 100;
let heights = DMatrix::from_fn(nsubdivs + 1, nsubdivs + 1, |i, j| {
-(i as f32 * 40.0 / (nsubdivs as f32) / 2.0).cos()
- (j as f32 * 40.0 / (nsubdivs as f32) / 2.0).cos()
});
let heightfield = HeightField::new(heights, vector![100.0, 2.0, 100.0]);
let mut trimesh = TriMesh::from(heightfield);
trimesh.set_flags(TriMeshFlags::FIX_INTERNAL_EDGES);
colliders.insert(ColliderBuilder::new(SharedShape::new(trimesh.clone())));
/*
* 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_y = 8.0f32;
let shift_xz = 9.0f32;
for (igeom, obj_path) in geoms.into_iter().enumerate() {
let deltas = Isometry::identity();
let mut shapes = Vec::new();
println!("Parsing and decomposing: {}", obj_path);
let input = BufReader::new(File::open(obj_path).unwrap());
if let Ok(model) = obj::raw::parse_obj(input) {
let mut vertices: Vec<_> = model
.positions
.iter()
.map(|v| point![v.0, v.1, v.2])
.collect();
let indices: Vec<_> = model
.polygons
.into_iter()
.flat_map(|p| match p {
Polygon::P(idx) => idx.into_iter(),
Polygon::PT(idx) => Vec::from_iter(idx.into_iter().map(|i| i.0)).into_iter(),
Polygon::PN(idx) => Vec::from_iter(idx.into_iter().map(|i| i.0)).into_iter(),
Polygon::PTN(idx) => Vec::from_iter(idx.into_iter().map(|i| i.0)).into_iter(),
})
.collect();
// Compute the size of the model, to scale it and have similar size for everything.
let aabb = bounding_volume::details::point_cloud_aabb(&deltas, &vertices);
let center = aabb.center();
let diag = (aabb.maxs - aabb.mins).norm();
vertices
.iter_mut()
.for_each(|p| *p = (*p - center.coords) * 10.0 / diag);
let indices: Vec<_> = indices
.chunks(3)
.map(|idx| [idx[0] as u32, idx[1] as u32, idx[2] as u32])
.collect();
let decomposed_shape = if use_convex_decomposition {
SharedShape::convex_decomposition(&vertices, &indices)
} else {
// SharedShape::trimesh(vertices, indices)
SharedShape::trimesh_with_flags(vertices, indices, TriMeshFlags::FIX_INTERNAL_EDGES)
};
shapes.push(decomposed_shape);
// let compound = SharedShape::compound(compound_parts);
for k in 1..num_duplications + 1 {
let x =
(igeom % width) as f32 * shift_xz - num_duplications as f32 * shift_xz / 2.0;
let y = (igeom / width) as f32 * shift_y + 7.0;
let z = k as f32 * shift_xz - num_duplications as f32 * shift_xz / 2.0;
let body = RigidBodyBuilder::dynamic().translation(vector![x, y, z]);
let handle = bodies.insert(body);
for shape in &shapes {
let collider = ColliderBuilder::new(shape.clone()).contact_skin(0.1);
colliders.insert_with_parent(collider, handle, &mut bodies);
}
}
}
}
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, impulse_joints, multibody_joints);
testbed.look_at(point![100.0, 100.0, 100.0], Point::origin());
}
fn models() -> Vec<String> {
vec![
"assets/3d/camel_decimated.obj".to_string(),
"assets/3d/chair.obj".to_string(),
"assets/3d/cup_decimated.obj".to_string(),
"assets/3d/dilo_decimated.obj".to_string(),
"assets/3d/tstTorusModel2.obj".to_string(),
"assets/3d/feline_decimated.obj".to_string(),
"assets/3d/genus3_decimated.obj".to_string(),
// "assets/3d/hand2_decimated.obj".to_string(),
// "assets/3d/hand_decimated.obj".to_string(),
"assets/3d/hornbug.obj".to_string(),
"assets/3d/tstTorusModel.obj".to_string(),
"assets/3d/octopus_decimated.obj".to_string(),
"assets/3d/rabbit_decimated.obj".to_string(),
"assets/3d/rust_logo_simplified.obj".to_string(),
"assets/3d/screwdriver_decimated.obj".to_string(),
"assets/3d/table.obj".to_string(),
"assets/3d/tstTorusModel3.obj".to_string(),
]
}