From 2e22e77d7552d7e0b708dff63468ef4bd5d43d9b Mon Sep 17 00:00:00 2001 From: Stefan Dresselhaus Date: Sat, 26 Apr 2014 16:52:32 +0200 Subject: [PATCH 1/2] memory gets allocated and written. No garantuee for correctness.... --- src/Importer/IQM/Parser.hs | 32 ++++++++++++++++---------------- src/Importer/IQM/Types.hs | 8 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Importer/IQM/Parser.hs b/src/Importer/IQM/Parser.hs index e330f19..0295516 100644 --- a/src/Importer/IQM/Parser.hs +++ b/src/Importer/IQM/Parser.hs @@ -200,28 +200,30 @@ parseIQM :: String -> IO IQM parseIQM a = do f <- B.readFile a - putStrLn "Before Parse:" - putStrLn $ show f - putStrLn "Real Parse:" - r <- return $ parse doIQMparse f - raw <- case r of + -- Parse Headers/Offsets + let result = parse doIQMparse f + raw <- case result of Done _ x -> return x - y -> error $ show y - let ret = raw - return ret + y -> error $ show y + -- Fill Vertex-Arrays with data of Offsets + let va = vertexArrays raw + va' <- mapM (readInVAO f) va + return $ raw { + vertexArrays = va' + } -readInVAO :: IQMVertexArray -> ByteString -> IO IQMVertexArray -readInVAO (IQMVertexArray type' a format num offset ptr) d = +readInVAO :: ByteString -> IQMVertexArray -> IO IQMVertexArray +readInVAO d (IQMVertexArray type' a format num offset ptr) = do let - byteLen = (fromIntegral num)*(vaSize format) + byteLen = fromIntegral num * vaSize format data' = skipDrop (fromIntegral offset) byteLen d - when (not (ptr == nullPtr)) $ error $ "Error reading Vertex-Array: Double Read of " ++ show type' + unless (ptr == nullPtr) $ error $ "Error reading Vertex-Array: Double Read of " ++ show type' p <- mallocBytes byteLen + putStrLn $ concat ["Allocating ", show byteLen, " Bytes at ", show p] unsafeUseAsCString data' (\s -> copyBytes p s byteLen) - p' <- unsafeCoerce p - return (IQMVertexArray type' a format num offset p') + return $ IQMVertexArray type' a format num offset $ castPtr p doIQMparse :: Parser IQM doIQMparse = @@ -235,8 +237,6 @@ doIQMparse = meshes' <- readMeshes $ fromIntegral $ num_meshes h --read meshes skipToCounter $ ofs_vertexarrays h --skip 0-n bytes to get to Vertex-Arrays vaf <- readVAFs $ fromIntegral $ num_vertexarrays h --read Vertex-Arrays - - _ <- lift takeByteString return IQM { header = h , texts = filter (not.null) (split (unsafeCoerce '\0') text) diff --git a/src/Importer/IQM/Types.hs b/src/Importer/IQM/Types.hs index 3558660..01ec020 100644 --- a/src/Importer/IQM/Types.hs +++ b/src/Importer/IQM/Types.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE ExistentialQuantification, RankNTypes, CPP, BangPatterns #-} +-- {-# LANGUAGE ExistentialQuantification, RankNTypes, CPP, BangPatterns #-} -- | 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 @@ -13,7 +13,6 @@ import Graphics.Rendering.OpenGL.Raw.Types import Prelude as P import Foreign.Storable import Foreign.C.Types -import Foreign.Marshal.Array -- | Mesh-Indices to distinguish the meshes referenced newtype Mesh = Mesh Word32 deriving (Show, Eq) @@ -148,7 +147,7 @@ vaSize IQMshort = sizeOf (undefined :: CShort) vaSize IQMushort = sizeOf (undefined :: CUShort) vaSize IQMint = sizeOf (undefined :: CInt) vaSize IQMuint = sizeOf (undefined :: CUInt) -vaSize IQMhalf = sizeOf (undefined :: Word16) --TODO: Find 16-Bit-Float-Datatype +vaSize IQMhalf = sizeOf (undefined :: Word16) --TODO: Find 16-Bit-Float-Datatype FIXME! vaSize IQMfloat = sizeOf (undefined :: CFloat) vaSize IQMdouble = sizeOf (undefined :: CDouble) @@ -187,10 +186,11 @@ data IQMVertexArray = IQMVertexArray IQMData deriving (Eq) instance Show IQMVertexArray where - show (IQMVertexArray t fl fo nc off _) = "IQMVertexArray (Type: " ++ show t ++ + show (IQMVertexArray t fl fo nc off dat) = "IQMVertexArray (Type: " ++ show t ++ ", Flags: " ++ show fl ++ ", Format: " ++ show fo ++ ", NumComponents: " ++ show nc ++ ", Offset: " ++ show off ++ + ", Data at: " ++ show dat ++ ")" From 5223c34da2f24d1f217863df33826affd757ba8c Mon Sep 17 00:00:00 2001 From: Stefan Dresselhaus Date: Sat, 26 Apr 2014 17:12:19 +0200 Subject: [PATCH 2/2] 100% Haddock --- src/Importer/IQM/Parser.hs | 16 ++++++++++++++++ src/Importer/IQM/Types.hs | 13 ++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Importer/IQM/Parser.hs b/src/Importer/IQM/Parser.hs index 0295516..1d5b9fe 100644 --- a/src/Importer/IQM/Parser.hs +++ b/src/Importer/IQM/Parser.hs @@ -196,6 +196,9 @@ skipToCounter a = do put d -- | Parses an IQM-File and handles back the Haskell-Structure +-- +-- Does a 2-Pass-Parsing. Reads in Structure on first pass (O(n))and +-- fills the Structure in a 2nd Pass from Offsets (O(memcpy'd bytes)). parseIQM :: String -> IO IQM parseIQM a = do @@ -212,6 +215,11 @@ parseIQM a = vertexArrays = va' } +-- | Allocates memory for the Vertex-data and copies it over there +-- from the given input-String +-- +-- Note: The String-Operations are O(1), so only O(numberOfCopiedBytes) +-- is needed in term of computation. readInVAO :: ByteString -> IQMVertexArray -> IO IQMVertexArray readInVAO d (IQMVertexArray type' a format num offset ptr) = do @@ -225,6 +233,10 @@ readInVAO d (IQMVertexArray type' a format num offset ptr) = unsafeUseAsCString data' (\s -> copyBytes p s byteLen) return $ IQMVertexArray type' a format num offset $ castPtr p +-- | Real internal Parser. +-- +-- Consumes the String only once, thus in O(n). But all Data-Structures are +-- not allocated and copied. readInVAO has to be called on each one. doIQMparse :: Parser IQM doIQMparse = flip evalStateT 0 $ --evaluate parser with state starting at 0 @@ -244,5 +256,9 @@ doIQMparse = , vertexArrays = vaf } +-- | Helper-Function for Extracting a random substring out of a Bytestring +-- by the Offsets provided. +-- +-- O(1). skipDrop :: Int -> Int -> ByteString -> ByteString skipDrop a b= B.drop b . B.take a diff --git a/src/Importer/IQM/Types.hs b/src/Importer/IQM/Types.hs index 01ec020..847320f 100644 --- a/src/Importer/IQM/Types.hs +++ b/src/Importer/IQM/Types.hs @@ -20,10 +20,19 @@ newtype Mesh = Mesh Word32 deriving (Show, Eq) -- Bytes read for offset-gap reasons type CParser a = StateT Int64 Parser a +-- | Alias type Flags = GLbitfield -- ^ Alias for UInt32 + +-- | Alias type Offset = Word32 -- ^ Alias for UInt32 + +-- | Alias type Index = GLuint -- ^ Alias for UInt32 + +-- | Alias type NumComponents = GLsizei -- ^ Alias for UInt32 + +-- | Data-BLOB inside IQM type IQMData = Ptr IQMVertexArrayFormat -- ^ Pointer for Data -- | Header of IQM-Format. @@ -104,7 +113,6 @@ data IQM = IQM -- | Different Vertex-Array-Types in IQM -- -- Custom Types have to be > 0x10 as of specification - data IQMVertexArrayType = IQMPosition | IQMTexCoord | IQMNormal @@ -116,7 +124,6 @@ data IQMVertexArrayType = IQMPosition deriving (Show, Eq) -- | Lookup-Function for internal enum to VertexArrayFormat - rawEnumToVAT :: Word32 -> CParser IQMVertexArrayType rawEnumToVAT 0 = return IQMPosition rawEnumToVAT 1 = return IQMTexCoord @@ -140,6 +147,7 @@ data IQMVertexArrayFormat = IQMbyte -- | Unknown Word32 deriving (Show, Eq) +-- | Get the Size (in Bytes) of the given IQMVertexArrayFormat-Struct vaSize :: IQMVertexArrayFormat -> Int vaSize IQMbyte = sizeOf (undefined :: CSChar) vaSize IQMubyte = sizeOf (undefined :: CUChar) @@ -156,7 +164,6 @@ vaSize IQMdouble = sizeOf (undefined :: CDouble) --mallocVArray IQMubyte n = mallocArray n :: IO (Ptr CUChar) -- | Lookup-Function for internal enum to VertexArrayFormat - rawEnumToVAF :: Word32 -> CParser IQMVertexArrayFormat rawEnumToVAF 0 = return IQMbyte rawEnumToVAF 1 = return IQMubyte