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