@@ -3,100 +3,48 @@ use path::SlicedSegment3D;
33
44use crate :: * ;
55
6- #[ derive( Debug , Copy , Clone ) ]
7- pub struct Observation {
8- pub eye : WPoint3 ,
9- pub center : WVec3 ,
10- pub up : WVec3 ,
11- }
12-
13- impl Default for Observation {
14- fn default ( ) -> Self {
15- Self :: new ( ( 0.0 , 0.0 , 1.0 ) , ( 0.0 , 0.0 , 0.0 ) , ( 0.0 , 1.0 , 0.0 ) )
16- }
17- }
18-
19- /// Type parameter for a camera that isn't yet looking anywhere
20- #[ derive( Debug , Copy , Clone ) ]
21- pub struct NoObservation ;
22-
23- impl Observation {
24- pub fn new ( eye : impl Into < WPoint3 > , center : impl Into < WVec3 > , up : impl Into < WVec3 > ) -> Self {
25- let eye = eye. into ( ) ;
26- let center = center. into ( ) ;
27- let up = up. into ( ) . normalize ( ) ;
28-
29- Self { eye, center, up }
30- }
31-
32- #[ rustfmt:: skip]
33- pub fn look_matrix ( & self ) -> WCTransform {
34- let Observation { eye, center, up, .. } = * self ;
35- let f = ( center - eye. to_vector ( ) ) . normalize ( ) ;
36- let s = f. cross ( up) . normalize ( ) ;
37- let u = s. cross ( f) . normalize ( ) ;
38-
39- CWTransform :: from_array (
40- // euclid used to let us specify things in column major order and now it doesn't.
41- // So we're just transposing it here.
42- CWTransform :: new (
43- s. x , u. x , -f. x , eye. x ,
44- s. y , u. y , -f. y , eye. y ,
45- s. z , u. z , -f. z , eye. z ,
46- 0.0 , 0.0 , 0.0 , 1.0 ,
47- )
48- . to_array_transposed ( ) ,
49- )
50- . inverse ( )
51- . unwrap ( )
52- }
6+ #[ derive( Debug , Clone ) ]
7+ pub struct Camera < P , O > {
8+ pub observation : O ,
9+ pub perspective : P ,
10+ pub render_options : CameraOptions ,
5311}
5412
55- #[ derive( Debug , Copy , Clone ) ]
56- pub struct Perspective {
57- pub fovy : f64 ,
58- pub width : usize ,
59- pub height : usize ,
60- pub aspect : f64 ,
61- pub znear : f64 ,
62- pub zfar : f64 ,
13+ #[ derive( Debug , Clone ) ]
14+ pub struct CameraOptions {
15+ pub pen_px_size : f64 ,
16+ pub hatch_pixel_spacing : f64 ,
17+ pub hatch_pixel_chop_factor : f64 ,
18+ pub hatch_slice_forgiveness : usize ,
19+ pub vert_hatch_brightness_scaling : f64 ,
20+ pub diag_hatch_brightness_scaling : f64 ,
6321}
6422
65- impl Default for Perspective {
23+ impl Default for CameraOptions {
6624 fn default ( ) -> Self {
67- Self :: new ( 45.0 , 1920 , 1080 , 0.1 , 100 .0)
25+ Self :: defaults_for_pen_px_size ( 4 .0)
6826 }
6927}
7028
71- /// Type parameter for a camera that doesn't yet have a defined perspective
72- #[ derive( Debug , Copy , Clone ) ]
73- pub struct NoPerspective ;
74-
75- impl Perspective {
76- pub fn new ( fovy : f64 , width : usize , height : usize , znear : f64 , zfar : f64 ) -> Self {
77- let aspect = width as f64 / height as f64 ;
29+ impl CameraOptions {
30+ pub fn defaults_for_pen_px_size ( px_size : f64 ) -> Self {
7831 Self {
79- fovy ,
80- width ,
81- height ,
82- aspect ,
83- znear ,
84- zfar ,
32+ pen_px_size : px_size ,
33+ hatch_pixel_spacing : px_size * 2.0 ,
34+ hatch_pixel_chop_factor : px_size / 3.0 ,
35+ hatch_slice_forgiveness : 1 ,
36+ vert_hatch_brightness_scaling : 0.8 ,
37+ diag_hatch_brightness_scaling : 0.46 ,
8538 }
8639 }
8740}
8841
89- #[ derive( Debug , Copy , Clone ) ]
90- pub struct Camera < P , O > {
91- pub observation : O ,
92- pub perspective : P ,
93- }
94-
9542impl Camera < NoPerspective , NoObservation > {
9643 pub fn new ( ) -> Self {
9744 Self {
9845 observation : NoObservation ,
9946 perspective : NoPerspective ,
47+ render_options : Default :: default ( ) ,
10048 }
10149 }
10250}
@@ -106,6 +54,7 @@ impl Default for Camera<Perspective, Observation> {
10654 Self {
10755 observation : Observation :: default ( ) ,
10856 perspective : Perspective :: default ( ) ,
57+ render_options : Default :: default ( ) ,
10958 }
11059 }
11160}
@@ -117,11 +66,16 @@ impl<P, O> Camera<P, O> {
11766 center : impl Into < WVec3 > ,
11867 up : impl Into < WVec3 > ,
11968 ) -> Camera < P , Observation > {
120- let Camera { perspective, .. } = self ;
69+ let Camera {
70+ perspective,
71+ render_options,
72+ ..
73+ } = self ;
12174 let observation = Observation :: new ( eye. into ( ) , center. into ( ) , up. into ( ) ) ;
12275 Camera {
12376 observation,
12477 perspective,
78+ render_options,
12579 }
12680 }
12781
@@ -133,11 +87,16 @@ impl<P, O> Camera<P, O> {
13387 znear : f64 ,
13488 zfar : f64 ,
13589 ) -> Camera < Perspective , O > {
136- let Camera { observation, .. } = self ;
90+ let Camera {
91+ observation,
92+ render_options,
93+ ..
94+ } = self ;
13795 let perspective = Perspective :: new ( fovy, width, height, znear, zfar) ;
13896 Camera {
13997 observation,
14098 perspective,
99+ render_options,
141100 }
142101 }
143102}
@@ -185,7 +144,8 @@ impl Camera<Perspective, Observation> {
185144
186145 let chunk_count = canvas_points
187146 . map ( |( p1t, p2t) | {
188- let rough_chop_size = ( p2t - p1t) . length ( ) / ( PEN_PX_SIZE / 2.0 ) ;
147+ let rough_chop_size =
148+ ( p2t - p1t) . length ( ) / ( self . render_options . pen_px_size / 2.0 ) ;
189149 rough_chop_size. round_ties_even ( ) as usize
190150 } )
191151 . unwrap_or_else ( || {
@@ -233,6 +193,89 @@ impl<O> Camera<Perspective, O> {
233193 }
234194}
235195
196+ #[ derive( Debug , Copy , Clone ) ]
197+ pub struct Observation {
198+ pub eye : WPoint3 ,
199+ pub center : WVec3 ,
200+ pub up : WVec3 ,
201+ }
202+
203+ impl Default for Observation {
204+ fn default ( ) -> Self {
205+ Self :: new ( ( 0.0 , 0.0 , 1.0 ) , ( 0.0 , 0.0 , 0.0 ) , ( 0.0 , 1.0 , 0.0 ) )
206+ }
207+ }
208+
209+ /// Type parameter for a camera that isn't yet looking anywhere
210+ #[ derive( Debug , Copy , Clone ) ]
211+ pub struct NoObservation ;
212+
213+ impl Observation {
214+ pub fn new ( eye : impl Into < WPoint3 > , center : impl Into < WVec3 > , up : impl Into < WVec3 > ) -> Self {
215+ let eye = eye. into ( ) ;
216+ let center = center. into ( ) ;
217+ let up = up. into ( ) . normalize ( ) ;
218+
219+ Self { eye, center, up }
220+ }
221+
222+ #[ rustfmt:: skip]
223+ pub fn look_matrix ( & self ) -> WCTransform {
224+ let Observation { eye, center, up, .. } = * self ;
225+ let f = ( center - eye. to_vector ( ) ) . normalize ( ) ;
226+ let s = f. cross ( up) . normalize ( ) ;
227+ let u = s. cross ( f) . normalize ( ) ;
228+
229+ CWTransform :: from_array (
230+ // euclid used to let us specify things in column major order and now it doesn't.
231+ // So we're just transposing it here.
232+ CWTransform :: new (
233+ s. x , u. x , -f. x , eye. x ,
234+ s. y , u. y , -f. y , eye. y ,
235+ s. z , u. z , -f. z , eye. z ,
236+ 0.0 , 0.0 , 0.0 , 1.0 ,
237+ )
238+ . to_array_transposed ( ) ,
239+ )
240+ . inverse ( )
241+ . unwrap ( )
242+ }
243+ }
244+
245+ #[ derive( Debug , Copy , Clone ) ]
246+ pub struct Perspective {
247+ pub fovy : f64 ,
248+ pub width : usize ,
249+ pub height : usize ,
250+ pub aspect : f64 ,
251+ pub znear : f64 ,
252+ pub zfar : f64 ,
253+ }
254+
255+ impl Default for Perspective {
256+ fn default ( ) -> Self {
257+ Self :: new ( 45.0 , 1920 , 1080 , 0.1 , 100.0 )
258+ }
259+ }
260+
261+ /// Type parameter for a camera that doesn't yet have a defined perspective
262+ #[ derive( Debug , Copy , Clone ) ]
263+ pub struct NoPerspective ;
264+
265+ impl Perspective {
266+ pub fn new ( fovy : f64 , width : usize , height : usize , znear : f64 , zfar : f64 ) -> Self {
267+ let aspect = width as f64 / height as f64 ;
268+ Self {
269+ fovy,
270+ width,
271+ height,
272+ aspect,
273+ znear,
274+ zfar,
275+ }
276+ }
277+ }
278+
236279#[ rustfmt:: skip]
237280fn frustum (
238281 l : f64 ,
0 commit comments