module BabyRays.Scene where

import Core.Constants
import Core.Transform
import Core.Geometry

import BabyRays.Camera
import BabyRays.Types
import BabyRays.Color
import BabyRays.Light
import BabyRays.Shape
import BabyRays.Material

data Scene = Scene {backgroundColor :: Color,
                    ambientLight    :: Color,
                    lights          :: [Light],
                    shapes          :: [Shape],
                    camera          :: Camera,
                    image           :: Image}

defaultScene = Scene {backgroundColor = (0,0,0),
                      ambientLight    = (0.1,0.1,0.1),
                      -- lights       = [Spotlight (Point 100 (-30) 0) nearlywhite,
                      --                    Spotlight (Point 0 0 200) nearlywhite,
                      --                    Spotlight (Point 0 0 200) nearlywhite],
                      lights          = [Spotlight cameraLoc nearlywhite],
                      shapes          = objs,
                      camera          = view,
                      image           = film}
  where (view, film) = stdCamera cameraLoc (Vector 0 0 1) (Vector 0 1 0) (Vector 1 0 0)
        cameraLoc    = Point 0 0 (-200)
    -- (view, film) = stdCamera 100 cameraLoc dir up right -- (hat $ up `cross` dir)

        -- cameraLoc = Point 0 (-100) 0
        -- dir = (Point 0 0 200) .-. cameraLoc
        -- up = Vector 0 (1) 0
        -- right = Vector 1 0 0
        -- dir@(Vector vx vy vz) = Point 50 35 100 .-. cameraLoc
        -- wx = -(vy*vy + vz*vz) / (vx*vy)
        -- wz = vz/vy
        -- up = Vector wx 1 wz

        u    = Vector 100 0 0
        v    = Vector 0 100 0
        w    = Vector 0 0 100
        objs = makeBox flatred (Point (-100) 0 100) u v w
        -- objs = [Triangle (Point 0 0 100) (Point 100 0 100) (Point 100 100 100) flatgreen,
        --         Triangle (Point 0 0 100) (Point 100 100 100) (Point 0 100 100) flatgreen,
        --         Triangle (Point 0 100 100) (Point 100 100 100) (Point 100 100 200) flatgreen]

        -- objs = [Sphere (Point 0 0 0) 65 flatred]
        -- objs = [Triangle (Point 0 0 25) (Point 100 0 25) (Point 0 100 25) flatred]


cornellBox = Scene {backgroundColor = black,
                    ambientLight    = cornellAmbient,
                    -- lights          = [lamp, Spotlight (Point 0 0 (-cl)) nearlywhite],
                    lights          = lamps,
                    shapes          = floor ++ bWall ++ ceil ++ lWall ++ rWall ++ rBox ++ lBox,
                    camera          = camera,
                    image           = image}
  where cl = 200
        -- w  = 100
        lh = 90
        h  = 100
        d  = 100

        (camera, image) = stdCamera (Point 0 0 (-cl)) (Vector 0 0 1) (Vector 0 1 0) (Vector 1 0 0)
        -- floor = finitePlane flatred (Point (-50) 25 0) (Vector 100 0 0) (Vector 0 0 100)
        -- u    = Vector 300 0 0
        -- v    = Vector 0 1 0
        -- w    = Vector 0 0 300

        wallColor = cornellWhite

        floor = [Triangle (Point (-150) 150 100) (Point (-150) 150 400) (Point 150 150 400) wallColor,
                 Triangle (Point (-150) 150 100) (Point 150 150 400) (Point 150 150 100) wallColor]
        bWall = [Triangle (Point (-150) 150 400) (Point (-150) (-150) 400) (Point 150 150 400) wallColor,
                 Triangle (Point (-150) (-150) 400) (Point 150 (-150) 400) (Point 150 150 400) wallColor]
        ceil = [Triangle (Point (-150) (-150) 400) (Point (-150) (-150) 100) (Point 150 (-150) 400) wallColor,
                Triangle (Point (-150) (-150) 100) (Point 150 (-150) 100) (Point 150 (-150) 400) wallColor]
        lWall = [Triangle (Point (-150) 150 100) (Point (-150) (-150) 100) (Point (-150) 150 400) cornellRed,
                 Triangle (Point (-150) (-150) 100) (Point (-150) (-150) 400) (Point (-150) 150 400) cornellRed]
        rWall = [Triangle (Point 150 150 400) (Point 150 (-150) 100) (Point 150 150 100) cornellGreen,
                 Triangle (Point 150 150 400) (Point 150 (-150) 400) (Point 150 (-150) 100) cornellGreen]

        rRot = rotateY 20
        [u,v,w] = map (appTrans rRot) [Vector 90 0 0, Vector 0 (-90) 0, Vector 0 0 90]
        rBox = makeBox wallColor (Point (-10) 150 150) u v w

        lRot = rotateY (-20)
        [u',v',w'] = map (appTrans lRot) [Vector 90 0 0, Vector 0 (-180) 0, Vector 0 0 90]
        lBox = makeBox wallColor (Point (-80) 150 210) u' v' w'


        entry = Point 0 0 0
        -- camera = Camera {location   = Point 0 0 0,
        --                  screenDist = cl,
        --                  lookingAt  = entry,
        --                  upDir      = Vector 0 1 0}
        -- film = let sw = entry .+^ Vector (-w/2) (h/2) 0
        --        in (sw, sw .+^ Vector 0 (-h) 0, sw .+^ Vector w 0 0)

        -- sphere = Sphere (Point (-75) 100 250) 50 flatred
        lamps = [Spotlight (Point x (-145) (250+z)) (0.00075,0.00075,0.00075) | x <- [-30,-20..30], z <- [-30,-20..30]]
        -- lamps = [Spotlight (Point 0 (-145) 250) (0.125, 0.125, 0.125)]
