1use super::graphics_state::GraphicsState;
2use super::graphics_state::MaterialInstance;
3use super::render_options::RenderOptions;
4
5use crate::accelerators::*;
6use crate::cameras::*;
7use crate::core::api::parse_context::*;
8use crate::core::base::*;
9use crate::core::camera::*;
10use crate::core::error::*;
11use crate::core::film::*;
12use crate::core::filter::*;
13use crate::core::integrator::*;
14use crate::core::light::*;
15use crate::core::material::*;
16use crate::core::medium::*;
17use crate::core::param_set::*;
18use crate::core::primitive::*;
19use crate::core::scene::*;
20use crate::core::shape::*;
21use crate::core::spectrum::*;
22use crate::core::stats::*;
23use crate::core::texture::*;
24use crate::core::transform::transform_set::*;
25use crate::core::transform::*;
26use crate::filters::*;
27use crate::integrators::*;
28use crate::lights::*;
29use crate::materials::*;
30use crate::media::*;
31use crate::samplers::*;
32use crate::shapes::*;
33use crate::textures::*;
34
35use log::*;
36use std::cell::RefCell;
37use std::collections::HashMap;
38use std::ops::Deref;
39use std::path::Path;
40use std::sync::Arc;
41use std::sync::RwLock;
42
43thread_local!(static N_SHAPES: StatCounter = StatCounter::new("Scene/Shapes")); thread_local!(static N_LIGHTS: StatCounter = StatCounter::new("Scene/Lights"));
45thread_local!(static N_AREA_LIGHTS: StatCounter = StatCounter::new("Scene/AreaLights"));
46thread_local!(static N_MATERIALS: StatCounter = StatCounter::new("Scene/Materials")); thread_local!(static N_OBJECT_INSTANCES_CREATED: StatCounter = StatCounter::new("Scene/Object instances created")); thread_local!(static N_OBJECT_INSTANCES_USED: StatCounter = StatCounter::new("Scene/Object instances used")); #[derive(Debug, PartialEq)]
51enum APIState {
52 OptionsBlock,
53 WorldBlock,
54}
55
56fn get_param_type(s: &str) -> (&str, &str) {
57 let ss: Vec<&str> = s.split_ascii_whitespace().collect();
58 if ss.len() == 2 {
59 return (ss[0], ss[1]);
60 } else if ss.len() == 1 {
61 if let Some(t) = wellknown_params::find_type_from_key(ss[0]) {
62 return (t, ss[0]);
63 } else {
64 return ("", ss[0]);
65 }
66 } else {
67 return ("", s);
68 }
69}
70
71type FloatTextureMap = HashMap<String, Arc<dyn Texture<Float>>>;
72pub struct SceneContext {
75 current_api_state: APIState,
76 transforms: Vec<RefCell<TransformSet>>,
77 transform_bits: Vec<u32>,
78 graphics_states: Vec<RefCell<GraphicsState>>,
79 render_options: RefCell<RenderOptions>,
80 named_coordinate_systems: HashMap<String, RefCell<TransformSet>>,
81 float_textures: RefCell<HashMap<String, Arc<dyn Texture<Float>>>>,
82 spectrum_textures: RefCell<HashMap<String, Arc<dyn Texture<Spectrum>>>>,
83 work_dirs: Vec<String>,
84}
85
86impl SceneContext {
87 pub fn new() -> Self {
88 let mut ctx = SceneContext {
89 current_api_state: APIState::OptionsBlock,
90 transforms: Vec::new(),
91 transform_bits: Vec::new(),
92 graphics_states: Vec::new(),
93 render_options: RefCell::new(RenderOptions::new()),
94 named_coordinate_systems: HashMap::new(),
95 float_textures: RefCell::new(HashMap::new()),
96 spectrum_textures: RefCell::new(HashMap::new()),
97 work_dirs: Vec::new(),
98 };
99 ctx.initialize();
100 return ctx;
101 }
102
103 pub fn initialize(&mut self) {
104 self.transforms.clear();
105 self.transform_bits.clear();
106 self.graphics_states.clear();
107 self.transforms.push(RefCell::new(TransformSet::new()));
108 self.transform_bits.push(ALL_TRANSFORM_BITS);
109 self.graphics_states
110 .push(RefCell::new(GraphicsState::new()));
111 }
112
113 pub fn push_transform(&mut self) {
114 self.transforms
115 .push(self.transforms[self.transforms.len() - 1].clone());
116 self.transform_bits
117 .push(self.transform_bits[self.transform_bits.len() - 1]);
118 }
119
120 pub fn pop_transform(&mut self) {
121 self.transform_bits.pop();
122 self.transforms.pop();
123 }
124
125 pub fn push_graphics_state(&mut self) {
126 self.graphics_states
127 .push(self.graphics_states[self.transforms.len() - 1].clone());
128 }
129
130 pub fn pop_graphics_state(&mut self) {
131 self.graphics_states.pop();
132 }
133
134 pub fn print_error(&self, e: &PbrtError) {
135 match e.kind {
136 PbrtErrorKind::Error => {
137 error!("{}", e.msg);
138 }
139 PbrtErrorKind::Warning => {
140 warn!("{}", e.msg);
141 }
142 }
143 }
144
145 pub fn verify_initialized(&mut self, _fun: &str) {
146 }
148
149 pub fn verify_options(&mut self, fun: &str) {
150 if self.current_api_state != APIState::OptionsBlock {
151 error!(
152 "Options cannot be set inside world block;\n\"{}\" not allowed. Ignoring.",
153 fun
154 );
155 }
156 }
157
158 pub fn verify_world(&mut self, fun: &str) {
159 if self.current_api_state == APIState::WorldBlock {
160 error!(
161 "Scene description must be inside world block;\n\"{}\" not allowed. Ignoring.",
162 fun
163 );
164 }
165 }
166
167 pub fn replace_params_int(
168 &mut self,
169 name: &str,
170 key: &str,
171 value: i32,
172 ) -> Result<(), PbrtError> {
173 match name {
174 "Sampler" => {
175 let mut opts = self.render_options.borrow_mut();
176 let params = &mut opts.sampler_params;
177 params.replace_one_int(key, value);
178 return Ok(());
179 }
180 _ => {
181 let msg = format!("\"{}\" is unknown params name.", name);
182 return Err(PbrtError::error(&msg));
183 }
184 }
185 }
186
187 pub fn replace_params_string(
188 &mut self,
189 name: &str,
190 key: &str,
191 value: &str,
192 ) -> Result<(), PbrtError> {
193 match name {
194 "Film" => {
195 let mut opts = self.render_options.borrow_mut();
196 let params = &mut opts.film_params;
197 params.replace_one_string(key, value);
198 return Ok(());
199 }
200 _ => {
201 let msg = format!("\"{}\" is unknown params name.", name);
202 return Err(PbrtError::error(&msg));
203 }
204 }
205 }
206
207 pub fn create_medium_interface(&self) -> MediumInterface {
208 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
209 let opts = self.render_options.borrow();
210 let inside_name = attr.current_inside_medium.clone();
211 let outside_name = attr.current_outside_medium.clone();
212 let mut m = MediumInterface::new();
213 if let Some(medium) = opts.named_media.get(&inside_name) {
214 m.set_inside(medium);
216 }
217 if let Some(medium) = opts.named_media.get(&outside_name) {
218 m.set_outside(medium);
220 }
221 return m;
222 }
223
224 pub fn shape_may_set_material_parameters(params: &ParamSet) -> bool {
225 for name in params.strings.keys() {
226 if name != "alpha" && name != "shadowalpha" {
227 return true;
228 }
229 }
230 for (name, p) in ¶ms.floats {
231 let param = p.borrow();
232 if param.len() == 1 && name != "radius" {
233 return true;
234 }
235 }
236 for (name, p) in ¶ms.strings {
237 let param = p.borrow();
238 if param.len() == 1 && name != "filename" && name != "type" && name != "scheme" {
239 return true;
240 }
241 }
242 for p in params.bools.values() {
243 let param = p.borrow();
244 if param.len() == 1 {
245 return true;
246 }
247 }
248 for p in params.ints.values() {
249 let param = p.borrow();
250 if param.len() == 1 {
251 return true;
252 }
253 }
254 for p in params.spectrums.values() {
255 let param = p.borrow();
256 if param.len() == 1 {
257 return true;
258 }
259 }
260 for p in params.points.values() {
261 let param = p.borrow();
262 if param.len() == 3 {
263 return true;
264 }
265 }
266 return false;
267 }
268
269 pub fn get_material_for_shape(&self, params: &ParamSet) -> Option<Arc<dyn Material>> {
270 if Self::shape_may_set_material_parameters(params) {
271 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
272 if let Some(mat_inst) = attr.current_material.as_ref() {
273 let mat_inst = mat_inst.borrow();
274 let f_tex = attr.float_textures.as_ref().borrow();
275 let s_tex = attr.spectrum_textures.as_ref().borrow();
276 let mp = TextureParams::new(params, &mat_inst.params, &f_tex, &s_tex);
277 match self.make_material(&mat_inst.name, &mp) {
278 Ok(material) => {
279 return Some(material);
280 }
281 Err(e) => {
282 self.print_error(&e);
283 return None;
284 }
285 }
286 }
287 return None;
288 } else {
289 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
290 if let Some(mat_inst) = attr.current_material.as_ref() {
291 let mat_inst = mat_inst.borrow();
292 return Some(Arc::clone(&mat_inst.material));
293 }
294 }
295 return None;
296 }
297
298 pub fn get_named_material(&self, name: &str) -> Option<Arc<RefCell<MaterialInstance>>> {
299 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
300 let materials = attr.named_materials.as_ref().borrow();
301 let mat = materials.get(name);
302 match mat {
303 Some(m) => {
304 return Some(Arc::clone(m));
305 }
306 None => None,
307 }
308 }
309
310 pub fn get_current_instance_name(&self) -> Option<String> {
311 let opts = self.render_options.borrow();
312 match opts.current_instance_name.as_ref() {
313 Some(name) => {
314 return Some(name.clone());
315 }
316 None => None,
317 }
318 }
319
320 pub fn get_filepath(&self, name: &str) -> Option<String> {
321 let path = Path::new(name);
322 if path.is_absolute() || self.work_dirs.is_empty() {
323 return Some(String::from(path.to_str().unwrap()));
324 } else {
325 for d in self.work_dirs.iter().rev() {
326 let dir = Path::new(d);
327 let full_path = dir.join(name);
328 if full_path.exists() {
329 return Some(String::from(full_path.to_str().unwrap()));
330 }
331 }
332 return None;
333 }
334 }
335
336 pub fn create_shapes(
337 &self,
338 name: &str,
339 object2world: &Transform,
340 reverse_orientation: bool,
341 params: &ParamSet,
342 float_textures: &FloatTextureMap,
343 ) -> Result<Vec<Arc<dyn Shape>>, PbrtError> {
344 match name {
345 "trianglemesh" => {
346 return create_shapes(
348 name,
349 object2world,
350 reverse_orientation,
351 params,
352 float_textures,
353 );
354 }
355 "curve" => {
356 return create_shapes(
358 name,
359 object2world,
360 reverse_orientation,
361 params,
362 float_textures,
363 );
364 }
365 _ => {
366 let params = self.make_absolute_path(params);
367 return create_shapes(
368 name,
369 object2world,
370 reverse_orientation,
371 ¶ms,
372 float_textures,
373 );
374 }
375 }
376 }
377
378 pub fn make_shapes_core(
379 &self,
380 name: &str,
381 object2world: &Transform,
382 reverse_orientation: bool,
383 params: &ParamSet,
384 ) -> Vec<Arc<dyn Shape>> {
385 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
386 let f_tex = attr.float_textures.borrow();
387 match self.create_shapes(
388 name,
389 object2world,
390 reverse_orientation,
391 params,
392 f_tex.deref(),
393 ) {
394 Ok(shapes) => {
395 N_SHAPES.with(|c| c.add(shapes.len() as u64));
396 return shapes;
397 }
398 Err(e) => {
399 self.print_error(&e);
400 return Vec::new();
401 }
402 }
403 }
404
405 pub fn make_shapes(
406 &self,
407 name: &str,
408 object2world: &Transform,
409 reverse_orientation: bool,
410 params: &ParamSet,
411 ) -> Vec<Arc<dyn Shape>> {
412 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
413 if !attr.area_light_name.is_empty() {
414 let two_sided = attr.area_light_params.find_one_bool("twosided", true);
415 let two_sided = params.find_one_bool("twosided", two_sided);
416 let mut params = params.clone();
417 params.replace_one_bool("bool twosided", two_sided);
418 return self.make_shapes_core(name, object2world, reverse_orientation, ¶ms);
419 }
420 return self.make_shapes_core(name, object2world, reverse_orientation, params);
421 }
422
423 pub fn get_named_material_matte(&self, mp: &TextureParams, key: &str) -> Arc<dyn Material> {
424 if let Some(mat) = self.get_named_material(key) {
425 return Arc::clone(&mat.borrow().material);
426 } else {
427 return self.make_material("matte", mp).unwrap();
429 }
430 }
431
432 pub fn make_material(
433 &self,
434 name: &str,
435 mp: &TextureParams,
436 ) -> Result<Arc<dyn Material>, PbrtError> {
437 if name == "subsurface" || name == "kdsubsurface" {
438 let render_options = self.render_options.borrow();
439 if render_options.integrator_name != "path"
440 && render_options.integrator_name != "volpath"
441 {
442 warn!("Subsurface scattering material \"{}\" used, but \"{}\" integrator doesn't support subsurface scattering. Use \"path\" or \"volpath\".", name, render_options.integrator_name);
443 }
444 }
445
446 let material = if name == "mix" {
447 let m1 = mp.find_string("namedmaterial1", "");
448 let m2 = mp.find_string("namedmaterial2", "");
449 let mat1 = self.get_named_material_matte(mp, &m1);
450 let mat2 = self.get_named_material_matte(mp, &m2);
451 create_mix_material(mp, &mat1, &mat2)?
452 } else {
453 create_material(name, mp)?
454 };
455 N_MATERIALS.with(|c| c.inc());
456 return Ok(material);
457 }
458
459 fn make_material_params(
460 &self,
461 name: &str,
462 geom_params: &ParamSet,
463 mat_params: &ParamSet,
464 ) -> Option<Arc<dyn Material>> {
465 let attr = self.graphics_states.last().unwrap().borrow();
466 let f_tex = attr.float_textures.clone();
467 let s_tex = attr.spectrum_textures.clone();
468 let f = f_tex.as_ref().borrow();
469 let s = s_tex.as_ref().borrow();
470 let mp = TextureParams::new(geom_params, mat_params, f.deref(), s.deref());
471 match self.make_material(name, &mp) {
472 Ok(material) => {
473 return Some(material);
474 }
475 Err(e) => {
476 self.print_error(&e);
477 return None;
478 }
479 }
480 }
481
482 pub fn make_float_texture(
483 &self,
484 name: &str,
485 tex2world: &Transform,
486 tp: &TextureParams,
487 ) -> Option<Arc<dyn Texture<Float>>> {
488 if let Some(texinfo) = create_texinfo(tp) {
489 let key = format!("{:?}", texinfo);
490 let textures = self.float_textures.borrow();
491 if let Some(texture) = textures.get(&key) {
492 return Some(Arc::clone(texture));
493 }
494 }
495
496 match create_float_texture(name, tex2world, tp) {
497 Ok(texture) => {
498 if let Some(texinfo) = create_texinfo(tp) {
499 let key = format!("{:?}", texinfo);
500 let mut textures = self.float_textures.borrow_mut();
501 textures.insert(key, Arc::clone(&texture));
502 }
503
504 return Some(texture);
505 }
506 Err(e) => {
507 self.print_error(&e);
508 return None;
509 }
510 }
511 }
512
513 pub fn make_spectrum_texture(
514 &self,
515 name: &str,
516 tex2world: &Transform,
517 tp: &TextureParams,
518 ) -> Option<Arc<dyn Texture<Spectrum>>> {
519 if let Some(texinfo) = create_texinfo(tp) {
520 let key = format!("{:?}", texinfo);
521 let textures = self.spectrum_textures.borrow();
522 if let Some(texture) = textures.get(&key) {
523 return Some(Arc::clone(texture));
524 }
525 }
526
527 match create_spectrum_texture(name, tex2world, tp) {
528 Ok(texture) => {
529 if let Some(texinfo) = create_texinfo(tp) {
530 let key = format!("{:?}", texinfo);
531 let mut textures = self.spectrum_textures.borrow_mut();
532 textures.insert(key, Arc::clone(&texture));
533 }
534
535 return Some(texture);
536 }
537 Err(e) => {
538 self.print_error(&e);
539 return None;
540 }
541 }
542 }
543
544 pub fn make_light(
545 &self,
546 name: &str,
547 light2world: &Transform,
548 medium_interface: &MediumInterface,
549 params: &ParamSet,
550 ) -> Option<Arc<dyn Light>> {
551 match create_light(name, light2world, medium_interface, params) {
552 Ok(light) => {
553 N_LIGHTS.with(|c| c.inc());
554 return Some(light);
555 }
556 Err(e) => {
557 self.print_error(&e);
558 return None;
559 }
560 }
561 }
562
563 pub fn make_area_light(
564 &self,
565 name: &str,
566 light2world: &Transform,
567 medium_interface: &MediumInterface,
568 params: &ParamSet,
569 shape: &Arc<dyn Shape>,
570 ) -> Option<Arc<dyn Light>> {
571 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
572 if attr.area_light_name.is_empty() {
573 return None;
574 }
575 match create_area_light(name, light2world, medium_interface, params, shape) {
576 Ok(light) => {
577 N_LIGHTS.with(|c| c.inc());
578 N_AREA_LIGHTS.with(|c| c.inc());
579 return Some(light);
580 }
581 Err(e) => {
582 self.print_error(&e);
583 return None;
584 }
585 }
586 }
587
588 pub fn make_accelerator(
589 &self,
590 name: &str,
591 prims: &[Arc<dyn Primitive>],
592 params: &ParamSet,
593 ) -> Option<Arc<dyn Primitive>> {
594 match create_accelerator(name, prims, params) {
595 Ok(accelerator) => {
596 return Some(accelerator);
597 }
598 Err(_e) => {
599 return None;
600 }
601 }
602 }
603
604 pub fn make_medium(
605 &self,
606 name: &str,
607 params: &ParamSet,
608 medium2world: &Transform,
609 ) -> Option<Arc<dyn Medium>> {
610 return create_medium(name, params, medium2world);
611 }
612
613 pub fn make_filter(&self) -> Option<Arc<dyn Filter>> {
614 let opts = self.render_options.borrow();
615 match create_filter(&opts.filter_name, &opts.filter_params) {
616 Ok(filter) => {
617 return Some(filter);
618 }
619 Err(e) => {
620 self.print_error(&e);
621 return None;
622 }
623 }
624 }
625
626 pub fn make_film(&self, filter: &Arc<dyn Filter>) -> Option<Arc<RwLock<Film>>> {
627 let opts = self.render_options.borrow();
628 match create_film(&opts.film_name, &opts.film_params, filter) {
629 Ok(film) => {
630 return Some(film);
631 }
632 Err(e) => {
633 self.print_error(&e);
634 return None;
635 }
636 }
637 }
638
639 pub fn make_camera(&self) -> Option<Arc<dyn Camera>> {
640 if let Some(camera_transform) = self.named_coordinate_systems.get("camera") {
641 let camera_to_world = &camera_transform.borrow();
642 if let Some(filter) = self.make_filter() {
643 if let Some(film) = self.make_film(&filter) {
644 let medium_interface = self.create_medium_interface();
645 let opts = self.render_options.borrow();
646 let start_time = opts.transform_start_time;
647 let end_time = opts.transform_end_time;
648 let animated_cam_2_world = AnimatedTransform::new(
649 &camera_to_world[0],
650 start_time,
651 &camera_to_world[1],
652 end_time,
653 );
654 match create_camera(
655 &opts.camera_name,
656 &opts.camera_params,
657 &animated_cam_2_world,
658 &film,
659 &medium_interface,
660 ) {
661 Ok(camara) => {
662 return Some(camara);
663 }
664 Err(e) => {
665 self.print_error(&e);
666 return None;
667 }
668 }
669 }
670 }
671 }
672 return None;
673 }
674
675 pub fn make_integrator(&self) -> Option<Arc<RwLock<dyn Integrator>>> {
676 let camera = self.make_camera();
677 if camera.is_none() {
678 error!("Unable to create camera");
679 return None;
680 }
681 let camera = camera.unwrap();
682 let film = camera.as_ref().get_film();
683 let opts = self.render_options.borrow();
684 let sampler = create_sampler(&opts.sampler_name, &opts.sampler_params, &film);
685 if sampler.is_err() {
686 self.print_error(&sampler.err().unwrap());
687 return None;
688 }
689 let sampler = sampler.unwrap();
690
691 if opts.have_scattering_media
692 && opts.integrator_name != "volpath"
693 && opts.integrator_name != "bdpt"
694 && opts.integrator_name != "mlt"
695 {
696 warn!("Scene has scattering media but \"{}\" integrator doesn't support volume scattering. Use \"volpath\", \"bdpt\" or \"mlt\".", opts.integrator_name);
697 }
698 if opts.lights.is_empty() {
700 warn!("No light sources defined in scene; rendering a black image.");
701 }
702 match create_integrator(
703 &opts.integrator_name,
704 &opts.integrator_params,
705 &sampler,
706 &camera,
707 ) {
708 Ok(integrator) => {
709 return Some(integrator);
710 }
711 Err(e) => {
712 self.print_error(&e);
713 return None;
714 }
715 }
716 }
717
718 pub fn make_scene(&self) -> Option<Arc<Scene>> {
719 let opts = self.render_options.borrow();
720 if let Some(accelerator) = self.make_accelerator(
721 &opts.accelerator_name,
722 &opts.primitives,
723 &opts.accelerator_params,
724 ) {
725 let scene = Arc::new(Scene::new(&accelerator, &opts.lights));
726 return Some(scene);
727 }
728 return None;
729 }
730
731 pub fn make_absolute_path(&self, params: &ParamSet) -> ParamSet {
733 let mut n_params = params.clone();
734 let keys = params.get_keys();
735 {
737 let target_keys: Vec<_> = keys
738 .iter()
739 .filter(|key| -> bool {
740 let (t, _) = get_param_type(key);
741 return t == "spectrum";
742 })
743 .collect();
744 for key in target_keys {
745 if let Some(names) = params.get_strings_ref(key) {
746 for name in names.iter() {
747 if let Some(path) = self.get_filepath(name) {
748 let ret = SampledSpectrum::load_sampled_spectrum_file(&path);
749 match ret {
750 Ok(spc) => {
751 let spc = Spectrum::from(&spc);
752 n_params.add_spectrum_no_key(name, &spc);
753 }
754 Err(e) => {
755 self.print_error(&e);
756 }
757 }
758 }
759 }
760 }
761 }
762 }
763 {
765 let target_keys: Vec<_> = keys
766 .iter()
767 .filter(|key| -> bool {
768 let (t, _) = get_param_type(key);
769 return t == "blackbody";
770 })
771 .collect();
772 for key in target_keys {
773 if let Some(values) = params.get_floats_ref(key) {
774 let spc = SampledSpectrum::from_blackbody(&values);
775 let spc = Spectrum::from(&spc);
776 n_params.add_spectrum_no_key(key, &spc);
777 }
778 }
779 }
780
781 {
783 let file_path_keys = ["filename", "mapname", "bsdffile", "lensfile"];
784
785 let target_keys: Vec<_> = keys
786 .iter()
787 .filter(|key| -> bool {
788 let (_, key) = get_param_type(key);
789 for file_path_key in file_path_keys {
790 if file_path_key == key {
791 return true;
792 }
793 }
794 return false;
795 })
796 .collect();
797 let mut replaces = Vec::new();
798 for key in target_keys {
799 if let Some(names) = params.get_strings_ref(key) {
800 for name in names.iter() {
801 if let Some(path) = self.get_filepath(name) {
802 replaces.push((key.clone(), path));
803 }
804 }
805 }
806 }
807 for (key, value) in replaces.iter() {
808 n_params.replace_one_string(key, value);
809 }
810 }
811
812 return n_params;
813 }
814}
815
816impl ParseContext for SceneContext {
817 fn pbrt_cleanup(&mut self) {
818 self.initialize();
819 }
820
821 fn pbrt_identity(&mut self) {
822 self.verify_initialized("Identity");
823
824 let t = Transform::identity();
825 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
826 trns.set_transform(&t, self.transform_bits[self.transform_bits.len() - 1]);
827 }
828
829 fn pbrt_translate(&mut self, dx: Float, dy: Float, dz: Float) {
830 self.verify_initialized("Translate");
831
832 let t = Transform::translate(dx, dy, dz);
833 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
834 trns.mul_transform(&t, self.transform_bits[self.transform_bits.len() - 1]);
835 }
836
837 fn pbrt_rotate(&mut self, angle: Float, ax: Float, ay: Float, az: Float) {
838 self.verify_initialized("Rotate");
839
840 let t = Transform::rotate(angle, ax, ay, az);
841 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
842 trns.mul_transform(&t, self.transform_bits[self.transform_bits.len() - 1]);
843 }
844
845 fn pbrt_scale(&mut self, sx: Float, sy: Float, sz: Float) {
846 self.verify_initialized("Scale");
847
848 let t = Transform::scale(sx, sy, sz);
849 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
850 trns.mul_transform(&t, self.transform_bits[self.transform_bits.len() - 1]);
851 }
852
853 fn pbrt_look_at(
854 &mut self,
855 ex: Float,
856 ey: Float,
857 ez: Float,
858 lx: Float,
859 ly: Float,
860 lz: Float,
861 ux: Float,
862 uy: Float,
863 uz: Float,
864 ) {
865 self.verify_initialized("LookAt");
866
867 let t = Transform::look_at(ex, ey, ez, lx, ly, lz, ux, uy, uz); let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
869 trns.mul_transform(&t, self.transform_bits[self.transform_bits.len() - 1]);
870 }
871
872 fn pbrt_concat_transform(&mut self, t: &[Float]) {
873 self.verify_initialized("ConcatTransform");
874
875 #[rustfmt::skip]
876 let m = Matrix4x4::from([
877 t[0], t[4], t[8], t[12],
878 t[1], t[5], t[9], t[13],
879 t[2], t[6], t[10], t[14],
880 t[3], t[7], t[11], t[15],
881 ]);
882 if let Some(im) = m.inverse() {
883 let t = Transform::from((m, im));
884 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
885 trns.mul_transform(&t, self.transform_bits[self.transform_bits.len() - 1]);
886 } else {
887 error!("Singular matrix in MatrixInvert");
888 }
889 }
890
891 fn pbrt_transform(&mut self, t: &[Float]) {
892 self.verify_initialized("Transform");
893
894 #[rustfmt::skip]
895 let m = Matrix4x4::from([
896 t[0], t[4], t[8], t[12],
897 t[1], t[5], t[9], t[13],
898 t[2], t[6], t[10], t[14],
899 t[3], t[7], t[11], t[15],
900 ]);
901 if let Some(im) = m.inverse() {
902 let t = Transform::from((m, im));
903 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
904 trns.set_transform(&t, self.transform_bits[self.transform_bits.len() - 1]);
905 } else {
906 error!("Singular matrix in MatrixInvert");
907 }
908 }
909
910 fn pbrt_coordinate_system(&mut self, name: &str) {
911 self.verify_initialized("CoordinateSystem");
912
913 let trns = self.transforms[self.transforms.len() - 1].borrow();
914 self.named_coordinate_systems
915 .insert(String::from(name), RefCell::new(trns.clone()));
916 }
917
918 fn pbrt_coord_sys_transform(&mut self, name: &str) {
919 self.verify_initialized("CoordSysTransform");
920
921 if let Some(t) = self.named_coordinate_systems.get(&String::from(name)) {
922 let t = t.borrow();
923 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
924 trns.set(&t, self.transform_bits[self.transform_bits.len() - 1]); } else {
926 warn!("Couldn't find named coordinate system \"{}\"", name);
927 }
928 }
929
930 fn pbrt_active_transform_all(&mut self) {
931 let last = self.transform_bits.len() - 1;
932 self.transform_bits[last] = ALL_TRANSFORM_BITS;
933 }
934
935 fn pbrt_active_transform_end_time(&mut self) {
936 let last = self.transform_bits.len() - 1;
937 self.transform_bits[last] = END_TRANSFORM_BITS;
938 }
939
940 fn pbrt_active_transform_start_time(&mut self) {
941 let last = self.transform_bits.len() - 1;
942 self.transform_bits[last] = START_TRANSFORM_BITS;
943 }
944
945 fn pbrt_transform_times(&mut self, start: Float, end: Float) {
946 self.verify_options("TransformTimes");
947
948 let mut opts = self.render_options.borrow_mut();
949 opts.transform_start_time = start;
950 opts.transform_end_time = end;
951 }
952
953 fn pbrt_pixel_filter(&mut self, name: &str, params: &ParamSet) {
954 self.verify_options("PixelFilter");
955
956 let mut opts = self.render_options.borrow_mut();
957 opts.filter_name = String::from(name);
958 opts.filter_params.set(params);
959 }
960
961 fn pbrt_film(&mut self, name: &str, params: &ParamSet) {
962 self.verify_options("Film");
963 let mut opts = self.render_options.borrow_mut();
964 opts.film_name = String::from(name);
965 opts.film_params.set(params);
966 }
967
968 fn pbrt_sampler(&mut self, name: &str, params: &ParamSet) {
969 self.verify_options("Sampler");
970
971 let mut opts = self.render_options.borrow_mut();
972 opts.sampler_name = String::from(name);
973 opts.sampler_params.set(params);
974 }
975
976 fn pbrt_accelerator(&mut self, name: &str, params: &ParamSet) {
977 self.verify_options("Accelerator");
978
979 let mut opts = self.render_options.borrow_mut();
980 opts.accelerator_name = String::from(name);
981 opts.accelerator_params.set(params);
982 }
983
984 fn pbrt_integrator(&mut self, name: &str, params: &ParamSet) {
985 self.verify_options("Integrator");
986
987 let mut opts = self.render_options.borrow_mut();
988 opts.integrator_name = String::from(name);
989 opts.integrator_params.set(params);
990 }
991
992 fn pbrt_camera(&mut self, name: &str, params: &ParamSet) {
993 self.verify_options("Camera");
994
995 let params = self.make_absolute_path(params);
996
997 let trns = self.transforms[self.transforms.len() - 1].borrow();
998 let mut opts = self.render_options.borrow_mut();
999 opts.camera_name = String::from(name);
1000 opts.camera_params.set(¶ms);
1001 self.named_coordinate_systems.insert(
1003 String::from("camera"),
1004 RefCell::new(TransformSet::inverse(&trns)),
1005 );
1006 }
1007
1008 fn pbrt_make_named_medium(&mut self, name: &str, params: &ParamSet) {
1009 self.verify_initialized("MakeNamedMedium");
1010
1011 let t = params.find_one_string("type", "");
1012 if t == "" {
1013 error!("No parameter string \"type\" found in MakeNamedMedium");
1014 } else {
1015 let trns = self.transforms[self.transforms.len() - 1].borrow();
1016 if let Some(m) = self.make_medium(&t, params, &trns[0]) {
1017 let mut opts = self.render_options.borrow_mut();
1018 opts.named_media.insert(String::from(name), m);
1019 } else {
1020 error!("Unable to create medium \"{}\" \"{}\"", name, t);
1021 }
1022 }
1023 }
1024
1025 fn pbrt_medium_interface(&mut self, inside_name: &str, outside_name: &str) {
1026 self.verify_initialized("MediumInterface");
1027
1028 let mut atrs = self.graphics_states[self.graphics_states.len() - 1].borrow_mut();
1029 let mut opts = self.render_options.borrow_mut();
1030 atrs.current_inside_medium = String::from(inside_name);
1031 atrs.current_outside_medium = String::from(outside_name);
1032 opts.have_scattering_media = true;
1033 }
1034
1035 fn pbrt_world_begin(&mut self) {
1036 self.verify_options("WorldBegin");
1037
1038 self.current_api_state = APIState::OptionsBlock;
1039 let mut trns = self.transforms[self.transforms.len() - 1].borrow_mut();
1040 trns.set_transform(&Transform::identity(), ALL_TRANSFORM_BITS);
1041 let last = self.transform_bits.len() - 1;
1042 self.transform_bits[last] = ALL_TRANSFORM_BITS;
1043 self.named_coordinate_systems
1044 .insert(String::from("world"), RefCell::new(trns.clone()));
1045 }
1046
1047 fn pbrt_attribute_begin(&mut self) {
1048 self.verify_world("AttributeBegin");
1049
1050 self.push_graphics_state();
1051 self.push_transform();
1052 let mut attr = self.graphics_states[self.graphics_states.len() - 1].borrow_mut();
1053 attr.float_textures_shared = true;
1054 attr.spectrum_textures_shared = true;
1055 attr.named_materials_shared = true;
1056 }
1057
1058 fn pbrt_attribute_end(&mut self) {
1059 self.verify_world("AttributeEnd");
1060
1061 self.pop_transform();
1062 self.pop_graphics_state();
1063 }
1064
1065 fn pbrt_transform_begin(&mut self) {
1066 self.verify_world("TransformBegin");
1067
1068 self.push_transform();
1069 }
1070
1071 fn pbrt_transform_end(&mut self) {
1072 self.verify_world("Transformend");
1073
1074 self.pop_transform();
1075 }
1076
1077 fn pbrt_texture(&mut self, name: &str, t: &str, tex_name: &str, params: &ParamSet) {
1078 self.verify_world("Texture");
1079
1080 let params = self.make_absolute_path(params);
1081
1082 if let Some(maps) = params.get_strings_ref("filename") {
1084 if maps.len() == 1 {
1085 let path = Path::new(&maps[0]);
1086 if !path.exists() {
1087 warn!("Texture file \"{}\" does not exist.", path.display());
1088 return;
1089 }
1090 }
1091 }
1092
1093 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow_mut();
1094
1095 let mut f_tex = attr.float_textures.as_ref().borrow_mut();
1096 let mut s_tex = attr.spectrum_textures.as_ref().borrow_mut();
1097 let tp = TextureParams::new(¶ms, ¶ms, &f_tex, &s_tex);
1098
1099 if t == "float" {
1100 let cur_trans = self.transforms[self.transforms.len() - 1].borrow();
1101 if let Some(ft) = self.make_float_texture(tex_name, &cur_trans[0], &tp) {
1102 f_tex.insert(String::from(name), ft);
1104 }
1105 } else if t == "color" || t == "rgb" || t == "spectrum" {
1106 let cur_trans = self.transforms[self.transforms.len() - 1].borrow();
1107 if let Some(st) = self.make_spectrum_texture(tex_name, &cur_trans[0], &tp) {
1108 s_tex.insert(String::from(name), st);
1110 }
1111 } else {
1112 }
1114 }
1115
1116 fn pbrt_material(&mut self, name: &str, params: &ParamSet) {
1117 self.verify_world("Material");
1118
1119 if name == "" {
1120 let mut attr = self.graphics_states.last().unwrap().borrow_mut();
1121 attr.current_material = None;
1122 } else {
1123 let params = self.make_absolute_path(params);
1124 let empty_params = ParamSet::new();
1125 if let Some(mtl) = self.make_material_params(name, ¶ms, &empty_params) {
1126 let mut attr = self.graphics_states.last().unwrap().borrow_mut();
1127 attr.current_material = Some(Arc::new(RefCell::new(MaterialInstance::new(
1128 name, mtl, ¶ms,
1129 ))));
1130 }
1131 }
1132 }
1133
1134 fn pbrt_make_named_material(&mut self, name: &str, params: &ParamSet) {
1135 let params = self.make_absolute_path(params);
1138 let empty_params = ParamSet::new();
1139 let mat_name = params.find_one_string("type", "");
1140 if mat_name.is_empty() {
1141 error!("No parameter string \"type\" found in MakeNamedMaterial");
1142 }
1143 if let Some(mat) = self.make_material_params(&mat_name, ¶ms, &empty_params) {
1144 let mut attr = self.graphics_states.last().unwrap().borrow_mut();
1145 {
1146 let named_materials = attr.named_materials.as_ref().borrow();
1147 if named_materials.contains_key(name) {
1148 warn!("Named material \"{}\" redefined.", name);
1149 }
1150 }
1151
1152 if attr.named_materials_shared {
1153 let materials = attr.clone_named_materials();
1154 attr.named_materials = materials;
1155 attr.named_materials_shared = false;
1156 }
1157 {
1158 let mut named_materials = attr.named_materials.as_ref().borrow_mut();
1159 named_materials.insert(
1160 String::from(name),
1161 Arc::new(RefCell::new(MaterialInstance::new(&mat_name, mat, ¶ms))),
1162 );
1163 }
1164 }
1165 }
1166
1167 fn pbrt_named_material(&mut self, name: &str) {
1168 self.verify_world("NamedMaterial");
1169
1170 if let Some(mtl) = self.get_named_material(name) {
1171 let mut attr = self.graphics_states[self.graphics_states.len() - 1].borrow_mut();
1172 attr.current_material = Some(mtl);
1173 } else {
1174 error!("NamedMaterial \"{}\" unknown.", name);
1175 }
1176 }
1177
1178 fn pbrt_light_source(&mut self, name: &str, params: &ParamSet) {
1179 self.verify_world("LightSource");
1180
1181 let params = self.make_absolute_path(params);
1182
1183 let cur_trans = self.transforms[self.transforms.len() - 1].borrow()[0];
1184 let mi = self.create_medium_interface();
1185 if let Some(lt) = self.make_light(name, &cur_trans, &mi, ¶ms) {
1186 let mut opts = self.render_options.borrow_mut();
1187 opts.lights.push(lt);
1188 }
1189 }
1190
1191 fn pbrt_area_light_source(&mut self, name: &str, params: &ParamSet) {
1192 self.verify_world("AreaLightSource");
1193
1194 let params = self.make_absolute_path(params);
1195
1196 let mut attr = self.graphics_states[self.graphics_states.len() - 1].borrow_mut();
1197 attr.area_light_name = String::from(name);
1198 attr.area_light_params = params;
1199 }
1200
1201 fn pbrt_shape(&mut self, name: &str, params: &ParamSet) {
1202 self.verify_world("Shape");
1203
1204 let mut prims: Vec<Arc<dyn Primitive>> = Vec::new();
1205 let mut area_lights: Vec<Arc<dyn Light>> = Vec::new();
1206
1207 let attr = self.graphics_states[self.graphics_states.len() - 1].borrow();
1208 let cur_trans = self.transforms[self.transforms.len() - 1].borrow();
1210 if !cur_trans.is_animated() {
1211 let object2world = cur_trans[0].clone();
1212 let shapes = self.make_shapes(name, &object2world, attr.reverse_orientation, params);
1213 if !shapes.is_empty() {
1214 prims.reserve(shapes.len());
1215 let mtl = self.get_material_for_shape(params);
1216 let mi = self.create_medium_interface();
1217
1218 for s in shapes {
1219 let area = self.make_area_light(
1220 &attr.area_light_name,
1221 &object2world,
1222 &mi,
1223 &attr.area_light_params,
1224 &s,
1225 );
1226 if let Some(a) = area.as_ref() {
1227 area_lights.push(a.clone());
1228 }
1229 let prim = Arc::new(GeometricPrimitive::new(&s, &mtl, &area, &mi));
1230 prims.push(prim);
1231 }
1232 }
1233 } else {
1234 if attr.area_light_name != "" {
1238 warn!("Ignoring currently set area light when creating animated shape");
1239 }
1240
1241 let identity = Transform::identity();
1242 let shapes = self.make_shapes(name, &identity, attr.reverse_orientation, params);
1243 if shapes.is_empty() {
1244 return;
1245 }
1246
1247 let mtl = self.get_material_for_shape(params);
1249 let mi = self.create_medium_interface();
1250 prims.reserve(shapes.len());
1251 for s in shapes {
1252 let prim = Arc::new(GeometricPrimitive::new(&s, &mtl, &None, &mi));
1253 prims.push(prim);
1254 }
1255 let cur_trans = self.transforms[self.transforms.len() - 1].borrow();
1259 if cur_trans.len() < 2 {
1260 error!("Transformation matrix has missing components");
1261 return;
1262 }
1263 let obj_to_world = [cur_trans[0].clone(), cur_trans[1].clone()];
1264 let animated_transform = {
1265 let opts = self.render_options.borrow();
1266 AnimatedTransform::new(
1268 &obj_to_world[0],
1269 opts.transform_start_time,
1270 &obj_to_world[1],
1271 opts.transform_end_time,
1272 )
1273 };
1274
1275 if prims.len() > 1 {
1276 let opts = self.render_options.borrow();
1277 let accelerator_name = opts.accelerator_name.clone();
1278 let accelerator_params = opts.accelerator_params.clone();
1279 if let Some(accel) =
1280 self.make_accelerator(&accelerator_name, &prims, &accelerator_params)
1281 {
1282 prims.clear();
1283 prims.push(accel);
1284 }
1285 }
1286
1287 if !prims.is_empty() {
1288 assert!(prims.len() == 1);
1289 let prim = Arc::new(TransformedPrimitive::new(&prims[0], &animated_transform));
1290 prims.clear();
1291 prims.push(prim);
1292 }
1293 }
1294
1295 {
1296 if let Some(instance_name) = self.get_current_instance_name() {
1297 if !area_lights.is_empty() {
1298 warn!("Area lights not supported with object instancing"); }
1300 let mut opts = self.render_options.borrow_mut();
1301 if let Some(out_primitives) = opts.instances.get_mut(&instance_name) {
1302 for prim in prims {
1303 out_primitives.push(prim);
1304 }
1305 }
1306 } else {
1307 let mut opts = self.render_options.borrow_mut();
1308 for prim in prims {
1309 opts.primitives.push(prim);
1310 }
1311 if !area_lights.is_empty() {
1312 for l in area_lights {
1313 opts.lights.push(l);
1314 }
1315 }
1316 }
1317 }
1318 }
1319
1320 fn pbrt_reverse_orientation(&mut self) {
1321 self.verify_world("ReverseOrientation");
1322
1323 let mut atrs = self.graphics_states[self.graphics_states.len() - 1].borrow_mut();
1324 atrs.reverse_orientation = !atrs.reverse_orientation;
1325 }
1326
1327 fn pbrt_object_begin(&mut self, name: &str) {
1328 self.verify_world("ObjectBegin");
1329
1330 self.pbrt_attribute_begin();
1331 {
1332 let mut opts = self.render_options.borrow_mut();
1333 opts.instances.insert(String::from(name), Vec::new());
1334 opts.current_instance_name = Some(String::from(name));
1335 }
1336 }
1337
1338 fn pbrt_object_end(&mut self) {
1339 self.verify_world("ObjectEnd");
1340
1341 {
1342 let mut opts = self.render_options.borrow_mut();
1343 opts.current_instance_name = None;
1344 }
1345 self.pbrt_attribute_end();
1346 N_OBJECT_INSTANCES_CREATED.with(|c| c.inc());
1347 }
1348
1349 fn pbrt_object_instance(&mut self, name: &str) {
1350 self.verify_world("ObjectInstance");
1351
1352 {
1353 let opts = self.render_options.borrow();
1354 if opts.current_instance_name.as_ref().is_some() {
1355 return;
1356 }
1357 }
1358
1359 {
1360 let mut opts = self.render_options.borrow_mut();
1361 let accelerator_name = opts.accelerator_name.clone();
1362 let accelerator_params = opts.accelerator_params.clone();
1363 let start_time = opts.transform_start_time;
1364 let end_time = opts.transform_end_time;
1365 let instances = &mut opts.instances;
1366 if let Some(prims) = instances.get_mut(name) {
1367 N_OBJECT_INSTANCES_USED.with(|c| c.inc());
1368
1369 if prims.len() > 1 {
1370 if let Some(accel) =
1371 self.make_accelerator(&accelerator_name, prims, &accelerator_params)
1372 {
1373 prims.clear();
1374 prims.push(accel);
1375 }
1376 }
1377 if !prims.is_empty() {
1378 assert_eq!(prims.len(), 1);
1379 let cur_trans = self.transforms[self.transforms.len() - 1].borrow();
1380 let animated_transform = AnimatedTransform::new(
1381 &cur_trans.t[0],
1382 start_time,
1383 &cur_trans.t[1],
1384 end_time,
1385 );
1386 let prim = Arc::new(TransformedPrimitive::new(&prims[0], &animated_transform));
1387 opts.primitives.push(prim);
1388 }
1389 }
1390 }
1391 }
1392
1393 fn pbrt_world_end(&mut self) {
1394 self.verify_world("WorldEnd");
1395 }
1397
1398 fn pbrt_parse_file(&mut self, _file_name: &str) {
1399 }
1401 fn pbrt_parse_string(&mut self, _s: &str) {
1402 }
1404
1405 fn pbrt_work_dir_begin(&mut self, path: &str) {
1406 self.work_dirs.push(String::from(path));
1407 }
1408
1409 fn pbrt_work_dir_end(&mut self) {
1410 self.work_dirs.pop();
1411 }
1412}