1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
//! ## STL loader for the Rapier physics engine
//!
//! Rapier is a set of 2D and 3D physics engines for games, animation, and robotics. The `rapier3d-stl`
//! crate lets you create a shape compatible with `rapier3d` and `parry3d` (the underlying collision-detection
//! library) from an STL file.
#![warn(missing_docs)]
use rapier3d::geometry::{MeshConverter, MeshConverterError, SharedShape};
use rapier3d::math::{Isometry, Point, Real, Vector};
use std::fs::File;
use std::io::{BufReader, Read, Seek};
use std::path::Path;
use stl_io::IndexedMesh;
/// Error while loading an STL file.
#[derive(thiserror::Error, Debug)]
pub enum StlLoaderError {
/// An error triggered by rapier’s [`MeshConverter`].
#[error(transparent)]
MeshConverter(#[from] MeshConverterError),
/// A generic IO error.
#[error(transparent)]
Io(#[from] std::io::Error),
}
/// The result of loading a shape from an stl mesh.
pub struct StlShape {
/// The shape loaded from the file and converted by the [`MeshConverter`].
pub shape: SharedShape,
/// The shape’s pose.
pub pose: Isometry<Real>,
/// The raw mesh read from the stl file without any modification.
pub raw_mesh: IndexedMesh,
}
/// Loads an STL file as a shape from a file.
///
/// # Parameters
/// - `file_path`: the STL file’s path.
/// - `converter`: controls how the shape is computed from the STL content. In particular, it lets
/// you specify if the computed [`StlShape::shape`] is a triangle mesh, its convex hull,
/// bounding box, etc.
/// - `scale`: the scaling factor applied to the geometry input to the `converter`. This scale will
/// affect at the geometric level the [`StlShape::shape`]. Note that raw mesh value stored
/// in [`StlShape::raw_mesh`] remains unscaled.
pub fn load_from_path(
file_path: impl AsRef<Path>,
converter: MeshConverter,
scale: Vector<Real>,
) -> Result<StlShape, StlLoaderError> {
let mut reader = BufReader::new(File::open(file_path)?);
load_from_reader(&mut reader, converter, scale)
}
/// Loads an STL file as a shape from an arbitrary reader.
///
/// # Parameters
/// - `reader`: the reader.
/// - `converter`: controls how the shape is computed from the STL content. In particular, it lets
/// you specify if the computed [`StlShape::shape`] is a triangle mesh, its convex hull,
/// bounding box, etc.
/// - `scale`: the scaling factor applied to the geometry input to the `converter`. This scale will
/// affect at the geometric level the [`StlShape::shape`]. Note that raw mesh value stored
/// in [`StlShape::raw_mesh`] remains unscaled.
pub fn load_from_reader<R: Read + Seek>(
read: &mut R,
converter: MeshConverter,
scale: Vector<Real>,
) -> Result<StlShape, StlLoaderError> {
let stl_mesh = stl_io::read_stl(read)?;
Ok(load_from_raw_mesh(stl_mesh, converter, scale)?)
}
/// Loads an STL file as a shape from a preloaded raw stl mesh.
///
/// # Parameters
/// - `raw_mesh`: the raw stl mesh.
/// - `converter`: controls how the shape is computed from the STL content. In particular, it lets
/// you specify if the computed [`StlShape::shape`] is a triangle mesh, its convex hull,
/// bounding box, etc.
/// - `scale`: the scaling factor applied to the geometry input to the `converter`. This scale will
/// affect at the geometric level the [`StlShape::shape`]. Note that raw mesh value stored
/// in [`StlShape::raw_mesh`] remains unscaled.
pub fn load_from_raw_mesh(
raw_mesh: IndexedMesh,
converter: MeshConverter,
scale: Vector<Real>,
) -> Result<StlShape, MeshConverterError> {
let mut vertices: Vec<_> = raw_mesh
.vertices
.iter()
.map(|xyz| Point::new(xyz[0] as Real, xyz[1] as Real, xyz[2] as Real))
.collect();
vertices
.iter_mut()
.for_each(|pt| pt.coords.component_mul_assign(&scale));
let indices: Vec<_> = raw_mesh
.faces
.iter()
.map(|f| f.vertices.map(|i| i as u32))
.collect();
let (shape, pose) = converter.convert(vertices, indices)?;
Ok(StlShape {
shape,
pose,
raw_mesh,
})
}
|