1use crate::serialization::core::{Camera, Configuration};
2use crate::serialization::environment::SerializeEnvironment;
3use crate::serialization::geometry::SerializeGeometry;
4use crate::serialization::{IdConstructor, IdReference, RayTracingObject};
5use ray_tracing_core::core;
6use ray_tracing_core::environment;
7use ray_tracing_core::geometry;
8use ray_tracing_core::material;
9use ray_tracing_core::texture;
10use serde::{Deserialize, Serialize};
11use std::cell::RefCell;
12use std::collections::HashMap;
13use std::error::Error;
14use std::path::Path;
15use std::rc::Rc;
16use std::sync::Arc;
17
18#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
19pub struct Scene {
20 pub configuration_id: usize,
21
22 pub camera_id: usize,
23
24 pub sky_id: usize,
25
26 pub root_node_id: usize,
27
28 #[serde(default = "Scene::default_light_node")]
29 pub light_node_id: usize,
30
31 pub objects: Vec<RayTracingObject>,
32}
33
34pub struct DeserializeOptions {
35 pub root_path: Option<String>,
36}
37
38impl DeserializeOptions {
39 pub fn default() -> DeserializeOptions {
40 DeserializeOptions { root_path: None }
41 }
42
43 pub fn form_path(root_path: &Path) -> DeserializeOptions {
44 DeserializeOptions {
45 root_path: match root_path.to_str() {
46 Some(path) => Some(String::from(path)),
47 None => None,
48 },
49 }
50 }
51}
52
53impl Scene {
54 fn default_light_node() -> usize {
55 0
56 }
57
58 pub fn from_scene(s: &core::Scene) -> Result<Scene, Box<dyn Error>> {
59 let object_map = Rc::new(RefCell::new(HashMap::<usize, RayTracingObject>::default()));
60 object_map.borrow_mut().insert(
61 s.configuration.id,
62 RayTracingObject::Configuration(Configuration::from_configuration(&s.configuration)?),
63 );
64 object_map.borrow_mut().insert(
65 s.camera.id,
66 RayTracingObject::Camera(Camera::from_camera(&s.camera)?),
67 );
68 let mut se = SerializeEnvironment {
69 object_map: object_map.clone(),
70 };
71 s.sky.accept(&mut se)?;
72 let mut sh = SerializeGeometry {
73 object_map: object_map.clone(),
74 collection: None,
75 };
76 s.world.accept(&mut sh)?;
77 drop(sh);
78 let mut tuples: Vec<(usize, RayTracingObject)> = object_map.take().into_iter().collect();
80 tuples.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
81 let objects = tuples.iter().map(|(_id, obj)| obj.clone()).collect();
82 Ok(Scene {
83 camera_id: s.camera.id,
84 root_node_id: s.world.get_id(),
85 sky_id: s.sky.get_id(),
86 configuration_id: s.configuration.id,
87 light_node_id: 0,
88 objects: objects,
89 })
90 }
91
92 pub fn to_scene(&self) -> Result<core::Scene, Box<dyn Error>> {
93 self.to_scene_with_options(&DeserializeOptions::default())
94 }
95
96 pub fn insert_texture<T, F>(
97 container: &mut HashMap<usize, Arc<dyn texture::Texture>>,
98 id: &IdConstructor,
99 object: &T,
100 convert: F,
101 ) where
102 F: Fn(&T, usize, &HashMap<usize, Arc<dyn texture::Texture>>) -> Arc<dyn texture::Texture>,
103 {
104 for index in 0..id.len() {
105 container.insert(id.get_id(index), convert(object, index, container));
106 }
107 }
108
109 pub fn insert_material<T, F>(
110 container: &mut HashMap<usize, Arc<dyn material::Material>>,
111 id: &IdConstructor,
112 object: &T,
113 convert: F,
114 ) where
115 F: Fn(
116 &T,
117 usize,
118 &HashMap<usize, Arc<dyn material::Material>>,
119 ) -> Arc<dyn material::Material>,
120 {
121 for index in 0..id.len() {
122 container.insert(id.get_id(index), convert(object, index, container));
123 }
124 }
125
126 pub fn insert_geometry<T, F>(
127 container: &mut HashMap<usize, Arc<dyn geometry::Geometry>>,
128 id: &IdConstructor,
129 object: &T,
130 convert: F,
131 ) where
132 F: Fn(
133 &T,
134 usize,
135 &HashMap<usize, Arc<dyn geometry::Geometry>>,
136 ) -> Arc<dyn geometry::Geometry>,
137 {
138 for index in 0..id.len() {
139 container.insert(id.get_id(index), convert(object, index, container));
140 }
141 }
142
143 pub fn to_scene_with_options(
144 &self,
145 deserialize_options: &DeserializeOptions,
146 ) -> Result<core::Scene, Box<dyn Error>> {
147 let mut configuration_map = HashMap::<usize, core::Configuration>::default();
148 let mut camera_map = HashMap::<usize, Arc<core::Camera>>::default();
149 let mut texture_map = HashMap::<usize, Arc<dyn texture::Texture>>::default();
150 for obj in self.objects.iter() {
151 match obj {
152 RayTracingObject::Configuration(c) => {
153 for index in 0..c.id.len() {
154 configuration_map.insert(c.id.get_id(index), c.to_configuration(index)?);
155 }
156 }
157 RayTracingObject::Camera(c) => {
158 for index in 0..c.id.len() {
159 camera_map.insert(c.id.get_id(index), Arc::new(c.to_camera(index)?));
160 }
161 }
162 RayTracingObject::CameraVerticalField(c) => {
163 for index in 0..c.id.len() {
164 camera_map.insert(c.id.get_id(index), Arc::new(c.to_camera(index)?));
165 }
166 }
167 RayTracingObject::CameraLookAt(c) => {
168 for index in 0..c.id.len() {
169 camera_map.insert(c.id.get_id(index), Arc::new(c.to_camera(index)?));
170 }
171 }
172 RayTracingObject::ConstantTexture(t) => {
173 Scene::insert_texture(&mut texture_map, &t.id, t, |t, i, _| {
174 Arc::new(t.to_texture(i).unwrap())
175 })
176 }
177 RayTracingObject::BitmapFile(t) => {
178 Scene::insert_texture(&mut texture_map, &t.id, t, |t, i, _| {
179 Arc::new(t.to_texture(i, &deserialize_options.root_path).unwrap())
180 })
181 }
182
183 RayTracingObject::CheckerTexture(t) => {
184 Scene::insert_texture(&mut texture_map, &t.id, t, |t, i, tm| {
185 Arc::new(
186 t.to_texture(
187 i,
188 Scene::get_texture(tm, &t.even_texture, i),
189 Scene::get_texture(tm, &t.odd_texture, i),
190 )
191 .unwrap(),
192 )
193 })
194 }
195 RayTracingObject::BlendTexture(t) => {
196 Scene::insert_texture(&mut texture_map, &t.id, t, |t, i, tm| {
197 Arc::new(
198 t.to_texture(
199 i,
200 Scene::get_texture(tm, &t.first_texture, i),
201 Scene::get_texture(tm, &t.second_texture, i),
202 Scene::get_texture(tm, &t.mask_texture, i),
203 )
204 .unwrap(),
205 )
206 })
207 }
208 RayTracingObject::NoiseTexture(t) => {
209 Scene::insert_texture(&mut texture_map, &t.id, t, |t, i, tm| {
210 Arc::new(
211 t.to_texture(
212 i,
213 Scene::get_texture(tm, &t.min_texture, i),
214 Scene::get_texture(tm, &t.max_texture, i),
215 )
216 .unwrap(),
217 )
218 })
219 }
220 RayTracingObject::ColorFilter(f) => {
221 Scene::insert_texture(&mut texture_map, &f.id, f, |t, i, tm| {
222 Arc::new(
223 f.to_texture(i, Scene::get_texture(tm, &t.texture, i))
224 .unwrap(),
225 )
226 })
227 }
228 _ => (),
229 };
230 }
231 let mut material_map = HashMap::<usize, Arc<dyn material::Material>>::default();
232 let mut environment_map = HashMap::<usize, Arc<dyn environment::Environment>>::default();
233 for obj in self.objects.iter() {
234 match obj {
235 RayTracingObject::NoMaterial(m) => {
236 Scene::insert_material(&mut material_map, &m.id, m, |m, i, _| {
237 Arc::new(m.to_material(i).unwrap())
238 })
239 }
240 RayTracingObject::Lambertian(m) => {
241 Scene::insert_material(&mut material_map, &m.id, m, |m, i, _| {
242 Arc::new(
243 m.to_material(i, Scene::get_texture(&texture_map, &m.albedo, i))
244 .unwrap(),
245 )
246 })
247 }
248 RayTracingObject::Metal(m) => {
249 Scene::insert_material(&mut material_map, &m.id, m, |m, i, _| {
250 Arc::new(
251 m.to_material(i, Scene::get_texture(&texture_map, &m.albedo, i))
252 .unwrap(),
253 )
254 })
255 }
256 RayTracingObject::Dielectric(m) => {
257 Scene::insert_material(&mut material_map, &m.id, m, |m, i, _| {
258 Arc::new(
259 m.to_material(i, Scene::get_texture(&texture_map, &m.albedo, i))
260 .unwrap(),
261 )
262 })
263 }
264 RayTracingObject::Isotropic(m) => {
265 Scene::insert_material(&mut material_map, &m.id, m, |m, i, _| {
266 Arc::new(
267 m.to_material(i, Scene::get_texture(&texture_map, &m.albedo, i))
268 .unwrap(),
269 )
270 })
271 }
272 RayTracingObject::DiffuseLight(m) => {
273 Scene::insert_material(&mut material_map, &m.id, m, |m, i, _| {
274 Arc::new(
275 m.to_material(i, Scene::get_texture(&texture_map, &m.emit, i))
276 .unwrap(),
277 )
278 })
279 }
280 RayTracingObject::Sky(s) => {
281 for index in 0..s.id.len() {
282 environment_map
283 .insert(s.id.get_id(index), Arc::new(s.to_environment(index)?));
284 }
285 }
286 _ => (),
287 };
288 }
289 for obj in self.objects.iter() {
290 match obj {
291 RayTracingObject::MaterialBlend(m) => {
292 for index in 0..m.id.len() {
293 let v = m
294 .materials
295 .iter()
296 .map(|id| Scene::get_material(&material_map, id, index))
297 .collect();
298 material_map
299 .insert(m.id.get_id(index), Arc::new(m.to_material(index, &v)?));
300 }
301 }
302 _ => (),
303 }
304 }
305 let mut object_map = HashMap::<usize, Arc<dyn geometry::Geometry>>::default();
306 for obj in self.objects.iter() {
307 match obj {
308 RayTracingObject::Sphere(h) => {
309 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, _| {
310 Arc::new(
311 h.to_shape(i, Scene::get_material(&material_map, &h.material, i))
312 .unwrap(),
313 )
314 })
315 }
316 RayTracingObject::MovableSphere(h) => {
317 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, _| {
318 Arc::new(
319 h.to_shape(i, Scene::get_material(&material_map, &h.material, i))
320 .unwrap(),
321 )
322 })
323 }
324 RayTracingObject::Collection(c) => {
325 let mut obj_list = Vec::<Arc<dyn geometry::Geometry>>::default();
326 for id in IdReference::get_list(&c.object_id_list) {
327 obj_list.push(Scene::get_geometry(
328 &object_map,
329 &IdReference::Single(id),
330 0,
331 ));
332 }
333 Scene::insert_geometry(&mut object_map, &c.id, c, |c, _, _| {
334 c.to_collection(&obj_list, 0.0..0.0).unwrap()
335 })
336 }
337 RayTracingObject::XYRect(h) => {
338 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, _| {
339 Arc::new(
340 h.to_shape(i, Scene::get_material(&material_map, &h.material, i))
341 .unwrap(),
342 )
343 })
344 }
345 RayTracingObject::XZRect(h) => {
346 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, _| {
347 Arc::new(
348 h.to_shape(i, Scene::get_material(&material_map, &h.material, i))
349 .unwrap(),
350 )
351 })
352 }
353 RayTracingObject::YZRect(h) => {
354 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, _| {
355 Arc::new(
356 h.to_shape(i, Scene::get_material(&material_map, &h.material, i))
357 .unwrap(),
358 )
359 })
360 }
361 RayTracingObject::Cuboid(h) => {
362 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, _| {
363 Arc::new(
364 h.to_shape(i, Scene::get_material(&material_map, &h.material, i))
365 .unwrap(),
366 )
367 })
368 }
369 RayTracingObject::ConstantMedium(h) => {
370 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, om| {
371 Arc::new(
372 h.to_volume(
373 i,
374 Scene::get_geometry(&om, &h.boundary, i),
375 Scene::get_material(&material_map, &h.phase_function, i),
376 )
377 .unwrap(),
378 )
379 })
380 }
381 RayTracingObject::FlipNormals(h) => {
382 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, om| {
383 Arc::new(
384 h.to_geometry(i, Scene::get_geometry(&om, &h.node, i))
385 .unwrap(),
386 )
387 })
388 }
389 RayTracingObject::RotateX(h) => {
390 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, om| {
391 Arc::new(
392 h.to_geometry(i, Scene::get_geometry(&om, &h.node, i))
393 .unwrap(),
394 )
395 })
396 }
397 RayTracingObject::RotateY(h) => {
398 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, om| {
399 Arc::new(
400 h.to_geometry(i, Scene::get_geometry(&om, &h.node, i))
401 .unwrap(),
402 )
403 })
404 }
405 RayTracingObject::RotateZ(h) => {
406 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, om| {
407 Arc::new(
408 h.to_geometry(i, Scene::get_geometry(&om, &h.node, i))
409 .unwrap(),
410 )
411 })
412 }
413 RayTracingObject::Translate(h) => {
414 Scene::insert_geometry(&mut object_map, &h.id, h, |h, i, om| {
415 Arc::new(
416 h.to_geometry(i, Scene::get_geometry(&om, &h.node, i))
417 .unwrap(),
418 )
419 })
420 }
421 _ => (),
422 };
423 }
424 let light = if self.light_node_id > 0 {
425 Some(Scene::get_geometry(
426 &object_map,
427 &IdReference::Single(self.light_node_id),
428 0,
429 ))
430 } else {
431 None
432 };
433 Ok(core::Scene::new(
434 Scene::get_configuration(&configuration_map, &self.configuration_id),
435 Scene::get_camera(&camera_map, &self.camera_id),
436 Scene::get_environment(&environment_map, &self.sky_id),
437 Scene::get_geometry(&object_map, &IdReference::Single(self.root_node_id), 0),
438 light,
439 ))
440 }
441
442 fn get_configuration(
443 configuration_map: &HashMap<usize, core::Configuration>,
444 id: &usize,
445 ) -> core::Configuration {
446 if !configuration_map.contains_key(id) {
447 panic!("No configuration with id {} found", id);
448 }
449 configuration_map[id].clone()
450 }
451
452 fn get_camera(camera_map: &HashMap<usize, Arc<core::Camera>>, id: &usize) -> Arc<core::Camera> {
453 if !camera_map.contains_key(id) {
454 panic!("No camera with id {} found", id);
455 }
456 camera_map[id].clone()
457 }
458
459 fn get_environment(
460 environment_map: &HashMap<usize, Arc<dyn environment::Environment>>,
461 id: &usize,
462 ) -> Arc<dyn environment::Environment> {
463 if !environment_map.contains_key(id) {
464 panic!("No environment with id {} found", id);
465 }
466 environment_map[id].clone()
467 }
468
469 fn get_texture(
470 texture_map: &HashMap<usize, Arc<dyn texture::Texture>>,
471 id: &IdReference,
472 index: usize,
473 ) -> Arc<dyn texture::Texture> {
474 let id = id.get_id(index);
475 if !texture_map.contains_key(&id) {
476 panic!("No texture with id {} found", id);
477 }
478 texture_map[&id].clone()
479 }
480
481 fn get_material(
482 material_map: &HashMap<usize, Arc<dyn material::Material>>,
483 id: &IdReference,
484 index: usize,
485 ) -> Arc<dyn material::Material> {
486 let id = id.get_id(index);
487 if !material_map.contains_key(&id) {
488 panic!("No material with id {} found", id);
489 }
490 material_map[&id].clone()
491 }
492
493 fn get_geometry(
494 object_map: &HashMap<usize, Arc<dyn geometry::Geometry>>,
495 id: &IdReference,
496 index: usize,
497 ) -> Arc<dyn geometry::Geometry> {
498 let id = id.get_id(index);
499 if !object_map.contains_key(&id) {
500 panic!("No hit able object with id {} found", id);
501 }
502 object_map[&id].clone()
503 }
504}
505
506#[cfg(test)]
507mod serialize_scene_test {
508 use super::*;
509 use ray_tracing_core::test;
510
511 #[test]
512 fn serialize_scene_from_scene() {
513 let ts = test::TestSceneSimple::new();
514 let s = Scene::from_scene(&ts.scene).unwrap();
515 assert_eq!(s.objects.len(), 10);
516 }
517
518 #[test]
519 fn serialize_scene_to_scene() {
520 let ts = test::TestSceneSimple::new();
521 let s = Scene::from_scene(&ts.scene).unwrap();
522 let ds = s.to_scene().unwrap();
523 assert_eq!(ds.configuration.maximum_depth, 50);
524 }
525}