132 lines
4.3 KiB
Haskell
132 lines
4.3 KiB
Haskell
|
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
|
||
|
}
|
||
|
|