module Graphics.GLUtil.Camera3D
(
Camera(..), panRad, pan, tiltRad, tilt, rollRad, roll, dolly,
panGlobalRad, panGlobal, tiltGlobalRad, tiltGlobal, rollGlobalRad,
rollGlobal,
rosCamera, fpsCamera,
projectionMatrix, orthoMatrix, camMatrix,
deg2rad) where
import Linear (Conjugate (conjugate), Epsilon, V3 (..),
V4 (..))
import Linear.Matrix (M44, mkTransformation)
import Linear.Quaternion (Quaternion, axisAngle, rotate)
data Camera a = Camera { Camera a -> V3 a
forward :: V3 a
, Camera a -> V3 a
upward :: V3 a
, Camera a -> V3 a
rightward :: V3 a
, Camera a -> Quaternion a
orientation :: Quaternion a
, Camera a -> V3 a
location :: V3 a }
panRad :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
panRad :: a -> Camera a -> Camera a
panRad theta :: a
theta c :: Camera a
c = Camera a
c { orientation :: Quaternion a
orientation = Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c Quaternion a -> Quaternion a -> Quaternion a
forall a. Num a => a -> a -> a
* Quaternion a
r }
where r :: Quaternion a
r = V3 a -> a -> Quaternion a
forall a. (Epsilon a, Floating a) => V3 a -> a -> Quaternion a
axisAngle (Camera a -> V3 a
forall a. Camera a -> V3 a
upward Camera a
c) a
theta
pan :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
pan :: a -> Camera a -> Camera a
pan = a -> Camera a -> Camera a
forall a. (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
panRad (a -> Camera a -> Camera a)
-> (a -> a) -> a -> Camera a -> Camera a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. RealFloat a => a -> a
deg2rad
panGlobalRad :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
panGlobalRad :: a -> Camera a -> Camera a
panGlobalRad theta :: a
theta c :: Camera a
c = Camera a
c { orientation :: Quaternion a
orientation = Quaternion a
r Quaternion a -> Quaternion a -> Quaternion a
forall a. Num a => a -> a -> a
* Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c }
where r :: Quaternion a
r = V3 a -> a -> Quaternion a
forall a. (Epsilon a, Floating a) => V3 a -> a -> Quaternion a
axisAngle (Camera a -> V3 a
forall a. Camera a -> V3 a
upward Camera a
c) a
theta
panGlobal :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
panGlobal :: a -> Camera a -> Camera a
panGlobal = a -> Camera a -> Camera a
forall a. (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
panGlobalRad (a -> Camera a -> Camera a)
-> (a -> a) -> a -> Camera a -> Camera a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. RealFloat a => a -> a
deg2rad
tiltRad :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
tiltRad :: a -> Camera a -> Camera a
tiltRad theta :: a
theta c :: Camera a
c = Camera a
c { orientation :: Quaternion a
orientation = Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c Quaternion a -> Quaternion a -> Quaternion a
forall a. Num a => a -> a -> a
* Quaternion a
r }
where r :: Quaternion a
r = V3 a -> a -> Quaternion a
forall a. (Epsilon a, Floating a) => V3 a -> a -> Quaternion a
axisAngle (Camera a -> V3 a
forall a. Camera a -> V3 a
rightward Camera a
c) a
theta
tilt :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
tilt :: a -> Camera a -> Camera a
tilt = a -> Camera a -> Camera a
forall a. (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
tiltRad (a -> Camera a -> Camera a)
-> (a -> a) -> a -> Camera a -> Camera a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. RealFloat a => a -> a
deg2rad
tiltGlobalRad :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
tiltGlobalRad :: a -> Camera a -> Camera a
tiltGlobalRad theta :: a
theta c :: Camera a
c = Camera a
c { orientation :: Quaternion a
orientation = Quaternion a
r Quaternion a -> Quaternion a -> Quaternion a
forall a. Num a => a -> a -> a
* Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c }
where r :: Quaternion a
r = V3 a -> a -> Quaternion a
forall a. (Epsilon a, Floating a) => V3 a -> a -> Quaternion a
axisAngle (Camera a -> V3 a
forall a. Camera a -> V3 a
rightward Camera a
c) a
theta
tiltGlobal :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
tiltGlobal :: a -> Camera a -> Camera a
tiltGlobal = a -> Camera a -> Camera a
forall a. (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
tiltGlobalRad (a -> Camera a -> Camera a)
-> (a -> a) -> a -> Camera a -> Camera a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. RealFloat a => a -> a
deg2rad
rollRad :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
rollRad :: a -> Camera a -> Camera a
rollRad theta :: a
theta c :: Camera a
c = Camera a
c { orientation :: Quaternion a
orientation = Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c Quaternion a -> Quaternion a -> Quaternion a
forall a. Num a => a -> a -> a
* Quaternion a
r }
where r :: Quaternion a
r = V3 a -> a -> Quaternion a
forall a. (Epsilon a, Floating a) => V3 a -> a -> Quaternion a
axisAngle (Camera a -> V3 a
forall a. Camera a -> V3 a
forward Camera a
c) a
theta
roll :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
roll :: a -> Camera a -> Camera a
roll = a -> Camera a -> Camera a
forall a. (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
rollRad (a -> Camera a -> Camera a)
-> (a -> a) -> a -> Camera a -> Camera a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. RealFloat a => a -> a
deg2rad
rollGlobalRad :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
rollGlobalRad :: a -> Camera a -> Camera a
rollGlobalRad theta :: a
theta c :: Camera a
c = Camera a
c { orientation :: Quaternion a
orientation = Quaternion a
r Quaternion a -> Quaternion a -> Quaternion a
forall a. Num a => a -> a -> a
* Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c }
where r :: Quaternion a
r = V3 a -> a -> Quaternion a
forall a. (Epsilon a, Floating a) => V3 a -> a -> Quaternion a
axisAngle (Camera a -> V3 a
forall a. Camera a -> V3 a
forward Camera a
c) a
theta
rollGlobal :: (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
rollGlobal :: a -> Camera a -> Camera a
rollGlobal = a -> Camera a -> Camera a
forall a. (Epsilon a, RealFloat a) => a -> Camera a -> Camera a
rollGlobalRad (a -> Camera a -> Camera a)
-> (a -> a) -> a -> Camera a -> Camera a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. RealFloat a => a -> a
deg2rad
dolly :: (Conjugate a, Epsilon a, RealFloat a) => V3 a -> Camera a -> Camera a
dolly :: V3 a -> Camera a -> Camera a
dolly t :: V3 a
t c :: Camera a
c = Camera a
c { location :: V3 a
location = Camera a -> V3 a
forall a. Camera a -> V3 a
location Camera a
c V3 a -> V3 a -> V3 a
forall a. Num a => a -> a -> a
+ V3 a
t' }
where t' :: V3 a
t' = Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c Quaternion a -> V3 a -> V3 a
forall a.
(Conjugate a, RealFloat a) =>
Quaternion a -> V3 a -> V3 a
`rotate` V3 a
t
deg2rad :: RealFloat a => a -> a
deg2rad :: a -> a
deg2rad x :: a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi a -> a -> a
forall a. Fractional a => a -> a -> a
/ 180
rosCamera :: (Epsilon a, RealFloat a) => Camera a
rosCamera :: Camera a
rosCamera = V3 a -> V3 a -> V3 a -> Quaternion a -> V3 a -> Camera a
forall a. V3 a -> V3 a -> V3 a -> Quaternion a -> V3 a -> Camera a
Camera (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 1 0 0) (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 0 0 1) (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 0 1 0) 1 0
fpsCamera :: (Epsilon a, RealFloat a) => Camera a
fpsCamera :: Camera a
fpsCamera = V3 a -> V3 a -> V3 a -> Quaternion a -> V3 a -> Camera a
forall a. V3 a -> V3 a -> V3 a -> Quaternion a -> V3 a -> Camera a
Camera (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 0 0 (-1)) (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 0 1 0) (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 1 0 0) 1 0
projectionMatrix :: (Conjugate a, Epsilon a, RealFloat a)
=> a -> a -> a -> a -> M44 a
projectionMatrix :: a -> a -> a -> a -> M44 a
projectionMatrix fovy :: a
fovy aspect :: a
aspect near :: a
near far :: a
far =
V4 a -> V4 a -> V4 a -> V4 a -> M44 a
forall a. a -> a -> a -> a -> V4 a
V4 (a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 (a
focal a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
aspect) 0 0 0)
(a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 0 a
focal 0 0)
(a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 0 0 ((a
fara -> a -> a
forall a. Num a => a -> a -> a
+a
near) a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a
near a -> a -> a
forall a. Num a => a -> a -> a
- a
far)) ((2a -> a -> a
forall a. Num a => a -> a -> a
*a
fara -> a -> a
forall a. Num a => a -> a -> a
*a
near) a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a
near a -> a -> a
forall a. Num a => a -> a -> a
- a
far)))
(a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 0 0 (-1) 0)
where focal :: a
focal = 1 a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a. Floating a => a -> a
tan (a
fovy a -> a -> a
forall a. Num a => a -> a -> a
* 0.5)
orthoMatrix :: (Num a, Fractional a) => a -> a -> a -> a -> a -> a -> M44 a
orthoMatrix :: a -> a -> a -> a -> a -> a -> M44 a
orthoMatrix left :: a
left right :: a
right top :: a
top bottom :: a
bottom near :: a
near far :: a
far =
V4 a -> V4 a -> V4 a -> V4 a -> M44 a
forall a. a -> a -> a -> a -> V4 a
V4 (a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 (2a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
righta -> a -> a
forall a. Num a => a -> a -> a
-a
left)) 0 0 (-(a
righta -> a -> a
forall a. Num a => a -> a -> a
+a
left)a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
righta -> a -> a
forall a. Num a => a -> a -> a
-a
left)) )
(a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 0 (2a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
topa -> a -> a
forall a. Num a => a -> a -> a
-a
bottom)) 0 (-(a
topa -> a -> a
forall a. Num a => a -> a -> a
+a
bottom)a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
topa -> a -> a
forall a. Num a => a -> a -> a
-a
bottom)) )
(a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 0 0 (-2a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
fara -> a -> a
forall a. Num a => a -> a -> a
-a
near)) (-(a
fara -> a -> a
forall a. Num a => a -> a -> a
+a
near)a -> a -> a
forall a. Fractional a => a -> a -> a
/(a
fara -> a -> a
forall a. Num a => a -> a -> a
-a
near)) )
(a -> a -> a -> a -> V4 a
forall a. a -> a -> a -> a -> V4 a
V4 0 0 0 1)
camMatrix :: (Conjugate a, Epsilon a, RealFloat a) => Camera a -> M44 a
camMatrix :: Camera a -> M44 a
camMatrix c :: Camera a
c = Quaternion a -> V3 a -> M44 a
forall a. Num a => Quaternion a -> V3 a -> M44 a
mkTransformation Quaternion a
q (Quaternion a -> V3 a -> V3 a
forall a.
(Conjugate a, RealFloat a) =>
Quaternion a -> V3 a -> V3 a
rotate Quaternion a
q (V3 a -> V3 a) -> (Camera a -> V3 a) -> Camera a -> V3 a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. V3 a -> V3 a
forall a. Num a => a -> a
negate (V3 a -> V3 a) -> (Camera a -> V3 a) -> Camera a -> V3 a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Camera a -> V3 a
forall a. Camera a -> V3 a
location (Camera a -> V3 a) -> Camera a -> V3 a
forall a b. (a -> b) -> a -> b
$ Camera a
c)
where q :: Quaternion a
q = Quaternion a -> Quaternion a
forall a. Conjugate a => a -> a
conjugate (Quaternion a -> Quaternion a) -> Quaternion a -> Quaternion a
forall a b. (a -> b) -> a -> b
$ Camera a -> Quaternion a
forall a. Camera a -> Quaternion a
orientation Camera a
c