rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 Open Asset Import Library (assimp)
|
nuclear@0
|
3 ----------------------------------------------------------------------
|
nuclear@0
|
4
|
nuclear@0
|
5 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
6 All rights reserved.
|
nuclear@0
|
7
|
nuclear@0
|
8 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
9 with or without modification, are permitted provided that the
|
nuclear@0
|
10 following conditions are met:
|
nuclear@0
|
11
|
nuclear@0
|
12 * Redistributions of source code must retain the above
|
nuclear@0
|
13 copyright notice, this list of conditions and the
|
nuclear@0
|
14 following disclaimer.
|
nuclear@0
|
15
|
nuclear@0
|
16 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
17 copyright notice, this list of conditions and the
|
nuclear@0
|
18 following disclaimer in the documentation and/or other
|
nuclear@0
|
19 materials provided with the distribution.
|
nuclear@0
|
20
|
nuclear@0
|
21 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
22 contributors may be used to endorse or promote products
|
nuclear@0
|
23 derived from this software without specific prior
|
nuclear@0
|
24 written permission of the assimp team.
|
nuclear@0
|
25
|
nuclear@0
|
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
37
|
nuclear@0
|
38 ----------------------------------------------------------------------
|
nuclear@0
|
39 */
|
nuclear@0
|
40
|
nuclear@0
|
41 /** @file Definition of the base class for all importer worker classes. */
|
nuclear@0
|
42 #ifndef INCLUDED_AI_BASEIMPORTER_H
|
nuclear@0
|
43 #define INCLUDED_AI_BASEIMPORTER_H
|
nuclear@0
|
44
|
nuclear@0
|
45 #include "Exceptional.h"
|
nuclear@0
|
46
|
nuclear@0
|
47 #include <string>
|
nuclear@0
|
48 #include <map>
|
nuclear@0
|
49 #include <vector>
|
nuclear@0
|
50 #include "assimp/types.h"
|
nuclear@0
|
51
|
nuclear@0
|
52 struct aiScene;
|
nuclear@0
|
53
|
nuclear@0
|
54 namespace Assimp {
|
nuclear@0
|
55
|
nuclear@0
|
56 class IOSystem;
|
nuclear@0
|
57 class Importer;
|
nuclear@0
|
58 class BaseImporter;
|
nuclear@0
|
59 class BaseProcess;
|
nuclear@0
|
60 class SharedPostProcessInfo;
|
nuclear@0
|
61 class IOStream;
|
nuclear@0
|
62
|
nuclear@0
|
63 // utility to do char4 to uint32 in a portable manner
|
nuclear@0
|
64 #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
|
nuclear@0
|
65 (string[1] << 16) + (string[2] << 8) + string[3]))
|
nuclear@0
|
66
|
nuclear@0
|
67 // ---------------------------------------------------------------------------
|
nuclear@0
|
68 template <typename T>
|
nuclear@0
|
69 struct ScopeGuard
|
nuclear@0
|
70 {
|
nuclear@0
|
71 ScopeGuard(T* obj) : obj(obj), mdismiss() {}
|
nuclear@0
|
72 ~ScopeGuard () throw() {
|
nuclear@0
|
73 if (!mdismiss) {
|
nuclear@0
|
74 delete obj;
|
nuclear@0
|
75 }
|
nuclear@0
|
76 obj = NULL;
|
nuclear@0
|
77 }
|
nuclear@0
|
78
|
nuclear@0
|
79 T* dismiss() {
|
nuclear@0
|
80 mdismiss=true;
|
nuclear@0
|
81 return obj;
|
nuclear@0
|
82 }
|
nuclear@0
|
83
|
nuclear@0
|
84 operator T*() {
|
nuclear@0
|
85 return obj;
|
nuclear@0
|
86 }
|
nuclear@0
|
87
|
nuclear@0
|
88 T* operator -> () {
|
nuclear@0
|
89 return obj;
|
nuclear@0
|
90 }
|
nuclear@0
|
91
|
nuclear@0
|
92 private:
|
nuclear@0
|
93 T* obj;
|
nuclear@0
|
94 bool mdismiss;
|
nuclear@0
|
95 };
|
nuclear@0
|
96
|
nuclear@0
|
97
|
nuclear@0
|
98
|
nuclear@0
|
99 // ---------------------------------------------------------------------------
|
nuclear@0
|
100 /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
|
nuclear@0
|
101 * for all importer worker classes.
|
nuclear@0
|
102 *
|
nuclear@0
|
103 * The interface defines two functions: CanRead() is used to check if the
|
nuclear@0
|
104 * importer can handle the format of the given file. If an implementation of
|
nuclear@0
|
105 * this function returns true, the importer then calls ReadFile() which
|
nuclear@0
|
106 * imports the given file. ReadFile is not overridable, it just calls
|
nuclear@0
|
107 * InternReadFile() and catches any ImportErrorException that might occur.
|
nuclear@0
|
108 */
|
nuclear@0
|
109 class BaseImporter
|
nuclear@0
|
110 {
|
nuclear@0
|
111 friend class Importer;
|
nuclear@0
|
112
|
nuclear@0
|
113 public:
|
nuclear@0
|
114
|
nuclear@0
|
115 /** Constructor to be privately used by #Importer */
|
nuclear@0
|
116 BaseImporter();
|
nuclear@0
|
117
|
nuclear@0
|
118 /** Destructor, private as well */
|
nuclear@0
|
119 virtual ~BaseImporter();
|
nuclear@0
|
120
|
nuclear@0
|
121 public:
|
nuclear@0
|
122 // -------------------------------------------------------------------
|
nuclear@0
|
123 /** Returns whether the class can handle the format of the given file.
|
nuclear@0
|
124 *
|
nuclear@0
|
125 * The implementation should be as quick as possible. A check for
|
nuclear@0
|
126 * the file extension is enough. If no suitable loader is found with
|
nuclear@0
|
127 * this strategy, CanRead() is called again, the 'checkSig' parameter
|
nuclear@0
|
128 * set to true this time. Now the implementation is expected to
|
nuclear@0
|
129 * perform a full check of the file structure, possibly searching the
|
nuclear@0
|
130 * first bytes of the file for magic identifiers or keywords.
|
nuclear@0
|
131 *
|
nuclear@0
|
132 * @param pFile Path and file name of the file to be examined.
|
nuclear@0
|
133 * @param pIOHandler The IO handler to use for accessing any file.
|
nuclear@0
|
134 * @param checkSig Set to true if this method is called a second time.
|
nuclear@0
|
135 * This time, the implementation may take more time to examine the
|
nuclear@0
|
136 * contents of the file to be loaded for magic bytes, keywords, etc
|
nuclear@0
|
137 * to be able to load files with unknown/not existent file extensions.
|
nuclear@0
|
138 * @return true if the class can read this file, false if not.
|
nuclear@0
|
139 */
|
nuclear@0
|
140 virtual bool CanRead(
|
nuclear@0
|
141 const std::string& pFile,
|
nuclear@0
|
142 IOSystem* pIOHandler,
|
nuclear@0
|
143 bool checkSig
|
nuclear@0
|
144 ) const = 0;
|
nuclear@0
|
145
|
nuclear@0
|
146 // -------------------------------------------------------------------
|
nuclear@0
|
147 /** Imports the given file and returns the imported data.
|
nuclear@0
|
148 * If the import succeeds, ownership of the data is transferred to
|
nuclear@0
|
149 * the caller. If the import fails, NULL is returned. The function
|
nuclear@0
|
150 * takes care that any partially constructed data is destroyed
|
nuclear@0
|
151 * beforehand.
|
nuclear@0
|
152 *
|
nuclear@0
|
153 * @param pImp #Importer object hosting this loader.
|
nuclear@0
|
154 * @param pFile Path of the file to be imported.
|
nuclear@0
|
155 * @param pIOHandler IO-Handler used to open this and possible other files.
|
nuclear@0
|
156 * @return The imported data or NULL if failed. If it failed a
|
nuclear@0
|
157 * human-readable error description can be retrieved by calling
|
nuclear@0
|
158 * GetErrorText()
|
nuclear@0
|
159 *
|
nuclear@0
|
160 * @note This function is not intended to be overridden. Implement
|
nuclear@0
|
161 * InternReadFile() to do the import. If an exception is thrown somewhere
|
nuclear@0
|
162 * in InternReadFile(), this function will catch it and transform it into
|
nuclear@0
|
163 * a suitable response to the caller.
|
nuclear@0
|
164 */
|
nuclear@0
|
165 aiScene* ReadFile(
|
nuclear@0
|
166 const Importer* pImp,
|
nuclear@0
|
167 const std::string& pFile,
|
nuclear@0
|
168 IOSystem* pIOHandler
|
nuclear@0
|
169 );
|
nuclear@0
|
170
|
nuclear@0
|
171 // -------------------------------------------------------------------
|
nuclear@0
|
172 /** Returns the error description of the last error that occured.
|
nuclear@0
|
173 * @return A description of the last error that occured. An empty
|
nuclear@0
|
174 * string if there was no error.
|
nuclear@0
|
175 */
|
nuclear@0
|
176 const std::string& GetErrorText() const {
|
nuclear@0
|
177 return mErrorText;
|
nuclear@0
|
178 }
|
nuclear@0
|
179
|
nuclear@0
|
180 // -------------------------------------------------------------------
|
nuclear@0
|
181 /** Called prior to ReadFile().
|
nuclear@0
|
182 * The function is a request to the importer to update its configuration
|
nuclear@0
|
183 * basing on the Importer's configuration property list.
|
nuclear@0
|
184 * @param pImp Importer instance
|
nuclear@0
|
185 */
|
nuclear@0
|
186 virtual void SetupProperties(
|
nuclear@0
|
187 const Importer* pImp
|
nuclear@0
|
188 );
|
nuclear@0
|
189
|
nuclear@0
|
190
|
nuclear@0
|
191 // -------------------------------------------------------------------
|
nuclear@0
|
192 /** Called by #Importer::GetImporterInfo to get a description of
|
nuclear@0
|
193 * some loader features. Importers must provide this information. */
|
nuclear@0
|
194 virtual const aiImporterDesc* GetInfo() const = 0;
|
nuclear@0
|
195
|
nuclear@0
|
196
|
nuclear@0
|
197
|
nuclear@0
|
198 // -------------------------------------------------------------------
|
nuclear@0
|
199 /** Called by #Importer::GetExtensionList for each loaded importer.
|
nuclear@0
|
200 * Take the extension list contained in the structure returned by
|
nuclear@0
|
201 * #GetInfo and insert all file extensions into the given set.
|
nuclear@0
|
202 * @param extension set to collect file extensions in*/
|
nuclear@0
|
203 void GetExtensionList(std::set<std::string>& extensions);
|
nuclear@0
|
204
|
nuclear@0
|
205 protected:
|
nuclear@0
|
206
|
nuclear@0
|
207 // -------------------------------------------------------------------
|
nuclear@0
|
208 /** Imports the given file into the given scene structure. The
|
nuclear@0
|
209 * function is expected to throw an ImportErrorException if there is
|
nuclear@0
|
210 * an error. If it terminates normally, the data in aiScene is
|
nuclear@0
|
211 * expected to be correct. Override this function to implement the
|
nuclear@0
|
212 * actual importing.
|
nuclear@0
|
213 * <br>
|
nuclear@0
|
214 * The output scene must meet the following requirements:<br>
|
nuclear@0
|
215 * <ul>
|
nuclear@0
|
216 * <li>At least a root node must be there, even if its only purpose
|
nuclear@0
|
217 * is to reference one mesh.</li>
|
nuclear@0
|
218 * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
|
nuclear@0
|
219 * in the mesh are determined automatically in this case.</li>
|
nuclear@0
|
220 * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
|
nuclear@0
|
221 * In fact this means that every vertex that is referenced by
|
nuclear@0
|
222 * a face is unique. Or the other way round: a vertex index may
|
nuclear@0
|
223 * not occur twice in a single aiMesh.</li>
|
nuclear@0
|
224 * <li>aiAnimation::mDuration may be -1. Assimp determines the length
|
nuclear@0
|
225 * of the animation automatically in this case as the length of
|
nuclear@0
|
226 * the longest animation channel.</li>
|
nuclear@0
|
227 * <li>aiMesh::mBitangents may be NULL if tangents and normals are
|
nuclear@0
|
228 * given. In this case bitangents are computed as the cross product
|
nuclear@0
|
229 * between normal and tangent.</li>
|
nuclear@0
|
230 * <li>There needn't be a material. If none is there a default material
|
nuclear@0
|
231 * is generated. However, it is recommended practice for loaders
|
nuclear@0
|
232 * to generate a default material for yourself that matches the
|
nuclear@0
|
233 * default material setting for the file format better than Assimp's
|
nuclear@0
|
234 * generic default material. Note that default materials *should*
|
nuclear@0
|
235 * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
|
nuclear@0
|
236 * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
|
nuclear@0
|
237 * texture. </li>
|
nuclear@0
|
238 * </ul>
|
nuclear@0
|
239 * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
|
nuclear@0
|
240 * <li> at least one mesh must be there</li>
|
nuclear@0
|
241 * <li> there may be no meshes with 0 vertices or faces</li>
|
nuclear@0
|
242 * </ul>
|
nuclear@0
|
243 * This won't be checked (except by the validation step): Assimp will
|
nuclear@0
|
244 * crash if one of the conditions is not met!
|
nuclear@0
|
245 *
|
nuclear@0
|
246 * @param pFile Path of the file to be imported.
|
nuclear@0
|
247 * @param pScene The scene object to hold the imported data.
|
nuclear@0
|
248 * NULL is not a valid parameter.
|
nuclear@0
|
249 * @param pIOHandler The IO handler to use for any file access.
|
nuclear@0
|
250 * NULL is not a valid parameter. */
|
nuclear@0
|
251 virtual void InternReadFile(
|
nuclear@0
|
252 const std::string& pFile,
|
nuclear@0
|
253 aiScene* pScene,
|
nuclear@0
|
254 IOSystem* pIOHandler
|
nuclear@0
|
255 ) = 0;
|
nuclear@0
|
256
|
nuclear@0
|
257 public: // static utilities
|
nuclear@0
|
258
|
nuclear@0
|
259 // -------------------------------------------------------------------
|
nuclear@0
|
260 /** A utility for CanRead().
|
nuclear@0
|
261 *
|
nuclear@0
|
262 * The function searches the header of a file for a specific token
|
nuclear@0
|
263 * and returns true if this token is found. This works for text
|
nuclear@0
|
264 * files only. There is a rudimentary handling of UNICODE files.
|
nuclear@0
|
265 * The comparison is case independent.
|
nuclear@0
|
266 *
|
nuclear@0
|
267 * @param pIOSystem IO System to work with
|
nuclear@0
|
268 * @param file File name of the file
|
nuclear@0
|
269 * @param tokens List of tokens to search for
|
nuclear@0
|
270 * @param numTokens Size of the token array
|
nuclear@0
|
271 * @param searchBytes Number of bytes to be searched for the tokens.
|
nuclear@0
|
272 */
|
nuclear@0
|
273 static bool SearchFileHeaderForToken(
|
nuclear@0
|
274 IOSystem* pIOSystem,
|
nuclear@0
|
275 const std::string& file,
|
nuclear@0
|
276 const char** tokens,
|
nuclear@0
|
277 unsigned int numTokens,
|
nuclear@0
|
278 unsigned int searchBytes = 200,
|
nuclear@0
|
279 bool tokensSol = false);
|
nuclear@0
|
280
|
nuclear@0
|
281 // -------------------------------------------------------------------
|
nuclear@0
|
282 /** @brief Check whether a file has a specific file extension
|
nuclear@0
|
283 * @param pFile Input file
|
nuclear@0
|
284 * @param ext0 Extension to check for. Lowercase characters only, no dot!
|
nuclear@0
|
285 * @param ext1 Optional second extension
|
nuclear@0
|
286 * @param ext2 Optional third extension
|
nuclear@0
|
287 * @note Case-insensitive
|
nuclear@0
|
288 */
|
nuclear@0
|
289 static bool SimpleExtensionCheck (
|
nuclear@0
|
290 const std::string& pFile,
|
nuclear@0
|
291 const char* ext0,
|
nuclear@0
|
292 const char* ext1 = NULL,
|
nuclear@0
|
293 const char* ext2 = NULL);
|
nuclear@0
|
294
|
nuclear@0
|
295 // -------------------------------------------------------------------
|
nuclear@0
|
296 /** @brief Extract file extension from a string
|
nuclear@0
|
297 * @param pFile Input file
|
nuclear@0
|
298 * @return Extension without trailing dot, all lowercase
|
nuclear@0
|
299 */
|
nuclear@0
|
300 static std::string GetExtension (
|
nuclear@0
|
301 const std::string& pFile);
|
nuclear@0
|
302
|
nuclear@0
|
303 // -------------------------------------------------------------------
|
nuclear@0
|
304 /** @brief Check whether a file starts with one or more magic tokens
|
nuclear@0
|
305 * @param pFile Input file
|
nuclear@0
|
306 * @param pIOHandler IO system to be used
|
nuclear@0
|
307 * @param magic n magic tokens
|
nuclear@0
|
308 * @params num Size of magic
|
nuclear@0
|
309 * @param offset Offset from file start where tokens are located
|
nuclear@0
|
310 * @param Size of one token, in bytes. Maximally 16 bytes.
|
nuclear@0
|
311 * @return true if one of the given tokens was found
|
nuclear@0
|
312 *
|
nuclear@0
|
313 * @note For convinence, the check is also performed for the
|
nuclear@0
|
314 * byte-swapped variant of all tokens (big endian). Only for
|
nuclear@0
|
315 * tokens of size 2,4.
|
nuclear@0
|
316 */
|
nuclear@0
|
317 static bool CheckMagicToken(
|
nuclear@0
|
318 IOSystem* pIOHandler,
|
nuclear@0
|
319 const std::string& pFile,
|
nuclear@0
|
320 const void* magic,
|
nuclear@0
|
321 unsigned int num,
|
nuclear@0
|
322 unsigned int offset = 0,
|
nuclear@0
|
323 unsigned int size = 4);
|
nuclear@0
|
324
|
nuclear@0
|
325 // -------------------------------------------------------------------
|
nuclear@0
|
326 /** An utility for all text file loaders. It converts a file to our
|
nuclear@0
|
327 * UTF8 character set. Errors are reported, but ignored.
|
nuclear@0
|
328 *
|
nuclear@0
|
329 * @param data File buffer to be converted to UTF8 data. The buffer
|
nuclear@0
|
330 * is resized as appropriate. */
|
nuclear@0
|
331 static void ConvertToUTF8(
|
nuclear@0
|
332 std::vector<char>& data);
|
nuclear@0
|
333
|
nuclear@0
|
334 // -------------------------------------------------------------------
|
nuclear@0
|
335 /** Utility for text file loaders which copies the contents of the
|
nuclear@0
|
336 * file into a memory buffer and converts it to our UTF8
|
nuclear@0
|
337 * representation.
|
nuclear@0
|
338 * @param stream Stream to read from.
|
nuclear@0
|
339 * @param data Output buffer to be resized and filled with the
|
nuclear@0
|
340 * converted text file data. The buffer is terminated with
|
nuclear@0
|
341 * a binary 0. */
|
nuclear@0
|
342 static void TextFileToBuffer(
|
nuclear@0
|
343 IOStream* stream,
|
nuclear@0
|
344 std::vector<char>& data);
|
nuclear@0
|
345
|
nuclear@0
|
346 protected:
|
nuclear@0
|
347
|
nuclear@0
|
348 /** Error description in case there was one. */
|
nuclear@0
|
349 std::string mErrorText;
|
nuclear@0
|
350
|
nuclear@0
|
351 /** Currently set progress handler */
|
nuclear@0
|
352 ProgressHandler* progress;
|
nuclear@0
|
353 };
|
nuclear@0
|
354
|
nuclear@0
|
355
|
nuclear@0
|
356
|
nuclear@0
|
357 } // end of namespace Assimp
|
nuclear@0
|
358
|
nuclear@0
|
359 #endif // AI_BASEIMPORTER_H_INC
|