packages feed

shapes-demo-0.1.0.0: src/Physics/Draw/Opt.hs

{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE MagicHash            #-}
{-# LANGUAGE RecordWildCards      #-}
{-# LANGUAGE TypeFamilies         #-}
{-# LANGUAGE TypeSynonymInstances #-}

module Physics.Draw.Opt where

import           GHC.Types                  (Double (D#))

import           Physics.Draw.Canonical

import           Control.Lens               (sequenceOf_, (^.))
import           Data.Array                 (elems)
import           Data.Either.Combinators

import qualified Linear.Matrix              as L
import qualified Linear.V2                  as L
import           Physics.Draw
import qualified SDL.Video.Renderer         as R

import qualified Physics.Broadphase.Aabb    as B
import           Physics.Contact            (Shape (..))
import           Physics.Contact.Circle     (Circle (..))
import           Physics.Contact.ConvexHull
import qualified Physics.Contact.SAT        as O
import qualified Physics.Contact.Types      as O
import           Physics.Linear
import           Physics.Linear.Convert
import           Physics.World              (World (..), worldObjs)
import           Physics.World.Object       (WorldObj (..))
import           Utils.Utils

instance ToCanonical V2 where
  type Canonical V2 = V2'
  toCanonical = toLV2

instance ToCanonical P2 where
  type Canonical P2 = P2'
  toCanonical = toLP2

instance ToCanonical O.ContactPoints where
  type Canonical O.ContactPoints = ContactPoints
  toCanonical =
    mapBoth f (fromSP . spMap f)
    where f = toCanonical . _neighborhoodCenter

instance ToCanonical O.Contact where
  type Canonical O.Contact = Contact
  toCanonical O.Contact{..} =
    Contact
    (toCanonical _contactPenetrator)
    (toCanonical . _neighborhoodUnitNormal $ _contactEdge)

instance ToCanonical O.Contact' where
  type Canonical O.Contact' = Contact
  toCanonical O.Contact'{..} =
    Contact
    (Left . toCanonical $ _contactPenetrator')
    (toCanonical _contactEdgeNormal')

instance ToCanonical O.Overlap where
  type Canonical O.Overlap = Overlap
  toCanonical O.Overlap{..} =
    Overlap (e0, e1) depth pen
    where e0 = toCanonical $ _neighborhoodCenter _overlapEdge
          e1 = toCanonical . _neighborhoodCenter . _neighborhoodNext $ _overlapEdge
          n = toCanonical $ _neighborhoodUnitNormal _overlapEdge
          depth = fmap (*(-_overlapDepth)) n
          pen = toCanonical $ _neighborhoodCenter _overlapPenetrator

instance ToCanonical ConvexHull where
  type Canonical ConvexHull = Polygon
  toCanonical ConvexHull{..} = toCanonical <$> elems _hullVertices

unitCircle :: [P2]
unitCircle = fmap f [0,step..(2 - step)]
  where f = P2 . unitV2 . (*pi)
        step = 0.1

instance ToCanonical Circle where
  type Canonical Circle = Polygon
  toCanonical Circle{..} = toCanonical . t <$> unitCircle
    where t (P2 a) = _circleCenter `pplusV2` (_circleRadius `smulV2` a)

instance ToCanonical B.Aabb where
  type Canonical B.Aabb = Aabb
  toCanonical (B.Aabb (B.Bounds x0 x1) (B.Bounds y0 y1)) =
    Aabb $ L.V2 (D# x0, D# x1) (D# y0, D# y1)

drawObj :: R.Renderer -> L.M33 Double -> Shape -> IO ()
drawObj r viewtrans (HullShape hull) =
  drawPolygon r (transform viewtrans . toCanonical $ hull)
drawObj r viewtrans (CircleShape circle) =
  drawPolygon r (transform viewtrans . toCanonical $ circle)

drawWorld :: R.Renderer -> L.M33 Double -> World (WorldObj ()) -> IO ()
drawWorld r vt w = sequenceOf_ traverse (fmap (drawObj r vt . _worldShape) (w ^. worldObjs))