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