BaseImporter.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. Open Asset Import Library (ASSIMP)
  3. ----------------------------------------------------------------------
  4. Copyright (c) 2006-2010, ASSIMP Development Team
  5. All rights reserved.
  6. Redistribution and use of this software in source and binary forms,
  7. with or without modification, are permitted provided that the
  8. following conditions are met:
  9. * Redistributions of source code must retain the above
  10. copyright notice, this list of conditions and the
  11. following disclaimer.
  12. * Redistributions in binary form must reproduce the above
  13. copyright notice, this list of conditions and the
  14. following disclaimer in the documentation and/or other
  15. materials provided with the distribution.
  16. * Neither the name of the ASSIMP team, nor the names of its
  17. contributors may be used to endorse or promote products
  18. derived from this software without specific prior
  19. written permission of the ASSIMP Development Team.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. ----------------------------------------------------------------------
  32. */
  33. /** @file Definition of the base class for all importer worker classes. */
  34. #ifndef INCLUDED_AI_BASEIMPORTER_H
  35. #define INCLUDED_AI_BASEIMPORTER_H
  36. #include "Exceptional.h"
  37. #include <string>
  38. #include <map>
  39. #include <vector>
  40. #include "./../include/aiTypes.h"
  41. struct aiScene;
  42. namespace Assimp {
  43. class IOSystem;
  44. class Importer;
  45. class BaseImporter;
  46. class BaseProcess;
  47. class SharedPostProcessInfo;
  48. class IOStream;
  49. // utility to do char4 to uint32 in a portable manner
  50. #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
  51. (string[1] << 16) + (string[2] << 8) + string[3]))
  52. // ---------------------------------------------------------------------------
  53. template <typename T>
  54. struct ScopeGuard
  55. {
  56. ScopeGuard(T* obj) : obj(obj), mdismiss() {}
  57. ~ScopeGuard () throw() {
  58. if (!mdismiss) {
  59. delete obj;
  60. }
  61. obj = NULL;
  62. }
  63. T* dismiss() {
  64. mdismiss=true;
  65. return obj;
  66. }
  67. operator T*() {
  68. return obj;
  69. }
  70. T* operator -> () {
  71. return obj;
  72. }
  73. private:
  74. T* obj;
  75. bool mdismiss;
  76. };
  77. //! @cond never
  78. // ---------------------------------------------------------------------------
  79. /** @brief Internal PIMPL implementation for Assimp::Importer
  80. *
  81. * Using this idiom here allows us to drop the dependency from
  82. * std::vector and std::map in the public headers. Furthermore we are dropping
  83. * any STL interface problems caused by mismatching STL settings. All
  84. * size calculation are now done by us, not the app heap. */
  85. class ASSIMP_API ImporterPimpl
  86. {
  87. public:
  88. // Data type to store the key hash
  89. typedef unsigned int KeyType;
  90. // typedefs for our three configuration maps.
  91. // We don't need more, so there is no need for a generic solution
  92. typedef std::map<KeyType, int> IntPropertyMap;
  93. typedef std::map<KeyType, float> FloatPropertyMap;
  94. typedef std::map<KeyType, std::string> StringPropertyMap;
  95. public:
  96. /** IO handler to use for all file accesses. */
  97. IOSystem* mIOHandler;
  98. bool mIsDefaultHandler;
  99. /** Progress handler for feedback. */
  100. ProgressHandler* mProgressHandler;
  101. bool mIsDefaultProgressHandler;
  102. /** Format-specific importer worker objects - one for each format we can read.*/
  103. std::vector<BaseImporter*> mImporter;
  104. /** Post processing steps we can apply at the imported data. */
  105. std::vector<BaseProcess*> mPostProcessingSteps;
  106. /** The imported data, if ReadFile() was successful, NULL otherwise. */
  107. aiScene* mScene;
  108. /** The error description, if there was one. */
  109. std::string mErrorString;
  110. /** List of integer properties */
  111. IntPropertyMap mIntProperties;
  112. /** List of floating-point properties */
  113. FloatPropertyMap mFloatProperties;
  114. /** List of string properties */
  115. StringPropertyMap mStringProperties;
  116. /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step
  117. * to be executed before and after every single postprocess step */
  118. bool bExtraVerbose;
  119. /** Used by post-process steps to share data */
  120. SharedPostProcessInfo* mPPShared;
  121. };
  122. //! @endcond
  123. // ---------------------------------------------------------------------------
  124. /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
  125. * for all importer worker classes.
  126. *
  127. * The interface defines two functions: CanRead() is used to check if the
  128. * importer can handle the format of the given file. If an implementation of
  129. * this function returns true, the importer then calls ReadFile() which
  130. * imports the given file. ReadFile is not overridable, it just calls
  131. * InternReadFile() and catches any ImportErrorException that might occur.
  132. */
  133. class ASSIMP_API BaseImporter
  134. {
  135. friend class Importer;
  136. protected:
  137. /** Constructor to be privately used by #Importer */
  138. BaseImporter();
  139. /** Destructor, private as well */
  140. virtual ~BaseImporter();
  141. public:
  142. // -------------------------------------------------------------------
  143. /** Returns whether the class can handle the format of the given file.
  144. *
  145. * The implementation should be as quick as possible. A check for
  146. * the file extension is enough. If no suitable loader is found with
  147. * this strategy, CanRead() is called again, the 'checkSig' parameter
  148. * set to true this time. Now the implementation is expected to
  149. * perform a full check of the file structure, possibly searching the
  150. * first bytes of the file for magic identifiers or keywords.
  151. *
  152. * @param pFile Path and file name of the file to be examined.
  153. * @param pIOHandler The IO handler to use for accessing any file.
  154. * @param checkSig Set to true if this method is called a second time.
  155. * This time, the implementation may take more time to examine the
  156. * contents of the file to be loaded for magic bytes, keywords, etc
  157. * to be able to load files with unknown/not existent file extensions.
  158. * @return true if the class can read this file, false if not.
  159. */
  160. virtual bool CanRead(
  161. const std::string& pFile,
  162. IOSystem* pIOHandler,
  163. bool checkSig
  164. ) const = 0;
  165. // -------------------------------------------------------------------
  166. /** Imports the given file and returns the imported data.
  167. * If the import succeeds, ownership of the data is transferred to
  168. * the caller. If the import fails, NULL is returned. The function
  169. * takes care that any partially constructed data is destroyed
  170. * beforehand.
  171. *
  172. * @param pImp #Importer object hosting this loader.
  173. * @param pFile Path of the file to be imported.
  174. * @param pIOHandler IO-Handler used to open this and possible other files.
  175. * @return The imported data or NULL if failed. If it failed a
  176. * human-readable error description can be retrieved by calling
  177. * GetErrorText()
  178. *
  179. * @note This function is not intended to be overridden. Implement
  180. * InternReadFile() to do the import. If an exception is thrown somewhere
  181. * in InternReadFile(), this function will catch it and transform it into
  182. * a suitable response to the caller.
  183. */
  184. aiScene* ReadFile(
  185. const Importer* pImp,
  186. const std::string& pFile,
  187. IOSystem* pIOHandler
  188. );
  189. // -------------------------------------------------------------------
  190. /** Returns the error description of the last error that occured.
  191. * @return A description of the last error that occured. An empty
  192. * string if there was no error.
  193. */
  194. const std::string& GetErrorText() const {
  195. return mErrorText;
  196. }
  197. // -------------------------------------------------------------------
  198. /** Called prior to ReadFile().
  199. * The function is a request to the importer to update its configuration
  200. * basing on the Importer's configuration property list.
  201. * @param pImp Importer instance
  202. */
  203. virtual void SetupProperties(
  204. const Importer* pImp
  205. );
  206. protected:
  207. // -------------------------------------------------------------------
  208. /** Called by Importer::GetExtensionList() for each loaded importer.
  209. * Implementations are expected to insert() all file extensions
  210. * handled by them into the extension set. A loader capable of
  211. * reading certain files with the extension BLA would place the
  212. * string bla (lower-case!) in the output set.
  213. * @param extensions Output set. */
  214. virtual void GetExtensionList(
  215. std::set<std::string>& extensions
  216. ) = 0;
  217. // -------------------------------------------------------------------
  218. /** Imports the given file into the given scene structure. The
  219. * function is expected to throw an ImportErrorException if there is
  220. * an error. If it terminates normally, the data in aiScene is
  221. * expected to be correct. Override this function to implement the
  222. * actual importing.
  223. * <br>
  224. * The output scene must meet the following requirements:<br>
  225. * <ul>
  226. * <li>At least a root node must be there, even if its only purpose
  227. * is to reference one mesh.</li>
  228. * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
  229. * in the mesh are determined automatically in this case.</li>
  230. * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
  231. * In fact this means that every vertex that is referenced by
  232. * a face is unique. Or the other way round: a vertex index may
  233. * not occur twice in a single aiMesh.</li>
  234. * <li>aiAnimation::mDuration may be -1. Assimp determines the length
  235. * of the animation automatically in this case as the length of
  236. * the longest animation channel.</li>
  237. * <li>aiMesh::mBitangents may be NULL if tangents and normals are
  238. * given. In this case bitangents are computed as the cross product
  239. * between normal and tangent.</li>
  240. * <li>There needn't be a material. If none is there a default material
  241. * is generated. However, it is recommended practice for loaders
  242. * to generate a default material for yourself that matches the
  243. * default material setting for the file format better than Assimp's
  244. * generic default material. Note that default materials *should*
  245. * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
  246. * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
  247. * texture. </li>
  248. * </ul>
  249. * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
  250. * <li> at least one mesh must be there</li>
  251. * <li> there may be no meshes with 0 vertices or faces</li>
  252. * </ul>
  253. * This won't be checked (except by the validation step): Assimp will
  254. * crash if one of the conditions is not met!
  255. *
  256. * @param pFile Path of the file to be imported.
  257. * @param pScene The scene object to hold the imported data.
  258. * NULL is not a valid parameter.
  259. * @param pIOHandler The IO handler to use for any file access.
  260. * NULL is not a valid parameter. */
  261. virtual void InternReadFile(
  262. const std::string& pFile,
  263. aiScene* pScene,
  264. IOSystem* pIOHandler
  265. ) = 0;
  266. public: // static utilities
  267. // -------------------------------------------------------------------
  268. /** A utility for CanRead().
  269. *
  270. * The function searches the header of a file for a specific token
  271. * and returns true if this token is found. This works for text
  272. * files only. There is a rudimentary handling of UNICODE files.
  273. * The comparison is case independent.
  274. *
  275. * @param pIOSystem IO System to work with
  276. * @param file File name of the file
  277. * @param tokens List of tokens to search for
  278. * @param numTokens Size of the token array
  279. * @param searchBytes Number of bytes to be searched for the tokens.
  280. */
  281. static bool SearchFileHeaderForToken(
  282. IOSystem* pIOSystem,
  283. const std::string& file,
  284. const char** tokens,
  285. unsigned int numTokens,
  286. unsigned int searchBytes = 200);
  287. // -------------------------------------------------------------------
  288. /** @brief Check whether a file has a specific file extension
  289. * @param pFile Input file
  290. * @param ext0 Extension to check for. Lowercase characters only, no dot!
  291. * @param ext1 Optional second extension
  292. * @param ext2 Optional third extension
  293. * @note Case-insensitive
  294. */
  295. static bool SimpleExtensionCheck (
  296. const std::string& pFile,
  297. const char* ext0,
  298. const char* ext1 = NULL,
  299. const char* ext2 = NULL);
  300. // -------------------------------------------------------------------
  301. /** @brief Extract file extension from a string
  302. * @param pFile Input file
  303. * @return Extension without trailing dot, all lowercase
  304. */
  305. static std::string GetExtension (
  306. const std::string& pFile);
  307. // -------------------------------------------------------------------
  308. /** @brief Check whether a file starts with one or more magic tokens
  309. * @param pFile Input file
  310. * @param pIOHandler IO system to be used
  311. * @param magic n magic tokens
  312. * @params num Size of magic
  313. * @param offset Offset from file start where tokens are located
  314. * @param Size of one token, in bytes. Maximally 16 bytes.
  315. * @return true if one of the given tokens was found
  316. *
  317. * @note For convinence, the check is also performed for the
  318. * byte-swapped variant of all tokens (big endian). Only for
  319. * tokens of size 2,4.
  320. */
  321. static bool CheckMagicToken(
  322. IOSystem* pIOHandler,
  323. const std::string& pFile,
  324. const void* magic,
  325. unsigned int num,
  326. unsigned int offset = 0,
  327. unsigned int size = 4);
  328. // -------------------------------------------------------------------
  329. /** An utility for all text file loaders. It converts a file to our
  330. * UTF8 character set. Errors are reported, but ignored.
  331. *
  332. * @param data File buffer to be converted to UTF8 data. The buffer
  333. * is resized as appropriate. */
  334. static void ConvertToUTF8(
  335. std::vector<char>& data);
  336. // -------------------------------------------------------------------
  337. /** Utility for text file loaders which copies the contents of the
  338. * file into a memory buffer and converts it to our UTF8
  339. * representation.
  340. * @param stream Stream to read from.
  341. * @param data Output buffer to be resized and filled with the
  342. * converted text file data. The buffer is terminated with
  343. * a binary 0. */
  344. static void TextFileToBuffer(
  345. IOStream* stream,
  346. std::vector<char>& data);
  347. protected:
  348. /** Error description in case there was one. */
  349. std::string mErrorText;
  350. /** Currently set progress handler */
  351. ProgressHandler* progress;
  352. };
  353. struct BatchData;
  354. // ---------------------------------------------------------------------------
  355. /** FOR IMPORTER PLUGINS ONLY: A helper class for the pleasure of importers
  356. * which need to load many extern meshes recursively.
  357. *
  358. * The class uses several threads to load these meshes (or at least it
  359. * could, this has not yet been implemented at the moment).
  360. *
  361. * @note The class may not be used by more than one thread*/
  362. class ASSIMP_API BatchLoader
  363. {
  364. // friend of Importer
  365. public:
  366. //! @cond never
  367. // -------------------------------------------------------------------
  368. /** Wraps a full list of configuration properties for an importer.
  369. * Properties can be set using SetGenericProperty */
  370. struct PropertyMap
  371. {
  372. ImporterPimpl::IntPropertyMap ints;
  373. ImporterPimpl::FloatPropertyMap floats;
  374. ImporterPimpl::StringPropertyMap strings;
  375. bool operator == (const PropertyMap& prop) const {
  376. // fixme: really isocpp? gcc complains
  377. return ints == prop.ints && floats == prop.floats && strings == prop.strings;
  378. }
  379. bool empty () const {
  380. return ints.empty() && floats.empty() && strings.empty();
  381. }
  382. };
  383. //! @endcond
  384. public:
  385. // -------------------------------------------------------------------
  386. /** Construct a batch loader from a given IO system to be used
  387. * to acess external files */
  388. BatchLoader(IOSystem* pIO);
  389. ~BatchLoader();
  390. // -------------------------------------------------------------------
  391. /** Add a new file to the list of files to be loaded.
  392. * @param file File to be loaded
  393. * @param steps Post-processing steps to be executed on the file
  394. * @param map Optional configuration properties
  395. * @return 'Load request channel' - an unique ID that can later
  396. * be used to access the imported file data.
  397. * @see GetImport */
  398. unsigned int AddLoadRequest (
  399. const std::string& file,
  400. unsigned int steps = 0,
  401. const PropertyMap* map = NULL
  402. );
  403. // -------------------------------------------------------------------
  404. /** Get an imported scene.
  405. * This polls the import from the internal request list.
  406. * If an import is requested several times, this function
  407. * can be called several times, too.
  408. *
  409. * @param which LRWC returned by AddLoadRequest().
  410. * @return NULL if there is no scene with this file name
  411. * in the queue of the scene hasn't been loaded yet. */
  412. aiScene* GetImport(
  413. unsigned int which
  414. );
  415. // -------------------------------------------------------------------
  416. /** Waits until all scenes have been loaded. This returns
  417. * immediately if no scenes are queued.*/
  418. void LoadAll();
  419. private:
  420. // No need to have that in the public API ...
  421. BatchData* data;
  422. };
  423. } // end of namespace Assimp
  424. #endif // AI_BASEIMPORTER_H_INC