pioneers/src/Importer/IQM/Parser.hs

132 lines
4.3 KiB
Haskell
Raw Normal View History

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
}