content: {-# LANGUAGE ConstraintKinds #-}
  {-# LANGUAGE DeriveDataTypeable    #-}
  {-# LANGUAGE FlexibleContexts      #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE TypeFamilies          #-}
  {-# LANGUAGE UndecidableInstances  #-}
  
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Diagrams.ThreeD.Render
  -- Copyright   :  (c) 2013 diagrams-lib team (see LICENSE)
  -- License     :  BSD-style (see LICENSE)
  -- Maintainer  :  diagrams-discuss@googlegroups.com
  --
  -- Types to specify lighting for 3D rendering.
  --
  -----------------------------------------------------------------------------
  
  module Diagrams.ThreeD.Light where
  
  import           Data.Colour
  import           Data.Monoid
  import           Data.Typeable
  
  import           Diagrams.Core
  import           Diagrams.Direction
  import           Diagrams.ThreeD.Types
  
  -- | A @PointLight@ radiates uniformly in all directions from a given
  -- point.
  data PointLight n = PointLight (Point V3 n) (Colour Double)
    deriving Typeable
  
  type instance V (PointLight n) = V3
  type instance N (PointLight n) = n
  
  -- | A @ParallelLight@ casts parallel rays in the specified direction,
  -- from some distant location outside the scene.
  data ParallelLight n = ParallelLight (V3 n) (Colour Double)
    deriving Typeable
  
  type instance V (ParallelLight n) = V3
  type instance N (ParallelLight n) = n
  
  instance Fractional n => Transformable (PointLight n) where
    transform t (PointLight p c) = PointLight (transform t p) c
  
  instance Transformable (ParallelLight n) where
    transform t (ParallelLight v c) = ParallelLight (transform t v) c
  
  -- | Construct a Diagram with a single PointLight at the origin, which
  -- takes up no space.
  pointLight :: (Typeable n, Num n, Ord n, Renderable (PointLight n) b)
                => Colour Double -- ^ The color of the light
                -> QDiagram b V3 n Any
  pointLight c = mkQD (Prim $ PointLight origin c) mempty mempty mempty
                 (Query . const . Any $ False)
  
  -- | Construct a Diagram with a single ParallelLight, which takes up no space.
  parallelLight :: (Typeable n, OrderedField n, Renderable (ParallelLight n) b)
                   => Direction V3 n -- ^ The direction in which the light travels.
                   -> Colour Double  -- ^ The color of the light.
                   -> QDiagram b V3 n Any
  parallelLight d c = mkQD (Prim $ ParallelLight (fromDirection d) c)
                      mempty mempty mempty (Query . const . Any $ False)
  