packages feed

gltf-loader 0.2.0.1 → 0.3.0.0

raw patch · 26 files changed

+2039/−976 lines, 26 filesbinary-addedPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Text.GLTF.Loader: fromByteString :: MonadUnliftIO io => ByteString -> io (Either Errors Gltf)
- Text.GLTF.Loader: fromFile :: MonadUnliftIO io => FilePath -> io (Either Errors Gltf)
- Text.GLTF.Loader.Adapter: adaptAlphaMode :: MaterialAlphaMode -> MaterialAlphaMode
- Text.GLTF.Loader.Adapter: adaptAsset :: Asset -> Asset
- Text.GLTF.Loader.Adapter: adaptGltf :: GlTF -> Vector GltfBuffer -> Gltf
- Text.GLTF.Loader.Adapter: adaptMaterial :: Material -> Material
- Text.GLTF.Loader.Adapter: adaptMaterials :: Maybe (Vector Material) -> Vector Material
- Text.GLTF.Loader.Adapter: adaptMesh :: GlTF -> Vector GltfBuffer -> Mesh -> Mesh
- Text.GLTF.Loader.Adapter: adaptMeshPrimitive :: GlTF -> Vector GltfBuffer -> MeshPrimitive -> MeshPrimitive
- Text.GLTF.Loader.Adapter: adaptMeshPrimitiveMode :: MeshPrimitiveMode -> MeshPrimitiveMode
- Text.GLTF.Loader.Adapter: adaptMeshPrimitives :: GlTF -> Vector GltfBuffer -> Vector MeshPrimitive -> Vector MeshPrimitive
- Text.GLTF.Loader.Adapter: adaptMeshes :: GlTF -> Vector GltfBuffer -> Maybe (Vector Mesh) -> Vector Mesh
- Text.GLTF.Loader.Adapter: adaptNode :: Node -> Node
- Text.GLTF.Loader.Adapter: adaptNodes :: Maybe (Vector Node) -> Vector Node
- Text.GLTF.Loader.Adapter: adaptPbrMetallicRoughness :: PbrMetallicRoughness -> PbrMetallicRoughness
- Text.GLTF.Loader.Adapter: attributeNormal :: Text
- Text.GLTF.Loader.Adapter: attributePosition :: Text
- Text.GLTF.Loader.Adapter: attributeTexCoord :: Text
- Text.GLTF.Loader.BufferAccessor: GltfBuffer :: ByteString -> GltfBuffer
- Text.GLTF.Loader.BufferAccessor: [unBuffer] :: GltfBuffer -> ByteString
- Text.GLTF.Loader.BufferAccessor: instance GHC.Classes.Eq Text.GLTF.Loader.BufferAccessor.GltfBuffer
- Text.GLTF.Loader.BufferAccessor: instance GHC.Show.Show Text.GLTF.Loader.BufferAccessor.GltfBuffer
- Text.GLTF.Loader.BufferAccessor: loadBuffers :: MonadUnliftIO io => GlTF -> io (Vector GltfBuffer)
- Text.GLTF.Loader.BufferAccessor: newtype GltfBuffer
- Text.GLTF.Loader.BufferAccessor: vertexIndices :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector Int
- Text.GLTF.Loader.BufferAccessor: vertexNormals :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)
- Text.GLTF.Loader.BufferAccessor: vertexPositions :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)
- Text.GLTF.Loader.BufferAccessor: vertexTexCoords :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V2 Float)
- Text.GLTF.Loader.Decoders: getByte :: Get Int8
- Text.GLTF.Loader.Decoders: getFloat :: Get Float
- Text.GLTF.Loader.Decoders: getIndices :: Get (Vector Int)
- Text.GLTF.Loader.Decoders: getMat2 :: Get a -> Get (Vector (M22 a))
- Text.GLTF.Loader.Decoders: getMat3 :: Get a -> Get (Vector (M33 a))
- Text.GLTF.Loader.Decoders: getMat4 :: Get a -> Get (Vector (M44 a))
- Text.GLTF.Loader.Decoders: getNormals :: Get (Vector (V3 Float))
- Text.GLTF.Loader.Decoders: getPositions :: Get (Vector (V3 Float))
- Text.GLTF.Loader.Decoders: getScalar :: Get a -> Get (Vector a)
- Text.GLTF.Loader.Decoders: getShort :: Get Int16
- Text.GLTF.Loader.Decoders: getTexCoords :: Get (Vector (V2 Float))
- Text.GLTF.Loader.Decoders: getUnsignedByte :: Get Word8
- Text.GLTF.Loader.Decoders: getUnsignedInt :: Get Word32
- Text.GLTF.Loader.Decoders: getUnsignedShort :: Get Word16
- Text.GLTF.Loader.Decoders: getVec2 :: Get a -> Get (Vector (V2 a))
- Text.GLTF.Loader.Decoders: getVec3 :: Get a -> Get (Vector (V3 a))
- Text.GLTF.Loader.Decoders: getVec4 :: Get a -> Get (Vector (V4 a))
+ Text.GLTF.Loader: fromBinaryByteString :: MonadUnliftIO io => ByteString -> io (Either Errors Glb)
+ Text.GLTF.Loader: fromBinaryFile :: MonadUnliftIO io => FilePath -> io (Either Errors Glb)
+ Text.GLTF.Loader: fromJsonByteString :: MonadUnliftIO io => ByteString -> io (Either Errors Gltf)
+ Text.GLTF.Loader: fromJsonFile :: MonadUnliftIO io => FilePath -> io (Either Errors Gltf)
+ Text.GLTF.Loader.Glb: Glb :: Gltf -> Glb
+ Text.GLTF.Loader.Glb: [unGltf] :: Glb -> Gltf
+ Text.GLTF.Loader.Glb: _gltf :: Lens' Glb Gltf
+ Text.GLTF.Loader.Glb: instance GHC.Classes.Eq Text.GLTF.Loader.Glb.Glb
+ Text.GLTF.Loader.Glb: instance GHC.Show.Show Text.GLTF.Loader.Glb.Glb
+ Text.GLTF.Loader.Glb: newtype Glb
+ Text.GLTF.Loader.Gltf: ClampToEdge :: SamplerWrap
+ Text.GLTF.Loader.Gltf: Image :: Maybe ByteString -> Text -> Maybe Text -> Image
+ Text.GLTF.Loader.Gltf: MagLinear :: MagFilter
+ Text.GLTF.Loader.Gltf: MagNearest :: MagFilter
+ Text.GLTF.Loader.Gltf: MinLinear :: MinFilter
+ Text.GLTF.Loader.Gltf: MinLinearMipmapLinear :: MinFilter
+ Text.GLTF.Loader.Gltf: MinLinearMipmapNearest :: MinFilter
+ Text.GLTF.Loader.Gltf: MinNearest :: MinFilter
+ Text.GLTF.Loader.Gltf: MinNearestMipmapLinear :: MinFilter
+ Text.GLTF.Loader.Gltf: MinNearestMipmapNearest :: MinFilter
+ Text.GLTF.Loader.Gltf: MirroredRepeat :: SamplerWrap
+ Text.GLTF.Loader.Gltf: Repeat :: SamplerWrap
+ Text.GLTF.Loader.Gltf: Sampler :: Maybe MagFilter -> Maybe MinFilter -> Maybe Text -> SamplerWrap -> SamplerWrap -> Sampler
+ Text.GLTF.Loader.Gltf: Texture :: Maybe Text -> Maybe Int -> Maybe Int -> Texture
+ Text.GLTF.Loader.Gltf: TextureInfo :: Int -> Int -> TextureInfo
+ Text.GLTF.Loader.Gltf: [gltfImages] :: Gltf -> Vector Image
+ Text.GLTF.Loader.Gltf: [gltfSamplers] :: Gltf -> Vector Sampler
+ Text.GLTF.Loader.Gltf: [gltfTextures] :: Gltf -> Vector Texture
+ Text.GLTF.Loader.Gltf: [imageData] :: Image -> Maybe ByteString
+ Text.GLTF.Loader.Gltf: [imageMimeType] :: Image -> Text
+ Text.GLTF.Loader.Gltf: [imageName] :: Image -> Maybe Text
+ Text.GLTF.Loader.Gltf: [nodeChildren] :: Node -> Vector Int
+ Text.GLTF.Loader.Gltf: [pbrBaseColorTexture] :: PbrMetallicRoughness -> Maybe TextureInfo
+ Text.GLTF.Loader.Gltf: [samplerMagFilter] :: Sampler -> Maybe MagFilter
+ Text.GLTF.Loader.Gltf: [samplerMinFilter] :: Sampler -> Maybe MinFilter
+ Text.GLTF.Loader.Gltf: [samplerName] :: Sampler -> Maybe Text
+ Text.GLTF.Loader.Gltf: [samplerWrapS] :: Sampler -> SamplerWrap
+ Text.GLTF.Loader.Gltf: [samplerWrapT] :: Sampler -> SamplerWrap
+ Text.GLTF.Loader.Gltf: [textureId] :: TextureInfo -> Int
+ Text.GLTF.Loader.Gltf: [textureName] :: Texture -> Maybe Text
+ Text.GLTF.Loader.Gltf: [textureSamplerId] :: Texture -> Maybe Int
+ Text.GLTF.Loader.Gltf: [textureSourceId] :: Texture -> Maybe Int
+ Text.GLTF.Loader.Gltf: [textureTexCoord] :: TextureInfo -> Int
+ Text.GLTF.Loader.Gltf: _imageData :: Lens' Image (Maybe ByteString)
+ Text.GLTF.Loader.Gltf: _imageMimeType :: Lens' Image Text
+ Text.GLTF.Loader.Gltf: _imageName :: Lens' Image (Maybe Text)
+ Text.GLTF.Loader.Gltf: _images :: Lens' Gltf (Vector Image)
+ Text.GLTF.Loader.Gltf: _nodeChildren :: Lens' Node (Vector Int)
+ Text.GLTF.Loader.Gltf: _pbrBaseColorTexture :: Lens' PbrMetallicRoughness (Maybe TextureInfo)
+ Text.GLTF.Loader.Gltf: _samplerMagFilter :: Lens' Sampler (Maybe MagFilter)
+ Text.GLTF.Loader.Gltf: _samplerMinFilter :: Lens' Sampler (Maybe MinFilter)
+ Text.GLTF.Loader.Gltf: _samplerName :: Lens' Sampler (Maybe Text)
+ Text.GLTF.Loader.Gltf: _samplerWrapS :: Lens' Sampler SamplerWrap
+ Text.GLTF.Loader.Gltf: _samplerWrapT :: Lens' Sampler SamplerWrap
+ Text.GLTF.Loader.Gltf: _samplers :: Lens' Gltf (Vector Sampler)
+ Text.GLTF.Loader.Gltf: _textureInfoId :: Lens' TextureInfo Int
+ Text.GLTF.Loader.Gltf: _textureInfoTexCoord :: Lens' TextureInfo Int
+ Text.GLTF.Loader.Gltf: _textureName :: Lens' Texture (Maybe Text)
+ Text.GLTF.Loader.Gltf: _textureSamplerId :: Lens' Texture (Maybe Int)
+ Text.GLTF.Loader.Gltf: _textureSourceId :: Lens' Texture (Maybe Int)
+ Text.GLTF.Loader.Gltf: _textures :: Lens' Gltf (Vector Texture)
+ Text.GLTF.Loader.Gltf: data Image
+ Text.GLTF.Loader.Gltf: data MagFilter
+ Text.GLTF.Loader.Gltf: data MinFilter
+ Text.GLTF.Loader.Gltf: data Sampler
+ Text.GLTF.Loader.Gltf: data SamplerWrap
+ Text.GLTF.Loader.Gltf: data Texture
+ Text.GLTF.Loader.Gltf: data TextureInfo
+ Text.GLTF.Loader.Gltf: instance GHC.Classes.Eq Text.GLTF.Loader.Gltf.Image
+ Text.GLTF.Loader.Gltf: instance GHC.Classes.Eq Text.GLTF.Loader.Gltf.MagFilter
+ Text.GLTF.Loader.Gltf: instance GHC.Classes.Eq Text.GLTF.Loader.Gltf.MinFilter
+ Text.GLTF.Loader.Gltf: instance GHC.Classes.Eq Text.GLTF.Loader.Gltf.Sampler
+ Text.GLTF.Loader.Gltf: instance GHC.Classes.Eq Text.GLTF.Loader.Gltf.SamplerWrap
+ Text.GLTF.Loader.Gltf: instance GHC.Classes.Eq Text.GLTF.Loader.Gltf.Texture
+ Text.GLTF.Loader.Gltf: instance GHC.Classes.Eq Text.GLTF.Loader.Gltf.TextureInfo
+ Text.GLTF.Loader.Gltf: instance GHC.Enum.Enum Text.GLTF.Loader.Gltf.MagFilter
+ Text.GLTF.Loader.Gltf: instance GHC.Enum.Enum Text.GLTF.Loader.Gltf.MinFilter
+ Text.GLTF.Loader.Gltf: instance GHC.Enum.Enum Text.GLTF.Loader.Gltf.SamplerWrap
+ Text.GLTF.Loader.Gltf: instance GHC.Show.Show Text.GLTF.Loader.Gltf.Image
+ Text.GLTF.Loader.Gltf: instance GHC.Show.Show Text.GLTF.Loader.Gltf.MagFilter
+ Text.GLTF.Loader.Gltf: instance GHC.Show.Show Text.GLTF.Loader.Gltf.MinFilter
+ Text.GLTF.Loader.Gltf: instance GHC.Show.Show Text.GLTF.Loader.Gltf.Sampler
+ Text.GLTF.Loader.Gltf: instance GHC.Show.Show Text.GLTF.Loader.Gltf.SamplerWrap
+ Text.GLTF.Loader.Gltf: instance GHC.Show.Show Text.GLTF.Loader.Gltf.Texture
+ Text.GLTF.Loader.Gltf: instance GHC.Show.Show Text.GLTF.Loader.Gltf.TextureInfo
+ Text.GLTF.Loader.Internal.Adapter: adaptAlphaMode :: MaterialAlphaMode -> MaterialAlphaMode
+ Text.GLTF.Loader.Internal.Adapter: adaptAsset :: Asset -> Asset
+ Text.GLTF.Loader.Internal.Adapter: adaptGltf :: Adapter Gltf
+ Text.GLTF.Loader.Internal.Adapter: adaptImage :: GltfImageData -> Image -> Adapter Image
+ Text.GLTF.Loader.Internal.Adapter: adaptImages :: Maybe (Vector Image) -> Adapter (Vector Image)
+ Text.GLTF.Loader.Internal.Adapter: adaptMaterial :: Material -> Material
+ Text.GLTF.Loader.Internal.Adapter: adaptMaterials :: Maybe (Vector Material) -> Vector Material
+ Text.GLTF.Loader.Internal.Adapter: adaptMesh :: Mesh -> Adapter Mesh
+ Text.GLTF.Loader.Internal.Adapter: adaptMeshPrimitive :: MeshPrimitive -> Adapter MeshPrimitive
+ Text.GLTF.Loader.Internal.Adapter: adaptMeshPrimitiveMode :: MeshPrimitiveMode -> MeshPrimitiveMode
+ Text.GLTF.Loader.Internal.Adapter: adaptMeshPrimitives :: Vector MeshPrimitive -> Adapter (Vector MeshPrimitive)
+ Text.GLTF.Loader.Internal.Adapter: adaptMeshes :: Maybe (Vector Mesh) -> Adapter (Vector Mesh)
+ Text.GLTF.Loader.Internal.Adapter: adaptNode :: Node -> Node
+ Text.GLTF.Loader.Internal.Adapter: adaptNodes :: Maybe (Vector Node) -> Vector Node
+ Text.GLTF.Loader.Internal.Adapter: adaptPbrMetallicRoughness :: PbrMetallicRoughness -> PbrMetallicRoughness
+ Text.GLTF.Loader.Internal.Adapter: adaptTexture :: Texture -> Texture
+ Text.GLTF.Loader.Internal.Adapter: adaptTextures :: Maybe (Vector Texture) -> Vector Texture
+ Text.GLTF.Loader.Internal.Adapter: attributeNormal :: Text
+ Text.GLTF.Loader.Internal.Adapter: attributePosition :: Text
+ Text.GLTF.Loader.Internal.Adapter: attributeTexCoord :: Text
+ Text.GLTF.Loader.Internal.Adapter: runAdapter :: GlTF -> Vector GltfBuffer -> Vector GltfImageData -> Gltf
+ Text.GLTF.Loader.Internal.BufferAccessor: GltfBuffer :: ByteString -> GltfBuffer
+ Text.GLTF.Loader.Internal.BufferAccessor: ImageBufferView :: BufferViewIx -> GltfImageData
+ Text.GLTF.Loader.Internal.BufferAccessor: ImageData :: ByteString -> GltfImageData
+ Text.GLTF.Loader.Internal.BufferAccessor: NoImageData :: GltfImageData
+ Text.GLTF.Loader.Internal.BufferAccessor: [unBuffer] :: GltfBuffer -> ByteString
+ Text.GLTF.Loader.Internal.BufferAccessor: data GltfImageData
+ Text.GLTF.Loader.Internal.BufferAccessor: imageDataRaw :: GlTF -> Vector GltfBuffer -> BufferViewIx -> Maybe ByteString
+ Text.GLTF.Loader.Internal.BufferAccessor: instance GHC.Base.Monoid Text.GLTF.Loader.Internal.BufferAccessor.GltfBuffer
+ Text.GLTF.Loader.Internal.BufferAccessor: instance GHC.Base.Semigroup Text.GLTF.Loader.Internal.BufferAccessor.GltfBuffer
+ Text.GLTF.Loader.Internal.BufferAccessor: instance GHC.Classes.Eq Text.GLTF.Loader.Internal.BufferAccessor.GltfBuffer
+ Text.GLTF.Loader.Internal.BufferAccessor: instance GHC.Classes.Eq Text.GLTF.Loader.Internal.BufferAccessor.GltfImageData
+ Text.GLTF.Loader.Internal.BufferAccessor: instance GHC.Show.Show Text.GLTF.Loader.Internal.BufferAccessor.GltfBuffer
+ Text.GLTF.Loader.Internal.BufferAccessor: instance GHC.Show.Show Text.GLTF.Loader.Internal.BufferAccessor.GltfImageData
+ Text.GLTF.Loader.Internal.BufferAccessor: loadBuffers :: MonadUnliftIO io => GlTF -> Maybe Chunk -> FilePath -> io (Vector GltfBuffer)
+ Text.GLTF.Loader.Internal.BufferAccessor: loadImages :: MonadUnliftIO io => GlTF -> FilePath -> io (Vector GltfImageData)
+ Text.GLTF.Loader.Internal.BufferAccessor: newtype GltfBuffer
+ Text.GLTF.Loader.Internal.BufferAccessor: vertexIndices :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector Word16
+ Text.GLTF.Loader.Internal.BufferAccessor: vertexNormals :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)
+ Text.GLTF.Loader.Internal.BufferAccessor: vertexPositions :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)
+ Text.GLTF.Loader.Internal.BufferAccessor: vertexTexCoords :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V2 Float)
+ Text.GLTF.Loader.Internal.Decoders: getByte :: Get Int8
+ Text.GLTF.Loader.Internal.Decoders: getFloat :: Get Float
+ Text.GLTF.Loader.Internal.Decoders: getIndices :: Get (Vector Word16)
+ Text.GLTF.Loader.Internal.Decoders: getMat2 :: Get a -> Get (Vector (M22 a))
+ Text.GLTF.Loader.Internal.Decoders: getMat3 :: Get a -> Get (Vector (M33 a))
+ Text.GLTF.Loader.Internal.Decoders: getMat4 :: Get a -> Get (Vector (M44 a))
+ Text.GLTF.Loader.Internal.Decoders: getNormals :: Get (Vector (V3 Float))
+ Text.GLTF.Loader.Internal.Decoders: getPositions :: Get (Vector (V3 Float))
+ Text.GLTF.Loader.Internal.Decoders: getScalar :: Get a -> Get (Vector a)
+ Text.GLTF.Loader.Internal.Decoders: getShort :: Get Int16
+ Text.GLTF.Loader.Internal.Decoders: getTexCoords :: Get (Vector (V2 Float))
+ Text.GLTF.Loader.Internal.Decoders: getUnsignedByte :: Get Word8
+ Text.GLTF.Loader.Internal.Decoders: getUnsignedInt :: Get Word32
+ Text.GLTF.Loader.Internal.Decoders: getUnsignedShort :: Get Word16
+ Text.GLTF.Loader.Internal.Decoders: getVec2 :: Get a -> Get (Vector (V2 a))
+ Text.GLTF.Loader.Internal.Decoders: getVec3 :: Get a -> Get (Vector (V3 a))
+ Text.GLTF.Loader.Internal.Decoders: getVec4 :: Get a -> Get (Vector (V4 a))
+ Text.GLTF.Loader.Internal.MonadAdapter: AdaptEnv :: GlTF -> Vector GltfBuffer -> Vector GltfImageData -> AdaptEnv
+ Text.GLTF.Loader.Internal.MonadAdapter: [asBuffers] :: AdaptEnv -> Vector GltfBuffer
+ Text.GLTF.Loader.Internal.MonadAdapter: [asGltf] :: AdaptEnv -> GlTF
+ Text.GLTF.Loader.Internal.MonadAdapter: [asImages] :: AdaptEnv -> Vector GltfImageData
+ Text.GLTF.Loader.Internal.MonadAdapter: data AdaptEnv
+ Text.GLTF.Loader.Internal.MonadAdapter: getBuffers :: Reader AdaptEnv (Vector GltfBuffer)
+ Text.GLTF.Loader.Internal.MonadAdapter: getGltf :: Reader AdaptEnv GlTF
+ Text.GLTF.Loader.Internal.MonadAdapter: getImages :: Reader AdaptEnv (Vector GltfImageData)
+ Text.GLTF.Loader.Internal.MonadAdapter: type Adapter = Reader AdaptEnv
- Text.GLTF.Loader.Gltf: Gltf :: Asset -> Vector Material -> Vector Mesh -> Vector Node -> Gltf
+ Text.GLTF.Loader.Gltf: Gltf :: Asset -> Vector Image -> Vector Material -> Vector Mesh -> Vector Node -> Vector Sampler -> Vector Texture -> Gltf
- Text.GLTF.Loader.Gltf: Mesh :: Vector MeshPrimitive -> Vector Float -> Maybe Text -> Mesh
+ Text.GLTF.Loader.Gltf: Mesh :: Maybe Text -> Vector MeshPrimitive -> Vector Float -> Mesh
- Text.GLTF.Loader.Gltf: MeshPrimitive :: Vector Int -> Maybe Int -> MeshPrimitiveMode -> Vector (V3 Float) -> Vector (V3 Float) -> Vector (V2 Float) -> MeshPrimitive
+ Text.GLTF.Loader.Gltf: MeshPrimitive :: Vector Word16 -> Maybe Int -> MeshPrimitiveMode -> Vector (V3 Float) -> Vector (V3 Float) -> Vector (V2 Float) -> MeshPrimitive
- Text.GLTF.Loader.Gltf: Node :: Maybe Int -> Maybe Text -> Maybe (V4 Float) -> Maybe (V3 Float) -> Maybe (V3 Float) -> [Float] -> Node
+ Text.GLTF.Loader.Gltf: Node :: Vector Int -> Maybe Int -> Maybe Text -> Maybe (V4 Float) -> Maybe (V3 Float) -> Maybe (V3 Float) -> [Float] -> Node
- Text.GLTF.Loader.Gltf: PbrMetallicRoughness :: V4 Float -> Float -> Float -> PbrMetallicRoughness
+ Text.GLTF.Loader.Gltf: PbrMetallicRoughness :: V4 Float -> Maybe TextureInfo -> Float -> Float -> PbrMetallicRoughness
- Text.GLTF.Loader.Gltf: [meshPrimitiveIndices] :: MeshPrimitive -> Vector Int
+ Text.GLTF.Loader.Gltf: [meshPrimitiveIndices] :: MeshPrimitive -> Vector Word16
- Text.GLTF.Loader.Gltf: _meshPrimitiveIndices :: Lens' MeshPrimitive (Vector Int)
+ Text.GLTF.Loader.Gltf: _meshPrimitiveIndices :: Lens' MeshPrimitive (Vector Word16)

Files

README.md view
@@ -4,7 +4,6 @@  > A high level GlTF loader - ## Prerequisites  In order to build or install you will need@@ -57,20 +56,20 @@ Currently, only geometries and PBR materials are supported, but we hope to support the majority of GlTF features: - - [ ] Animitions+ - [ ] Animations  - [x] Asset  - [ ] Cameras- - [ ] Images- - [ ] Materials+ - [x] Images+ - [x] Materials    - [x] PBR Metallic Roughness-   - [ ] Textures+   - [x] Textures  - [x] Meshes     - [x] Positions     - [x] Indices     - [x] Normals     - [x] Texture Coordinates  - [x] Nodes- - [ ] Samplers+ - [x] Samplers  - [ ] Skins  ## Authors
app/Command/GLTF/Loader/App.hs view
@@ -5,7 +5,8 @@  -- | Command line arguments data Options = Options-  { optionsSummary :: !Bool,+  { optionsBinary :: !Bool,+    optionsSummary :: !Bool,     optionsVerbose :: !Bool,     optionsFile :: FilePath   }@@ -28,6 +29,11 @@  instance HasOptions App where   optionsL = lens appOptions (\app opts -> app { appOptions = opts })++_optionsBinary :: Lens' Options Bool+_optionsBinary = lens+  optionsBinary+  (\opts bin -> opts { optionsBinary = bin })  _optionsSummary :: Lens' Options Bool _optionsSummary = lens
app/Command/GLTF/Loader/Run.hs view
@@ -13,8 +13,12 @@ run = do   options <- asks (^. optionsL)   let file = options ^. _optionsFile+      binary = options ^. _optionsBinary       summary = options ^. _optionsSummary       verbose = options ^. _optionsVerbose+      fromFile = if binary+        then fmap (over _Right (^. _gltf)) . fromBinaryFile+        else fromJsonFile    logInfo $ "File: " <> fromString file   result <- liftIO $ fromFile file@@ -80,12 +84,18 @@   forM_ (mesh ^. _meshPrimitives) $ \primitive' -> do     -- Report Vertices     logInfo "      Vertices:"-+         let positions = primitive' ^. _meshPrimitivePositions     forM_ (primitive' ^. _meshPrimitiveIndices) $ \index -> do-      forM_ (positions Vector.!? index) $ \position -> do+      forM_ (positions Vector.!? fromIntegral index) $ \position -> do         logInfo $ "        [" <> display index <> "]: " <> displayV3 position +    logInfo "      Normals:"+    let normals = primitive' ^. _meshPrimitiveNormals+    forM_ (primitive' ^. _meshPrimitiveIndices) $ \index -> do+      forM_ (normals Vector.!? fromIntegral index) $ \normal -> do+        logInfo $ "        [" <> display index <> "]: " <> displayV3 normal+     -- Report material     forM_ (primitive' ^. _meshPrimitiveMaterial) $ \materialId -> do       forM_ (gltf ^. _materials . to (Vector.!? materialId)) reportMaterial@@ -118,7 +128,7 @@  reportMaterial :: Material -> RIO App () reportMaterial material = do-  logInfo $ "      Material:"+  logInfo "      Material:"   logInfo $ "        Name: " <>     material ^. _materialName . to (display . fromMaybe "Unknown")   
app/Main.hs view
@@ -40,9 +40,15 @@  options :: Parser Options options = Options-  <$> switch summaryOption+  <$> switch binaryOption+  <*> switch summaryOption   <*> switch verboseOption   <*> strArgument fileArg++binaryOption :: Mod FlagFields Bool+binaryOption = long "binary"+  <> short 'b'+  <> help "Load file as GLB (Binary glTF)"  summaryOption :: Mod FlagFields Bool summaryOption
+ data/Untitled.png view

binary file changed (absent → 20559 bytes)

+ data/cube-separate.bin view

binary file changed (absent → 840 bytes)

+ data/cube-separate.gltf view
@@ -0,0 +1,137 @@+{+    "asset" : {+        "generator" : "Khronos glTF Blender I/O v3.3.27",+        "version" : "2.0"+    },+    "scene" : 0,+    "scenes" : [+        {+            "name" : "Scene",+            "nodes" : [+                0+            ]+        }+    ],+    "nodes" : [+        {+            "mesh" : 0,+            "name" : "Cube"+        }+    ],+    "materials" : [+        {+            "doubleSided" : true,+            "name" : "Material",+            "pbrMetallicRoughness" : {+                "baseColorTexture" : {+                    "index" : 0+                },+                "metallicFactor" : 0,+                "roughnessFactor" : 0.5+            }+        }+    ],+    "meshes" : [+        {+            "name" : "Cube",+            "primitives" : [+                {+                    "attributes" : {+                        "POSITION" : 0,+                        "NORMAL" : 1,+                        "TEXCOORD_0" : 2+                    },+                    "indices" : 3,+                    "material" : 0+                }+            ]+        }+    ],+    "textures" : [+        {+            "sampler" : 0,+            "source" : 0+        }+    ],+    "images" : [+        {+            "mimeType" : "image/png",+            "name" : "Untitled",+            "uri" : "Untitled.png"+        }+    ],+    "accessors" : [+        {+            "bufferView" : 0,+            "componentType" : 5126,+            "count" : 24,+            "max" : [+                1,+                1,+                1+            ],+            "min" : [+                -1,+                -1,+                -1+            ],+            "type" : "VEC3"+        },+        {+            "bufferView" : 1,+            "componentType" : 5126,+            "count" : 24,+            "type" : "VEC3"+        },+        {+            "bufferView" : 2,+            "componentType" : 5126,+            "count" : 24,+            "type" : "VEC2"+        },+        {+            "bufferView" : 3,+            "componentType" : 5123,+            "count" : 36,+            "type" : "SCALAR"+        }+    ],+    "bufferViews" : [+        {+            "buffer" : 0,+            "byteLength" : 288,+            "byteOffset" : 0,+            "target" : 34962+        },+        {+            "buffer" : 0,+            "byteLength" : 288,+            "byteOffset" : 288,+            "target" : 34962+        },+        {+            "buffer" : 0,+            "byteLength" : 192,+            "byteOffset" : 576,+            "target" : 34962+        },+        {+            "buffer" : 0,+            "byteLength" : 72,+            "byteOffset" : 768,+            "target" : 34963+        }+    ],+    "samplers" : [+        {+            "magFilter" : 9729,+            "minFilter" : 9987+        }+    ],+    "buffers" : [+        {+            "byteLength" : 840,+            "uri" : "cube-separate.bin"+        }+    ]+}
+ data/cube.glb view

binary file changed (absent → 22660 bytes)

data/cube.gltf view
@@ -1,6 +1,6 @@ {     "asset" : {-        "generator" : "Khronos glTF Blender I/O v3.2.40",+        "generator" : "Khronos glTF Blender I/O v3.3.27",         "version" : "2.0"     },     "scene" : 0,@@ -23,14 +23,11 @@             "doubleSided" : true,             "name" : "Material",             "pbrMetallicRoughness" : {-                "baseColorFactor" : [-                    0.800000011920929,-                    0.800000011920929,-                    0.800000011920929,-                    1-                ],+                "baseColorTexture" : {+                    "index" : 0+                },                 "metallicFactor" : 0,-                "roughnessFactor" : 0.4000000059604645+                "roughnessFactor" : 0.5             }         }     ],@@ -50,6 +47,19 @@             ]         }     ],+    "textures" : [+        {+            "sampler" : 0,+            "source" : 0+        }+    ],+    "images" : [+        {+            "bufferView" : 4,+            "mimeType" : "image/png",+            "name" : "Untitled"+        }+    ],     "accessors" : [         {             "bufferView" : 0,@@ -90,28 +100,43 @@         {             "buffer" : 0,             "byteLength" : 288,-            "byteOffset" : 0+            "byteOffset" : 0,+            "target" : 34962         },         {             "buffer" : 0,             "byteLength" : 288,-            "byteOffset" : 288+            "byteOffset" : 288,+            "target" : 34962         },         {             "buffer" : 0,             "byteLength" : 192,-            "byteOffset" : 576+            "byteOffset" : 576,+            "target" : 34962         },         {             "buffer" : 0,             "byteLength" : 72,-            "byteOffset" : 768+            "byteOffset" : 768,+            "target" : 34963+        },+        {+            "buffer" : 0,+            "byteLength" : 20559,+            "byteOffset" : 840         }     ],+    "samplers" : [+        {+            "magFilter" : 9729,+            "minFilter" : 9987+        }+    ],     "buffers" : [         {-            "byteLength" : 840,-            "uri" : "data:application/octet-stream;base64,AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAQAOABQAAQAUAAcACgAGABMACgATABcAFQASAAwAFQAMAA8AEAADAAkAEAAJABYABQACAAgABQAIAAsAEQANAAAAEQAAAAQA"+            "byteLength" : 21400,+            "uri" : "data:application/octet-stream;base64,AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAQAOABQAAQAUAAcACgAGABMACgATABcAFQASAAwAFQAMAA8AEAADAAkAEAAJABYABQACAAgABQAIAAsAEQANAAAAEQAAAAQAiVBORw0KGgoAAAANSUhEUgAABAAAAAQACAYAAAB/HSuDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAgAElEQVR4AezYQREAIAwDQcC/Z2CQwW0dZNNX5r43HAECBAgQIECAAAECBAgQIPC1wPo6nXAECBAgQIAAAQIECBAgQIDAEzAAeAQCBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAvxMergAACAASURBVAQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgNt3nXAAAD+lJREFUQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIECAAAECBAgQIGAA8AMECBAgQIAAAQIECBAgQCAgYAAIlCwiAQIECBAgQIAAAQIECBAwAPgBAgQIECBAgAABAgQIECAQEDAABEoWkQABAgQIECBAgAABAgQIGAD8AAECBAgQIECAAAECBAgQCAgYAAIli0iAAAECBAgQIECAAAECBAwAfoAAAQIECBAgQIAAAQIECAQEDACBkkUkQIAAAQIECBAgQIAAAQIGAD9AgAABAgQIECBAgAABAgQCAgaAQMkiEiBAgAABAgQIECBAgAABA4AfIECAAAECBAgQIECAAAECAQEDQKBkEQkQIECAAAECBAgQIECAgAHADxAgQIAAAQIECBAgQIAAgYCAASBQsogECBAgQIAAAQIECBAgQMAA4AcIECBAgAABAgQIECBAgEBAwAAQKFlEAgQIECBAgAABAgQIECBgAPADBAgQIECAAAECBAgQIEAgIGAACJQsIgECBAgQIECAAAECBAgQMAD4AQIECBAgQIAAAQIECBAgEBAwAARKFpEAAQIECBAgQIAAAQIECBgA/AABAgQIECBAgAABAgQIEAgIGAACJYtIgAABAgQIECBAgAABAgQMAH6AAAECBAgQIECAAAECBAgEBAwAgZJFJECAAAECBAgQIECAAAECBgA/QIAAAQIECBAgQIAAAQIEAgIGgEDJIhIgQIAAAQIECBAgQIAAAQOAHyBAgAABAgQIECBAgAABAgEBA0CgZBEJECBAgAABAgQIECBAgIABwA8QIECAAAECBAgQIECAAIGAgAEgULKIBAgQIECAAAECBAgQIEDAAOAHCBAgQIAAAQIECBAgQIBAQMAAEChZRAIECBAgQIAAAQIECBAgYADwAwQIECBAgAABAgQIECBAICBgAAiULCIBAgQIECBAgAABAgQIEDAA+AECBAgQIECAAAECBAgQIBAQMAAEShaRAAECBAgQIECAAAECBAgYAPwAAQIECBAgQIAAAQIECBAICBgAAiWLSIAAAQIECBAgQIAAAQIEDAB+gAABAgQIECBAgAABAgQIBAQMAIGSRSRAgAABAgQIECBAgAABAgYAP0CAAAECBAgQIECAAAECBAICBoBAySISIECAAAECBAgQIECAAAEDgB8gQIAAAQIECBAgQIAAAQIBAQNAoGQRCRAgQIAAAQIECBAgQICAAcAPECBAgAABAgQIECBAgACBgIABIFCyiAQIECBAgAABAgQIECBAwADgBwgQIECAAAECBAgQIECAQEDAABAoWUQCBAgQIEDgbDQERkNgNARGQ2A0BEZDYDQEAOJdC/zeE7NaAAAAAElFTkSuQmCCAA=="         }     ] }
gltf-loader.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.7.+-- This file has been generated from package.yaml by hpack version 0.35.0. -- -- see: https://github.com/sol/hpack  name:           gltf-loader-version:        0.2.0.1+version:        0.3.0.0 synopsis:       High level GlTF loader description:    Please see the README on Github at <https://github.com/sgillespie/haskell-gltf-loader#readme> category:       Graphics@@ -20,8 +20,12 @@ extra-source-files:     README.md     data/big-cube.gltf+    data/cube-separate.bin+    data/cube-separate.gltf+    data/cube.glb     data/cube.gltf     data/invalid.gltf+    data/Untitled.png  source-repository head   type: git@@ -30,11 +34,13 @@ library   exposed-modules:       Text.GLTF.Loader-      Text.GLTF.Loader.Adapter-      Text.GLTF.Loader.BufferAccessor-      Text.GLTF.Loader.Decoders       Text.GLTF.Loader.Errors+      Text.GLTF.Loader.Glb       Text.GLTF.Loader.Gltf+      Text.GLTF.Loader.Internal.Adapter+      Text.GLTF.Loader.Internal.BufferAccessor+      Text.GLTF.Loader.Internal.Decoders+      Text.GLTF.Loader.Internal.MonadAdapter   other-modules:       Paths_gltf_loader   hs-source-dirs:@@ -86,6 +92,7 @@     , gltf-codec     , linear     , microlens+    , microlens-platform     , rio >=0.1.12.0     , unordered-containers   default-language: Haskell2010@@ -153,8 +160,8 @@   type: exitcode-stdio-1.0   main-is: Spec.hs   other-modules:-      Text.GLTF.Loader.AdapterSpec-      Text.GLTF.Loader.BufferAccessorSpec+      Text.GLTF.Loader.Internal.AdapterSpec+      Text.GLTF.Loader.Internal.BufferAccessorSpec       Text.GLTF.Loader.Test.MkGltf       Text.GLTF.LoaderSpec       Paths_gltf_loader@@ -210,6 +217,7 @@     , hspec     , linear     , microlens+    , microlens-platform     , rio >=0.1.12.0     , unordered-containers   default-language: Haskell2010
src/Text/GLTF/Loader.hs view
@@ -1,37 +1,79 @@- module Text.GLTF.Loader   ( -- * Scene loading functions-    fromFile,-    fromByteString,+    fromJsonFile,+    fromJsonByteString,+    fromBinaryFile,+    fromBinaryByteString, -    -- * GLTF Types+    -- * GLTF Data Types     module Text.GLTF.Loader.Gltf,+    module Text.GLTF.Loader.Glb,      -- * Loading Errors     module Text.GLTF.Loader.Errors   ) where -import Text.GLTF.Loader.Adapter-import Text.GLTF.Loader.BufferAccessor+import Text.GLTF.Loader.Internal.Adapter+import Text.GLTF.Loader.Internal.BufferAccessor import Text.GLTF.Loader.Errors+import Text.GLTF.Loader.Glb import Text.GLTF.Loader.Gltf +import Data.Binary.Get (ByteOffset) import Data.Either+import Data.Maybe (fromJust) import Lens.Micro import RIO+import RIO.FilePath (takeDirectory) import qualified Codec.GlTF as GlTF+import qualified Codec.GLB as GLB+import qualified RIO.Vector as Vector  -- | Load a glTF scene from a ByteString-fromByteString :: MonadUnliftIO io => ByteString -> io (Either Errors Gltf)-fromByteString =  toGltfResult . GlTF.fromByteString+fromJsonByteString :: MonadUnliftIO io => ByteString -> io (Either Errors Gltf)+fromJsonByteString input = toGltfResult "." Nothing (GlTF.fromByteString input)  -- | Load a glTF scene from a file-fromFile :: MonadUnliftIO io => FilePath -> io (Either Errors Gltf)-fromFile path = liftIO (GlTF.fromFile path) >>= toGltfResult+fromJsonFile :: MonadUnliftIO io => FilePath -> io (Either Errors Gltf)+fromJsonFile path = liftIO (GlTF.fromFile path) >>= toGltfResult (takeDirectory path) Nothing++fromBinaryFile :: MonadUnliftIO io => FilePath -> io (Either Errors Glb)+fromBinaryFile path = liftIO (GLB.fromFile path) >>= toGlbResult "."   -toGltfResult :: MonadUnliftIO io => Either String GlTF.GlTF -> io (Either Errors Gltf)-toGltfResult res-  = res-    & over _Left (ReadError . fromString)-    & traverseOf _Right toGltfResult'-  where toGltfResult' gltf = adaptGltf gltf <$> loadBuffers gltf+fromBinaryByteString :: MonadUnliftIO io => ByteString -> io (Either Errors Glb)+fromBinaryByteString input = toGlbResult "." (GLB.fromByteString input)++toGltfResult+  :: MonadUnliftIO io+  => FilePath+  -> Maybe GLB.Chunk+  -> Either String GlTF.GlTF+  -> io (Either Errors Gltf)+toGltfResult basePath chunk res = res+  & over _Left (ReadError . fromString)+  & traverseOf _Right (runGltfAdapter basePath chunk)++toGlbResult+  :: MonadUnliftIO io+  => FilePath+  -> Either (ByteOffset, String) GLB.GLB+  -> io (Either Errors Glb)+toGlbResult basePath (Right res) = processGlb basePath res+toGlbResult _        (Left (_, err)) = pure . Left . ReadError . fromString $ err++runGltfAdapter+  :: MonadUnliftIO io+  => FilePath+  -> Maybe GLB.Chunk+  -> GlTF.GlTF+  -> io Gltf+runGltfAdapter basePath chunk gltf = runAdapter gltf+  <$> loadBuffers gltf chunk basePath+  <*> loadImages gltf basePath++processGlb :: MonadUnliftIO io => FilePath -> GLB.GLB -> io (Either Errors Glb)+processGlb basePath GLB.GLB{..} = over _Right Glb <$> res+  where gltfChunk = chunks Vector.!? 0+        bufferChunk = chunks Vector.!? 1+        gltf = GlTF.fromChunk (fromJust gltfChunk)+        res = toGltfResult basePath bufferChunk gltf
− src/Text/GLTF/Loader/Adapter.hs
@@ -1,153 +0,0 @@--- |Transform a `Codec.GlTF.GlTF` to `Text.GLTF.Loader.Gltf.Gltf`-module Text.GLTF.Loader.Adapter-  ( attributePosition,-    attributeNormal,-    attributeTexCoord,-    adaptGltf,-    adaptAsset,-    adaptMaterials,-    adaptMeshes,-    adaptNodes,-    adaptMaterial,-    adaptMesh,-    adaptNode,-    adaptAlphaMode,-    adaptPbrMetallicRoughness,-    adaptMeshPrimitives,-    adaptMeshPrimitive,-    adaptMeshPrimitiveMode-  ) where--import Text.GLTF.Loader.BufferAccessor-import Text.GLTF.Loader.Gltf--import Linear (V3(..), V4(..))-import RIO-import RIO.Partial (toEnum)-import qualified Codec.GlTF as GlTF-import qualified Codec.GlTF.Asset as GlTF.Asset-import qualified Codec.GlTF.Material as GlTF.Material-import qualified Codec.GlTF.PbrMetallicRoughness as GlTF.PbrMetallicRoughness-import qualified Codec.GlTF.Mesh as GlTF.Mesh-import qualified Codec.GlTF.Node as GlTF.Node-import qualified Data.HashMap.Strict as HashMap--attributePosition :: Text-attributePosition = "POSITION"--attributeNormal :: Text-attributeNormal = "NORMAL"--attributeTexCoord :: Text-attributeTexCoord = "TEXCOORD_0"--adaptGltf :: GlTF.GlTF -> Vector GltfBuffer -> Gltf-adaptGltf gltf@GlTF.GlTF{..} buffers' = Gltf-    { gltfAsset = adaptAsset asset,-      gltfMaterials = adaptMaterials materials,-      gltfMeshes = adaptMeshes gltf buffers' meshes,-      gltfNodes = adaptNodes nodes-    }--adaptAsset :: GlTF.Asset.Asset -> Asset-adaptAsset GlTF.Asset.Asset{..} = Asset-  { assetVersion = version,-    assetCopyright = copyright,-    assetGenerator = generator,-    assetMinVersion = minVersion-  }--adaptMaterials :: Maybe (Vector GlTF.Material.Material) -> Vector Material-adaptMaterials = maybe mempty (fmap adaptMaterial)--adaptMeshes-  :: GlTF.GlTF-  -> Vector GltfBuffer-  -> Maybe (Vector GlTF.Mesh.Mesh)-  -> Vector Mesh-adaptMeshes gltf buffers' = maybe mempty (fmap $ adaptMesh gltf buffers')--adaptNodes :: Maybe (Vector GlTF.Node.Node) -> Vector Node-adaptNodes = maybe mempty (fmap adaptNode)--adaptMaterial :: GlTF.Material.Material -> Material-adaptMaterial GlTF.Material.Material{..} = Material-  { materialAlphaCutoff = alphaCutoff,-    materialAlphaMode = adaptAlphaMode alphaMode,-    materialDoubleSided = doubleSided,-    materialEmissiveFactor = toV3 emissiveFactor,-    materialName = name,-    materialPbrMetallicRoughness = adaptPbrMetallicRoughness <$> pbrMetallicRoughness-  }--adaptMesh-  :: GlTF.GlTF-  -> Vector GltfBuffer-  -> GlTF.Mesh.Mesh-  -> Mesh-adaptMesh gltf buffers' GlTF.Mesh.Mesh{..} = Mesh-    { meshPrimitives = adaptMeshPrimitives gltf buffers' primitives,-      meshWeights = fromMaybe mempty weights,-      meshName = name-    }--adaptNode :: GlTF.Node.Node -> Node-adaptNode GlTF.Node.Node{..} = Node-  { nodeMeshId = GlTF.Mesh.unMeshIx <$> mesh,-    nodeName = name,-    nodeRotation = toV4 <$> rotation,-    nodeScale = toV3 <$> scale,-    nodeTranslation = toV3 <$> translation,-    nodeWeights = maybe [] toList weights-  }--adaptAlphaMode :: GlTF.Material.MaterialAlphaMode -> MaterialAlphaMode-adaptAlphaMode GlTF.Material.BLEND = Blend-adaptAlphaMode GlTF.Material.MASK = Mask-adaptAlphaMode GlTF.Material.OPAQUE = Opaque-adaptAlphaMode (GlTF.Material.MaterialAlphaMode alphaMode)-  = error $ "Invalid MaterialAlphaMode: " <> show alphaMode--adaptPbrMetallicRoughness-  :: GlTF.PbrMetallicRoughness.PbrMetallicRoughness-  -> PbrMetallicRoughness-adaptPbrMetallicRoughness GlTF.PbrMetallicRoughness.PbrMetallicRoughness{..}-  = PbrMetallicRoughness-    { pbrBaseColorFactor = toV4 baseColorFactor,-      pbrMetallicFactor = metallicFactor,-      pbrRoughnessFactor = roughnessFactor-    }--adaptMeshPrimitives-  :: GlTF.GlTF-  -> Vector GltfBuffer-  -> Vector GlTF.Mesh.MeshPrimitive-  -> Vector MeshPrimitive-adaptMeshPrimitives gltf = fmap . adaptMeshPrimitive gltf--adaptMeshPrimitive-  :: GlTF.GlTF-  -> Vector GltfBuffer-  -> GlTF.Mesh.MeshPrimitive-  -> MeshPrimitive-adaptMeshPrimitive gltf buffers' GlTF.Mesh.MeshPrimitive{..} = MeshPrimitive-    { meshPrimitiveIndices = maybe mempty (vertexIndices gltf buffers') indices,-      meshPrimitiveMaterial = GlTF.Material.unMaterialIx <$> material,-      meshPrimitiveMode = adaptMeshPrimitiveMode mode,-      meshPrimitiveNormals = maybe mempty (vertexNormals gltf buffers') normals,-      meshPrimitivePositions = maybe mempty (vertexPositions gltf buffers') positions,-      meshPrimitiveTexCoords = maybe mempty (vertexTexCoords gltf buffers') texCoords-    }-    where positions = attributes HashMap.!? attributePosition-          normals = attributes HashMap.!? attributeNormal-          texCoords = attributes HashMap.!? attributeTexCoord-          --adaptMeshPrimitiveMode :: GlTF.Mesh.MeshPrimitiveMode -> MeshPrimitiveMode-adaptMeshPrimitiveMode = toEnum . GlTF.Mesh.unMeshPrimitiveMode--toV3 :: (a, a, a) -> V3 a-toV3 (x, y, z) = V3 x y z--toV4 :: (a, a, a, a) -> V4 a-toV4 (w, x, y, z) = V4 w x y z
− src/Text/GLTF/Loader/BufferAccessor.hs
@@ -1,136 +0,0 @@-module Text.GLTF.Loader.BufferAccessor-  ( GltfBuffer(..),-    -- * Loading GLTF buffers-    loadBuffers,-    -- * Deserializing Accessors-    vertexIndices,-    vertexPositions,-    vertexNormals,-    vertexTexCoords,-  ) where--import Text.GLTF.Loader.Decoders--import Codec.GlTF.Accessor-import Codec.GlTF.Buffer-import Codec.GlTF.BufferView-import Codec.GlTF.URI-import Codec.GlTF-import Data.Binary.Get-import Data.ByteString.Lazy (fromStrict)-import Foreign.Storable-import Linear-import RIO hiding (min, max)-import qualified RIO.Vector as Vector-import qualified RIO.ByteString as ByteString---- | Holds the entire payload of a glTF buffer-newtype GltfBuffer = GltfBuffer { unBuffer :: ByteString }-  deriving (Eq, Show)---- | A buffer and some metadata-data BufferAccessor = BufferAccessor-  { offset :: Int,-    count :: Int,-    buffer :: GltfBuffer-  }---- | Read all the buffers into memory-loadBuffers :: MonadUnliftIO io => GlTF -> io (Vector GltfBuffer)-loadBuffers GlTF{buffers=buffers} = do-  let buffers' = fromMaybe [] buffers--  Vector.forM buffers' $ \Buffer{..} -> do-    payload <--      maybe-      (return "")-      (\uri' -> do-          readRes <- liftIO $ loadURI undefined uri'-          case readRes of-            Left err -> error err-            Right res -> return res)-      uri-    -    return $ GltfBuffer payload---- | Decode vertex indices-vertexIndices :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector Int-vertexIndices = readBufferWithGet getIndices---- | Decode vertex positions-vertexPositions :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)-vertexPositions = readBufferWithGet getPositions---- | Decode vertex normals-vertexNormals :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)-vertexNormals = readBufferWithGet getNormals---- | Decode texture coordinates. Note that we only use the first one.-vertexTexCoords :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V2 Float)-vertexTexCoords = readBufferWithGet getTexCoords---- | Decode a buffer using the given Binary decoder-readBufferWithGet-  :: Storable storable-  => Get (Vector storable)-  -> GlTF-  -> Vector GltfBuffer-  -> AccessorIx-  -> Vector storable-readBufferWithGet getter gltf buffers' accessorId-  = maybe mempty-      (readFromBuffer undefined getter)-      (bufferAccessor gltf buffers' accessorId)---- | Look up a Buffer from a GlTF and AccessorIx-bufferAccessor-  :: GlTF-  -> Vector GltfBuffer-  -> AccessorIx-  -> Maybe BufferAccessor-bufferAccessor GlTF{..} buffers' accessorId = do-  accessor <- lookupAccessor accessorId =<< accessors-  bufferView <- lookupBufferViewFromAccessor accessor =<< bufferViews-  buffer <- lookupBufferFromBufferView bufferView buffers'--  let Accessor{byteOffset=offset, count=count} = accessor-      BufferView{byteOffset=offset'} = bufferView--  return $ BufferAccessor-    { offset = offset + offset',-      count = count,-      buffer = buffer-    }---- | Look up a BufferView by Accessor-lookupBufferViewFromAccessor :: Accessor -> Vector BufferView -> Maybe BufferView-lookupBufferViewFromAccessor Accessor{..} bufferViews-  = bufferView >>= flip lookupBufferView bufferViews---- | Look up a Buffer by BufferView-lookupBufferFromBufferView :: BufferView -> Vector GltfBuffer -> Maybe GltfBuffer-lookupBufferFromBufferView BufferView{..} = lookupBuffer buffer---- | Look up an Accessor by Ix-lookupAccessor :: AccessorIx -> Vector Accessor -> Maybe Accessor-lookupAccessor (AccessorIx accessorId) = (Vector.!? accessorId)---- | Look up a BufferView by Ix-lookupBufferView :: BufferViewIx -> Vector BufferView -> Maybe BufferView-lookupBufferView (BufferViewIx bufferViewId) = (Vector.!? bufferViewId)---- | Look up a Buffer by Ix-lookupBuffer :: BufferIx -> Vector GltfBuffer -> Maybe GltfBuffer-lookupBuffer (BufferIx bufferId) = (Vector.!? bufferId)---- | Decode a buffer using the given Binary decoder-readFromBuffer-  :: Storable storable-  => storable-  -> Get (Vector storable)-  -> BufferAccessor-  -> Vector storable-readFromBuffer storable getter BufferAccessor{..}-  = runGet getter (fromStrict payload')-  where payload' = ByteString.take len' . ByteString.drop offset . unBuffer $ buffer-        len' = count * sizeOf storable
− src/Text/GLTF/Loader/Decoders.hs
@@ -1,157 +0,0 @@-module Text.GLTF.Loader.Decoders-  ( -- * GLTF Property-specific Type decoders-    getIndices,-    getPositions,-    getNormals,-    getTexCoords,-    -- * GLTF Accessor Type decoders-    getScalar,-    getVec2,-    getVec3,-    getVec4,-    getMat2,-    getMat3,-    getMat4,-    -- * GLTF Component Type decoders-    getByte,-    getUnsignedByte,-    getShort,-    getUnsignedShort,-    getUnsignedInt,-    getFloat-  ) where--import Data.Binary.Get-import Linear-import RIO hiding (min, max)-import qualified RIO.Vector as Vector---- | Vertex indices binary decoder-getIndices :: Get (Vector Int)-getIndices = getScalar (fromIntegral <$> getUnsignedShort)---- | Vertex positions binary decoder-getPositions :: Get (Vector (V3 Float))-getPositions = getVec3 getFloat---- | Vertex normals binary decoder-getNormals :: Get (Vector (V3 Float))-getNormals = getVec3 getFloat---- | Texture coordinates binary decoder-getTexCoords :: Get (Vector (V2 Float))-getTexCoords = getVec2 getFloat---- | Scalar (simple) type binary decoder-getScalar :: Get a -> Get (Vector a)-getScalar = getVector---- | 2D Vector binary decoder-getVec2 :: Get a -> Get (Vector (V2 a))-getVec2 getter = getVector $ V2 <$> getter <*> getter---- | 3D Vector binary decoder-getVec3 :: Get a -> Get (Vector (V3 a))-getVec3 getter = getVector $ V3 <$> getter <*> getter <*> getter---- | 4D Vector binary decoder-getVec4 :: Get a -> Get (Vector (V4 a))-getVec4 getter = getVector $ V4 <$> getter <*> getter <*> getter <*> getter---- | 2x2 Matrix binary decoder-getMat2 :: Get a -> Get (Vector (M22 a))-getMat2 getter = getVector $ do-  m1_1 <- getter-  m1_2 <- getter--  m2_1 <- getter-  m2_2 <- getter--  return $ V2-    (V2 m1_1 m2_1)-    (V2 m1_2 m2_2)---- | 3x3 Matrix binary decoder-getMat3 :: Get a -> Get (Vector (M33 a))-getMat3 getter = getVector $ do-  m1_1 <- getter-  m1_2 <- getter-  m1_3 <- getter-  -  m2_1 <- getter-  m2_2 <- getter-  m2_3 <- getter--  m3_1 <- getter-  m3_2 <- getter-  m3_3 <- getter--  return $ V3-    (V3 m1_1 m2_1 m3_1)-    (V3 m1_2 m2_2 m3_2)-    (V3 m1_3 m2_3 m3_3)---- | 4x4 Matrix binary decoder-getMat4 :: Get a -> Get (Vector (M44 a))-getMat4 getter = getVector $ do-  m1_1 <- getter-  m1_2 <- getter-  m1_3 <- getter-  m1_4 <- getter-  -  m2_1 <- getter-  m2_2 <- getter-  m2_3 <- getter-  m2_4 <- getter--  m3_1 <- getter-  m3_2 <- getter-  m3_3 <- getter-  m3_4 <- getter--  m4_1 <- getter-  m4_2 <- getter-  m4_3 <- getter-  m4_4 <- getter--  return $ V4-    (V4 m1_1 m2_1 m3_1 m4_1)-    (V4 m1_2 m2_2 m3_2 m4_2)-    (V4 m1_3 m2_3 m3_3 m4_3)-    (V4 m1_4 m2_4 m3_4 m4_4)---- | Byte binary decoder-getByte :: Get Int8-getByte = getInt8---- | Unsigned Byte binary decoder-getUnsignedByte :: Get Word8-getUnsignedByte = getWord8---- | Short binary decoder-getShort :: Get Int16-getShort = getInt16le---- | Unsigned Short binary decoder-getUnsignedShort :: Get Word16-getUnsignedShort = getWord16le---- | Unsigned Int binary decoder-getUnsignedInt :: Get Word32-getUnsignedInt = getWord32le---- | Float binary decoder-getFloat :: Get Float-getFloat = getFloatle---- | Boxed Vector binary decoder-getVector :: Get a -> Get (Vector a)-getVector = fmap Vector.fromList . getList---- | List binary decoder-getList :: Get a -> Get [a]-getList getter = do-  empty <- isEmpty-  if empty-    then return []-    else (:) <$> getter <*> getList getter
+ src/Text/GLTF/Loader/Glb.hs view
@@ -0,0 +1,16 @@+module Text.GLTF.Loader.Glb+  ( Glb(..),+    _gltf+  ) where++import RIO++import Text.GLTF.Loader.Gltf++-- | A Binary glTF+newtype Glb = Glb { unGltf :: Gltf }+  deriving (Eq, Show)++-- | Embedded glTF root data, from the first chunk+_gltf :: Lens' Glb Gltf+_gltf = lens unGltf (const Glb)
src/Text/GLTF/Loader/Gltf.hs view
@@ -2,6 +2,9 @@   ( -- * Data constructors     Gltf(..),     Asset(..),+    Image(..),+    MagFilter(..),+    MinFilter(..),     Material(..),     MaterialAlphaMode(..),     Mesh(..),@@ -9,16 +12,28 @@     MeshPrimitive(..),     PbrMetallicRoughness(..),     MeshPrimitiveMode(..),+    Sampler(..),+    SamplerWrap(..),+    Texture(..),+    TextureInfo(..),     -- * Lenses+    -- ** Top-level Gltf Lenses     _asset,+    _images,     _materials,     _meshes,     _nodes,+    _samplers,+    _textures,     -- ** Asset Lenses     _assetVersion,     _assetCopyright,     _assetGenerator,     _assetMinVersion,+    -- ** Image Lenses+    _imageData,+    _imageMimeType,+    _imageName,     -- ** Material Lenses     _materialAlphaCutoff,     _materialAlphaMode,@@ -31,12 +46,23 @@     _meshWeights,     _meshName,     -- ** Node Lenses+    _nodeChildren,     _nodeMeshId,     _nodeName,     _nodeRotation,     _nodeScale,     _nodeTranslation,     _nodeWeights,+    -- ** Sampler Lenses+    _samplerMagFilter,+    _samplerMinFilter,+    _samplerName,+    _samplerWrapS,+    _samplerWrapT,+    -- ** Texture Lenses+    _textureName,+    _textureSamplerId,+    _textureSourceId,     -- ** MeshPrimitive Lenses     _meshPrimitiveMaterial,     _meshPrimitiveIndices,@@ -45,8 +71,12 @@     _meshPrimitivePositions,     -- ** PbrMetallicRoughness Lenses     _pbrBaseColorFactor,+    _pbrBaseColorTexture,     _pbrMetallicFactor,-    _pbrRoughnessFactor+    _pbrRoughnessFactor,+    -- ** TextureInfo Lenses+    _textureInfoId,+    _textureInfoTexCoord   ) where  import Linear@@ -55,71 +85,166 @@ -- | The root data type for a glTF asset data Gltf = Gltf   { gltfAsset :: Asset,+    gltfImages :: Vector Image,     gltfMaterials :: Vector Material,     gltfMeshes :: Vector Mesh,-    gltfNodes :: Vector Node+    gltfNodes :: Vector Node,+    gltfSamplers :: Vector Sampler,+    gltfTextures :: Vector Texture   } deriving (Eq, Show)  -- | Metadata about the glTF asset data Asset = Asset-  { assetVersion :: Text,+  { -- | The glTF version that this asset targets.+    assetVersion :: Text,+    -- | A copyright message suitable for display to credit the content creator.     assetCopyright :: Maybe Text,+    -- | Tool that generated this glTF model.     assetGenerator :: Maybe Text,+    -- | The minimum glTF version that this asset targets     assetMinVersion :: Maybe Text   } deriving (Eq, Show) +-- | Image data used to create a texture.+data Image = Image+  { -- | The binary data of the image+    imageData :: Maybe ByteString,+    -- | The image’s media type.+    imageMimeType :: Text,+    -- | The user-defined name of this object.+    imageName :: Maybe Text+  } deriving (Eq, Show)+ -- | The material appearance of a primitive data Material = Material-  { materialAlphaCutoff :: Float,+  { -- | Specifies the cutoff threshold when in MASK alpha mode.+    materialAlphaCutoff :: Float,+    -- | The material’s alpha rendering mode enumeration specifying the interpretation of+    --   the alpha value of the base color.     materialAlphaMode :: MaterialAlphaMode,+    -- | Specifies whether the material is double sided.     materialDoubleSided :: Bool,+    -- | The factors for the emissive color of the material.     materialEmissiveFactor :: V3 Float,+    -- | The user-defined name of this object.     materialName :: Maybe Text,+    -- | Metallic roughness Physically Based Rendering (PBR) methodology parameter values.     materialPbrMetallicRoughness :: Maybe PbrMetallicRoughness   } deriving (Eq, Show)  -- | A set of primitives to be rendered data Mesh = Mesh-  { meshPrimitives :: Vector MeshPrimitive,-    meshWeights :: Vector Float,-    meshName :: Maybe Text+  { -- | The user-defined name of this object.+    meshName :: Maybe Text,+    -- | A Vector of primitives, each defining geometry to be rendered.+    meshPrimitives :: Vector MeshPrimitive,+    -- | A Vector of weights to be applied to the morph targets.+    meshWeights :: Vector Float   } deriving (Eq, Show)  -- | A node in the node hierarchy data Node = Node-  { nodeMeshId :: Maybe Int,+  { -- | The indices of this Node's children+    nodeChildren :: Vector Int,+    -- | The index of the mesh in this node.+    nodeMeshId :: Maybe Int,+    -- | The user-defined name of this object.     nodeName :: Maybe Text,+    -- | The node's unit quaternion rotation.     nodeRotation :: Maybe (V4 Float),+    -- | The node's non-uniform scale     nodeScale :: Maybe (V3 Float),+    -- | The node's translation along the x, y, and z axes.     nodeTranslation :: Maybe (V3 Float),+    -- | The weights of the instantiated morph target.     nodeWeights :: [Float]   } deriving (Eq, Show) +-- | Texture sampler properties for filtering and wrapping modes.+data Sampler = Sampler+  { -- | Magnification filter.+    samplerMagFilter :: Maybe MagFilter,+    -- | Minification filter.+    samplerMinFilter :: Maybe MinFilter,+    -- | The user-defined name of this object.+    samplerName :: Maybe Text,+    -- | S (U) wrapping mode. All valid values correspond to WebGL enums.+    samplerWrapS :: SamplerWrap,+    -- | T (V) wrapping mode. All valid values correspond to WebGL enums.+    samplerWrapT :: SamplerWrap+  } deriving (Eq, Show)++-- | A texture and its sampler.+data Texture = Texture+  { -- | The user-defined name of this object.+    textureName :: Maybe Text,+    -- | The index of the sampler used by this texture.+    textureSamplerId :: Maybe Int,+    -- | The index of the image used by this texture.+    textureSourceId :: Maybe Int+  } deriving (Eq, Show)+ -- | Geometry to be rendered with the given material data MeshPrimitive = MeshPrimitive-  { meshPrimitiveIndices :: Vector Int,+  { -- | A Vector of vertex indices.+    meshPrimitiveIndices :: Vector Word16,+    -- | The index of the material to apply to this primitive when rendering.     meshPrimitiveMaterial :: Maybe Int,+    -- | The topology type of primitives to render.     meshPrimitiveMode :: MeshPrimitiveMode,+    -- | A Vector of vertex normals.     meshPrimitiveNormals :: Vector (V3 Float),+    -- | A Vector of vertex positions.     meshPrimitivePositions :: Vector (V3 Float),+    -- | A Vector of vertex texture coordinates     meshPrimitiveTexCoords :: Vector (V2 Float)   } deriving (Eq, Show)  -- | Alpha rendering mode of a material data MaterialAlphaMode+  -- | The alpha value is used to composite the source and destination areas.   = Blend+  -- | The rendered output is either fully opaque or fully transparent depending on the+  -- alpha value and the specified alphaCutoff value.   | Mask+  -- |The alpha value is ignored, and the rendered output is fully opaque.   | Opaque   deriving (Eq, Enum, Show)  -- | A set of parameter values that are used to define the metallic-roughness material -- model from Physically-Based Rendering (PBR) methodology. data PbrMetallicRoughness = PbrMetallicRoughness-  { pbrBaseColorFactor :: V4 Float,+  { -- | The factors for the base color of the material.+    pbrBaseColorFactor :: V4 Float,+    -- | The base color texture+    pbrBaseColorTexture :: Maybe TextureInfo,+    -- | The factor for the metalness of the material.     pbrMetallicFactor :: Float,+    -- | The factor for the roughness of the material.     pbrRoughnessFactor :: Float   } deriving (Eq, Show) +-- | Magnification filter.+data MagFilter = MagLinear | MagNearest+  deriving (Enum, Eq, Show)++-- | Minification Filter.+data MinFilter+  = MinNearest+  | MinLinear+  | MinNearestMipmapNearest+  | MinLinearMipmapNearest+  | MinNearestMipmapLinear+  | MinLinearMipmapLinear+  deriving (Enum, Eq, Show)++-- | Sampler wrapping mode.  +data SamplerWrap+  = ClampToEdge+  | MirroredRepeat+  | Repeat+  deriving (Enum, Eq, Show)+ -- | The topology type of primitives to render. data MeshPrimitiveMode   = Points@@ -131,138 +256,276 @@   | TriangleFan   deriving (Eq, Enum, Show) +-- | Reference to a texture.+data TextureInfo = TextureInfo+  { -- | The index of the texture.+    textureId :: Int,+    -- | This integer value is used to construct a string in the format+    -- TEXCOORD_<set_index> which is a reference to a key in mesh.primitives.attributes+    -- (e.g. a value of 0 corresponds to TEXCOORD_0).+    textureTexCoord :: Int+  } deriving (Eq, Show)++-- | Metadata about the glTF asset _asset :: Lens' Gltf Asset _asset = lens gltfAsset (\gltf asset -> gltf { gltfAsset = asset }) +-- | A Vector of Images. An Image defines data used to create a texture.+_images :: Lens' Gltf (Vector Image)+_images = lens gltfImages (\gltf images -> gltf { gltfImages = images })++-- | A Vector of Materials. A Material defines the appearance of a primitive. _materials :: Lens' Gltf (Vector Material) _materials = lens gltfMaterials (\gltf mats -> gltf { gltfMaterials = mats }) +-- | A Vector of Meshes. A Mesh is a set of primitives to be rendered. _meshes :: Lens' Gltf (Vector Mesh) _meshes = lens gltfMeshes (\gltf meshes -> gltf { gltfMeshes = meshes }) +-- | A Vector of Nodes in the hierarchy. _nodes :: Lens' Gltf (Vector Node) _nodes = lens gltfNodes (\gltf nodes -> gltf { gltfNodes = nodes }) +-- | A Vector of Texture Samplers. Texture Sampler defines properties for filtering and+-- wrapping modes.+_samplers :: Lens' Gltf (Vector Sampler)+_samplers = lens gltfSamplers (\gltf samplers -> gltf { gltfSamplers = samplers })++-- | A texture and its sampler.+_textures :: Lens' Gltf (Vector Texture)+_textures = lens gltfTextures (\gltf texs -> gltf { gltfTextures = texs })++-- | The glTF version that this asset targets. _assetVersion :: Lens' Asset Text _assetVersion = lens assetVersion (\asset version' -> asset { assetVersion = version' }) +-- | A copyright message suitable for display to credit the content creator. _assetCopyright :: Lens' Asset (Maybe Text) _assetCopyright = lens   assetCopyright   (\asset copyright' -> asset { assetCopyright = copyright' }) +-- | Tool that generated this glTF model. _assetGenerator :: Lens' Asset (Maybe Text) _assetGenerator = lens   assetGenerator   (\asset generator' -> asset { assetGenerator = generator' }) +-- | The minimum glTF version that this asset targets _assetMinVersion :: Lens' Asset (Maybe Text) _assetMinVersion = lens   assetMinVersion   (\asset minVersion' -> asset { assetMinVersion = minVersion' }) +-- | The binary data of the image+_imageData :: Lens' Image (Maybe ByteString)+_imageData = lens imageData (\img data' -> img { imageData = data' })++-- | The image’s media type.+_imageMimeType :: Lens' Image Text+_imageMimeType = lens imageMimeType (\img mime -> img { imageMimeType = mime })++-- | The user-defined name of this object.+_imageName :: Lens' Image (Maybe Text)+_imageName = lens imageName (\img name -> img { imageName = name })++-- | Specifies the cutoff threshold when in MASK alpha mode. _materialAlphaCutoff :: Lens' Material Float _materialAlphaCutoff = lens   materialAlphaCutoff   (\material alphaCutoff -> material { materialAlphaCutoff = alphaCutoff }) +-- | The material's alpha rendering mode enumeration specifying the interpretation of+--   the alpha value of the base color. _materialAlphaMode :: Lens' Material MaterialAlphaMode _materialAlphaMode = lens   materialAlphaMode   (\material mode -> material { materialAlphaMode = mode }) +-- | Specifies whether the material is double sided. _materialDoubleSided :: Lens' Material Bool _materialDoubleSided = lens   materialDoubleSided   (\material doubleSided -> material { materialDoubleSided = doubleSided }) +-- | The factors for the emissive color of the material. _materialEmissiveFactor :: Lens' Material (V3 Float) _materialEmissiveFactor = lens   materialEmissiveFactor   (\material emissiveFactor -> material { materialEmissiveFactor = emissiveFactor }) +-- | The user-defined name of this object. _materialName :: Lens' Material (Maybe Text) _materialName = lens   materialName   (\material name -> material { materialName = name }) +-- | Metallic roughness Physically Based Rendering (PBR) methodology parameter values. _materialPbrMetallicRoughness :: Lens' Material (Maybe PbrMetallicRoughness) _materialPbrMetallicRoughness = lens   materialPbrMetallicRoughness   (\material roughness -> material { materialPbrMetallicRoughness = roughness }) -_meshWeights :: Lens' Mesh (Vector Float)-_meshWeights = lens meshWeights (\mesh weights -> mesh { meshWeights = weights })-+-- | The user-defined name of this object. _meshName :: Lens' Mesh (Maybe Text) _meshName = lens meshName (\mesh name -> mesh { meshName = name }) +-- | A Vector of primitives, each defining geometry to be rendered. _meshPrimitives :: Lens' Mesh (Vector MeshPrimitive) _meshPrimitives = lens   meshPrimitives   (\mesh primitives -> mesh { meshPrimitives = primitives }) +-- | A Vector of weights to be applied to the morph targets.+_meshWeights :: Lens' Mesh (Vector Float)+_meshWeights = lens meshWeights (\mesh weights -> mesh { meshWeights = weights })++-- | The indices of this node's children.+_nodeChildren :: Lens' Node (Vector Int)+_nodeChildren = lens nodeChildren (\node children -> node { nodeChildren = children })++-- | The index of the mesh in this node. _nodeMeshId :: Lens' Node (Maybe Int) _nodeMeshId = lens nodeMeshId (\node meshId -> node { nodeMeshId = meshId }) +-- | The user-defined name of this object. _nodeName :: Lens' Node (Maybe Text) _nodeName = lens nodeName (\node name' -> node { nodeName = name' }) +-- | The node's unit quaternion rotation. _nodeRotation :: Lens' Node (Maybe (V4 Float)) _nodeRotation = lens nodeRotation (\node rotation' -> node { nodeRotation = rotation' }) +-- | The node's non-uniform scale _nodeScale :: Lens' Node (Maybe (V3 Float)) _nodeScale = lens nodeScale (\node scale' -> node { nodeScale = scale' }) +-- | The node's translation along the x, y, and z axes. _nodeTranslation :: Lens' Node (Maybe (V3 Float)) _nodeTranslation = lens   nodeTranslation   (\node translation' -> node { nodeTranslation = translation' }) +-- | The weights of the instantiated morph target. _nodeWeights :: Lens' Node [Float] _nodeWeights = lens nodeWeights (\node weights' -> node { nodeWeights = weights' }) -_meshPrimitiveIndices :: Lens' MeshPrimitive (Vector Int)+-- | Magnification filter.+_samplerMagFilter :: Lens' Sampler (Maybe MagFilter)+_samplerMagFilter = lens+  samplerMagFilter+  (\sampler mag -> sampler { samplerMagFilter = mag })++-- | Minification filter.+_samplerMinFilter :: Lens' Sampler (Maybe MinFilter)+_samplerMinFilter = lens+  samplerMinFilter+  (\sampler min' -> sampler { samplerMinFilter = min' })++-- | The user-defined name of this object.+_samplerName :: Lens' Sampler (Maybe Text)+_samplerName = lens+  samplerName+  (\sampler name -> sampler { samplerName = name })++-- | S (U) wrapping mode.+_samplerWrapS :: Lens' Sampler SamplerWrap+_samplerWrapS = lens+  samplerWrapS+  (\sampler wrapS -> sampler { samplerWrapS = wrapS })++-- | T (V) wrapping mode.+_samplerWrapT :: Lens' Sampler SamplerWrap+_samplerWrapT = lens+  samplerWrapT+  (\sampler wrapT -> sampler { samplerWrapT = wrapT })++-- | The user-defined name of this object.+_textureName :: Lens' Texture (Maybe Text)+_textureName = lens textureName (\tex name -> tex { textureName = name })++-- | The index of the sampler used by this texture.+_textureSamplerId :: Lens' Texture (Maybe Int)+_textureSamplerId = lens+  textureSamplerId+  (\tex sampler -> tex { textureSamplerId = sampler })++-- | The index of the image used by this texture.+_textureSourceId :: Lens' Texture (Maybe Int)+_textureSourceId = lens+  textureSourceId+  (\tex source -> tex { textureSourceId = source })++-- | A Vector of vertex indices.+_meshPrimitiveIndices :: Lens' MeshPrimitive (Vector Word16) _meshPrimitiveIndices = lens   meshPrimitiveIndices   (\primitive' indices -> primitive' { meshPrimitiveIndices = indices }) +-- | The index of the material to apply to this primitive when rendering. _meshPrimitiveMaterial :: Lens' MeshPrimitive (Maybe Int) _meshPrimitiveMaterial = lens   meshPrimitiveMaterial   (\primitive' material -> primitive' { meshPrimitiveMaterial = material }) +-- | The topology type of primitives to render. _meshPrimitiveMode :: Lens' MeshPrimitive MeshPrimitiveMode _meshPrimitiveMode = lens   meshPrimitiveMode   (\primitive' mode -> primitive' { meshPrimitiveMode = mode }) +-- | A Vector of vertex normals. _meshPrimitiveNormals :: Lens' MeshPrimitive (Vector (V3 Float)) _meshPrimitiveNormals = lens   meshPrimitiveNormals   (\primitive' normals -> primitive' { meshPrimitiveNormals = normals }) +-- | A Vector of vertex positions. _meshPrimitivePositions :: Lens' MeshPrimitive (Vector (V3 Float)) _meshPrimitivePositions = lens   meshPrimitivePositions   (\primitive' positions -> primitive' { meshPrimitivePositions = positions }) +-- | A Vector of vertex texture coordinates _meshPrimitiveTexCoords :: Lens' MeshPrimitive (Vector (V2 Float)) _meshPrimitiveTexCoords = lens   meshPrimitiveTexCoords   (\primitive' coords -> primitive' { meshPrimitiveTexCoords = coords })-  ++-- | The factors for the base color of the material. _pbrBaseColorFactor :: Lens' PbrMetallicRoughness (V4 Float) _pbrBaseColorFactor = lens   pbrBaseColorFactor   (\pbr baseColor -> pbr { pbrBaseColorFactor = baseColor })-  ++-- | The base color texture+_pbrBaseColorTexture :: Lens' PbrMetallicRoughness (Maybe TextureInfo)+_pbrBaseColorTexture = lens+  pbrBaseColorTexture+  (\pbr texture -> pbr { pbrBaseColorTexture = texture })++-- | The factor for the metalness of the material. _pbrMetallicFactor :: Lens' PbrMetallicRoughness Float _pbrMetallicFactor = lens   pbrMetallicFactor   (\pbr metallicFactor -> pbr { pbrMetallicFactor = metallicFactor }) +-- | The factor for the roughness of the material. _pbrRoughnessFactor :: Lens' PbrMetallicRoughness Float _pbrRoughnessFactor = lens   pbrRoughnessFactor   (\pbr roughnessFactor -> pbr { pbrRoughnessFactor = roughnessFactor })++-- | The index of the texture.+_textureInfoId :: Lens' TextureInfo Int+_textureInfoId = lens+  textureId+  (\texInfo id' -> texInfo { textureId = id' })++-- | This integer value is used to construct a string in the format+-- TEXCOORD_<set_index> which is a reference to a key in mesh.primitives.attributes+-- (e.g. a value of 0 corresponds to TEXCOORD_0).+_textureInfoTexCoord :: Lens' TextureInfo Int+_textureInfoTexCoord = lens+  textureTexCoord+  (\texInfo coord -> texInfo { textureTexCoord = coord })
+ src/Text/GLTF/Loader/Internal/Adapter.hs view
@@ -0,0 +1,254 @@+-- |Transform a `Codec.GlTF.GlTF` to `Text.GLTF.Loader.Gltf.Gltf`+module Text.GLTF.Loader.Internal.Adapter+  ( attributePosition,+    attributeNormal,+    attributeTexCoord,+    runAdapter,+    adaptGltf,+    adaptAsset,+    adaptImages,+    adaptMaterials,+    adaptMeshes,+    adaptNodes,+    adaptTextures,+    adaptImage,+    adaptMaterial,+    adaptMesh,+    adaptNode,+    adaptTexture,+    adaptAlphaMode,+    adaptPbrMetallicRoughness,+    adaptMeshPrimitives,+    adaptMeshPrimitive,+    adaptMeshPrimitiveMode+  ) where++import Text.GLTF.Loader.Gltf+import Text.GLTF.Loader.Internal.BufferAccessor+import Text.GLTF.Loader.Internal.MonadAdapter++import Linear (V3(..), V4(..))+import RIO+import RIO.Partial (toEnum)+import RIO.Vector.Partial ((!))+import qualified Codec.GlTF as GlTF+import qualified Codec.GlTF.Asset as Asset+import qualified Codec.GlTF.Image as Image+import qualified Codec.GlTF.Material as Material+import qualified Codec.GlTF.PbrMetallicRoughness as PbrMetallicRoughness+import qualified Codec.GlTF.Mesh as Mesh+import qualified Codec.GlTF.Node as Node+import qualified Codec.GlTF.Sampler as Sampler+import qualified Codec.GlTF.Texture as Texture+import qualified Codec.GlTF.TextureInfo as TextureInfo+import qualified Data.HashMap.Strict as HashMap+import qualified RIO.Vector as V++attributePosition :: Text+attributePosition = "POSITION"++attributeNormal :: Text+attributeNormal = "NORMAL"++attributeTexCoord :: Text+attributeTexCoord = "TEXCOORD_0"++runAdapter+  :: GlTF.GlTF+  -> Vector GltfBuffer+  -> Vector GltfImageData+  -> Gltf+runAdapter gltf buffers images = runReader adaptGltf env+  where env = AdaptEnv gltf buffers images++adaptGltf :: Adapter Gltf+adaptGltf = do+  GlTF.GlTF{..} <- getGltf++  gltfImages <- adaptImages images+  gltfMeshes <- adaptMeshes meshes+  +  return $ Gltf+    { gltfAsset = adaptAsset asset,+      gltfImages = gltfImages,+      gltfMaterials = adaptMaterials materials,+      gltfMeshes = gltfMeshes,+      gltfNodes = adaptNodes nodes,+      gltfSamplers = adaptSamplers samplers,+      gltfTextures = adaptTextures textures+    }++adaptAsset :: Asset.Asset -> Asset+adaptAsset Asset.Asset{..} = Asset+  { assetVersion = version,+    assetCopyright = copyright,+    assetGenerator = generator,+    assetMinVersion = minVersion+  }++adaptImages :: Maybe (Vector Image.Image) -> Adapter (Vector Image)+adaptImages codecImages = do+  imageData <- getImages++  let images' = fromMaybe mempty codecImages+      iforM = flip V.imapM++  iforM images' $ \imgId img ->+    adaptImage (imageData ! imgId) img++adaptMaterials :: Maybe (Vector Material.Material) -> Vector Material+adaptMaterials = maybe mempty (fmap adaptMaterial)++adaptMeshes :: Maybe (Vector Mesh.Mesh) -> Adapter (Vector Mesh)+adaptMeshes = maybe (return mempty) (V.mapM adaptMesh)++adaptNodes :: Maybe (Vector Node.Node) -> Vector Node+adaptNodes = maybe mempty (fmap adaptNode)++adaptSamplers :: Maybe (Vector Sampler.Sampler) -> Vector Sampler+adaptSamplers = maybe mempty (fmap adaptSampler)++adaptTextures :: Maybe (Vector Texture.Texture) -> Vector Texture+adaptTextures = maybe mempty (fmap adaptTexture)++adaptImage :: GltfImageData -> Image.Image -> Adapter Image+adaptImage imgData Image.Image{..} = do+  payload <- getImageData imgData++  -- Note that we treat mimeType as required, even though it may not be in the+  -- specification. Tests in Blender suggest it's ALWAYS provided; When we come+  -- across an example where it isn't, we'll address it then.+  case mimeType of+    Nothing -> error "Invalid Image: no mime-type specified"+    Just mimeType' -> return Image+      { imageData = payload,+        imageMimeType = mimeType',+        imageName = name+      }++adaptMaterial :: Material.Material -> Material+adaptMaterial Material.Material{..} = Material+  { materialAlphaCutoff = alphaCutoff,+    materialAlphaMode = adaptAlphaMode alphaMode,+    materialDoubleSided = doubleSided,+    materialEmissiveFactor = toV3 emissiveFactor,+    materialName = name,+    materialPbrMetallicRoughness = adaptPbrMetallicRoughness <$> pbrMetallicRoughness+  }++adaptMesh :: Mesh.Mesh -> Adapter Mesh+adaptMesh Mesh.Mesh{..} = do+  primitives' <- adaptMeshPrimitives primitives+  +  return $ Mesh+    { meshPrimitives = primitives',+      meshWeights = fromMaybe mempty weights,+      meshName = name+    }++adaptNode :: Node.Node -> Node+adaptNode Node.Node{..} = Node+  { nodeChildren = maybe mempty (fmap Node.unNodeIx) children,+    nodeMeshId = Mesh.unMeshIx <$> mesh,+    nodeName = name,+    nodeRotation = toV4 <$> rotation,+    nodeScale = toV3 <$> scale,+    nodeTranslation = toV3 <$> translation,+    nodeWeights = maybe [] toList weights+  }++adaptSampler :: Sampler.Sampler -> Sampler+adaptSampler Sampler.Sampler{..} = Sampler+  { samplerMagFilter = adaptMagFilter <$> magFilter,+    samplerMinFilter = adaptMinFilter <$> minFilter,+    samplerName = name,+    samplerWrapS = adaptSamplerWrap wrapS,+    samplerWrapT = adaptSamplerWrap wrapT+  }++adaptTexture :: Texture.Texture -> Texture+adaptTexture Texture.Texture{..} = Texture+  { textureName = name,+    textureSamplerId = Sampler.unSamplerIx <$> sampler,+    textureSourceId = Image.unImageIx <$> source+  }++getImageData :: GltfImageData -> Adapter (Maybe ByteString)+getImageData (ImageData payload) = return $ Just payload+getImageData NoImageData = return Nothing+getImageData (ImageBufferView bufferViewId) = imageDataRaw' <$> getGltf <*> getBuffers+  where imageDataRaw' gltf buffers' = imageDataRaw gltf buffers' bufferViewId++adaptAlphaMode :: Material.MaterialAlphaMode -> MaterialAlphaMode+adaptAlphaMode Material.BLEND = Blend+adaptAlphaMode Material.MASK = Mask+adaptAlphaMode Material.OPAQUE = Opaque+adaptAlphaMode (Material.MaterialAlphaMode alphaMode)+  = error $ "Invalid MaterialAlphaMode: " <> show alphaMode++adaptPbrMetallicRoughness+  :: PbrMetallicRoughness.PbrMetallicRoughness+  -> PbrMetallicRoughness+adaptPbrMetallicRoughness PbrMetallicRoughness.PbrMetallicRoughness{..}+  = PbrMetallicRoughness+    { pbrBaseColorFactor = toV4 baseColorFactor,+      pbrBaseColorTexture = adaptTextureInfo <$> baseColorTexture,+      pbrMetallicFactor = metallicFactor,+      pbrRoughnessFactor = roughnessFactor+    }++adaptMeshPrimitives :: Vector Mesh.MeshPrimitive -> Adapter (Vector MeshPrimitive)+adaptMeshPrimitives = V.mapM adaptMeshPrimitive++adaptMagFilter :: Sampler.SamplerMagFilter -> MagFilter+adaptMagFilter Sampler.MAG_LINEAR = MagLinear+adaptMagFilter Sampler.MAG_NEAREST = MagNearest+adaptMagFilter mode = error $ "Invalid MagFilter: " <> show mode++adaptMinFilter :: Sampler.SamplerMinFilter -> MinFilter+adaptMinFilter Sampler.MIN_NEAREST = MinNearest+adaptMinFilter Sampler.MIN_LINEAR = MinLinear+adaptMinFilter Sampler.MIN_NEAREST_MIPMAP_NEAREST = MinNearestMipmapNearest+adaptMinFilter Sampler.MIN_NEAREST_MIPMAP_LINEAR = MinNearestMipmapLinear+adaptMinFilter Sampler.MIN_LINEAR_MIPMAP_NEAREST = MinLinearMipmapNearest+adaptMinFilter Sampler.MIN_LINEAR_MIPMAP_LINEAR = MinLinearMipmapLinear+adaptMinFilter mode = error $ "Invalid MinFilter: " <> show mode++adaptSamplerWrap :: Sampler.SamplerWrap -> SamplerWrap+adaptSamplerWrap Sampler.CLAMP_TO_EDGE = ClampToEdge+adaptSamplerWrap Sampler.MIRRORED_REPEAT = MirroredRepeat+adaptSamplerWrap Sampler.REPEAT = Repeat+adaptSamplerWrap mode = error $ "Invalid SamplerWrap: " <> show mode++adaptTextureInfo :: TextureInfo.TextureInfo a -> TextureInfo+adaptTextureInfo TextureInfo.TextureInfo{..} = TextureInfo+  { textureId = index,+    textureTexCoord = texCoord+  }++adaptMeshPrimitive :: Mesh.MeshPrimitive -> Adapter MeshPrimitive+adaptMeshPrimitive Mesh.MeshPrimitive{..} = do+  gltf <- getGltf+  buffers' <- getBuffers+  +  return $ MeshPrimitive+    { meshPrimitiveIndices = maybe mempty (vertexIndices gltf buffers') indices,+      meshPrimitiveMaterial = Material.unMaterialIx <$> material,+      meshPrimitiveMode = adaptMeshPrimitiveMode mode,+      meshPrimitiveNormals = maybe mempty (vertexNormals gltf buffers') normals,+      meshPrimitivePositions = maybe mempty (vertexPositions gltf buffers') positions,+      meshPrimitiveTexCoords = maybe mempty (vertexTexCoords gltf buffers') texCoords+    }+    where positions = attributes HashMap.!? attributePosition+          normals = attributes HashMap.!? attributeNormal+          texCoords = attributes HashMap.!? attributeTexCoord+          ++adaptMeshPrimitiveMode :: Mesh.MeshPrimitiveMode -> MeshPrimitiveMode+adaptMeshPrimitiveMode = toEnum . Mesh.unMeshPrimitiveMode++toV3 :: (a, a, a) -> V3 a+toV3 (x, y, z) = V3 x y z++toV4 :: (a, a, a, a) -> V4 a+toV4 (w, x, y, z) = V4 w x y z
+ src/Text/GLTF/Loader/Internal/BufferAccessor.hs view
@@ -0,0 +1,216 @@+module Text.GLTF.Loader.Internal.BufferAccessor+  ( GltfBuffer(..),+    GltfImageData(..),+    -- * Loading GLTF buffers+    loadBuffers,+    loadImages,+    -- * Deserializing Accessors+    vertexIndices,+    vertexPositions,+    vertexNormals,+    vertexTexCoords,+    imageDataRaw,+  ) where++import Text.GLTF.Loader.Internal.Decoders++import Codec.GLB (Chunk(..))+import Codec.GlTF.Accessor+import Codec.GlTF.Buffer+import Codec.GlTF.BufferView+import Codec.GlTF.Image+import Codec.GlTF.URI+import Codec.GlTF+import Data.Binary.Get+import Data.ByteString.Lazy (fromStrict)+import Foreign.Storable+import Linear+import RIO hiding (min, max)+import RIO.FilePath+import qualified RIO.Vector as Vector+import qualified RIO.ByteString as ByteString++-- | Holds the entire payload of a glTF buffer+newtype GltfBuffer+  = GltfBuffer { unBuffer :: ByteString }+  deriving (Eq, Show, Semigroup, Monoid)++data GltfImageData+  = ImageData ByteString+  | ImageBufferView BufferViewIx+  | NoImageData+  deriving (Eq, Show)++-- | A buffer and some metadata+data BufferAccessor = BufferAccessor+  { offset :: Int,+    count :: Int,+    buffer :: GltfBuffer+  }++-- | Read all the buffers into memory+loadBuffers+  :: MonadUnliftIO io+  => GlTF+  -> Maybe Chunk+  -> FilePath -- ^ Base path of GlTF file+  -> io (Vector GltfBuffer)+loadBuffers GlTF{buffers=buffers} chunk basePath = do+  let buffers' = fromMaybe [] buffers+      iforM = flip Vector.imapM+  +  iforM buffers' $ \idx Buffer{..} -> do+    -- If the first buffer does not have a URI defined, it refers to a GLB chunk+    let fallback = if idx == 0 && isNothing uri+          then maybe mempty chunkData chunk+          else mempty+    +    uri' <- maybe (pure fallback) (loadUri' basePath) uri+    return $ GltfBuffer uri'++loadImages+  :: MonadUnliftIO io+  => GlTF+  -> FilePath -- ^ Base path of GlTF file+  -> io (Vector GltfImageData)+loadImages GlTF{images=images} basePath = do+  let images' = fromMaybe [] images++  Vector.forM images' $ \Image{..} -> do+    let fallbackImageData = return $ maybe NoImageData ImageBufferView bufferView+    maybe fallbackImageData (fmap ImageData . loadUri' basePath) uri++-- | Decode vertex indices+vertexIndices :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector Word16+vertexIndices = readBufferWithGet getIndices++-- | Decode vertex positions+vertexPositions :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)+vertexPositions = readBufferWithGet getPositions++-- | Decode vertex normals+vertexNormals :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V3 Float)+vertexNormals = readBufferWithGet getNormals++-- | Decode texture coordinates. Note that we only use the first one.+vertexTexCoords :: GlTF -> Vector GltfBuffer -> AccessorIx -> Vector (V2 Float)+vertexTexCoords = readBufferWithGet getTexCoords++-- | Read an image from a buffer view+imageDataRaw :: GlTF -> Vector GltfBuffer -> BufferViewIx -> Maybe ByteString+imageDataRaw = readBufferView++-- | Return a buffer view undecoded+readBufferView :: GlTF -> Vector GltfBuffer -> BufferViewIx -> Maybe ByteString+readBufferView gltf buffers' bufferViewId = do+  accessor@BufferAccessor{count=length'}+    <- bufferViewAccessor gltf buffers' bufferViewId++  return $ readFromBufferRaw accessor length'++-- | Read a URI. Throws error on failure+loadUri'+  :: MonadUnliftIO io+  => FilePath -- ^ Base path+  -> URI      -- ^ URI to load+  -> io ByteString+loadUri' baseDir uri' = do+  readRes <- liftIO $ loadURI (loadFile baseDir) uri'+  case readRes of+    Left err -> error err+    Right res -> return res++loadFile :: MonadUnliftIO io => FilePath -> FilePath -> io (Either String ByteString)+loadFile baseDir filename = do+  contents <- readFileBinary (baseDir </> filename)++  return $ Right contents++-- | Decode a buffer using the given Binary decoder+readBufferWithGet+  :: Storable storable+  => Get (Vector storable)+  -> GlTF+  -> Vector GltfBuffer+  -> AccessorIx+  -> Vector storable+readBufferWithGet getter gltf buffers' accessorId+  = maybe mempty+      (readFromBuffer undefined getter)+      (bufferAccessor gltf buffers' accessorId)++-- | Look up a Buffer from a GlTF and AccessorIx+bufferAccessor+  :: GlTF+  -> Vector GltfBuffer+  -> AccessorIx+  -> Maybe BufferAccessor+bufferAccessor GlTF{..} buffers' accessorId = do+  accessor <- lookupAccessor accessorId =<< accessors+  bufferView <- lookupBufferViewFromAccessor accessor =<< bufferViews+  buffer <- lookupBufferFromBufferView bufferView buffers'++  let Accessor{byteOffset=offset, count=count} = accessor+      BufferView{byteOffset=offset'} = bufferView++  return $ BufferAccessor+    { offset = offset + offset',+      count = count,+      buffer = buffer+    }++-- | Look up a Buffer from a GlTF and BufferView+bufferViewAccessor+  :: GlTF+  -> Vector GltfBuffer+  -> BufferViewIx+  -> Maybe BufferAccessor+bufferViewAccessor GlTF{..} buffers' bufferViewId = do+  bufferView <- lookupBufferView bufferViewId =<< bufferViews+  buffer <- lookupBufferFromBufferView bufferView buffers'++  let BufferView{byteLength=length', byteOffset=offset'} = bufferView++  return $ BufferAccessor+    { offset = offset',+      count = length',+      buffer = buffer+    }++-- | Look up a BufferView by Accessor+lookupBufferViewFromAccessor :: Accessor -> Vector BufferView -> Maybe BufferView+lookupBufferViewFromAccessor Accessor{..} bufferViews+  = bufferView >>= flip lookupBufferView bufferViews++-- | Look up a Buffer by BufferView+lookupBufferFromBufferView :: BufferView -> Vector GltfBuffer -> Maybe GltfBuffer+lookupBufferFromBufferView BufferView{..} = lookupBuffer buffer++-- | Look up an Accessor by Ix+lookupAccessor :: AccessorIx -> Vector Accessor -> Maybe Accessor+lookupAccessor (AccessorIx accessorId) = (Vector.!? accessorId)++-- | Look up a BufferView by Ix+lookupBufferView :: BufferViewIx -> Vector BufferView -> Maybe BufferView+lookupBufferView (BufferViewIx bufferViewId) = (Vector.!? bufferViewId)++-- | Look up a Buffer by Ix+lookupBuffer :: BufferIx -> Vector GltfBuffer -> Maybe GltfBuffer+lookupBuffer (BufferIx bufferId) = (Vector.!? bufferId)++-- | Decode a buffer using the given Binary decoder+readFromBuffer+  :: Storable storable+  => storable+  -> Get (Vector storable)+  -> BufferAccessor+  -> Vector storable+readFromBuffer storable getter accessor@BufferAccessor{..}+  = runGet getter . fromStrict $ payload+  where payload = readFromBufferRaw accessor len'+        len' = count * sizeOf storable++-- | Read from buffer without decoding+readFromBufferRaw :: BufferAccessor -> Int -> ByteString+readFromBufferRaw BufferAccessor{..} len'+  = ByteString.take len' . ByteString.drop offset . unBuffer $ buffer
+ src/Text/GLTF/Loader/Internal/Decoders.hs view
@@ -0,0 +1,157 @@+module Text.GLTF.Loader.Internal.Decoders+  ( -- * GLTF Property-specific Type decoders+    getIndices,+    getPositions,+    getNormals,+    getTexCoords,+    -- * GLTF Accessor Type decoders+    getScalar,+    getVec2,+    getVec3,+    getVec4,+    getMat2,+    getMat3,+    getMat4,+    -- * GLTF Component Type decoders+    getByte,+    getUnsignedByte,+    getShort,+    getUnsignedShort,+    getUnsignedInt,+    getFloat+  ) where++import Data.Binary.Get+import Linear+import RIO hiding (min, max)+import qualified RIO.Vector as Vector++-- | Vertex indices binary decoder+getIndices :: Get (Vector Word16)+getIndices = getScalar getUnsignedShort++-- | Vertex positions binary decoder+getPositions :: Get (Vector (V3 Float))+getPositions = getVec3 getFloat++-- | Vertex normals binary decoder+getNormals :: Get (Vector (V3 Float))+getNormals = getVec3 getFloat++-- | Texture coordinates binary decoder+getTexCoords :: Get (Vector (V2 Float))+getTexCoords = getVec2 getFloat++-- | Scalar (simple) type binary decoder+getScalar :: Get a -> Get (Vector a)+getScalar = getVector++-- | 2D Vector binary decoder+getVec2 :: Get a -> Get (Vector (V2 a))+getVec2 getter = getVector $ V2 <$> getter <*> getter++-- | 3D Vector binary decoder+getVec3 :: Get a -> Get (Vector (V3 a))+getVec3 getter = getVector $ V3 <$> getter <*> getter <*> getter++-- | 4D Vector binary decoder+getVec4 :: Get a -> Get (Vector (V4 a))+getVec4 getter = getVector $ V4 <$> getter <*> getter <*> getter <*> getter++-- | 2x2 Matrix binary decoder+getMat2 :: Get a -> Get (Vector (M22 a))+getMat2 getter = getVector $ do+  m1_1 <- getter+  m1_2 <- getter++  m2_1 <- getter+  m2_2 <- getter++  return $ V2+    (V2 m1_1 m2_1)+    (V2 m1_2 m2_2)++-- | 3x3 Matrix binary decoder+getMat3 :: Get a -> Get (Vector (M33 a))+getMat3 getter = getVector $ do+  m1_1 <- getter+  m1_2 <- getter+  m1_3 <- getter+  +  m2_1 <- getter+  m2_2 <- getter+  m2_3 <- getter++  m3_1 <- getter+  m3_2 <- getter+  m3_3 <- getter++  return $ V3+    (V3 m1_1 m2_1 m3_1)+    (V3 m1_2 m2_2 m3_2)+    (V3 m1_3 m2_3 m3_3)++-- | 4x4 Matrix binary decoder+getMat4 :: Get a -> Get (Vector (M44 a))+getMat4 getter = getVector $ do+  m1_1 <- getter+  m1_2 <- getter+  m1_3 <- getter+  m1_4 <- getter+  +  m2_1 <- getter+  m2_2 <- getter+  m2_3 <- getter+  m2_4 <- getter++  m3_1 <- getter+  m3_2 <- getter+  m3_3 <- getter+  m3_4 <- getter++  m4_1 <- getter+  m4_2 <- getter+  m4_3 <- getter+  m4_4 <- getter++  return $ V4+    (V4 m1_1 m2_1 m3_1 m4_1)+    (V4 m1_2 m2_2 m3_2 m4_2)+    (V4 m1_3 m2_3 m3_3 m4_3)+    (V4 m1_4 m2_4 m3_4 m4_4)++-- | Byte binary decoder+getByte :: Get Int8+getByte = getInt8++-- | Unsigned Byte binary decoder+getUnsignedByte :: Get Word8+getUnsignedByte = getWord8++-- | Short binary decoder+getShort :: Get Int16+getShort = getInt16le++-- | Unsigned Short binary decoder+getUnsignedShort :: Get Word16+getUnsignedShort = getWord16le++-- | Unsigned Int binary decoder+getUnsignedInt :: Get Word32+getUnsignedInt = getWord32le++-- | Float binary decoder+getFloat :: Get Float+getFloat = getFloatle++-- | Boxed Vector binary decoder+getVector :: Get a -> Get (Vector a)+getVector = fmap Vector.fromList . getList++-- | List binary decoder+getList :: Get a -> Get [a]+getList getter = do+  empty <- isEmpty+  if empty+    then return []+    else (:) <$> getter <*> getList getter
+ src/Text/GLTF/Loader/Internal/MonadAdapter.hs view
@@ -0,0 +1,29 @@+module Text.GLTF.Loader.Internal.MonadAdapter+  ( Adapter(),+    AdaptEnv(..),+    getGltf,+    getBuffers,+    getImages+  ) where++import Text.GLTF.Loader.Internal.BufferAccessor++import RIO+import qualified Codec.GlTF as GlTF++type Adapter = Reader AdaptEnv++data AdaptEnv = AdaptEnv+  { asGltf :: GlTF.GlTF,+    asBuffers :: Vector GltfBuffer,+    asImages :: Vector GltfImageData+  }++getGltf :: Reader AdaptEnv GlTF.GlTF+getGltf = asks asGltf++getBuffers :: Reader AdaptEnv (Vector GltfBuffer)+getBuffers = asks asBuffers++getImages :: Reader AdaptEnv (Vector GltfImageData)+getImages = asks asImages
− test/Text/GLTF/Loader/AdapterSpec.hs
@@ -1,224 +0,0 @@-module Text.GLTF.Loader.AdapterSpec (spec) where--import Text.GLTF.Loader.Adapter-import Text.GLTF.Loader.BufferAccessor-import Text.GLTF.Loader.Gltf-import Text.GLTF.Loader.Test.MkGltf--import Linear-import RIO-import Test.Hspec-import qualified Codec.GlTF.Material as Material-import qualified Codec.GlTF.Mesh as Mesh-import qualified Codec.GlTF.Node as Node--spec :: Spec-spec = do-  let codecGltf = mkCodecGltf-      codecMeshPrimitive = mkCodecMeshPrimitive--  describe "adaptGltf" $ do-    it "Adapts a basic GlTF" $ do-      buffers' <- buffers-      adaptGltf codecGltf buffers' `shouldBe` loaderGltf--  describe "adaptAsset" $ do-    let codecAsset = mkCodecAsset-    -    it "Adapts a basic asset" $ -      adaptAsset codecAsset `shouldBe` loaderAsset--  describe "adaptMeshes" $ do-    let codecMesh = mkCodecMesh-        codecMesh' = mkCodecMesh { Mesh.weights = Just [3.1] }-    -    it "Adapts a list of nodes" $ do-      buffers' <- buffers-      -      let meshes = Just [codecMesh, codecMesh']-          adaptedMeshes = [loaderMesh, set _meshWeights [3.1] loaderMesh]--      adaptMeshes codecGltf buffers' meshes `shouldBe` adaptedMeshes--    it "Adapts empty meshes" $ do-      buffers' <- buffers-      -      adaptMeshes codecGltf buffers' (Just []) `shouldBe` []-      adaptMeshes codecGltf buffers' Nothing `shouldBe` []--  describe "adaptMaterials" $ do-    let materials = Just [mkCodecMaterial]--    it "Adapts a list of materials" $ do-      adaptMaterials Nothing `shouldBe` []-      adaptMaterials materials `shouldBe` [loaderMaterial]--    it "Ignores PBR metallic roughness when not specified" $ do-      let materials' = Just-            [mkCodecMaterial { Material.pbrMetallicRoughness = Nothing }]-          adaptedMaterial = set _materialPbrMetallicRoughness Nothing loaderMaterial--      adaptMaterials materials' `shouldBe` [adaptedMaterial]--  describe "adaptNodes" $ do-    let codecNode = mkCodecNode-        codecNode' = codecNode { Node.rotation = Nothing }-    -    it "Adapts a list of nodes" $ do-      let nodes = Just [codecNode, codecNode']-      adaptNodes nodes `shouldBe` [loaderNode, set _nodeRotation Nothing loaderNode]--    it "Adapts empty nodes" $ do-      adaptNodes (Just []) `shouldBe` []-      adaptNodes Nothing `shouldBe` []--  describe "adaptMesh" $ do-    let codecMesh = mkCodecMesh-        codecMesh' = mkCodecMesh { Mesh.weights = Nothing }-        codecMesh'' = mkCodecMesh { Mesh.weights = Just [] }-    -    it "Adapts a basic mesh" $ do-      buffers' <- buffers-      adaptMesh codecGltf buffers' codecMesh `shouldBe` loaderMesh--    it "Adapts empty weights" $ do-      buffers' <- buffers-      let meshEmptyWeight = set _meshWeights [] loaderMesh-      -      adaptMesh codecGltf buffers' codecMesh' `shouldBe` meshEmptyWeight-      adaptMesh codecGltf buffers' codecMesh'' `shouldBe` meshEmptyWeight-  -  describe "adaptNode" $ do-    let codecNode = mkCodecNode-        codecNode' = mkCodecNode { Node.weights = Nothing }-        codecNode'' = mkCodecNode { Node.weights = Just [] }-        -    it "Adapts a basic node" $ do-      adaptNode codecNode `shouldBe` loaderNode--    it "Adapts empty weights" $ do-      let nodeEmptyWeight = set _nodeWeights [] loaderNode-      adaptNode codecNode' `shouldBe` nodeEmptyWeight-      adaptNode codecNode'' `shouldBe` nodeEmptyWeight--  describe "adaptAlphaMode" $ do-    it "Adapts all expected modes" $ do-      adaptAlphaMode Material.BLEND `shouldBe` Blend-      adaptAlphaMode Material.MASK `shouldBe` Mask-      adaptAlphaMode Material.OPAQUE `shouldBe` Opaque-      evaluate (adaptAlphaMode $ Material.MaterialAlphaMode "???")-        `shouldThrow` anyErrorCall--  describe "adaptMeshPrimitives" $ do-    let codecMeshPrimitive' = mkCodecMeshPrimitive-          { Mesh.mode = Mesh.MeshPrimitiveMode 0 }-  -    it "adapts a list of primitives" $ do-      buffers' <- buffers-      let primitives = [codecMeshPrimitive, codecMeshPrimitive']-          expectedResult-            = [ loaderMeshPrimitive,-                set _meshPrimitiveMode Points loaderMeshPrimitive-              ]-      -      adaptMeshPrimitives codecGltf buffers' primitives `shouldBe` expectedResult--  describe "adaptMeshPrimitive" $ do-    it "adapts a basic primitive" $ do-      buffers' <- buffers-      adaptMeshPrimitive codecGltf buffers' codecMeshPrimitive `shouldBe` loaderMeshPrimitive--    it "ignores indices when unspecified" $ do-      buffers' <- buffers-      -      let codecMeshPrimitive' = mkCodecMeshPrimitive-            { Mesh.indices = Nothing }-          loaderMeshPrimitive' = loaderMeshPrimitive & _meshPrimitiveIndices .~ []--      adaptMeshPrimitive codecGltf buffers' codecMeshPrimitive' `shouldBe` loaderMeshPrimitive'--    it "ignores material when unspecified" $ do-      buffers' <- buffers--      let codecMeshPrimitive' = mkCodecMeshPrimitive-            { Mesh.material = Nothing }-          loaderMeshPrimitive' = loaderMeshPrimitive & _meshPrimitiveMaterial .~ Nothing--      adaptMeshPrimitive codecGltf buffers' codecMeshPrimitive'-        `shouldBe` loaderMeshPrimitive'-      -    -  describe "adaptMeshPrimitiveMode" $-    it "Adapts all expected modes" $ do-      adaptMeshPrimitiveMode Mesh.POINTS `shouldBe` Points-      adaptMeshPrimitiveMode Mesh.LINES `shouldBe` Lines-      adaptMeshPrimitiveMode Mesh.LINE_LOOP `shouldBe` LineLoop-      adaptMeshPrimitiveMode Mesh.LINE_STRIP `shouldBe` LineStrip-      adaptMeshPrimitiveMode Mesh.TRIANGLES `shouldBe` Triangles-      adaptMeshPrimitiveMode Mesh.TRIANGLE_STRIP `shouldBe` TriangleStrip-      adaptMeshPrimitiveMode Mesh.TRIANGLE_FAN `shouldBe` TriangleFan-      evaluate (adaptMeshPrimitiveMode $ Mesh.MeshPrimitiveMode 7)-        `shouldThrow` anyErrorCall--buffers :: MonadUnliftIO io => io (Vector GltfBuffer)-buffers = loadBuffers mkCodecGltf--loaderGltf :: Gltf-loaderGltf = Gltf-  { gltfAsset = loaderAsset,-    gltfMaterials = [loaderMaterial],-    gltfMeshes = [loaderMesh],-    gltfNodes = [loaderNode]-  }--loaderAsset :: Asset-loaderAsset = Asset-  { assetVersion = "version",-    assetCopyright = Just "copyright",-    assetGenerator = Just "generator",-    assetMinVersion = Just "minVersion"-  }--loaderMaterial :: Material-loaderMaterial = Material-  { materialAlphaCutoff = 1.0,-    materialAlphaMode = Opaque,-    materialDoubleSided = True,-    materialEmissiveFactor = V3 1.0 2.0 3.0,-    materialName = Just "Material",-    materialPbrMetallicRoughness = Just loaderPbrMetallicRoughness-  }--loaderMesh :: Mesh-loaderMesh = Mesh-  { meshPrimitives = [loaderMeshPrimitive],-    meshWeights = [1.2],-    meshName = Just "mesh"-  }--loaderNode :: Node-loaderNode = Node-  { nodeMeshId = Just 5,-    nodeName = Just "node",-    nodeRotation = Just $ V4 1 2 3 4,-    nodeScale = Just $ V3 5 6 7,-    nodeTranslation = Just $ V3 8 9 10,-    nodeWeights = [11, 12, 13]-  }--loaderPbrMetallicRoughness :: PbrMetallicRoughness-loaderPbrMetallicRoughness = PbrMetallicRoughness-  { pbrBaseColorFactor = V4 1.0 2.0 3.0 4.0,-    pbrMetallicFactor = 1.0,-    pbrRoughnessFactor = 2.0-  }--loaderMeshPrimitive :: MeshPrimitive-loaderMeshPrimitive = MeshPrimitive-  { meshPrimitiveIndices = [1..4],-    meshPrimitiveMaterial = Just 1,-    meshPrimitiveMode = Triangles,-    meshPrimitiveNormals = fmap (\x -> V3 x x x) [5..8],-    meshPrimitivePositions = fmap (\x -> V3 x x x) [1..4],-    meshPrimitiveTexCoords = fmap (\x -> V2 x x) [9..12]-  }
− test/Text/GLTF/Loader/BufferAccessorSpec.hs
@@ -1,94 +0,0 @@-module Text.GLTF.Loader.BufferAccessorSpec (spec) where--import Text.GLTF.Loader.BufferAccessor-import Text.GLTF.Loader.Decoders-import Text.GLTF.Loader.Test.MkGltf--import Linear (V3(..))-import Data.Binary.Builder-import Data.Binary.Get (runGet)-import Data.Binary.Put (putFloatle, runPut)-import Data.ByteString.Lazy (fromStrict, toStrict)-import RIO-import RIO.Vector.Partial ((!))-import Test.Hspec-import qualified Codec.GlTF as GlTF-import qualified Codec.GlTF.Accessor as Accessor-import qualified Codec.GlTF.Buffer as Buffer-import qualified Codec.GlTF.BufferView as BufferView-import qualified Codec.GlTF.URI as URI--spec :: Spec-spec = do-  let gltf = mkCodecGltf-  -  describe "loadBuffers" $ do-    it "Reads buffers from GlTF" $ do-      buffers <- loadBuffers gltf-      -      let (GltfBuffer buffer') = buffers ! 0-          values = runGet (getScalar (fromIntegral <$> getUnsignedShort)) . fromStrict $ buffer'-      -      values `shouldBe` ([1..4] :: Vector Integer)--    it "Handles malformed URI" $ do-      let gltf' = gltf-            { GlTF.buffers = Just-                [ mkCodecBufferIndices { Buffer.uri = Just $ URI.URI "uh oh!" } ]-            }--      loadBuffers gltf' `shouldThrow` anyException--    it "Handles no buffer" $ do-      let gltf' = gltf { GlTF.buffers = Nothing }-      buffers <- loadBuffers gltf'--      buffers `shouldBe` []-  -  describe "vertexIndices" $ do-    it "Reads basic values from buffer" $ do-      vertexIndices gltf buffers' accessorIdIndices `shouldBe` [1, 2, 3, 4]--    it "Returns empty when accessor not defined" $ do-      let gltf' = gltf { GlTF.accessors = Nothing } -      vertexIndices gltf' buffers' accessorIdIndices `shouldBe` []--    it "Returns empty when buffer not found" $ do-      let bufferView = mkCodecBufferViewIndices { BufferView.buffer = Buffer.BufferIx 99 }-          gltf' = gltf { GlTF.bufferViews = Just [bufferView] }-      vertexIndices gltf' buffers' accessorIdIndices `shouldBe` []--  describe "vertexPositions" $ do-    it "Reads basic values from buffer" $ do-      vertexPositions gltf buffers' accessorIdPositions `shouldBe`-        [ V3 1 1 1,-          V3 2 2 2,-          V3 3 3 3,-          V3 4 4 4-        ]--    it "Returns empty when accessor not defined" $ do-      let gltf' = gltf { GlTF.accessors = Nothing } -      vertexPositions gltf' buffers' accessorIdPositions `shouldBe` []--    it "Returns empty when buffer not found" $ do-      let bufferView = mkCodecBufferViewIndices { BufferView.buffer = Buffer.BufferIx 99 }-          gltf' = gltf { GlTF.bufferViews = Just [bufferView] }-      vertexPositions gltf' buffers' accessorIdPositions `shouldBe` []--buffers' :: Vector GltfBuffer-buffers' = [bufferIndices, bufferPositions]--accessorIdIndices :: Accessor.AccessorIx-accessorIdIndices = Accessor.AccessorIx 0--accessorIdPositions :: Accessor.AccessorIx-accessorIdPositions = Accessor.AccessorIx 1--bufferIndices :: GltfBuffer-bufferIndices = GltfBuffer . toStrict . toLazyByteString $ putIndices-  where putIndices = foldr ((<>) . putWord16le) empty ([1, 2, 3, 4] :: [Word16])--bufferPositions :: GltfBuffer-bufferPositions = GltfBuffer . toStrict . runPut $ putPositions-  where putPositions = mapM_ (replicateM_ 3 . putFloatle) ([1..4] :: [Float])
+ test/Text/GLTF/Loader/Internal/AdapterSpec.hs view
@@ -0,0 +1,350 @@+module Text.GLTF.Loader.Internal.AdapterSpec (spec) where++import Text.GLTF.Loader.Gltf+import Text.GLTF.Loader.Internal.Adapter+import Text.GLTF.Loader.Internal.BufferAccessor+import Text.GLTF.Loader.Internal.MonadAdapter+import Text.GLTF.Loader.Test.MkGltf++import Linear+import RIO+import Test.Hspec+import qualified Codec.GlTF.BufferView as BufferView+import qualified Codec.GlTF.Image as Image+import qualified Codec.GlTF.Material as Material+import qualified Codec.GlTF.Mesh as Mesh+import qualified Codec.GlTF.Node as Node+import qualified Codec.GlTF.Texture as Texture+import qualified Codec.GlTF.URI as URI++spec :: Spec+spec = do+  let codecGltf = mkCodecGltf+      codecMeshPrimitive = mkCodecMeshPrimitive++  describe "runAdapter" $ do+    it "Runs a basic GlTF adapter" $ do+      buffers' <- buffers+      images' <- images+      +      runAdapter codecGltf buffers' images' `shouldBe` loaderGltf++  describe "adaptGltf" $ do+    it "Adapts a basic GlTF" $ do+      env' <- env+      runReader adaptGltf env' `shouldBe` loaderGltf++  describe "adaptAsset" $ do+    let codecAsset = mkCodecAsset+    +    it "Adapts a basic asset" $ +      adaptAsset codecAsset `shouldBe` loaderAsset++  describe "adaptMeshes" $ do+    let codecMesh = mkCodecMesh+        codecMesh' = mkCodecMesh { Mesh.weights = Just [3.1] }+    +    it "Adapts a list of nodes" $ do+      env' <- env+      +      let meshes = Just [codecMesh, codecMesh']+          adaptedMeshes = [loaderMesh, set _meshWeights [3.1] loaderMesh]++      runReader (adaptMeshes meshes) env' `shouldBe` adaptedMeshes++    it "Adapts empty meshes" $ do+      env' <- env+      +      runReader (adaptMeshes (Just [])) env' `shouldBe` []+      runReader (adaptMeshes Nothing) env' `shouldBe` []++  describe "adaptMaterials" $ do+    let materials = Just [mkCodecMaterial]++    it "Adapts a list of materials" $ do+      adaptMaterials Nothing `shouldBe` []+      adaptMaterials materials `shouldBe` [loaderMaterial]++    it "Ignores PBR metallic roughness when not specified" $ do+      let materials' = Just+            [mkCodecMaterial { Material.pbrMetallicRoughness = Nothing }]+          adaptedMaterial = set _materialPbrMetallicRoughness Nothing loaderMaterial++      adaptMaterials materials' `shouldBe` [adaptedMaterial]++  describe "adaptNodes" $ do+    let codecNode = mkCodecNode+        codecNode' = codecNode { Node.rotation = Nothing }+    +    it "Adapts a list of nodes" $ do+      let nodes = Just [codecNode, codecNode']+      adaptNodes nodes `shouldBe` [loaderNode, set _nodeRotation Nothing loaderNode]++    it "Adapts empty nodes" $ do+      adaptNodes (Just []) `shouldBe` []+      adaptNodes Nothing `shouldBe` []++  describe "adaptImage" $ do+    let codecImage = Image.Image+            { uri = Nothing,+              mimeType = Just "text/jpg",+              bufferView = Just $ BufferView.BufferViewIx 4,+              name = Just "Image",+              extensions = Nothing,+              extras = Nothing+              +            }+    +    it "Adapts a BufferView image" $ do+      env' <- env+      let image = ImageBufferView (BufferView.BufferViewIx 4)+      +      runReader (adaptImage image codecImage) env' `shouldBe`+        Image+          { imageData = Just "imageData",+            imageMimeType = "text/jpg",+            imageName = Just "Image"+          }++    it "Adapts a URI image" $ do+      env' <- env+      +      let image = ImageData "imageData"+          codecImage' = codecImage+            { Image.uri = Just $ URI.URI "",+              Image.bufferView = Nothing+            }++      runReader (adaptImage image codecImage') env' `shouldBe`+        Image+          { imageData = Just "imageData",+            imageMimeType = "text/jpg",+            imageName = Just "Image"+          }++    it "Fails when mimeType is Nothing" $ do+      env' <- env++      let image = ImageData "imageData"+          codecImage' = codecImage { Image.mimeType = Nothing }++      -- evaluate (error "") `shouldThrow` anyErrorCall+      evaluate (runReader (adaptImage image codecImage') env') `shouldThrow` anyErrorCall+      +  describe "adaptMesh" $ do+    let codecMesh = mkCodecMesh+        codecMesh' = mkCodecMesh { Mesh.weights = Nothing }+        codecMesh'' = mkCodecMesh { Mesh.weights = Just [] }+    +    it "Adapts a basic mesh" $ do+      env' <- env+      runReader (adaptMesh codecMesh) env' `shouldBe` loaderMesh++    it "Adapts empty weights" $ do+      env' <- env+      let meshEmptyWeight = set _meshWeights [] loaderMesh+      +      runReader (adaptMesh codecMesh') env' `shouldBe` meshEmptyWeight+      runReader (adaptMesh codecMesh'') env' `shouldBe` meshEmptyWeight+  +  describe "adaptNode" $ do+    it "Adapts a basic node" $ do+      adaptNode mkCodecNode `shouldBe` loaderNode++    it "Adapts empty weights" $ do+      let nodeEmptyWeight = set _nodeWeights [] loaderNode+          codecNodeEmpty = mkCodecNode { Node.weights = Nothing }+          codecNodeNothing = mkCodecNode { Node.weights = Just [] }++      adaptNode codecNodeNothing `shouldBe` nodeEmptyWeight+      adaptNode codecNodeEmpty `shouldBe` nodeEmptyWeight++    it "Adapts empty children" $ do+      let nodeEmptyChildren = set _nodeChildren [] loaderNode+          codecNodeNothing = mkCodecNode { Node.children = Nothing }+          codecNodeEmpty = mkCodecNode { Node.children = Just [] }++      adaptNode codecNodeNothing `shouldBe` nodeEmptyChildren+      adaptNode codecNodeEmpty `shouldBe` nodeEmptyChildren++      ++  describe "adaptTexture" $ do+    it "Adapts simple textures" $ do+      adaptTexture mkCodecTexture `shouldBe` loaderTexture++    it "Returns Nothing fields unchanged" $ do+      let texture = mkCodecTexture+            { Texture.sampler = Nothing,+              Texture.source = Nothing+            }++          expectedResult = loaderTexture+            & _textureSamplerId .~ Nothing+            & _textureSourceId .~ Nothing++      adaptTexture texture `shouldBe` expectedResult++  describe "adaptAlphaMode" $ do+    it "Adapts all expected modes" $ do+      adaptAlphaMode Material.BLEND `shouldBe` Blend+      adaptAlphaMode Material.MASK `shouldBe` Mask+      adaptAlphaMode Material.OPAQUE `shouldBe` Opaque+      evaluate (adaptAlphaMode $ Material.MaterialAlphaMode "???")+        `shouldThrow` anyErrorCall++  describe "adaptMeshPrimitives" $ do+    let codecMeshPrimitive' = mkCodecMeshPrimitive+          { Mesh.mode = Mesh.MeshPrimitiveMode 0 }+  +    it "adapts a list of primitives" $ do+      env' <- env+      let primitives = [codecMeshPrimitive, codecMeshPrimitive']+          expectedResult+            = [ loaderMeshPrimitive,+                set _meshPrimitiveMode Points loaderMeshPrimitive+              ]+      +      runReader (adaptMeshPrimitives primitives) env' `shouldBe` expectedResult++  describe "adaptMeshPrimitive" $ do+    it "adapts a basic primitive" $ do+      env' <- env+      runReader (adaptMeshPrimitive codecMeshPrimitive) env' `shouldBe` loaderMeshPrimitive++    it "ignores indices when unspecified" $ do+      env' <- env+      +      let codecMeshPrimitive' = mkCodecMeshPrimitive+            { Mesh.indices = Nothing }+          loaderMeshPrimitive' = loaderMeshPrimitive & _meshPrimitiveIndices .~ []++      runReader (adaptMeshPrimitive codecMeshPrimitive') env' `shouldBe` loaderMeshPrimitive'++    it "ignores material when unspecified" $ do+      env' <- env++      let codecMeshPrimitive' = mkCodecMeshPrimitive+            { Mesh.material = Nothing }+          loaderMeshPrimitive' = loaderMeshPrimitive & _meshPrimitiveMaterial .~ Nothing++      runReader (adaptMeshPrimitive codecMeshPrimitive') env'+        `shouldBe` loaderMeshPrimitive'+      +    +  describe "adaptMeshPrimitiveMode" $+    it "Adapts all expected modes" $ do+      adaptMeshPrimitiveMode Mesh.POINTS `shouldBe` Points+      adaptMeshPrimitiveMode Mesh.LINES `shouldBe` Lines+      adaptMeshPrimitiveMode Mesh.LINE_LOOP `shouldBe` LineLoop+      adaptMeshPrimitiveMode Mesh.LINE_STRIP `shouldBe` LineStrip+      adaptMeshPrimitiveMode Mesh.TRIANGLES `shouldBe` Triangles+      adaptMeshPrimitiveMode Mesh.TRIANGLE_STRIP `shouldBe` TriangleStrip+      adaptMeshPrimitiveMode Mesh.TRIANGLE_FAN `shouldBe` TriangleFan+      evaluate (adaptMeshPrimitiveMode $ Mesh.MeshPrimitiveMode 7)+        `shouldThrow` anyErrorCall++buffers :: MonadUnliftIO io => io (Vector GltfBuffer)+buffers = loadBuffers mkCodecGltf Nothing basePath+  where basePath = "."++images :: MonadUnliftIO io => io (Vector GltfImageData)+images = loadImages mkCodecGltf basePath+  where basePath = "."++env :: MonadUnliftIO io => io AdaptEnv+env = AdaptEnv mkCodecGltf <$> buffers <*> images++loaderGltf :: Gltf+loaderGltf = Gltf+  { gltfAsset = loaderAsset,+    gltfImages = [loaderImage],+    gltfMaterials = [loaderMaterial],+    gltfMeshes = [loaderMesh],+    gltfNodes = [loaderNode],+    gltfSamplers = [loaderSampler],+    gltfTextures = [loaderTexture]+  }++loaderAsset :: Asset+loaderAsset = Asset+  { assetVersion = "version",+    assetCopyright = Just "copyright",+    assetGenerator = Just "generator",+    assetMinVersion = Just "minVersion"+  }++loaderImage :: Image+loaderImage = Image+  { imageData = Just "imagePayload",+    imageMimeType = "image/png",+    imageName = Just "Image"+  }++loaderMaterial :: Material+loaderMaterial = Material+  { materialAlphaCutoff = 1.0,+    materialAlphaMode = Opaque,+    materialDoubleSided = True,+    materialEmissiveFactor = V3 1.0 2.0 3.0,+    materialName = Just "Material",+    materialPbrMetallicRoughness = Just loaderPbrMetallicRoughness+  }++loaderMesh :: Mesh+loaderMesh = Mesh+  { meshPrimitives = [loaderMeshPrimitive],+    meshWeights = [1.2],+    meshName = Just "mesh"+  }++loaderNode :: Node+loaderNode = Node+  { nodeChildren = [1],+    nodeMeshId = Just 5,+    nodeName = Just "node",+    nodeRotation = Just $ V4 1 2 3 4,+    nodeScale = Just $ V3 5 6 7,+    nodeTranslation = Just $ V3 8 9 10,+    nodeWeights = [11, 12, 13]+  }++loaderSampler :: Sampler+loaderSampler = Sampler+  { samplerMagFilter = Just MagLinear,+    samplerMinFilter = Just MinLinear,+    samplerName = Just "Sampler",+    samplerWrapS = ClampToEdge,+    samplerWrapT = Repeat+  }++loaderTexture :: Texture+loaderTexture = Texture+  { textureName = Just "Texture",+    textureSamplerId = Just 0,+    textureSourceId = Just 0+  }++loaderPbrMetallicRoughness :: PbrMetallicRoughness+loaderPbrMetallicRoughness = PbrMetallicRoughness+  { pbrBaseColorFactor = V4 1.0 2.0 3.0 4.0,+    pbrBaseColorTexture = Just loaderBaseColorTexture,+    pbrMetallicFactor = 1.0,+    pbrRoughnessFactor = 2.0+  }++loaderMeshPrimitive :: MeshPrimitive+loaderMeshPrimitive = MeshPrimitive+  { meshPrimitiveIndices = [1..4],+    meshPrimitiveMaterial = Just 1,+    meshPrimitiveMode = Triangles,+    meshPrimitiveNormals = fmap (\x -> V3 x x x) [5..8],+    meshPrimitivePositions = fmap (\x -> V3 x x x) [1..4],+    meshPrimitiveTexCoords = fmap (\x -> V2 x x) [9..12]+  }++loaderBaseColorTexture :: TextureInfo+loaderBaseColorTexture = TextureInfo+  { textureId = 15,+    textureTexCoord = 10+  }
+ test/Text/GLTF/Loader/Internal/BufferAccessorSpec.hs view
@@ -0,0 +1,162 @@+module Text.GLTF.Loader.Internal.BufferAccessorSpec (spec) where++import Text.GLTF.Loader.Internal.BufferAccessor+import Text.GLTF.Loader.Internal.Decoders+import Text.GLTF.Loader.Test.MkGltf++import Linear (V3(..))+import Data.Binary.Builder+import Data.Binary.Get (runGet)+import Data.Binary.Put (putFloatle, runPut)+import Data.ByteString.Lazy (fromStrict, toStrict)+import RIO+import RIO.Vector.Partial ((!))+import Test.Hspec+import qualified Codec.GlTF as GlTF+import qualified Codec.GlTF.Accessor as Accessor+import qualified Codec.GlTF.Buffer as Buffer+import qualified Codec.GlTF.BufferView as BufferView+import qualified Codec.GlTF.Image as Image+import qualified Codec.GlTF.URI as URI++spec :: Spec+spec = do+  let gltf = mkCodecGltf+      basePath = "."+  +  describe "loadBuffers" $ do+    it "Reads buffers from GlTF" $ do+      buffers <- loadBuffers gltf Nothing basePath+      +      let (GltfBuffer buffer') = buffers ! 0+          values = runGet (getScalar (fromIntegral <$> getUnsignedShort)) . fromStrict $ buffer'+      +      values `shouldBe` ([1..4] :: Vector Integer)++    it "Handles malformed URI" $ do+      let gltf' = gltf+            { GlTF.buffers = Just+                [ mkCodecBufferIndices { Buffer.uri = Just $ URI.URI "uh oh!" } ]+            }++      loadBuffers gltf' Nothing basePath `shouldThrow` anyException++    it "Handles no buffer" $ do+      let gltf' = gltf { GlTF.buffers = Nothing }+      buffers <- loadBuffers gltf' Nothing basePath++      buffers `shouldBe` []++    it "Handles a chunk buffer" $ do+      let chunk = mkCodecBufferChunk+      +          gltf' = gltf+            { GlTF.buffers = Just+              [ mkCodecBufferIndices { Buffer.uri = Nothing } ]+            }+      buffers <- loadBuffers gltf' (Just chunk) basePath+      +      let (GltfBuffer buffer') = buffers ! 0+          values = runGet (getScalar (fromIntegral <$> getUnsignedShort)) . fromStrict $ buffer'+      +      values `shouldBe` ([1..4] :: Vector Integer)+      +    it "Handles chunk + buffers" $ do+      let chunk = mkCodecBufferChunk+      +          gltf' = gltf+            { GlTF.buffers = Just+              [ mkCodecBufferIndices { Buffer.uri = Nothing },+                mkCodecBufferIndices+              ]+            }+      buffers <- loadBuffers gltf' (Just chunk) basePath+      +      let getValue = runGet (getScalar (fromIntegral <$> getUnsignedShort)) . fromStrict++      forM_ buffers $ \buffer -> do+        let value = getValue . unBuffer $ buffer+        value `shouldBe` ([1..4] :: Vector Integer)++  describe "loadImages" $ do+    it "Reads image URIs from GlTF" $ do+      images <- loadImages gltf basePath+      images `shouldBe` [ImageData "imagePayload"]++    it "Reads image BufferViews from GlTF" $ do+      let gltf' = gltf+            { GlTF.images = Just+                [ mkCodecImage { Image.uri = Nothing } ]+            }+      +      images <- loadImages gltf' basePath+      images `shouldBe` [ImageBufferView (BufferView.BufferViewIx 4)]++    it "Returns NoImage when no data specificed" $ do+      let gltf' = gltf+            { GlTF.images = Just+                [ mkCodecImage+                    { Image.uri = Nothing,+                      Image.bufferView = Nothing+                    }+                ]+            }+      +      images <- loadImages gltf' basePath+      images `shouldBe` [NoImageData]++    it "Handles malformed URIs" $ do+      let gltf' = gltf+            { GlTF.images = Just+                [mkCodecImage { Image.uri = Just (URI.URI "Uh oh!") }]+            }++      loadImages gltf' basePath `shouldThrow` anyException+  +  describe "vertexIndices" $ do+    it "Reads basic values from buffer" $ do+      vertexIndices gltf buffers' accessorIdIndices `shouldBe` [1, 2, 3, 4]++    it "Returns empty when accessor not defined" $ do+      let gltf' = gltf { GlTF.accessors = Nothing } +      vertexIndices gltf' buffers' accessorIdIndices `shouldBe` []++    it "Returns empty when buffer not found" $ do+      let bufferView = mkCodecBufferViewIndices { BufferView.buffer = Buffer.BufferIx 99 }+          gltf' = gltf { GlTF.bufferViews = Just [bufferView] }+      vertexIndices gltf' buffers' accessorIdIndices `shouldBe` []++  describe "vertexPositions" $ do+    it "Reads basic values from buffer" $ do+      vertexPositions gltf buffers' accessorIdPositions `shouldBe`+        [ V3 1 1 1,+          V3 2 2 2,+          V3 3 3 3,+          V3 4 4 4+        ]++    it "Returns empty when accessor not defined" $ do+      let gltf' = gltf { GlTF.accessors = Nothing } +      vertexPositions gltf' buffers' accessorIdPositions `shouldBe` []++    it "Returns empty when buffer not found" $ do+      let bufferView = mkCodecBufferViewIndices { BufferView.buffer = Buffer.BufferIx 99 }+          gltf' = gltf { GlTF.bufferViews = Just [bufferView] }+      vertexPositions gltf' buffers' accessorIdPositions `shouldBe` []++buffers' :: Vector GltfBuffer+buffers' = [bufferIndices, bufferPositions]++accessorIdIndices :: Accessor.AccessorIx+accessorIdIndices = Accessor.AccessorIx 0++accessorIdPositions :: Accessor.AccessorIx+accessorIdPositions = Accessor.AccessorIx 1++bufferIndices :: GltfBuffer+bufferIndices = GltfBuffer . toStrict . toLazyByteString $ putIndices+  where putIndices = foldr ((<>) . putWord16le) empty ([1, 2, 3, 4] :: [Word16])++bufferPositions :: GltfBuffer+bufferPositions = GltfBuffer . toStrict . runPut $ putPositions+  where putPositions = mapM_ (replicateM_ 3 . putFloatle) ([1..4] :: [Float])
test/Text/GLTF/Loader/Test/MkGltf.hs view
@@ -1,6 +1,6 @@ module Text.GLTF.Loader.Test.MkGltf where -import Text.GLTF.Loader.Adapter+import Text.GLTF.Loader.Internal.Adapter  import Data.Binary.Builder import Data.Binary.Put (putFloatle, runPut)@@ -9,16 +9,22 @@ import Data.ByteString.Lazy (toStrict) import Foreign (Storable(..)) import Linear-import RIO+import RIO hiding (length)+import RIO.Text (length)+import qualified Codec.GLB as GLB import qualified Codec.GlTF as GlTF import qualified Codec.GlTF.Accessor as Accessor import qualified Codec.GlTF.Asset as Asset import qualified Codec.GlTF.Buffer as Buffer import qualified Codec.GlTF.BufferView as BufferView+import qualified Codec.GlTF.Image as Image import qualified Codec.GlTF.Material as Material import qualified Codec.GlTF.Mesh as Mesh import qualified Codec.GlTF.PbrMetallicRoughness as PbrMetallicRoughness import qualified Codec.GlTF.Node as Node+import qualified Codec.GlTF.Sampler as Sampler+import qualified Codec.GlTF.Texture as Texture+import qualified Codec.GlTF.TextureInfo as TextureInfo import qualified Codec.GlTF.URI as URI import qualified Data.HashMap.Strict as HashMap @@ -38,23 +44,25 @@       [ mkCodecBufferIndices,         mkCodecBufferPositions,         mkCodecBufferNormals,-        mkCodecBufferTexCoords+        mkCodecBufferTexCoords,+        mkCodecBufferImage       ],     bufferViews = Just       [ mkCodecBufferViewIndices,         mkCodecBufferViewPositions,         mkCodecBufferViewNormals,-        mkCodecBufferViewTexCoords+        mkCodecBufferViewTexCoords,+        mkCodecBufferViewImage       ],     cameras = Nothing,-    images = Nothing,+    images = Just [mkCodecImage],     materials = Just [mkCodecMaterial],     meshes = Just [mkCodecMesh],     nodes = Just [mkCodecNode],-    samplers = Nothing,+    samplers = Just [mkCodecSampler],     scenes = Nothing,     skins = Nothing,-    textures = Nothing,+    textures = Just [mkCodecTexture],     extensions = Nothing,     extras = Nothing   }@@ -185,6 +193,28 @@     extras = Nothing   } +mkCodecBufferViewImage :: BufferView.BufferView+mkCodecBufferViewImage = BufferView.BufferView+  { buffer = Buffer.BufferIx 4,+    byteOffset = 0,+    byteLength = length "imageData" * 4,+    byteStride = Nothing,+    target = Nothing,+    name = Just "BufferView Image",+    extensions = Nothing,+    extras = Nothing+  }++mkCodecImage :: Image.Image+mkCodecImage = Image.Image+  { uri = Just (URI.URI "data:image/jpg;base64,aW1hZ2VQYXlsb2Fk"),+    mimeType = Just "image/png",+    bufferView = Just $ BufferView.BufferViewIx 4,+    name = Just "Image",+    extensions = Nothing,+    extras = Nothing+  }+ mkCodecBufferIndices :: Buffer.Buffer mkCodecBufferIndices = Buffer.Buffer   { byteLength = sizeOf (undefined :: Word16) * 4,@@ -221,6 +251,15 @@     name = Just "Buffer Positions"   } +mkCodecBufferImage :: Buffer.Buffer+mkCodecBufferImage = Buffer.Buffer+  { byteLength = length "imageData" * 4,+    uri = Just mkCodecBufferUriImage,+    extensions = Nothing,+    extras = Nothing,+    name = Just "Buffer Image"+  }+ mkCodecMaterial :: Material.Material mkCodecMaterial = Material.Material   { alphaCutoff = 1.0,@@ -251,7 +290,7 @@     metallicFactor = 1.0,     roughnessFactor = 2.0,     metallicRoughnessTexture = Nothing,-    baseColorTexture = Nothing,+    baseColorTexture = Just mkCodecBaseColorTexture,     extensions = Nothing,     extras = Nothing   }@@ -259,7 +298,7 @@ mkCodecBufferUriIndices :: URI.URI mkCodecBufferUriIndices = URI.URI uriText   where uriText = "data:application/octet-stream;base64," <> encodedText-        encodedText = encodeBase64. toStrict . toLazyByteString $ putIndices+        encodedText = encodeBase64 . toStrict . toLazyByteString $ putIndices         putIndices = foldr ((<>) . putWord16le) empty ([1..4] :: [Word16])  mkCodecBufferUriNormals :: URI.URI@@ -280,6 +319,20 @@         encodedText = encodeBase64. toStrict . runPut $ putPositions         putPositions = mapM_ (replicateM_ 2 . putFloatle) ([9..12] :: [Float]) +mkCodecBufferUriImage :: URI.URI+mkCodecBufferUriImage = URI.URI uriText+  where uriText = "data:application/octet-stream;base64," <> encodedText+        encodedText = encodeBase64 . toStrict $ "imageData"++mkCodecBufferChunk :: GLB.Chunk+mkCodecBufferChunk = GLB.Chunk+  { chunkLength = fromIntegral $ sizeOf (undefined :: Word16) * 4,+    chunkType = 0x004E4942,+    chunkData = binary+  }+  where binary = toStrict . toLazyByteString $ putIndices+        putIndices = foldr ((<>) . putWord16le) empty ([1..4] :: [Word16])+ mkCodecMeshPrimitive :: Mesh.MeshPrimitive mkCodecMeshPrimitive = Mesh.MeshPrimitive   { attributes = HashMap.fromList@@ -295,10 +348,19 @@     extras = Nothing   } +mkCodecBaseColorTexture :: TextureInfo.TextureInfo_+mkCodecBaseColorTexture = TextureInfo.TextureInfo+  { extensions = Nothing,+    extras = Nothing,+    index = 15,+    subtype = TextureInfo.Basic,+    texCoord = 10+  }+ mkCodecNode :: Node.Node mkCodecNode = Node.Node   { camera = Nothing,-    children = Nothing,+    children = Just [Node.NodeIx 1],     skin = Nothing,     matrix = Nothing,     mesh = Just (Mesh.MeshIx 5),@@ -307,6 +369,26 @@     translation = Just (8, 9, 10),     weights = Just [11, 12, 13],     name = Just "node",+    extensions = Nothing,+    extras = Nothing+  }++mkCodecSampler :: Sampler.Sampler+mkCodecSampler = Sampler.Sampler+  { extensions = Nothing,+    extras = Nothing,+    magFilter = Just Sampler.MAG_LINEAR,+    minFilter = Just Sampler.MIN_LINEAR,+    name = Just "Sampler",+    wrapS = Sampler.CLAMP_TO_EDGE,+    wrapT = Sampler.REPEAT+  }++mkCodecTexture :: Texture.Texture+mkCodecTexture = Texture.Texture+  { sampler = Just (Sampler.SamplerIx 0),+    source = Just (Image.ImageIx 0),+    name = Just "Texture",     extensions = Nothing,     extras = Nothing   }
test/Text/GLTF/LoaderSpec.hs view
@@ -3,158 +3,223 @@ import Text.GLTF.Loader  import Lens.Micro+import Lens.Micro.Platform () import Linear (V2(..), V3(..), V4(..)) import RIO import Test.Hspec  spec :: Spec spec = do-  describe "fromByteString" $ do+  describe "fromJsonByteString" $ do     it "Parses embedded gltf content" $ do       gltfText <- readFileBinary "data/cube.gltf"-      res <- fromByteString gltfText+      res <- fromJsonByteString gltfText       res `shouldSatisfy` has _Right      it "Fails on invalid content" $ do-      res <- fromByteString "Invalid GLTF"+      res <- fromJsonByteString "Invalid GLTF"       res `shouldSatisfy` has (_Left . _ReadError) -  describe "fromFile" $ do-    it "Parses embedded gltf file" $ do-      gltf <- fromFile "data/cube.gltf"+  describe "fromJsonFile" $ do+    describe "Gltf embedded" $ gltfFromFileTests "data/cube.gltf"+    describe "Gltf separate" $ gltfFromFileTests "data/cube-separate.gltf"++  describe "fromBinaryBinaryString" $ do+    it "parses glb content" $ do+      glb <- readFileBinary "data/cube.glb"+      res <- fromBinaryByteString glb+      res `shouldSatisfy` has _Right++  describe "fromBinaryFile" $ do+    describe "Glb" $ glbFromFileTests "data/cube.glb"++gltfFromFileTests :: FilePath -> Spec+gltfFromFileTests file = fromFileTests file fromJsonFile++glbFromFileTests :: FilePath -> Spec+glbFromFileTests file = fromFileTests file fromFile+  where fromFile path = do+          glb <- fromBinaryFile path+          pure $ over _Right (^. _gltf) glb++fromFileTests+  :: FilePath+  -> (FilePath -> IO (Either Errors Gltf))+  -> Spec+fromFileTests file fromFile = do+  it "Parses embedded gltf file" $ do+      gltf <- fromFile file       gltf `shouldSatisfy` has _Right -    it "Parses expected nodes" $ do-      gltf <- fromFile "data/cube.gltf"-      let expected = Gltf-            { gltfAsset = Asset-                { assetVersion = "2.0",-                  assetGenerator = Just "Khronos glTF Blender I/O v3.2.40",-                  assetCopyright = Nothing,-                  assetMinVersion = Nothing-                },+  it "Parses expected nodes" $ do+      gltf <- fromFile file -              gltfMaterials-                = [ Material-                      { materialAlphaCutoff = 0.5,-                        materialAlphaMode = Opaque,-                        materialDoubleSided = True,-                        materialEmissiveFactor = V3 0.0 0.0 0.0,-                        materialName = Just "Material",-                        materialPbrMetallicRoughness = Just $ PbrMetallicRoughness-                          { pbrBaseColorFactor = V4 0.8 0.8 0.8 1.0,-                            pbrMetallicFactor = 0.0,-                            pbrRoughnessFactor = 0.4-                          }-                      }-                  ],-              -              gltfMeshes-                = [ Mesh-                     { meshPrimitives-                         = [ MeshPrimitive-                               { meshPrimitiveMode = Triangles,-                                 meshPrimitiveIndices-                                   = [ 1, 14, 20, 1, 20, 7, 10, 6, 19, 10, 19, 23,-                                       21, 18, 12, 21, 12, 15, 16, 3, 9, 16, 9,-                                       22, 5, 2, 8, 5, 8, 11, 17, 13, 0, 17, 0, 4-                                     ],-                                 meshPrimitiveMaterial = Just 0,-                                 meshPrimitivePositions-                                   =  [ V3 1.0 1.0 (-1.0),      -- 1-                                        V3 1.0 1.0 (-1.0),      -- 2-                                        V3 1.0 1.0 (-1.0),      -- 3-                                        V3 1.0 (-1.0) (-1.0),   -- 4-                                        V3 1.0 (-1.0) (-1.0),   -- 5-                                        V3 1.0 (-1.0) (-1.0),   -- 6-                                        V3 1.0 1.0 1.0,         -- 7-                                        V3 1.0 1.0 1.0,         -- 8-                                        V3 1.0 1.0 1.0,         -- 9-                                        V3 1.0 (-1.0) 1.0,      -- 10-                                        V3 1.0 (-1.0) 1.0,      -- 11-                                        V3 1.0 (-1.0) 1.0,      -- 12-                                        V3 (-1.0) 1.0 (-1.0),   -- 13-                                        V3 (-1.0) 1.0 (-1.0),   -- 14-                                        V3 (-1.0) 1.0 (-1.0),   -- 15-                                        V3 (-1.0) (-1.0) (-1.0),-- 16-                                        V3 (-1.0) (-1.0) (-1.0),-- 17-                                        V3 (-1.0) (-1.0) (-1.0),-- 18-                                        V3 (-1.0) 1.0 1.0,      -- 19-                                        V3 (-1.0) 1.0 1.0,      -- 20-                                        V3 (-1.0) 1.0 1.0,      -- 21-                                        V3 (-1.0) (-1.0) 1.0,   -- 22-                                        V3 (-1.0) (-1.0) 1.0,   -- 23-                                        V3 (-1.0) (-1.0) 1.0    -- 24-                                      ],-                                 meshPrimitiveNormals-                                   = [ V3 0.0 0.0 (-1.0),-                                       V3 0.0 1.0 (-0.0),-                                       V3 1.0 0.0 (-0.0),-                                       V3 0.0 (-1.0) (-0.0),-                                       V3 0.0 0.0 (-1.0),-                                       V3 1.0 0.0 (-0.0),-                                       V3 0.0 0.0 1.0,-                                       V3 0.0 1.0 (-0.0),-                                       V3 1.0 0.0 (-0.0),-                                       V3 0.0 (-1.0) (-0.0),-                                       V3 0.0 0.0 1.0,-                                       V3 1.0 0.0 (-0.0),-                                       V3 (-1.0) 0.0 (-0.0),-                                       V3 0.0 0.0 (-1.0),-                                       V3 0.0 1.0 (-0.0),-                                       V3 (-1.0) 0.0 (-0.0),-                                       V3 0.0 (-1.0) (-0.0),-                                       V3 0.0 0.0 (-1.0),-                                       V3 (-1.0) 0.0 (-0.0),-                                       V3 0.0 0.0 1.0,-                                       V3 0.0 1.0 (-0.0),-                                       V3 (-1.0) 0.0 (-0.0),-                                       V3 0.0 (-1.0) (-0.0),-                                       V3 0.0 0.0 1.0-                                     ],-                                 meshPrimitiveTexCoords-                                   = [ V2 0.625 0.5,-                                       V2 0.625 0.5,-                                       V2 0.625 0.5,-                                       V2 0.375 0.5,-                                       V2 0.375 0.5,-                                       V2 0.375 0.5,-                                       V2 0.625 0.25,-                                       V2 0.625 0.25,-                                       V2 0.625 0.25,-                                       V2 0.375 0.25,-                                       V2 0.375 0.25,-                                       V2 0.375 0.25,-                                       V2 0.625 0.75,-                                       V2 0.625 0.75,-                                       V2 0.875 0.5,-                                       V2 0.375 0.75,-                                       V2 0.125 0.5,-                                       V2 0.375 0.75,-                                       V2 0.625 1.0,-                                       V2 0.625 0.0,-                                       V2 0.875 0.25,-                                       V2 0.375 1.0,-                                       V2 0.125 0.25,-                                       V2 0.375 0.0-                                     ]-                               }-                           ],-                       meshWeights = [],-                       meshName = Just "Cube"-                     }-                  ],+      let gltf' = gltf ^?! _Right -              gltfNodes-                = [ Node-                      { nodeMeshId = Just 0,-                        nodeName = Just "Cube",-                        nodeRotation = Nothing,-                        nodeScale = Nothing,-                        nodeTranslation = Nothing,-                        nodeWeights = []-                      }-                  ]-            }-      -      gltf `shouldBe` Right expected+      gltf' ^? _asset `shouldBe` Just expectedAsset+      gltf' ^?! _images `shouldSatisfy` \images ->+        images ^? _head . _imageMimeType == Just "image/png" &&+        images ^? _head . _imageName == Just (Just "Untitled")+      gltf' ^? _materials `shouldBe` Just expectedMaterials+      gltf' ^? _meshes `shouldBe` Just expectedMeshes+      gltf' ^? _nodes `shouldBe` Just expectedNodes+      gltf' ^? _samplers `shouldBe` Just expectedSamplers+      gltf' ^? _textures `shouldBe` Just expectedTextures++expectedAsset :: Asset+expectedAsset = Asset+  { assetVersion = "2.0",+    assetGenerator = Just "Khronos glTF Blender I/O v3.3.27",+    assetCopyright = Nothing,+    assetMinVersion = Nothing+  }++expectedMaterials :: Vector Material+expectedMaterials+  = [ Material+      { materialAlphaCutoff = 0.5,+        materialAlphaMode = Opaque,+        materialDoubleSided = True,+        materialEmissiveFactor = V3 0.0 0.0 0.0,+        materialName = Just "Material",+        materialPbrMetallicRoughness = Just $ PbrMetallicRoughness+          { pbrBaseColorFactor = V4 1 1 1 1,+            pbrBaseColorTexture = Just $ TextureInfo+              { textureId = 0,+                textureTexCoord = 0+              },+            pbrMetallicFactor = 0.0,+            pbrRoughnessFactor = 0.5+          }+      }+    ]++expectedMeshes :: Vector Mesh+expectedMeshes+  = [ Mesh+        { meshPrimitives+            = [ MeshPrimitive+                  { meshPrimitiveMode = Triangles,+                    meshPrimitiveIndices+                      = [ 1, 14, 20, 1, 20, 7, 10, 6, 19, 10, 19, 23,+                          21, 18, 12, 21, 12, 15, 16, 3, 9, 16, 9,+                          22, 5, 2, 8, 5, 8, 11, 17, 13, 0, 17, 0, 4+                        ],+                    meshPrimitiveMaterial = Just 0,+                    meshPrimitivePositions+                      =  [ V3 1.0 1.0 (-1.0),      -- 1+                           V3 1.0 1.0 (-1.0),      -- 2+                           V3 1.0 1.0 (-1.0),      -- 3+                           V3 1.0 (-1.0) (-1.0),   -- 4+                           V3 1.0 (-1.0) (-1.0),   -- 5+                           V3 1.0 (-1.0) (-1.0),   -- 6+                           V3 1.0 1.0 1.0,         -- 7+                           V3 1.0 1.0 1.0,         -- 8+                           V3 1.0 1.0 1.0,         -- 9+                           V3 1.0 (-1.0) 1.0,      -- 10+                           V3 1.0 (-1.0) 1.0,      -- 11+                           V3 1.0 (-1.0) 1.0,      -- 12+                           V3 (-1.0) 1.0 (-1.0),   -- 13+                           V3 (-1.0) 1.0 (-1.0),   -- 14+                           V3 (-1.0) 1.0 (-1.0),   -- 15+                           V3 (-1.0) (-1.0) (-1.0),-- 16+                           V3 (-1.0) (-1.0) (-1.0),-- 17+                           V3 (-1.0) (-1.0) (-1.0),-- 18+                           V3 (-1.0) 1.0 1.0,      -- 19+                           V3 (-1.0) 1.0 1.0,      -- 20+                           V3 (-1.0) 1.0 1.0,      -- 21+                           V3 (-1.0) (-1.0) 1.0,   -- 22+                           V3 (-1.0) (-1.0) 1.0,   -- 23+                           V3 (-1.0) (-1.0) 1.0    -- 24+                         ],+                    meshPrimitiveNormals+                      = [ V3 0.0 0.0 (-1.0),+                          V3 0.0 1.0 (-0.0),+                          V3 1.0 0.0 (-0.0),+                          V3 0.0 (-1.0) (-0.0),+                          V3 0.0 0.0 (-1.0),+                          V3 1.0 0.0 (-0.0),+                          V3 0.0 0.0 1.0,+                          V3 0.0 1.0 (-0.0),+                          V3 1.0 0.0 (-0.0),+                          V3 0.0 (-1.0) (-0.0),+                          V3 0.0 0.0 1.0,+                          V3 1.0 0.0 (-0.0),+                          V3 (-1.0) 0.0 (-0.0),+                          V3 0.0 0.0 (-1.0),+                          V3 0.0 1.0 (-0.0),+                          V3 (-1.0) 0.0 (-0.0),+                          V3 0.0 (-1.0) (-0.0),+                          V3 0.0 0.0 (-1.0),+                          V3 (-1.0) 0.0 (-0.0),+                          V3 0.0 0.0 1.0,+                          V3 0.0 1.0 (-0.0),+                          V3 (-1.0) 0.0 (-0.0),+                          V3 0.0 (-1.0) (-0.0),+                          V3 0.0 0.0 1.0+                        ],+                    meshPrimitiveTexCoords+                      = [ V2 0.625 0.5,+                          V2 0.625 0.5,+                          V2 0.625 0.5,+                          V2 0.375 0.5,+                          V2 0.375 0.5,+                          V2 0.375 0.5,+                          V2 0.625 0.25,+                          V2 0.625 0.25,+                          V2 0.625 0.25,+                          V2 0.375 0.25,+                          V2 0.375 0.25,+                          V2 0.375 0.25,+                          V2 0.625 0.75,+                          V2 0.625 0.75,+                          V2 0.875 0.5,+                          V2 0.375 0.75,+                          V2 0.125 0.5,+                          V2 0.375 0.75,+                          V2 0.625 1.0,+                          V2 0.625 0.0,+                          V2 0.875 0.25,+                          V2 0.375 1.0,+                          V2 0.125 0.25,+                          V2 0.375 0.0+                        ]+                  }+              ],+          meshWeights = [],+          meshName = Just "Cube"+        }+    ]++expectedNodes :: Vector Node+expectedNodes =+  [ Node+    { nodeChildren = [],+      nodeMeshId = Just 0,+      nodeName = Just "Cube",+      nodeRotation = Nothing,+      nodeScale = Nothing,+      nodeTranslation = Nothing,+      nodeWeights = []+    }+  ]++expectedSamplers :: Vector Sampler+expectedSamplers+  = [ Sampler+      { samplerMagFilter = Just MagLinear,+        samplerMinFilter = Just MinLinearMipmapLinear,+        samplerName = Nothing,+        samplerWrapS = Repeat,+        samplerWrapT = Repeat+      }+    ]++expectedTextures :: Vector Texture+expectedTextures+  = [ Texture+      { textureName = Nothing,+        textureSamplerId = Just 0,+        textureSourceId = Just 0+      }+    ]