Skip to main content

asset_importer_rs_post_process/
lib.rs

1//! Post-processing module for asset-importer-rs
2//!
3//! This module provides implementations of various post-processing steps
4//! that can be applied to 3D assets after import.
5
6pub mod error;
7pub mod helper;
8pub mod steps;
9
10// Re-export commonly used items
11pub use asset_importer_rs_core::AiPostProcessSteps;
12pub use asset_importer_rs_scene::AiScene;
13pub use error::AiPostProcessError;
14
15use asset_importer_rs_core::AiPostProcess;
16use bytemuck;
17use enumflags2::BitFlags;
18
19// Re-export steps based on features
20#[cfg(feature = "calc-tangent-spaces")]
21pub use steps::CalcTangentSpaces;
22#[cfg(feature = "find-degenerates")]
23pub use steps::FindDegenerates;
24#[cfg(feature = "find-invalid-data")]
25pub use steps::FindInvalidData;
26#[cfg(feature = "gen-normals")]
27pub use steps::GenNormals;
28#[cfg(feature = "gen-smooth-normals")]
29pub use steps::GenSmoothNormals;
30#[cfg(feature = "join-identical-vertices")]
31pub use steps::JoinIdenticalVertices;
32#[cfg(feature = "optimize-graph")]
33pub use steps::OptimizeGraph;
34#[cfg(feature = "optimize-meshes")]
35pub use steps::OptimizeMeshes;
36#[cfg(feature = "remove-redundant-materials")]
37pub use steps::RemoveRedundantMaterials;
38#[cfg(feature = "triangulate")]
39pub use steps::Triangulate;
40#[cfg(feature = "validate-data-structure")]
41pub use steps::ValidateDataStructure;
42
43// Additional feature re-exports
44#[cfg(feature = "debone")]
45pub use steps::Debone;
46#[cfg(feature = "drop-normals")]
47pub use steps::DropNormals;
48#[cfg(feature = "embed-textures")]
49pub use steps::EmbedTextures;
50#[cfg(feature = "find-instances")]
51pub use steps::FindInstances;
52#[cfg(feature = "fix-infacing-normals")]
53pub use steps::FixInfacingNormals;
54#[cfg(feature = "flip-uvs")]
55pub use steps::FlipUVs;
56#[cfg(feature = "flip-winding-order")]
57pub use steps::FlipWindingOrder;
58#[cfg(feature = "force-gen-normals")]
59pub use steps::ForceGenNormals;
60#[cfg(feature = "gen-bounding-boxes")]
61pub use steps::GenBoundingBoxes;
62#[cfg(feature = "gen-uv-coords")]
63pub use steps::GenUVCoords;
64#[cfg(feature = "global-scale")]
65pub use steps::GlobalScale;
66#[cfg(feature = "improve-cache-locality")]
67pub use steps::ImproveCacheLocality;
68#[cfg(feature = "limit-bone-weights")]
69pub use steps::LimitBoneWeights;
70#[cfg(feature = "make-left-handed")]
71pub use steps::MakeLeftHanded;
72#[cfg(feature = "populate-armature-data")]
73pub use steps::PopulateArmatureData;
74#[cfg(feature = "pre-transform-vertices")]
75pub use steps::PreTransformVertices;
76#[cfg(feature = "remove-component")]
77pub use steps::RemoveComponent;
78#[cfg(feature = "sort-by-p-type")]
79pub use steps::SortByPType;
80#[cfg(feature = "split-by-bone-count")]
81pub use steps::SplitByBoneCount;
82#[cfg(feature = "split-large-meshes")]
83pub use steps::SplitLargeMeshes;
84#[cfg(feature = "transform-uv-coords")]
85pub use steps::TransformUVCoords;
86
87type AiPostProcessDyn = dyn AiPostProcess<Error = AiPostProcessError>;
88
89pub struct PostProcess {
90    processors: Vec<Box<AiPostProcessDyn>>,
91}
92
93impl PostProcess {
94    pub fn new(processors: Vec<Box<AiPostProcessDyn>>) -> Self {
95        Self { processors }
96    }
97
98    pub fn process(
99        &mut self,
100        scene: &mut AiScene,
101        steps: BitFlags<AiPostProcessSteps>,
102    ) -> Result<(), AiPostProcessError> {
103        for processor in self.processors.iter_mut() {
104            if processor.prepare(steps) {
105                processor.process(scene)?;
106            }
107        }
108        Ok(())
109    }
110}
111
112pub struct AiPostProcesserWrapper<T: AiPostProcess>
113where
114    T::Error: Into<AiPostProcessError>,
115{
116    inner: T,
117}
118
119impl<T: AiPostProcess> AiPostProcesserWrapper<T>
120where
121    T::Error: Into<AiPostProcessError>,
122{
123    pub fn new(inner: T) -> Self {
124        Self { inner }
125    }
126
127    pub fn into_inner(self) -> T {
128        self.inner
129    }
130
131    pub fn inner(&self) -> &T {
132        &self.inner
133    }
134
135    pub fn inner_mut(&mut self) -> &mut T {
136        &mut self.inner
137    }
138}
139
140impl<T: AiPostProcess> AiPostProcess for AiPostProcesserWrapper<T>
141where
142    T::Error: Into<AiPostProcessError>,
143{
144    type Error = AiPostProcessError;
145
146    fn prepare(&mut self, steps: BitFlags<AiPostProcessSteps>) -> bool {
147        self.inner.prepare(steps)
148    }
149
150    fn process(&self, scene: &mut AiScene) -> Result<(), Self::Error> {
151        self.inner.process(scene).map_err(Into::into)
152    }
153}
154pub struct AiPostProcesser;
155
156impl AiPostProcesser {
157    pub fn post_process() -> PostProcess {
158        PostProcess::new(vec![
159            #[cfg(feature = "calc-tangent-spaces")]
160            Box::new(AiPostProcesserWrapper::new(CalcTangentSpaces)),
161            #[cfg(feature = "find-degenerates")]
162            Box::new(AiPostProcesserWrapper::new(FindDegenerates)),
163            #[cfg(feature = "find-invalid-data")]
164            Box::new(AiPostProcesserWrapper::new(FindInvalidData)),
165            #[cfg(feature = "gen-normals")]
166            Box::new(AiPostProcesserWrapper::new(GenNormals::default())),
167            #[cfg(feature = "gen-smooth-normals")]
168            Box::new(AiPostProcesserWrapper::new(GenSmoothNormals::default())),
169            #[cfg(feature = "join-identical-vertices")]
170            Box::new(AiPostProcesserWrapper::new(JoinIdenticalVertices)),
171            #[cfg(feature = "optimize-graph")]
172            Box::new(AiPostProcesserWrapper::new(OptimizeGraph)),
173            #[cfg(feature = "optimize-meshes")]
174            Box::new(AiPostProcesserWrapper::new(OptimizeMeshes)),
175            #[cfg(feature = "remove-redundant-materials")]
176            Box::new(AiPostProcesserWrapper::new(RemoveRedundantMaterials)),
177            #[cfg(feature = "triangulate")]
178            Box::new(AiPostProcesserWrapper::new(Triangulate)),
179            #[cfg(feature = "validate-data-structure")]
180            Box::new(AiPostProcesserWrapper::new(ValidateDataStructure)),
181            #[cfg(feature = "debone")]
182            Box::new(AiPostProcesserWrapper::new(Debone)),
183            #[cfg(feature = "drop-normals")]
184            Box::new(AiPostProcesserWrapper::new(DropNormals)),
185            #[cfg(feature = "embed-textures")]
186            Box::new(AiPostProcesserWrapper::new(EmbedTextures)),
187            #[cfg(feature = "find-instances")]
188            Box::new(AiPostProcesserWrapper::new(FindInstances)),
189            #[cfg(feature = "fix-infacing-normals")]
190            Box::new(AiPostProcesserWrapper::new(FixInfacingNormals)),
191            #[cfg(feature = "flip-uvs")]
192            Box::new(AiPostProcesserWrapper::new(FlipUVs::default())),
193            #[cfg(feature = "flip-winding-order")]
194            Box::new(AiPostProcesserWrapper::new(FlipWindingOrder)),
195            #[cfg(feature = "force-gen-normals")]
196            Box::new(AiPostProcesserWrapper::new(ForceGenNormals)),
197            #[cfg(feature = "gen-bounding-boxes")]
198            Box::new(AiPostProcesserWrapper::new(GenBoundingBoxes)),
199            #[cfg(feature = "gen-uv-coords")]
200            Box::new(AiPostProcesserWrapper::new(GenUVCoords)),
201            #[cfg(feature = "global-scale")]
202            Box::new(AiPostProcesserWrapper::new(GlobalScale)),
203            #[cfg(feature = "improve-cache-locality")]
204            Box::new(AiPostProcesserWrapper::new(ImproveCacheLocality)),
205            #[cfg(feature = "limit-bone-weights")]
206            Box::new(AiPostProcesserWrapper::new(LimitBoneWeights)),
207            #[cfg(feature = "make-left-handed")]
208            Box::new(AiPostProcesserWrapper::new(MakeLeftHanded)),
209            #[cfg(feature = "populate-armature-data")]
210            Box::new(AiPostProcesserWrapper::new(PopulateArmatureData)),
211            #[cfg(feature = "pre-transform-vertices")]
212            Box::new(AiPostProcesserWrapper::new(PreTransformVertices)),
213            #[cfg(feature = "remove-component")]
214            Box::new(AiPostProcesserWrapper::new(RemoveComponent)),
215            #[cfg(feature = "sort-by-p-type")]
216            Box::new(AiPostProcesserWrapper::new(SortByPType)),
217            #[cfg(feature = "split-by-bone-count")]
218            Box::new(AiPostProcesserWrapper::new(SplitByBoneCount)),
219            #[cfg(feature = "split-large-meshes")]
220            Box::new(AiPostProcesserWrapper::new(SplitLargeMeshes)),
221            #[cfg(feature = "transform-uv-coords")]
222            Box::new(AiPostProcesserWrapper::new(TransformUVCoords)),
223        ])
224    }
225}