Browse Source

using builder pattern to avoid repeating construction args

Inderjit Gill 4 months ago
parent
commit
33ec135b09
3 changed files with 82 additions and 70 deletions
  1. 38
    2
      src/camera.rs
  2. 11
    0
      src/picture.rs
  3. 33
    68
      src/scene_parser.rs

+ 38
- 2
src/camera.rs View File

@@ -4,6 +4,42 @@ use ray::*;
4 4
 use rng::ThreadLocalRng;
5 5
 use types::*;
6 6
 
7
+pub struct CameraBuilder {
8
+    pub look_from: V3,
9
+    pub look_at: V3,
10
+    pub look_up: V3,
11
+    pub vfov: S,
12
+    pub aspect: S,
13
+    pub aperture: S,
14
+    pub focus_dist: S,
15
+}
16
+
17
+impl Default for CameraBuilder {
18
+    fn default() -> CameraBuilder {
19
+        CameraBuilder {
20
+            look_from: V3::new(0.0, 0.0, 0.0),
21
+            look_at: V3::new(0.0, 0.0, -1.0),
22
+            look_up: V3::new(0.0, 1.0, 0.0),
23
+            vfov: 90.0,
24
+            aspect: 1.0,
25
+            aperture: 0.0,
26
+            focus_dist: 1.0,
27
+        }
28
+    }
29
+}
30
+
31
+impl CameraBuilder {
32
+    pub fn build(&self) -> Camera {
33
+        Camera::new(self.look_from,
34
+                    self.look_at,
35
+                    self.look_up,
36
+                    self.vfov,
37
+                    self.aspect,
38
+                    self.aperture,
39
+                    self.focus_dist)
40
+    }
41
+}
42
+
7 43
 pub struct Camera {
8 44
     lower_left_corner: V3,
9 45
     horizontal: V3,
@@ -18,7 +54,7 @@ impl Camera {
18 54
     pub fn new(
19 55
         look_from: V3,
20 56
         look_at: V3,
21
-        vup: V3,
57
+        look_up: V3,
22 58
         vfov: S,
23 59
         aspect: S,
24 60
         aperture: S,
@@ -31,7 +67,7 @@ impl Camera {
31 67
         let half_width = aspect * half_height;
32 68
 
33 69
         let w = (look_from - look_at).normalize();
34
-        let u = vup.cross(w).normalize();
70
+        let u = look_up.cross(w).normalize();
35 71
         let v = w.cross(u);
36 72
 
37 73
         Camera {

+ 11
- 0
src/picture.rs View File

@@ -5,3 +5,14 @@ pub struct Picture {
5 5
     pub samples: u32,
6 6
     pub output: String,
7 7
 }
8
+
9
+impl Default for Picture {
10
+    fn default() -> Picture {
11
+        Picture {
12
+            width: 100,
13
+            height: 50,
14
+            samples: 10,
15
+            output: "output.png".to_string(),
16
+        }
17
+    }
18
+}

+ 33
- 68
src/scene_parser.rs View File

@@ -27,42 +27,28 @@ pub fn parse_scene(filename: &str) -> Result<(Scene, Picture)> {
27 27
 fn create_scene(ast: &Vec<Node>) -> Result<(Scene, Picture)> {
28 28
     let mut world = HitableList::new();
29 29
 
30
-    let mut picture = Picture {
31
-        width: 100,
32
-        height: 50,
33
-        samples: 1,
34
-        output: "auto.png".to_string(),
35
-    };
36
-
37
-    let look_from = V3::new(0.0, 0.0, 0.0);
38
-    let look_at = V3::new(0.0, 0.0, -1.0);
39
-    let dist_to_focus = (look_from - look_at).magnitude();
40
-    let aperture = 0.0;
41
-
42
-    let mut camera = Camera::new(
43
-        look_from,
44
-        look_at,
45
-        V3::new(0.0, 1.0, 0.0),
46
-        90.0,
47
-        picture.width as S / picture.height as S,
48
-        aperture,
49
-        dist_to_focus,
50
-    );
51
-
52 30
     // first search for a picture decl.
31
+    let mut picture: Picture = Default::default();
53 32
     for n in ast {
54 33
         if declaring(&n, "picture") {
55 34
             picture = create_picture(&n)?;
56 35
             break;
57 36
         }
58 37
     }
59
-    // then a camera
38
+
39
+    // using a CameraBuilder since the Camera constructor derives it's member
40
+    // variables from the arguments given. We can't just construct a Camera and
41
+    // then individually set parameters that would have been passed into it's
42
+    // constructor.
43
+    let mut camera_builder: CameraBuilder = Default::default();
60 44
     for n in ast {
61 45
         if declaring(&n, "camera") {
62
-            camera = create_camera(&n, &picture)?;
46
+            camera_builder = create_camera_builder(&n, &picture)?;
63 47
             break;
64 48
         }
65 49
     }
50
+    let camera = camera_builder.build();
51
+
66 52
     // now parse the geometry
67 53
     for n in ast {
68 54
         if declaring(&n, "sphere") {
@@ -82,21 +68,12 @@ fn create_picture(node: &Node) -> Result<Picture> {
82 68
         Node::List(nodes) => {
83 69
             let args = &nodes.as_slice()[1..];
84 70
 
85
-            let mut width = 0.0;
86
-            let mut height = 0.0;
87
-            let mut samples = 0.0;
88
-            let mut output = "".to_string();
89
-
71
+            let mut picture: Picture = Default::default();
90 72
             let mut kv = args;
91 73
 
92 74
             loop {
93 75
                 if kv.len() < 2 {
94
-                    return Ok(Picture {
95
-                        width: width as u32,
96
-                        height: height as u32,
97
-                        samples: samples as u32,
98
-                        output: output,
99
-                    })
76
+                    return Ok(picture)
100 77
                 } else {
101 78
                     let k = &kv[0];
102 79
                     let v = &kv[1];
@@ -104,10 +81,10 @@ fn create_picture(node: &Node) -> Result<Picture> {
104 81
 
105 82
                     let name = get_label_name(k)?;
106 83
                     match name.as_ref() {
107
-                        "width" => width = get_float(v)?,
108
-                        "height" => height = get_float(v)?,
109
-                        "samples" => samples = get_float(v)?,
110
-                        "output" => output = get_string(v)?,
84
+                        "width" => picture.width = get_float(v)? as u32,
85
+                        "height" => picture.height = get_float(v)? as u32,
86
+                        "samples" => picture.samples = get_float(v)? as u32,
87
+                        "output" => picture.output = get_string(v)?,
111 88
                         _ => return Err(RayTracerError::SceneParser)
112 89
                     }
113 90
                 }
@@ -117,36 +94,24 @@ fn create_picture(node: &Node) -> Result<Picture> {
117 94
     }
118 95
 }
119 96
 
120
-fn create_camera(node: &Node, picture: &Picture) -> Result<Camera> {
97
+fn create_camera_builder(node: &Node, picture: &Picture) -> Result<CameraBuilder> {
121 98
     match node {
122 99
         Node::List(nodes) => {
123 100
             let args = &nodes.as_slice()[1..];
124 101
 
125
-            let mut look_from = V3::new(0.0, 0.0, 0.0);
126
-            let mut look_at = V3::new(0.0, 0.0, -1.0);
127
-            let mut look_up = V3::new(0.0, 1.0, 0.0);
128
-            let mut vfov = 90.0;
129
-            let mut aspect = picture.width as S / picture.height as S;
130
-            let mut aperture = 0.0;
131
-            let mut dist_to_focus = (look_from - look_at).magnitude();
132
-            let mut given_dist_to_focus = false;
133
-
102
+            let mut camera_builder = CameraBuilder {
103
+                aspect: picture.width as S / picture.height as S,
104
+                ..Default::default()
105
+            };
106
+            let mut given_focus_dist = false;
134 107
             let mut kv = args;
135 108
 
136 109
             loop {
137 110
                 if kv.len() < 2 {
138
-                    if !given_dist_to_focus {
139
-                        dist_to_focus = (look_from - look_at).magnitude();
111
+                    if !given_focus_dist {
112
+                        camera_builder.focus_dist = (camera_builder.look_from - camera_builder.look_at).magnitude();
140 113
                     }
141
-                    return Ok(Camera::new(
142
-                        look_from,
143
-                        look_at,
144
-                        look_up,
145
-                        vfov,
146
-                        aspect,
147
-                        aperture,
148
-                        dist_to_focus,
149
-                    ))
114
+                    return Ok(camera_builder)
150 115
                 } else {
151 116
                     let k = &kv[0];
152 117
                     let v = &kv[1];
@@ -154,15 +119,15 @@ fn create_camera(node: &Node, picture: &Picture) -> Result<Camera> {
154 119
 
155 120
                     let name = get_label_name(k)?;
156 121
                     match name.as_ref() {
157
-                        "look-from" => look_from = get_v3(v)?,
158
-                        "look-at" => look_at = get_v3(v)?,
159
-                        "look-up" => look_up = get_v3(v)?,
160
-                        "vfov" => vfov = get_float(v)?,
161
-                        "aspect" => aspect = get_float(v)?,
162
-                        "aperture" => aperture = get_float(v)?,
122
+                        "look-from" => camera_builder.look_from = get_v3(v)?,
123
+                        "look-at" => camera_builder.look_at = get_v3(v)?,
124
+                        "look-up" => camera_builder.look_up = get_v3(v)?,
125
+                        "vfov" => camera_builder.vfov = get_float(v)?,
126
+                        "aspect" => camera_builder.aspect = get_float(v)?,
127
+                        "aperture" => camera_builder.aperture = get_float(v)?,
163 128
                         "focus-dist" => {
164
-                            dist_to_focus = get_float(v)?;
165
-                            given_dist_to_focus = true;
129
+                            camera_builder.focus_dist = get_float(v)?;
130
+                            given_focus_dist = true;
166 131
                         },
167 132
                         _ => return Err(RayTracerError::SceneParser)
168 133
                     }