pub struct PolygonMesh<V = StandardVertex, A = StandardAttributes> { /* private fields */ }
Expand description

Polygon mesh

The polygon data is held in a method compliant with wavefront obj. Position, uv (texture) coordinates, and normal vectors are held in separate arrays, and each face vertex accesses those values by an indices triple.

Implementations§

Contract attributes and expand polygon.

Examples
use truck_polymesh::*;
let polygon = PolygonMesh::new(
    StandardAttributes {
        positions: vec![
            Point3::new(0.0, 0.0, 0.0),
            Point3::new(1.0, 0.0, 0.0),
            Point3::new(0.0, 1.0, 0.0),
            Point3::new(1.0, 1.0, 0.0),
        ],
        normals: vec![
            Vector3::new(0.0, 0.0, 1.0),
            Vector3::new(0.0, 0.0, -1.0),
        ],
        ..Default::default()
    },
    Faces::from_iter(&[
        &[(0, None, Some(0)), (1, None, Some(0)), (2, None, Some(0))],
        &[(3, None, Some(1)), (1, None, Some(1)), (2, None, Some(1))],
    ])
);
let expands = polygon.expands(|attr| (attr.position, attr.normal.unwrap()));
assert_eq!(
    expands,
    PolygonMesh::<usize, Vec<(Point3, Vector3)>>::new(
        vec![
           (Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0)),
           (Point3::new(1.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0)),
           (Point3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 0.0, 1.0)),
           (Point3::new(1.0, 1.0, 0.0), Vector3::new(0.0, 0.0, -1.0)),
           (Point3::new(1.0, 0.0, 0.0), Vector3::new(0.0, 0.0, -1.0)),
           (Point3::new(0.0, 1.0, 0.0), Vector3::new(0.0, 0.0, -1.0)),
        ],
        Faces::from_iter(&[[0, 1, 2], [3, 4, 5]]),
    )
);

complete constructor

Panics

Panic occurs if there is an index is out of range.

Remarks

This method does not check whether the normal is normalized or not.

Examples found in repository?
src/polygon_mesh.rs (line 39)
37
38
39
40
41
42
    pub fn debug_new(attributes: A, faces: Faces<V>) -> Self {
        match cfg!(debug_assertions) {
            true => Self::new(attributes, faces),
            false => Self::new_unchecked(attributes, faces),
        }
    }
More examples
Hide additional examples
src/expand.rs (line 69)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    pub fn expands<T: Copy>(
        &self,
        contraction: impl Fn(A::Output) -> T,
    ) -> PolygonMesh<usize, Vec<T>> {
        let mut vec = Vec::<T>::new();
        let mut vertex_map = EntryMap::new(
            |x| x,
            |vertex| {
                let idx = vec.len();
                vec.push(contraction(self.attributes.get(vertex).unwrap()));
                idx
            },
        );
        let faces: Faces<usize> = self
            .face_iter()
            .map(|face| {
                face.iter()
                    .cloned()
                    .map(|vertex| *vertex_map.entry_or_insert(vertex))
                    .collect::<Vec<_>>()
            })
            .collect();
        PolygonMesh::new(vec, faces)
    }

complete constructor

Errors

Returns Error::OutOfRange if there is an index is out of range.

Remarks

This method does not check whether the normal is normalized or not.

Examples found in repository?
src/polygon_mesh.rs (line 12)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
    pub fn new(attributes: A, faces: Faces<V>) -> Self {
        Self::try_new(attributes, faces).unwrap_or_else(|e| panic!("{:?}", e))
    }

    /// complete constructor
    /// # Errors
    /// Returns [`Error::OutOfRange`] if there is an index is out of range.
    ///
    /// [`Error::OutOfRange`]: ./errors/enum.Error.html#variant.OutOfRange
    ///
    /// # Remarks
    /// This method does not check whether the normal is normalized or not.
    pub fn try_new(attributes: A, faces: Faces<V>) -> Result<Self, Error<V>> {
        faces
            .is_compatible(&attributes)
            .map(|_| Self::new_unchecked(attributes, faces))
    }

    /// constructor without boundary check
    #[inline(always)]
    pub const fn new_unchecked(attributes: A, faces: Faces<V>) -> Self {
        Self { attributes, faces }
    }

    /// constructor, boundary check is acrivated only in debug mode.
    #[inline(always)]
    pub fn debug_new(attributes: A, faces: Faces<V>) -> Self {
        match cfg!(debug_assertions) {
            true => Self::new(attributes, faces),
            false => Self::new_unchecked(attributes, faces),
        }
    }

    /// Returns attributes
    #[inline(always)]
    pub const fn attributes(&self) -> &A { &self.attributes }

    /// Returns the faces of the polygon.
    #[inline(always)]
    pub const fn faces(&self) -> &Faces<V> { &self.faces }

    /// Returns the vector of all triangles of the polygon.
    #[inline(always)]
    pub const fn tri_faces(&self) -> &Vec<[V; 3]> { &self.faces.tri_faces }

    /// Returns the vector of all quadrangles.
    #[inline(always)]
    pub const fn quad_faces(&self) -> &Vec<[V; 4]> { &self.faces.quad_faces }

    /// Returns the vector of n-gons (n > 4).
    #[inline(always)]
    pub const fn other_faces(&self) -> &Vec<Vec<V>> { &self.faces.other_faces }

    /// Returns the iterator of the slice.
    ///
    /// By the internal optimization, this iterator does not runs in the simple order
    /// in which they are registered, but runs order: triangle, square, and the others.
    /// cf: [`Faces::face_iter`](./struct.Faces.html#method.face_iter)
    #[inline(always)]
    pub fn face_iter(&self) -> impl Iterator<Item = &[V]> { self.faces.face_iter() }

    /// Returns the iterator of the slice.
    ///
    /// By the internal optimization, this iterator does not runs in the simple order
    /// in which they are registered, but runs order: triangle, square, and the others.
    /// cf: [`Faces::face_iter`](./struct.Faces.html#method.face_iter)
    #[inline(always)]
    pub fn face_iter_mut(&mut self) -> impl Iterator<Item = &mut [V]> { self.faces.face_iter_mut() }
    /// Creates an editor that performs boundary checking on dropped.
    #[inline(always)]
    pub fn editor(&mut self) -> PolygonMeshEditor<'_, V, A> {
        PolygonMeshEditor {
            attributes: &mut self.attributes,
            faces: &mut self.faces,
            bound_check: true,
        }
    }
    /// Creates an editor that does NOT perform boundary checking on dropped.
    #[inline(always)]
    pub fn uncheck_editor(&mut self) -> PolygonMeshEditor<'_, V, A> {
        PolygonMeshEditor {
            attributes: &mut self.attributes,
            faces: &mut self.faces,
            bound_check: false,
        }
    }
    /// Creates an editor that performs boundary checking on dropped ONLY in debug build.
    #[inline(always)]
    pub fn debug_editor(&mut self) -> PolygonMeshEditor<'_, V, A> {
        PolygonMeshEditor {
            attributes: &mut self.attributes,
            faces: &mut self.faces,
            bound_check: cfg!(debug_assertions),
        }
    }
}

impl PolygonMesh {
    /// Returns polygonmesh merged `self` and `mesh`.
    pub fn merge(&mut self, mut mesh: PolygonMesh) {
        let n_pos = self.positions().len();
        let n_uv = self.uv_coords().len();
        let n_nor = self.normals().len();
        mesh.faces.face_iter_mut().for_each(move |face| {
            face.iter_mut().for_each(|v| {
                v.pos += n_pos;
                v.uv = v.uv.map(|uv| uv + n_uv);
                v.nor = v.nor.map(|nor| nor + n_nor);
            })
        });
        self.attributes.positions.extend(mesh.attributes.positions);
        self.attributes.uv_coords.extend(mesh.attributes.uv_coords);
        self.attributes.normals.extend(mesh.attributes.normals);
        self.faces.naive_concat(mesh.faces);
    }
    /// Creates the bounding box of the polygon mesh.
    #[inline(always)]
    pub fn bounding_box(&self) -> BoundingBox<Point3> { self.positions().iter().collect() }
}

impl Invertible for PolygonMesh {
    #[inline(always)]
    fn invert(&mut self) {
        self.attributes.normals.iter_mut().for_each(|n| *n = -*n);
        self.faces.invert();
    }
    #[inline(always)]
    fn inverse(&self) -> Self {
        Self {
            attributes: StandardAttributes {
                positions: self.attributes.positions.clone(),
                uv_coords: self.attributes.uv_coords.clone(),
                normals: self.attributes.normals.iter().map(|n| -*n).collect(),
            },
            faces: self.faces.inverse(),
        }
    }
}

impl PolygonMesh {
    /// Returns the vector of all positions.
    #[inline(always)]
    pub const fn positions(&self) -> &Vec<Point3> { &self.attributes.positions }

    /// Returns the mutable slice of all positions.
    #[inline(always)]
    pub fn positions_mut(&mut self) -> &mut [Point3] { &mut self.attributes.positions }

    /// Adds a position.
    #[inline(always)]
    pub fn push_position(&mut self, position: Point3) { self.attributes.positions.push(position) }

    /// Extend positions by iterator.
    #[inline(always)]
    pub fn extend_positions<I: IntoIterator<Item = Point3>>(&mut self, iter: I) {
        self.attributes.positions.extend(iter)
    }

    /// Returns the vector of all uv (texture) coordinates.
    #[inline(always)]
    pub const fn uv_coords(&self) -> &Vec<Vector2> { &self.attributes.uv_coords }

    /// Returns the mutable slice of all uv (texture) coordinates.
    #[inline(always)]
    pub fn uv_coords_mut(&mut self) -> &mut [Vector2] { &mut self.attributes.uv_coords }

    /// Adds a uv (texture) coordinate.
    #[inline(always)]
    pub fn push_uv_coord(&mut self, uv_coord: Vector2) { self.attributes.uv_coords.push(uv_coord) }

    /// Extend uv (texture) coordinates by iterator.
    #[inline(always)]
    pub fn extend_uv_coords<I: IntoIterator<Item = Vector2>>(&mut self, iter: I) {
        self.attributes.uv_coords.extend(iter)
    }

    /// Returns the vector of all normals.
    #[inline(always)]
    pub const fn normals(&self) -> &Vec<Vector3> { &self.attributes.normals }

    /// Returns the mutable slice of all normals.
    #[inline(always)]
    pub fn normals_mut(&mut self) -> &mut [Vector3] { &mut self.attributes.normals }

    /// Extend normals by iterator
    #[inline(always)]
    pub fn extend_normals<I: IntoIterator<Item = Vector3>>(&mut self, iter: I) {
        self.attributes.normals.extend(iter)
    }
}

impl<V, A: Default> Default for PolygonMesh<V, A> {
    fn default() -> Self {
        Self {
            attributes: A::default(),
            faces: Faces::default(),
        }
    }
}

impl<'de, V, A> Deserialize<'de> for PolygonMesh<V, A>
where
    V: Copy + Debug + Deserialize<'de>,
    A: Attributes<V> + Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where D: serde::Deserializer<'de> {
        #[derive(Deserialize)]
        struct PolygonMesh_<V, A> {
            attributes: A,
            faces: Faces<V>,
        }
        let PolygonMesh_ { attributes, faces } = PolygonMesh_::<V, A>::deserialize(deserializer)?;
        Self::try_new(attributes, faces).map_err(serde::de::Error::custom)
    }
More examples
Hide additional examples
src/obj.rs (lines 178-185)
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
pub fn read<R: Read>(reader: R) -> Result<PolygonMesh> {
    let mut positions = Vec::new();
    let mut uv_coords = Vec::new();
    let mut normals = Vec::new();
    let mut faces = Faces::default();
    let reader = BufReader::new(reader);
    for line in reader.lines().map(|s| s.unwrap()) {
        let mut args = line.split_whitespace();
        if let Some(first_str) = args.next() {
            if first_str == "v" {
                let x = args.next().unwrap().parse::<f64>()?;
                let y = args.next().unwrap().parse::<f64>()?;
                let z = args.next().unwrap().parse::<f64>()?;
                positions.push(Point3::new(x, y, z));
            } else if first_str == "vt" {
                let u = args.next().unwrap().parse::<f64>()?;
                let v = args.next().unwrap().parse::<f64>()?;
                uv_coords.push(Vector2::new(u, v));
            } else if first_str == "vn" {
                let x = args.next().unwrap().parse::<f64>()?;
                let y = args.next().unwrap().parse::<f64>()?;
                let z = args.next().unwrap().parse::<f64>()?;
                normals.push(Vector3::new(x, y, z));
            } else if first_str == "f" {
                let mut face = Vec::new();
                for vert_str in args {
                    if &vert_str[0..1] == "#" {
                        break;
                    }
                    let mut iter = vert_str.split('/');
                    let pos = iter
                        .next()
                        .map(|val| val.parse::<usize>().map(|i| i - 1).ok())
                        .unwrap_or(None);
                    let uv = iter
                        .next()
                        .map(|val| val.parse::<usize>().map(|i| i - 1).ok())
                        .unwrap_or(None);
                    let nor = iter
                        .next()
                        .map(|val| val.parse::<usize>().map(|i| i - 1).ok())
                        .unwrap_or(None);
                    let vert = match (pos, uv, nor) {
                        (None, _, _) => continue,
                        (Some(pos), uv, nor) => Vertex { pos, uv, nor },
                    };
                    face.push(vert);
                }
                faces.push(face);
            }
        }
    }
    PolygonMesh::try_new(
        StandardAttributes {
            positions,
            uv_coords,
            normals,
        },
        faces,
    )
}

constructor without boundary check

Examples found in repository?
src/polygon_mesh.rs (line 26)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    pub fn try_new(attributes: A, faces: Faces<V>) -> Result<Self, Error<V>> {
        faces
            .is_compatible(&attributes)
            .map(|_| Self::new_unchecked(attributes, faces))
    }

    /// constructor without boundary check
    #[inline(always)]
    pub const fn new_unchecked(attributes: A, faces: Faces<V>) -> Self {
        Self { attributes, faces }
    }

    /// constructor, boundary check is acrivated only in debug mode.
    #[inline(always)]
    pub fn debug_new(attributes: A, faces: Faces<V>) -> Self {
        match cfg!(debug_assertions) {
            true => Self::new(attributes, faces),
            false => Self::new_unchecked(attributes, faces),
        }
    }

constructor, boundary check is acrivated only in debug mode.

Examples found in repository?
src/stl.rs (lines 342-349)
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
    fn from_iter<I: IntoIterator<Item = STLFace>>(iter: I) -> PolygonMesh {
        let mut positions = HashMap::<[i64; 3], usize>::default();
        let mut normals = HashMap::<[i64; 3], usize>::default();
        let faces: Vec<[Vertex; 3]> = iter
            .into_iter()
            .map(|face| {
                let n = signup_vector(face.normal, &mut normals);
                let p = [
                    signup_vector(face.vertices[0], &mut positions),
                    signup_vector(face.vertices[1], &mut positions),
                    signup_vector(face.vertices[2], &mut positions),
                ];
                [
                    (p[0], None, Some(n)).into(),
                    (p[1], None, Some(n)).into(),
                    (p[2], None, Some(n)).into(),
                ]
            })
            .collect();
        let faces = Faces::from_tri_and_quad_faces(faces, Vec::new());
        let mut positions: Vec<([i64; 3], usize)> = positions.into_iter().collect();
        positions.sort_by(|a, b| a.1.cmp(&b.1));
        let positions: Vec<Point3> = positions
            .into_iter()
            .map(|(p, _)| {
                Point3::new(
                    p[0] as f64 * TOLERANCE * 0.5,
                    p[1] as f64 * TOLERANCE * 0.5,
                    p[2] as f64 * TOLERANCE * 0.5,
                )
            })
            .collect();
        let mut normals: Vec<([i64; 3], usize)> = normals.into_iter().collect();
        normals.sort_by(|a, b| a.1.cmp(&b.1));
        let normals: Vec<Vector3> = normals
            .into_iter()
            .map(|(p, _)| {
                Vector3::new(
                    p[0] as f64 * TOLERANCE * 0.5,
                    p[1] as f64 * TOLERANCE * 0.5,
                    p[2] as f64 * TOLERANCE * 0.5,
                )
            })
            .collect();
        PolygonMesh::debug_new(
            StandardAttributes {
                positions,
                uv_coords: Vec::new(),
                normals,
            },
            faces,
        )
    }

Returns attributes

Returns the faces of the polygon.

Examples found in repository?
src/stl.rs (line 269)
268
269
270
271
272
273
274
275
    fn into_iter(self) -> Self::IntoIter {
        let iter = self.faces().triangle_iter();
        Self::IntoIter {
            positions: self.positions(),
            len: iter.len(),
            faces: iter,
        }
    }

Returns the vector of all triangles of the polygon.

Returns the vector of all quadrangles.

Returns the vector of n-gons (n > 4).

Returns the iterator of the slice.

By the internal optimization, this iterator does not runs in the simple order in which they are registered, but runs order: triangle, square, and the others. cf: Faces::face_iter

Examples found in repository?
src/expand.rs (line 61)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    pub fn expands<T: Copy>(
        &self,
        contraction: impl Fn(A::Output) -> T,
    ) -> PolygonMesh<usize, Vec<T>> {
        let mut vec = Vec::<T>::new();
        let mut vertex_map = EntryMap::new(
            |x| x,
            |vertex| {
                let idx = vec.len();
                vec.push(contraction(self.attributes.get(vertex).unwrap()));
                idx
            },
        );
        let faces: Faces<usize> = self
            .face_iter()
            .map(|face| {
                face.iter()
                    .cloned()
                    .map(|vertex| *vertex_map.entry_or_insert(vertex))
                    .collect::<Vec<_>>()
            })
            .collect();
        PolygonMesh::new(vec, faces)
    }

Returns the iterator of the slice.

By the internal optimization, this iterator does not runs in the simple order in which they are registered, but runs order: triangle, square, and the others. cf: Faces::face_iter

Creates an editor that performs boundary checking on dropped.

Creates an editor that does NOT perform boundary checking on dropped.

Creates an editor that performs boundary checking on dropped ONLY in debug build.

Returns polygonmesh merged self and mesh.

Creates the bounding box of the polygon mesh.

Returns the vector of all positions.

Examples found in repository?
src/stl.rs (line 271)
268
269
270
271
272
273
274
275
    fn into_iter(self) -> Self::IntoIter {
        let iter = self.faces().triangle_iter();
        Self::IntoIter {
            positions: self.positions(),
            len: iter.len(),
            faces: iter,
        }
    }
More examples
Hide additional examples
src/obj.rs (line 119)
118
119
120
121
122
123
fn sub_write<W: Write>(mesh: &PolygonMesh, writer: &mut BufWriter<W>) -> Result<()> {
    write3vec(writer, mesh.positions(), "v")?;
    write2vec(writer, mesh.uv_coords(), "vt")?;
    write3vec(writer, mesh.normals(), "vn")?;
    mesh.faces.write(writer)
}
src/polygon_mesh.rs (line 111)
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    pub fn merge(&mut self, mut mesh: PolygonMesh) {
        let n_pos = self.positions().len();
        let n_uv = self.uv_coords().len();
        let n_nor = self.normals().len();
        mesh.faces.face_iter_mut().for_each(move |face| {
            face.iter_mut().for_each(|v| {
                v.pos += n_pos;
                v.uv = v.uv.map(|uv| uv + n_uv);
                v.nor = v.nor.map(|nor| nor + n_nor);
            })
        });
        self.attributes.positions.extend(mesh.attributes.positions);
        self.attributes.uv_coords.extend(mesh.attributes.uv_coords);
        self.attributes.normals.extend(mesh.attributes.normals);
        self.faces.naive_concat(mesh.faces);
    }
    /// Creates the bounding box of the polygon mesh.
    #[inline(always)]
    pub fn bounding_box(&self) -> BoundingBox<Point3> { self.positions().iter().collect() }

Returns the mutable slice of all positions.

Adds a position.

Extend positions by iterator.

Returns the vector of all uv (texture) coordinates.

Examples found in repository?
src/obj.rs (line 120)
118
119
120
121
122
123
fn sub_write<W: Write>(mesh: &PolygonMesh, writer: &mut BufWriter<W>) -> Result<()> {
    write3vec(writer, mesh.positions(), "v")?;
    write2vec(writer, mesh.uv_coords(), "vt")?;
    write3vec(writer, mesh.normals(), "vn")?;
    mesh.faces.write(writer)
}
More examples
Hide additional examples
src/polygon_mesh.rs (line 112)
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    pub fn merge(&mut self, mut mesh: PolygonMesh) {
        let n_pos = self.positions().len();
        let n_uv = self.uv_coords().len();
        let n_nor = self.normals().len();
        mesh.faces.face_iter_mut().for_each(move |face| {
            face.iter_mut().for_each(|v| {
                v.pos += n_pos;
                v.uv = v.uv.map(|uv| uv + n_uv);
                v.nor = v.nor.map(|nor| nor + n_nor);
            })
        });
        self.attributes.positions.extend(mesh.attributes.positions);
        self.attributes.uv_coords.extend(mesh.attributes.uv_coords);
        self.attributes.normals.extend(mesh.attributes.normals);
        self.faces.naive_concat(mesh.faces);
    }

Returns the mutable slice of all uv (texture) coordinates.

Adds a uv (texture) coordinate.

Extend uv (texture) coordinates by iterator.

Returns the vector of all normals.

Examples found in repository?
src/obj.rs (line 121)
118
119
120
121
122
123
fn sub_write<W: Write>(mesh: &PolygonMesh, writer: &mut BufWriter<W>) -> Result<()> {
    write3vec(writer, mesh.positions(), "v")?;
    write2vec(writer, mesh.uv_coords(), "vt")?;
    write3vec(writer, mesh.normals(), "vn")?;
    mesh.faces.write(writer)
}
More examples
Hide additional examples
src/polygon_mesh.rs (line 113)
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    pub fn merge(&mut self, mut mesh: PolygonMesh) {
        let n_pos = self.positions().len();
        let n_uv = self.uv_coords().len();
        let n_nor = self.normals().len();
        mesh.faces.face_iter_mut().for_each(move |face| {
            face.iter_mut().for_each(|v| {
                v.pos += n_pos;
                v.uv = v.uv.map(|uv| uv + n_uv);
                v.nor = v.nor.map(|nor| nor + n_nor);
            })
        });
        self.attributes.positions.extend(mesh.attributes.positions);
        self.attributes.uv_coords.extend(mesh.attributes.uv_coords);
        self.attributes.normals.extend(mesh.attributes.normals);
        self.faces.naive_concat(mesh.faces);
    }

Returns the mutable slice of all normals.

Extend normals by iterator

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Deserialize this value from the given Serde deserializer. Read more
Creates a value from an iterator. Read more
Which kind of iterator are we turning this into?
Creates an iterator from a value.
Inverts self
Returns the inverse.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.