pioneers/src/Render/Misc.hs

192 lines
7.4 KiB
Haskell
Raw Normal View History

module Render.Misc where
import Control.Monad
import qualified Data.ByteString as B (ByteString)
2014-04-05 23:09:57 +02:00
import Data.Int (Int8)
2014-08-29 21:25:31 +02:00
import Data.Word (Word32,Word8)
import Graphics.Rendering.OpenGL.GL.Shaders
import Graphics.Rendering.OpenGL.GL.StateVar
import Graphics.Rendering.OpenGL.GL.StringQueries
import Graphics.Rendering.OpenGL.GLU.Errors
import Graphics.Rendering.OpenGL.GL.VertexArrayObjects
import Graphics.Rendering.OpenGL.GL.VertexArrays
import Graphics.Rendering.OpenGL.GL.VertexSpec
import Graphics.Rendering.OpenGL.GL.BufferObjects
2014-03-24 08:21:30 +01:00
import Graphics.UI.SDL.Types (Texture)
import System.IO (hPutStrLn, stderr)
2014-01-04 17:57:30 +01:00
import Linear
import Foreign.C (CFloat, CUChar)
import Foreign.Marshal.Array (peekArray)
import Foreign.Ptr (Ptr, castPtr)
2014-01-06 21:13:58 +01:00
2014-01-04 17:57:30 +01:00
up :: V3 CFloat
up = V3 0 1 0
checkError :: String -> IO ()
checkError functionName = get errors >>= mapM_ reportError
where reportError e =
hPutStrLn stderr (showError e ++ " detected in " ++ functionName)
showError (Error category message) =
"GL error " ++ show category ++ " (" ++ message ++ ")"
dumpInfo :: IO ()
dumpInfo = do
let dump message var = putStrLn . ((message ++ ": ") ++) =<< get var
dump "Vendor" vendor
dump "Renderer" renderer
dump "Version" glVersion
dump "GLSL" shadingLanguageVersion
checkError "dumpInfo"
checked :: (t -> IO ()) -> (t -> GettableStateVar Bool) -> (t -> GettableStateVar String) -> String -> t -> IO ()
checked action getStatus getInfoLog message object = do
action object
status <- get (getStatus object)
unless status $
hPutStrLn stderr . ((message ++ " log: ") ++) =<< get (getInfoLog object)
compileAndCheck :: Shader -> IO ()
compileAndCheck = checked compileShader compileStatus shaderInfoLog "compile"
compileShaderSource :: ShaderType -> B.ByteString -> IO Shader
compileShaderSource st source = do
shader <- createShader st
shaderSourceBS shader $= source
compileAndCheck shader
return shader
linkAndCheck :: Program -> IO ()
linkAndCheck = checked linkProgram linkStatus programInfoLog "link"
createProgramUsing :: [Shader] -> IO Program
createProgramUsing shaders = do
program <- createProgram
attachedShaders program $= shaders
linkAndCheck program
return program
2014-01-05 19:09:01 +01:00
createFrustum :: Float -> Float -> Float -> Float -> M44 CFloat
createFrustum fov n' f' rat =
let
2014-01-05 19:09:01 +01:00
f = realToFrac f'
n = realToFrac n'
s = realToFrac $ recip (tan $ fov*0.5 * pi / 180)
(ratw,rath) = if rat > 1 then
(1,1/realToFrac rat)
else
(realToFrac rat,1)
in
V4 (V4 (s/ratw) 0 0 0)
(V4 0 (s/rath) 0 0)
(V4 0 0 (-((f+n)/(f-n))) (-((2*f*n)/(f-n))))
(V4 0 0 (-1) 0)
-- | Creates an orthogonal frustum with given width, height, near and far-plane
createFrustumOrtho :: Float -> Float -> Float -> Float -> M44 CFloat
createFrustumOrtho w' h' n' f' =
let [w,h,n,f] = map realToFrac [w',h',n',f']
in
V4 (V4 (0.5/w) 0 0 0)
(V4 0 (0.5/h) 0 0)
(V4 0 0 (-2/(f-n)) ((-f+n)/(f-n)))
(V4 0 0 0 1)
2014-01-04 23:47:07 +01:00
-- from vmath.h
2014-01-04 17:57:30 +01:00
lookAt :: V3 CFloat -> V3 CFloat -> V3 CFloat -> M44 CFloat
lookAt eye center up' =
2014-01-04 17:57:30 +01:00
V4
(V4 xx xy xz (-dot x eye))
(V4 yx yy yz (-dot y eye))
(V4 zx zy zz (-dot z eye))
2014-01-04 17:57:30 +01:00
(V4 0 0 0 1)
where
z@(V3 zx zy zz) = normalize (eye ^-^ center)
x@(V3 xx xy xz) = normalize (cross up' z)
y@(V3 yx yy yz) = normalize (cross z x)
2014-01-04 17:57:30 +01:00
2014-04-21 19:46:24 +02:00
{-getCam :: (Double, Double) -- ^ Target in x/z-Plane
-> Double -- ^ Distance from Target
-> Double -- ^ Angle around X-Axis (angle down/up)
-> Double -- ^ Angle around Y-Axis (angle left/right)
-> M44 CFloat
getCam (x',z') dist' xa' ya' = lookAt (cpos ^+^ at') at' up
where
at' = V3 x 0 z
cpos = crot !* (V3 0 0 (-dist))
crot = (
(fromQuaternion $ axisAngle upmap (xa::CFloat))
!*!
(fromQuaternion $ axisAngle (V3 0 1 0) (ya::CFloat))
) ::M33 CFloat
upmap = ((fromQuaternion $ axisAngle (V3 0 1 0) (ya::CFloat)) :: M33 CFloat)
!* (V3 1 0 0)
x = realToFrac x'
z = realToFrac z'
dist = realToFrac dist'
xa = realToFrac xa'
2014-04-21 19:46:24 +02:00
ya = realToFrac ya'-}
-- | Prints any Pointer as Float-Array with given number of elements and chunks.
printPtrAsFloatArray :: Ptr a -> Int -> Int -> IO ()
printPtrAsFloatArray pointer num co = do
a <- peekArray num (castPtr pointer :: Ptr CFloat)
print $ chunksOf co a
-- | Prints any Pointer as UByte-Array with given number of elements and chunks.
printPtrAsUByteArray :: Ptr a -> Int -> Int -> IO ()
printPtrAsUByteArray pointer num co = do
a <- peekArray num (castPtr pointer :: Ptr CUChar)
print $ chunksOf co a
-- | Prints any Pointer as Word32-Array with given number of elements and chunks.
printPtrAsWord32Array :: Ptr a -> Int -> Int -> IO ()
printPtrAsWord32Array pointer num co = do
a <- peekArray num (castPtr pointer :: Ptr Word32)
print $ chunksOf co a
2014-01-20 23:18:07 +01:00
curb :: Ord a => a -> a -> a -> a
curb l h x
| x < l = l
| x > h = h
| otherwise = x
2014-03-24 08:21:30 +01:00
tryWithTexture :: Maybe Texture -> (Texture -> a) -> a -> a
tryWithTexture t f fail' =
case t of
Just tex -> f tex
_ -> fail'
2014-03-24 23:26:02 +01:00
2014-04-05 23:09:57 +02:00
genColorData :: Int -- ^ Amount
2014-08-29 21:25:31 +02:00
-> [Word8] -- ^ [r,g,b,a], [r,g,b] - whatever should be repeatet.
-> [Word8]
genColorData n c = take (length c*n) (cycle c)
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf a xs = take a xs : chunksOf a (drop a xs)
withVAO :: VertexArrayObject -> IO a -> IO a
withVAO v a = do
bindVertexArrayObject $= Just v
ret <- a
bindVertexArrayObject $= Nothing
return ret
withVBO :: BufferObject -> BufferTarget -> IO a -> IO a
withVBO b t a = do
bindBuffer t $= Just b
ret <- a
bindBuffer t $= Nothing
return ret
withVAA :: [AttribLocation] -> IO a -> IO a
withVAA atts action = do
mapM_ (\a -> vertexAttribArray a $= Enabled) atts
ret <- action
mapM_ (\a -> vertexAttribArray a $= Disabled) atts
return ret