| /* |
| --------------------------------------------------------------------------- |
| Open Asset Import Library (assimp) |
| --------------------------------------------------------------------------- |
| |
| Copyright (c) 2006-2017, assimp team |
| |
| |
| All rights reserved. |
| |
| Redistribution and use of this software in source and binary forms, |
| with or without modification, are permitted provided that the following |
| conditions are met: |
| |
| * Redistributions of source code must retain the above |
| copyright notice, this list of conditions and the |
| following disclaimer. |
| |
| * Redistributions in binary form must reproduce the above |
| copyright notice, this list of conditions and the |
| following disclaimer in the documentation and/or other |
| materials provided with the distribution. |
| |
| * Neither the name of the assimp team, nor the names of its |
| contributors may be used to endorse or promote products |
| derived from this software without specific prior |
| written permission of the assimp team. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| --------------------------------------------------------------------------- |
| */ |
| |
| /** @file Exporter.hpp |
| * @brief Defines the CPP-API for the Assimp export interface |
| */ |
| #pragma once |
| #ifndef AI_EXPORT_HPP_INC |
| #define AI_EXPORT_HPP_INC |
| |
| #ifndef ASSIMP_BUILD_NO_EXPORT |
| |
| #include "cexport.h" |
| #include <map> |
| |
| namespace Assimp { |
| |
| class ExporterPimpl; |
| class IOSystem; |
| |
| // ---------------------------------------------------------------------------------- |
| /** CPP-API: The Exporter class forms an C++ interface to the export functionality |
| * of the Open Asset Import Library. Note that the export interface is available |
| * only if Assimp has been built with ASSIMP_BUILD_NO_EXPORT not defined. |
| * |
| * The interface is modeled after the importer interface and mostly |
| * symmetric. The same rules for threading etc. apply. |
| * |
| * In a nutshell, there are two export interfaces: #Export, which writes the |
| * output file(s) either to the regular file system or to a user-supplied |
| * #IOSystem, and #ExportToBlob which returns a linked list of memory |
| * buffers (blob), each referring to one output file (in most cases |
| * there will be only one output file of course, but this extra complexity is |
| * needed since Assimp aims at supporting a wide range of file formats). |
| * |
| * #ExportToBlob is especially useful if you intend to work |
| * with the data in-memory. |
| */ |
| class ASSIMP_API ExportProperties; |
| |
| class ASSIMP_API Exporter { |
| public: |
| /** Function pointer type of a Export worker function */ |
| typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*); |
| |
| /** Internal description of an Assimp export format option */ |
| struct ExportFormatEntry |
| { |
| /// Public description structure to be returned by aiGetExportFormatDescription() |
| aiExportFormatDesc mDescription; |
| |
| // Worker function to do the actual exporting |
| fpExportFunc mExportFunction; |
| |
| // Post-processing steps to be executed PRIOR to invoking mExportFunction |
| unsigned int mEnforcePP; |
| |
| // Constructor to fill all entries |
| ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u) |
| { |
| mDescription.id = pId; |
| mDescription.description = pDesc; |
| mDescription.fileExtension = pExtension; |
| mExportFunction = pFunction; |
| mEnforcePP = pEnforcePP; |
| } |
| |
| ExportFormatEntry() : |
| mExportFunction() |
| , mEnforcePP() |
| { |
| mDescription.id = NULL; |
| mDescription.description = NULL; |
| mDescription.fileExtension = NULL; |
| } |
| }; |
| |
| |
| public: |
| Exporter(); |
| ~Exporter(); |
| |
| public: |
| // ------------------------------------------------------------------- |
| /** Supplies a custom IO handler to the exporter to use to open and |
| * access files. |
| * |
| * If you need #Export to use custom IO logic to access the files, |
| * you need to supply a custom implementation of IOSystem and |
| * IOFile to the exporter. |
| * |
| * #Exporter takes ownership of the object and will destroy it |
| * afterwards. The previously assigned handler will be deleted. |
| * Pass NULL to take again ownership of your IOSystem and reset Assimp |
| * to use its default implementation, which uses plain file IO. |
| * |
| * @param pIOHandler The IO handler to be used in all file accesses |
| * of the Importer. */ |
| void SetIOHandler( IOSystem* pIOHandler); |
| |
| // ------------------------------------------------------------------- |
| /** Retrieves the IO handler that is currently set. |
| * You can use #IsDefaultIOHandler() to check whether the returned |
| * interface is the default IO handler provided by ASSIMP. The default |
| * handler is active as long the application doesn't supply its own |
| * custom IO handler via #SetIOHandler(). |
| * @return A valid IOSystem interface, never NULL. */ |
| IOSystem* GetIOHandler() const; |
| |
| // ------------------------------------------------------------------- |
| /** Checks whether a default IO handler is active |
| * A default handler is active as long the application doesn't |
| * supply its own custom IO handler via #SetIOHandler(). |
| * @return true by default */ |
| bool IsDefaultIOHandler() const; |
| |
| // ------------------------------------------------------------------- |
| /** Exports the given scene to a chosen file format. Returns the exported |
| * data as a binary blob which you can write into a file or something. |
| * When you're done with the data, simply let the #Exporter instance go |
| * out of scope to have it released automatically. |
| * @param pScene The scene to export. Stays in possession of the caller, |
| * is not changed by the function. |
| * @param pFormatId ID string to specify to which format you want to |
| * export to. Use |
| * #GetExportFormatCount / #GetExportFormatDescription to learn which |
| * export formats are available. |
| * @param pPreprocessing See the documentation for #Export |
| * @return the exported data or NULL in case of error. |
| * @note If the Exporter instance did already hold a blob from |
| * a previous call to #ExportToBlob, it will be disposed. |
| * Any IO handlers set via #SetIOHandler are ignored here. |
| * @note Use aiCopyScene() to get a modifiable copy of a previously |
| * imported scene. */ |
| const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* = NULL); |
| const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); |
| |
| // ------------------------------------------------------------------- |
| /** Convenience function to export directly to a file. Use |
| * #SetIOSystem to supply a custom IOSystem to gain fine-grained control |
| * about the output data flow of the export process. |
| * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be NULL. |
| * @param pPath Full target file name. Target must be accessible. |
| * @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated |
| * flags, but in reality only a subset of them makes sense here. Specifying |
| * 'preprocessing' flags is useful if the input scene does not conform to |
| * Assimp's default conventions as specified in the @link data Data Structures Page @endlink. |
| * In short, this means the geometry data should use a right-handed coordinate systems, face |
| * winding should be counter-clockwise and the UV coordinate origin is assumed to be in |
| * the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and |
| * #aiProcess_FlipWindingOrder flags are used in the import side to allow users |
| * to have those defaults automatically adapted to their conventions. Specifying those flags |
| * for exporting has the opposite effect, respectively. Some other of the |
| * #aiPostProcessSteps enumerated values may be useful as well, but you'll need |
| * to try out what their effect on the exported file is. Many formats impose |
| * their own restrictions on the structure of the geometry stored therein, |
| * so some preprocessing may have little or no effect at all, or may be |
| * redundant as exporters would apply them anyhow. A good example |
| * is triangulation - whilst you can enforce it by specifying |
| * the #aiProcess_Triangulate flag, most export formats support only |
| * triangulate data so they would run the step even if it wasn't requested. |
| * |
| * If assimp detects that the input scene was directly taken from the importer side of |
| * the library (i.e. not copied using aiCopyScene and potentially modified afterwards), |
| * any post-processing steps already applied to the scene will not be applied again, unless |
| * they show non-idempotent behavior (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and |
| * #aiProcess_FlipWindingOrder). |
| * @return AI_SUCCESS if everything was fine. |
| * @note Use aiCopyScene() to get a modifiable copy of a previously |
| * imported scene.*/ |
| aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); |
| aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); |
| |
| // ------------------------------------------------------------------- |
| /** Returns an error description of an error that occurred in #Export |
| * or #ExportToBlob |
| * |
| * Returns an empty string if no error occurred. |
| * @return A description of the last error, an empty string if no |
| * error occurred. The string is never NULL. |
| * |
| * @note The returned function remains valid until one of the |
| * following methods is called: #Export, #ExportToBlob, #FreeBlob */ |
| const char* GetErrorString() const; |
| |
| // ------------------------------------------------------------------- |
| /** Return the blob obtained from the last call to #ExportToBlob */ |
| const aiExportDataBlob* GetBlob() const; |
| |
| // ------------------------------------------------------------------- |
| /** Orphan the blob from the last call to #ExportToBlob. This means |
| * the caller takes ownership and is thus responsible for calling |
| * the C API function #aiReleaseExportBlob to release it. */ |
| const aiExportDataBlob* GetOrphanedBlob() const; |
| |
| // ------------------------------------------------------------------- |
| /** Frees the current blob. |
| * |
| * The function does nothing if no blob has previously been |
| * previously produced via #ExportToBlob. #FreeBlob is called |
| * automatically by the destructor. The only reason to call |
| * it manually would be to reclaim as much storage as possible |
| * without giving up the #Exporter instance yet. */ |
| void FreeBlob( ); |
| |
| // ------------------------------------------------------------------- |
| /** Returns the number of export file formats available in the current |
| * Assimp build. Use #Exporter::GetExportFormatDescription to |
| * retrieve infos of a specific export format. |
| * |
| * This includes built-in exporters as well as exporters registered |
| * using #RegisterExporter. |
| **/ |
| size_t GetExportFormatCount() const; |
| |
| // ------------------------------------------------------------------- |
| /** Returns a description of the nth export file format. Use # |
| * #Exporter::GetExportFormatCount to learn how many export |
| * formats are supported. |
| * |
| * The returned pointer is of static storage duration if the |
| * pIndex pertains to a built-in exporter (i.e. one not registered |
| * via #RegistrerExporter). It is restricted to the life-time of the |
| * #Exporter instance otherwise. |
| * |
| * @param pIndex Index of the export format to retrieve information |
| * for. Valid range is 0 to #Exporter::GetExportFormatCount |
| * @return A description of that specific export format. |
| * NULL if pIndex is out of range. */ |
| const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const; |
| |
| // ------------------------------------------------------------------- |
| /** Register a custom exporter. Custom export formats are limited to |
| * to the current #Exporter instance and do not affect the |
| * library globally. The indexes under which the format's |
| * export format description can be queried are assigned |
| * monotonously. |
| * @param desc Exporter description. |
| * @return aiReturn_SUCCESS if the export format was successfully |
| * registered. A common cause that would prevent an exporter |
| * from being registered is that its format id is already |
| * occupied by another format. */ |
| aiReturn RegisterExporter(const ExportFormatEntry& desc); |
| |
| // ------------------------------------------------------------------- |
| /** Remove an export format previously registered with #RegisterExporter |
| * from the #Exporter instance (this can also be used to drop |
| * built-in exporters because those are implicitly registered |
| * using #RegisterExporter). |
| * @param id Format id to be unregistered, this refers to the |
| * 'id' field of #aiExportFormatDesc. |
| * @note Calling this method on a format description not yet registered |
| * has no effect.*/ |
| void UnregisterExporter(const char* id); |
| |
| protected: |
| // Just because we don't want you to know how we're hacking around. |
| ExporterPimpl* pimpl; |
| }; |
| |
| class ASSIMP_API ExportProperties { |
| public: |
| // Data type to store the key hash |
| typedef unsigned int KeyType; |
| |
| // typedefs for our four configuration maps. |
| // We don't need more, so there is no need for a generic solution |
| typedef std::map<KeyType, int> IntPropertyMap; |
| typedef std::map<KeyType, ai_real> FloatPropertyMap; |
| typedef std::map<KeyType, std::string> StringPropertyMap; |
| typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap; |
| |
| public: |
| /** Standard constructor |
| * @see ExportProperties() |
| */ |
| ExportProperties(); |
| |
| // ------------------------------------------------------------------- |
| /** Copy constructor. |
| * |
| * This copies the configuration properties of another ExportProperties. |
| * @see ExportProperties(const ExportProperties& other) |
| */ |
| ExportProperties(const ExportProperties& other); |
| |
| // ------------------------------------------------------------------- |
| /** Set an integer configuration property. |
| * @param szName Name of the property. All supported properties |
| * are defined in the aiConfig.g header (all constants share the |
| * prefix AI_CONFIG_XXX and are simple strings). |
| * @param iValue New value of the property |
| * @return true if the property was set before. The new value replaces |
| * the previous value in this case. |
| * @note Property of different types (float, int, string ..) are kept |
| * on different stacks, so calling SetPropertyInteger() for a |
| * floating-point property has no effect - the loader will call |
| * GetPropertyFloat() to read the property, but it won't be there. |
| */ |
| bool SetPropertyInteger(const char* szName, int iValue); |
| |
| // ------------------------------------------------------------------- |
| /** Set a boolean configuration property. Boolean properties |
| * are stored on the integer stack internally so it's possible |
| * to set them via #SetPropertyBool and query them with |
| * #GetPropertyBool and vice versa. |
| * @see SetPropertyInteger() |
| */ |
| bool SetPropertyBool(const char* szName, bool value) { |
| return SetPropertyInteger(szName,value); |
| } |
| |
| // ------------------------------------------------------------------- |
| /** Set a floating-point configuration property. |
| * @see SetPropertyInteger() |
| */ |
| bool SetPropertyFloat(const char* szName, ai_real fValue); |
| |
| // ------------------------------------------------------------------- |
| /** Set a string configuration property. |
| * @see SetPropertyInteger() |
| */ |
| bool SetPropertyString(const char* szName, const std::string& sValue); |
| |
| // ------------------------------------------------------------------- |
| /** Set a matrix configuration property. |
| * @see SetPropertyInteger() |
| */ |
| bool SetPropertyMatrix(const char* szName, const aiMatrix4x4& sValue); |
| |
| // ------------------------------------------------------------------- |
| /** Get a configuration property. |
| * @param szName Name of the property. All supported properties |
| * are defined in the aiConfig.g header (all constants share the |
| * prefix AI_CONFIG_XXX). |
| * @param iErrorReturn Value that is returned if the property |
| * is not found. |
| * @return Current value of the property |
| * @note Property of different types (float, int, string ..) are kept |
| * on different lists, so calling SetPropertyInteger() for a |
| * floating-point property has no effect - the loader will call |
| * GetPropertyFloat() to read the property, but it won't be there. |
| */ |
| int GetPropertyInteger(const char* szName, |
| int iErrorReturn = 0xffffffff) const; |
| |
| // ------------------------------------------------------------------- |
| /** Get a boolean configuration property. Boolean properties |
| * are stored on the integer stack internally so it's possible |
| * to set them via #SetPropertyBool and query them with |
| * #GetPropertyBool and vice versa. |
| * @see GetPropertyInteger() |
| */ |
| bool GetPropertyBool(const char* szName, bool bErrorReturn = false) const { |
| return GetPropertyInteger(szName,bErrorReturn)!=0; |
| } |
| |
| // ------------------------------------------------------------------- |
| /** Get a floating-point configuration property |
| * @see GetPropertyInteger() |
| */ |
| ai_real GetPropertyFloat(const char* szName, |
| ai_real fErrorReturn = 10e10f) const; |
| |
| // ------------------------------------------------------------------- |
| /** Get a string configuration property |
| * |
| * The return value remains valid until the property is modified. |
| * @see GetPropertyInteger() |
| */ |
| const std::string GetPropertyString(const char* szName, |
| const std::string& sErrorReturn = "") const; |
| |
| // ------------------------------------------------------------------- |
| /** Get a matrix configuration property |
| * |
| * The return value remains valid until the property is modified. |
| * @see GetPropertyInteger() |
| */ |
| const aiMatrix4x4 GetPropertyMatrix(const char* szName, |
| const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const; |
| |
| // ------------------------------------------------------------------- |
| /** Determine a integer configuration property has been set. |
| * @see HasPropertyInteger() |
| */ |
| bool HasPropertyInteger(const char* szName) const; |
| |
| /** Determine a boolean configuration property has been set. |
| * @see HasPropertyBool() |
| */ |
| bool HasPropertyBool(const char* szName) const; |
| |
| /** Determine a boolean configuration property has been set. |
| * @see HasPropertyFloat() |
| */ |
| bool HasPropertyFloat(const char* szName) const; |
| |
| /** Determine a String configuration property has been set. |
| * @see HasPropertyString() |
| */ |
| bool HasPropertyString(const char* szName) const; |
| |
| /** Determine a Matrix configuration property has been set. |
| * @see HasPropertyMatrix() |
| */ |
| bool HasPropertyMatrix(const char* szName) const; |
| |
| protected: |
| |
| /** List of integer properties */ |
| IntPropertyMap mIntProperties; |
| |
| /** List of floating-point properties */ |
| FloatPropertyMap mFloatProperties; |
| |
| /** List of string properties */ |
| StringPropertyMap mStringProperties; |
| |
| /** List of Matrix properties */ |
| MatrixPropertyMap mMatrixProperties; |
| }; |
| |
| // ---------------------------------------------------------------------------------- |
| inline |
| const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const std::string& pFormatId, |
| unsigned int pPreprocessing, const ExportProperties* pProperties) |
| { |
| return ExportToBlob(pScene,pFormatId.c_str(),pPreprocessing, pProperties); |
| } |
| |
| // ---------------------------------------------------------------------------------- |
| inline |
| aiReturn Exporter :: Export( const aiScene* pScene, const std::string& pFormatId, |
| const std::string& pPath, unsigned int pPreprocessing, |
| const ExportProperties* pProperties) |
| { |
| return Export(pScene,pFormatId.c_str(),pPath.c_str(),pPreprocessing, pProperties); |
| } |
| |
| } // namespace Assimp |
| |
| #endif // ASSIMP_BUILD_NO_EXPORT |
| #endif // AI_EXPORT_HPP_INC |