diff options
Diffstat (limited to 'examples3d')
30 files changed, 38188 insertions, 239 deletions
diff --git a/examples3d/Cargo.toml b/examples3d/Cargo.toml index 5362554..3f1d3f0 100644 --- a/examples3d/Cargo.toml +++ b/examples3d/Cargo.toml @@ -14,7 +14,8 @@ enhanced-determinism = [ "rapier3d/enhanced-determinism" ] [dependencies] rand = "0.7" Inflector = "0.11" -nalgebra = "0.23" +nalgebra = "0.24" +kiss3d = "0.29" [dependencies.rapier_testbed3d] path = "../build/rapier_testbed3d" @@ -25,3 +26,7 @@ path = "../build/rapier3d" [[bin]] name = "all_examples3" path = "./all_examples3.rs" + +[[bin]] +name = "harness_capsules3" +path = "./harness_capsules3.rs" diff --git a/examples3d/all_examples3.rs b/examples3d/all_examples3.rs index 4bc15a8..9cbf4c3 100644 --- a/examples3d/all_examples3.rs +++ b/examples3d/all_examples3.rs @@ -12,6 +12,8 @@ use std::cmp::Ordering; mod collision_groups3; mod compound3; +mod convex_decomposition3; +mod convex_polyhedron3; mod damping3; mod debug_add_remove_collider3; mod debug_boxes3; @@ -31,7 +33,6 @@ mod platform3; mod primitives3; mod restitution3; mod sensor3; -mod stacks3; mod trimesh3; fn demo_name_from_command_line() -> Option<String> { @@ -75,6 +76,8 @@ pub fn main() { ("Primitives", primitives3::init_world), ("Collision groups", collision_groups3::init_world), ("Compound", compound3::init_world), + ("Convex decomposition", convex_decomposition3::init_world), + ("Convex polyhedron", convex_polyhedron3::init_world), ("Damping", damping3::init_world), ("Domino", domino3::init_world), ("Heightfield", heightfield3::init_world), @@ -82,9 +85,8 @@ pub fn main() { ("Locked rotations", locked_rotations3::init_world), ("Platform", platform3::init_world), ("Restitution", restitution3::init_world), - ("Stacks", stacks3::init_world), ("Sensor", sensor3::init_world), - ("Trimesh", trimesh3::init_world), + ("TriMesh", trimesh3::init_world), ("Keva tower", keva3::init_world), ( "(Debug) add/rm collider", diff --git a/examples3d/compound3.rs b/examples3d/compound3.rs index 34a654d..4168fe9 100644 --- a/examples3d/compound3.rs +++ b/examples3d/compound3.rs @@ -1,6 +1,6 @@ -use na::Point3; +use na::{Isometry3, Point3}; use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet}; -use rapier3d::geometry::{ColliderBuilder, ColliderSet}; +use rapier3d::geometry::{ColliderBuilder, ColliderSet, SharedShape}; use rapier_testbed3d::Testbed; pub fn init_world(testbed: &mut Testbed) { @@ -28,6 +28,7 @@ pub fn init_world(testbed: &mut Testbed) { * Create the cubes */ let num = 8; + let numy = 15; let rad = 0.2; let shift = rad * 4.0 + rad; @@ -37,7 +38,7 @@ pub fn init_world(testbed: &mut Testbed) { let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5; - for j in 0usize..15 { + for j in 0usize..numy { for i in 0..num { for k in 0usize..num { let x = i as f32 * shift * 5.0 - centerx + offset; @@ -47,16 +48,39 @@ pub fn init_world(testbed: &mut Testbed) { // Build the rigid body. let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let handle = bodies.insert(rigid_body); - let collider1 = ColliderBuilder::cuboid(rad * 10.0, rad, rad).build(); - let collider2 = ColliderBuilder::cuboid(rad, rad * 10.0, rad) - .translation(rad * 10.0, rad * 10.0, 0.0) - .build(); - let collider3 = ColliderBuilder::cuboid(rad, rad * 10.0, rad) - .translation(-rad * 10.0, rad * 10.0, 0.0) - .build(); - colliders.insert(collider1, handle, &mut bodies); - colliders.insert(collider2, handle, &mut bodies); - colliders.insert(collider3, handle, &mut bodies); + + // First option: attach several colliders to a single rigid-body. + if j < numy / 2 { + let collider1 = ColliderBuilder::cuboid(rad * 10.0, rad, rad).build(); + let collider2 = ColliderBuilder::cuboid(rad, rad * 10.0, rad) + .translation(rad * 10.0, rad * 10.0, 0.0) + .build(); + let collider3 = ColliderBuilder::cuboid(rad, rad * 10.0, rad) + .translation(-rad * 10.0, rad * 10.0, 0.0) + .build(); + colliders.insert(collider1, handle, &mut bodies); + colliders.insert(collider2, handle, &mut bodies); + colliders.insert(collider3, handle, &mut bodies); + } else { + // Second option: create a compound shape and attach it to a single collider. + let shapes = vec![ + ( + Isometry3::identity(), + SharedShape::cuboid(rad * 10.0, rad, rad), + ), + ( + Isometry3::translation(rad * 10.0, rad * 10.0, 0.0), + SharedShape::cuboid(rad, rad * 10.0, rad), + ), + ( + Isometry3::translation(-rad * 10.0, rad * 10.0, 0.0), + SharedShape::cuboid(rad, rad * 10.0, rad), + ), + ]; + + let collider = ColliderBuilder::compound(shapes).build(); + colliders.insert(collider, handle, &mut bodies); + } } } diff --git a/examples3d/convex_decomposition3.rs b/examples3d/convex_decomposition3.rs new file mode 100644 index 0000000..e175f57 --- /dev/null +++ b/examples3d/convex_decomposition3.rs @@ -0,0 +1,133 @@ +use kiss3d::loader::obj; +use na::{Point3, Translation3}; +use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet}; +use rapier3d::geometry::{ColliderBuilder, ColliderSet, SharedShape}; +use rapier3d::parry::bounding_volume::{self, BoundingVolume}; +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 shapes = 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 vertices = trimesh.coords; + let indices: Vec<_> = trimesh + .indices + .unwrap_unified() + .into_iter() + .map(|idx| [idx.x, idx.y, idx.z]) + .collect(); + + let decomposed_shape = SharedShape::convex_decomposition(&vertices, &indices); + shapes.push(decomposed_shape); + } + + // let compound = SharedShape::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 shape in &shapes { + let collider = ColliderBuilder::new(shape.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(), + ] +} diff --git a/examples3d/convex_polyhedron3.rs b/examples3d/convex_polyhedron3.rs new file mode 100644 index 0000000..3cbcbf1 --- /dev/null +++ b/examples3d/convex_polyhedron3.rs @@ -0,0 +1,78 @@ +use na::Point3; +use rand::distributions::{Distribution, Standard}; +use rand::{rngs::StdRng, SeedableRng}; +use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet}; +use rapier3d::geometry::{ColliderBuilder, ColliderSet}; +use rapier_testbed3d::Testbed; + +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 = 40.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 polyhedra + */ + let num = 5; + let scale = 2.0; + let border_rad = 0.1; + + let shift = border_rad * 2.0 + scale; + let centerx = shift * (num / 2) as f32; + let centery = shift / 2.0; + let centerz = shift * (num / 2) as f32; + + let mut rng = StdRng::seed_from_u64(0); + let distribution = Standard; + + for j in 0usize..25 { + for i in 0..num { + for k in 0usize..num { + let x = i as f32 * shift - centerx; + let y = j as f32 * shift + centery + 3.0; + let z = k as f32 * shift - centerz; + + let mut points = Vec::new(); + for _ in 0..10 { + let pt: Point3<f32> = distribution.sample(&mut rng); + points.push(pt * scale); + } + + // Build the rigid body. + let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); + let handle = bodies.insert(rigid_body); + let collider = ColliderBuilder::round_convex_hull(&points, border_rad) + .unwrap() + .build(); + colliders.insert(collider, handle, &mut bodies); + } + } + } + + /* + * Set up the testbed. + */ + testbed.set_world(bodies, colliders, joints); + testbed.look_at(Point3::new(30.0, 30.0, 30.0), Point3::origin()); +} + +fn main() { + let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]); + testbed.run() +} diff --git a/examples3d/debug_trimesh3.rs b/examples3d/debug_trimesh3.rs index 0d0b276..186e673 100644 --- a/examples3d/debug_trimesh3.rs +++ b/examples3d/debug_trimesh3.rs @@ -24,18 +24,18 @@ pub fn init_world(testbed: &mut Testbed) { Point3::new(-width, -width, width), ]; let idx = vec![ - Point3::new(0, 1, 2), - Point3::new(0, 2, 3), - Point3::new(4, 5, 6), - Point3::new(4, 6, 7), - Point3::new(0, 4, 7), - Point3::new(0, 7, 3), - Point3::new(1, 5, 6), - Point3::new(1, 6, 2), - Point3::new(3, 2, 7), - Point3::new(2, 6, 7), - Point3::new(0, 1, 5), - Point3::new(0, 5, 4), + [0, 1, 2], + [0, 2, 3], + [4, 5, 6], + [4, 6, 7], + [0, 4, 7], + [0, 7, 3], + [1, 5, 6], + [1, 6, 2], + [3, 2, 7], + [2, 6, 7], + [0, 1, 5], + [0, 5, 4], ]; // Dynamic box rigid body. diff --git a/examples3d/harness_capsules3.rs b/examples3d/harness_capsules3.rs new file mode 100644 index 0000000..4632811 --- /dev/null +++ b/examples3d/harness_capsules3.rs @@ -0,0 +1,72 @@ +extern crate nalgebra as na; + +use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet}; +use rapier3d::geometry::{ColliderBuilder, ColliderSet}; +use rapier_testbed3d::harness::Harness; + +pub fn init_world(harness: &mut Harness) { + /* + * World + */ + let mut bodies = RigidBodySet::new(); + let mut colliders = ColliderSet::new(); + let joints = JointSet::new(); + + /* + * Ground + */ + let ground_size = 200.1; + 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 cubes + */ + let num = 8; + let rad = 1.0; + + let shift = rad * 2.0 + rad; + let shifty = rad * 4.0; + let centerx = shift * (num / 2) as f32; + let centery = shift / 2.0; + let centerz = shift * (num / 2) as f32; + + let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5; + + for j in 0usize..47 { + for i in 0..num { + for k in 0usize..num { + let x = i as f32 * shift - centerx + offset; + let y = j as f32 * shifty + centery + 3.0; + let z = k as f32 * shift - centerz + offset; + + // Build the rigid body. + let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); + let handle = bodies.insert(rigid_body); + let collider = ColliderBuilder::capsule_y(rad, rad).build(); + colliders.insert(collider, handle, &mut bodies); + } + } + + offset -= 0.05 * rad * (num as f32 - 1.0); + } + + /* + * Set up the harness. + */ + harness.set_world(bodies, colliders, joints); +} + +fn main() { + let harness = &mut Harness::new_empty(); + init_world(harness); + harness.set_max_steps(10000); + harness.run(); + println!("{}", harness.state.timestep_id); +} diff --git a/examples3d/heightfield3.rs b/examples3d/heightfield3.rs index 6558614..f603bb1 100644 --- a/examples3d/heightfield3.rs +++ b/examples3d/heightfield3.rs @@ -1,6 +1,6 @@ -use na::{ComplexField, DMatrix, Point3, Vector3}; +use na::{ComplexField, DMatrix, Isometry3, Point3, Vector3}; use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet}; -use rapier3d::geometry::{ColliderBuilder, ColliderSet}; +use rapier3d::geometry::{ColliderBuilder, ColliderSet, SharedShape}; use rapier_testbed3d::Testbed; pub fn init_world(testbed: &mut Testbed) { @@ -27,7 +27,7 @@ pub fn init_world(testbed: &mut Testbed) { // NOTE: make sure we use the sin/cos from simba to ensure // cross-platform determinism of the example when the // enhanced_determinism feature is enabled. - <f32 as ComplexField>::sin(x) + <f32 as ComplexField>::cos(z) + ComplexField::sin(x) + ComplexField::cos(z) } }); @@ -58,14 +58,32 @@ pub fn init_world(testbed: &mut Testbed) { let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build(); let handle = bodies.insert(rigid_body); - let collider = match j % 5 { + let collider = match j % 6 { 0 => ColliderBuilder::cuboid(rad, rad, rad).build(), 1 => ColliderBuilder::ball(rad).build(), // Rounded cylinders are much more efficient that cylinder, even if the // rounding margin is small. 2 => ColliderBuilder::round_cylinder(rad, rad, rad / 10.0).build(), 3 => ColliderBuilder::cone(rad, rad).build(), - _ => ColliderBuilder::capsule_y(rad, rad).build(), + 4 => ColliderBuilder::capsule_y(rad, rad).build(), + _ => { + let shapes = vec![ + ( + Isometry3::identity(), + SharedShape::cuboid(rad, rad / 2.0, rad / 2.0), + ), + ( + Isometry3::translation(rad, 0.0, 0.0), + SharedShape::cuboid(rad / 2.0, rad, rad / 2.0), + ), + ( + Isometry3::translation(-rad, 0.0, 0.0), + SharedShape::cuboid(rad / 2.0, rad, rad / 2.0), + ), + ]; + + ColliderBuilder::compound(shapes).build() + } }; colliders.insert(collider, handle, &mut bodies); diff --git a/examples3d/joints3.rs b/examples3d/joints3.rs index dd56958..d777655 100644 --- a/examples3d/joints3.rs +++ b/examples3d/joints3.rs @@ -196,16 +196,16 @@ fn create_ball_joints( }; let rigid_body = RigidBodyBuilder::new(status) - .translation(fk * shift, 0.0, fi * shift) + .translation(fk * shift, 0.0, fi * shift * 2.0) .build(); let child_handle = bodies.insert(rigid_body); - let collider = ColliderBuilder::ball(rad).build(); + let collider = ColliderBuilder::capsule_z(rad * 1.25, rad).build(); colliders.insert(collider, child_handle, bodies); // Vertical joint. if i > 0 { let parent_handle = *body_handles.last().unwrap(); - let joint = BallJoint::new(Point3::origin(), Point3::new(0.0, 0.0, -shift)); + let joint = BallJoint::new(Point3::origin(), Point3::new(0.0, 0.0, -shift * 2.0)); joints.insert(bodies, parent_handle, child_handle, joint); } diff --git a/examples3d/locked_rotations3.rs b/examples3d/locked_rotations3.rs index a39895a..c626925 100644 --- a/examples3d/locked_rotations3.rs +++ b/examples3d/locked_rotations3.rs @@ -33,7 +33,7 @@ pub fn init_world(testbed: &mut Testbed) { let rigid_body = RigidBodyBuilder::new_dynamic() .translation(0.0, 3.0, 0.0) .lock_translations() - .principal_angular_inertia(Vector3::zeros(), Vector3::new(true, false, false)) + .restrict_rotations(true, false, false) .build(); let handle = bodies.insert(rigid_body); let collider = ColliderBuilder::cuboid(0.2, 0.6, 2.0).build(); @@ -50,6 +50,8 @@ pub fn init_world(testbed: &mut Testbed) { let handle = bodies.insert(rigid_body); let collider = ColliderBuilder::capsule_y(0.6, 0.4).build(); colliders.insert(collider, handle, &mut bodies); + let collider = ColliderBuilder::capsule_x(0.6, 0.4).build(); + colliders.insert(collider, handle, &mut bodies); /* * Set up the testbed. diff --git a/examples3d/media/models/camel_decimated.obj b/examples3d/media/models/camel_decimated.obj new file mode 100644 index 0000000..f63ad44 --- /dev/null +++ b/examples3d/media/models/camel_decimated.obj @@ -0,0 +1,3004 @@ +# 1002 +# 2000 +v -0.050388 -0.350210 0.022403 +v -0.048678 -0.130496 0.060662 +v -0.044669 0.243192 0.277197 +v 0.078833 0.022370 -0.015607 +v 0.050680 0.007189 -0.013118 +v 0.084614 0.010521 0.031128 +v 0.050878 -0.022492 0.024685 +v 0.033090 -0.371687 -0.424968 +v 0.075191 0.093570 -0.253683 +v -0.051764 -0.014380 0.025295 +v -0.076064 -0.014582 0.026880 +v -0.031546 0.449722 0.269074 +v -0.024081 0.414657 0.270146 +v -0.069569 -0.083204 -0.365774 +v -0.055686 0.107869 -0.415909 +v -0.117478 0.179205 -0.201737 +v -0.023915 0.010133 0.095191 +v -0.048404 0.019126 0.107904 +v -0.002358 0.241309 0.365850 +v -0.025664 0.241325 0.358793 +v -0.008902 0.354662 0.366952 +v -0.039608 0.428512 0.450664 +v -0.016938 0.454796 0.438974 +v -0.036921 0.417415 0.391918 +v -0.032057 0.406409 0.423741 +v 0.000371 0.376797 0.488460 +v -0.007894 0.264235 0.260070 +v -0.020176 0.325239 0.278125 +v -0.015544 0.192099 -0.409741 +v -0.027591 0.141760 -0.418868 +v -0.016752 0.124681 -0.410712 +v -0.009241 0.091347 -0.394700 +v -0.039021 -0.425507 -0.397227 +v -0.024504 -0.321668 -0.451027 +v -0.030920 -0.241836 -0.442142 +v -0.047113 -0.204467 -0.443042 +v -0.025112 -0.166981 -0.434575 +v -0.069671 -0.025295 -0.311591 +v -0.083044 -0.020125 -0.307680 +v -0.014762 -0.193705 -0.483566 +v -0.088726 -0.452177 -0.418307 +v -0.084037 -0.454761 0.065889 +v -0.047782 -0.361093 0.015777 +v -0.068511 -0.437601 0.024318 +v -0.049368 -0.453551 0.038600 +v -0.051189 -0.390765 0.051127 +v -0.043158 -0.450001 0.076305 +v 0.000463 -0.262988 0.012976 +v -0.014434 -0.234685 0.045387 +v -0.016971 -0.213612 0.039432 +v -0.007452 -0.002182 -0.445485 +v -0.017204 0.214252 -0.407657 +v -0.003770 0.161810 -0.432425 +v -0.004279 0.187997 -0.437487 +v 0.007123 0.343968 0.065505 +v 0.033276 0.333237 0.051940 +v -0.012411 -0.211216 0.007054 +v -0.042643 -0.117167 0.009132 +v -0.124326 0.062298 0.048544 +v -0.130689 0.102265 0.080301 +v -0.094676 0.026984 0.040359 +v -0.102167 0.029167 0.062763 +v -0.068921 -0.086827 0.012183 +v -0.004079 0.414057 -0.078553 +v 0.003605 0.388842 -0.049820 +v -0.028269 0.330714 -0.003973 +v -0.060655 0.305875 -0.004726 +v -0.079765 0.297511 -0.041093 +v -0.069576 0.345626 -0.078772 +v -0.098494 0.299670 -0.111757 +v -0.141738 0.216390 -0.138374 +v -0.145235 0.117310 -0.139099 +v -0.126093 0.073574 -0.145680 +v -0.113001 0.069134 -0.174687 +v -0.086582 0.040490 -0.178385 +v -0.067740 0.036729 -0.196594 +v -0.072306 0.289049 0.046666 +v -0.008771 0.113710 -0.307686 +v -0.044618 0.102447 -0.279981 +v 0.027119 -0.063073 -0.437349 +v 0.018378 -0.176230 -0.472289 +v 0.035405 -0.281865 0.029584 +v 0.023904 0.009674 0.094208 +v 0.035242 0.463399 0.277158 +v 0.040592 0.381953 0.321156 +v 0.025591 0.453335 0.461662 +v 0.015839 0.457789 0.438348 +v 0.031349 0.475765 0.271976 +v 0.067181 0.478935 0.233496 +v 0.033627 0.336881 0.290329 +v 0.052960 0.473675 0.346195 +v 0.051408 0.386355 0.329605 +v 0.002429 0.376324 0.460823 +v 0.001163 0.381316 0.447729 +v 0.013278 0.083623 -0.401720 +v 0.058015 -0.454024 -0.387010 +v 0.030815 -0.315631 -0.464720 +v 0.067652 -0.422483 -0.397635 +v 0.070014 -0.453641 -0.428822 +v 0.098749 -0.012162 -0.387491 +v 0.065676 -0.091801 -0.420394 +v 0.058214 -0.137208 -0.439754 +v 0.035354 -0.134876 -0.467585 +v 0.034896 -0.192070 -0.488266 +v 0.030118 -0.240837 -0.489575 +v 0.011985 -0.252274 -0.470828 +v 0.043300 -0.442299 0.025235 +v 0.044365 -0.453446 0.045970 +v 0.068087 0.091144 -0.260248 +v 0.047498 0.100933 -0.275746 +v 0.014360 0.087597 -0.355161 +v 0.050234 0.057346 -0.285363 +v 0.047313 0.013387 -0.310783 +v 0.025248 -0.099331 -0.414592 +v 0.012447 -0.015785 -0.391115 +v 0.037125 -0.030309 -0.345573 +v 0.010171 -0.282458 0.022124 +v 0.041287 -0.068818 0.016568 +v 0.040154 -0.240288 0.039401 +v 0.034839 -0.215077 0.037582 +v 0.005613 0.114122 -0.448145 +v 0.142558 0.214990 -0.127540 +v 0.147246 0.160164 -0.153983 +v 0.138468 0.129313 -0.167198 +v 0.121170 0.088986 -0.183606 +v 0.098204 0.070856 -0.206767 +v 0.140692 0.093333 -0.128143 +v 0.110162 0.037784 -0.088067 +v 0.091370 0.021390 -0.063181 +v -0.023665 0.014311 -0.007288 +v -0.039408 0.002793 -0.051799 +v 0.152698 0.137675 -0.087052 +v 0.140846 0.177335 -0.027662 +v 0.130720 0.211621 -0.030426 +v 0.101634 0.234496 0.007479 +v 0.054155 0.277048 0.123919 +v 0.086551 0.229643 0.141995 +v 0.089126 0.198939 0.164927 +v 0.103032 0.172836 0.153206 +v 0.050600 0.221173 0.184858 +v 0.095285 0.293974 -0.078528 +v 0.110115 0.245379 -0.195999 +v 0.102402 0.287292 -0.160884 +v 0.051588 0.399137 -0.171387 +v 0.047114 0.369792 -0.202609 +v 0.018939 0.391096 -0.206778 +v 0.019371 0.417343 -0.181690 +v -0.002113 0.412163 -0.192733 +v 0.078302 0.358406 -0.123736 +v 0.046345 0.390495 -0.087902 +v 0.024471 0.402117 -0.073897 +v 0.047874 -0.333222 0.019491 +v 0.092364 -0.067467 0.062362 +v 0.086169 -0.085054 0.033307 +v 0.102053 -0.019961 0.049005 +v -0.012994 0.012561 0.124190 +v 0.029414 -0.068493 0.068774 +v 0.027370 -0.066404 0.038519 +v 0.029707 -0.128266 0.053262 +v 0.027668 -0.121261 0.028250 +v 0.103957 0.096585 -0.256474 +v 0.018349 0.214659 -0.405838 +v 0.057951 0.215355 -0.384786 +v 0.058152 0.269094 -0.326670 +v 0.093895 0.253759 -0.310216 +v 0.066879 0.104970 -0.411331 +v 0.112875 0.065943 -0.368140 +v 0.124379 0.077915 -0.294444 +v 0.124577 0.156128 -0.341619 +v 0.056614 0.281249 -0.299480 +v -0.003861 0.298973 -0.318120 +v 0.130748 0.148488 -0.259396 +v -0.002980 0.280236 -0.349511 +v 0.075283 0.049851 -0.268880 +v 0.043072 -0.159960 -0.421633 +v 0.041600 -0.316406 -0.434381 +v 0.012978 0.002495 0.069669 +v 0.043623 0.221207 0.322216 +v 0.034982 0.140470 0.272172 +v 0.003108 0.175383 0.335506 +v 0.024620 0.306011 0.363679 +v 0.005728 0.072251 0.185608 +v 0.061387 0.146453 0.191743 +v 0.065589 0.176887 0.191310 +v 0.057434 0.189572 0.250343 +v 0.046028 0.240624 0.279320 +v 0.019348 0.014524 0.123705 +v 0.042121 0.285571 0.342438 +v 0.039800 0.349178 0.327126 +v 0.038772 0.340781 0.305020 +v 0.017695 -0.338477 0.025203 +v 0.022883 -0.435524 0.051676 +v 0.039803 -0.428549 -0.396040 +v 0.055589 -0.322835 -0.442587 +v 0.050945 -0.178451 -0.441333 +v -0.012898 0.415009 0.263138 +v -0.034463 0.485660 0.366983 +v -0.052593 0.474055 0.346235 +v -0.057724 0.483606 0.254205 +v 0.044490 0.471161 0.373052 +v 0.037408 0.485417 0.365346 +v 0.000648 0.484079 0.284889 +v 0.053 |
