Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 09:30:08

0001 /*
0002 ---------------------------------------------------------------------------
0003 Open Asset Import Library (assimp)
0004 ---------------------------------------------------------------------------
0005 
0006 Copyright (c) 2006-2024, assimp team
0007 
0008 All rights reserved.
0009 
0010 Redistribution and use of this software in source and binary forms,
0011 with or without modification, are permitted provided that the following
0012 conditions are met:
0013 
0014 * Redistributions of source code must retain the above
0015 copyright notice, this list of conditions and the
0016 following disclaimer.
0017 
0018 * Redistributions in binary form must reproduce the above
0019 copyright notice, this list of conditions and the
0020 following disclaimer in the documentation and/or other
0021 materials provided with the distribution.
0022 
0023 * Neither the name of the assimp team, nor the names of its
0024 contributors may be used to endorse or promote products
0025 derived from this software without specific prior
0026 written permission of the assimp team.
0027 
0028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0029 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0030 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0031 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0032 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0033 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0034 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0035 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0036 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0038 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0039 ---------------------------------------------------------------------------
0040 */
0041 
0042 /** @file  Exporter.hpp
0043 *  @brief Defines the CPP-API for the Assimp export interface
0044 */
0045 #pragma once
0046 #ifndef AI_EXPORT_HPP_INC
0047 #define AI_EXPORT_HPP_INC
0048 
0049 #ifdef __GNUC__
0050 #pragma GCC system_header
0051 #endif
0052 
0053 #ifndef ASSIMP_BUILD_NO_EXPORT
0054 
0055 #include "cexport.h"
0056 #include <map>
0057 #include <functional>
0058 
0059 namespace Assimp {
0060 
0061 class ExporterPimpl;
0062 class IOSystem;
0063 class ProgressHandler;
0064 
0065 // ----------------------------------------------------------------------------------
0066 /** CPP-API: The Exporter class forms an C++ interface to the export functionality
0067  * of the Open Asset Import Library. Note that the export interface is available
0068  * only if Assimp has been built with ASSIMP_BUILD_NO_EXPORT not defined.
0069  *
0070  * The interface is modeled after the importer interface and mostly
0071  * symmetric. The same rules for threading etc. apply.
0072  *
0073  * In a nutshell, there are two export interfaces: #Export, which writes the
0074  * output file(s) either to the regular file system or to a user-supplied
0075  * #IOSystem, and #ExportToBlob which returns a linked list of memory
0076  * buffers (blob), each referring to one output file (in most cases
0077  * there will be only one output file of course, but this extra complexity is
0078  * needed since Assimp aims at supporting a wide range of file formats).
0079  *
0080  * #ExportToBlob is especially useful if you intend to work
0081  * with the data in-memory.
0082 */
0083 class ASSIMP_API ExportProperties;
0084 
0085 class ASSIMP_API Exporter {
0086 public:
0087     /** Function pointer type of a Export worker function */
0088     typedef void (*fpExportFunc)(const char *, IOSystem *, const aiScene *, const ExportProperties *);
0089 
0090     /** Internal description of an Assimp export format option */
0091     struct ExportFormatEntry {
0092         /// Public description structure to be returned by aiGetExportFormatDescription()
0093         aiExportFormatDesc mDescription;
0094 
0095         // Worker function to do the actual exporting
0096         fpExportFunc mExportFunction;
0097 
0098         // Post-processing steps to be executed PRIOR to invoking mExportFunction
0099         unsigned int mEnforcePP;
0100 
0101         // Constructor to fill all entries
0102         ExportFormatEntry(const char *pId, const char *pDesc, const char *pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u) {
0103             mDescription.id = pId;
0104             mDescription.description = pDesc;
0105             mDescription.fileExtension = pExtension;
0106             mExportFunction = pFunction;
0107             mEnforcePP = pEnforcePP;
0108         }
0109 
0110         ExportFormatEntry() :
0111                 mExportFunction(),
0112                 mEnforcePP() {
0113             mDescription.id = nullptr;
0114             mDescription.description = nullptr;
0115             mDescription.fileExtension = nullptr;
0116         }
0117     };
0118 
0119     /**
0120      *  @brief  The class constructor.
0121      */
0122     Exporter();
0123 
0124     /**
0125     *  @brief  The class destructor.
0126     */
0127     ~Exporter();
0128 
0129     // -------------------------------------------------------------------
0130     /** Supplies a custom IO handler to the exporter to use to open and
0131      * access files.
0132      *
0133      * If you need #Export to use custom IO logic to access the files,
0134      * you need to supply a custom implementation of IOSystem and
0135      * IOFile to the exporter.
0136      *
0137      * #Exporter takes ownership of the object and will destroy it
0138      * afterwards. The previously assigned handler will be deleted.
0139      * Pass NULL to take again ownership of your IOSystem and reset Assimp
0140      * to use its default implementation, which uses plain file IO.
0141      *
0142      * @param pIOHandler The IO handler to be used in all file accesses
0143      *   of the Importer. */
0144     void SetIOHandler(IOSystem *pIOHandler);
0145 
0146     // -------------------------------------------------------------------
0147     /** Retrieves the IO handler that is currently set.
0148      * You can use #IsDefaultIOHandler() to check whether the returned
0149      * interface is the default IO handler provided by ASSIMP. The default
0150      * handler is active as long the application doesn't supply its own
0151      * custom IO handler via #SetIOHandler().
0152      * @return A valid IOSystem interface, never NULL. */
0153     IOSystem *GetIOHandler() const;
0154 
0155     // -------------------------------------------------------------------
0156     /** Checks whether a default IO handler is active
0157      * A default handler is active as long the application doesn't
0158      * supply its own custom IO handler via #SetIOHandler().
0159      * @return true by default */
0160     bool IsDefaultIOHandler() const;
0161 
0162     // -------------------------------------------------------------------
0163     /** Supplies a custom progress handler to the exporter. This
0164      *  interface exposes an #Update() callback, which is called
0165      *  more or less periodically (please don't sue us if it
0166      *  isn't as periodically as you'd like it to have ...).
0167      *  This can be used to implement progress bars and loading
0168      *  timeouts.
0169      *  @param pHandler Progress callback interface. Pass nullptr to
0170      *    disable progress reporting.
0171      *  @note Progress handlers can be used to abort the loading
0172      *    at almost any time.*/
0173     void SetProgressHandler(ProgressHandler *pHandler);
0174 
0175     // -------------------------------------------------------------------
0176     /** Exports the given scene to a chosen file format. Returns the exported
0177     * data as a binary blob which you can write into a file or something.
0178     * When you're done with the data, simply let the #Exporter instance go
0179     * out of scope to have it released automatically.
0180     * @param pScene The scene to export. Stays in possession of the caller,
0181     *   is not changed by the function.
0182     * @param pFormatId ID string to specify to which format you want to
0183     *   export to. Use
0184     * #GetExportFormatCount / #GetExportFormatDescription to learn which
0185     *   export formats are available.
0186     * @param pPreprocessing See the documentation for #Export
0187     * @return the exported data or nullptr in case of error.
0188     * @note If the Exporter instance did already hold a blob from
0189     *   a previous call to #ExportToBlob, it will be disposed.
0190     *   Any IO handlers set via #SetIOHandler are ignored here.
0191     * @note Use aiCopyScene() to get a modifiable copy of a previously
0192     *   imported scene. */
0193     const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const char *pFormatId,
0194             unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
0195     const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const std::string &pFormatId,
0196             unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
0197 
0198     // -------------------------------------------------------------------
0199     /** Convenience function to export directly to a file. Use
0200      *  #SetIOSystem to supply a custom IOSystem to gain fine-grained control
0201      *  about the output data flow of the export process.
0202      * @param pBlob A data blob obtained from a previous call to #aiExportScene. Must not be nullptr.
0203      * @param pPath Full target file name. Target must be accessible.
0204      * @param pPreprocessing Accepts any choice of the #aiPostProcessSteps enumerated
0205      *   flags, but in reality only a subset of them makes sense here. Specifying
0206      *   'preprocessing' flags is useful if the input scene does not conform to
0207      *   Assimp's default conventions as specified in the @link data Data Structures Page @endlink.
0208      *   In short, this means the geometry data should use a right-handed coordinate systems, face
0209      *   winding should be counter-clockwise and the UV coordinate origin is assumed to be in
0210      *   the upper left. The #aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
0211      *   #aiProcess_FlipWindingOrder flags are used in the import side to allow users
0212      *   to have those defaults automatically adapted to their conventions. Specifying those flags
0213      *   for exporting has the opposite effect, respectively. Some other of the
0214      *   #aiPostProcessSteps enumerated values may be useful as well, but you'll need
0215      *   to try out what their effect on the exported file is. Many formats impose
0216      *   their own restrictions on the structure of the geometry stored therein,
0217      *   so some preprocessing may have little or no effect at all, or may be
0218      *   redundant as exporters would apply them anyhow. A good example
0219      *   is triangulation - whilst you can enforce it by specifying
0220      *   the #aiProcess_Triangulate flag, most export formats support only
0221      *   triangulate data so they would run the step even if it wasn't requested.
0222      *
0223      *   If assimp detects that the input scene was directly taken from the importer side of
0224      *   the library (i.e. not copied using aiCopyScene and potentially modified afterwards),
0225      *   any post-processing steps already applied to the scene will not be applied again, unless
0226      *   they show non-idempotent behavior (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
0227      *   #aiProcess_FlipWindingOrder).
0228      * @return AI_SUCCESS if everything was fine.
0229      * @note Use aiCopyScene() to get a modifiable copy of a previously
0230      *   imported scene.*/
0231     aiReturn Export(const aiScene *pScene, const char *pFormatId, const char *pPath,
0232             unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
0233     aiReturn Export(const aiScene *pScene, const std::string &pFormatId, const std::string &pPath,
0234             unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);
0235 
0236     // -------------------------------------------------------------------
0237     /** Returns an error description of an error that occurred in #Export
0238      *    or #ExportToBlob
0239      *
0240      * Returns an empty string if no error occurred.
0241      * @return A description of the last error, an empty string if no
0242      *   error occurred. The string is never nullptr.
0243      *
0244      * @note The returned function remains valid until one of the
0245      * following methods is called: #Export, #ExportToBlob, #FreeBlob */
0246     const char *GetErrorString() const;
0247 
0248     // -------------------------------------------------------------------
0249     /** Return the blob obtained from the last call to #ExportToBlob */
0250     const aiExportDataBlob *GetBlob() const;
0251 
0252     // -------------------------------------------------------------------
0253     /** Orphan the blob from the last call to #ExportToBlob. This means
0254      *  the caller takes ownership and is thus responsible for calling
0255      *  the C API function #aiReleaseExportBlob to release it. */
0256     const aiExportDataBlob *GetOrphanedBlob() const;
0257 
0258     // -------------------------------------------------------------------
0259     /** Frees the current blob.
0260      *
0261      *  The function does nothing if no blob has previously been
0262      *  previously produced via #ExportToBlob. #FreeBlob is called
0263      *  automatically by the destructor. The only reason to call
0264      *  it manually would be to reclaim as much storage as possible
0265      *  without giving up the #Exporter instance yet. */
0266     void FreeBlob();
0267 
0268     // -------------------------------------------------------------------
0269     /** Returns the number of export file formats available in the current
0270      *  Assimp build. Use #Exporter::GetExportFormatDescription to
0271      *  retrieve infos of a specific export format.
0272      *
0273      *  This includes built-in exporters as well as exporters registered
0274      *  using #RegisterExporter.
0275      **/
0276     size_t GetExportFormatCount() const;
0277 
0278     // -------------------------------------------------------------------
0279     /** Returns a description of the nth export file format. Use #
0280      *  #Exporter::GetExportFormatCount to learn how many export
0281      *  formats are supported.
0282      *
0283      * The returned pointer is of static storage duration if the
0284      * pIndex pertains to a built-in exporter (i.e. one not registered
0285      * via #RegistrerExporter). It is restricted to the life-time of the
0286      * #Exporter instance otherwise.
0287      *
0288      * @param pIndex Index of the export format to retrieve information
0289      *  for. Valid range is 0 to #Exporter::GetExportFormatCount
0290      * @return A description of that specific export format.
0291      *  NULL if pIndex is out of range. */
0292     const aiExportFormatDesc *GetExportFormatDescription(size_t pIndex) const;
0293 
0294     // -------------------------------------------------------------------
0295     /** Register a custom exporter. Custom export formats are limited to
0296      *    to the current #Exporter instance and do not affect the
0297      *    library globally. The indexes under which the format's
0298      *    export format description can be queried are assigned
0299      *    monotonously.
0300      *  @param desc Exporter description.
0301      *  @return aiReturn_SUCCESS if the export format was successfully
0302      *    registered. A common cause that would prevent an exporter
0303      *    from being registered is that its format id is already
0304      *    occupied by another format. */
0305     aiReturn RegisterExporter(const ExportFormatEntry &desc);
0306 
0307     // -------------------------------------------------------------------
0308     /** Remove an export format previously registered with #RegisterExporter
0309      *  from the #Exporter instance (this can also be used to drop
0310      *  built-in exporters because those are implicitly registered
0311      *  using #RegisterExporter).
0312      *  @param id Format id to be unregistered, this refers to the
0313      *    'id' field of #aiExportFormatDesc.
0314      *  @note Calling this method on a format description not yet registered
0315      *    has no effect.*/
0316     void UnregisterExporter(const char *id);
0317 
0318 protected:
0319     // Just because we don't want you to know how we're hacking around.
0320     ExporterPimpl *pimpl;
0321 };
0322 
0323 class ASSIMP_API ExportProperties {
0324 public:
0325     // Data type to store the key hash
0326     typedef unsigned int KeyType;
0327 
0328     // typedefs for our four configuration maps.
0329     // We don't need more, so there is no need for a generic solution
0330     typedef std::map<KeyType, int> IntPropertyMap;
0331     typedef std::map<KeyType, ai_real> FloatPropertyMap;
0332     typedef std::map<KeyType, std::string> StringPropertyMap;
0333     typedef std::map<KeyType, aiMatrix4x4> MatrixPropertyMap;
0334     typedef std::map<KeyType, std::function<void *(void *)>> CallbackPropertyMap;
0335 
0336 public:
0337     /** Standard constructor
0338     * @see ExportProperties()
0339     */
0340     ExportProperties();
0341 
0342     // -------------------------------------------------------------------
0343     /** Copy constructor.
0344      *
0345      * This copies the configuration properties of another ExportProperties.
0346      * @see ExportProperties(const ExportProperties& other)
0347      */
0348     ExportProperties(const ExportProperties &other);
0349 
0350     // -------------------------------------------------------------------
0351     /** Set an integer configuration property.
0352      * @param szName Name of the property. All supported properties
0353      *   are defined in the aiConfig.g header (all constants share the
0354      *   prefix AI_CONFIG_XXX and are simple strings).
0355      * @param iValue New value of the property
0356      * @return true if the property was set before. The new value replaces
0357      *   the previous value in this case.
0358      * @note Property of different types (float, int, string ..) are kept
0359      *   on different stacks, so calling SetPropertyInteger() for a
0360      *   floating-point property has no effect - the loader will call
0361      *   GetPropertyFloat() to read the property, but it won't be there.
0362      */
0363     bool SetPropertyInteger(const char *szName, int iValue);
0364 
0365     // -------------------------------------------------------------------
0366     /** Set a boolean configuration property. Boolean properties
0367      *  are stored on the integer stack internally so it's possible
0368      *  to set them via #SetPropertyBool and query them with
0369      *  #GetPropertyBool and vice versa.
0370      * @see SetPropertyInteger()
0371      */
0372     bool SetPropertyBool(const char *szName, bool value) {
0373         return SetPropertyInteger(szName, value);
0374     }
0375 
0376     // -------------------------------------------------------------------
0377     /** Set a floating-point configuration property.
0378      * @see SetPropertyInteger()
0379      */
0380     bool SetPropertyFloat(const char *szName, ai_real fValue);
0381 
0382     // -------------------------------------------------------------------
0383     /** Set a string configuration property.
0384      * @see SetPropertyInteger()
0385      */
0386     bool SetPropertyString(const char *szName, const std::string &sValue);
0387 
0388     // -------------------------------------------------------------------
0389     /** Set a matrix configuration property.
0390      * @see SetPropertyInteger()
0391      */
0392     bool SetPropertyMatrix(const char *szName, const aiMatrix4x4 &sValue);
0393 
0394     bool SetPropertyCallback(const char *szName, const std::function<void *(void *)> &f);
0395 
0396     // -------------------------------------------------------------------
0397     /** Get a configuration property.
0398      * @param szName Name of the property. All supported properties
0399      *   are defined in the aiConfig.g header (all constants share the
0400      *   prefix AI_CONFIG_XXX).
0401      * @param iErrorReturn Value that is returned if the property
0402      *   is not found.
0403      * @return Current value of the property
0404      * @note Property of different types (float, int, string ..) are kept
0405      *   on different lists, so calling SetPropertyInteger() for a
0406      *   floating-point property has no effect - the loader will call
0407      *   GetPropertyFloat() to read the property, but it won't be there.
0408      */
0409     int GetPropertyInteger(const char *szName,
0410             int iErrorReturn = 0xffffffff) const;
0411 
0412     // -------------------------------------------------------------------
0413     /** Get a boolean configuration property. Boolean properties
0414      *  are stored on the integer stack internally so it's possible
0415      *  to set them via #SetPropertyBool and query them with
0416      *  #GetPropertyBool and vice versa.
0417      * @see GetPropertyInteger()
0418      */
0419     bool GetPropertyBool(const char *szName, bool bErrorReturn = false) const {
0420         return GetPropertyInteger(szName, bErrorReturn) != 0;
0421     }
0422 
0423     // -------------------------------------------------------------------
0424     /** Get a floating-point configuration property
0425      * @see GetPropertyInteger()
0426      */
0427     ai_real GetPropertyFloat(const char *szName,
0428             ai_real fErrorReturn = 10e10f) const;
0429 
0430     // -------------------------------------------------------------------
0431     /** Get a string configuration property
0432      *
0433      *  The return value remains valid until the property is modified.
0434      * @see GetPropertyInteger()
0435      */
0436     const std::string GetPropertyString(const char *szName,
0437             const std::string &sErrorReturn = "") const;
0438 
0439     // -------------------------------------------------------------------
0440     /** Get a matrix configuration property
0441      *
0442      *  The return value remains valid until the property is modified.
0443      * @see GetPropertyInteger()
0444      */
0445     const aiMatrix4x4 GetPropertyMatrix(const char *szName,
0446             const aiMatrix4x4 &sErrorReturn = aiMatrix4x4()) const;
0447 
0448     std::function<void *(void *)> GetPropertyCallback(const char* szName) const;
0449 
0450     // -------------------------------------------------------------------
0451     /** Determine a integer configuration property has been set.
0452     * @see HasPropertyInteger()
0453      */
0454     bool HasPropertyInteger(const char *szName) const;
0455 
0456     /** Determine a boolean configuration property has been set.
0457     * @see HasPropertyBool()
0458      */
0459     bool HasPropertyBool(const char *szName) const;
0460 
0461     /** Determine a boolean configuration property has been set.
0462     * @see HasPropertyFloat()
0463      */
0464     bool HasPropertyFloat(const char *szName) const;
0465 
0466     /** Determine a String configuration property has been set.
0467     * @see HasPropertyString()
0468      */
0469     bool HasPropertyString(const char *szName) const;
0470 
0471     /** Determine a Matrix configuration property has been set.
0472     * @see HasPropertyMatrix()
0473      */
0474     bool HasPropertyMatrix(const char *szName) const;
0475 
0476     bool HasPropertyCallback(const char *szName) const;
0477 
0478     /** List of integer properties */
0479     IntPropertyMap mIntProperties;
0480 
0481     /** List of floating-point properties */
0482     FloatPropertyMap mFloatProperties;
0483 
0484     /** List of string properties */
0485     StringPropertyMap mStringProperties;
0486 
0487     /** List of Matrix properties */
0488     MatrixPropertyMap mMatrixProperties;
0489 
0490     CallbackPropertyMap mCallbackProperties;
0491 };
0492 
0493 // ----------------------------------------------------------------------------------
0494 inline const aiExportDataBlob *Exporter::ExportToBlob(const aiScene *pScene, const std::string &pFormatId,
0495         unsigned int pPreprocessing, const ExportProperties *pProperties) {
0496     return ExportToBlob(pScene, pFormatId.c_str(), pPreprocessing, pProperties);
0497 }
0498 
0499 // ----------------------------------------------------------------------------------
0500 inline aiReturn Exporter ::Export(const aiScene *pScene, const std::string &pFormatId,
0501         const std::string &pPath, unsigned int pPreprocessing,
0502         const ExportProperties *pProperties) {
0503     return Export(pScene, pFormatId.c_str(), pPath.c_str(), pPreprocessing, pProperties);
0504 }
0505 
0506 } // namespace Assimp
0507 
0508 #endif // ASSIMP_BUILD_NO_EXPORT
0509 #endif // AI_EXPORT_HPP_INC