packages feed

lambdacube-bullet-0.1.1: src/lambdacube-bullet-example.hs

import Data.Maybe
import Data.Map hiding (filter)
import qualified Data.IntMap as IntMap
import Control.Monad
import Control.Applicative
import Foreign
import Foreign.C.Types

import FRP.Elerea
import Graphics.UI.GLFW as GLFW
import Graphics.Rendering.OpenGL as GL hiding (light)
import System.Log.Logger

import Graphics.LambdaCube
import Graphics.LambdaCube.RenderSystem.GL
import qualified Graphics.LambdaCube.Loader.StbImage as Stb
import Physics.Bullet

import Paths_lambdacube_bullet (getDataFileName)

import Utils
import BulletUtils

integral v0 s = transfer v0 (\dt v v0 -> v0+v*realToFrac dt) s

baseMousePos = Position 200 200

main = do
    updateGlobalLogger rootLoggerName (setLevel DEBUG)
    initialize
    openWindow (Size 640 480) [DisplayRGBBits 8 8 8, DisplayAlphaBits 8, DisplayDepthBits 24] Window
    windowTitle $= "Lambda-Cube GLFW UnsafeFRP Example 1"
    GLFW.mousePos $= baseMousePos
    GLFW.disableSpecial MouseCursor

    GL.TextureUnit mtu <- GL.get GL.maxTextureUnit
    print $ "max texunit: " ++ (show mtu)

    v <- get vendor
    rend <- get renderer
    ver <- get glVersion
    exts <- get glExtensions
    shver <- get shadingLanguageVersion
--    mm <- get majorMinor
    debugM "gl" $ "vendor: " ++ show v
    debugM "gl" $ "renderer: " ++ show rend
    debugM "gl" $ "glVersion: " ++ show ver
    debugM "gl" $ "glExtensions: " ++ show exts
    debugM "gl" $ "shadingLanguageVersion: " ++ show shver
--    debugM "gl" $ "majorMinor: " ++ show mm

    initGL 640 480
    (windowSize,windowSizeSink) <- external (0,0)
    (mousePosition,mousePositionSink) <- external (0,0)
    (mousePress,mousePressSink) <- external False
    (firePress,firePressSink) <- external False
    (fblrPress,fblrPressSink) <- external (False,False,False,False,False)

    mediaPath <- getDataFileName "media"
    
    windowSizeCallback $= resizeGLScene windowSizeSink
    renderSystem <- mkGLRenderSystem
    world <- addRenderWindow "MainWindow" 640 480 [mkViewport 0 0 1 1 "Camera1" []]
          =<< addResourceLibrary [("General",[(PathDir,mediaPath)])]
--          =<< addConfig "resources.cfg"
          =<< mkWorld renderSystem [Stb.loadImage]

    --(w',ent) <- createEntity world "Cube" "Cube.mesh.xml"
    (w',ent) <- createEntity world "car" "scooby_body.mesh.xml"
    (w'',colent) <- createEntity w' "car_collision" "scooby_body.mesh.xml"
    (w''',ground) <- createEntity w'' "ground" "Ground.mesh.xml"
    --,mkNode "Root" "GroundNode1" (scal 80 <> transl sx 0 sz) [mesh "Ground.mesh.xml"]
    (worldSignal,worldSignalSink) <- external (w'',0,[])

    let shapeMesh = enMesh colent -- (rlMeshMap $ wrResource w') ! "Cube.mesh.xml" -- "ogrehead.lmesh"

    sdk <- plNewBulletSdk
    dw <- plCreateDynamicsWorld sdk
    gs <- plNewBoxShape 1000 100 1000
    gb <- plCreateRigidBody nullPtr 0 gs
    plAddRigidBody dw gb
    plSetPosition gb (0,-103,0)
    --shape <- mkConvexHullMeshShape shapeMesh
    shape <- mkConvexTriangleMeshShape shapeMesh
    --shape <- mkStaticTriangleMeshShape shapeMesh
    --shape <- mkGimpactTriangleMeshShape shapeMesh
    --shape <- plNewBoxShape 1 1 1

    re1 <- createSignal $ integral 0 $ pure (1.5)
    re2 <- createSignal $ integral 10 $ pure (-1.0)
    re3 <- createSignal $ integral 110 $ pure (0.8)
    time <- createSignal $ stateful 0 (+)
    fire <- createSignal $ transfer (0,False) (\ t f (rt,_) -> if f then (if rt > 0 then (max 0 $ rt - t) else 0.5,rt <= 0) else ((max 0 $ rt - t),False)) firePress
    cam <- cameraSignal (-10,0,0) mousePosition fblrPress

    s <- fpsState

    driveNetwork (drawGLScene ent dw shape ground worldSignalSink <$> fire <*> worldSignal <*> windowSize <*> mousePosition <*> re1 <*> re2 <*> re3 <*> cam)-- <*> zsin <*> cam)
                 (readInput dw s firePressSink mousePositionSink mousePressSink fblrPressSink)

    closeWindow

readInput dw s fire mousePos mouseBut fblrPress = do
    t <- get GLFW.time
    updateFPS s t
    GLFW.time $= 0
    let Position x0 y0 = baseMousePos
    Position x y <- get GLFW.mousePos
    GLFW.mousePos $= baseMousePos
    mousePos (fromIntegral (x-x0),fromIntegral (y-x0))

    b <- GLFW.getMouseButton GLFW.ButtonLeft
    mouseBut (b == GLFW.Press)
    k <- (==GLFW.Press) <$> getKey ESC
    kw <- (==GLFW.Press) <$> getKey UP -- $ CharKey 'w'
    ks <- (==GLFW.Press) <$> getKey DOWN -- $ CharKey 's'
    ka <- (==GLFW.Press) <$> getKey LEFT -- $ CharKey 'a'
    kd <- (==GLFW.Press) <$> getKey RIGHT -- $ CharKey 'd'
    turbo <- (==GLFW.Press) <$> getKey RSHIFT
    fblrPress (ka,kw,ks,kd,turbo)
    fire =<< (==GLFW.Press) <$> getKey '.'
    plStepSimulation dw $ realToFrac t

    return (if k then Nothing else Just t)

drawGLScene ent dw shape ground worldSink (_,fire) (world,i,l) (w,h) (cx,cy) re1 re2 re3 (cam',dir,up,_) {-zsin camMat-} = do
    let getTransform body = do
            (e0',e1',e2',e3',e4',e5',e6',e7',e8',e9',eA',eB',eC',eD',eE',eF') <- plGetOpenGLMatrix body
            let (e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,eA,eB,eC,eD,eE,eF) = (f e0',f e1',f e2',f e3',f e4',f e5',f e6',f e7',f e8',f e9',f eA',f eB',f eC',f eD',f eE',f eF')
                f :: CFloat -> FloatType
                f = realToFrac
            return $ mk4 (Matrix4 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 eA eB eC eD eE eF) ent

        cam = Camera
            { cmName        = "Camera1"
            , cmFov         = 45
            , cmNear        = 0.1
            , cmFar         = 1000
            , cmAspectRatio = Nothing
            , cmPolygonMode = PM_SOLID
            }

        mk4 m e = (m,prepare m e,constRenderQueueMain,constRenderableDefaultPriority)

    p <- mapM getTransform l
    renderWorld 0 "MainWindow" (FlattenScene (mk4 (scal 200 <> transl 0 (-3) 0) ground:p)
                                               [(lookat cam' dir up,cam)] [])
                    =<< updateTargetSize "MainWindow" w h
                        world
    swapBuffers
    when fire $ do
        let world' = world
        -- create new rigid body
        b <- plCreateRigidBody Foreign.nullPtr 10 shape
        plAddRigidBody dw b
        --plSetPosition b (0,6 + fromIntegral (3*i+1),0)
        plSetPosition b (0,6,0)
        putStrLn $ "instances: " ++ show (i+1)
        -- update rigid body map
        worldSink (world',i+1,b:l)