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 +23/−0
- Media/Example.material +122/−0
- Media/HornetUV_Cylinder.tga binary
- Media/IMG_0436.JPG binary
- Media/TailWings.JPG binary
- Media/WingFlap.jpg binary
- Media/WingFlapBump.jpg binary
- Media/Wings.jpg binary
- Media/WingsBump.jpg binary
- Media/blackhawk.material +37/−0
- Media/clouds.jpg binary
- Media/lagoon.tga binary
- Media/lava.tga binary
- Media/mix.tga binary
- Media/terrain.cfg +71/−0
- Media/terrain.png binary
- Media/terrain_detail.jpg binary
- Media/terrain_texture.jpg binary
- README +1/−0
- Setup.hs +3/−0
- hogre-examples.cabal +66/−0
- plugins.cfg +12/−0
- resources.cfg +3/−0
- src/Common.hs +115/−0
- src/Example_01.hs +48/−0
- src/Example_02.hs +41/−0
- src/Example_03.hs +80/−0
+ 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)+