{-# OPTIONS_GHC -Wall #-} ---------------------------------------------------------------------- -- | -- Module : Graphics.Formats.Obj -- Copyright : (c) Anygma BVBA & Thomas Davie 2008 -- License : BSD3 -- -- Maintainer : tom.davie@gmail.com -- Stability : experimental -- -- Obj model loader ---------------------------------------------------------------------- module Graphics.Formats.Obj (objFromFile ,ObjModel ) where import Data.Binary import Control.Applicative import System.Directory import System.FilePath import qualified Data.Map as M import Data.Maybe hiding (fromJust) import Graphics.Formats.Obj.Parse import Graphics.Formats.Obj.ObjModel import Graphics.Formats.Mtl.Contents import Graphics.Formats.Mtl.Parse () import qualified Data.ByteString.Char8 as CBS -- | Loads an Obj model from a file given a list of search paths to find -- materials and textures at. objFromFile :: FilePath -> [FilePath] -> IO ObjModel objFromFile x sps = do -- Parse the obj cs <- decodeFile x -- Find the material files and parse them too let mtlfs = map CBS.unpack $ mtllibs cs files <- mapM (findFile sps) mtlfs mapM_ (putStrLn . ("Warning: File not found: " ++) . fst) . filter ((==Nothing) . snd) $ zip mtlfs files parsedMats <- mapM decodeFile (catMaybes files) let ms = MF . M.unions . map (\(MF a) -> a) $ parsedMats -- Now find all the textures and load them (missingTexFiles,ms') <- loadTextures (findFile sps) ms mapM_ (putStrLn . ("Warning: File not found: " ++)) missingTexFiles -- Put everything together and hand it back return $ geometry cs ms' -- | Finds a file given a list of search paths to look for it at. -- The first file found is returned. findFile :: [FilePath] -> FilePath -> IO (Maybe FilePath) findFile sps f = (listToMaybe . catMaybes) <$> (mapM (tryFile f) sps) -- | Checks if a file exists at a specified search path -- If it does, returns that filepath in a maybe tryFile :: FilePath -> FilePath -> IO (Maybe FilePath) tryFile x y = do e <- doesFileExist (y x) if e then return . Just $ (y x) else return Nothing