nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2018, assimp team nuclear@0: nuclear@0: nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file Definition of the base class for all importer worker classes. */ nuclear@0: #ifndef INCLUDED_AI_BASEIMPORTER_H nuclear@0: #define INCLUDED_AI_BASEIMPORTER_H nuclear@0: nuclear@0: #include "Exceptional.h" nuclear@0: nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: nuclear@0: struct aiScene; nuclear@0: struct aiImporterDesc; nuclear@0: nuclear@0: namespace Assimp { nuclear@0: nuclear@0: class Importer; nuclear@0: class IOSystem; nuclear@0: class BaseProcess; nuclear@0: class SharedPostProcessInfo; nuclear@0: class IOStream; nuclear@0: nuclear@0: // utility to do char4 to uint32 in a portable manner nuclear@0: #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \ nuclear@0: (string[1] << 16) + (string[2] << 8) + string[3])) nuclear@0: nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface nuclear@0: * for all importer worker classes. nuclear@0: * nuclear@0: * The interface defines two functions: CanRead() is used to check if the nuclear@0: * importer can handle the format of the given file. If an implementation of nuclear@0: * this function returns true, the importer then calls ReadFile() which nuclear@0: * imports the given file. ReadFile is not overridable, it just calls nuclear@0: * InternReadFile() and catches any ImportErrorException that might occur. nuclear@0: */ nuclear@0: class ASSIMP_API BaseImporter { nuclear@0: friend class Importer; nuclear@0: nuclear@0: public: nuclear@0: nuclear@0: /** Constructor to be privately used by #Importer */ nuclear@0: BaseImporter() AI_NO_EXCEPT; nuclear@0: nuclear@0: /** Destructor, private as well */ nuclear@0: virtual ~BaseImporter(); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Returns whether the class can handle the format of the given file. nuclear@0: * nuclear@0: * The implementation should be as quick as possible. A check for nuclear@0: * the file extension is enough. If no suitable loader is found with nuclear@0: * this strategy, CanRead() is called again, the 'checkSig' parameter nuclear@0: * set to true this time. Now the implementation is expected to nuclear@0: * perform a full check of the file structure, possibly searching the nuclear@0: * first bytes of the file for magic identifiers or keywords. nuclear@0: * nuclear@0: * @param pFile Path and file name of the file to be examined. nuclear@0: * @param pIOHandler The IO handler to use for accessing any file. nuclear@0: * @param checkSig Set to true if this method is called a second time. nuclear@0: * This time, the implementation may take more time to examine the nuclear@0: * contents of the file to be loaded for magic bytes, keywords, etc nuclear@0: * to be able to load files with unknown/not existent file extensions. nuclear@0: * @return true if the class can read this file, false if not. nuclear@0: */ nuclear@0: virtual bool CanRead( nuclear@0: const std::string& pFile, nuclear@0: IOSystem* pIOHandler, nuclear@0: bool checkSig nuclear@0: ) const = 0; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Imports the given file and returns the imported data. nuclear@0: * If the import succeeds, ownership of the data is transferred to nuclear@0: * the caller. If the import fails, NULL is returned. The function nuclear@0: * takes care that any partially constructed data is destroyed nuclear@0: * beforehand. nuclear@0: * nuclear@0: * @param pImp #Importer object hosting this loader. nuclear@0: * @param pFile Path of the file to be imported. nuclear@0: * @param pIOHandler IO-Handler used to open this and possible other files. nuclear@0: * @return The imported data or NULL if failed. If it failed a nuclear@0: * human-readable error description can be retrieved by calling nuclear@0: * GetErrorText() nuclear@0: * nuclear@0: * @note This function is not intended to be overridden. Implement nuclear@0: * InternReadFile() to do the import. If an exception is thrown somewhere nuclear@0: * in InternReadFile(), this function will catch it and transform it into nuclear@0: * a suitable response to the caller. nuclear@0: */ nuclear@0: aiScene* ReadFile( nuclear@0: const Importer* pImp, nuclear@0: const std::string& pFile, nuclear@0: IOSystem* pIOHandler nuclear@0: ); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Returns the error description of the last error that occurred. nuclear@0: * @return A description of the last error that occurred. An empty nuclear@0: * string if there was no error. nuclear@0: */ nuclear@0: const std::string& GetErrorText() const { nuclear@0: return m_ErrorText; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Called prior to ReadFile(). nuclear@0: * The function is a request to the importer to update its configuration nuclear@0: * basing on the Importer's configuration property list. nuclear@0: * @param pImp Importer instance nuclear@0: */ nuclear@0: virtual void SetupProperties( nuclear@0: const Importer* pImp nuclear@0: ); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Called by #Importer::GetImporterInfo to get a description of nuclear@0: * some loader features. Importers must provide this information. */ nuclear@0: virtual const aiImporterDesc* GetInfo() const = 0; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Called by #Importer::GetExtensionList for each loaded importer. nuclear@0: * Take the extension list contained in the structure returned by nuclear@0: * #GetInfo and insert all file extensions into the given set. nuclear@0: * @param extension set to collect file extensions in*/ nuclear@0: void GetExtensionList(std::set& extensions); nuclear@0: nuclear@0: protected: nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Imports the given file into the given scene structure. The nuclear@0: * function is expected to throw an ImportErrorException if there is nuclear@0: * an error. If it terminates normally, the data in aiScene is nuclear@0: * expected to be correct. Override this function to implement the nuclear@0: * actual importing. nuclear@0: *
nuclear@0: * The output scene must meet the following requirements:
nuclear@0: *
    nuclear@0: *
  • At least a root node must be there, even if its only purpose nuclear@0: * is to reference one mesh.
  • nuclear@0: *
  • aiMesh::mPrimitiveTypes may be 0. The types of primitives nuclear@0: * in the mesh are determined automatically in this case.
  • nuclear@0: *
  • the vertex data is stored in a pseudo-indexed "verbose" format. nuclear@0: * In fact this means that every vertex that is referenced by nuclear@0: * a face is unique. Or the other way round: a vertex index may nuclear@0: * not occur twice in a single aiMesh.
  • nuclear@0: *
  • aiAnimation::mDuration may be -1. Assimp determines the length nuclear@0: * of the animation automatically in this case as the length of nuclear@0: * the longest animation channel.
  • nuclear@0: *
  • aiMesh::mBitangents may be NULL if tangents and normals are nuclear@0: * given. In this case bitangents are computed as the cross product nuclear@0: * between normal and tangent.
  • nuclear@0: *
  • There needn't be a material. If none is there a default material nuclear@0: * is generated. However, it is recommended practice for loaders nuclear@0: * to generate a default material for yourself that matches the nuclear@0: * default material setting for the file format better than Assimp's nuclear@0: * generic default material. Note that default materials *should* nuclear@0: * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded nuclear@0: * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy) nuclear@0: * texture.
  • nuclear@0: *
nuclear@0: * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is not set:
    nuclear@0: *
  • at least one mesh must be there
  • nuclear@0: *
  • there may be no meshes with 0 vertices or faces
  • nuclear@0: *
nuclear@0: * This won't be checked (except by the validation step): Assimp will nuclear@0: * crash if one of the conditions is not met! nuclear@0: * nuclear@0: * @param pFile Path of the file to be imported. nuclear@0: * @param pScene The scene object to hold the imported data. nuclear@0: * NULL is not a valid parameter. nuclear@0: * @param pIOHandler The IO handler to use for any file access. nuclear@0: * NULL is not a valid parameter. */ nuclear@0: virtual void InternReadFile( nuclear@0: const std::string& pFile, nuclear@0: aiScene* pScene, nuclear@0: IOSystem* pIOHandler nuclear@0: ) = 0; nuclear@0: nuclear@0: public: // static utilities nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** A utility for CanRead(). nuclear@0: * nuclear@0: * The function searches the header of a file for a specific token nuclear@0: * and returns true if this token is found. This works for text nuclear@0: * files only. There is a rudimentary handling of UNICODE files. nuclear@0: * The comparison is case independent. nuclear@0: * nuclear@0: * @param pIOSystem IO System to work with nuclear@0: * @param file File name of the file nuclear@0: * @param tokens List of tokens to search for nuclear@0: * @param numTokens Size of the token array nuclear@0: * @param searchBytes Number of bytes to be searched for the tokens. nuclear@0: */ nuclear@0: static bool SearchFileHeaderForToken( nuclear@0: IOSystem* pIOSystem, nuclear@0: const std::string& file, nuclear@0: const char** tokens, nuclear@0: unsigned int numTokens, nuclear@0: unsigned int searchBytes = 200, nuclear@0: bool tokensSol = false, nuclear@0: bool noAlphaBeforeTokens = false); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Check whether a file has a specific file extension nuclear@0: * @param pFile Input file nuclear@0: * @param ext0 Extension to check for. Lowercase characters only, no dot! nuclear@0: * @param ext1 Optional second extension nuclear@0: * @param ext2 Optional third extension nuclear@0: * @note Case-insensitive nuclear@0: */ nuclear@0: static bool SimpleExtensionCheck ( nuclear@0: const std::string& pFile, nuclear@0: const char* ext0, nuclear@0: const char* ext1 = NULL, nuclear@0: const char* ext2 = NULL); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Extract file extension from a string nuclear@0: * @param pFile Input file nuclear@0: * @return Extension without trailing dot, all lowercase nuclear@0: */ nuclear@0: static std::string GetExtension ( nuclear@0: const std::string& pFile); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** @brief Check whether a file starts with one or more magic tokens nuclear@0: * @param pFile Input file nuclear@0: * @param pIOHandler IO system to be used nuclear@0: * @param magic n magic tokens nuclear@0: * @params num Size of magic nuclear@0: * @param offset Offset from file start where tokens are located nuclear@0: * @param Size of one token, in bytes. Maximally 16 bytes. nuclear@0: * @return true if one of the given tokens was found nuclear@0: * nuclear@0: * @note For convenience, the check is also performed for the nuclear@0: * byte-swapped variant of all tokens (big endian). Only for nuclear@0: * tokens of size 2,4. nuclear@0: */ nuclear@0: static bool CheckMagicToken( nuclear@0: IOSystem* pIOHandler, nuclear@0: const std::string& pFile, nuclear@0: const void* magic, nuclear@0: unsigned int num, nuclear@0: unsigned int offset = 0, nuclear@0: unsigned int size = 4); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** An utility for all text file loaders. It converts a file to our nuclear@0: * UTF8 character set. Errors are reported, but ignored. nuclear@0: * nuclear@0: * @param data File buffer to be converted to UTF8 data. The buffer nuclear@0: * is resized as appropriate. */ nuclear@0: static void ConvertToUTF8( nuclear@0: std::vector& data); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** An utility for all text file loaders. It converts a file from our nuclear@0: * UTF8 character set back to ISO-8859-1. Errors are reported, but ignored. nuclear@0: * nuclear@0: * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer nuclear@0: * is resized as appropriate. */ nuclear@0: static void ConvertUTF8toISO8859_1( nuclear@0: std::string& data); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /// @brief Enum to define, if empty files are ok or not. nuclear@0: enum TextFileMode { nuclear@0: ALLOW_EMPTY, nuclear@0: FORBID_EMPTY nuclear@0: }; nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Utility for text file loaders which copies the contents of the nuclear@0: * file into a memory buffer and converts it to our UTF8 nuclear@0: * representation. nuclear@0: * @param stream Stream to read from. nuclear@0: * @param data Output buffer to be resized and filled with the nuclear@0: * converted text file data. The buffer is terminated with nuclear@0: * a binary 0. nuclear@0: * @param mode Whether it is OK to load empty text files. */ nuclear@0: static void TextFileToBuffer( nuclear@0: IOStream* stream, nuclear@0: std::vector& data, nuclear@0: TextFileMode mode = FORBID_EMPTY); nuclear@0: nuclear@0: // ------------------------------------------------------------------- nuclear@0: /** Utility function to move a std::vector into a aiScene array nuclear@0: * @param vec The vector to be moved nuclear@0: * @param out The output pointer to the allocated array. nuclear@0: * @param numOut The output count of elements copied. */ nuclear@0: template nuclear@0: AI_FORCE_INLINE nuclear@0: static void CopyVector( nuclear@0: std::vector& vec, nuclear@0: T*& out, nuclear@0: unsigned int& outLength) nuclear@0: { nuclear@0: outLength = unsigned(vec.size()); nuclear@0: if (outLength) { nuclear@0: out = new T[outLength]; nuclear@0: std::swap_ranges(vec.begin(), vec.end(), out); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: protected: nuclear@0: /// Error description in case there was one. nuclear@0: std::string m_ErrorText; nuclear@0: /// Currently set progress handler. nuclear@0: ProgressHandler* m_progress; nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: nuclear@0: } // end of namespace Assimp nuclear@0: nuclear@0: #endif // AI_BASEIMPORTER_H_INC