Files
loop/src/Dodge/Room/Foreground.hs
T
2023-03-16 21:56:34 +00:00

259 lines
6.4 KiB
Haskell

module Dodge.Room.Foreground (
thinHighBar,
putShape,
girder,
girderZ,
girderV,
girderV',
barPP,
highDiagonalMesh,
highMesh,
) where
import Bound
import Control.Lens
import Data.List
import Data.Maybe
import Dodge.Data.GenWorld
import Dodge.Default.ForegroundShape
import Geometry
import Picture
import Quaternion
import Shape
import ShapePicture
highMesh ::
Point2 ->
Point2 ->
-- | width
Float ->
Picture
highMesh pa pb w =
highDiagonalMesh pa pb w 20
<> highDiagonalMesh (pa +.+ w *.* normalizeV (vNormal (pb -.- pa))) pa (dist pa pb) 20
highDiagonalMesh ::
Point2 ->
Point2 ->
-- | width
Float ->
-- | vertical distance between lines
Float ->
Picture
highDiagonalMesh pa pb w d =
setDepth 100 $
pictures $
map (thickLine 2 . tflat2) (diagonalLinesRect pb pa w d (3 * pi / 4))
++ map (thickLine 2 . tflat2) (diagonalLinesRect pb pc (negate h) d (pi / 4))
where
pc = pb +.+ w *.* normalizeV (vNormal (pb -.- pa))
h = dist pa pb
diagonalLinesRect ::
Point2 ->
Point2 ->
-- | width
Float ->
-- | vertical distance between lines
Float ->
Float ->
[(Point2, Point2)]
diagonalLinesRect pa pb w d ang = zip lhsPoints $ map findDiPoint lhsPoints
where
xVec = negate w *.* vNormal (normalizeV $ pb -.- pa)
diVec = rotateV ang xVec
pax = pa +.+ xVec
pbx = pb +.+ xVec
lhsPoints = divideLineExact d (pa -.- yN) (pb +.+ yN)
findDiPoint p =
head . sortOn (dist p) $
catMaybes
[ intersectLineLine' p (p +.+ diVec) pax pbx
, intersectSegLine pa pax p (p +.+ diVec)
, intersectSegLine pb pbx p (p +.+ diVec)
]
yN = d * 0.5 *.* normalizeV (pa -.- pb)
thinHighBar :: Float -> Point2 -> Point2 -> Shape
thinHighBar = highBar 3
--thinHighBarLoop :: Float -> [Point2] -> Shape
--thinHighBarLoop h = foldMap (uncurry $ thinHighBar h) . loopPairs
--thinHighBarChain :: Float -> [Point2] -> Shape
--thinHighBarChain h = foldMap (uncurry $ thinHighBar h) . chainPairs
--thickHighBar :: Float -> Point2 -> Point2 -> Shape
--thickHighBar = highBar 5
highBar :: Float -> Float -> Point2 -> Point2 -> Shape
highBar thickness h x y =
translateSHz h $
colorSH orange $
upperPrismPoly
thickness
[x +.+ n, y +.+ n, y -.- n, x -.- n]
where
n = 0.5 * thickness *.* normalizeV (vNormal (y -.- x))
--highPipe :: Float -> Point2 -> Point2 -> Shape
--highPipe h x y = colorSH orange $ prismPoly
-- (map (addZ (h + 5)) [x +.+ n2, y +.+ n2, y -.- n2, x -.- n2])
-- (map (addZ h) [x +.+ n, y +.+ n, y -.- n, x -.- n] )
-- where
-- n2 = 1.25 *.* normalizeV (vNormal (y -.- x))
-- n = 2.5 *.* normalizeV (vNormal (y -.- x))
girderZ ::
-- | height
Float ->
-- | distance between cross bars
Float ->
-- | width
Float ->
Point2 ->
Point2 ->
Shape
girderZ h d w x y =
colorSH red $
mconcat $
[ thinHighBar h xt yt
, thinHighBar h xb yb
]
<> zipWith (thinHighBar (h - 1)) ps qs
where
n = w *.* normalizeV (vNormal $ y -.- x)
xb = x +.+ n
yb = y +.+ n
xt = x -.- n
yt = y -.- n
ps = divideLineExact d xb yb
qs = tail $ divideLineExact d xt yt
putShape :: Shape -> PSType
putShape sh =
PutForeground $
defaultForeground
& fsPos .~ m
& fsRad .~ radBounds bnds
& fsSPic .~ noPic (uncurryV translateSHxy (- m) sh)
where
bnds = shapeBounds sh
m = midBounds bnds
shapePoints :: Shape -> [Point2]
shapePoints = concatMap (map stripZ . _sfVs)
shapeBounds :: Shape -> (Float, Float, Float, Float)
shapeBounds = fromMaybe (0, 0, 0, 0) . boundPoints . shapePoints
midBounds :: (Float, Float, Float, Float) -> Point2
midBounds (n, s, e, w) = V2 ((n + s) / 2) ((e + w) / 2)
radBounds :: (Float, Float, Float, Float) -> Float
radBounds (n, s, e, w) = max (n - s) (e - w) / 2
girderV' ::
-- | height
Float ->
-- | distance between cross bars
Float ->
-- | width
Float ->
Point2 ->
Point2 ->
ForegroundShape
girderV' h d w x y =
defaultForeground
& fsPos .~ m
& fsRad .~ dist m x
& fsSPic .~ noPic sh
where
m = midPoint x y
x' = x - m
y' = y - m
sh =
thinHighBar h (x' -.- n) (x' +.+ n)
<> thinHighBar h (y' -.- n) (y' +.+ n)
<> girderV h d w x' y'
n = min (w + 10) 20 *.* vNormal (normalizeV (x' -.- y'))
girderV ::
-- | height
Float ->
-- | distance between cross bars
Float ->
-- | width
Float ->
Point2 ->
Point2 ->
Shape
girderV h d w x y =
mconcat $
[ thinHighBar h xt yt
, thinHighBar h xb yb
]
<> zipWith (thinHighBar (h - 1)) ps qs
where
n = w *.* normalizeV (vNormal $ y -.- x)
xb = x +.+ n
yb = y +.+ n
xt = x -.- n
yt = y -.- n
ps = evenDouble $ divideLineExact d xb yb
qs = head qs' : evenDouble (tail qs')
where
qs' = divideLineExact d xt yt
evenDouble (a : _ : xs) = a : a : evenDouble xs
evenDouble xs = xs
girder ::
-- | height
Float ->
-- | distance between cross bars
Float ->
-- | width
Float ->
Point2 ->
Point2 ->
Shape
girder h d w x y =
mconcat $
[ thinHighBar h xt yt
, thinHighBar h xb yb
]
<> zipWith (thinHighBar (h - 1)) ps qs
where
n = w *.* normalizeV (vNormal $ y -.- x)
xb = x +.+ n
yb = y +.+ n
xt = x -.- n
yt = y -.- n
ps = divideLineExact d xb yb
qs = divideLineExact d xt yt
barPP :: Float -> Point3 -> Point3 -> Shape
barPP w a b
| a == b = mempty
| otherwise =
prismPoly
(map ((+.+.+ a) . rotateToZ z1 . addZ 0) $ polyCirc 2 w)
(map ((+.+.+ b) . rotateToZ z1 . addZ 0) $ polyCirc 2 w)
where
z1 = b -.-.- a
--pipePP :: Float -> Point3 -> Point3 -> Shape
--pipePP w a b = prismPoly
-- (map ((+.+.+ a) . rotateToZ z1 . addZ 0) $ polyCirc 4 w)
-- (map ((+.+.+ b) . rotateToZ z1 . addZ 0) $ polyCirc 4 w)
-- where
-- z1 = b -.-.- a
--tankTopPipe :: Shape
--tankTopPipe = colorSH orange $
-- upperPrismPoly 31 (polyCirc 4 20)
-- <> prismPoly
-- (map (addZ 41) $ polyCirc 4 5)
-- (map (addZ 31) $ polyCirc 4 20)
---- <> pipePP 5 (V3 0 0 51) (V3 0 0 41)