ray_tracing_utility/serialization/
texture.rs

1use crate::serialization::RayTracingObject;
2use ray_tracing_core::texture;
3use std::cell::RefCell;
4use std::collections::HashMap;
5use std::error::Error;
6use std::rc::Rc;
7use std::sync::Arc;
8
9mod constant_texture;
10pub use self::constant_texture::*;
11
12mod bitmap_file;
13pub use self::bitmap_file::*;
14
15mod checker_texture;
16pub use self::checker_texture::*;
17
18mod blend_texture;
19pub use self::blend_texture::*;
20
21mod noise_texture;
22pub use self::noise_texture::*;
23
24mod color_filter;
25pub use self::color_filter::*;
26
27pub struct SerializeTexture {
28    pub object_map: Rc<RefCell<HashMap<usize, RayTracingObject>>>,
29}
30
31impl SerializeTexture {
32    fn add_texture(&mut self, t: Arc<dyn texture::Texture>) -> Result<(), Box<dyn Error>> {
33        if !self.object_map.borrow().contains_key(&t.get_id()) {
34            t.accept(self)?;
35        }
36        Ok(())
37    }
38}
39
40impl texture::Visitor for SerializeTexture {
41    fn visit_constant_texture(
42        &mut self,
43        t: &texture::ConstantTexture,
44    ) -> Result<(), Box<dyn Error>> {
45        self.object_map.borrow_mut().insert(
46            t.id,
47            RayTracingObject::ConstantTexture(ConstantTexture::from_texture(t)?),
48        );
49        Ok(())
50    }
51
52    fn visit_bitmap_texture(&mut self, _: &texture::BitmapTexture) -> Result<(), Box<dyn Error>> {
53        Err("not yet implemented".into())
54    }
55
56    fn visit_checker_texture(&mut self, t: &texture::CheckerTexture) -> Result<(), Box<dyn Error>> {
57        self.add_texture(t.even_texture.clone())?;
58        self.add_texture(t.odd_texture.clone())?;
59
60        self.object_map.borrow_mut().insert(
61            t.id,
62            RayTracingObject::CheckerTexture(CheckerTexture::from_texture(t)?),
63        );
64        Ok(())
65    }
66
67    fn visit_blend_texture(&mut self, t: &texture::BlendTexture) -> Result<(), Box<dyn Error>> {
68        self.add_texture(t.first_texture.clone())?;
69        self.add_texture(t.second_texture.clone())?;
70        self.add_texture(t.mask_texture.clone())?;
71
72        self.object_map.borrow_mut().insert(
73            t.id,
74            RayTracingObject::BlendTexture(BlendTexture::from_texture(t)?),
75        );
76        Ok(())
77    }
78
79    fn visit_noise_texture(&mut self, t: &texture::NoiseTexture) -> Result<(), Box<dyn Error>> {
80        self.add_texture(t.min_texture.clone())?;
81        self.add_texture(t.max_texture.clone())?;
82
83        self.object_map.borrow_mut().insert(
84            t.id,
85            RayTracingObject::NoiseTexture(NoiseTexture::from_texture(t)?),
86        );
87        Ok(())
88    }
89
90    fn visit_color_filter(&mut self, t: &texture::ColorFilter) -> Result<(), Box<dyn Error>> {
91        self.add_texture(t.texture.clone())?;
92
93        self.object_map.borrow_mut().insert(
94            t.id,
95            RayTracingObject::ColorFilter(ColorFilter::from_texture(t)?),
96        );
97        Ok(())
98    }
99}
100
101#[cfg(test)]
102mod serialize_texture_test {
103    use super::*;
104    use ray_tracing_core::texture::Texture;
105    use ray_tracing_core::types::{ColorRGBA, Vector3};
106
107    #[test]
108    fn visit_constant_texture_test() {
109        let mut s = SerializeTexture {
110            object_map: Rc::new(RefCell::new(HashMap::default())),
111        };
112        let ct = texture::ConstantTexture::new(ColorRGBA::new(0.0, 0.0, 0.0, 1.0));
113        ct.accept(&mut s).unwrap();
114        assert_eq!(s.object_map.borrow_mut().len(), 1);
115        match &s.object_map.borrow_mut()[&ct.id] {
116            RayTracingObject::ConstantTexture(_) => (),
117            _ => panic!("unexpected ray tracing object"),
118        };
119    }
120
121    #[test]
122    fn visit_checker_texture_test() {
123        let mut s = SerializeTexture {
124            object_map: Rc::new(RefCell::new(HashMap::default())),
125        };
126        let ct1 = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
127            0.0, 0.0, 0.0, 1.0,
128        )));
129        let ct1_id = ct1.clone().id;
130        let ct2 = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
131            1.0, 1.0, 1.0, 1.0,
132        )));
133        let ct2_id = ct2.clone().id;
134        let ct = texture::CheckerTexture::new(Vector3::new(1.0, 1.0, 1.0), ct1, ct2);
135        ct.accept(&mut s).unwrap();
136        assert_eq!(s.object_map.borrow_mut().len(), 3);
137        match &s.object_map.borrow_mut()[&ct1_id] {
138            RayTracingObject::ConstantTexture(_) => (),
139            _ => panic!("unexpected ray tracing object"),
140        };
141        match &s.object_map.borrow_mut()[&ct2_id] {
142            RayTracingObject::ConstantTexture(_) => (),
143            _ => panic!("unexpected ray tracing object"),
144        };
145        match &s.object_map.borrow_mut()[&ct.id] {
146            RayTracingObject::CheckerTexture(_) => (),
147            _ => panic!("unexpected ray tracing object"),
148        };
149    }
150
151    #[test]
152    fn visit_blend_texture_test() {
153        let mut s = SerializeTexture {
154            object_map: Rc::new(RefCell::new(HashMap::default())),
155        };
156        let ct1 = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
157            0.0, 0.0, 0.0, 1.0,
158        )));
159        let ct1_id = ct1.clone().id;
160        let ct2 = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
161            1.0, 1.0, 1.0, 1.0,
162        )));
163        let ct2_id = ct2.clone().id;
164        let mt = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
165            0.5, 0.5, 0.5, 0.5,
166        )));
167        let mt_id = mt.clone().id;
168        let ct = texture::BlendTexture::new(Vector3::new(0.5, 0.5, 0.5), ct1, ct2, mt);
169        ct.accept(&mut s).unwrap();
170        assert_eq!(s.object_map.borrow_mut().len(), 4);
171        match &s.object_map.borrow_mut()[&ct1_id] {
172            RayTracingObject::ConstantTexture(_) => (),
173            _ => panic!("unexpected ray tracing object"),
174        };
175        match &s.object_map.borrow_mut()[&ct2_id] {
176            RayTracingObject::ConstantTexture(_) => (),
177            _ => panic!("unexpected ray tracing object"),
178        };
179        match &s.object_map.borrow_mut()[&mt_id] {
180            RayTracingObject::ConstantTexture(_) => (),
181            _ => panic!("unexpected ray tracing object"),
182        };
183        match &s.object_map.borrow_mut()[&ct.id] {
184            RayTracingObject::BlendTexture(_) => (),
185            _ => panic!("unexpected ray tracing object"),
186        };
187    }
188
189    #[test]
190    fn visit_noise_texture_test() {
191        let mut s = SerializeTexture {
192            object_map: Rc::new(RefCell::new(HashMap::default())),
193        };
194        let ct1 = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
195            0.0, 0.0, 0.0, 1.0,
196        )));
197        let ct1_id = ct1.clone().id;
198        let ct2 = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
199            1.0, 1.0, 1.0, 1.0,
200        )));
201        let ct2_id = ct2.clone().id;
202        let ct = texture::NoiseTexture::new(1.0, texture::NoiseType::Default, ct1, ct2);
203        ct.accept(&mut s).unwrap();
204        assert_eq!(s.object_map.borrow_mut().len(), 3);
205        match &s.object_map.borrow_mut()[&ct1_id] {
206            RayTracingObject::ConstantTexture(_) => (),
207            _ => panic!("unexpected ray tracing object"),
208        };
209        match &s.object_map.borrow_mut()[&ct2_id] {
210            RayTracingObject::ConstantTexture(_) => (),
211            _ => panic!("unexpected ray tracing object"),
212        };
213        match &s.object_map.borrow_mut()[&ct.id] {
214            RayTracingObject::NoiseTexture(_) => (),
215            _ => panic!("unexpected ray tracing object"),
216        };
217    }
218
219    #[test]
220    fn visit_color_filter_test() {
221        let mut s = SerializeTexture {
222            object_map: Rc::new(RefCell::new(HashMap::default())),
223        };
224        let ct = Arc::new(texture::ConstantTexture::new(ColorRGBA::new(
225            1.0, 1.0, 1.0, 1.0,
226        )));
227        let ct_id = ct.clone().id;
228        let cf = texture::ColorFilter::new(
229            ColorRGBA::new(0.0, 0.0, 0.0, 0.0),
230            ColorRGBA::new(1.0, 0.5, 0.25, 1.0),
231            ColorRGBA::new(0.0, 0.0, 0.0, 0.0),
232            ct,
233        );
234        cf.accept(&mut s).unwrap();
235        assert_eq!(s.object_map.borrow_mut().len(), 2);
236        match &s.object_map.borrow_mut()[&ct_id] {
237            RayTracingObject::ConstantTexture(_) => (),
238            _ => panic!("unexpected ray tracing object"),
239        };
240        match &s.object_map.borrow_mut()[&cf.id] {
241            RayTracingObject::ColorFilter(_) => (),
242            _ => panic!("unexpected ray tracing object"),
243        };
244    }
245}