Ticket #2185: All.hs

File All.hs, 4.8 KB (added by igloo, 4 years ago)
Line 
1
2module Main (main) where
3
4import Control.Parallel.Strategies
5import System.Environment
6import System.IO
7
8type CFlt = Float
9data Color = Color !CFlt !CFlt !CFlt deriving Show
10
11c_black :: Color
12c_black = Color 0.0 0.0 0.0
13c_white :: Color
14c_white = Color 1.0 1.0 1.0
15
16get_color :: Flt -> Flt -> Scene -> Color
17get_color x y scn =
18 let (Scene _ (Camera pos fwd up right) _ _) = scn
19     dir0 = vnorm $ vadd3 fwd (vscale right (-x)) (vscale up y)
20     ray = Ray pos dir0
21 in
22  trace scn ray infinity
23
24gen_pixel_list :: Flt -> Flt -> Flt -> Flt -> Flt -> Flt -> Scene
25               -> [(Float,Float,Float,Float,Float)]
26gen_pixel_list curx cury stopx stopy maxx maxy scene =
27 [ let scx = (x - midx) / midx
28       scy = (y - midy) / midy
29       Color r g b = get_color scx (scy * (midy / midx)) scene
30   in (scx, scy, r, g, b)
31 | x <- [curx .. (stopx - 1)],
32   y <- [cury .. (stopy - 1)]
33 ]
34    where midx = maxx / 2
35          midy = maxy / 2
36
37gen_blocks_list :: Bool -> Flt -> Flt -> Flt -> Scene -> IO ()
38gen_blocks_list par maxx maxy block_size scene =
39 let xblocks = maxx / block_size
40     yblocks = maxy / block_size
41     blocks  = [ (x*block_size, y*block_size)
42               | x <- [0..xblocks-1],
43                 y <- [0..yblocks-1] ]
44     mapper = if par then parMap rnf else map
45     pixels  = mapper
46               (\(x,y) -> gen_pixel_list x y (x+block_size) (y+block_size) maxx maxy scene)
47               blocks
48 in
49  do
50   print ('A', xblocks)
51   print ('B', yblocks)
52   print ('C', blocks)
53   rnf pixels `seq` return ()
54
55
56main :: IO ()
57main = do
58  args <- getArgs
59  let par = null args
60  display par xscene
61  display par xscene
62  display par xscene
63  display par xscene
64  display par xscene
65
66display :: Bool -> Scene -> IO ()
67display par scene = do
68  gen_blocks_list par 512 512 128 scene
69
70data Rayint = RayHit !Flt !Vec !Vec !Texture | RayMiss deriving Show
71
72data Material = Material Color !Flt !Flt !Flt !Flt !Flt deriving Show
73type Texture = Rayint -> Material
74
75showTexture :: Texture -> String
76showTexture t = show $ t RayMiss
77
78instance Show Texture where
79 show = showTexture
80
81t_white :: Rayint -> Material
82t_white _ = Material c_white 0 0 0 1 2
83
84data Solid =  Sphere !Vec !Flt !Flt !Flt
85            | SNothing deriving Show
86
87sphere :: Vec -> Flt -> Solid
88sphere c r =
89 Sphere c r (r*r) (1.0/r)
90
91rayint :: Solid -> Ray -> Flt -> Texture -> Rayint
92
93rayint (Sphere center r rsqr _) (Ray e dir0) dist t =
94 let eo = vsub center e
95     v  = vdot eo dir0
96 in
97 if (dist >= (v - r)) && (v > 0.0)
98 then
99  let vsqr = v*v
100      csqr = vdot eo eo
101      disc = rsqr - (csqr - vsqr) in
102  if disc < 0.0 then
103   RayMiss
104  else
105   let d = sqrt disc
106       p = vscaleadd e dir0 (v - d)
107       n = vnorm (vsub p center) in
108    RayHit (v-d) p n t
109 else
110  RayMiss
111
112rayint SNothing _ _ _ = RayMiss
113
114data Camera = Camera !Vec !Vec !Vec !Vec deriving Show
115
116camera :: Vec -> Vec -> Vec -> Flt -> Camera
117camera pos at up angle =
118 let fwd   = vnorm $ vsub at pos
119     right = vnorm $ vcross up fwd
120     up_   = vnorm $ vcross fwd right
121     cam_scale = tan ((pi/180)*(angle/2))
122 in
123  Camera pos fwd
124         (vscale up_ cam_scale)
125         (vscale right cam_scale)
126
127data Scene = Scene !Solid !Camera !Texture !Color deriving Show
128
129cam :: Camera
130cam = camera (Vec 2.1 1.3 1.7)
131                        (Vec 0 0 0)
132                        (Vec 0 0 1)
133                        45
134
135bgc :: Color
136bgc = Color 0.078 0.361 0.753
137
138xscene :: Scene
139xscene = let prim = sphere (Vec 0.272166 0.272166 0.544331) 0.166667
140         in Scene prim cam t_white bgc
141
142shade :: Rayint -> Color
143shade ri =
144 case ri of
145  RayHit _ _ _ _ -> c_black
146  RayMiss -> c_white
147
148trace :: Scene -> Ray -> Flt -> Color
149trace scn ray depth =
150    let (Scene xsld _ dtex _) = scn
151        ri = rayint xsld ray depth dtex
152    in shade ri
153
154type Flt = Float
155
156infinity :: Flt
157infinity = 1.0 / 0.0
158
159data Vec = Vec {vec_x, vec_y, vec_z :: !Flt} deriving Show
160data Ray = Ray !Vec !Vec deriving Show
161
162vdot :: Vec -> Vec -> Flt
163vdot !v1 !v2 =
164 ((vec_x v1) * (vec_x v2)) + ((vec_y v1) * (vec_y v2)) + ((vec_z v1) * (vec_z v2))
165
166vcross :: Vec -> Vec -> Vec
167vcross !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
168 Vec
169  ((y1 * z2) - (z1 * y2))
170  ((z1 * x2) - (x1 * z2))
171  ((x1 * y2) - (y1 * x2))
172
173vadd3 :: Vec -> Vec -> Vec -> Vec
174vadd3 !(Vec x1 y1 z1) !(Vec x2 y2 z2) !(Vec x3 y3 z3) =
175    Vec (x1 + x2 + x3)
176        (y1 + y2 + y3)
177        (z1 + z2 + z3)
178
179vsub :: Vec -> Vec -> Vec
180vsub !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
181 Vec (x1 - x2)
182     (y1 - y2)
183     (z1 - z2)
184
185vscale :: Vec -> Flt -> Vec
186vscale v1 fac =
187 Vec ((vec_x v1) * fac)
188     ((vec_y v1) * fac)
189     ((vec_z v1) * fac)
190
191vscaleadd :: Vec -> Vec -> Flt -> Vec
192vscaleadd v1 v2 fac =
193 Vec ((vec_x v1) + ((vec_x v2) * fac))
194     ((vec_y v1) + ((vec_y v2) * fac))
195     ((vec_z v1) + ((vec_z v2) * fac))
196
197vnorm :: Vec -> Vec
198vnorm (Vec x1 y1 z1) =
199 let len = 1.0 / (sqrt ((x1*x1)+(y1*y1)+(z1*z1))) in
200 Vec (x1*len) (y1*len) (z1*len)