packages feed

bogre-banana-0.0.1: src/Reactive/Banana/BOGRE/OGRE.hs

--
-- Insert Documentation here :-)
--
module Reactive.Banana.BOGRE.OGRE where



import Reactive.Banana
import Reactive.Banana.Frameworks (
                Frameworks,
                AddHandler,
                fromAddHandler,
                newAddHandler
        )

import Control.Concurrent (
                forkIO
        )




import System.Exit
import Control.Monad

import Graphics.Ogre.HOgre
import Graphics.Ogre.Types

import BB.Workarounds


type Position = (Float,Float,Float)

data World = World {
                worldObject :: SceneNode,
                worldObjectPosition :: Position
        }
        
data DisplaySystem = DisplaySystem {
                window :: RenderWindow,
                root :: Root,
                sceneManager :: SceneManager
        }


createDisplaySystem :: IO(DisplaySystem)
createDisplaySystem = do
        -- construct Ogre::Root
        root <- root_new "plugins.cfg" "ogre.cfg" "Ogre.log"

        -- setup resources
        root_addResourceLocation root "../Media" "FileSystem" "Group" True
        
        -- configure
        -- show the configuration dialog and initialise the system
        restored <- root_restoreConfig root
        when (not restored) $ do
                configured <- root_showConfigDialog root
                when (not configured) $ exitWith (ExitFailure 1)
        window <- root_initialise root True "Render Window" ""
        
        -- set default mipmap level (some APIs ignore this)
        root_getTextureManager root >>= \tmgr -> textureManager_setDefaultNumMipmaps tmgr 5
        
        -- initialise all resource groups
        resourceGroupManager_getSingletonPtr >>= resourceGroupManager_initialiseAllResourceGroups
        
        -- create the scene manager, here a generic one
        smgr <- root_createSceneManager_RootPcharPcharP root "DefaultSceneManager" "Scene Manager"
        
        -- create and position the camera
        cam <- sceneManager_createCamera smgr "PlayerCam"
        frustum_setNearClipDistance (toFrustum cam) 5
        
        -- create one viewport, entire window
        vp <- renderTarget_addViewport (toRenderTarget window) cam 0 0 0 1 1
        colourValue_with 0 0 0 1 $ viewport_setBackgroundColour vp
        
        -- Alter the camera aspect ratio to match the viewport
        vpw <- viewport_getActualWidth vp
        vph <- viewport_getActualHeight vp
        frustum_setAspectRatio (toFrustum cam) (fromIntegral vpw / fromIntegral vph)
        
        -- AddHandler for the render Event
        (renderAH, fireRenderEvent) <- newAddHandler
        
        return DisplaySystem {
                        window = window,
                        root = root,
                        sceneManager = smgr
                }
                                
closeDisplaySystem :: DisplaySystem -> IO ()
closeDisplaySystem = root_delete . root
                
nullHandler :: Root -> Float -> () -> IO ((), Bool)
nullHandler _ _ _ = return ((), True)

addEntity :: DisplaySystem -> String -> IO (Entity, SceneNode)
addEntity ds mesh = do
        let smgr = sceneManager ds
        ent <- sceneManager_createEntity_SceneManagerPcharP smgr mesh
        rootNode <- sceneManager_getRootSceneNode smgr
        node <- sceneManager_createSceneNode_SceneManagerP smgr
        node_addChild (toNode rootNode) (toNode node)
        sceneNode_attachObject node (toMovableObject ent)
        return (ent, node)

getPosition :: SceneNode -> IO (Float, Float, Float)
getPosition sn = do
        pos <- node_getPosition (toNode sn)
        x <- getVector3X pos
        y <- getVector3Y pos
        z <- getVector3Z pos
        return (x,y,z)

setPosition :: SceneNode -> (Float, Float, Float) -> IO ()
setPosition sn (x,y,z) = node_setPosition (toNode sn) x y z

setPositionRelative :: SceneNode -> (Float, Float, Float) -> IO ()
setPositionRelative sn (x,y,z) = node_translate_NodePfloatfloatfloatNodeTransformSpace (toNode sn) x y z TS_WORLD

render :: RenderWindow -> Root -> a -> (Root -> Float -> Float -> a -> IO (a, Bool)) -> IO a
render win root value fun = do
    timer <- root_getTimer root
    time <- timer_getMicroseconds timer
    render' time win root value fun

render' :: Int -> RenderWindow -> Root -> a -> (Root -> Float -> Float -> a -> IO (a, Bool)) -> IO a
render' time win root value fun = 
  do windowEventUtilities_messagePump
     closed <- renderWindow_isClosed win
     if closed
       then return value
       else do
         success <- root_renderOneFrame_RootP root
         timer <- root_getTimer root
         time' <- timer_getMicroseconds timer
         let tiF = (fromIntegral (time)) / 1000000
         let tfF = (fromIntegral (time')) / 1000000
         (value', cont) <- fun root tiF tfF value
         if success && cont
           then render' time' win root value' fun
           else return value'




{-
create3DWindow :: Int -> IO (InputSystem)
create3DWindow hwnd = do
        im <- inputManager_createInputSystem_size_t hwnd
        -- get mouse and keyboard objects
        -- unsafeCoerce instead of static_cast
        mouse <- unsafeCoerce $ inputManager_createInputObject im OISMouse True ""
        keyboard <- unsafeCoerce $ inputManager_createInputObject im OISKeyboard True ""
        -- create the addhandlers
        mouseNewAddHandler <- newAddHandler
        keyboardNewAddHandler <- newAddHandler
        -- done, package into a InputSystem
        return ((keyboard, keyboardNewAddHandler), (mouse, mouseNewAddHandler)) -}