-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCamera.hs
executable file
·135 lines (119 loc) · 3.93 KB
/
Camera.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
{-# LANGUAGE BangPatterns #-}
-- camera module
module Camera where
-- math
import Math3D.Vector
import Math3D.CommonOps
import Math3D.Ray
-- import Math3D.Transform
import Math3D.Onb
-- spectral
import Spectral.PbrtSpecdata
import Utility.Utils
import Utility.BaseEnum
import Random
-- thirdparty
import Prelude hiding (subtract)
import System.Random
import GHC.Float
data Camera = Cam {
corigin :: Vector,
lowerLeftCorner :: Vector,
horizontal :: Vector,
vertical :: Vector,
camU :: Vector,
camV :: Vector,
camW :: Vector,
lensRadius :: Double,
time0 :: Double,
time1 :: Double
} deriving (Eq, Show)
mkCam :: Vector -> Vector -> Vector -> Double -> Double -> Double -> Double -> Double -> Double -> Camera
mkCam !lookFrom !lookAt !vup !vfov !aspect_ratio !aperture !focusDist !t0 !t1 =
let theta = degrees_to_radians vfov
h = tan (theta / 2.0)
viewPortH = 2.0 * h
viewPortW = aspect_ratio * viewPortH
cw = toUnit $! subtract lookFrom lookAt
cu = toUnit $! cross3d vup cw
cv = cross3d cw cu
cameraOrigin = lookFrom
cameraH = multiplyS cu (focusDist * viewPortW)
cameraV = multiplyS cv (focusDist * viewPortH)
fDcw = multiplyS cw focusDist
vhalf = divideS cameraV 2.0
hhalf = divideS cameraH 2.0
llC1 = subtract cameraOrigin hhalf
llc2 = subtract llC1 vhalf
llCorner = subtract llc2 fDcw
in Cam {
corigin = cameraOrigin,
lowerLeftCorner = llCorner,
horizontal = cameraH,
vertical = cameraV,
camU = cu,
camW = cw,
camV = cv,
lensRadius = aperture / 2.0,
time0 = t0,
time1 = t1
}
mkCamTime :: Vector -> Vector -> Vector -> Double -> Double -> Double -> Double -> Camera
mkCamTime lookFrom lookAt vup vfov aspect_ratio aperture focusDist =
mkCam lookFrom lookAt vup vfov aspect_ratio aperture focusDist 0.0 0.0
--
getCameraOnb :: Camera -> OrthoNormalBase
getCameraOnb c =
let w = camW c
v = camV c
u = camU c
in onb3 w v u
getCameraTime :: RandomGen g => g -> Camera -> Double
getCameraTime gen c =
let t0 = time0 c
t1 = time1 c
RandResult (res, _) = randomDouble gen (t0, t1)
in res
-- getCameraLocatingParams :: RandomGen g => g -> Camera -> LocatingParams
-- getCameraLocatingParams g c = (corigin c, getCameraOnb c, getCameraTime g c)
-- camera for listing 69
lookF :: Vector
lookF = fromList2Vec 13.0 [2.0, 3.0]
lookT :: Vector
lookT = fromList2Vec 0.0 [0.0, 0.0]
vUp :: Vector
vUp = fromList2Vec 0.0 [1.0, 0.0]
mkCamera :: Camera
mkCamera =
mkCamTime
lookF -- look from
lookT -- look to
vUp -- vup
20.0 -- vfov
(3.0/2.0) -- aspect ratio
0.1 -- aperture
10.0 -- focus distance
getRay :: RandomGen g => g -> Camera -> Double -> Double -> RandomResult Ray g
getRay gen Cam {corigin = cameraOrigin, horizontal = cameraH,
vertical = cameraV, lowerLeftCorner = llCorner,
camU = cu, camW = cw, camV = cv, lensRadius = lr,
time0 = t0, time1 = t1
} s t =
let RandResult (uvec, g) = randomUnitDisk gen
rd = multiplyS uvec lr
rdx = vget rd 0
rdy = vget rd 1
offset = add (multiplyS cu rdx) (multiplyS cv rdy)
rorigin = add cameraOrigin offset
rdir1 = add llCorner (multiplyS cameraH s)
rdir2 = add rdir1 (multiplyS cameraV t)
rdir3 = subtract rdir2 cameraOrigin
rdir4 = subtract rdir3 offset
RandResult (timeD, g2) = randomDouble g (t0, t1)
lambdaStart = word2Float visibleWavelengthStart
lambdaEnd = word2Float visibleWavelengthEnd
RandResult (wlength, g3) = randomWaveVal g (lambdaStart, lambdaEnd)
in RandResult (Rd {origin = rorigin,
direction = rdir4,
rtime = timeD,
wavelength = wlength}, g3)