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
111
112
113
114
115
116
117
118
119
//!
//! This crate contains a [Mesh] struct which represents a triangle mesh.
//! It is implemented using a half-edge data structure which is efficient for creating, editing, traversing and computing on that mesh.
//! Also, the mesh can easily be created from and exported into a format that is efficient for visualization.
//! Finally, operations on the mesh is implemented as methods on the [Mesh] struct, so take a look at that rather long list of methods for a complete overview.
//!

#![warn(missing_docs)]

pub mod math;

mod mesh;
pub use mesh::*;

mod operations;
pub use operations::*;

use thiserror::Error;
///
/// Error when performing a mesh operation
///
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum Error {
    #[error("configuration is not valid: {0}")]
    ActionWillResultInInvalidMesh(String),
    #[error("action will produce a non-manifold mesh: {0}")]
    ActionWillResultInNonManifoldMesh(String),
    #[error("the mesh has ended up in an invalid state: {0}")]
    MeshIsInvalid(String),
}

#[cfg(test)]
mod test_utility {
    use super::*;
    use three_d_asset::{Indices, Positions, TriMesh};
    /// Creates three connected triangles in `x = [-3, 3]`, `y = [-1, 2]` and `z = 0`
    /// which covers a square in `x = [-1, 1]`, `y = [-1, 1]` and `z = 0`
    /// and has a common vertex in `(0, 0, 0)`.
    pub(crate) fn subdivided_triangle() -> Mesh {
        TriMesh {
            indices: Indices::U8(vec![0, 2, 3, 0, 3, 1, 0, 1, 2]),
            positions: Positions::F64(vec![
                vec3(0.0, 0.0, 0.0),
                vec3(-3.0, -1.0, 0.0),
                vec3(3.0, -1.0, 0.0),
                vec3(0.0, 2.0, 0.0),
            ]),
            ..Default::default()
        }
        .into()
    }

    /// Creates a triangle in `x = [-3, 3]`, `y = [-1, 2]` and `z = 0` which covers a square in `x = [-1, 1]`, `y = [-1, 1]` and `z = 0`.
    pub(crate) fn triangle() -> Mesh {
        TriMesh {
            indices: Indices::U8(vec![0, 1, 2]),
            positions: Positions::F64(vec![
                vec3(-3.0, -1.0, 0.0),
                vec3(3.0, -1.0, 0.0),
                vec3(0.0, 2.0, 0.0),
            ]),
            ..Default::default()
        }
        .into()
    }

    /// Creates a square in `x = [-1, 1]`, `y = [-1, 1]` and `z = 0`.
    pub(crate) fn square() -> Mesh {
        TriMesh {
            indices: Indices::U8(vec![0, 1, 2, 2, 1, 3]),
            positions: Positions::F64(vec![
                vec3(-1.0, -1.0, 0.0),
                vec3(1.0, -1.0, 0.0),
                vec3(-1.0, 1.0, 0.0),
                vec3(1.0, 1.0, 0.0),
            ]),
            ..Default::default()
        }
        .into()
    }

    pub(crate) fn triangle_strip() -> Mesh {
        TriMesh {
            indices: Indices::U8(vec![0, 1, 2, 2, 1, 3, 3, 1, 4, 3, 4, 5]),
            positions: Positions::F64(vec![
                vec3(0.0, 0.0, 0.0),
                vec3(0.0, 0.0, 1.0),
                vec3(1.0, 0.0, 0.5),
                vec3(1.0, 0.0, 1.5),
                vec3(0.0, 0.0, 2.0),
                vec3(0.0, 0.0, 2.5),
            ]),
            ..Default::default()
        }
        .into()
    }

    pub(crate) fn cube() -> Mesh {
        TriMesh {
            indices: Indices::U8(vec![
                0, 1, 2, 0, 2, 3, 4, 7, 6, 4, 6, 5, 0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2,
                7, 3, 4, 0, 3, 4, 3, 7,
            ]),
            positions: Positions::F64(vec![
                vec3(1.0, -1.0, -1.0),
                vec3(1.0, -1.0, 1.0),
                vec3(-1.0, -1.0, 1.0),
                vec3(-1.0, -1.0, -1.0),
                vec3(1.0, 1.0, -1.0),
                vec3(1.0, 1.0, 1.0),
                vec3(-1.0, 1.0, 1.0),
                vec3(-1.0, 1.0, -1.0),
            ]),
            ..Default::default()
        }
        .into()
    }
}