more parsing ... -.-

This commit is contained in:
Nicole Dresselhaus 2014-04-25 21:21:19 +02:00
parent e5857e8435
commit 64d542adf3
5 changed files with 256 additions and 127 deletions

View File

@ -16,14 +16,15 @@ executable Pioneers
Map.Graphics, Map.Graphics,
Map.Creation, Map.Creation,
Map.StaticMaps, Map.StaticMaps,
IQM.Types, Importer.IQM.Types,
IQM.TestMain, Importer.IQM.TestMain,
IQM.Parser, Importer.IQM.Parser,
Render.Misc, Render.Misc,
Render.Render, Render.Render,
Render.RenderObject, Render.RenderObject,
Render.Types,
UI.Callbacks, UI.Callbacks,
Types, UI.Types,
UI.SurfaceOverlay UI.SurfaceOverlay
Types Types
main-is: Main.hs main-is: Main.hs
@ -45,6 +46,7 @@ executable Pioneers
SDL2 >= 0.1.0, SDL2 >= 0.1.0,
time >=1.4.0, time >=1.4.0,
GLUtil >= 0.7, GLUtil >= 0.7,
attoparsec >= 0.11.2 attoparsec >= 0.11.2,
attoparsec-binary >= 0.1
Default-Language: Haskell2010 Default-Language: Haskell2010

View File

@ -2,6 +2,101 @@
#extension GL_ARB_tessellation_shader : require #extension GL_ARB_tessellation_shader : require
//#include "shaders/3rdParty/noise.glsl"
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 mod289(vec4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 permute(vec4 x) {
return mod289(((x*34.0)+1.0)*x);
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
float snoise(vec3 v)
{
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy) );
vec3 x0 = v - i + dot(i, C.xxx) ;
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx;
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod289(i);
vec4 p = permute( permute( permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0)*2.0 + 1.0;
vec4 s1 = floor(b1)*2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
vec3 p0 = vec3(a0.xy,h.x);
vec3 p1 = vec3(a0.zw,h.y);
vec3 p2 = vec3(a1.xy,h.z);
vec3 p3 = vec3(a1.zw,h.w);
//Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
dot(p2,x2), dot(p3,x3) ) );
}
layout(triangles, equal_spacing, cw) in; layout(triangles, equal_spacing, cw) in;
in vec3 tcPosition[]; in vec3 tcPosition[];
in vec4 tcColor[]; in vec4 tcColor[];
@ -37,6 +132,7 @@ void main()
float i2 = (1-gl_TessCoord.z)*gl_TessCoord.z * length(cross(tcNormal[2],tessNormal)); float i2 = (1-gl_TessCoord.z)*gl_TessCoord.z * length(cross(tcNormal[2],tessNormal));
float standout = i0+i1+i2; float standout = i0+i1+i2;
tePosition = tePosition+tessNormal*standout; tePosition = tePosition+tessNormal*standout;
tePosition = tePosition+0.05*snoise(tePosition);
gl_Position = ProjectionMatrix * ViewMatrix * vec4(tePosition, 1); gl_Position = ProjectionMatrix * ViewMatrix * vec4(tePosition, 1);
//COLOR-BLENDING //COLOR-BLENDING
@ -48,4 +144,4 @@ void main()
//mix gravel based on incline (sin (normal,up)) //mix gravel based on incline (sin (normal,up))
gmix = length(cross(tessNormal, vec3(0,1,0))); gmix = length(cross(tessNormal, vec3(0,1,0)));
} }

View File

@ -8,8 +8,11 @@ module Importer.IQM.Parser (parseIQM) where
import Importer.IQM.Types import Importer.IQM.Types
import Data.Attoparsec.ByteString.Char8 import Data.Attoparsec.ByteString.Char8
import Data.Attoparsec.ByteString import Data.Attoparsec.ByteString
import Data.Attoparsec.Binary
import Data.Attoparsec (parse, takeByteString)
import Data.ByteString.Char8 (pack) import Data.ByteString.Char8 (pack)
import Data.ByteString (split, null) import Data.ByteString (split, null, ByteString)
import qualified Data.ByteString as B
import Data.Word import Data.Word
import Data.Int import Data.Int
import Unsafe.Coerce import Unsafe.Coerce
@ -20,12 +23,12 @@ import Control.Monad
import Prelude as P hiding (take, null) import Prelude as P hiding (take, null)
-- | helper-function for creating an integral out of [8-Bit Ints] -- | helper-function for creating an integral out of [8-Bit Ints]
w8ToInt :: Integral a => a -> a -> a _w8ToInt :: Integral a => a -> a -> a
w8ToInt i add = 256*i + add _w8ToInt i add = 256*i + add
-- | shorthand-function for parsing Word8 into Integrals -- | shorthand-function for parsing Word8 into Integrals
parseNum :: (Integral a, Integral b) => [a] -> b _parseNum :: (Integral a, Integral b) => [a] -> b
parseNum = (foldl1 w8ToInt) . map fromIntegral _parseNum = foldl1 _w8ToInt . map fromIntegral
-- | read a 16-Bit Int from Parsing-Input and log 2 bytes in our Parsing-Monad -- | read a 16-Bit Int from Parsing-Input and log 2 bytes in our Parsing-Monad
-- --
@ -35,55 +38,62 @@ _int16 = do
ret <- lift $ do ret <- lift $ do
a <- anyWord8 :: Parser Word8 a <- anyWord8 :: Parser Word8
b <- anyWord8 :: Parser Word8 b <- anyWord8 :: Parser Word8
return $ parseNum [b,a] return $ _parseNum [b,a]
modify (+2) modify (+2)
return ret return ret
-- | read a 32-Bit Int from Parsing-Input and log 4 bytes in our Parsing-Monad -- | read a 32-Bit Int from Parsing-Input and log 4 bytes in our Parsing-Monad
int32 :: CParser Word32 _int32 :: CParser Int32
int32 = do _int32 = do
ret <- lift $ do ret <- lift $ do
a <- anyWord8 :: Parser Word8 a <- anyWord8 :: Parser Word8
b <- anyWord8 :: Parser Word8 b <- anyWord8 :: Parser Word8
c <- anyWord8 :: Parser Word8 c <- anyWord8 :: Parser Word8
d <- anyWord8 :: Parser Word8 d <- anyWord8 :: Parser Word8
return $ parseNum [d,c,b,a] return $ _parseNum [d,c,b,a]
modify (+4) modify (+4)
return $ ret return ret
w32leCParser :: CParser Word32
w32leCParser = do
ret <- lift anyWord32le
modify (+4)
return ret
-- | Parser for the header -- | Parser for the header
readHeader :: CParser IQMHeader readHeader :: CParser IQMHeader
readHeader = do readHeader = do
_ <- lift $ string (pack "INTERQUAKEMODEL\0") _ <- lift $ string (pack "INTERQUAKEMODEL\0")
modify (+16) modify (+16)
v <- int32 v <- w32leCParser
-- when v /= 2 then --TODO: error something lift $ when (v /= 2) $ fail "Version /= 2.\nThis Parser only supports Version 2 of the InterQuake-Model IQM"
size' <- int32 -- when v /= 2 then fail parsing.
flags' <- int32 size' <- w32leCParser
num_text' <- int32 flags' <- w32leCParser
ofs_text' <- int32 num_text' <- w32leCParser
num_meshes' <- int32 ofs_text' <- w32leCParser
ofs_meshes' <- int32 num_meshes' <- w32leCParser
num_vertexarrays' <- int32 ofs_meshes' <- w32leCParser
num_vertexes' <- int32 num_vertexarrays' <- w32leCParser
ofs_vertexarrays' <- int32 num_vertexes' <- w32leCParser
num_triangles' <- int32 ofs_vertexarrays' <- w32leCParser
ofs_triangles' <- int32 num_triangles' <- w32leCParser
ofs_adjacency' <- int32 ofs_triangles' <- w32leCParser
num_joints' <- int32 ofs_adjacency' <- w32leCParser
ofs_joints' <- int32 num_joints' <- w32leCParser
num_poses' <- int32 ofs_joints' <- w32leCParser
ofs_poses' <- int32 num_poses' <- w32leCParser
num_anims' <- int32 ofs_poses' <- w32leCParser
ofs_anims' <- int32 num_anims' <- w32leCParser
num_frames' <- int32 ofs_anims' <- w32leCParser
num_framechannels' <- int32 num_frames' <- w32leCParser
ofs_frames' <- int32 num_framechannels' <- w32leCParser
ofs_bounds' <- int32 ofs_frames' <- w32leCParser
num_comment' <- int32 ofs_bounds' <- w32leCParser
ofs_comment' <- int32 num_comment' <- w32leCParser
num_extensions' <- int32 ofs_comment' <- w32leCParser
ofs_extensions' <- int32 num_extensions' <- w32leCParser
ofs_extensions' <- w32leCParser
return IQMHeader { version = v return IQMHeader { version = v
, filesize = size' , filesize = size'
, flags = fromIntegral flags' , flags = fromIntegral flags'
@ -116,12 +126,12 @@ readHeader = do
-- | Parser for Mesh-Structure -- | Parser for Mesh-Structure
readMesh :: CParser IQMMesh readMesh :: CParser IQMMesh
readMesh = do readMesh = do
name <- int32 name <- w32leCParser
mat <- int32 mat <- w32leCParser
fv <- int32 fv <- w32leCParser
nv <- int32 nv <- w32leCParser
ft <- int32 ft <- w32leCParser
nt <- int32 nt <- w32leCParser
return IQMMesh return IQMMesh
{ meshName = if name == 0 then Nothing else Just (Mesh name) { meshName = if name == 0 then Nothing else Just (Mesh name)
, meshMaterial = mat , meshMaterial = mat
@ -144,11 +154,11 @@ readMeshes n = do
-- | Parser for Mesh-Structure -- | Parser for Mesh-Structure
readVAF :: CParser IQMVertexArray readVAF :: CParser IQMVertexArray
readVAF = do readVAF = do
vat <- rawEnumToVAT =<< int32 vat <- rawEnumToVAT =<< w32leCParser
flags' <- int32 flags' <- w32leCParser
format <- rawEnumToVAF =<< int32 format <- rawEnumToVAF =<< w32leCParser
size <- int32 size <- w32leCParser
offset <- int32 offset <- w32leCParser
return $ IQMVertexArray vat (fromIntegral flags') format (fromIntegral size) offset return $ IQMVertexArray vat (fromIntegral flags') format (fromIntegral size) offset
-- | helper to read n consecutive Meshes tail-recursive -- | helper to read n consecutive Meshes tail-recursive
@ -166,7 +176,7 @@ readVAFs n = do
(.-) :: forall a a1 a2. (.-) :: forall a a1 a2.
(Num a, Integral a2, Integral a1) => (Num a, Integral a2, Integral a1) =>
a1 -> a2 -> a a1 -> a2 -> a
(.-) a b = (fromIntegral a) - (fromIntegral b) (.-) a b = fromIntegral a - fromIntegral b
infix 5 .- infix 5 .-
@ -183,21 +193,35 @@ skipToCounter a = do
put d put d
-- | Parses an IQM-File and handles back the Haskell-Structure -- | Parses an IQM-File and handles back the Haskell-Structure
parseIQM :: CParser IQM parseIQM :: String -> IO IQM
parseIQM = do parseIQM a =
put 0 --start at offset 0 do
h <- readHeader --read header f <- B.readFile a
skipToCounter $ ofs_text h --skip 0-n bytes to get to text Done _ raw <- return $ parse doIQMparse f
text <- lift . take . fromIntegral $ num_text h --read texts
modify . (+) . fromIntegral $ num_text h --put offset forward let ret = raw
skipToCounter $ ofs_meshes h --skip 0-n bytes to get to meshes return ret
meshes' <- readMeshes (fromIntegral (num_meshes h)) --read meshes
skipToCounter $ ofs_vertexarrays h --skip 0-n byots to get to vertexarray definition
va <- readVAFs (fromIntegral (num_vertexarrays h)) --read them
return IQM
{ header = h
, texts = filter (not.null) (split (unsafeCoerce '\0') text)
, meshes = meshes'
, vertexArrays = va
}
doIQMparse :: Parser IQM
doIQMparse =
flip evalStateT 0 $ --evaluate parser with state starting at 0
do
h <- readHeader --read header
skipToCounter $ ofs_text h --skip 0-n bytes to get to text
text <- lift . take . fromIntegral $ num_text h --read texts
modify . (+) . fromIntegral $ num_text h --put offset forward
skipToCounter $ ofs_meshes h --skip 0-n bytes to get to meshes
meshes' <- readMeshes $ fromIntegral $ num_meshes h --read meshes
skipToCounter $ ofs_vertexarrays h
vaf <- readVAFs $ fromIntegral $ num_vertexarrays h --read Vertex-Arrays
_ <- lift takeByteString
return IQM
{ header = h
, texts = filter (not.null) (split (unsafeCoerce '\0') text)
, meshes = meshes'
, vertexArrays = vaf
}
skipDrop :: Int -> Int -> ByteString -> ByteString
skipDrop a b= B.drop b . B.take a

View File

@ -1,5 +1,6 @@
-- | Int32 or Int64 - depending on implementation. Format just specifies "uint". {-# LANGUAGE BangPatterns #-}
-- 4-Byte in the documentation indicates Int32 - but not specified! -- | Word32 or Word64 - depending on implementation. Format just specifies "uint".
-- 4-Byte in the documentation indicates Word32 - but not specified!
module Importer.IQM.Types where module Importer.IQM.Types where
import Control.Monad.Trans.State.Lazy (StateT) import Control.Monad.Trans.State.Lazy (StateT)
@ -31,33 +32,33 @@ type IQMData = Ptr IQMVertexArrayFormat
-- --
-- ofs_* fields are aligned at 4-byte-boundaries -- ofs_* fields are aligned at 4-byte-boundaries
data IQMHeader = IQMHeader data IQMHeader = IQMHeader
{ version :: Word32 -- ^ Must be 2 { version :: !Word32 -- ^ Must be 2
, filesize :: Word32 , filesize :: !Word32
, flags :: Flags , flags :: !Flags
, num_text :: Word32 , num_text :: !Word32
, ofs_text :: Offset , ofs_text :: !Offset
, num_meshes :: Word32 , num_meshes :: !Word32
, ofs_meshes :: Offset , ofs_meshes :: !Offset
, num_vertexarrays :: Word32 , num_vertexarrays :: !Word32
, num_vertexes :: Word32 , num_vertexes :: !Word32
, ofs_vertexarrays :: Offset , ofs_vertexarrays :: !Offset
, num_triangles :: Word32 , num_triangles :: !Word32
, ofs_triangles :: Offset , ofs_triangles :: !Offset
, ofs_adjacency :: Offset , ofs_adjacency :: !Offset
, num_joints :: Word32 , num_joints :: !Word32
, ofs_joints :: Offset , ofs_joints :: !Offset
, num_poses :: Word32 , num_poses :: !Word32
, ofs_poses :: Offset , ofs_poses :: !Offset
, num_anims :: Word32 , num_anims :: !Word32
, ofs_anims :: Offset , ofs_anims :: !Offset
, num_frames :: Word32 , num_frames :: !Word32
, num_framechannels :: Word32 , num_framechannels :: !Word32
, ofs_frames :: Offset , ofs_frames :: !Offset
, ofs_bounds :: Offset , ofs_bounds :: !Offset
, num_comment :: Word32 , num_comment :: !Word32
, ofs_comment :: Offset , ofs_comment :: !Offset
, num_extensions :: Word32 -- ^ stored as linked list, not as array. , num_extensions :: !Word32 -- ^ stored as linked list, not as array.
, ofs_extensions :: Offset , ofs_extensions :: !Offset
} deriving (Show, Eq) } deriving (Show, Eq)
-- | Format of an IQM-Mesh Structure. -- | Format of an IQM-Mesh Structure.
@ -72,6 +73,22 @@ data IQMMesh = IQMMesh
, meshNumTriangles :: Word32 , meshNumTriangles :: Word32
} deriving (Show, Eq) } deriving (Show, Eq)
-- | Format of IQM-Triangle Structure
data IQMTriangle = IQMTriangle VertexIndex VertexIndex VertexIndex
-- | Type-Alias for Word32 indicating an index on vertices in IQMMesh
type VertexIndex = Word32
-- | Type-Alias for Word32 indicating an index on IQMTriangle
type TriangleIndex = Word32
-- | From the IQM-Format-Description:
--
-- each value is the index of the adjacent triangle for edge 0, 1, and 2, where ~0 (= -1)
-- indicates no adjacent triangle indexes are relative to the iqmheader.ofs_triangles array
-- and span all meshes, where 0 is the first triangle, 1 is the second, 2 is the third, etc.
data IQMAdjacency = IQMAdjacency TriangleIndex TriangleIndex TriangleIndex
-- | Format of a whole IQM-File -- | Format of a whole IQM-File
-- --
-- still unfinished! -- still unfinished!
@ -151,23 +168,10 @@ data IQMVertexArray = IQMVertexArray
Offset Offset
deriving (Eq) deriving (Eq)
instance Show IQMVertexArray where instance Show IQMVertexArray where
show (IQMVertexArray t fl fo nc off) = "IQMVertexArray (Type: " ++ (show t) ++ show (IQMVertexArray t fl fo nc off) = "IQMVertexArray (Type: " ++ show t ++
", Flags: " ++ (show fl) ++ ", Flags: " ++ show fl ++
", Format: " ++ (show fo) ++ ", Format: " ++ show fo ++
", NumComponents: " ++ (show nc) ++ ", NumComponents: " ++ show nc ++
", Offset: " ++ (show off) ++ ", Offset: " ++ show off ++
")" ")"
-- | A triangle out of the Vertices at the Indexed Positions
data IQMTriangle = IQMTriangle Index Index Index
deriving (Show, Eq)
-- | From the IQM-Format-Description:
--
-- each value is the index of the adjacent triangle for edge 0, 1, and 2, where ~0 (= -1)
-- indicates no adjacent triangle indexes are relative to the iqmheader.ofs_triangles array
-- and span all meshes, where 0 is the first triangle, 1 is the second, 2 is the third, etc.
data IQMAdjacency = IQMAdjacency Index Index Index
deriving (Show, Eq)

View File

@ -16,7 +16,6 @@ import Control.Concurrent.STM (TQueue,
newTQueueIO) newTQueueIO)
import Control.Monad.RWS.Strict (ask, evalRWST, get, liftIO, modify) import Control.Monad.RWS.Strict (ask, evalRWST, get, liftIO, modify)
import Control.Monad.Trans.State (evalStateT)
import Data.Functor ((<$>)) import Data.Functor ((<$>))
import Data.Distributive (distribute, collect) import Data.Distributive (distribute, collect)
import Data.Monoid (mappend) import Data.Monoid (mappend)
@ -51,17 +50,21 @@ import Render.Render (initRendering,
import UI.Callbacks import UI.Callbacks
import Types import Types
import Importer.IQM.Parser import Importer.IQM.Parser
import Data.Attoparsec.Char8 (parseTest) --import Data.Attoparsec.Char8 (parseTest)
import qualified Data.ByteString as B --import qualified Data.ByteString as B
-- import qualified Debug.Trace as D (trace) -- import qualified Debug.Trace as D (trace)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
testParser :: IO () testParser :: String -> IO ()
testParser = do testParser a = putStrLn . show =<< parseIQM a
f <- B.readFile "sample.iqm" {-do
parseTest (evalStateT parseIQM 0) f f <- B.readFile a
putStrLn "reading in:"
putStrLn $ show f
putStrLn "parsed:"
parseTest parseIQM f-}
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------