{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}

-- | Transforms has a pile of utility functions for data type conversion
module Haskengl.Math.Transforms (addCamera, Vertex(..)) where

-- IMPORTS --

import qualified Graphics.Rendering.OpenGL as GL

import Foreign.Storable

import Relude

import Haskengl.Types

-- classes --

class Vertex a where
  toPoint :: a -> Point
  fromPoint :: Point -> Maybe a
  fromPointLossy :: Point -> a

instance Vertex Point where
  toPoint point = point
  fromPoint point = Just point
  fromPointLossy point = point

instance Vertex (GL.Color4 GL.GLfloat) where
  toPoint (GL.Color4 x y z k) = Point x y z k
  fromPoint (Point x y z k) = Just $ GL.Color4 x y z k
  fromPointLossy (Point x y z k) = GL.Color4 x y z k

instance Vertex (GL.Vertex4 GL.GLfloat) where
  toPoint (GL.Vertex4 x y z k) = Point x y z k
  fromPoint (Point x y z k) = Just $ GL.Vertex4 x y z k
  fromPointLossy (Point x y z k) = GL.Vertex4 x y z k

instance Vertex (GL.Vertex3 GL.GLfloat) where
  toPoint (GL.Vertex3 x y z) = Point x y z 0
  fromPoint (Point x y z 0) = Just $ GL.Vertex3 x y z
  fromPoint (Point x y z _) = Nothing
  fromPointLossy (Point x y z _) = GL.Vertex3 x y z

instance Vertex (GL.Vertex2 GL.GLfloat) where
  toPoint (GL.Vertex2 x y) = Point x y 0 0
  fromPoint (Point x y 0 0) = Just $ GL.Vertex2 x y
  fromPoint (Point x y _ _) = Nothing
  fromPointLossy (Point x y _ _) = GL.Vertex2 x y

addCamera :: Point -> Point -> Point
addCamera camera@(Point 0 0 cz 0) point@(Point x y z k) =
  Point
    (cz * x / (cz - z))
    (cz * y / (cz - z))
    z
    (cz * k / (cz - z))
