summaryrefslogtreecommitdiff
path: root/src/mesh/assimp-master/include/assimp/Exporter.hpp
blob: 09a459442f0795ab57ee2704c442728638e8c63b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------

Copyright (c) 2006-2022, 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

#ifdef __GNUC__
#pragma GCC system_header
#endif

#ifndef ASSIMP_BUILD_NO_EXPORT

#include "cexport.h"
#include <map>
#include <functional>

namespace Assimp {

class ExporterPimpl;
class IOSystem;
class ProgressHandler;

// ----------------------------------------------------------------------------------
/** 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 = nullptr;
            mDescription.description = nullptr;
            mDescription.fileExtension = nullptr;
        }
    };

    /**
     *  @brief  The class constructor.
     */
    Exporter();

    /**
    *  @brief  The class destructor.
    */
    ~Exporter();

    // -------------------------------------------------------------------
    /** 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;

    // -------------------------------------------------------------------
    /** Supplies a custom progress handler to the exporter. This
     *  interface exposes an #Update() callback, which is called
     *  more or less periodically (please don't sue us if it
     *  isn't as periodically as you'd like it to have ...).
     *  This can be used to implement progress bars and loading
     *  timeouts.
     *  @param pHandler Progress callback interface. Pass nullptr to
     *    disable progress reporting.
     *  @note Progress handlers can be used to abort the loading
     *    at almost any time.*/
    void SetProgressHandler(ProgressHandler *pHandler);

    // -------------------------------------------------------------------
    /** 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 nullptr 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 *pProperties = nullptr);
    const aiExportDataBlob *ExportToBlob(const aiScene *pScene, const std::string &pFormatId,
            unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);

    // -------------------------------------------------------------------
    /** 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 nullptr.
     * @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 = nullptr);
    aiReturn Export(const aiScene *pScene, const std::string &pFormatId, const std::string &pPath,
            unsigned int pPreprocessing = 0u, const ExportProperties *pProperties = nullptr);

    // -------------------------------------------------------------------
    /** 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 nullptr.
     *
     * @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;
    typedef std::map<KeyType, std::function<void *(void *)>> CallbackPropertyMap;

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);

    bool SetPropertyCallback(const char *szName, const std::function<void *(void *)> &f);

    // -------------------------------------------------------------------
    /** 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;

    std::function<void *(void *)> GetPropertyCallback(const char* szName) 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;

    bool HasPropertyCallback(const char *szName) const;

    /** 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;

    CallbackPropertyMap mCallbackProperties;
};

// ----------------------------------------------------------------------------------
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