axiolid_mesh/
error.rs

1//! Structured mesh validation failures.
2
3use core::fmt;
4
5/// Cheap structural validation failure.
6#[non_exhaustive]
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum MeshValidationError {
9    /// Triangle index buffer is not divisible by three.
10    IncompleteTriangle { index_count: usize },
11    /// Position index does not exist.
12    PositionIndexOutOfRange { index: u32, position_count: usize },
13    /// Non-indexed normals do not align with positions.
14    NormalCount { expected: usize, actual: usize },
15    /// Independently indexed normals do not align with corners.
16    NormalIndexCount { expected: usize, actual: usize },
17    /// Normal index does not exist.
18    NormalIndexOutOfRange { index: u32, normal_count: usize },
19    /// A channel does not carry one tuple per vertex.
20    AttributeCount {
21        /// Channel name.
22        name: String,
23        /// Vertices in the mesh.
24        expected: usize,
25        /// Vertices the channel covers.
26        actual: usize,
27    },
28    /// A channel declares a zero tuple width, which covers no vertices.
29    AttributeZeroWidth {
30        /// Channel name.
31        name: String,
32    },
33    /// Two channels share a name, so a lookup would be ambiguous.
34    AttributeDuplicateName {
35        /// The repeated name.
36        name: String,
37    },
38    /// A corner-indexed channel's `values` is not whole tuples.
39    AttributeRaggedValues {
40        /// Channel name.
41        name: String,
42        /// Scalars found.
43        values: usize,
44        /// Declared tuple width.
45        width: usize,
46    },
47    /// A corner-indexed channel does not have one entry per triangle corner.
48    AttributeCornerCount {
49        /// Channel name.
50        name: String,
51        /// Triangle corners in the mesh.
52        expected: usize,
53        /// Corner entries in the channel.
54        actual: usize,
55    },
56    /// A corner index points past the channel's values.
57    AttributeCornerIndexOutOfRange {
58        /// Channel name.
59        name: String,
60        /// The offending index.
61        index: u32,
62        /// Tuples available.
63        value_count: usize,
64    },
65    /// A triangle has some corners mapped and some unmapped.
66    AttributePartiallyMapped {
67        /// Channel name.
68        name: String,
69        /// The triangle.
70        triangle: usize,
71    },
72}
73
74impl fmt::Display for MeshValidationError {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        match self {
77            Self::IncompleteTriangle { index_count } => {
78                write!(f, "index count {index_count} is not divisible by three")
79            }
80            Self::PositionIndexOutOfRange {
81                index,
82                position_count,
83            } => write!(
84                f,
85                "position index {index} exceeds {position_count} positions"
86            ),
87            Self::NormalCount { expected, actual } => {
88                write!(f, "expected {expected} normals, found {actual}")
89            }
90            Self::NormalIndexCount { expected, actual } => {
91                write!(f, "expected {expected} normal indices, found {actual}")
92            }
93            Self::NormalIndexOutOfRange {
94                index,
95                normal_count,
96            } => write!(f, "normal index {index} exceeds {normal_count} normals"),
97            Self::AttributeCount {
98                name,
99                expected,
100                actual,
101            } => write!(
102                f,
103                "attribute channel {name} covers {actual} vertices, mesh has {expected}"
104            ),
105            Self::AttributeZeroWidth { name } => {
106                write!(f, "attribute channel {name} declares a zero tuple width")
107            }
108            Self::AttributeDuplicateName { name } => {
109                write!(f, "attribute channel name {name} is used more than once")
110            }
111            Self::AttributeRaggedValues {
112                name,
113                values,
114                width,
115            } => write!(
116                f,
117                "attribute channel {name} has {values} scalars, not a multiple of width {width}"
118            ),
119            Self::AttributeCornerCount {
120                name,
121                expected,
122                actual,
123            } => write!(
124                f,
125                "attribute channel {name} has {actual} corner indices, mesh has {expected} corners"
126            ),
127            Self::AttributeCornerIndexOutOfRange {
128                name,
129                index,
130                value_count,
131            } => write!(
132                f,
133                "attribute channel {name} corner index {index} exceeds {value_count} values"
134            ),
135            Self::AttributePartiallyMapped { name, triangle } => write!(
136                f,
137                "attribute channel {name} maps only some corners of triangle {triangle}"
138            ),
139        }
140    }
141}
142
143impl std::error::Error for MeshValidationError {}