"Gloss / OpenGL Stack Overflow" error after drawPicture. "" when using animation based on recursion

Just to chat with the Haskell Gloss library, I wrote:

import Graphics.Gloss

data World = World { worldBugs :: [Picture] }

bug :: Point -> Float -> Picture
bug (x, y) s =
    let head = Translate x (y - s) $ Circle (s * 0.8)
        body = Translate x (y + s) $ Circle (s * 1.2)
    in  pictures [head, body]

main = play (InWindow "Animation Test" (400, 400) (100, 100)) white 10
    (World . map (\(n,b) -> Translate (n * 20) (n * 20) $ b) $ zip [0..] $ replicate 100 $ bug (0,0) 100)
    (\world -> pictures $ worldBugs world)
    (\event world -> world)
    (\time (World bs) -> World $ map (Rotate (time * 10)) bs)

      

which displays some "bugs" (the two circles forming the head and torso) that rotate over time. The problem is that after a couple of seconds it will fire with:

Gloss / OpenGL Qaru "after drawPicture."
  This program uses the Gloss vector graphics library, which tried to
  draw a picture using more nested transforms (Translate/Rotate/Scale)
  than your OpenGL implementation supports. The OpenGL spec requires
  all implementations to have a transform stack depth of at least 32,
  and Gloss tries not to push the stack when it doesn't have to, but
  that still wasn't enough.

  You should complain to your harware vendor that they don't provide
  a better way to handle this situation at the OpenGL API level.

  To make this program work you'll need to reduce the number of nested
  transforms used when defining the Picture given to Gloss. Sorry.

      

which, if I understand it correctly, basically means that in the end too many conversions are pushed onto the stack and it overflows. He notes that it might be a hardware limitation (I'm on a Surface 2 Pro), so I'm SOL? It doesn't do this when used animate

, but probably due to the fact that it doesn't pass state to every tick.

If I am going to make a game, I will need to use play

to pass the state to the next tick; I cannot found all the time. Is there a way to get around this? The startup error gives almost nothing.

+3


source to share


1 answer


The problem is that on every tick, it additionally splits the image, wrapping it in another transform (which ultimately causes an overflow). To solve this problem, I simply stored each of the values ​​in an object Entity

and then applied the transforms once per fromEntity

.



    {- LANGUAGE threaded -}
module GlossTest where

import Graphics.Gloss

data Entity = Entity { entRot :: Float, entTrans :: Point, entScale :: Point, entPict :: Picture }

data World = World { worldBugs :: [Entity] }

entTranslate :: Float -> Float -> Entity -> Entity
entTranslate x y (Entity r t s p) = Entity r (x,y) s p

entRotate :: Float -> Entity -> Entity
entRotate x (Entity r t s p) = Entity x t s p

entRotateBy :: Float -> Entity -> Entity
entRotateBy n (Entity r t s p) = Entity (r + n) t s p

entMove :: Float -> Float -> Entity -> Entity
entMove x y (Entity r (tX,tY) s p) = Entity r (tX + x, tY + y) s p

toEntity :: Picture -> Entity
toEntity = Entity 0 (0,0) 1

fromEntity :: Entity -> Picture
fromEntity (Entity r (tX,tY) (sX,sY) p) = Rotate r . Translate tX tY $ Scale sX sY p

bug :: Point -> Float -> Entity
bug (x, y) s =
    let head = Rotate 0 $ Translate x (y - s) $ Circle (s * 0.8)
        body = Rotate 0 $ Translate x (y + s) $ Circle (s * 1.2)
    in  toEntity $ pictures [head, body]

main = play
    (InWindow "Animation Test" (400, 400) (100, 100)) white 1
    (World . map (\(n,b) -> entTranslate (n * 1) (n * 1) $ b) $ zip [0..] $ replicate 10 $ bug (0,0) 100)
    (\world -> pictures . map fromEntity $ worldBugs world)
    (\event world -> world)
    (\time (World bs) -> World $ map (\(n,b) -> entRotateBy (n * time) $ entMove time time b) $ zip [0..] bs)

      

+1


source







All Articles