packages feed

hogre-examples (empty) → 0.0.1

raw patch · 27 files changed

+622/−0 lines, 27 filesdep +SDLdep +basedep +haskell98setup-changedbinary-added

Dependencies added: SDL, base, haskell98, hogre, stm

Files

+ LICENSE view
@@ -0,0 +1,23 @@+Copyright (c) 2009 Antti Salonen++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.+
+ Media/Example.material view
@@ -0,0 +1,122 @@++material Examples/CloudyNoonSkyBox+{+	technique+	{+		pass+		{+			lighting off+			depth_write off++			texture_unit+			{+				cubic_texture cloudy_noon.jpg separateUV+				tex_address_mode clamp+			}+		}+	}+}++material Examples/StormySkyBox+{+	technique+	{+		pass+		{+			lighting off+			depth_write off++			texture_unit+			{+				cubic_texture stormy.jpg separateUV+				tex_address_mode clamp+			}+		}+	}+}++material Examples/EveningSkyBox+{+	technique+	{+		pass+		{+			lighting off+			depth_write off++			texture_unit+			{+				cubic_texture evening.jpg separateUV+				tex_address_mode clamp+			}+		}+	}+}++material Examples/CloudySky+{+	technique+	{+		pass+		{+			lighting off+			depth_write off++			texture_unit+			{+				texture clouds.jpg+				scroll_anim 0.15 0+			}+		}+	}+}++material Examples/Robot+{+        // Hardware skinning techniique+        technique+        {+                pass+                {+/*+                        vertex_program_ref Ogre/HardwareSkinningOneWeight+                        {+                                param_named_auto worldMatrix3x4Array world_matrix_array_3x4+                                param_named_auto viewProjectionMatrix viewproj_matrix+                                param_named_auto lightPos[0] light_position 0+                                param_named_auto lightPos[1] light_position 1+                                param_named_auto lightDiffuseColour[0] light_diffuse_colour 0+                                param_named_auto lightDiffuseColour[1] light_diffuse_colour 1+                                param_named_auto ambient ambient_light_colour++                        }+                        // alternate shadow caster program+                        shadow_caster_vertex_program_ref Ogre/HardwareSkinningOneWeightShadowCaster+                        {+                                param_named_auto worldMatrix3x4Array world_matrix_array_3x4+                                param_named_auto viewProjectionMatrix viewproj_matrix+                                param_named_auto ambient ambient_light_colour++                        }+*/+                        texture_unit+                        {+                                texture r2skin.jpg+                        }+                }+        }++        // Software blending technique+        technique+        {+                pass+                {++                        texture_unit+                        {+                                texture r2skin.jpg+                        }+                }+        }+}+
+ Media/HornetUV_Cylinder.tga view

binary file changed (absent → 288662 bytes)

+ Media/IMG_0436.JPG view

binary file changed (absent → 460342 bytes)

+ Media/TailWings.JPG view

binary file changed (absent → 21859 bytes)

+ Media/WingFlap.jpg view

binary file changed (absent → 9396 bytes)

+ Media/WingFlapBump.jpg view

binary file changed (absent → 11059 bytes)

+ Media/Wings.jpg view

binary file changed (absent → 29852 bytes)

+ Media/WingsBump.jpg view

binary file changed (absent → 17302 bytes)

+ Media/blackhawk.material view
@@ -0,0 +1,37 @@+material Windows+{+	receive_shadows on+	technique+	{+		pass+		{+			ambient 0.500000 0.500000 0.500000 0.168000+			diffuse 0.640000 0.640000 0.711253 0.168000+			specular 0.490442 0.490442 0.490442 0.168000 4.000000+			emissive 0.000000 0.000000 0.000000 0.168000+			scene_blend alpha_blend+			depth_write off+		}+	}+}+material HelicopterBody+{+	receive_shadows on+	technique+	{+		pass+		{+			// ambient 0.300000 0.300000 0.000000 1.000000+			// diffuse 0.786168 0.795673 0.786204 1.000000+			// specular 0.630000 0.630000 0.630000 1.000000 12.500000+			// emissive 0.000000 0.000000 0.000000 1.000000+			texture_unit+			{+				texture lava.tga+				// tex_address_mode wrap+				// filtering trilinear+				// colour_op alpha_blend+			}+		}+	}+}
+ Media/clouds.jpg view

binary file changed (absent → 5166 bytes)

+ Media/lagoon.tga view

binary file changed (absent → 8236 bytes)

+ Media/lava.tga view

binary file changed (absent → 630239 bytes)

+ Media/mix.tga view

binary file changed (absent → 763090 bytes)

+ Media/terrain.cfg view
@@ -0,0 +1,71 @@+# The main world texture (if you wish the terrain manager to create a material for you)+WorldTexture=terrain_texture.jpg++# The detail texture (if you wish the terrain manager to create a material for you)+DetailTexture=terrain_detail.jpg++#number of times the detail texture will tile in a terrain tile+DetailTile=3++# Heightmap source+PageSource=Heightmap++# Heightmap-source specific settings+Heightmap.image=terrain.png++# If you use RAW, fill in the below too+# RAW-specific setting - size (horizontal/vertical)+#Heightmap.raw.size=513+# RAW-specific setting - bytes per pixel (1 = 8bit, 2=16bit)+#Heightmap.raw.bpp=2++# How large is a page of tiles (in vertices)? Must be (2^n)+1+PageSize=513++# How large is each tile? Must be (2^n)+1 and be smaller than PageSize+TileSize=65++# The maximum error allowed when determining which LOD to use+MaxPixelError=3++# The size of a terrain page, in world units+PageWorldX=1500+PageWorldZ=1500+# Maximum height of the terrain +MaxHeight=100++# Upper LOD limit+MaxMipMapLevel=5++#VertexNormals=yes+#VertexColors=yes+#UseTriStrips=yes++# Use vertex program to morph LODs, if available+VertexProgramMorph=yes++# The proportional distance range at which the LOD morph starts to take effect+# This is as a proportion of the distance between the current LODs effective range,+# and the effective range of the next lower LOD+LODMorphStart=0.2++# This following section is for if you want to provide your own terrain shading routine+# Note that since you define your textures within the material this makes the +# WorldTexture and DetailTexture settings redundant++# The name of the vertex program parameter you wish to bind the morph LOD factor to+# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely+# to the same position as the next lower LOD+# USE THIS IF YOU USE HIGH-LEVEL VERTEX PROGRAMS WITH LOD MORPHING+#MorphLODFactorParamName=morphFactor++# The index of the vertex program parameter you wish to bind the morph LOD factor to+# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely+# to the same position as the next lower LOD+# USE THIS IF YOU USE ASSEMBLER VERTEX PROGRAMS WITH LOD MORPHING+#MorphLODFactorParamIndex=4++# The name of the material you will define to shade the terrain+#CustomMaterialName=TestTerrainMaterial++
+ Media/terrain.png view

binary file changed (absent → 103088 bytes)

+ Media/terrain_detail.jpg view

binary file changed (absent → 14832 bytes)

+ Media/terrain_texture.jpg view

binary file changed (absent → 72019 bytes)

+ README view
@@ -0,0 +1,1 @@+Models available at http://www.blendermodels.org/
+ Setup.hs view
@@ -0,0 +1,3 @@+import Distribution.Simple+main = defaultMain+
+ hogre-examples.cabal view
@@ -0,0 +1,66 @@+Name:           hogre-examples+Version:        0.0.1+Cabal-Version:  >= 1.6+License:        OtherLicense+License-File:   LICENSE+Author:         Antti Salonen<ajsalonen at gmail dot com>+Maintainer:     Antti Salonen<ajsalonen at gmail dot com>+Copyright:      Antti Salonen 2009+Stability:      Unstable+Category:       Graphics+Synopsis:       Examples for using Hogre.+Description:    Examples for using Hogre, Haskell bindings to OGRE+                (Object-Oriented Graphics Rendering Engine)+                (<http://www.ogre3d.org/>).+                example_01 creates a simple scene with a moving entity.+                example_02 demonstrates use of SDL for input and window+                creation.+                example_03 demonstrates ray scene queries and loading+                a world configuration from a file.+Build-type:     Simple+extra-source-files: src/Common.hs,+                resources.cfg, plugins.cfg, README,+                Media/blackhawk.material,+                Media/clouds.jpg,+                Media/Example.material,+                Media/HornetUV_Cylinder.tga,+                Media/IMG_0436.JPG,+                Media/lagoon.tga,+                Media/lava.tga,+                Media/mix.tga,+                Media/TailWings.JPG,+                Media/terrain.cfg,+                Media/terrain_detail.jpg,+                Media/terrain.png,+                Media/terrain_texture.jpg,+                Media/WingFlapBump.jpg,+                Media/WingFlap.jpg,+                Media/WingsBump.jpg,+                Media/Wings.jpg++source-repository head+  type:      git+  location:  http://github.com/anttisalonen/hogre-examples++Executable example_01+  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.0.1+  Main-is:         Example_01.hs+  Hs-Source-Dirs:  src+  Ghc-options:     -Wall+  extra-libraries: CEGUIOgreRenderer, OgreMain, CEGUIBase++Executable example_02+  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.0.1, SDL>=0.4.0+  Main-is:         Example_02.hs+  Hs-Source-Dirs:  src+  Ghc-options:     -Wall+  extra-libraries: CEGUIOgreRenderer, OgreMain, CEGUIBase++Executable example_03+  Build-Depends:   base >= 3 && < 5, haskell98, hogre>=0.0.1, SDL>=0.4.0,+                   stm>=2.1.1.2+  Main-is:         Example_03.hs+  Hs-Source-Dirs:  src+  Ghc-options:     -Wall+  extra-libraries: CEGUIOgreRenderer, OgreMain, CEGUIBase+
+ plugins.cfg view
@@ -0,0 +1,12 @@+# Defines plugins to load++# Define plugin folder+PluginFolder=/usr/lib/OGRE++# Define D3D rendering implementation plugin+Plugin=RenderSystem_GL.so+Plugin=Plugin_ParticleFX.so+Plugin=Plugin_BSPSceneManager.so+Plugin=Plugin_OctreeSceneManager.so+Plugin=Plugin_CgProgramManager.so+
+ resources.cfg view
@@ -0,0 +1,3 @@+# Resource locations to be added to the default path+[General]+FileSystem=./Media
+ src/Common.hs view
@@ -0,0 +1,115 @@+module Common(runWithSDL, FrameCallback(..), EventCallback(..))+where++import System.IO+import Control.Concurrent+import Control.Concurrent.STM++import qualified Graphics.UI.SDL as SDL++import Graphics.Ogre.Ogre++data FrameCallback a = FrameCallback { framecallback :: (a -> IO a) }+data EventCallback a = EventCallback { eventcallback :: (a -> [SDL.Event] -> IO a) }++pollAllSDLEvents :: IO [SDL.Event]+pollAllSDLEvents = go []+    where go l = do+                   e <- SDL.pollEvent+                   if e == SDL.NoEvent +                     then return l +                     else do+                       es <- pollAllSDLEvents+                       return (e:es)++type Action = (Bool,        -- right mouse button pressed+    (Float, Float),         -- rotation (yaw, pitch)+    (Float, Float, Float),  -- translation (x, y, z)+    Bool)                   -- quit flag++eventToAction :: Action -> SDL.Event -> Action+eventToAction (bt, ro, t, _) SDL.Quit = (bt, ro, t, True)+eventToAction (bt, ro, t, _) (SDL.KeyDown (SDL.Keysym SDL.SDLK_ESCAPE _ _)) = (bt, ro, t, True)+eventToAction (bt, ro, t, _) (SDL.KeyDown (SDL.Keysym SDL.SDLK_q      _ _)) = (bt, ro, t, True)+eventToAction (bt, ro, t@(x_, y_, z_), q) (SDL.KeyDown (SDL.Keysym k _ _)) = case k of+  SDL.SDLK_UP       -> (bt, ro, (x_, y_, z_ - 1.0), q)+  SDL.SDLK_DOWN     -> (bt, ro, (x_, y_, z_ + 1.0), q)+  SDL.SDLK_RIGHT    -> (bt, ro, (x_ + 1.0, y_, z_), q)+  SDL.SDLK_LEFT     -> (bt, ro, (x_ - 1.0, y_, z_), q)+  SDL.SDLK_PAGEDOWN -> (bt, ro, (x_, y_ - 1.0, z_), q)+  SDL.SDLK_PAGEUP   -> (bt, ro, (x_, y_ + 1.0, z_), q)+  _ -> (bt, ro, t, q)+eventToAction (bt, ro, t@(x_, y_, z_), q) (SDL.KeyUp   (SDL.Keysym k _ _)) = case k of+  SDL.SDLK_UP        -> (bt, ro, (x_, y_, z_ + 1.0), q)+  SDL.SDLK_DOWN      -> (bt, ro, (x_, y_, z_ - 1.0), q)+  SDL.SDLK_RIGHT     -> (bt, ro, (x_ - 1.0, y_, z_), q)+  SDL.SDLK_LEFT      -> (bt, ro, (x_ + 1.0, y_, z_), q)+  SDL.SDLK_PAGEDOWN  -> (bt, ro, (x_, y_ + 1.0, z_), q)+  SDL.SDLK_PAGEUP    -> (bt, ro, (x_, y_ - 1.0, z_), q)+  _ -> (bt, ro, t, q)+eventToAction (False, ro, t, q)        (SDL.MouseMotion _ _ _ _) = (False, ro, t, q)+eventToAction (True, (ya, pit), t, q) (SDL.MouseMotion _ _ abs_x abs_y) = (True, (ya - (0.005 * fromIntegral abs_x), pit - (0.005 * fromIntegral abs_y)), t, q)+eventToAction (_,  ro, t, q) (SDL.MouseButtonUp   _ _ SDL.ButtonRight) = (False, ro, t, q)+eventToAction (_,  ro, t, q) (SDL.MouseButtonDown _ _ SDL.ButtonRight) = (True, ro, t, q)+eventToAction (bt, ro, t, q) _ = (bt, ro, t, q)++resetRotation :: Action -> Action+resetRotation (bt, _, t, q) = (bt, (0, 0), t, q)++doAction :: (Float, Float) -> (Float, Float, Float) -> IO ()+doAction (ya, pit) (x_, y_, z_) = do+  rotateCamera (YPR ya 0 0)  World+  rotateCamera (YPR 0 pit 0) Local+  translateCamera (Vector3 x_ y_ z_)++shutdown :: IO ()+shutdown = do+    putStrLn "Shutting down..."+    cleanupOgre++runWithSDL :: IO () -> (a, EventCallback a, FrameCallback a) -> IO ()+runWithSDL initGame action = SDL.withInit [SDL.InitEverything] $ runThreadedNonblocking initGame action 20 20 >> return ()++nullAction :: Action+nullAction = (False, (0, 0), (0, 0, 0), False)++runThreadedNonblocking :: IO () -> (a, EventCallback a, FrameCallback a) -> Int -> Int -> IO ()+runThreadedNonblocking initGame (ival, ecb, fcb) renderinterval handleinterval = do+   initGame+   let ri = renderinterval * 1000+   let si = handleinterval * 1000+   box <- atomically $ newTMVar ival+   rtid <- forkIO (renderLoop box fcb ri)+   inputLoop si box ecb [rtid] nullAction++renderLoop :: TMVar a -> FrameCallback a -> Int -> IO ()+renderLoop box action ri = do+   renderOgre+   val <- atomically $ takeTMVar box+   nval <- (framecallback action) val+   atomically $ putTMVar box nval+   threadDelay ri+   renderLoop box action ri++fullCleanup :: [ThreadId] -> IO () -> IO ()+fullCleanup tids cf = mapM_ killThread tids >> cf++inputLoop :: Int -> TMVar a -> EventCallback a -> [ThreadId] -> Action -> IO ()+inputLoop si box action tids ac = do+  i <- input ac box action+  case i of+    Nothing  -> fullCleanup tids shutdown+    Just nac -> threadDelay si >> inputLoop si box action tids (resetRotation nac)++input :: Action -> TMVar a -> EventCallback a -> IO (Maybe Action)+input ac box action = do+  events <- pollAllSDLEvents+  -- when (not (null events)) (print events >> (getCameraPosition >>= print))+  let nac@(_, ro, t, q) = foldl eventToAction ac events+  if q then return Nothing else do +               val <- atomically $ takeTMVar box+               nval <- (eventcallback action) val events+               atomically $ putTMVar box nval+               doAction ro t+               return (Just nac)+
+ src/Example_01.hs view
@@ -0,0 +1,48 @@+module Main+where++import Graphics.Ogre.Ogre+import Control.Exception+import Control.Concurrent (threadDelay)++renderLoop :: Float -> IO ()+renderLoop f = do+    renderOgre+    setEntityPosition "obj1" (ogreloc f)+    setLightPosition "light2" (Vector3 30 20 50)+    threadDelay 10000+    renderLoop (f + 0.008)++ogreloc :: Float -> Vector3+ogreloc f = Vector3 (30 + 20 * sin f) (8 + 2 * sin (0.2 * f)) (50 + 20 * cos f)++plloc :: Float -> Vector3+plloc f = Vector3 (30 + 40 * sin (4.0 * f)) 20 (50 + 40 * cos (4.0 * f))++main :: IO ()+main = do+    let set = OgreSettings "resources.cfg" True "Hogre Example 01" (Color 0.2 0.2 0.2) StencilAdditive [Generic]+    let cam = Camera (Vector3 30.0 8.0 50.0) 0 (Vector3 135.0 40.0 50.0)+    let yelcol = Color 1.0 1.0 0.0+    let dircol = Color 0.25 0.25 0+    let whitecol = Color 1 1 1+    let spotrange = (0.0, degToRad 80.0)+    let l1 = Light "light1" yelcol yelcol (SpotLight (Vector3  30 50.0 50) (Vector3  0.0  (-1.0)   0.0) spotrange)+    let l2 = Light "light2" whitecol whitecol (PointLight (plloc 0))+    let l3 = Light "light3" dircol dircol (DirectionalLight (Vector3 0 0 1))+    let plane = Plane unitY 0.0 70.0 100.0 20 20 5.0 5.0 unitZ "DarkBlue"+    let pl = Entity "ground" (Vector3 35.0 0.0 50.0) plane False (Vector3 1.0 1.0 1.0)+    let lig = [l1, l2, l3]+    let ents = [pl]+    let sce = OgreScene cam ents lig+    initOgre set+    addScene sce+    addEntity (Entity "obj1" (ogreloc 0) (StdMesh "robot.mesh" (YPR 0 0 0)) True (Vector3 0.20 0.20 0.20))+    handle shutdown (renderLoop 0)++shutdown :: (Show a) => a -> IO ()+shutdown e = do+    print e+    putStrLn "Shutting down..."+    cleanupOgre+
+ src/Example_02.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, FunctionalDependencies #-}+module Main+where++import System.IO++import qualified Graphics.UI.SDL as SDL++import Graphics.Ogre.Ogre+import Common++initGame :: IO ()+initGame = do+    let set = OgreSettings "resources.cfg" False "Hogre Example 02" (Color 0.2 0.2 0.2) StencilModulative [Generic]+    let cam = Camera (Vector3 100.0 10.0 40) 0 (Vector3 101 10 40)+    let lightdiffuse = Color 0.9 0.9 0.9+    let lightspecular = Color 0.8 0.8 0.8+    let spotrange = (0.0, degToRad 80.0)+    let l1 = Light "light1" lightdiffuse lightspecular (SpotLight (Vector3  0 15.0 0) (Vector3   1.0  (-1.0)   1.0) spotrange)+    let l2 = Light "light2" lightdiffuse lightspecular (SpotLight (Vector3 70 15.0 0) (Vector3 (-1.0) (-1.0)   1.0) spotrange)+    let l3 = Light "light3" lightdiffuse lightspecular (SpotLight (Vector3  0 15.0 100) (Vector3   1.0  (-1.0) (-1.0)) spotrange)+    let l4 = Light "light4" lightdiffuse lightspecular (SpotLight (Vector3 70 15.0 100) (Vector3 (-1.0) (-1.0) (-1.0)) spotrange)+    let plane = Plane unitY 0.0 70.0 100.0 20 20 5.0 5.0 unitZ "HelicopterBody"+    let pl = Entity "ground" (Vector3 35.0 0.0 50.0) plane False (Vector3 1.0 1.0 1.0)+    let robotmesh = "robot.mesh"+    let robotscale = Vector3 0.36 0.24 0.3+    let robot1 = Entity "robot1" (Vector3 35.0 3.0 4.2) (StdMesh robotmesh (YPR  halfPI  0.0 0.0)) True robotscale+    let robot2 = Entity "robot2" (Vector3 35.0 3.0 84.5)  (StdMesh robotmesh (YPR  halfPI  0.0 0.0)) True robotscale+    let lig = [l1, l2, l3, l4]+    let ents = [pl, robot1, robot2]+    let sce = OgreScene cam ents lig+    let (wid, hei) = (1024, 768)+    _ <- SDL.setVideoMode wid hei 16 [SDL.OpenGL, SDL.HWAccel]+    SDL.wasInit [SDL.InitEverything] >>= print+    initOgre set+    addScene sce+    addEntity (Entity "obj1" (Vector3 5.0 20.0 10.0) (StdMesh robotmesh (YPR 0.0 0.0 0.0)) True (Vector3 0.2 0.2 0.2))++main :: IO ()+main = runWithSDL initGame ((), EventCallback (\_ _ -> return ()), FrameCallback (\_ -> return ()))+
+ src/Example_03.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, FunctionalDependencies #-}+module Main+where++import Data.Maybe+import System.IO+import Control.Monad (when)++import qualified Graphics.UI.SDL as SDL++import Graphics.Ogre.Ogre+import Common++robotTemplate :: String -> Vector3 -> Entity+robotTemplate swname pos = Entity swname pos (StdMesh "robot.mesh" (YPR  halfPI  0.0 0.0)) True (Vector3 0.2 0.2 0.2)++initGame :: IO ()+initGame = do+    let set = OgreSettings "resources.cfg" False "Hogre Example 03" (Color 0.9 0.9 0.9) StencilModulative [ExteriorClose]+    let cam = Camera (Vector3 242.0 120.0 580) 0 (Vector3 241 120 580)+    let (wid, hei) = (1024, 768)+    let sce = OgreScene cam [] []+    _ <- SDL.setVideoMode wid hei 16 [SDL.OpenGL, SDL.HWAccel]+    SDL.wasInit [SDL.InitEverything] >>= print+    initOgre set+    addScene sce+    setSkyDome (Just ("Examples/CloudySky", 5))+    setWorldGeometry "terrain.cfg"++main :: IO ()+main = runWithSDL initGame (0, EventCallback query, FrameCallback (\v -> return v))++getLMB :: IO (Maybe (Int, Int))+getLMB = do+  (xpos, ypos, btns) <- SDL.getMouseState+  return $ case SDL.ButtonLeft `elem` btns of+    True  -> Just (xpos, ypos)+    False -> Nothing++getLMBPressed :: [SDL.Event] -> Maybe (Int, Int)+getLMBPressed []     = Nothing+getLMBPressed (e:es) = case e of+                         (SDL.MouseButtonDown xp yp SDL.ButtonLeft) -> Just ((fromIntegral xp), (fromIntegral yp))+                         _                                          -> getLMBPressed es++query :: Int -> [SDL.Event] -> IO Int+query counter events = do+  cameraAboveGround+  putObject counter events++cameraAboveGround :: IO ()+cameraAboveGround = do+  (Vector3 camx camy camz) <- getCameraPosition+  mres <- raySceneQuerySimple (Vector3 camx 5000 camz) negUnitY+  case mres of+    Nothing  -> return ()+    Just res -> when ((y res) + 10 > camy) $ setCameraPosition (Vector3 camx ((y res) + 10) camz)++putObject :: Int -> [SDL.Event] -> IO Int+putObject counter events = do+  let mp = getLMBPressed events+  case mp of+    Nothing           -> return counter+    Just (xpos, ypos) -> do+      scr <- SDL.getVideoSurface+      let wid = SDL.surfaceGetWidth scr+      let hei = SDL.surfaceGetHeight scr+      print (xpos, ypos, wid, hei)+      let wabs = (fromIntegral xpos) / (fromIntegral wid)+      let habs = (fromIntegral ypos) / (fromIntegral hei)+      pres <- raySceneQueryMouseSimple wabs habs+      case pres of+        Nothing                       -> return counter+        Just (Vector3 resx resy resz) -> do+          let swname = "robot" ++ (show counter)+          let pos = Vector3 resx (resy + 10) resz+          addEntity (robotTemplate swname pos)+          print swname+          return (counter + 1)+