-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCamera.hs
137 lines (118 loc) · 4.3 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
136
137
module Camera where
import Util
import Constants
data Camera =
Camera {
cameraDims :: !Vec2,
cameraPos :: !Vec3,
cameraYaw :: !Float,
cameraPitch :: !Float,
cameraZoom :: !Float,
cameraVel :: !Vec3,
cameraYawVel :: !Float,
cameraPitchVel :: !Float
}
createCamera :: Vec2 -> Vec3 -> Float -> Float -> Float -> Camera
createCamera dims pos yaw pitch zoom =
Camera {
cameraDims = dims,
cameraPos = pos,
cameraYaw = yaw,
cameraPitch = pitch,
cameraZoom = zoom,
cameraVel = (0, 0, 0),
cameraYawVel = 0,
cameraPitchVel = 0
}
applyCameraTranslate :: Camera -> Vec3 -> Vec3
applyCameraTranslate camera (x, y, z) =
(x - cx, y - cy, z - cz)
where (cx, cy, cz) = cameraPos camera
applyCameraYaw :: Camera -> Vec3 -> Vec3
applyCameraYaw camera (x, y, z) =
(x * c - z * s, y, x * s + z * c)
where c = cos(-yaw)
s = sin(-yaw)
yaw = cameraYaw camera
applyCameraPitch :: Camera -> Vec3 -> Vec2
applyCameraPitch camera (x, y, z) =
(x, z * percentZ + y * percentY)
where percentZ = sin(pitch)
percentY = cos(pitch)
pitch = cameraPitch camera
applyCameraZoom :: Camera -> Vec2 -> Vec2
applyCameraZoom camera (x, y) =
(x * zoom, y * zoom)
where zoom = cameraZoom camera
applyCameraDims :: Camera -> Vec2 -> Vec2
applyCameraDims camera (x, y) =
(x * height, y * height)
where (_, height) = cameraDims camera
mapCameraWorldToScreen :: Camera -> Vec3 -> Vec2
mapCameraWorldToScreen camera = applyCameraTranslate camera ...
applyCameraYaw camera ...
applyCameraPitch camera ...
applyCameraZoom camera ...
applyCameraDims camera
where (...) = flip (.)
unapplyCameraDims :: Camera -> Vec2 -> Vec2
unapplyCameraDims camera (x, y) =
(x / height, y / height)
where (_, height) = cameraDims camera
unapplyCameraZoom :: Camera -> Vec2 -> Vec2
unapplyCameraZoom camera (x, y) =
(x / zoom, y / zoom)
where zoom = cameraZoom camera
unapplyCameraPitch :: Camera -> Vec2 -> Vec3
unapplyCameraPitch camera (x, y) =
(x, 0, y / percentZ)
where percentZ = sin(pitch)
pitch = cameraPitch camera
unapplyCameraYaw :: Camera -> Vec3 -> Vec3
unapplyCameraYaw camera (x, y, z) =
(x * c - z * s, y, x * s + z * c)
where c = cos(yaw)
s = sin(yaw)
yaw = cameraYaw camera
unapplyCameraTranslate :: Camera -> Vec3 -> Vec3
unapplyCameraTranslate camera (x, y, z) =
(x + cx, y + cy, z + cz)
where (cx, cy, cz) = cameraPos camera
mapCameraScreenToWorld :: Camera -> Vec2 -> Vec3
mapCameraScreenToWorld camera = unapplyCameraDims camera ...
unapplyCameraZoom camera ...
unapplyCameraPitch camera ...
unapplyCameraYaw camera ...
unapplyCameraTranslate camera
where (...) = flip (.)
createCameraUpdater :: Updater Camera
createCameraUpdater = createUpdater camUR updateFunc
where updateFunc dt camera =
camera {
cameraPos = pos',
cameraYaw = yaw',
cameraPitch = pitch'',
cameraVel = vel',
cameraYawVel = yawVel',
cameraPitchVel = pitchVel''
}
where pos' = pos `v3Plus` (dt `v3Scale` vel)
vel' = (camVM ** dt) `v3Scale` vel
yaw' = yaw + dt * yawVel
yawVel' = (* camYVM ** dt) yawVel
pitch' = pitch + dt * pitchVel
pitchVel' = (* camPVM ** dt) pitchVel
(pitch'', pitchVel'') =
if pitch' < 0
then (0, 0)
else if pitch' > pi / 2
then (pi / 2, 0)
else (pitch', pitchVel')
Camera {
cameraPos = pos,
cameraYaw = yaw,
cameraPitch = pitch,
cameraVel = vel,
cameraYawVel = yawVel,
cameraPitchVel = pitchVel
} = camera