Exporter.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (assimp)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2025, assimp team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the assimp team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the assimp team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file Exporter.hpp
  35. * @brief Defines the CPP-API for the Assimp export interface
  36. */
  37. #pragma once
  38. #ifndef AI_EXPORT_HPP_INC
  39. #define AI_EXPORT_HPP_INC
  40. #ifdef __GNUC__
  41. #pragma GCC system_header
  42. #endif
  43. #ifndef ASSIMP_BUILD_NO_EXPORT
  44. #include "cexport.h"
  45. #include <map>
  46. #include <functional>
  47. namespace Assimp {
  48. class ExporterPimpl;
  49. class IOSystem;
  50. class ProgressHandler;
  51. // ----------------------------------------------------------------------------------
  52. /** CPP-API: The Exporter class forms an C++ interface to the export functionality
  53. * of the Open Asset Import Library. Note that the export interface is available
  54. * only if Assimp has been built with ASSIMP_BUILD_NO_EXPORT not defined.
  55. *
  56. * The interface is modeled after the importer interface and mostly
  57. * symmetric. The same rules for threading etc. apply.
  58. *
  59. * In a nutshell, there are two export interfaces: #Export, which writes the
  60. * output file(s) either to the regular file system or to a user-supplied
  61. * #IOSystem, and #ExportToBlob which returns a linked list of memory
  62. * buffers (blob), each referring to one output file (in most cases
  63. * there will be only one output file of course, but this extra complexity is
  64. * needed since Assimp aims at supporting a wide range of file formats).
  65. *
  66. * #ExportToBlob is especially useful if you intend to work
  67. * with the data in-memory.
  68. */
  69. class ASSIMP_API ExportProperties;
  70. class ASSIMP_API Exporter {
  71. public:
  72. /** Function pointer type of a Export worker function */
  73. typedef void (*fpExportFunc)(const char *, IOSystem *, const aiScene *, const ExportProperties *);
  74. /** Internal description of an Assimp export format option */
  75. struct ExportFormatEntry {
  76. /// Public description structure to be returned by aiGetExportFormatDescription()
  77. aiExportFormatDesc mDescription;
  78. // Worker function to do the actual exporting
  79. fpExportFunc mExportFunction;
  80. // Post-processing steps to be executed PRIOR to invoking mExportFunction
  81. unsigned int mEnforcePP;
  82. // Constructor to fill all entries
  83. ExportFormatEntry(const char *pId, const char *pDesc, const char *pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u) {
  84. mDescription.id = pId;
  85. mDescription.description = pDesc;
  86. mDescription.fileExtension = pExtension;
  87. mExportFunction = pFunction;
  88. mEnforcePP = pEnforcePP;
  89. }
  90. ExportFormatEntry() :
  91. mExportFunction(),
  92. mEnforcePP() {
  93. mDescription.id = nullptr;
  94. mDescription.description = nullptr;
  95. mDescription.fileExtension = nullptr;
  96. }
  97. };
  98. /**
  99. * @brief The class constructor.
  100. */
  101. Exporter();
  102. /**
  103. * @brief The class destructor.
  104. */
  105. ~Exporter();
  106. // -------------------------------------------------------------------
  107. /** Supplies a custom IO handler to the exporter to use to open and
  108. * access files.
  109. *
  110. * If you need #Export to use custom IO logic to access the files,
  111. * you need to supply a custom implementation of IOSystem and
  112. * IOFile to the exporter.
  113. *
  114. * #Exporter takes ownership of the object and will destroy it
  115. * afterwards. The previously assigned handler will be deleted.
  116. * Pass NULL to take again ownership of your IOSystem and reset Assimp
  117. * to use its default implementation, which uses plain file IO.
  118. *
  119. * @param pIOHandler The IO handler to be used in all file accesses
  120. * of the Importer. */
  121. void SetIOHandler(IOSystem *pIOHandler);
  122. // -------------------------------------------------------------------
  123. /** Retrieves the IO handler that is currently set.
  124. * You can use #IsDefaultIOHandler() to check whether the returned
  125. * interface is the default IO handler provided by ASSIMP. The default
  126. * handler is active as long the application doesn't supply its own
  127. * custom IO handler via #SetIOHandler().
  128. * @return A valid IOSystem interface, never NULL. */
  129. IOSystem *GetIOHandler() const;
  130. // -------------------------------------------------------------------
  131. /** Checks whether a default IO handler is active
  132. * A default handler is active as long the application doesn't
  133. * supply its own custom IO handler via #SetIOHandler().
  134. * @return true by default */
  135. bool IsDefaultIOHandler() const;
  136. // -------------------------------------------------------------------
  137. /** Supplies a custom progress handler to the exporter. This
  138. * interface exposes an #Update() callback, which is called
  139. * more or less periodically (please don't sue us if it
  140. * isn't as periodically as you'd like it to have ...).
  141. * This can be used to implement progress bars and loading
  142. * timeouts.
  143. * @param pHandler Progress callback interface. Pass nullptr to
  144. * disable progress reporting.
  145. * @note Progress handlers can be used to abort the loading
  146. * at almost any time.*/
  147. void SetProgressHandler(ProgressHandler *pHandler);
  148. // -------------------------------------------------------------------
  149. /** Exports the given scene to a chosen file format. Returns the exported
  150. * data as a binary blob which you can write into a file or something.
  151. * When you're done with the data, simply let the #Exporter instance go
  152. * out of scope to have it released automatically.
  153. * @param pScene The scene to export. Stays in possession of the caller,
  154. * is not changed by the function.
  155. * @param pFormatId ID string to specify to which format you want to
  156. * export to. Use
  157. * #GetExportFormatCount / #GetExportFormatDescription to learn which
  158. * export formats are available.
  159. * @param pPreprocessing See the documentation for #Export
  160. * @return the exported data or nullptr in case of error.
  161. * @note If the Exporter instance did already hold a blob from
  162. * a previous call to #ExportToBlob, it will be disposed.
  163. * Any IO handlers set via #SetIOHandler are ignored here.
  164. * @note Use aiCopyScene() to get a modifiable copy of a previously
  165. * imported scene. */
  166. const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const char *pFormatId,
  167. unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
  168. const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const std::string &pFormatId,
  169. unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
  170. // -------------------------------------------------------------------
  171. /** Convenience function to export directly to a file. Use
  172. * #SetIOSystem to supply a custom IOSystem to gain fine-grained control
  173. * about the output data flow of the export process.
  174. * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be nullptr.
  175. * @param pPath Full target file name. Target must be accessible.
  176. * @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
  177. * flags, but in reality only a subset of them makes sense here. Specifying
  178. * 'preprocessing' flags is useful if the input scene does not conform to
  179. * Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
  180. * In short, this means the geometry data should use a right-handed coordinate systems, face
  181. * winding should be counter-clockwise and the UV coordinate origin is assumed to be in
  182. * the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
  183. * #aiProcess_FlipWindingOrder flags are used in the import side to allow users
  184. * to have those defaults automatically adapted to their conventions. Specifying those flags
  185. * for exporting has the opposite effect, respectively. Some other of the
  186. * #aiPostProcessSteps enumerated values may be useful as well, but you'll need
  187. * to try out what their effect on the exported file is. Many formats impose
  188. * their own restrictions on the structure of the geometry stored therein,
  189. * so some preprocessing may have little or no effect at all, or may be
  190. * redundant as exporters would apply them anyhow. A good example
  191. * is triangulation - whilst you can enforce it by specifying
  192. * the #aiProcess_Triangulate flag, most export formats support only
  193. * triangulate data so they would run the step even if it wasn't requested.
  194. *
  195. * If assimp detects that the input scene was directly taken from the importer side of
  196. * the library (i.e. not copied using aiCopyScene and potentially modified afterwards),
  197. * any post-processing steps already applied to the scene will not be applied again, unless
  198. * they show non-idempotent behavior (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
  199. * #aiProcess_FlipWindingOrder).
  200. * @return AI_SUCCESS if everything was fine.
  201. * @note Use aiCopyScene() to get a modifiable copy of a previously
  202. * imported scene.*/
  203. aiReturn Export(const aiScene *pScene, const char *pFormatId, const char *pPath,
  204. unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
  205. aiReturn Export(const aiScene *pScene, const std::string &pFormatId, const std::string &pPath,
  206. unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
  207. // -------------------------------------------------------------------
  208. /** Returns an error description of an error that occurred in #Export
  209. * or #ExportToBlob
  210. *
  211. * Returns an empty string if no error occurred.
  212. * @return A description of the last error, an empty string if no
  213. * error occurred. The string is never nullptr.
  214. *
  215. * @note The returned function remains valid until one of the
  216. * following methods is called: #Export, #ExportToBlob, #FreeBlob */
  217. const char *GetErrorString() const;
  218. // -------------------------------------------------------------------
  219. /** Return the blob obtained from the last call to #ExportToBlob */
  220. const aiExportDataBlob *GetBlob() const;
  221. // -------------------------------------------------------------------
  222. /** Orphan the blob from the last call to #ExportToBlob. This means
  223. * the caller takes ownership and is thus responsible for calling
  224. * the C API function #aiReleaseExportBlob to release it. */
  225. const aiExportDataBlob *GetOrphanedBlob() const;
  226. // -------------------------------------------------------------------
  227. /** Frees the current blob.
  228. *
  229. * The function does nothing if no blob has previously been
  230. * previously produced via #ExportToBlob. #FreeBlob is called
  231. * automatically by the destructor. The only reason to call
  232. * it manually would be to reclaim as much storage as possible
  233. * without giving up the #Exporter instance yet. */
  234. void FreeBlob();
  235. // -------------------------------------------------------------------
  236. /** Returns the number of export file formats available in the current
  237. * Assimp build. Use #Exporter::GetExportFormatDescription to
  238. * retrieve infos of a specific export format.
  239. *
  240. * This includes built-in exporters as well as exporters registered
  241. * using #RegisterExporter.
  242. **/
  243. size_t GetExportFormatCount() const;
  244. // -------------------------------------------------------------------
  245. /** Returns a description of the nth export file format. Use #
  246. * #Exporter::GetExportFormatCount to learn how many export
  247. * formats are supported.
  248. *
  249. * The returned pointer is of static storage duration if the
  250. * pIndex pertains to a built-in exporter (i.e. one not registered
  251. * via #RegistrerExporter). It is restricted to the life-time of the
  252. * #Exporter instance otherwise.
  253. *
  254. * @param pIndex Index of the export format to retrieve information
  255. * for. Valid range is 0 to #Exporter::GetExportFormatCount
  256. * @return A description of that specific export format.
  257. * NULL if pIndex is out of range. */
  258. const aiExportFormatDesc *GetExportFormatDescription(size_t pIndex) const;
  259. // -------------------------------------------------------------------
  260. /** Register a custom exporter. Custom export formats are limited to
  261. * to the current #Exporter instance and do not affect the
  262. * library globally. The indexes under which the format's
  263. * export format description can be queried are assigned
  264. * monotonously.
  265. * @param desc Exporter description.
  266. * @return aiReturn_SUCCESS if the export format was successfully
  267. * registered. A common cause that would prevent an exporter
  268. * from being registered is that its format id is already
  269. * occupied by another format. */
  270. aiReturn RegisterExporter(const ExportFormatEntry &desc);
  271. // -------------------------------------------------------------------
  272. /** Remove an export format previously registered with #RegisterExporter
  273. * from the #Exporter instance (this can also be used to drop
  274. * built-in exporters because those are implicitly registered
  275. * using #RegisterExporter).
  276. * @param id Format id to be unregistered, this refers to the
  277. * 'id' field of #aiExportFormatDesc.
  278. * @note Calling this method on a format description not yet registered
  279. * has no effect.*/
  280. void UnregisterExporter(const char *id);
  281. protected:
  282. // Just because we don't want you to know how we're hacking around.
  283. ExporterPimpl *pimpl;
  284. };
  285. class ASSIMP_API ExportProperties {
  286. public:
  287. // Data type to store the key hash
  288. typedef unsigned int KeyType;
  289. // typedefs for our four configuration maps.
  290. // We don't need more, so there is no need for a generic solution
  291. typedef std::map<KeyType, int> IntPropertyMap;
  292. typedef std::map<KeyType, ai_real> FloatPropertyMap;
  293. typedef std::map<KeyType, std::string> StringPropertyMap;
  294. typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
  295. typedef std::map<KeyType, std::function<void *(void *)>> CallbackPropertyMap;
  296. public:
  297. /** Standard constructor
  298. * @see ExportProperties()
  299. */
  300. ExportProperties();
  301. // -------------------------------------------------------------------
  302. /** Copy constructor.
  303. *
  304. * This copies the configuration properties of another ExportProperties.
  305. * @see ExportProperties(const ExportProperties& other)
  306. */
  307. ExportProperties(const ExportProperties &other);
  308. // -------------------------------------------------------------------
  309. /** Set an integer configuration property.
  310. * @param szName Name of the property. All supported properties
  311. * are defined in the aiConfig.g header (all constants share the
  312. * prefix AI_CONFIG_XXX and are simple strings).
  313. * @param iValue New value of the property
  314. * @return true if the property was set before. The new value replaces
  315. * the previous value in this case.
  316. * @note Property of different types (float, int, string ..) are kept
  317. * on different stacks, so calling SetPropertyInteger() for a
  318. * floating-point property has no effect - the loader will call
  319. * GetPropertyFloat() to read the property, but it won't be there.
  320. */
  321. bool SetPropertyInteger(const char *szName, int iValue);
  322. // -------------------------------------------------------------------
  323. /** Set a boolean configuration property. Boolean properties
  324. * are stored on the integer stack internally so it's possible
  325. * to set them via #SetPropertyBool and query them with
  326. * #GetPropertyBool and vice versa.
  327. * @see SetPropertyInteger()
  328. */
  329. bool SetPropertyBool(const char *szName, bool value) {
  330. return SetPropertyInteger(szName, value);
  331. }
  332. // -------------------------------------------------------------------
  333. /** Set a floating-point configuration property.
  334. * @see SetPropertyInteger()
  335. */
  336. bool SetPropertyFloat(const char *szName, ai_real fValue);
  337. // -------------------------------------------------------------------
  338. /** Set a string configuration property.
  339. * @see SetPropertyInteger()
  340. */
  341. bool SetPropertyString(const char *szName, const std::string &sValue);
  342. // -------------------------------------------------------------------
  343. /** Set a matrix configuration property.
  344. * @see SetPropertyInteger()
  345. */
  346. bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue);
  347. bool SetPropertyCallback(const char *szName, const std::function<void *(void *)> &f);
  348. // -------------------------------------------------------------------
  349. /** Get a configuration property.
  350. * @param szName Name of the property. All supported properties
  351. * are defined in the aiConfig.g header (all constants share the
  352. * prefix AI_CONFIG_XXX).
  353. * @param iErrorReturn Value that is returned if the property
  354. * is not found.
  355. * @return Current value of the property
  356. * @note Property of different types (float, int, string ..) are kept
  357. * on different lists, so calling SetPropertyInteger() for a
  358. * floating-point property has no effect - the loader will call
  359. * GetPropertyFloat() to read the property, but it won't be there.
  360. */
  361. int GetPropertyInteger(const char *szName,
  362. int iErrorReturn = 0xffffffff) const;
  363. // -------------------------------------------------------------------
  364. /** Get a boolean configuration property. Boolean properties
  365. * are stored on the integer stack internally so it's possible
  366. * to set them via #SetPropertyBool and query them with
  367. * #GetPropertyBool and vice versa.
  368. * @see GetPropertyInteger()
  369. */
  370. bool GetPropertyBool(const char *szName, bool bErrorReturn = false) const {
  371. return GetPropertyInteger(szName, bErrorReturn) != 0;
  372. }
  373. // -------------------------------------------------------------------
  374. /** Get a floating-point configuration property
  375. * @see GetPropertyInteger()
  376. */
  377. ai_real GetPropertyFloat(const char *szName,
  378. ai_real fErrorReturn = 10e10f) const;
  379. // -------------------------------------------------------------------
  380. /** Get a string configuration property
  381. *
  382. * The return value remains valid until the property is modified.
  383. * @see GetPropertyInteger()
  384. */
  385. const std::string GetPropertyString(const char *szName,
  386. const std::string &sErrorReturn = "") const;
  387. // -------------------------------------------------------------------
  388. /** Get a matrix configuration property
  389. *
  390. * The return value remains valid until the property is modified.
  391. * @see GetPropertyInteger()
  392. */
  393. const aiMatrix4x4 GetPropertyMatrix(const char *szName,
  394. const aiMatrix4x4 &sErrorReturn = aiMatrix4x4()) const;
  395. std::function<void *(void *)> GetPropertyCallback(const char* szName) const;
  396. // -------------------------------------------------------------------
  397. /** Determine a integer configuration property has been set.
  398. * @see HasPropertyInteger()
  399. */
  400. bool HasPropertyInteger(const char *szName) const;
  401. /** Determine a boolean configuration property has been set.
  402. * @see HasPropertyBool()
  403. */
  404. bool HasPropertyBool(const char *szName) const;
  405. /** Determine a boolean configuration property has been set.
  406. * @see HasPropertyFloat()
  407. */
  408. bool HasPropertyFloat(const char *szName) const;
  409. /** Determine a String configuration property has been set.
  410. * @see HasPropertyString()
  411. */
  412. bool HasPropertyString(const char *szName) const;
  413. /** Determine a Matrix configuration property has been set.
  414. * @see HasPropertyMatrix()
  415. */
  416. bool HasPropertyMatrix(const char *szName) const;
  417. bool HasPropertyCallback(const char *szName) const;
  418. /** List of integer properties */
  419. IntPropertyMap mIntProperties;
  420. /** List of floating-point properties */
  421. FloatPropertyMap mFloatProperties;
  422. /** List of string properties */
  423. StringPropertyMap mStringProperties;
  424. /** List of Matrix properties */
  425. MatrixPropertyMap mMatrixProperties;
  426. CallbackPropertyMap mCallbackProperties;
  427. };
  428. // ----------------------------------------------------------------------------------
  429. inline const aiExportDataBlob *Exporter::ExportToBlob(const aiScene *pScene, const std::string &pFormatId,
  430. unsigned int pPreprocessing, const ExportProperties *pProperties) {
  431. return ExportToBlob(pScene, pFormatId.c_str(), pPreprocessing, pProperties);
  432. }
  433. // ----------------------------------------------------------------------------------
  434. inline aiReturn Exporter ::Export(const aiScene *pScene, const std::string &pFormatId,
  435. const std::string &pPath, unsigned int pPreprocessing,
  436. const ExportProperties *pProperties) {
  437. return Export(pScene, pFormatId.c_str(), pPath.c_str(), pPreprocessing, pProperties);
  438. }
  439. } // namespace Assimp
  440. #endif // ASSIMP_BUILD_NO_EXPORT
  441. #endif // AI_EXPORT_HPP_INC