Better latex example and a few bug fixes.

Former-commit-id: c08f4f7b31996b8a6672a91d86724ea57869d043
This commit is contained in:
David Himmelstrup 2019-12-03 23:20:11 +08:00
commit a8192aa099
8 changed files with 180 additions and 62 deletions

View file

@ -226,3 +226,18 @@ This file is auto-generated by docs/render_all.sh. DO NOT EDIT.
<br/><hr><br/> <br/><hr><br/>
## tut_glue_latex
<details>
<summary>View tut_glue_latex.hs</summary>
<pre><code class="haskell">
{!examples/tut_glue_latex.hs!}
</code></pre>
</details>
<br/>
<video width="640" height="360" autoplay loop>
<source src="https://github.com/Lemmih/reanimate/raw/master/docs/rendered/tut_glue_latex.mp4">
</video>
<br/><hr><br/>

View file

@ -4,7 +4,7 @@ ROOT=`stack path --project-root`
EXAMPLES='boundingbox colormaps goo latex_basic latex_color latex_draw EXAMPLES='boundingbox colormaps goo latex_basic latex_color latex_draw
latex_wheel raster sphere blender_default_cube latex_wheel raster sphere blender_default_cube
tut_glue_svg tut_glue_animate tut_glue_keyframe tut_glue_fourier tut_glue_svg tut_glue_animate tut_glue_keyframe tut_glue_fourier
tut_glue_physics' tut_glue_physics tut_glue_latex'
WIDTH=640 WIDTH=640
HEIGHT=$((WIDTH*9/16)) HEIGHT=$((WIDTH*9/16))

View file

@ -105,6 +105,19 @@ TODO: Show that LaTeX is a provider of SVG graphics. It has the type
'latex :: Text -> SVG'. Caching is automatic and it plays well with 'latex :: Text -> SVG'. Caching is automatic and it plays well with
other SVG functions (partialSvg, center, etc). other SVG functions (partialSvg, center, etc).
<details>
<summary>Toggle source code.</summary>
<pre><code class="haskell">
{!examples/tut_glue_latex.hs!}
</code></pre>
</details>
<br/>
<video width="640" height="360" autoplay loop>
<source src="../rendered/tut_glue_latex.mp4">
<source src="https://github.com/Lemmih/reanimate/raw/master/docs/rendered/tut_glue_latex.mp4">
</video>
## Pillar III: potrace ## Pillar III: potrace
## Pillar IV: Povray ## Pillar IV: Povray

92
examples/tut_glue_latex.hs Executable file
View file

@ -0,0 +1,92 @@
#!/usr/bin/env stack
-- stack runghc --package reanimate
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import Codec.Picture
import Codec.Picture.Types
import Control.Lens ((^.))
import Control.Monad
import Data.Monoid
import Graphics.SvgTree
import Linear.V2
import Reanimate
import Reanimate.Animation
import Reanimate.Effect
import Reanimate.Scene
import System.Random
import System.Random.Shuffle
main :: IO ()
main = reanimate $ parA bg $ sceneAnimation $ do
-- Draw equation
play $ drawAnimation strokedSvg
sprites <- forM glyphs $ \(fn, _, elt) ->
newSpriteA $ animate $ const $ fn elt
-- Yoink each glyph
forM_ (reverse sprites) $ \sprite -> do
spriteE sprite (overBeginning 1 $ aroundCenterE $ highlightE)
wait 0.5
-- Flash glyphs randomly with color
forM_ (shuffleList (sprites++sprites)) $ \sprite -> do
spriteE sprite (overBeginning 0.5 $ aroundCenterE $ flashE)
wait 0.1
wait 0.5
mapM_ destroySprite sprites
-- Undraw equations
play $ drawAnimation' (Just 0xdeadbeef) 1 0.1 strokedSvg
# reverseA
where
glyphs = svgGlyphs svg
strokedSvg =
withStrokeWidth (defaultStrokeWidth*0.5) $
withStrokeColor "black" svg
svg = lowerTransformations $ simplify $ scale 2 $ center $
latexAlign "\\sum_{k=1}^\\infty {1 \\over k^2} = {\\pi^2 \\over 6}"
bg = animate $ const $ mkBackgroundPixel (PixelRGBA8 252 252 252 0xFF)
shuffleList lst = shuffle' lst (length lst) (mkStdGen 0xdeadbeef)
highlightE :: Effect
highlightE d t =
scale (1 + bellS 2 (t/d)*0.5) . rotate (wiggleS (t/d) * 20)
flashE :: Effect
flashE d t =
withStrokeColor "black" .
withStrokeWidth (defaultStrokeWidth*0.5*bellS 2 (t/d)) .
withFillColorPixel (promotePixel $ turbo (t/d))
-- s-curve, sin, s-curve
wiggleS :: Signal
wiggleS t
| t < 0.25 = curveS 2 (t*4)
| t < 0.75 = sin ((t-0.25)*2*pi+pi/2)
| otherwise = curveS 2 ((t-0.75)*4)-1
--
drawAnimation :: SVG -> Animation
drawAnimation = drawAnimation' Nothing 0.5 0.3
drawAnimation' :: Maybe Int -> Double -> Double -> SVG -> Animation
drawAnimation' mbSeed fillDur step svg = sceneAnimation $ do
forM_ (zip [0..] $ shuf $ svgGlyphs svg) $ \(n, (fn, attr, tree)) -> do
let sWidth =
case toUserUnit defaultDPI <$> getLast (attr ^. strokeWidth) of
Just (Num d) -> d
_ -> defaultStrokeWidth
fork $ do
wait (n*step)
play $ mapA fn $ (animate (\t -> withFillOpacity 0 $ partialSvg t tree)
# applyE (overEnding fillDur $ fadeLineOutE sWidth))
fork $ do
wait (n*step+(1-fillDur))
newSprite $ do
return $ \_real_t d t ->
withStrokeWidth 0 $ fn $ withFillOpacity (min 1 $ t/fillDur) tree
where
shuf lst =
case mbSeed of
Nothing -> lst
Just seed -> shuffle' lst (length lst) (mkStdGen seed)
len = fromIntegral $ length $ svgGlyphs svg

View file

@ -5,23 +5,22 @@
module Main (main) where module Main (main) where
import Chiphunk.Low import Chiphunk.Low
import Control.Monad import Codec.Picture (PixelRGBA8 (..))
import Control.Monad (forM_)
import Graphics.SvgTree (Tree) import Graphics.SvgTree (Tree)
import Linear.V2 import Linear.V2 (V2 (..))
import Reanimate.Chiphunk
import Reanimate import Reanimate
import Reanimate.Chiphunk
import Reanimate.PolyShape import Reanimate.PolyShape
import System.IO.Unsafe import Reanimate.Signal
import Codec.Picture import System.IO.Unsafe (unsafePerformIO)
test :: Animation shatter :: Animation
test = unsafePerformIO $ do shatter = unsafePerformIO $ do
bodyStore <- newBodyStore bodyStore <- newBodyStore
let gravity = Vect 0 (-1) let gravity = Vect 0 (-1) -- Gravity points down (negative 1 y/s^2)
-- Create an empty space.
space <- spaceNew space <- spaceNew
-- spaceCollisionSlop space $= (screenWidth/2560)
spaceGravity space $= gravity spaceGravity space $= gravity
static <- get $ spaceStaticBody space static <- get $ spaceStaticBody space
@ -30,13 +29,10 @@ test = unsafePerformIO $ do
(Vect (screenWidth/2) (-screenHeight/2)) 0 (Vect (screenWidth/2) (-screenHeight/2)) 0
shapeFriction ground $= 1 shapeFriction ground $= 1
spaceAddShape space ground spaceAddShape space ground
shapeElasticity ground $= 1
let toVect (V2 x y) = Vect x y let toVect (V2 x y) = Vect x y
vectGroup = plDecompose $ svgToPolyShapes $ center $ scale 4 $
let svg = center $ scale 4 $ latex "$F=ma$" latex "$F=ma$"
poly = svgToPolyShapes svg
vectGroup = plDecompose poly
forM_ vectGroup $ \polygon -> do forM_ vectGroup $ \polygon -> do
bd <- polygonsToBody space [map toVect polygon] bd <- polygonsToBody space [map toVect polygon]
@ -44,29 +40,21 @@ test = unsafePerformIO $ do
addToBodyStore bodyStore bd $ addToBodyStore bodyStore bd $
renderPolyShape $ plFromPolygon polygon renderPolyShape $ plFromPolygon polygon
ani <- simulate space bodyStore 60 10 10 ani <- simulate space bodyStore fps stepsPerFrame shatterT
spaceFreeRecursive space spaceFreeRecursive space
return ani return $ mapA pp ani
where
shatterT = 10
chunkPolyshapes :: Tree -> Tree fps = 60
chunkPolyshapes t = stepsPerFrame = 10
mkGroup pp = withStrokeWidth 0.01 . withStrokeColor "black" . withFillColor "black"
[
withStrokeWidth 0.01 $
withStrokeColor "black" $
-- withFillOpacity 0 $
withFillColor "black" $
mkGroup $ map renderPolyShape $
svgToPolyShapes t
]
reorient :: Tree -> Tree
reorient = id -- scale 6 . translate 0 (-0.9)
main :: IO () main :: IO ()
main = reanimate $ bg `parA` mapA reorient (mapA chunkPolyshapes test) main = reanimate $ parA bg $ sceneAnimation $ do
play $ shatter
play $ shatter
# reverseA
# setDuration 5
# signalA (powerS 2)
where where
bg = animate $ const $ mkBackgroundPixel (PixelRGBA8 252 252 252 0xFF) bg = animate $ const $ mkBackgroundPixel (PixelRGBA8 252 252 252 0xFF)

View file

@ -60,3 +60,6 @@ scaleE target d t = scale (1 + (target-1) * t/d)
translateE :: Double -> Double -> Effect translateE :: Double -> Double -> Effect
translateE x y d t = translate (x * t/d) (y * t/d) translateE x y d t = translate (x * t/d) (y * t/d)
aroundCenterE :: Effect -> Effect
aroundCenterE e d t = aroundCenter (e d t)

View file

@ -66,7 +66,7 @@ sceneAnimation action =
| (startT, a, z) <- tl | (startT, a, z) <- tl
] ]
genFns <- sequence gens genFns <- sequence gens
return $ anis `parA` mkAnimation dur (\t -> return $ anis `parDropA` mkAnimation dur (\t ->
mkGroup $ mkGroup $
map fst $ map fst $
sortBy (comparing snd) sortBy (comparing snd)

View file

@ -28,10 +28,18 @@ rotateAround a (V2 x y) = withTransformations [Rotate a (Just (x,y))]
rotateAroundCenter :: Double -> Tree -> Tree rotateAroundCenter :: Double -> Tree -> Tree
rotateAroundCenter a t = rotateAroundCenter a t =
rotateAround a (V2 (x+w/h) (y+h/2)) t rotateAround a (V2 (x+w/2) (y+h/2)) t
where where
(x,y,w,h) = boundingBox t (x,y,w,h) = boundingBox t
aroundCenter :: (Tree -> Tree) -> Tree -> Tree
aroundCenter fn t =
translate (-offsetX) (-offsetY) $ fn $ translate offsetX offsetY t
where
offsetX = -x-w/2
offsetY = -y-h/2
(x,y,w,h) = boundingBox t
scale :: Double -> Tree -> Tree scale :: Double -> Tree -> Tree
scale a = withTransformations [Scale a Nothing] scale a = withTransformations [Scale a Nothing]
@ -207,4 +215,3 @@ mkText str =
& fontSize .~ pure (Num 2) & fontSize .~ pure (Num 2)
where where
span_ = defaultSvg & spanContent .~ [SpanText str] span_ = defaultSvg & spanContent .~ [SpanText str]