From 40e3b6ed4dec9458ebbe841d2aee6c57b31cd38f Mon Sep 17 00:00:00 2001 From: Stefan Dresselhaus Date: Wed, 9 Apr 2014 20:04:06 +0200 Subject: [PATCH] started iqm-parser - can parse header - can parse initial texts - can parse mesh-structure - cannot parse everything else. --- Pioneers.cabal | 6 +- sample.iqm | Bin 0 -> 3104 bytes src/Importer/IQM/Parser.hs | 132 +++++++++++++++++++++++++++++++++++++ src/Importer/IQM/Types.hs | 60 +++++++++++++++++ src/Main.hs | 9 +++ 5 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 sample.iqm create mode 100644 src/Importer/IQM/Parser.hs create mode 100644 src/Importer/IQM/Types.hs diff --git a/Pioneers.cabal b/Pioneers.cabal index 27a407f..48b2fc3 100644 --- a/Pioneers.cabal +++ b/Pioneers.cabal @@ -16,6 +16,9 @@ executable Pioneers Map.Graphics, Map.Creation, Map.StaticMaps, + IQM.Types, + IQM.TestMain, + IQM.Parser, Render.Misc, Render.Render, Render.RenderObject, @@ -41,6 +44,7 @@ executable Pioneers lens >=4.0, SDL2 >= 0.1.0, time >=1.4.0, - GLUtil >= 0.7 + GLUtil >= 0.7, + attoparsec >= 0.11.2 Default-Language: Haskell2010 diff --git a/sample.iqm b/sample.iqm new file mode 100644 index 0000000000000000000000000000000000000000..44a9d4607b18d9834d46352efe43593c03b4a54d GIT binary patch literal 3104 zcmeH}%}bO~6vl5;+LxwT*@rgs`jLfLOw_KXJ7%+xGAom4BO$nwDUI3%&bpP*CMv?9 zphY`f2$HYRB5GxSL17#JfHu+M?fK2T7cT?R8$zo&aOOVe+~=Ho&T&T0;MJRj8`nqs zFBgV}FBPtslrbh~(1&Ed^pSLnbXHm~Jt2K74aFGil1{XRb{PQ#bA+|<|; zyQn<%$^-UeeLSlCCzT(LAM3yCmukPO z0l&lWU2L`A^@!hLzn5yis|~-y@LjC$2fG@;ehogq@)xgtZhiu#a3jZ`aVEF292AP- zdSuTe!JXoYcR@edg(SFL+>S!gMp4s360Dpyt(sEi&e^1xy6F}E-*8)85BwxJqkg*; z13wAwjpqqJ35HjZl6A#y7Txl23qr#_dJyL~g%f-(ja?|6w=6 z)*58A_86^oWz1TK%}UrP-4o-c*lyOjSK1;4?~84Awgb{uDfnP)AJTbPdPE9ti|uxu zN2O^gI1}4}&JJm(6x=1n?v@^t_Qd#jY||Tk&?mjn7lKWF_z-$#CUEJAd&HjyJ#$Y^ zX22aMHnGfz{N!X#%!hm4VIJJ$V^+js<0mgZ=0+XZ%#Awmk&FD;_}yH|#T^{t$wl5s z^6~3CJGRtgi{lT%so~Gd6X{lqP77E5Pw`tVS>l~U(TsgOI6ePz^3}P?pEF@!UH|zH J&ps{r{NI61n*#s< literal 0 HcmV?d00001 diff --git a/src/Importer/IQM/Parser.hs b/src/Importer/IQM/Parser.hs new file mode 100644 index 0000000..09efd9a --- /dev/null +++ b/src/Importer/IQM/Parser.hs @@ -0,0 +1,132 @@ +module Importer.IQM.Parser where + +import Importer.IQM.Types +import Data.Attoparsec.ByteString.Char8 +import Data.Attoparsec.ByteString +import Data.Attoparsec +import Data.ByteString.Char8 (pack) +import Data.ByteString (split, null) +import Data.Word +import Data.Int +import Data.List (foldl1) +import Foreign.C.Types +import Unsafe.Coerce + +import Prelude as P hiding (take, null) + +w8Toint :: Integral a => a -> a -> a +w8Toint i add = 256*i + add + + +int16 :: Parser Int16 +int16 = do + a <- anyWord8 :: Parser Word8 + b <- anyWord8 :: Parser Word8 + return $ foldl1 w8Toint $ map fromIntegral [b,a] + +int32 :: Parser Int32 +int32 = do + a <- anyWord8 :: Parser Word8 + b <- anyWord8 :: Parser Word8 + c <- anyWord8 :: Parser Word8 + d <- anyWord8 :: Parser Word8 + return $ foldl1 w8Toint $ map fromIntegral [d,c,b,a] + +readHeader = do + string (pack "INTERQUAKEMODEL\0") + v <- int32 + -- when v /= 2 then --TODO: error something + size <- int32 + flags <- int32 + num_text <- int32 + ofs_text <- int32 + num_meshes <- int32 + ofs_meshes <- int32 + num_vertexarrays <- int32 + num_vertexes <- int32 + ofs_vertexarrays <- int32 + num_triangles <- int32 + ofs_triangles <- int32 + ofs_adjacency <- int32 + num_joints <- int32 + ofs_joints <- int32 + num_poses <- int32 + ofs_poses <- int32 + num_anims <- int32 + ofs_anims <- int32 + num_frames <- int32 + num_framechannels <- int32 + ofs_frames <- int32 + ofs_bounds <- int32 + num_comment <- int32 + ofs_comment <- int32 + num_extensions <- int32 + ofs_extensions <- int32 + return (IQMHeader { version = v + , filesize = size + , flags = flags + , num_text = num_text + , ofs_text = ofs_text + , num_meshes = num_meshes + , ofs_meshes = ofs_meshes + , num_vertexarrays = num_vertexarrays + , num_vertexes = num_vertexes + , ofs_vertexarrays = ofs_vertexarrays + , num_triangles = num_triangles + , ofs_triangles = ofs_triangles + , ofs_adjacency = ofs_adjacency + , num_joints = num_joints + , ofs_joints = ofs_joints + , num_poses = num_poses + , ofs_poses = ofs_poses + , num_anims = num_anims + , ofs_anims = ofs_anims + , num_frames = num_frames + , num_framechannels = num_framechannels + , ofs_frames = ofs_frames + , ofs_bounds = ofs_bounds + , num_comment = num_comment + , ofs_comment = ofs_comment + , num_extensions = num_extensions + , ofs_extensions = ofs_extensions + } + , 16+27*4) + +readMesh :: Parser IQMMesh +readMesh = do + name <- int32 + mat <- int32 + fv <- int32 + nv <- int32 + ft <- int32 + nt <- int32 + return IQMMesh + { meshName = if name == 0 then Nothing else Just (Mesh name) + , meshMaterial = mat + , meshFirstVertex = fv + , meshNumVertexes = nv + , meshFirstTriangle = ft + , meshNumTriangles = nt + } + +readMeshes :: Int -> Parser [IQMMesh] +readMeshes 1 = do + m <- readMesh + return [m] +readMeshes n = do + m <- readMesh + ms <- readMeshes (n-1) + return $ m:ms + +parseIQM :: Parser IQM +parseIQM = do + (h,soFar) <- readHeader + take $ (fromIntegral (ofs_text h)) - soFar + text <- take $ fromIntegral $ num_text h + meshes <- readMeshes (fromIntegral (num_meshes h)) + return IQM + { header = h + , texts = filter (not.null) (split (unsafeCoerce '\0') text) + , meshes = meshes + } + \ No newline at end of file diff --git a/src/Importer/IQM/Types.hs b/src/Importer/IQM/Types.hs new file mode 100644 index 0000000..8222e85 --- /dev/null +++ b/src/Importer/IQM/Types.hs @@ -0,0 +1,60 @@ +module Importer.IQM.Types where + +import Data.Int +import Data.ByteString + +newtype Mesh = Mesh Int32 deriving (Show, Eq) +newtype CParser a = Parser (a, Int64) + +-- Int32 or Int64 - depending on implementation. Format just specifies "uint". +-- 4-Byte indicates Int32 + +-- | ofs_* fields are relative tot he beginning of the iqmheader struct +-- ofs_* fields are set to 0 when data is empty +-- ofs_* fields are aligned at 4-byte-boundaries +data IQMHeader = IQMHeader + { version :: Int32 -- ^ Must be 2 + , filesize :: Int32 + , flags :: Int32 + , num_text :: Int32 + , ofs_text :: Int32 + , num_meshes :: Int32 + , ofs_meshes :: Int32 + , num_vertexarrays :: Int32 + , num_vertexes :: Int32 + , ofs_vertexarrays :: Int32 + , num_triangles :: Int32 + , ofs_triangles :: Int32 + , ofs_adjacency :: Int32 + , num_joints :: Int32 + , ofs_joints :: Int32 + , num_poses :: Int32 + , ofs_poses :: Int32 + , num_anims :: Int32 + , ofs_anims :: Int32 + , num_frames :: Int32 + , num_framechannels :: Int32 + , ofs_frames :: Int32 + , ofs_bounds :: Int32 + , num_comment :: Int32 + , ofs_comment :: Int32 + , num_extensions :: Int32 -- ^ stored as linked list, not as array. + , ofs_extensions :: Int32 + } deriving (Show, Eq) + + +data IQMMesh = IQMMesh + { meshName :: Maybe Mesh + , meshMaterial :: Int32 + , meshFirstVertex :: Int32 + , meshNumVertexes :: Int32 + , meshFirstTriangle :: Int32 + , meshNumTriangles :: Int32 + } deriving (Show, Eq) + +data IQM = IQM + { header :: IQMHeader + , texts :: [ByteString] + , meshes :: [IQMMesh] + } deriving (Show, Eq) + \ No newline at end of file diff --git a/src/Main.hs b/src/Main.hs index c9963cb..a8283e4 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -60,12 +60,21 @@ import Render.Render (initRendering, import UI.Callbacks import UI.GUIOverlay import Types +import Importer.IQM.Parser +import Data.Attoparsec.Char8 (parseTest) +import qualified Data.ByteString as B --import ThirdParty.Flippers import qualified Debug.Trace as D (trace) -------------------------------------------------------------------------------- + +testParser = do + B.readFile "sample.iqm" >>= parseTest parseIQM + +-------------------------------------------------------------------------------- + main :: IO () main = do SDL.withInit [InitVideo, InitAudio, InitEvents, InitTimer] $ do --also: InitNoParachute -> faster, without parachute!