diff --git a/Readme.md b/Readme.md index 112d389e8..8b476c6cf 100644 --- a/Readme.md +++ b/Readme.md @@ -46,6 +46,10 @@ The library provides importers for a lot of file formats, including: - NDO - Ogre XML - Q3D + +Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries. + +- C4D (https://github.com/acgessler/assimp-cinema4d) Exporters include: diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 662f31532..a97ea2c6a 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -73,7 +73,7 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer ColladaLoader::ColladaLoader() -: noSkeletonMesh() +: noSkeletonMesh(), ignoreUpDirection(false) {} // ------------------------------------------------------------------------------------------------ @@ -108,6 +108,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo void ColladaLoader::SetupProperties(const Importer* pImp) { noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; + ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0; } @@ -160,21 +161,21 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I 0, parser.mUnitSize, 0, 0, 0, 0, parser.mUnitSize, 0, 0, 0, 0, 1); - + if( !ignoreUpDirection ) { // Convert to Y_UP, if different orientation - if( parser.mUpDirection == ColladaParser::UP_X) - pScene->mRootNode->mTransformation *= aiMatrix4x4( - 0, -1, 0, 0, - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - else if( parser.mUpDirection == ColladaParser::UP_Z) - pScene->mRootNode->mTransformation *= aiMatrix4x4( - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, -1, 0, 0, - 0, 0, 0, 1); - + if( parser.mUpDirection == ColladaParser::UP_X) + pScene->mRootNode->mTransformation *= aiMatrix4x4( + 0, -1, 0, 0, + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + else if( parser.mUpDirection == ColladaParser::UP_Z) + pScene->mRootNode->mTransformation *= aiMatrix4x4( + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, -1, 0, 0, + 0, 0, 0, 1); + } // store all meshes StoreSceneMeshes( pScene); diff --git a/code/ColladaLoader.h b/code/ColladaLoader.h index 850bce780..953bd20b8 100644 --- a/code/ColladaLoader.h +++ b/code/ColladaLoader.h @@ -234,6 +234,7 @@ protected: std::vector mAnims; bool noSkeletonMesh; + bool ignoreUpDirection; }; } // end of namespace Assimp diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index c7fdb8374..b5f151c15 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -232,7 +232,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, // compute length based on type and check against the stored value if(encoding == 0) { - uint32_t stride; + uint32_t stride = 0; switch(type) { case 'f': @@ -248,6 +248,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, default: ai_assert(false); }; + ai_assert(stride > 0); if(length * stride != comp_len) { TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor); } diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 3a21a89ee..342c5f144 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -547,6 +547,10 @@ private: default: ai_assert(false); } + + ai_assert((order[0] >= 0) && (order[0] <= 2)); + ai_assert((order[1] >= 0) && (order[1] <= 2)); + ai_assert((order[2] >= 0) && (order[2] <= 2)); if(!is_id[order[0]]) { out = temp[order[0]]; @@ -1844,7 +1848,7 @@ private: }} #endif - const AnimationCurveNode* curve_node; + const AnimationCurveNode* curve_node = NULL; BOOST_FOREACH(const AnimationCurveNode* node, curves) { ai_assert(node); diff --git a/code/FBXDocumentUtil.h b/code/FBXDocumentUtil.h index 7ff71937c..6f150b6d5 100644 --- a/code/FBXDocumentUtil.h +++ b/code/FBXDocumentUtil.h @@ -50,8 +50,8 @@ namespace Util { /* DOM/Parse error reporting - does not return */ -void DOMError(const std::string& message, const Token& token); -void DOMError(const std::string& message, const Element* element = NULL); +AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX; // does return void DOMWarning(const std::string& message, const Token& token); diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index 7b32e1df5..af0e929bf 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -512,7 +512,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha ai_assert(data + comp_len == end); // determine the length of the uncompressed data by looking at the type signature - uint32_t stride; + uint32_t stride = 0; switch(type) { case 'f': diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index 36100ec48..50c403fe1 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -102,7 +102,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, } // data is given in floats, simply copy it - unsigned int iWrite; + unsigned int iWrite = 0; if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) { iWrite = prop->mDataLength / sizeof(float); if (pMax) { @@ -175,7 +175,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, } // data is given in ints, simply copy it - unsigned int iWrite; + unsigned int iWrite = 0; if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) { iWrite = prop->mDataLength / sizeof(int32_t); if (pMax) { diff --git a/code/PostStepRegistry.cpp b/code/PostStepRegistry.cpp index 0e3de18a0..3fdbeb257 100644 --- a/code/PostStepRegistry.cpp +++ b/code/PostStepRegistry.cpp @@ -47,6 +47,7 @@ corresponding preprocessor flag to selectively disable steps. */ #include "AssimpPCH.h" +#include "ProcessHelper.h" #ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS # include "CalcTangentsProcess.h" @@ -215,7 +216,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS) out.push_back( new FlipWindingOrderProcess()); #endif -#if (!defined ASSIMP_BUILD_DEBONE_PROCESS) +#if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS) out.push_back( new DeboneProcess()); #endif #if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS) diff --git a/code/StreamReader.h b/code/StreamReader.h index 8d40922e0..8301d1b27 100644 --- a/code/StreamReader.h +++ b/code/StreamReader.h @@ -193,7 +193,7 @@ public: // --------------------------------------------------------------------- /** Increase the file pointer (relative seeking) */ - void IncPtr(int plus) { + void IncPtr(size_t plus) { current += plus; if (current > limit) { throw DeadlyImportError("End of file or read limit was reached"); diff --git a/code/ValidateDataStructure.h b/code/ValidateDataStructure.h index e33bb5b82..4a3ec86d2 100644 --- a/code/ValidateDataStructure.h +++ b/code/ValidateDataStructure.h @@ -82,7 +82,7 @@ protected: /** Report a validation error. This will throw an exception, * control won't return. * @param msg Format string for sprintf().*/ - AI_WONT_RETURN void ReportError(const char* msg,...); + AI_WONT_RETURN void ReportError(const char* msg,...) AI_WONT_RETURN_SUFFIX; // ------------------------------------------------------------------- diff --git a/code/fast_atof.h b/code/fast_atof.h index 68a120c1f..a10ee9666 100644 --- a/code/fast_atof.h +++ b/code/fast_atof.h @@ -16,6 +16,7 @@ #define __FAST_A_TO_F_H_INCLUDED__ #include +#include namespace Assimp { diff --git a/include/assimp/config.h b/include/assimp/config.h index c1694c94c..8683cc385 100644 --- a/include/assimp/config.h +++ b/include/assimp/config.h @@ -841,4 +841,6 @@ enum aiComponent */ #define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION" -#endif // !! AI_CONFIG_H_INC \ No newline at end of file +#define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION" + +#endif // !! AI_CONFIG_H_INC diff --git a/include/assimp/defs.h b/include/assimp/defs.h index 1b777a5f2..aeae0778f 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -162,6 +162,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # define AI_FORCE_INLINE inline #endif // (defined _MSC_VER) +#ifdef __clang__ +# define AI_WONT_RETURN_SUFFIX __attribute__((analyzer_noreturn)) +#else +# define AI_WONT_RETURN_SUFFIX +#endif // (defined __clang__) + #ifdef __cplusplus /* No explicit 'struct' and 'enum' tags for C++, this keeps showing up * in doxydocs. diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 22670431d..ab1e913cd 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -58,14 +58,14 @@ def make_tuple(ai_obj, type = None): return res def call_init(obj, caller = None): - # init children - if helper.hasattr_silent(obj, '_init'): - obj._init(parent = caller) + # init children + if helper.hasattr_silent(obj, '_init'): + obj._init(parent = caller) - # pointers - elif helper.hasattr_silent(obj, 'contents'): - if helper.hasattr_silent(obj.contents, '_init'): - obj.contents._init(target = obj, parent = caller) + # pointers + elif helper.hasattr_silent(obj, 'contents'): + if helper.hasattr_silent(obj.contents, '_init'): + obj.contents._init(target = obj, parent = caller) @@ -313,7 +313,7 @@ def _finalize_mesh(mesh, target): data = numpy.array([make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)], dtype=numpy.float32) setattr(target, name[1:].lower(), data) else: - setattr(target, name[1:].lower(), []) + setattr(target, name[1:].lower(), numpy.array([], dtype="float32")) def fillarray(name): mAttr = getattr(mesh, name) @@ -336,6 +336,27 @@ def _finalize_mesh(mesh, target): faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32) setattr(target, 'faces', faces) + +class PropertyGetter(dict): + def __getitem__(self, key): + semantic = 0 + if isinstance(key, tuple): + key, semantic = key + + return dict.__getitem__(self, (key, semantic)) + + def keys(self): + for k in dict.keys(self): + yield k[0] + + def __iter__(self): + return self.keys() + + def items(self): + for k, v in dict.items(self): + yield k[0], v + + def _get_properties(properties, length): """ Convenience Function to get the material properties as a dict @@ -346,7 +367,7 @@ def _get_properties(properties, length): for p in [properties[i] for i in range(length)]: #the name p = p.contents - key = str(p.mKey.data.decode("utf-8")).split('.')[1] + key = (str(p.mKey.data.decode("utf-8")).split('.')[1], p.mSemantic) #the data from ctypes import POINTER, cast, c_int, c_float, sizeof @@ -366,7 +387,7 @@ def _get_properties(properties, length): result[key] = value - return result + return PropertyGetter(result) def decompose_matrix(matrix): if not isinstance(matrix, structs.Matrix4x4): diff --git a/port/PyAssimp/scripts/sample.py b/port/PyAssimp/scripts/sample.py index b7b08748f..5153a9bab 100755 --- a/port/PyAssimp/scripts/sample.py +++ b/port/PyAssimp/scripts/sample.py @@ -10,6 +10,7 @@ import logging logging.basicConfig(level=logging.INFO) import pyassimp +import pyassimp.postprocess def recur_node(node,level = 0): print(" " + "\t" * level + "- " + str(node)) @@ -19,7 +20,7 @@ def recur_node(node,level = 0): def main(filename=None): - scene = pyassimp.load(filename) + scene = pyassimp.load(filename, pyassimp.postprocess.aiProcess_Triangulate) #the model we load print("MODEL:" + filename)