{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE TypeSynonymInstances   #-}
module Graphics.SceneGraph.Matrix
  ( translateM
  , translatePostM
  , scaleM
  , rotateM
  , rotatePostM
  ) where

-- Warning: Because this matrix is going to get passed directly to GL we convert to GL space
-- here.

import           Control.Lens ((^.))
import           Linear       (M44, R1 (..), R2 (..), R3 (..), V3 (..), V4 (..),
                               (!*!))


asMatrix :: V3 Float -> M44 Float
asMatrix :: V3 Float -> M44 Float
asMatrix (V3 Float
x Float
y Float
z) = V4 Float -> V4 Float -> V4 Float -> V4 Float -> M44 Float
forall a. a -> a -> a -> a -> V4 a
V4
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
1 Float
0 Float
0 Float
x)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
0 Float
1 Float
0 Float
y)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
0 Float
0 Float
1 Float
z)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
0 Float
0 Float
0 Float
1)

translateM :: V3 Float -> M44 Float -> M44 Float
translateM :: V3 Float -> M44 Float -> M44 Float
translateM V3 Float
v M44 Float
m = V3 Float -> M44 Float
asMatrix V3 Float
v M44 Float -> M44 Float -> M44 Float
forall (m :: * -> *) (t :: * -> *) (n :: * -> *) a.
(Functor m, Foldable t, Additive t, Additive n, Num a) =>
m (t a) -> t (n a) -> m (n a)
!*! M44 Float
m

translatePostM :: V3 Float -> M44 Float -> M44 Float
translatePostM :: V3 Float -> M44 Float -> M44 Float
translatePostM V3 Float
v M44 Float
m = M44 Float
m M44 Float -> M44 Float -> M44 Float
forall (m :: * -> *) (t :: * -> *) (n :: * -> *) a.
(Functor m, Foldable t, Additive t, Additive n, Num a) =>
m (t a) -> t (n a) -> m (n a)
!*! V3 Float -> M44 Float
asMatrix V3 Float
v

scaleM :: V3 Float -> M44 Float -> M44 Float
scaleM :: V3 Float -> M44 Float -> M44 Float
scaleM V3 Float
v M44 Float
m = M44 Float
m M44 Float -> M44 Float -> M44 Float
forall (m :: * -> *) (t :: * -> *) (n :: * -> *) a.
(Functor m, Foldable t, Additive t, Additive n, Num a) =>
m (t a) -> t (n a) -> m (n a)
!*! V4 Float -> V4 Float -> V4 Float -> V4 Float -> M44 Float
forall a. a -> a -> a -> a -> V4 a
V4
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 (V3 Float
vV3 Float -> Getting Float (V3 Float) Float -> Float
forall s a. s -> Getting a s a -> a
^.Getting Float (V3 Float) Float
forall (t :: * -> *) a. R1 t => Lens' (t a) a
_x) Float
0 Float
0 Float
0)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
0 (V3 Float
vV3 Float -> Getting Float (V3 Float) Float -> Float
forall s a. s -> Getting a s a -> a
^.Getting Float (V3 Float) Float
forall (t :: * -> *) a. R2 t => Lens' (t a) a
_y) Float
0 Float
0)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
0 Float
0 (V3 Float
vV3 Float -> Getting Float (V3 Float) Float -> Float
forall s a. s -> Getting a s a -> a
^.Getting Float (V3 Float) Float
forall (t :: * -> *) a. R3 t => Lens' (t a) a
_z) Float
0)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
0 Float
0 Float
0 Float
1)

-- | Build rotational transform matrix for rotate of ''theta'' around a vector.
rotateM' :: Float -> V3 Float -> M44 Float
rotateM' :: Float -> V3 Float -> M44 Float
rotateM' Float
theta (V3 Float
x Float
y Float
z) = V4 Float -> V4 Float -> V4 Float -> V4 Float -> M44 Float
forall a. a -> a -> a -> a -> V4 a
V4
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
c) (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
yFloat -> Float -> Float
forall a. Num a => a -> a -> a
-Float
sFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
z) (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
z Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
sFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
y) Float
0)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
yFloat -> Float -> Float
forall a. Num a => a -> a -> a
+Float
sFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
z) (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
yFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
c) (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
yFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
z Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
sFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
x)  Float
0)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
xFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
zFloat -> Float -> Float
forall a. Num a => a -> a -> a
-Float
sFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
y) (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
yFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
z Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
sFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
x) (Float
tFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
zFloat -> Float -> Float
forall a. Num a => a -> a -> a
*Float
zFloat -> Float -> Float
forall a. Num a => a -> a -> a
+Float
c) Float
0)
  (Float -> Float -> Float -> Float -> V4 Float
forall a. a -> a -> a -> a -> V4 a
V4 Float
0 Float
0 Float
0 Float
1)
  where
    t :: Float
t = Float
1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float -> Float
forall a. Floating a => a -> a
cos Float
theta
    c :: Float
c = Float -> Float
forall a. Floating a => a -> a
cos Float
theta
    s :: Float
s = Float -> Float
forall a. Floating a => a -> a
sin Float
theta

rotateM :: Float -> V3 Float -> M44 Float -> M44 Float
rotateM :: Float -> V3 Float -> M44 Float -> M44 Float
rotateM Float
theta V3 Float
v M44 Float
m = Float -> V3 Float -> M44 Float
rotateM' Float
theta V3 Float
v M44 Float -> M44 Float -> M44 Float
forall (m :: * -> *) (t :: * -> *) (n :: * -> *) a.
(Functor m, Foldable t, Additive t, Additive n, Num a) =>
m (t a) -> t (n a) -> m (n a)
!*! M44 Float
m

rotatePostM :: Float -> V3 Float -> M44 Float -> M44 Float
rotatePostM :: Float -> V3 Float -> M44 Float -> M44 Float
rotatePostM Float
theta V3 Float
v M44 Float
m = M44 Float
m M44 Float -> M44 Float -> M44 Float
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 -> V3 Float -> M44 Float
rotateM' Float
theta V3 Float
v