{-# LANGUAGE TemplateHaskell #-}
module Brick3D.Camera where
import Lens.Micro.Platform
import Linear.V3 
import Linear.Matrix
import Data.Default (Default(..))
import Brick3D.Type

-- | Represents 'Camera' that will be used for rendering
data Camera = Camera { Camera -> Position
_position :: Position
                     , Camera -> Rotation
_rotation :: Rotation
                     , Camera -> Float
_hFov :: Float
                     , Camera -> Float
_nearClip :: Float
                     , Camera -> Float
_farClip :: Float
                     }
makeLenses ''Camera

instance Default Camera where
  def :: Camera
def = Position -> Rotation -> Float -> Float -> Float -> Camera
Camera (Float -> Float -> Float -> Position
forall a. a -> a -> a -> V3 a
V3 Float
0 Float
0 Float
0) Rotation
forall a (t :: * -> *).
(Num a, Traversable t, Applicative t) =>
t (t a)
identity Float
60 Float
1 Float
10

-- | Move camera's transform
moveCamera :: Position -> Camera -> Camera
moveCamera :: Position -> Camera -> Camera
moveCamera Position
diff = (Position -> Identity Position) -> Camera -> Identity Camera
Lens' Camera Position
position((Position -> Identity Position) -> Camera -> Identity Camera)
-> Position -> Camera -> Camera
forall a s t. Num a => ASetter s t a a -> a -> s -> t
+~Position
diff

-- | Rotate Camera
--
-- カメラ自身の場所で回すにはどうすれば??
rotateCamera :: V3 Float -> Camera -> Camera
rotateCamera :: Position -> Camera -> Camera
rotateCamera Position
diff = (Rotation -> Identity Rotation) -> Camera -> Identity Camera
Lens' Camera Rotation
rotation((Rotation -> Identity Rotation) -> Camera -> Identity Camera)
-> (Rotation -> Rotation) -> Camera -> Camera
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~(\Rotation
r -> Rotation
rotationMat Rotation -> Rotation -> Rotation
forall (m :: * -> *) (t :: * -> *) (n :: * -> *) a.
(Functor m, Foldable t, Additive t, Additive n, Num a) =>
m (t a) -> t (n a) -> m (n a)
!*! Rotation
r)
  where
    -- 回転行列
    rotation_x :: a -> V3 (V3 a)
rotation_x a
theta = V3 a -> V3 a -> V3 a -> V3 (V3 a)
forall a. a -> a -> a -> V3 a
V3 (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3              a
1               a
0           a
0)
                          (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3              a
0      (a -> a
forall a. Floating a => a -> a
cos a
theta) (a -> a
forall a. Floating a => a -> a
sin a
theta))
                          (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3              a
0  (- (a -> a
forall a. Floating a => a -> a
sin a
theta)) (a -> a
forall a. Floating a => a -> a
cos a
theta))
    rotation_y :: a -> V3 (V3 a)
rotation_y a
theta = V3 a -> V3 a -> V3 a -> V3 (V3 a)
forall a. a -> a -> a -> V3 a
V3 (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3     (a -> a
forall a. Floating a => a -> a
cos a
theta)              a
0  (a -> a
forall a. Floating a => a -> a
sin a
theta))
                          (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3              a
0               a
1           a
0)
                          (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 (- (a -> a
forall a. Floating a => a -> a
sin a
theta))              a
0  (a -> a
forall a. Floating a => a -> a
cos a
theta))
    -- (cos θ) (-sin θ) 0
    -- (sin θ)  (cos θ) θ
    --      0        0  1
    rotation_z :: a -> V3 (V3 a)
rotation_z a
theta = V3 a -> V3 a -> V3 a -> V3 (V3 a)
forall a. a -> a -> a -> V3 a
V3 (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3     (a -> a
forall a. Floating a => a -> a
cos a
theta) (- (a -> a
forall a. Floating a => a -> a
sin a
theta))          a
0)
                          (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3     (a -> a
forall a. Floating a => a -> a
sin a
theta)     (a -> a
forall a. Floating a => a -> a
cos a
theta)          a
0)
                          (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3              a
0               a
0           a
1)
    -- | Combine all rotation matrix into one
    rotationMat :: Rotation
rotationMat = Float -> Rotation
forall a. Floating a => a -> V3 (V3 a)
rotation_x (Position
diffPosition -> Getting Float Position Float -> Float
forall s a. s -> Getting a s a -> a
^.Getting Float Position Float
forall (t :: * -> *) a. R1 t => Lens' (t a) a
_x) Rotation -> Rotation -> Rotation
forall (m :: * -> *) (t :: * -> *) (n :: * -> *) a.
(Functor m, Foldable t, Additive t, Additive n, Num a) =>
m (t a) -> t (n a) -> m (n a)
!*! Float -> Rotation
forall a. Floating a => a -> V3 (V3 a)
rotation_y (Position
diffPosition -> Getting Float Position Float -> Float
forall s a. s -> Getting a s a -> a
^.Getting Float Position Float
forall (t :: * -> *) a. R2 t => Lens' (t a) a
_y) Rotation -> Rotation -> Rotation
forall (m :: * -> *) (t :: * -> *) (n :: * -> *) a.
(Functor m, Foldable t, Additive t, Additive n, Num a) =>
m (t a) -> t (n a) -> m (n a)
!*! Float -> Rotation
forall a. Floating a => a -> V3 (V3 a)
rotation_z (Position
diffPosition -> Getting Float Position Float -> Float
forall s a. s -> Getting a s a -> a
^.Getting Float Position Float
forall (t :: * -> *) a. R3 t => Lens' (t a) a
_z)