{-# OPTIONS_GHC -Wall #-}
module Graphics.FieldTrip.Material
  ( Material(..)
  , setAmbient , setDiffuse , setSpecular , setEmission , setShininess
  , plastic, flat
  , defaultMat, bluePlastic

  , material
  ) where

import Graphics.Rendering.OpenGL
import Graphics.FieldTrip.Misc
import Graphics.FieldTrip.Color

data Material = Mat
  { ambientM   :: Col
  , diffuseM   :: Col
  , specularM  :: Col
  , emissionM  :: Col
  , shininessM :: R   -- Between 0 and 1
  } deriving Show

defaultMat :: Material
defaultMat = Mat { ambientM   = rgba 0.2 0.2 0.2 1.0
                 , diffuseM   = rgba 0.8 0.8 0.8 1.0
                 , specularM  = rgba 0.0 0.0 0.0 1.0
                 , emissionM  = rgba 0.0 0.0 0.0 1.0
                 , shininessM = 0
                 }

setAmbient :: Col -> Material -> Material
setAmbient c m = m{ ambientM=c }

setDiffuse :: Col -> Material -> Material
setDiffuse c m = m{ diffuseM=c }

setSpecular :: Col -> Material -> Material
setSpecular c m = m{ specularM=c }

setEmission :: Col -> Material -> Material
setEmission c m = m{ emissionM=c }

setShininess :: R -> Material -> Material
setShininess c m = m{ shininessM=c }

polishedPlastic :: Material-> Material
polishedPlastic = \m -> m { specularM = (rgba 1.0 1.0 1.0 1.0)
                          , emissionM = (rgba 0.0 0.0 0.0 1.0)
                          , shininessM = (70.0/128.0)
                          }

-- Alternate defn.
-- polishedPlastic = setSpecular (rgba 1.0 1.0 1.0 1.0)
--                 . setEmission (rgba 0.0 0.0 0.0 1.0)
--                 . setShininess (70.0/128.0)
--
-- What do we like better, point free or clear nonsequentiality?

setAmbDiff :: Col -> Material -> Material
setAmbDiff c = \m -> m { ambientM = c
                       , diffuseM = c
                       }

bluePlastic :: Material
bluePlastic = plastic blue

plastic :: Col -> Material
plastic = polishedPlastic . flat

flat :: Col -> Material
flat = flip setAmbDiff defaultMat

material :: Material -> IO()
material m = do materialAmbient Front $= ambientM m
                materialDiffuse Front $= diffuseM m
                materialSpecular Front $= specularM m
                materialEmission Front $= emissionM m
                materialShininess Front $= (shininessM m)*128.0