1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2019, assimp team
6
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
12following conditions are met:
13
14* Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
17
18* Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
22
23* Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written 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
43/** @file Definition of the base class for all importer worker classes. */
44#ifndef INCLUDED_AI_BASEIMPORTER_H
45#define INCLUDED_AI_BASEIMPORTER_H
46
47#include "Exceptional.h"
48
49#include <vector>
50#include <set>
51#include <map>
52#include <assimp/types.h>
53#include <assimp/ProgressHandler.hpp>
54#include <assimp/ai_assert.h>
55
56struct aiScene;
57struct aiImporterDesc;
58
59namespace Assimp {
60
61class Importer;
62class IOSystem;
63class BaseProcess;
64class SharedPostProcessInfo;
65class IOStream;
66
67// utility to do char4 to uint32 in a portable manner
68#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
69 (string[1] << 16) + (string[2] << 8) + string[3]))
70
71
72// ---------------------------------------------------------------------------
73/** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
74 * for all importer worker classes.
75 *
76 * The interface defines two functions: CanRead() is used to check if the
77 * importer can handle the format of the given file. If an implementation of
78 * this function returns true, the importer then calls ReadFile() which
79 * imports the given file. ReadFile is not overridable, it just calls
80 * InternReadFile() and catches any ImportErrorException that might occur.
81 */
82class ASSIMP_API BaseImporter {
83 friend class Importer;
84
85private:
86 /* Pushes state into importer for the importer scale */
87 virtual void UpdateImporterScale( Importer* pImp );
88
89public:
90
91 /** Constructor to be privately used by #Importer */
92 BaseImporter() AI_NO_EXCEPT;
93
94 /** Destructor, private as well */
95 virtual ~BaseImporter();
96
97 // -------------------------------------------------------------------
98 /** Returns whether the class can handle the format of the given file.
99 *
100 * The implementation should be as quick as possible. A check for
101 * the file extension is enough. If no suitable loader is found with
102 * this strategy, CanRead() is called again, the 'checkSig' parameter
103 * set to true this time. Now the implementation is expected to
104 * perform a full check of the file structure, possibly searching the
105 * first bytes of the file for magic identifiers or keywords.
106 *
107 * @param pFile Path and file name of the file to be examined.
108 * @param pIOHandler The IO handler to use for accessing any file.
109 * @param checkSig Set to true if this method is called a second time.
110 * This time, the implementation may take more time to examine the
111 * contents of the file to be loaded for magic bytes, keywords, etc
112 * to be able to load files with unknown/not existent file extensions.
113 * @return true if the class can read this file, false if not.
114 */
115 virtual bool CanRead(
116 const std::string& pFile,
117 IOSystem* pIOHandler,
118 bool checkSig
119 ) const = 0;
120
121 // -------------------------------------------------------------------
122 /** Imports the given file and returns the imported data.
123 * If the import succeeds, ownership of the data is transferred to
124 * the caller. If the import fails, NULL is returned. The function
125 * takes care that any partially constructed data is destroyed
126 * beforehand.
127 *
128 * @param pImp #Importer object hosting this loader.
129 * @param pFile Path of the file to be imported.
130 * @param pIOHandler IO-Handler used to open this and possible other files.
131 * @return The imported data or NULL if failed. If it failed a
132 * human-readable error description can be retrieved by calling
133 * GetErrorText()
134 *
135 * @note This function is not intended to be overridden. Implement
136 * InternReadFile() to do the import. If an exception is thrown somewhere
137 * in InternReadFile(), this function will catch it and transform it into
138 * a suitable response to the caller.
139 */
140 aiScene* ReadFile(
141 Importer* pImp,
142 const std::string& pFile,
143 IOSystem* pIOHandler
144 );
145
146 // -------------------------------------------------------------------
147 /** Returns the error description of the last error that occurred.
148 * @return A description of the last error that occurred. An empty
149 * string if there was no error.
150 */
151 const std::string& GetErrorText() const {
152 return m_ErrorText;
153 }
154
155 // -------------------------------------------------------------------
156 /** Called prior to ReadFile().
157 * The function is a request to the importer to update its configuration
158 * basing on the Importer's configuration property list.
159 * @param pImp Importer instance
160 */
161 virtual void SetupProperties(
162 const Importer* pImp
163 );
164
165 // -------------------------------------------------------------------
166 /** Called by #Importer::GetImporterInfo to get a description of
167 * some loader features. Importers must provide this information. */
168 virtual const aiImporterDesc* GetInfo() const = 0;
169
170 /**
171 * Will be called only by scale process when scaling is requested.
172 */
173 virtual void SetFileScale(double scale)
174 {
175 fileScale = scale;
176 }
177
178 virtual double GetFileScale() const
179 {
180 return fileScale;
181 }
182
183 enum ImporterUnits {
184 M,
185 MM,
186 CM,
187 INCHES,
188 FEET
189 };
190
191 /**
192 * Assimp Importer
193 * unit conversions available
194 * if you need another measurment unit add it below.
195 * it's currently defined in assimp that we prefer meters.
196 * */
197 std::map<ImporterUnits, double> importerUnits = {
198 {ImporterUnits::M, 1},
199 {ImporterUnits::CM, 0.01},
200 {ImporterUnits::MM, 0.001},
201 {ImporterUnits::INCHES, 0.0254},
202 {ImporterUnits::FEET, 0.3048}
203 };
204
205 virtual void SetApplicationUnits( const ImporterUnits& unit )
206 {
207 importerScale = importerUnits[unit];
208 applicationUnits = unit;
209 }
210
211 virtual const ImporterUnits& GetApplicationUnits()
212 {
213 return applicationUnits;
214 }
215
216 // -------------------------------------------------------------------
217 /** Called by #Importer::GetExtensionList for each loaded importer.
218 * Take the extension list contained in the structure returned by
219 * #GetInfo and insert all file extensions into the given set.
220 * @param extension set to collect file extensions in*/
221 void GetExtensionList(std::set<std::string>& extensions);
222
223protected:
224 ImporterUnits applicationUnits = ImporterUnits::M;
225 double importerScale = 1.0;
226 double fileScale = 1.0;
227
228
229
230 // -------------------------------------------------------------------
231 /** Imports the given file into the given scene structure. The
232 * function is expected to throw an ImportErrorException if there is
233 * an error. If it terminates normally, the data in aiScene is
234 * expected to be correct. Override this function to implement the
235 * actual importing.
236 * <br>
237 * The output scene must meet the following requirements:<br>
238 * <ul>
239 * <li>At least a root node must be there, even if its only purpose
240 * is to reference one mesh.</li>
241 * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
242 * in the mesh are determined automatically in this case.</li>
243 * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
244 * In fact this means that every vertex that is referenced by
245 * a face is unique. Or the other way round: a vertex index may
246 * not occur twice in a single aiMesh.</li>
247 * <li>aiAnimation::mDuration may be -1. Assimp determines the length
248 * of the animation automatically in this case as the length of
249 * the longest animation channel.</li>
250 * <li>aiMesh::mBitangents may be NULL if tangents and normals are
251 * given. In this case bitangents are computed as the cross product
252 * between normal and tangent.</li>
253 * <li>There needn't be a material. If none is there a default material
254 * is generated. However, it is recommended practice for loaders
255 * to generate a default material for yourself that matches the
256 * default material setting for the file format better than Assimp's
257 * generic default material. Note that default materials *should*
258 * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
259 * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
260 * texture. </li>
261 * </ul>
262 * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
263 * <li> at least one mesh must be there</li>
264 * <li> there may be no meshes with 0 vertices or faces</li>
265 * </ul>
266 * This won't be checked (except by the validation step): Assimp will
267 * crash if one of the conditions is not met!
268 *
269 * @param pFile Path of the file to be imported.
270 * @param pScene The scene object to hold the imported data.
271 * NULL is not a valid parameter.
272 * @param pIOHandler The IO handler to use for any file access.
273 * NULL is not a valid parameter. */
274 virtual void InternReadFile(
275 const std::string& pFile,
276 aiScene* pScene,
277 IOSystem* pIOHandler
278 ) = 0;
279
280public: // static utilities
281
282 // -------------------------------------------------------------------
283 /** A utility for CanRead().
284 *
285 * The function searches the header of a file for a specific token
286 * and returns true if this token is found. This works for text
287 * files only. There is a rudimentary handling of UNICODE files.
288 * The comparison is case independent.
289 *
290 * @param pIOSystem IO System to work with
291 * @param file File name of the file
292 * @param tokens List of tokens to search for
293 * @param numTokens Size of the token array
294 * @param searchBytes Number of bytes to be searched for the tokens.
295 */
296 static bool SearchFileHeaderForToken(
297 IOSystem* pIOSystem,
298 const std::string& file,
299 const char** tokens,
300 unsigned int numTokens,
301 unsigned int searchBytes = 200,
302 bool tokensSol = false,
303 bool noAlphaBeforeTokens = false);
304
305 // -------------------------------------------------------------------
306 /** @brief Check whether a file has a specific file extension
307 * @param pFile Input file
308 * @param ext0 Extension to check for. Lowercase characters only, no dot!
309 * @param ext1 Optional second extension
310 * @param ext2 Optional third extension
311 * @note Case-insensitive
312 */
313 static bool SimpleExtensionCheck (
314 const std::string& pFile,
315 const char* ext0,
316 const char* ext1 = NULL,
317 const char* ext2 = NULL);
318
319 // -------------------------------------------------------------------
320 /** @brief Extract file extension from a string
321 * @param pFile Input file
322 * @return Extension without trailing dot, all lowercase
323 */
324 static std::string GetExtension (
325 const std::string& pFile);
326
327 // -------------------------------------------------------------------
328 /** @brief Check whether a file starts with one or more magic tokens
329 * @param pFile Input file
330 * @param pIOHandler IO system to be used
331 * @param magic n magic tokens
332 * @params num Size of magic
333 * @param offset Offset from file start where tokens are located
334 * @param Size of one token, in bytes. Maximally 16 bytes.
335 * @return true if one of the given tokens was found
336 *
337 * @note For convenience, the check is also performed for the
338 * byte-swapped variant of all tokens (big endian). Only for
339 * tokens of size 2,4.
340 */
341 static bool CheckMagicToken(
342 IOSystem* pIOHandler,
343 const std::string& pFile,
344 const void* magic,
345 unsigned int num,
346 unsigned int offset = 0,
347 unsigned int size = 4);
348
349 // -------------------------------------------------------------------
350 /** An utility for all text file loaders. It converts a file to our
351 * UTF8 character set. Errors are reported, but ignored.
352 *
353 * @param data File buffer to be converted to UTF8 data. The buffer
354 * is resized as appropriate. */
355 static void ConvertToUTF8(
356 std::vector<char>& data);
357
358 // -------------------------------------------------------------------
359 /** An utility for all text file loaders. It converts a file from our
360 * UTF8 character set back to ISO-8859-1. Errors are reported, but ignored.
361 *
362 * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer
363 * is resized as appropriate. */
364 static void ConvertUTF8toISO8859_1(
365 std::string& data);
366
367 // -------------------------------------------------------------------
368 /// @brief Enum to define, if empty files are ok or not.
369 enum TextFileMode {
370 ALLOW_EMPTY,
371 FORBID_EMPTY
372 };
373
374 // -------------------------------------------------------------------
375 /** Utility for text file loaders which copies the contents of the
376 * file into a memory buffer and converts it to our UTF8
377 * representation.
378 * @param stream Stream to read from.
379 * @param data Output buffer to be resized and filled with the
380 * converted text file data. The buffer is terminated with
381 * a binary 0.
382 * @param mode Whether it is OK to load empty text files. */
383 static void TextFileToBuffer(
384 IOStream* stream,
385 std::vector<char>& data,
386 TextFileMode mode = FORBID_EMPTY);
387
388 // -------------------------------------------------------------------
389 /** Utility function to move a std::vector into a aiScene array
390 * @param vec The vector to be moved
391 * @param out The output pointer to the allocated array.
392 * @param numOut The output count of elements copied. */
393 template<typename T>
394 AI_FORCE_INLINE
395 static void CopyVector(
396 std::vector<T>& vec,
397 T*& out,
398 unsigned int& outLength)
399 {
400 outLength = unsigned(vec.size());
401 if (outLength) {
402 out = new T[outLength];
403 std::swap_ranges(vec.begin(), vec.end(), out);
404 }
405 }
406
407protected:
408 /// Error description in case there was one.
409 std::string m_ErrorText;
410 /// Currently set progress handler.
411 ProgressHandler* m_progress;
412};
413
414
415
416} // end of namespace Assimp
417
418#endif // AI_BASEIMPORTER_H_INC
419

source code of qt3d/src/3rdparty/assimp/src/include/assimp/BaseImporter.h