reanimate-1.1.5.0: src/Reanimate/Povray.hs
{-# LANGUAGE OverloadedStrings #-}
{-|
[POV-Ray](http://povray.org/) (the Persistance of Vision Raytracer) is a
scriptable raytracer. All POV-Ray functions are cached and will reuse images
when scripts stay the same.
The functions come in two versions, for example 'povray' and 'povray''. The
versions without an apostrophe character yield a 'Tree'. The versions with a
final apostrophe character yield a 'FilePath' of a PNG file containing the
resulting image.
The functions differ in their use of the POV-Ray @+W@ (width), @+H@ (height)
and @+A@ or @-A@ (anti-aliasing) switches, as set out below. Resolutions are
\'width x height\'.
Example of use:
> povray args script
where @args@ is a list of other POV-Ray command-line switches (if any), and
@script@ is a POV-Ray scene description specified in the POV-Ray /scene/
/description language/.
-}
module Reanimate.Povray
( povray
, povrayQuick
, povraySlow
, povrayExtreme
, povray'
, povrayQuick'
, povraySlow'
, povrayExtreme'
) where
import Data.Hashable (Hashable (hash))
import Data.Text (Text)
import qualified Data.Text as T (concat, pack)
import qualified Data.Text.IO as T (writeFile)
import Graphics.SvgTree (Tree)
import POVRay (runPOVRay)
import Reanimate.Cache (cacheFile, encodeInt)
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Parameters (pNoExternals)
import Reanimate.Raster (mkImage)
import Reanimate.Svg.Constructors (mkText)
import System.FilePath (replaceExtension, (<.>))
import System.IO.Unsafe (unsafePerformIO)
povrayRaw :: [String] -> Text -> Tree
povrayRaw args script =
unsafePerformIO $ mkPovrayImage args script
povrayRaw' :: [String] -> Text -> FilePath
povrayRaw' args script =
unsafePerformIO $ mkPovrayImage' args script
-- | Run the POV-Ray raytracer with a default resolution of 320x180
-- and antialiasing enabled. The resulting image is scaled to fit
-- the screen exactly.
povray :: [String] -> Text -> Tree
povray args = povrayRaw (["+H180", "+W320", "+A"] ++ args)
-- | Run the POV-Ray raytracer with a default resolution of 320x180
-- and antialiasing enabled. The FilePath points to a PNG file
-- containing the resulting image.
povray' :: [String] -> Text -> FilePath
povray' args = povrayRaw' (["+H180", "+W320", "+A"] ++ args)
-- | Run the POV-Ray raytracer with a default resolution of 320x180
-- but without antialiasing. The resulting image is scaled to fit
-- the screen exactly.
povrayQuick :: [String] -> Text -> Tree
povrayQuick args = povrayRaw (["+H180", "+W320"] ++ args)
-- | Run the POV-Ray raytracer with a default resolution of 320x180
-- but without antialiasing. The FilePath points to a PNG file
-- containing the resulting image.
povrayQuick' :: [String] -> Text -> FilePath
povrayQuick' args = povrayRaw' (["+H180", "+W320"] ++ args)
-- | Run the POV-Ray raytracer with a default resolution of 2560x1440
-- and antialiasing enabled. The resulting image is scaled to fit
-- the screen exactly.
povraySlow :: [String] -> Text -> Tree
povraySlow args = povrayRaw (["+H1440", "+W2560", "+A"] ++ args)
-- | Run the POV-Ray raytracer with a default resolution of 2560x1440
-- and antialiasing enabled. The FilePath points to a PNG file
-- containing the resulting image.
povraySlow' :: [String] -> Text -> FilePath
povraySlow' args = povrayRaw' (["+H1440", "+W2560", "+A"] ++ args)
-- | Run the POV-Ray raytracer with a default resolution of 3840x2160
-- and antialiasing enabled. The resulting image is scaled to fit
-- the screen exactly.
povrayExtreme :: [String] -> Text -> Tree
povrayExtreme args = povrayRaw (["+H2160", "+W3840", "+A"] ++ args)
-- | Run the POV-Ray raytracer with a default resolution of 3840x2160
-- and antialiasing enabled. The FilePath points to a PNG file
-- containing the resulting image.
povrayExtreme' :: [String] -> Text -> FilePath
povrayExtreme' args = povrayRaw' (["+H2160", "+W3840", "+A"] ++ args)
mkPovrayImage :: [String] -> Text -> IO Tree
mkPovrayImage _ script | pNoExternals = pure $ mkText script
mkPovrayImage args script =
mkImage screenWidth screenHeight <$> mkPovrayImage' args script
mkPovrayImage' :: [String] -> Text -> IO FilePath
mkPovrayImage' _ _ | pNoExternals = pure "/povray/has/been/disabled"
mkPovrayImage' args script = cacheFile template $ \target -> do
let pov_file = replaceExtension target "pov"
otherArgs = ["-D", "+UA", "+I" ++ pov_file, "+O" ++ target]
T.writeFile pov_file script
runPOVRay $ args ++ otherArgs
where
template = encodeInt (hash key) <.> "png"
key = T.concat (script:map T.pack args)