From c08a78f7c66bb1cddecbcd9b68cdfbdf9584c301 Mon Sep 17 00:00:00 2001 From: "Chris Weermann (TGE)" Date: Wed, 2 Oct 2019 01:32:53 +0200 Subject: [PATCH 001/170] ColladaExporter: improve name/id handling --- code/Collada/ColladaExporter.cpp | 150 ++++++++++++++++++------------- 1 file changed, 88 insertions(+), 62 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index 6fd31ed3b..5aee96c23 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -92,6 +92,34 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p } // end of namespace Assimp +// ------------------------------------------------------------------------------------------------ +const std::string XMLIDEncode(const std::string& name) +{ + const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-."; + const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char); + + if (name.length() == 0) + return name; + + std::stringstream idEncoded; + + // xsd:ID must start with letter or underscore + if (!((name[0] >= 'A' && name[0] <= 'z') || name[0] == '_')) + idEncoded << '_'; + + for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) + { + // xsd:ID can only contain letters, digits, underscores, hyphens and periods + if (strchr(XML_ID_CHARS, *it) != nullptr) + idEncoded << *it; + else + // Select placeholder character based on invalid character to prevent name collisions + idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT]; + } + + return idEncoded.str(); +} + // ------------------------------------------------------------------------------------------------ // Constructor for a specific scene to export ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) @@ -146,7 +174,7 @@ void ColladaExporter::WriteFile() { // useless Collada fu at the end, just in case we haven't had enough indirections, yet. mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "mRootNode->mName.C_Str()) + "\" />" << endstr; + mOutput << startstr << "mRootNode->mName.C_Str()) + "\" />" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -356,9 +384,10 @@ void ColladaExporter::WriteCamerasLibrary() { void ColladaExporter::WriteCamera(size_t pIndex){ const aiCamera *cam = mScene->mCameras[pIndex]; - const std::string idstrEscaped = XMLEscape(cam->mName.C_Str()); + const std::string cameraName = XMLEscape(cam->mName.C_Str()); + const std::string cameraId = XMLIDEncode(cam->mName.C_Str()); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); @@ -412,10 +441,11 @@ void ColladaExporter::WriteLightsLibrary() { void ColladaExporter::WriteLight(size_t pIndex){ const aiLight *light = mScene->mLights[pIndex]; - const std::string idstrEscaped = XMLEscape(light->mName.C_Str()); + const std::string lightName = XMLEscape(light->mName.C_Str()); + const std::string lightId = XMLIDEncode(light->mName.C_Str()); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); @@ -586,7 +616,7 @@ static bool isalnum_C(char c) { void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) { if( !pSurface.texture.empty() ) { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << ""; @@ -619,7 +649,7 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std } else { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; } PopTag(); mOutput << startstr << "" << endstr; @@ -633,21 +663,21 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture if( !pSurface.texture.empty() ) { - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << XMLEscape(pMatName) << "-" << pTypeName << "-image" << endstr; + mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << XMLEscape(pMatName) << "-" << pTypeName << "-surface" << endstr; + mOutput << startstr << "" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface" << endstr; PopTag(); mOutput << startstr << "" << endstr; PopTag(); @@ -699,11 +729,6 @@ void ColladaExporter::WriteMaterials() materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); } } - for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { - if( !isalnum_C( *it ) ) { - *it = '_'; - } - } aiShadingMode shading = aiShadingMode_Flat; materials[a].shading_model = "phong"; @@ -768,7 +793,7 @@ void ColladaExporter::WriteMaterials() { const Material& mat = *it; // this is so ridiculous it must be right - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; PushTag(); @@ -819,9 +844,9 @@ void ColladaExporter::WriteMaterials() for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) { const Material& mat = *it; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; } @@ -851,7 +876,7 @@ void ColladaExporter::WriteController( size_t pIndex) { const aiMesh* mesh = mScene->mMeshes[pIndex]; const std::string idstr = GetMeshId( pIndex); - const std::string idstrEscaped = XMLEscape(idstr); + const std::string idstrEscaped = XMLIDEncode(idstr); if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) return; @@ -886,7 +911,7 @@ void ColladaExporter::WriteController( size_t pIndex) mOutput << startstr << "mNumBones << "\">"; for( size_t i = 0; i < mesh->mNumBones; ++i ) - mOutput << XMLEscape(mesh->mBones[i]->mName.C_Str()) << " "; + mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " "; mOutput << "" << endstr; @@ -1022,13 +1047,14 @@ void ColladaExporter::WriteGeometry( size_t pIndex) { const aiMesh* mesh = mScene->mMeshes[pIndex]; const std::string idstr = GetMeshId( pIndex); - const std::string idstrEscaped = XMLEscape(idstr); + const std::string geometryName = XMLEscape(idstr); + const std::string geometryId = XMLIDEncode(idstr); if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) return; // opening tag - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; @@ -1059,9 +1085,9 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // assemble vertex structure // Only write input for POSITION since we will write other as shared inputs in polygon definition - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; @@ -1079,18 +1105,18 @@ void ColladaExporter::WriteGeometry( size_t pIndex) { mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; if( mesh->HasNormals() ) - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) { if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; } for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) { if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; } mOutput << startstr << "

"; @@ -1113,18 +1139,18 @@ void ColladaExporter::WriteGeometry( size_t pIndex) { mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; if( mesh->HasNormals() ) - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) { if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; } for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) { if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; } mOutput << startstr << ""; @@ -1173,13 +1199,13 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy return; } - std::string arrayId = pIdString + "-array"; + std::string arrayId = XMLIDEncode(pIdString) + "-array"; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); // source array - mOutput << startstr << " "; + mOutput << startstr << " "; PushTag(); if( pType == FloatType_TexCoord2 ) @@ -1265,11 +1291,12 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy // Writes the scene library void ColladaExporter::WriteSceneLibrary() { - const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str()); + const std::string sceneName = XMLEscape(mScene->mRootNode->mName.C_Str()); + const std::string sceneId = XMLIDEncode(mScene->mRootNode->mName.C_Str()); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); // start recursive write at the root node @@ -1300,7 +1327,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) idstr = idstr + ending; } - const std::string idstrEscaped = XMLEscape(idstr); + const std::string idstrEscaped = XMLIDEncode(idstr); mOutput << startstr << "" << endstr; PushTag(); @@ -1372,13 +1399,13 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) } const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); - std::string arrayId = node_idstr + "-array"; + std::string arrayId = XMLIDEncode(node_idstr) + "-array"; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); // source array - mOutput << startstr << " "; + mOutput << startstr << " "; for( size_t a = 0; a < names.size(); ++a ) { mOutput << names[a] << " "; } @@ -1387,7 +1414,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; @@ -1409,12 +1436,12 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { // samplers const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler"); - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr; - mOutput << startstr << "mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr; PopTag(); mOutput << startstr << "" << endstr; @@ -1426,7 +1453,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { // channels - mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLEscape(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLIDEncode(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; } } @@ -1437,8 +1464,6 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) // ------------------------------------------------------------------------------------------------ void ColladaExporter::WriteAnimationsLibrary() { - const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str()); - if ( mScene->mNumAnimations > 0 ) { mOutput << startstr << "" << endstr; PushTag(); @@ -1546,16 +1571,17 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) } } - const std::string node_name_escaped = XMLEscape(pNode->mName.data); + const std::string node_id = XMLIDEncode(pNode->mName.data); + const std::string node_name = XMLEscape(pNode->mName.data); mOutput << startstr << "" << endstr; PushTag(); @@ -1594,14 +1620,14 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) //check if it is a camera node for(size_t i=0; imNumCameras; i++){ if(mScene->mCameras[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; + mOutput << startstr <<"" << endstr; break; } } //check if it is a light node for(size_t i=0; imNumLights; i++){ if(mScene->mLights[i]->mName == pNode->mName){ - mOutput << startstr <<"" << endstr; + mOutput << startstr <<"" << endstr; break; } } @@ -1617,13 +1643,13 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) if( mesh->mNumBones == 0 ) { - mOutput << startstr << "mMeshes[a])) << "\">" << endstr; + mOutput << startstr << "mMeshes[a])) << "\">" << endstr; PushTag(); } else { mOutput << startstr - << "mMeshes[a])) << "-skin\">" + << "mMeshes[a])) << "-skin\">" << endstr; PushTag(); @@ -1631,7 +1657,7 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // use the first bone to find skeleton root const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh ); if ( skeletonRootBoneNode ) { - mFoundSkeletonRootNodeID = XMLEscape( skeletonRootBoneNode->mName.C_Str() ); + mFoundSkeletonRootNodeID = XMLIDEncode( skeletonRootBoneNode->mName.C_Str() ); } mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; } @@ -1639,7 +1665,7 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) PushTag(); mOutput << startstr << "" << endstr; PushTag(); - mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; + mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; PushTag(); for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) { From 38153748ab5ce6672ccc237738c25a6fbd107ca0 Mon Sep 17 00:00:00 2001 From: "Chris Weermann (TGE)" Date: Wed, 2 Oct 2019 19:18:48 +0200 Subject: [PATCH 002/170] ColladaExporter: use actual mesh names when available --- code/Collada/ColladaExporter.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index 5aee96c23..c366fa72e 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -93,6 +93,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p } // end of namespace Assimp // ------------------------------------------------------------------------------------------------ +// Encodes a string into a valid XML ID using the xsd:ID schema qualifications. const std::string XMLIDEncode(const std::string& name) { const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-."; @@ -875,7 +876,7 @@ void ColladaExporter::WriteControllerLibrary() void ColladaExporter::WriteController( size_t pIndex) { const aiMesh* mesh = mScene->mMeshes[pIndex]; - const std::string idstr = GetMeshId( pIndex); + const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); const std::string idstrEscaped = XMLIDEncode(idstr); if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) @@ -1046,7 +1047,7 @@ void ColladaExporter::WriteGeometryLibrary() void ColladaExporter::WriteGeometry( size_t pIndex) { const aiMesh* mesh = mScene->mMeshes[pIndex]; - const std::string idstr = GetMeshId( pIndex); + const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str(); const std::string geometryName = XMLEscape(idstr); const std::string geometryId = XMLIDEncode(idstr); @@ -1641,15 +1642,17 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) continue; + const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str(); + if( mesh->mNumBones == 0 ) { - mOutput << startstr << "mMeshes[a])) << "\">" << endstr; + mOutput << startstr << "" << endstr; PushTag(); } else { mOutput << startstr - << "mMeshes[a])) << "-skin\">" + << "" << endstr; PushTag(); From 32781a566db2cd6022c7020ff2ac591d753c11ab Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Sun, 6 Oct 2019 15:42:11 +0200 Subject: [PATCH 003/170] Fix FBXConverter: use proper 64-bit constant Use proper 64-bit constant for CONVERT_FBX_TIME(time) conversion, fixes: code/FBXConverter.cpp:2025: error: integer constant is too large for 'long' type code/FBXConverter.cpp:2026: error: integer constant is too large for 'long' type code/FBXConverter.cpp:2794: error: integer constant is too large for 'long' type code/FBXConverter.cpp:2868: error: integer constant is too large for 'long' type code/FBXConverter.cpp:2878: error: integer constant is too large for 'long' type code/FBXConverter.cpp:2888: error: integer constant is too large for 'long' type Signed-off-by: Peter Seiderer [Retrieved from: https://git.buildroot.net/buildroot/tree/package/assimp/0001-Fix-FBXConverter-use-proper-64-bit-constant.patch] Signed-off-by: Fabrice Fontaine --- code/FBX/FBXConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 152be3277..b8601a2a5 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -77,7 +77,7 @@ namespace Assimp { #define MAGIC_NODE_TAG "_$AssimpFbx$" -#define CONVERT_FBX_TIME(time) static_cast(time) / 46186158000L +#define CONVERT_FBX_TIME(time) static_cast(time) / 46186158000LL FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones ) : defaultMaterialIndex() From 81d125a2cca748ef3f79f1f0a6731d7e6d694ec1 Mon Sep 17 00:00:00 2001 From: Robikz Date: Sun, 6 Oct 2019 18:46:35 +0200 Subject: [PATCH 004/170] dllexport ASSIMP_API in all Windows compilers, not just MSVC This fixes a problem mentioned in issue #2685 where the libassimp.dll compiled with MinGW doesn't export any symbols. --- include/assimp/defs.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/include/assimp/defs.h b/include/assimp/defs.h index 05a5e3fd4..e32b95dde 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -126,16 +126,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * GENBOUNDINGBOXES */ ////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER +#ifdef _WIN32 # undef ASSIMP_API - ////////////////////////////////////////////////////////////////////////// /* Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library */ ////////////////////////////////////////////////////////////////////////// # ifdef ASSIMP_BUILD_DLL_EXPORT # define ASSIMP_API __declspec(dllexport) # define ASSIMP_API_WINONLY __declspec(dllexport) -# pragma warning (disable : 4251) ////////////////////////////////////////////////////////////////////////// /* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in @@ -148,7 +146,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # define ASSIMP_API # define ASSIMP_API_WINONLY # endif +#elif defined(SWIG) + /* Do nothing, the relevant defines are all in AssimpSwigPort.i */ + +#else +# define ASSIMP_API __attribute__ ((visibility("default"))) +# define ASSIMP_API_WINONLY +#endif + +#ifdef _MSC_VER +# ifdef ASSIMP_BUILD_DLL_EXPORT +# pragma warning (disable : 4251) +# endif /* Force the compiler to inline a function, if possible */ # define AI_FORCE_INLINE __forceinline @@ -156,17 +166,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Tells the compiler that a function never returns. Used in code analysis * to skip dead paths (e.g. after an assertion evaluated to false). */ # define AI_WONT_RETURN __declspec(noreturn) - #elif defined(SWIG) /* Do nothing, the relevant defines are all in AssimpSwigPort.i */ #else - # define AI_WONT_RETURN - -# define ASSIMP_API __attribute__ ((visibility("default"))) -# define ASSIMP_API_WINONLY # define AI_FORCE_INLINE inline #endif // (defined _MSC_VER) From 0761530e17cb7638be3e8267a9128bea7a2dae51 Mon Sep 17 00:00:00 2001 From: Robikz Date: Sun, 6 Oct 2019 18:46:47 +0200 Subject: [PATCH 005/170] Set proper sharedLibraryName for MinGW in installed assimpTargets-*.cmake The shared library name for MinGW is the .a library with which we need to link the built binary. This problem is described in issue #2685. --- assimpTargets-debug.cmake.in | 7 ++++++- assimpTargets-release.cmake.in | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/assimpTargets-debug.cmake.in b/assimpTargets-debug.cmake.in index 1ebe2a608..ed3935970 100644 --- a/assimpTargets-debug.cmake.in +++ b/assimpTargets-debug.cmake.in @@ -63,7 +63,12 @@ if(MSVC) else() set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" ) if(ASSIMP_BUILD_SHARED_LIBS) - set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") + if(WIN32) + # Handle MinGW compiler. + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") + else() + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") + endif() set_target_properties(assimp::assimp PROPERTIES IMPORTED_SONAME_DEBUG "${sharedLibraryName}" IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" diff --git a/assimpTargets-release.cmake.in b/assimpTargets-release.cmake.in index b09b881f7..f00710d85 100644 --- a/assimpTargets-release.cmake.in +++ b/assimpTargets-release.cmake.in @@ -63,7 +63,12 @@ if(MSVC) else() set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" ) if(ASSIMP_BUILD_SHARED_LIBS) - set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") + if(WIN32) + # Handle MinGW compiler. + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") + else() + set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") + endif() set_target_properties(assimp::assimp PROPERTIES IMPORTED_SONAME_RELEASE "${sharedLibraryName}" IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" From 6ac8279977c3a54118551e549d77329497116f66 Mon Sep 17 00:00:00 2001 From: Robikz Date: Sun, 6 Oct 2019 18:46:51 +0200 Subject: [PATCH 006/170] assimpTargets.cmake: define add_library() with lib type directly Instead of using if(ON)/if(OFF) to determine which of the "hardcoded" add_library(... SHARED ...) or (... STATIC ...) should be used, specify a new BUILD_LIB_TYPE variable that is set directly to either SHARED or STATIC and substituted in the `add_library()` statement when assimpTargets.cmake.in is configured. This removes a CMP0012 collision with prior `cmake_policy(VERSION 2.6)` statement and makes the CMP0012 warning not appear in users' projects. This problem is mentioned in issue #2685. --- CMakeLists.txt | 5 +++++ assimpTargets.cmake.in | 6 +----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcafb649f..5a716daa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,6 +391,11 @@ IF(HUNTER_ENABLED) ) ELSE(HUNTER_ENABLED) # cmake configuration files + if(${BUILD_SHARED_LIBS}) + set(BUILD_LIB_TYPE SHARED) + else() + set(BUILD_LIB_TYPE STATIC) + endif() CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" @ONLY IMMEDIATE) IF (is_multi_config) diff --git a/assimpTargets.cmake.in b/assimpTargets.cmake.in index ab1a8d2c7..ea63ba2a5 100644 --- a/assimpTargets.cmake.in +++ b/assimpTargets.cmake.in @@ -51,11 +51,7 @@ if(_IMPORT_PREFIX STREQUAL "/") endif() # Create imported target assimp::assimp -if(@BUILD_SHARED_LIBS@) - add_library(assimp::assimp SHARED IMPORTED) -else() - add_library(assimp::assimp STATIC IMPORTED) -endif() +add_library(assimp::assimp @BUILD_LIB_TYPE@ IMPORTED) set_target_properties(assimp::assimp PROPERTIES COMPATIBLE_INTERFACE_STRING "assimp_MAJOR_VERSION" From 1e7d1ffbc2e74c529fdfcde0f9311d62af48dc7e Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 8 Oct 2019 10:34:08 +0100 Subject: [PATCH 007/170] Add non-indexed unit test. --- .../IncorrectVertexArrays/MarbleCube/Cube.bin | Bin 0 -> 1848 bytes .../MarbleCube/Cube.gltf | 226 ++++++++++++++++++ .../MarbleCube/Cube_BaseColor.png | Bin 0 -> 891995 bytes .../MarbleCube/Cube_MetallicRoughness.png | Bin 0 -> 319 bytes 4 files changed, 226 insertions(+) create mode 100644 test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.bin create mode 100644 test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf create mode 100644 test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_BaseColor.png create mode 100644 test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_MetallicRoughness.png diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.bin b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.bin new file mode 100644 index 0000000000000000000000000000000000000000..98a0dccbff0044f7f3998ef5136d13dccebcc78e GIT binary patch literal 1848 zcmcIhNm2tb3~bhfJ?uMSc>~4KPs1mEMde960o1bP(HKuA2XNJtrCwx71FT^k8`#7a zwlTpJJJ`h@_Hlqi9ASoIoZu8^IL8GpafNH#;1+kd#{=eg#1o$J0w4zY7Vc&|n16l0 zQy-?ur?FtB4=yfPuD7VX z5;xB7(7;Sr-&u>8Jo4)#7>G%Uo;*)0E?9JY6|29(Y9D7Rx`9{}dQ`h49^+}%_pJtJ ztm4FfzJ0u!_IJE&FD%Cze>GQcU$UQ-ayL_&Cjr_QXO3N-qSS9sYj0%%=P7=}q*l+< z$WuPOoN{3rA0>M_$hOJn7%7R^J}WQ%x1NlH0L;*{yi&^u+DhF1??e_j=B}p4VEj^Yl2u?KE-Wt!B}2w)_<= P_uQ+IN#7qKpQrc-3^+Dk literal 0 HcmV?d00001 diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf new file mode 100644 index 000000000..b310af99f --- /dev/null +++ b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf @@ -0,0 +1,226 @@ +{ + "accessors" : [ + { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 36, + "max" : [ + 35 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + 1.000000, + 1.000001 + ], + "min" : [ + -1.000000, + -1.000000, + -1.000000 + ], + "type" : "VEC3" + }, + { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + 1.000000, + 1.000000 + ], + "min" : [ + -1.000000, + -1.000000, + -1.000000 + ], + "type" : "VEC3" + }, + { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + -0.000000, + -0.000000, + 1.000000 + ], + "min" : [ + 0.000000, + -0.000000, + -1.000000, + -1.000000 + ], + "type" : "VEC4" + }, + { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + 1.000000 + ], + "min" : [ + -1.000000, + -1.000000 + ], + "type" : "VEC2" + }, + { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 5, + "type" : "VEC3" + } + ], + "asset" : { + "generator" : "VKTS glTF 2.0 exporter", + "version" : "2.0" + }, + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 72, + "byteOffset" : 0, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 432, + "byteOffset" : 72, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 432, + "byteOffset" : 504, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 576, + "byteOffset" : 936, + "target" : 349626 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 1512, + "target" : 34962 + } + ], + "buffers" : [ + { + "byteLength" : 1848, + "uri" : "Cube.bin" + } + ], + "images" : [ + { + "uri" : "Cube_BaseColor.png" + }, + { + "uri" : "Cube_MetallicRoughness.png" + } + ], + "materials" : [ + { + "name" : "Cube", + "pbrMetallicRoughness" : { + "baseColorTexture" : { + "index" : 0 + }, + "metallicRoughnessTexture" : { + "index" : 1 + } + } + } + ], + "meshes" : [ + { + "name" : "Cube", + "primitives" : [ + { + "attributes" : { + "NORMAL" : 2, + "POSITION" : 1, + "TANGENT" : 3, + "TEXCOORD_0" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } + ] + }, + { + "name" : "CubeInside", + "primitives" : [ { + "attributes" : { + "POSITION" : 5 + }, + "mode" : 4 + } ] + }, + { + "name" : "Lines", + "primitives" : [ { + "attributes" : { + "POSITION" : 5 + }, + "mode" : 1 + } ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "Cube" + }, + { + "mesh" : 1, + "name" : "CubeInside" + }, + { + "mesh" : 2, + "name" : "Lines" + } + ], + "samplers" : [ + {} + ], + "scene" : 0, + "scenes" : [ + { + "nodes" : [ + 0, 1, 2 + ] + } + ], + "textures" : [ + { + "sampler" : 0, + "source" : 0 + }, + { + "sampler" : 0, + "source" : 1 + } + ] +} diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_BaseColor.png b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_BaseColor.png new file mode 100644 index 0000000000000000000000000000000000000000..5e5cb2068fa85aec944bd75c981fa6420c1cea87 GIT binary patch literal 891995 zcmWifeO!zC|HrSJ-BjCJNo}=hh>B9{Mvc;zD4e8oj+3ENS9CK@M{}1b?Yc_kCU=LJ zM05DYAzbK?bD~Srjf&=Q7&_WSxk)YE*KU5-@2~bpk6pX2>wWinzF(hxu`y9B8y6b@ z09Z?xEcyWeAo3#wSkcHogIUkV0an@crHjH>W+kkz$z0cBu`p|$l}fF%@|49N_s0W_ zqm2&@{hhxQDiqFKt#&n6y80DYYBr@Ioga|V@lSM^6B3|qTv5)Ij%m3GVY}K4MHm*Y zJb4m3_*I}@p_(7(6hupHurSNTmZVWjUx-=}6jZ3FH4FD1u=Y2On@;M*cK3JpmtqCS zPGTpEO0a@c1=#7+JlXK7LUD1W>g6p9lSe!!VlLua=_72?dTUM+IYg-mMW1Y0d|cc*QNiBUOQobTt1H4%@W z)EmstR?(b-oM>ULu7zT;Stz%`{p5hjTwZWg|FXM{Y2n`G<{C}Rs)68q^oXartyav< z-EFBiO!>&(&cl+Ln++2q!89K*frjY(jic;s9C|?P)@Lp@{6OgIMEUXnP{BtI# z-$EELJ%lH`AVu|7#SEGgt*cgng~81?2K;g?%)!HeSlxEL);VkEDQ9yIJ<=&4Ks~Uk z%~>>0%S}$6jOFIis{|jdXhDT-9b$hgoZ)Yr7%9;^Xb!FN6$?WZ{l8&{57T94kHQs1 z)`zb3X?E`?AxBolA$Iof)@4nYL*Nhx2JE2O-Jvih>pFGGqxDS>39z`kue>%u-akOz z!Eh0Fs-!^Q`8S(s$<1Al=#UhhUQcbHI;cAY7PQyWVqko{){!U%Uqut!8kogfH>nPo z{X%yQ9o3KA@nyCf^O#1-Ev3b>ew0zHC*vp}bm#c-@Sj#64PW@fUj0a;g}M7ym+->> z3g8I67#5d{G;c?k(foL(x56UKp;TPWkc_lf?>?q~zHfl}+YghN?z`47o4;*gR)+GK zAR9gzkLlBo-rlqkmOXPJ1H&e z+s9ez9ms2ar!Gm?)tQEj4jsTwIdF>z@^PFFu0_%gBs`D z)EP+pfP9OvW^DAVzOP(NgsR&N0xmnAkkda{#L=zH+WWa+MOa+n4x;Aqut0fzPl2-; zdTca&2!YiZs@hlR*vU`gSYKatn=g^mQctadrIFBprSYY}ISd}CzM$g5ZW^;dECvUR ziO6dmts*-W85=o+l^kQsf`#`$^)a?G5`FN*Fw_`D^GOXtO5v^mT8v6i8;}E@II6mt zUviWh@1qzSJ_^3~-BclFCZb71!)%K8mA634`rN_}u_8b&_lKW7Q55z`;KX~m*51L+ z&XXsvBx{xlXgw|YTM zGl(t2Y&&gbNh( z7X|Ue&BMpSV~?NIPn>QeZWb_Aq#5c0Atu`!R?@b$jA#PqbN~=6SR*ijV>nmrrZr*HWrK{ErbtvQuP3&kLQTD*# z@X;zR&YhNuG>n49Ihjag3iSo0c3QfO=-Xx@WTbRPG?4VYRSvZD|7q9O?7P?xA$o$*$Ytb?237KHrL0-OC85^EKHM$>RUcILFR zGFFK?QUcTyZGGt3E@ZTk)@l^5=4#QBc^*QCfc)m*&cu-gsXI^1#O1Cw$Wf zn!8V|!4Gi5oTdFaaHNRC5yQdw^sJ#S2lYsKx$~Y;D)+vE9+Zrh2s#zW`EE8(J<>rm z(1mz4$^xAbw>=J0A!<{eD8_oBxM=U*feI;{apHk@;~!n~?hERzh9hLQpE3Bqd=Cx*N`< z#KjSkBrtNkwvSkrf1n5xOpYU(yFG9sg%YdlOku$#+?=;&JAo(B;)coImd8uzz?=^{esqeZHiK229Rk&9 zOy57?g&%GB#`(xbJ~TdVGq9zzg|{|?JVq_ys9h!J0}OF&r$LOL8)AFf79YzXBEd`R z^wgmDlB6+?^pgont!XO{^SAm2@K#C0H*ai#d07hXj71N*LFwAZ$hvh<@eX9BZMx7O z^jZ-c{t!$*Vls^t>7SnWU>e21qx%7jxb0=ohfkW>UNoEs9%5&7<(uxUL;7~3e(2P!Q}=dc`86G2M{OlcEpV(|1) z%u$NSZ}fw2bVOl@kZlAjx)X_pW&!f5pMCsEI4c+FgT8d0hLRA5xK1$Ak65UML*l|j z$*t9>jbsW78DMIgz={<}me~aNpa5@Exj84zj#fHS-Y-yxAa3~w_c5eh=r=FCAF8}y zhC27yE5o>0$|FT=6iu3Hw6MKH!t3V?f4%`e>wcM0OFj~>>JDN{iG%cL4n63z8Rl)! zZELY=J<@6<3a13%$J7mmB1h>abdN~#>so|kD~%Bfw?H9t6P=awM!A$~k#n^u3v)DN zAmihWQ>_LEu8WUEhFmImG|JIxDGehn-5Fe0aTbl~W=os$^Ut(doBftFQn@3w*ul8i zUB<>iw)Bw+&b*nM-;xp=2Fz_YLm@vWDt3cGg}Fi@+Dt{t`VCwCa=?Ol0>Oo(agG)n z8$OF2US+3rHTwe--%0vAh(jms)Wcu@=Dz>%!MRtQ(?oc9H`}@PP^14Qp1io2!Gs7~ z7kn03Ql6*{9Ii*P*x6Z$CDk?CL??=K1JHjue37@NagzspX^RoAjOuOQO~@@zelAoY ziL~#(pN7;of!l&Lq^ePEDP(co`IW>?rZhOmY&;#lM9FJkvK}a`-+_cdV+T%ArQLpc zJy6{94l(xZ>BX1VohfMV`lM8-D-oePDGN_wL+lB0?8HET=I0(Fbf_Gow%pgp z1GaNQAQW5Z|GR2wWkwUUV9#eaZ@|2obRu%5mj`|y2#PhsA*D>h_P?S&U8E>Pct)|? zLY4NKsX@Q(M7RF|zz%rs7?`fy0zG>p=qe|k@bOCUc3KDg<>U2^`vJnV#y!D6#6G=P zV^1bBI6SzTn+s<9^bnLbW_k(SSpu$<1i)^Sp07=TQ=jw^uJ75%g9b_^UyIt;(KbGS z16r>qDxA&0oKD9{Nx-;L&l9c>%N{Pq?4{1%r!Xq_h<76h80mRw%Q_&n z)FK%%(Qk`t;jiz3)aM<<{xXxmb2|3QN&0;Nbj-(7Qk!FHHS~Yw(89n>TI_o0c>h~) z?FbRZz+bYxD>3RM2F_s=Z_qW-+;EP`k-L{T;f>FI(g61S3%OYY_~wV!$qFEH1_Pg- zZ0s)ykN$zF4d_Hh**$XxV8+KpVp*RD{%6C)VV1HQo0EYg^}A@704D~SJ(g+C+~+Ou z-7z{ojeyekn1JET`yj(T#s}%MzQlgsK_4oT6ijkhau(FCr4^1uA-+AGCwDMa4X;nG zAR4Ujlf!y-TH(pIL{h}^Y;)p?1}ct^_4Bk`AnrEt*CA{ySY~)9P>=Wu$YEihk%zy3 z52ey(t+qzGx>H97snSu1w|V+HNEZ#e+(0N!F&2!2Mn_zwZ6U@eqzrSPZ^lpe6T&c3|&$sdMDNJkYg*#8swWywQXgG&f zQBcbihqL@#k@dFHEOghrm)8^0MuEyQEvBBH(@uOp6RDv8iKJY3$kpDhc20d<+J>b6 zug%c+CKy?7Bicy0V99eiN))~*VhhmoLT~1pWj4%rTW&JRXx?J2T&+Y4LNEQ61de~` zF2BySNLX`_`P8AaO3ZP5Ez-BdPCK1;XuF>fGBvWioBH1V^?2%RpGUxN78;Wmt468Z z?sS4kro>g2zg<8-QB%x}m+bB#BK`1kM$ZSb94EIjr`JKuGRf9Nm>0=s@|kt-781fV z1o%)uzE}I>MI!88a_kDOXqYfKJpVhHHg}yfc76p>$KqO42>=hrz70P3uCQ^10OM_# zziT6NVd(G74(#e!9}!4z4j~l+Wb0#uhSy0^$1Zx|cbsd&9NM8R{b2SR3+lF1fG+4v z%SZ??(hu3)0J7~nuo4HlhZp|Ry5}CC{_2ZgG_ti#Wa)3P0EZ$?^n-PPmyKqxwVOP- z$dP-kop^e*mZ%wowGrd&=qVQL;OKSY`x_R5)*?pkK6o(3Q5I%7lc_6H(x<@hFsQJkuoOd}zLhug3c=MWJ~2r*uewGKv*KX)AH*}TQDg&bzhMc~SCKWKo#z*Usg<*MDp zG9K5gs$+BQnM9tI)^{B>b0u05fVYn_dr-r-TkuzU=4`a&{mDLJOP?6$*lhEa1s2$A zzfS@W*&5C4%QdLuZ2X5bXu?5yD&Jn;hh_l0ujvx;ZhBBxF8Hqv zV?U5RPBidvZ*nZ#Gj9x~2IGFF{tv(C@TX#A4KO^q8a@9rQOA6~)<|z1@g@u=s>|P$ zAoJ*AG-ZnX!d_>sCjtfenBf-tI47OV1OIIuHSU`L{q*74=^ez=M;(N#h)m?>2ZrH) z>4hgV%7Lg%5qET_$k}`Y3h`#D?4`PofG}Q(eH!+VFX`fG`dSIvfG@KCtOK|9hnw#R zn!Q-nYFt>R#GJK=nawvPQ5(oU@|(%P(CAoK?G>V*&$ji2 zK|DTDNEMbFDVdV$(E?(K#)}opwlSYCeMdi(z8eT~L1Bm~c$>SvdRM1=er4s1d;mYM zrZ5F@DjpUQM69vV%4wN4wdV0=qOtA?z`qFHevE#C18b~oG7w|_>;;HT8Ukm=D4@>r z1N#n>s;sB=ozWj1i*oJ1Or__PVwTSx+jdNzN{IKA@t>YZqTNIsv0)nfUjDcU#m zpbHZ9{c<$IUyP+1z@o}rW8viK(L^NMO)jHp!>Al-2gaHj`+=aeE-IFYw*u;qbh#DD z^Li{6lXXlENw(9n#>N(?2Rv3dpA~1f$T`Z@o8H#c%X{mnNK(UN)ioOb+dE3kEx=*4 zXq7Lf-mgj$AuITz-Te%uwH7;N_uf`>3E(_a7`8Dk)wi(tC&uCQ(%N0)wC9`Fk6KPT zh>DqIG|+Jg!TdJ-^%tEdER4Vxx=6_B>lIm{lD5a{DV4-(^s1?ks2ljQDt5&&fi{93 z^ctn=GmvTH0xe`3?+=k*8fWBJS4|d9gD#TQGiX>*NwnIe&xNB(r09?C=|pudE4}0! zV+-85`Un_^)A*KT9W>0B{AgQ__FubvnaO|sGU?-&@&@FWj22)&J5%RL3&9t&U7n8F z^8cCSV4r&A$0O@U2OI*ETUceOpzR+JZ@t2jS7?Vtj1dh2hUYE#zo9AGW5ECDw#awm zb8w-Bm43lm4zFz@%33Ji{JYqK8Sbi(@E;TV#P_L(3Q0f%2faZ5wG*D%ENuU4_u=p* zd?{k4Rs`#CzW|}bEr|Ei|KCJUD45+uoMp0B9=}@3Wglovq!D?)cIRK&&a=VZd(4HOM!5?6-WLY60NlD zvCrSdX(h6b(SpKOhdOF^pQ9Lx_ zBSAAMV%M{^KbqO;8iUndAbUqKanw;KbCE0ieTB=>Z(_|NWY;*mHz|x7WOl|1j!(ty zjJ7Ty6y!9z2R;8iar9m-@$`yVWwi9p#OrDNrBKjoCAL6SP7JC^a3F-TyH#gheZ_bY z!+UKm%*aO89@huRFJRWvqYQvoZ^6zx)uL|Es-wX=k}s}8!t|7`?_-^Zc+#p|=+Jy4 zwc=Pgkr3o7pB=*#{nTi+4d%$!*+_lR3ceZQg{h|f%O++W7Z5g+0-L|tib~;)e3NCO z04uQ;EpHq@iIL^2$%_8~9@1c)Z<#8acWuEsd5FCF6i2J19`pt$rZIK2NkXy0WHtp|#pfee<9t=^WReCjek%jd?s+$3n?V5N*;zfIZFlvDrt<(GB zKN@()EgizpdzLc&EcvLp*HpxOdF|&E(bit?to@SjmSfnlRmI@*r#me!A`?BjmQOUa zu0qmm0hZJS~@JNhH>hp$dP#zEL)0eEA3PWb zJbO+@)MZn&Sw|_Emy}qFMU1>&MTuEzrWXc#$ttHv!TgIIXv9^Le}bj%W9-s8GD4-N zc5)>@#+G9#To2iEjuwG!$ABm%=C+;qbR#1XJ(!D}|2{I(R@ryozv zf+t&~r!RRghGkp}S&8~#tv~&-FU%u|yZl(M3w)}CnM93PoKK4>4< zXjQg~X8XoMb-Gqe)OC5to5mQzt$twk=4irZ{AEV0@97e~>B=4Ei0cAqC9ckxsab`+3U)t`of;;Eu)OG3`*Q(Ngv!@6XuWZDpg>csT*Vc^Vc!B{lsmGJjPD6 z$hK9Z(g%d;YDP%1>%%OYu5;*4i9K?Zc0JLK?vBK${-zYvqw0NP^xoADV%pa}W;?NP z72r7nD&5bD>9*4#FW5&H%agtBcawkY5oqpNBj3#4y+C%!_4zY;1xM3F zVavI_bX-5`B=R5lHpHVPO+!{3JjD>b9u$aXlDlt?@^&u3Tc8L-3&+r{4~bc`Q#FHj z__Rh^&rg0}k?9oX_*~(R=&gFr2vL_xRRu%ySd5*wF&cj-To(v$LD?&fs!zV|NIuEb zY=G>&mInhiss!B%l4w}-&rPDlgqUbS*UVt{s8}*^kys}0yOvMXePOHBjcw@HbG6JJ z84Hp%!5YeN^(*w3sA{ypR_m7MT6qn`m~_&Zobo@^__B4%vW3wzUB7uSz1a zukCu@)E`%?0&NHT5)l?ub~Xi=Tk4#vfMO1V1Ks5UVyCVH3C?#pdAM&uO7-?WR~+F` zuKi(;*iE7Y#h`AK9@Sg{0T~5y{*aig`fhR&r>qUT_nk&#%+Qq{^X)+IW$3JQV&w4Y zGmPgwX{o?Zm6esM?Q@7!ZmfWT|4y?tgNz^@f0mGy?{Y|t=^JhNGz)un7Peu^%Dp#% z0S6CFM@`*AqM=rZr;S)wb_Z*Ia7Q90yo3jD-prfNt94EQvZDoIxwPxA^bWvq_1hZi zlMH}2LeO9aKGHz-t_lB9pxV4D2+8pi!Y_FysOwkNYSjjZNaU~)CRY@k3$9X~f;#sm znlG!Aj9~vv_LXh467|_`^vtVJhJjwesmT2I;30P*#G}=QkI}W#F$#b47~SPA7~_Tg z!?@Hv+FMU2D^ms>HD1k~v3Qa51U5MNM|?MEBjrw zLh9A^qqdXRQ@col4#U#l`~Z(>&ehnLGu-gbGD6q|UdtFCqz4W@VaLCj_E0r-mUTkQ zG$#M?2Y9%5@l5K21^@XHM{fx_upc=DJ_+iwj1Y7E+7d%yA5#+T$=9u5)FiPm2Z#al zD&iiD38Ymfu#lAE>6DnW;DB0S*!!78k`95*^^oh&U{`{n%2EEf-d8iuoo4vhnyr&L zdI^2|ffj$KOx-Rg-L@ACbZfkRa$K$ZYi6v%SyaS|wo{-R3hk?IQ)I;=;jd?EbN1=! z_-1y`6Mw^&{Mj3kiwsc#utrSO)8nsv8=jNp=~@-{8J0gRar}5cn=SCO%KK*~8}DZ@ z*_p`OQF^gMW`ZuzN7$AZc_KF#j0pz3ezDbgiewkQaBznQpm#)XXbnAmz(~EA;fg#P zW8*Os#!oC*p2yJIjkip-<=elyztb!Kx6;{JmrtIIDkf*Fg8(cXKr6Cpfsh!8Fz9L5 z;8D2sN7aUV7H`#|CV^oMfc)7^G})BW){~L1p`zzsMicfCwuq^o%AZNSnn>2mx>V?| z)iGgOveH8rDEgu5xc7qmstcZ)?JDany4L~7+fGEEgv9I{{uKdz zQrCk|=Hys__$3tnH4~%foDpV~L)m|mIyy;5b&76nRV|)P*wKdN3b^RgSa`uq;iNHi z4xT~05RerISo7;cW)HYon7@llB>4wv>|EqAbWw7@-jt?$Hz$VXJkJ@?+mx=LpV+Tj zHd%RU6uXyqm|!+C`C(nquvkzA~gEYaWhuILKi$1sCMQe)0&{mRp`C~YG9d7`crID>#A7lLmU2WBmMIS^u&DA zIy*}0xImTQk4unbXwH#Nin}dBwM~~9AkLh;E`<`^rw`WfH97xfsLoi>S??U=_7`Tz zv9ilIU0~VOx(p;sh@Rj<0j+Cw29At-dWvZL0X!(?;f{}3tq(iUImwZTp0#l-|Ac#9 z;g}_F(j@tkz3ggvQGa)0;RwlddGfczUr7X;HBLXd3X8(Jg+ndT$<$t zM*SIn;Jp&vdZkX6K(vXEEIz+(`a)tBHFibWQ9UeQgdRLufF0P!h~J#=)JPf|hS^9K z`eFpFh?Z>qM>RBGwO{Wce{zZ~wK7xYT!I_?==ixoC(*8YxU4UYQZPk6zmtvsFu~w| zbDCsN@j0843KYCbM9vo%z&8z?>KRADz%%t$(E`=tnnd)|cnJQ|w)FRR@S!D507rHc z=EV|@AX8O1jUoIsf7j!3bc$7wPDZM9uDr^+x)9*T6caW!p={Q3`kHF`Mm*oCJuh;X z~nXvzjh%2kDIc?wN_=>&H4B<3JZFw#z}RSiX0&@BpV14gg1vy=MW zf}S-8>n;^dm2Vtm$8HF}Wiq#OK~d|D2Z8+o$0&>W&K> zvaEQbGZ3GZN-L}vXk-G}`$^J$3^-~#1$(w2ns`eKk*~CoRsk*Px+C-P2d8%%Lt3@O1tTQitk+E4*t=3$5$k?>RA8KhWmyo2q;cU%uCQdrL z4uaQ`fU7aIl7qw(H?}-{OrUa!(^VN5I%unVY$GWBegJxAFPrh3o0~s<% zX@@j&v^$e2C+ZW!6e(E)!*2Q2Ld|1hu))fkp@4b(9j;=~2caA~GB6+vg)`eppW-ZE zYW$#8afasIF3ql~-y`dfP^A?)w8OsvQ72Jwn5VQo6~6Tm5onmAwWgFLMH5fS(E7s$ z>1UOFTTk)bm;xVqy%~79%tVhf7n9C1xTk%|UaX>=T!+rj7NF05p6Zv0XagWMd|XkD z4Y^&q#g0E=8$Uwn(LQVhq5$;3jcWA3S(LR(*KQ;4x5p8RqehHU^MrWG2(RiNny9;< z{@xS$KrO8`!aWPg*zUQmx*OuI3mp@0GHlF=l(*;wa8peiF_vnJ5c#u%;*i7935!d^ znObN)uPB$IQT5w1;S&0k!WmOmKMe#a}{bnt0wt zm1kDdkgw(|k+PGiz#h+V(v=C>@?@yW#x%i>{lMt?8CaV}+WUa(74MP4L6Jm#T&2Ih zf*8BbA(9p*=;~a8RP$;v%<@4UMT^DitfDWdn)NJFsIa9+Nq>S)KrpR8V@B9L%oUkF zPG>ffi=_Q@?UF2ZF%pL;^SWM;+pE?cNCqP?%E(dTTShTLGbyr6UVz!>~ug}76A?MaJwY1q?h=i%U6?8j;fWaKbW8{_U#T; zIqA<>mP(3RShT|WGl&+x%EAu3l#~E&vX2aHY8RCH+E-P-lVCmu`E$msF2-sUc{mCdn_>9e)(SEju#>JK)|CAP0E1>19V8$L{oXq-Bi{TEoF~JQ&_)QN;c| zB9?s!lfMTipCq<@<7lOzV{$z4)KT+rFj2>y!4tYFFsBb_=33xcw?HEd#=orx4n<=x ze!=rx>Lm(n7gmd%4*MZdZ^uGkheWd7|s#>Bt$6)YNtE1Y8D^C<4 zBh}j4nkL?{Lnkzb=zd?bNoOaLOC7ZMsHv9&(}RVn5;r-q>@>_hsjB~rT-(na5R=K$ z^VBc^7R7~cRa-FDFUZDGF#Y&e;JQey3X~)X9Ton|ti)KCGE}sw!dxx3fS((Cj#bI+ zxMyhwKF_=Xa}sX`V3}3`Cm-a!B|&;~hRU*sau;3As}7)R|4sp&PLQhfA2xET@iFW3 z7`$o~+>%$TI8{cdFlr9= zsa#O~7hjvS4*I$gT%H0&)oIaj1-JtSqiV2$LCI;fpPk<9ht6(jT#*nEs<3Xh5D5XX zhf&p3{N@-dp|Kv=cm!qygSuW{&1)}BsW7%PGIC9E_@1?Uz`)lAhH{lCOVYVHo~XzA zoWp>Z=X0pne1SO+jp|WHX)3tN32d1Z8_^wbsU5yed5HazEMYB8MIugF2d=RyZt*3~ z&Lg2?Bh;!^SaJ|xxd3xnF2<%zj_vLe$agz9kjqi{&@QxMhY~wQdduR%sJ&BnP4u$z zAvx=aXSp3|ApF71^6oe#`K1osg+`oYTCkDqT22kN(_#3loypsbjVTO$dx^~YlrLAw((gLJW>6_ z2AkK`qyw%UzOq^~eV1;T;+F`wLUq(3e;L%ts`;BL+TIGeyrNb-P!JpLTU0}fC1TX2 zMm7H1zEk!!T?GYH(QoAOiuKU7od~dk4o1Dgwo}UO*y5CPFxj|ZUYc$ z`4a320!0f*SEuo$brscSr3x;(gYL>gOSmEUZ?vE#nBxrj-_zt+lR{H7761Jm<+g;1 zIXcsWJYONq;jn#VDdwLg~p@DJtM(@}PrfbP^wWP!hSLdyft z7cu01@YFnP&XYUDi+REL;?bcmYjyHza+yPD3DFE(u6ac~^C9A9$d!&&t`e*2tr+!V zkPkA`ru0CzO?;x^-3JEkr=Nb+O&>4U)z4PVS*fz=_m%w&$v?V2f7?kN_6`F%Zn z+S~cnsro6fSol`5wvU1_0%}cY`VH8fO^XdTv9;fgj`5xgAs-t2H5QnY2i>l*z)^>l z=)L!cuVZhT(4>d9m07FNtvmTDGbme0t-8+AZs`U#9a|5w^?4_*gR2(6-43tNdr5JK z^p=S>*9T?Xk+A+&5NF(pg-7Vz@@Px=T6b)19_kj+hdK5t5I0-xb_AH)D0=Wr)0v)#m)nJ$WuDar9VlhAYbX?i=cIQsqb|Ag9SriU(`2pwtjN zR!__1>&Lz{_=16w^g9m zeAVB%KzC{Q--VLw^OA`AR@HVcvG6pbx~YdFpMAtp)MotpWd*`>sy+s47WTIMVt@P_eR-N8KXNIy zc24-4LhQqI+10QRy!}1rLu%GYZvg&%tL@p1$@CyAOa3>pP>~<^0H$9-dCutHMd)VA zM!*KR==}=ouVbBcT~CQ|zL%T@wokA8{X!iuyU+sj{+L>8q+QEjM>}-WOzGO1imcCP zY5%c6>4OTI?ZJS&%nTqTzqpJ@`CWmPSgs!?hLY2nBfX*E^j2c{31Rx1 z*bt)oZEfs)AZF+$`r#o_$4bCs#GegbOy*^m3dK)H;-!n5AUAr42yZm;Z z>|r6RDwiQmg-@=4I7iK?qs-#QJH*vozGMUk)#a>}r}AA?D%-}y*xl5!T3w4NIGUiBYO_5Bo$#Ou;U+xXnafK7*j z_~TuM;(i`4Q&m5#`qQVF_(TecLb2>WI=*DxC}ZUS&y!~J<0jolf}yMXPUCqRkS7hS zP`wFXYf^wO=c2ct=e;YL=iYQt&yh*3mD2D7!IFrQ>t`X(B4F)7zG`fa&S)k3(04sU zO!|Jja#D3Q!IzFuuPV)O+0t>_b_>&G*BI?WEx2}RJkhGQj+PS}91NkYwdH;2obM3d z$yGn_L`-UXKa)B5l8Amp=^e|@v@*iJPVhA@^_mB;iAy__Odetc0=(Sh)K9B)@;P)o zg|g<47Ur5i7*%9|Y#n2J4~D@GZ5arAzys${)>Km0$Vd8uJ(J+|%1 z|4iL&mbEVD#R?t%CQ%pbP8aUT?-GVD2rnd46To%jw&^;de_kdF*fAY2J)o^Q#j2!8 z=Iqqi`I8I0hpg5n1xjVhD`4rToRqBou32)cwLs0dYhcGXM>^II@E9srE=PXFMfUNq zwWzWcsyazkf~T;OIu9NGF_E<2$ac^}@FdvfavF54*F+uc+kyPj>mjTRzt=BTjV+ID zpj{iJUtO2dy$JCt_;_ryel4nBImdcDL0~0Qo&f&$GFCvlpl8>YR1&mg@r5QJNYr`P)H9d5H6+ z@2N2a;q=uPnQ8eFBBKV#6++o1*74V9_ALdFZEPn-b+qxXzOhEHBNm?Ym1&$cUw}Di z9TZml-_3CQ3Ak)6d^_3#aK8707+W+#kw*w8Yx{5_@(VvOo$-1)iJ9b*ty{@VwUh0j z$j+5m$+yv~mJF~x&jZ`h$Z3*-*)qRpCk~!|u=Sm4*5wF~6#+7k1KfuTS>*AE!SR2| z?*DFC?6lS<=yep>bCvXf^bjwEA;LLi?!M<;nmTIT?qTY7kbfNG$-gjhduBYMe)x#` z)~C^S&8XFD4`xEKb^8F*do&mBuALV?@gm&ORX(G@zUm-dxq^t20*sl{bgl}GW}a-( zJ25VVzfLIF@t|2}UZ5+bAm3<*Trih=D*cYspj?{9Fp;5)_jS-j$013h4%(0`ApYYR zSJcOLDS(Gm2bnDH;NYL=FG(Vlu}2a{AATj-dY<@xzoj@@=Q@>l$(~&)B;8|2?E}Ap z-WrjV$|W8A*cCQ<&r^4oIn}ZiF6zS=aU{nKBO7)uq%I-%!Q@FPmtY0=ZEX&Xui8hpnQoC0niyN(63IHdcL`jJd_XDGSm{WsI z)L%KY7*1Y=qlD$9iCnKKRhARymZtjX0(FU+1eqpmw{Fb7R&tC^3@ky%!%N&Q^;^v^ zrv%=kzMcZDnL5FihUbm8s-AjkdZ!|%6TIdN{JMfsygmpS&9_-alcga-!L567ahaztxQGcS+5D9mJaD?4Ku~~QM*)9W^l>zs#;5pQv9;#**s^+Lk(}s?znih&&!5pQD!=&mTt)(eoR5X@0 z4fqPqd1qv7d=Go2kd2oA9Q^+=HJ9YZKSR7Z#8YZ4eULP*H`_3yG`F`H-X$X@FrgOo z{^jmG$tR0g{f2XW>fajlyj?B2T|l0%M4#xhhI?4@=3|HTJUPqG^J@N+Yv7cpbvC8T zz}vRI@%J01+J?RXs<@{el&N>oU;dD^ybMpHk%tJKJv)rRIPW-p>iJj1+#iXY>dk6f zTGFiVb@Ry#l}(q=VPifn#yj6INB977P77I!X89 z47;ryIL#tTjuX?~3W)DX+5j=N&E^(}G@lI9!Uv99&?~X4vCLfRaBldV|B;?!aHXAv zGG!cG12S9R*P_caH>sj>(KWX%&JVgBjqvqY>emC*O`qY+gA%$DI1pKQSVaw16$Gjr zUt1*fGdW=9!>OcYK5k>4%hX~bZ%WnpltA(&Df?Gj;38@5J(^FXejP9+u%A_ZS?SDe zQiQ(|ah)G{Y42i;JyJ})JrQ+mNYwmpqZ$5RUmtc4&>3306~xtfglUNQb$T>8;Dc3i zrgFo5;0`Va8QgCa+)cUd}_<4%HcF=vvLFZO_bpfD>ne;_fG6zsw_Pqf@GG_Da{-#k6QE1$y3# zI8FdAzjsrd_KVSjKANBt3Pt#Vh35P_A21i80DBW}h8h3sCYGVF6yI`Sudrt4@L7HH zK^|c*(Iv&I7Q7(}Uq&HW#!=h%@ORlkND_4!UPJ6Ju-4*ZP;r#K?)SC~V!u_@EtIYO zGH#vD-3zSh&!yjPCH;6-!MJ>sx+WM%mzimCgaUmQs(5Pwd_(__qH~XHvH$=0b=Y>b z*0z#b=Mai?(ov;t4&_+6kt8+8hSZQOrLJp}kizYh6xYr7RyShUtq@%aIdr(lO>(*t zH7TvqxwhZ+`@g^TX#2cBulMuy{0w*7%4J5f=@iGk1xvO;TdT#(IMX9V_bo;D{ez%Y z6KUYw$H#kfUf>pU<*7`zGXIK|_Lwa-p68x}@*bN&5nCTAz8ZA}Jy;KvoRc&IC1{-T z_Z7^6jc;F!HQYK%~7G7$>t#9$pymJvH~-+(M&K4pE}4t;!8Fu z^c{G~=6EAK^N1e%ur344(uuzR458ke;fC3W->P9g4bZasujHXahF)=LWBm@SbsnLt ziIPN(F@%4f%4(*dmrk2?4+OrqPwI(!pqur5OwHg|!cv7ce&`CZyT1eT7^ zVMYS!^j2VO1X=B-Wvb6uH2RJ3;?q8-Y70R1&n(M4)@t;@Hfj-%sxy`>`UZ8b+`I|( zBGA;FOcZejovla>SD-rX3`TeS=9Go^SgUT**Jxb)b4z2Ri1Sl~q>gPEG>UI5M_Tnl z!ti&1>@in8rPt9t5jB@8LL;C~I|)>~2Y$Cm1-yetfx5Y#V8~@1+WJb|TZjMqohYw| z;!$Pm{uHdiDpq_+fxj>)U(PPGFnvS9E;!_}3d(r|7EO(LkcwPWiUVBG1`8s%I*}UB zl{z9)%)?j4Xmca$@y_!Z;+^;whGaFtu<2)-ef>yu)_%cKz6(?#oUQIU*8G{p-JBUu z8t;lf*kW7@Dtb7UGB9^^pPfF)@V7Vwmzn)^lnq+T8!d}p@uSx~W?l0WHK6v`eP*PX zLtm=mg+R+;_*<}~{!f~&ey~@6091c6K6z9ecN^ugq1}Jz;1D03J2=2bBLZ$I>P`-G zqGNk3%b#)7V@D9bTYwddl`~24wl59j&GN*|>9GHpbtI-t-htLR(nX_n8F2r__oxou zJuJFZhzENYd-mG;aSg773xOgZQJX;^oG`5w`1QSo_3N~JNHeAC->apT78uuwu&V7ii|zgitve*|@0lh$X`NU79^*W~I2&f6wzuw=CW6jWsAsOK z<4nWsv2(s2#aE>6sJR9+7b{u^#cfa05Ie&sFJ6E_qlY@}J>}|ofP8c9Hj0;7ct6>r zASi|B_kBw}@cAC6rW6l$aB%+LGP>?~wT+QWjUm^CL+}xreydEwE&1fL|9mCQL+rdW zB95ot(-SNGt_V&Sb5@^i8289p)a!(Ij*llkXBo>r?>CD~IS96;??-!$9uZ4)eTeK8 zQ}(RKO@$al&97m6wi&jUTTuckW?6V9ry%wFCgv~OF{5b2Aev(MAL2LuiI~YMFv}H- z7J+_~`@pndB6hQn_Ry9i#9fF?pi2wP8NadYS~M#b5X^x~y8zB~3C3#QP5!>zOy2V@v03Eq13-|ldMF7j!kRE z>(K`y^5m3}*s0n>8TkAhA-by+BK~smku+DaY{ctW_pIMsj05{`eFoZq8(+%n0W0v> zu@iKC+x8h`bJ`r>b$NiRNF5lFj=L?_b{|YSojfmYQlqF#tIa*)8hv@Vs=G)c5d+Lk*1O31he26lwxg6co*)l^60pfb#7%`ihqh zw_ITRJpui*6lO`o4l;4m9@1PCJ_@htok9E_5tNIJ$}HH8l1-4gR){WNfWy~CyAI-p zT$=M4*zP+Eg=oDzZ{v$r9@3t=Q|2j?f zioEGijUj(O^H}iw#mutz0iG(LXu62wEuL*kRz~Abt&4BzIW|FUV84ps3MnT*y7z~# z?6-k>kHrct=$i@i{UF!%OdrERH06+W+4kN~Aynl`%H~yIbOWUy##sHpd(rYxoMtAC>Hn2DRu7$NJuWA_x&@7BgqMl82ngt6Qpk8}fQ}%baV$QP~Ad2R) zIttNT8EAF~Uqt5}t&VDhITQB!#Pok|q!#3#weq7 z)b!Ng%E$K@*OER@GG}0&Ozp+b_pF z%+t29;%!mr4^uBL+iH4iGb<;#2j>3-6O?e51UP@#u;YI+#brkFxuPXPy7=c!D4S&##+6@l10`zk||CdxEIG?2wF@v$`EC9v7i4#Q_fg6QtQC& z&sk;w;cYXCc#_#ptTnt4l*SyGSJ_}q94G3DA0bo8J4e3|uNI_Bo&)i}J;7d~gG#j? z&WQ&Cjt3G$so|UYp~i`0T(9N9Q5g891z}mj#Wu_m1YT+h4LHoCm(@z*y*-P3yN=XM zFFrrazQz%8my_Xse9iAUl)npgGl8-lFGRPQ=80{6C}U7FnVx62Y$l(x%ZXP3=90Oz zN@DH{L#s@1={nGPY535fWh4t+ZY29wh{!dj0Ww=eHkl`9u}r1;)=Bp!s$#~&xifEr zFSBW8MIiNIpVa?->brQQwRV41DFL5lSj0fqAEpy7wfOf2;=D5~-#@PLT5AiO(9Bq> zgsqG5zuR#W8*P&#^;>yA%UP*}=}kObS(jh&sc!qS zgNH5iRN|4|FQ6w!8an8vdh+Z!v&j$%Tt6-{1&dJcgyBwWS{f1 zSVz;1wsusxlT%L_N>kLvp9*cQDS zn+>K@539cr%NQ(j>r%-^Wv-m*GH#e#6Mv0>S~#lL%)&SVxb|L;9jFzj{vi&zsi^Y+ zrhdLaG|Q%vI}LGr?7OXOrJKyaHnQ<1^vPiB&0Rp-;njM~e8w1j;eXYvc)xBqYtvcL z)hB4P(?kchO$yV_*3c$slcROIxsgX-XsnW>IlrBepa za#mT|!KGG;%NGB`IB6%%zF`k&f!HW9YZH(1aix4XEK+rLf(#s2{Adug`EPK9(^v)d zsaA{56`ZvQ0{0w6dDogHh|3%}_n8V_&Qra6&J4_J85?;=T)Ko+?Iq;vz=#PMr~^C0 z4|P^!CAat3W6PHkhavU9-x0Di8aI87t{XD7a7-f{{CDrpu@F7z7ZCeMdTV&{58}V3 znFLel?|;uI`^+_oyKlorpyW1S_J@tlBcpmW`!XX%eBT&dEhzUyP0|9ron_;{x@eaG z38e7^8N;wKLISKTz!mmM@f|{H{F{oz3qX zNC%24(!r2go$@0us+NDm9;DCwD4Q2xN3-J2c@MDHtE`kAb%fQ?r_3$T!8Ti&+fT2D z`hO2$*$tvL(=^0MQBM$ES zz@xvxh#E(_hW1K1VuWu$jBh{CGxHAuekI~uylWwf^F=SC8BkF-1N&|-tT2%6A1`0w zA+zcex+km_$N2-xT{XoY>xtbnMv0yy|1VK;LBBIxdq$8Mh!7O~=!OI~%BObkv7$ho zj#cnuGaPy!dUA zn=}UqP%Y)uEXMzFk`(9|p-XQAMWLds)|-I!T)e7G#N8R5;>7=$>$|&k63ad@?%DfE zgn!4_Hpyz(h70dzi2``2vzeu+C}}4s2v+hw!iAS#FyfnS0@HKFYgdBhw&q^*neF>; zDy-~9o{?BHKi`Mt{X%@#(vM#aY@Oi=zneS;BIblOiwDTbcf&8mU?-r8hl;2j#NVcPZyi>$l8nd=vlqvG z-X*GwX4Qhwnlk*vS5fv=vCA9UbJgz_6O+y62}&WBH(!0@lKX}pglV{BmrL_UVN{4 z&kTYL7+$_FpqLbn)vt9(f4iuNqDz3`BsgD>?z)3-_l(9{Vl0Qy0Gk-B>kpu0E3?)? z2i47m)@(6yLsO4e0ByHL*}_3__J5-6TPW8zm^7asK8e{s$KoMchat6fJ!t()gzF+K zAED8yd4ncpCoq1Q%L;?CKkeR7!;sCzR;KGm==was&V^&-O*aUd5|~zpz><_f{`ra) z@InAxTR)q^r+dUJ4}7#aHoF`*Q{xlUVyJafDzI%PqD!GhxWge#XA010aOg`p@<;7*Fm&qat7qdE^Z!zlU6vHYN#t;h!Ix{x;?aQkq)x{llYM#Y2ka-_apN1 zUjk}jJW;g|&72UR8t8AcmcFu)J=Bg_YsD^;(k>d|EQXuR>wAD~Eh4S0&Y)ydHTxg! z!A-5OUqB(4(b>*D@Qz^FI_c5YBjQUl+O67+qKQSlZklqYBxb0u%>kA!w&!cpvl4|B zXx8`DqUwFnz)ofG$wqNb1lhh$0#nvBP{2Ln%L^twuEdJ}oh?5Jo@9taOt89N^cDYw zC}5nZ8cQHQAxHSn1`w8?@Se6+W@@FHqJlKY)iq=6z zVo}vG{7EvNDi$p_vqy_s9_;Nq+1%8ZMeM2f1HUJLm5DLSE}jv%)%YV0)WW+^a~_tnN zt)CM+&656TZ$ZN7Vwsl}0o$?10b!sX2#wVOFHKyj-%ie|0;YGq9!nMgAr`2w4M2Z6 zmyYcOoE;^$VDxAB1nS;okESYCy@$}isJqq9b#TNgKk@ZE(h_Q z$Q!DKb={Y?$GT`oZ6sNyWp%JuC)D1pXPz#cK^*vSVNa}O4E!!Y3xuSJIb3n|66IIZ zB!-`<)Wt|uz_R^f)PcC8$>n2!&pjp&?;{OptE3kv)agu8b9~w>_}n zJS=mP^zo2T9yePy@;yT~s(5`GqA6UpcEH}f6V0LtArny+j!oZ3`a6+l`S@BF8=@!I zr197gVpBK-Ch?_@QA@vz^g!w~&Qul$!o{gzN90V$>iIsS;P*KcDR3Y?GAi^?>@z6v zKDW%t(C-EmKN0IUx(x~H##ntEQR+b~)74SNpQJ&jlk3fWwCh}nT^BKzRj!hC{HR7G z3IU>OUqaW+(&5rj%>0DYbSP_%sO^L@n1zqLuK=ylwmhC zIL}9Uj>P6?cjn-d*(1B5~FM;@=L|s-<3#JQH-$u0ko>f&vM=fKZRiH9L zuDruDgtE@i_+~qYQgv^m+XDTyO5Wu`ovB*T?^_jspRXrk*aF!)OX&q4X@I4ybCTTR zFzp}AwE81>_&LCgu@H798KQ83AFyfnSU%dEL82``4=8z zHoi=O0w=Aok(ZGfc!juRH)%PJPBkP?YN3Y}l)bzSQU$KxUr^2WU%>QwGi0kSHj5-_ z>fotS{%62N$0(e_Yj?h>=%47R3=7=|cu&S=&jrQg*?z*qR$@2AyaxmFh~Zetl!@%X z;FH#VopAmfzWlHG*&pqwA&8_ zp0I0lVAjU!fVxset`}=5CrxMM|HCBm7!(povr!3~lgaLeipn#GQA2YwP$Sfy4wYOr zh`c!y;tc6=W&!Ore)Ix~eho#>9%Ggj8#l_COaH;F7DnSw=3iSvE#5CG+N9_)6cmF{ zbY~r>W7hL$VAxCsZ>{1Zr`<%S<2Ehl7FaPl8-WNZ?hW7%y6A0&G^0;QuKq#Hp)oZn zr*SZy7Z}s$tdeYoFDH_BrbSTCY7vPN$y9Z$EyaK^84Vt%|YoYRlvP7K;R;FNAxJNUC)g8J!3{jrC=)-JTFgl zh6&OYA%`aH)Ne;gHLNbl9d+6*6f~!DXGmtz=0Syd?M%4J$g7_J z+ZEOn9KJwpnL1S~g-0?Xw1342(H%g0{7sM_1%2x4F^R03oz`O@j}OpJUMBg7g?f$$ z&p!w6oolfT=dHkcp?5*p^u7$e7&+zXfnGi#`pFYD+{9naBBN$VWI(T;&mzHi`ZpNg zu3l5xMO#gV$HB#=CCtE@!zM{5f7_GdokYVh+HeEkX(m5s0c(=xk#9IoISPNf8p3-P zKL2(BAvXq2PnkhX^CF*j(>b{;7IlcncV?U9<RsX|X0pX#WkZ%;wCy=+`)Pn!w&7R>UFlylp@Occ zmsVhXG5K{5xpWIP_n?J%&pmg{dYBkK4XS@ZN!7K!l23sD5rZVQ zopdRe4jj6CWopiw^!s4!GlT~C%x|=T_q@<%e=Bdw5?M#@>9I+ zy#*RKq_lcUb!HQxCbFmF{QfoixSTQL{(E!_dj)3<46WJ${JckdaK`NAH%*Gy)v=ml z*il~q^(vt31MJnr^)Ecd&Rcc1!BkpKik*d$ z3~h=XpR#NwZD#VSu~ty*&~*WGnIWbY5OHKqGHw6m_|5puNvoM+I*78#^_T1k+8!yp zFN&C2Hbflr&msY_PjR2hvu0} znn&%`?dBF+kJ#Y5Dlq4x*j)N6KWm}n#-OL{yPwqbkx+8u$GbRE^Vp5*_mDgSuBQUr zyF%u9)}XOGYP>-8#K3>4;dnMajmN`BzQAoq8+GXBBy?^OvDsF-%tFfdlP;U0kuGFY z=6*B*D3!C*20$4|o)Cng56byQ_#(rk#a0^9l04S5ikj8dg;rJ47C^eVkVqQ-j3tg3 z-9nO%nMl{zXs$7XB~Km!{$B;fzr0nqS{bejhK-^-^)0<_EOG&(_{?MEV~;`mKZ?uD zba2mXIuuDmZ2DUnzgm#a`OFe?){P`q?P|JAq`r7TP!Ab zU*b4%dJSN>jqEPMhc11gn9(*y^|3NJGz>HBzu`z;jjy z)(wY9T1R3#FIOm!yzWcMJtYXEQl&-Vrvk^)(K z;p;wM5S8x0+&aLBAmZ>D6Lpcj`jJ4r((FwW(|oeE&oAJ5D`K~g6FBJ%yUhJhxbbQR zGqBF$O*T~Pp~&6AD!jh^6TeKz{}}9b zW|-M{4B}>G8!mQ7znXbHHjEN6qs)w~)_sM-wu6ap7nHS5L_R>7_cxa1Gy z69!Jtqazww4&*S%VP$_A@> zWt)+*9{VzcudeO0mrk6n{lyE~vEx7&k*Uy&mUHl5y@}L|t(0O>up~`kJ{wD(xf2L^ zD?)Cgmv25)^q8v7fKdPvB?Rud(pY;Z^AE&sJ!|Pppy780`Km&+TZl0Y`La)j#go<{ z7Xn#v)o?uXI&d_mW%Sr<#|nz>@L5UtUO1`eRpr$k6v zIP`|B$&lI3#CTh12IviHHHg2=wZI%r6||NreZ28k;6AfNCi}3AY1A7b(g74zAU>} z#8JH?8PJ)7*}%J~QMgrXLY<_)Q~rM*B}^Qstr8YFeeYC?EyIrs$%zYvq7U1#?mG68 zdYor0tsk|Q49mIk-{?i#W~k6;@Yr4l%B|V~!F40mL~BDtM8^c31z$P4u|Rf6<$t zKb`szb{73Ug)j5szM05e8{H?csE-wK7gNwiJBoV(ugVbR@JREGo2g0}-4zQW^NqvZ z3QW?#@&A9UJKNE--r+N+IDY>b6dWFc3KZa{xGJRll}SW4Tv6n!LvEE4)J*uiM7&+2mRyOW{)9Pv9~j@;EdJc9G9TlA zzo6p^O%Pc6`4+szhYWS4)-Mfb@}gRLxbh9o0@-AG;1j;gAbr+Rch*od7{yA%C@Q7* zDNGGJZK6(2b*}~99aF&}Qd&PaCWw5xL#E)(fn1o((C;AUkBDTl7?JLpEc+W$U4y+N z&!UCau58M{kvtzuEEAL4AtT)7HL+|CnQKS-PbPocN?*}_1rw&#bDcqZxH7pE>}9DY zte1oy=}!Pk@)?Ec%)sYLP<={i>UXU_>$`8&QtCw*8R#u_^VU55yF!$mf|g{2FCMR6 z%kx^&%W0HSpoQhPX`?ypEg< z25*xN>K~MgdlRGaH7#h#7HWI^65{-;ZPa{g{KXtYc}=^3oEC#undga$Hh5reuZ)3+ znbhoG#AmifYa1hR{yCI=l)AJ=%yjb{-0VXAvxivnlp77E>Ry=PsTt6X`zvWDO*t#3 zzh}RAd1xl6W}YxD%SAb5{mlZ>jx?VUK`AUG)!EJ7vMJ7*srQ8V76Yn1U2DM8G)79? zmPcA7HJEGt|DehPig&iLa&h#V_)NDBuvDy{3qV}&aB9q==ap!{*$z}f%hmG^7 z4501ZS!`}AzME4aR9fvOwxi6+X|EWIt5hb>0~$PF&F0zRb7^ROKnpi| zer;Kg*dwE~$L)`m@4(!019!BpRR?uEnfCmUvYK8F+z@S>LB9+!QyNn3Mlq+($Uv)3 z5$6Go&7ht*j*$KHT_t(CO>xkdXU_~>r5RY_DBSs;S(~SlDe5jE36>1=$CGGPn6rB! zUEot8(19m_nrv;7)e!`47 zs*AFS>%ki5zAJeE7g%;#J6dH8s*SFt{$23Du2HpJ|5G%@0a7A;Wlr-Rq; z1BDY<1y@J-fsIVH!LhSQqYUBgO4qY3kFN(47BdS+tD&u*pelNdPMxY!!M4H7_O&$q z_m?M_YJfZM5NC@jpuTRX%~f1o{JA_m3xmtbjv|roF;^Mb$)*`I;|lcBHk|tv|8Edq z2AWLVLC$cN{qJYMVDY*bYM~6@rp|!shvJZ!#9^l2Bdtx@zZNT0Z0P7)R>>U}_mkqX zwdkh{x`Cdbo*GLR9b_l9Om^41!!5t8rC~yPL8WS=4Z|awY5!9#+BdVQ1qP0?>Ag1EN9N>P z4>Ru+ioLVm(hf>&S-$EIX71E6)|d2Z_})T(NCpEUfZ2jh*vb2p9fB*UoGzqjGcpbGsg*(!pTWMLsZ=b7kR zE_(UOerzBqjpZ{a%9iS(qFbV@Lt{{32H^G6MRv7qIkoUKK5ZenV49okRlg2KEJSM_ zi)ZhJ;kgse9ct#NRvAV$zJQ`f0RPE98$Mhh8UT6)4GTIHFL>#auycY)AJj^Of7%*N z{2RUa^!1J8t9MK{npLoIX=c=JSMpKF?u$|RbPKQTP!sE=VZm}>=|8$Lu743r>MHX> zP4a{l;5**fCL}j`A0ziPQ1z1|tF_ShC549-ntClVxcAkz?4k~FPt?chKr0H4UCe7* zP{S@5H^ln*qnG11k8ijqyyZ`U-%`VN_kBaUT+k~AZaUS?EW5p*A9*<)?z{yhFOj2M zPI%l;d)ensA8i6}Vi5TNJYuxx*T?nr5OMNT+0LWlm1_@xNjQCjGO800xqkGp^qZg8 zEplWk-WDl&I?#4HD?b6qDI7(vyRB!GRKdUefE@GNP!*DN!cqDmNF%wa7h-#^13#tY z=?&xpAF01(lDnC-+S*eaWK8)GjjYhz49Z!qM-Md6l5J_iFMHW0T70r;id1Z+K{=#l zUxz46dB8jcn|rtdEtyXqW1Gsn4W+u#UIF>OX@(L04EQ&+3_IQfmgysaGX9v5_9Luk zY!?D%&cwQCN$aT5wQHi=ejkY!-EOMgjC=3SnlxVe2Do04FnHh51I?n+zA@0=hcW$& zW#zjSib+7yES{AA-IsKy?}S@00-ldvO&CJWUhk4Lv!ld(|0a|2wZ|=!8qBor#*&G^ zy_G-tDp4zAGlPt_m;W?TjRR{d6|J+x$W%1+B%C;(5kVA0uo{7o>f6i3?@0wGU1J(X1b>ITf z_O!wSO^DpU;Jre5UBFWM{MddDcFkKq#=rMlX(}IL%c8+D+cx?cp8Q z>5-+oE(KkV;P?CO;d*++?En=Apf6C73j_NwPFz)r&#uKSCFJ=HGpm9-EHl75XWEz1En2fd2-L?@zL5(~$=o#wlB)Aa z9>Umcw0~gyr(j4gcT^`lwD^e-J75>UmQxM^@mV7 z+ddK#*O1e9&^kmL^+SWC=?)ql&Dr$!SyrBbLF-<^%ixNW4jK^dVlM)n#neWDY7cj7 zBptey;Sb(dpqpULuq>ELn=NII*Gi%!ro1wuGvM3SEuAo^vuG)03$w`Hq-Z+2NB5j2Y#BW0R3+h`D-UxwujS0J=`$MLH4lueG6h# zfpIzH@C35EdIp|(ns{X4MQ4jq1CJc*v=(x+Qb1-FBu#bFM14=B2cHB+$B*)G=)Ubtu#R zp(6CJjT?c&Y|y_5P-h=!mz~bEEVfMYdG`PBCRBkoKbX0aTgqRz5Z=X6sLm||bbWdX ziHW&%Z33r!)=Gxo`fi52xPAjGyjo-|&;OdJJ-tox42#g+29N4kx%7wWSB7$pK*<xIN4#K;P?x*6_;q+An?QHGdWN#VPtxa|VGH%bQwtRp6wHx7PhMo`4n zJG3c9-bv0GTfTc^snC#2X`qE7rzm>2EB&YR1>@y2Q9Dc4@-4a9>2_qp)O=56}n0TI1Vr} znAZP=uw~$;w?%W)mk^KO6$5F*tfpaRV4H2^GCj<7Q}6^s(7i|nTkeS)!%|nBy(*-~ zHqYWNYGy0V%R}B+gPX0$=gIgFU-F*_Jmtp);;nOl>@&w}Ov`E9DFA-0VtxvqVpKC2 zi)9A{!CBwu&6`ZCUcvwxRM)WjXX?S!0sN&xbk=YMS^;o7fumgvvvm9i{TgdpXn3Mw z(j7qMKB9w@jvKkjK)&p@mG-IAEanz!zDJHmTJf< z^7%d_;)+n5H2}1HbyT?z0p$SW&DS=-$3F&MwL)obz^3=WaN*vkP|bu2@rH9mvoW~< zMr7ye*HG6XGUZ1Pktz_KI*K!dTDv4lHCbk-ag+Z2IhN!e$*6SrLYE<2tL(#XC`^)G zPgb3H!G72q6&h-gwq}y4%D0;Cp()K3I)Ha!A9UVSYf)A@03X}T;w55#GNdI;CmWGj z>2b`X>h0`Q!eyPSWbRM;fr5o`#5zwG$+}4f<*xG=}(pv+@e8W#6OD!f7o{A(G2+ZRYet z81ZL!fk#=)rR&gN!Y`$5#)EI&S6k9B@?Vo|h<_%AXF~U8(QAtdeA4z~G+}aj5AiPx zFGP6ae$jBMc$ z6@OSk5#9zRCu_|z!sHaPPr99h-_ynBXzEws(MEH<;yEJ4D%ehOv0LhH!ClnMTf zrQVp;R(x@R1-9;q!;30yOK*m1HSQ4l9-E8ei>%a3O_HY5EL7E>%rZ`^J>912B{Rkt zwv(U^571hEjqua)A1DOs`%Lw-Uv4VJuu)9_?);d!|1Qzne1tI5;eV|l^DTLJtWI&~ z9hAkZj5`F}ufeyJ*W>f|5WkV8ozI{pKWQsC8B1vp=@?JWnXDn5>AMiO<{cjVrZf@% zG>6y~fcDAcu^amrq{!Wd@8$m=O7eMjv=m2-^@-juE)xm<$Ko@G$XQsI$!Fm z2S`18oJd`C+)NG)6Y4%enTXRkj+rRcT(U&AneId@7 zolGrI>_0hPcJH7`+FEDndE1l13xOH6z&$!Aa_`kCv#6FVaaK0=wim6N2d-3HKzH<8 zC%v31QyZzhyJ2@Bedr>c!zs*TrJ3%(CM-YLRq1)*&C^t8TaF6?vxt$T@l z=ekNB4Ez*+3tmM&{?)g}7YnE>vz(0fv89WBIHsm@e=w<9&yie$lKg1`$AA=z@O@() z9W$uKX`$yIJf7fIWDvAk;MK-!I?rxeJrOAA88nQ(%JdH%`u(H9C_g{nX!@1IMmS8N zJkV7M*v{rg#~ayPNA7;-tF8|+qkqz=^=XFfgx^TxEckm@1+k1q@4N;E=*V7)H|$2a zEFQVQRRtO}*#gsFiX7O{#N5LV!Fo2}Jtz|NVWF#mrFRvf_crEod$vjt+gY4zstiT{ zAhhO4G%@xRZ@#Z5qB#%g+6<$THT&#guHUL|u&hTvTXl-%zwrRq?_)2V)HO?H(f=ib zqO-5XT3^{`8+DY0dd_d5YNgRuHs&! zKC%24z$-v{E{ZZ?*=_6vBiCiHXl-pMtc3+C)bQsQ>c2DBjPS)WQOG^TfjV)>1I6BE z+W!W5$}}wXcdfm9H`YoG4K-R$xcU*RiXg`RhwoY_+Vx-nV*<}^;I~V@09_t(_+uSt z<%$$u($SBBT>#$k&|kN8Nc6RSw%>09|E9>$)u+Xg4EgsdGU-Y{V@FPRA6zGa<69r&fHEM>E>yKWD5M6m{{RP{4?&39*?gvIKPc)*6{_KUDlOY zF%u2tx4?J)mqDNOfBf^$G-cTT;8+*KCdBBP@fVoSyqDf*4of>91yD?y zeg(b*HRz7V(6tF1`(^2LEa%AcK4zfy9X^N9m-9xyDFGrna;_PdpT|Ib=r{7Nx zW!-_ndi?r7b+YcS-rAw@w}`8rmZCMSXoEM-JcK`ZgLlg25I^VMjr6NTVm-i+nL7BB zLHu_QTDyEl5wSaiesPO_Fl_I7;^kkW`%5FmzOA4jEFJ#!U=wVfUx5}iVAHpORR1%2 z?}$Woj#%dTVAXl_l_shZxdqfhwBTw1-F_IhC|hKkq%kg*FqWJ>y0HTmMLF;@9^CY5I&zy^!f+D$FLDQ8R8w_ zuT47G-i7C%$5i_qGVwaXd3bib-#328^M&BR0Z$eBHiCYVjahz-seWRfB@LsQKd^V3E1#(iyr8Z6Bl!5w(Le@NEx^eQcK-L>4QvNoP<;&gT;F4&KF#(+boPE`&!5xE1U-!*$(j&}1$zAylfF6z zFB5Nz(TS?#MXU0a5t+(%`2ivB?W(V=8p%Lsr=RYklcj$i2?$QSC{Ci4Wy6c5ROcT2 zpJ*z%Mvw2BhjJrUt~8Tm{#^%Hy&6QKm5-5=@Y0It^0ZUUF0zt3fy8nIkZ+hGZT7I& zzFo1}ay}I`J(RV2%M=zFp>2q}j+S=kpZy6B^w12*;T`Uy>sg^kp`vWjfCBv$x{lSk z4avC&_1d|~I`>c3N@J7hOWe-3JyhMr47^W3r0j*M-;;}9@wQHIhePs2rM(_-=>2IYyAGd1=3Dt23F%u+!@5)YJvJytk6n8uoMyu?t~i*Hd+VC{9!dMeD5>3XKT9R zDEb2J!h6~1?#@KAayhQ-7F7?xFI~wfx~cT#2CjVZNU_#R)Z33g_@)<^8iQHp6+r2l zZn%_-wH^`89!Jg*gwy+BTRq!IPW~gs*PIsl`e5()s3BWY2du>mw>qJ`?O<0u;&KPL z9*ERBK7jA!i+u;MsQ*=n;}~c}Kb)G3uQ@KtJ}&CbpkDf*BT1{VlKcuHGqXZZ{}pkO zRtt3feD{t>wLv+@(42!|#C(1rq1-XZlvnoNuE2I})1x1X>41;>4Jw+5R{7$EG`02L zSKQ8CC^Mkn2o7Oik&7%=7}FGrR6LR_X1XIX>v4#x2yRM;{XYOn2MslkXvQQZBK+@{ z^rb`(%(s#8#wEr4A4g~65X1lf@i}&Ps=Z3bc5Ee~bl?9IjrgZVuGS<7HFuZ|^Ih=md3kYx+o6u;OEjH>|x_ zys^d2t9%=`Rf?IV4$1&)jh!IQS5V*DWh*IROxkxqzJmcIECBKgIoEBAwfj#XKFVsa zBKZJ2W{!H4oqW4q@$4v*n1#3?0(5=Y-}RZ>*JVq8eNQj?Ey4WvFj+|*&N*+2*aDsmLLN&xnw(B#nXaHC{`x8`c zJ$`#$+9Z(&H-Bnu6`)z2hAI_P+KY*&N%AIqA3ZYJ^q*33hK~H@@)&f5#A0*yTMhB zG16c*U2LStIc!}j&$h08vtk+hz+UX)2Q)JgPr0K}Wm9awf&UmzncS`ep()+fdxUd7 z8>>9Ej+`eX_8R#-Lt?pLfZHO&7y^HXGM6YF(mQid?pPDHG29qzCy;JUimzr}(X9|yo)Dh!ZZW^}#QM_O4s~D@NoNN6gi?{)y{^fXf)eu)~ zhV=YxF#@{Z1>FcnjfY)>grk=N{B6*C6Wr429`^N7IF)Zkd{*H5&=BDL3Cyyfocw4b zzu+$qeCtkI+EA>|>u8OhNHb{})Z2TTVI46=>QXT?fA7TZK0H8v43UrJDkn`Sm{ZLz zA7CjBtmF-&wSVF$xux9GK^`Jf)(PcWbLB8YafMgw@a%L>dnB~;%xJk1k&OJYN!1Fh zG$Q@_xq7iP9)L5|XRwxm(Cw_CX-LdMMmV00t_6KhOS|g{XC`-aDKrthw50-k@0u69 zaSvFl02UNv;DK99F>dG43s^LRfn9~JG)ZSC`?7BhPQkePQs(mGZ=iPaH)f)h2Xrg} z1?n3>U;;x5L6k-o{+idOEVm^1%1FQ74@EkXs~>QgReK2H&rpYruK*Z}lMK#+>$HQc z@@f2HNv=gq)W@>*N5I{N*ME`=hej0bNKS=m9jtZ2T>O{H6fFw82jtbl|`iU%|z(xL(`=|{{l!7 z|HL3@mz7dFQM-M2C^_eDBFWvn1ATuF4)^cJON@ru)qz-wzfS#bHsC3rGhX|Q&LG3= z92A!N%0*+eUnWrJ)=#$=t=Sw2go?TDw2(Zu&}P2?_5XAP`x5FUBe#wYl> zy`C87*f6K!H{G_W@x2)`>qmSS2kH6L4Ahk^`vb(U<%o}fA39#@Y?U1>j}aYs>5J6= z=`iPO#&~*C<>6n&9O~zVb@*w{f&}8Djj`r6$JGU}c7rTGBK#wG$#{TkL@h^WlJCs5 zqyd#@BX8r$r;YOIEmGP9A%yOxlaJ1Rvgs=*JdAAL5JV=p!Kqio#(mKK5pq8q zyYQt!dFf|F^JxGIO8@Mux%A7rR5w*D@pl9AS_Z(o9xYb7U!H5JB_7m*!-TIsX=4d% z);~7*aT^yD054yuEhAUAcJYY)piM73N{`t4#iC#|D`DnXsBnt(@*(NIb0P30RR~a` z#H;55z6Sr{YvBbtqB0g0!MIZ@6>#_}nL5CUdt1X5*F(t*2lbM^46z>P6TmX?thq+D zjPux9JE-)dDMQ{0rnyhoiODhjE=q||MfvF>o#iEug^}xwHa5GKW7gVhM*lY~Wu zxMkiXG!{s`a+_heV0t>6ZIR2_6-`Wp-dqWtHDvJHvnRG?A1=p7rE*7W;sEQi-u6IwFcb*eDo(Z9${L4&<5x!Tew9c9^>EGa+2SJA zHSp5FQGCrhltC~YHP=SwGrENL-ZZ|1a4q~acM|D!Ci8ynlv7}>eCvSahV$dJGO?L# z;lO}M8)V_8Tk^4nu$qEf7rT?zGZOLh1hH`3c!Ca*1`zhn2l2A z*lR$^mg_*Eg^COsvMwHNRQGusvsJ;XPxiC(o|z(UwWh|#OZs#jR=P3%VLC^ae5{er z26o=mm3^$B{mlDsl7n{ic-cgLfRLqZ)HV2@u|V5O8Jt&h-V6FMM}Fn$%Tv*Kv)wZw zV5e#7yim=?XN+ghCRNemrf5AXOmBL%PFB?;l!G=NMdX|HM8ig$A3!Y@5k^2{2+Oq& zz7o8J&pQxJhV6IKm968*{u?%xd>uw&-VF`1%jE{jSThBSU%ZB0++^$X2nhIs_^<_K z_rCR{(Gxw$UFPywgJK4yrug@eew||<64b^Rdr(7Vx2q!`wAx3^Sra)_Wl&g&dynP4 z_;2AWJ~1_txIA52G6BDJ!Bd^Rlf?<*df2IA{fQ&YZ8+X#AqfUzeb~8eNW0ZAx6p7Q zz8c-=OI)^-Hk8Fka_%1sl((6Q6rLspqWi4Ea;d-dHn!P2;yfvNdMP85RXyBP?;$3aGjvXghP? z3qB6#tfdc9o9Wh=gBcY-T05~%5du3KQ|oi-JIsR`O9Y?mn)``d@H(AGObtFqx_Uvx zosamH#xvy3eZ;B3qgdtgByy@>9=SNsblf<4tAQVf%34EwUX=)0jTuA2I9gS{7tTDp z1B(eWNWCzg3ZbZR{)(Nhnptq8Q{PF@rx01)sSe|zEeYPB{Zan>Cy>>${bYyGUH55U z4XKJoBlm;K1)c>x+}3RyV9|frEvN#tNx08yJpWQC4nr0k9+5U2#dbDl$ZCGNSGnuX zi6d1|`%nf)JmC=B@qPt7-YjyBjn8IQfXxZ3(z^C4A$@Kd?U(0IPWGt)qgCp6URcp( z*2yY^B>dRx1;#uG96?3$c>7#oLGz4%($@$RA zwj5697p7N$;eVkmGIh$*psl}5N->?jnxzOvw16Qs*uR;c_B@c<(nFp$lGj-(N568X z8qNE51V-rIo+O6*Pq`DiKcvpARACsySNFd6oW}gLE+9V4|i(7+}sWHaGOie<&1x zWA!8?0yPVeo@W9ZiNSs@efJakd-a+%URa8`LZOOSz)E<=D&$W!2hmu7F|O(Kl6sh zoy3Nhz{^uU* zk3r#fXr<;J#w>{^dazpq*MXrCPU+Ge+&bsQ?5A*eF4~<>eAEhc6Y|OR=CVqzPm-W@ z))3?PU|TD!@1(8VpNkm-FnKjuP2{QeV`1TiP)V?aLn+c>8hU9%TuQWaH!vXY2R(()Zob^DKn(OQz}hZ7 zG)F}?KN)TY=j)jo(#UbVU*y8d`=s#4_X;HWJUe2&9uPiJdWo_-fI`h5 z9e=)w`uA`sT-1ITF4_cG?_jSsRHejt03sIy(8|3j1GsvdeVpr#n|A-U?PS7*ml$M4 zHF_r#EqSH?bGnC4cf)HpAo5rD-VNP0c(B=7^BJz#2ukXE*{S-k8PDn-mSV?Tlhj#( z&hlq^b!eLKS5unI-m+Ny-8gdCPI2w$Qd!kstkRoC#euxy3w_Q^{BhuF6S*ia0|+mW z?z@K1c?wv5hm*M+YZY97l9hWsO&B*gD2NeY7f+!GjNdxEQL#@Yya&xXgNGI0!{2=Z ztc*IP{^ua8-Gg4Qc|oMnn#kEF;TXT|EE@?Y?-cNHSATBvlS4;H``ceFDuB&G9Z)iT z1dMu?PCm9Q=r#x_&$N{!vjd1MMAH6P-z9MvdhapF$v%1m><*SAmJXVg!`8(W+?;Bu zzwRzO;-u=7lO(I0h>9AT4hbb?CL2Y__1p_S&&ysGFD1U`9G7$m2@l-uPZ_x$KCYh%V4X4<}m)T=Y+&J8j<@Wlt; zll@WD#5al3s$rGEbmqn9udsWzQucVeep~?(D+9}Z>P$6N3b^iH*tKyKV$-f)|BYR? zI!2tcTROR>3Hx&l3;+5T=)QU}%WMj9TS^%f1d;Pjp!RcZ@jcw)Z3eYY+YNj~%G69p zMWB)V1SH?&u6)P!- z;wEBAlv#d@dlU5DXJ`d*#gztky-B3|dlT`7)v5Ru>HktUHv6sXygBU&jF4)}b?nRBn-s@MeZ|(u`k)`v@o(j*eJ}wb zwM&qfo%sPI+! zTH)ia8}GlEmRckczIMdM4|wHjy4wjet+b_c!N@q(`-Q*=Yx$_z`N49q(QH*riGJx8R3uK&gxxKil!yw$NaTELDZ%a!a|?=W#$;qR1`<` z@Q*f1qnE2ARt>_9UA@dyy;QIGeDfOzO8+pA_O?bZpO}ib%-_A|33l-|-tqw0{14#l zM{knwAo7i)bf6u-tTJEQbO)I^5K690$P3KS5BecASQ$baYRYoO>T(qXYxi%A{EC$I zuzebza(=a~qs?Z7P>W+p1(+qqETa?g$@}ui=DBn;L?)M$_A~JAn}ij3o6*&glWdEx z_jfkg(pTb%kAa%CKopTdzBg1?&!Jgv%4M)$qiyh3wu?N(TMtaTN+b+2E*Q@IpIGnS z3^+R#f6!&GvE#K~Q-u*|W(69C3Zu8`>F5FD{MeX!5w%O(zWZfOEdc^7~Wc)z?wiX}{F zYW-t@c*T$~uLHQE;iS|tk+c*B1Aj0>I!{1IhS-g#e~Wxx!(~liseo~T#@Hxd9Wqgj z-D@kc?B~>309lTzu(zngiD4v)m5#1Av_0y_aAUUtyFBIbuX@&$n4|LoN4+Mu>Bu$r zZsYv1)NX67de&u`egS`uBzqlU{ zUwjYA?pO~6Iuh4geHH7Sw11b?kX~T%3YIdiV>5j)1X0M%(?cMtDUWnj5|?X6z)aRc z{HtTZAx^~Af%`Wcg5jOU14_JcD z@W9>$VF58C=w=fjaLfoc4<184W_V1VLwcq5P~E#FG@Rwf5LlM7Ql6oixj(^{PB#7~ zi@9nVCI4gQvlX&*T?YAuktLg;H%wKE$sOoD*-YC^7}gK`#wf_Kf-7+9nGSs-Im^P z0geRJ?Kd(9ROEL7@MI7~=BE8tD3@p&NPhT4y$sh)PbA=l3pNLN~C&)#w){%8(9b}#Jh{>$c&8|G6 zEko)6dkro}4s0I;jt?c`+^mzvpCHRrtos2mucQKwHpjO<5))SCn5n+@$uug@OP&f9 z*I4)rlAM|8#Kv-|{WD_C*88FkV9_8QOpy=y0kNXmKP!P-U!@K0s1Y0ha*M-%`YM<& zDsHD;n-)bcgqe@;=WM#%&Y{48^`lw6c004p-ny7`ih1`HSI2eS}%x%^B~_ z6GGE?ak{SKpw9^?AZ0;}c^wM+DO2%4HfrxWioA1Hy68Yc&^BRtwN>gjF(o9QQ)Q1g#a<}2)k!~^q!3NrPaOr)D_J%GFS%sTaAHgFod5)H~Kn{5@Qk^)UXn8X4) zE0zJS25iPlmTU_z@HkBF+Q(7!I2FuAW}Qg~i*{!SU(6)nMK;0ACB(Tt<39A%0J-g| z&^DM;WQN=d!tIT!tKad4?s{ANuy$c=25CiNqB)H|Xf2QV%d$2Qa61k9{y-b%Nf&J; zFWm&wPT67&|Di1pGT?*;U?r*b?C+zps(L;{Bk85XLbz7%;lHso6lESpgV&?HFKVGT!?LV#THW@jkA#4 zuhbUuLZuCtu{ZOG1^42}yH9@*@BB4Zm0-wQ!`jd6)3-Qz;md)9i!AZmmB5EALA@87 z;bB+?_p^UI^#Tuk9%ctD8Xmt#>0$Y2O761JiHwp8+p)%{grkZ^j_C0zJx6CdiyaQqwBfv!T_jk2r zB_RN{^7c+LtiB<-#sb~fPQEvToqd?eH(|rjB$Z(CgI=NhSOAqzoZl&ZV;U;0nyQYz zqKe@4!;K-_a!{zW_E(q~)HXoAr6bVqp&Kx_k}S#IBYURXGI2_- z%)QsaqZ7CEC$20cj93&t{Res4&T(X~>RXR=7<7w+XXUH1pAI8Q1^PhvNCI@}3Hm)O zHfo2|JhjcqSpgOT8asZ#PGRvkmL%}L&ZO=}2CH#35_`GFTHE4J+_Wa{{K1(4QVCCF zh4lTBQkxzeICF0~&@MJIftZZ=5toyA)yf;!fpvwj&1+75SD$`?ZSnizHWB4Z@z7AX zq!)CSF<z7Uo;UzBKp6aVFIQgy*^b41MgreKkDaoE{_li$|-_eEAO=3;aa#--Z8xW2& zUM@pyUa;#so*DeuKgdammCoD246uHl$T(vW0+l511vifwM66c{lcdj_|H8waq|Fb( z{gbIrtHx85g|==p{p;XZDwt_NEiz7xg0+58R6jQqe?t)QM X!vGkH5P)xhsehq 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­fR+#{clFA&3$g?ja*v#Q8eu^Y9C=}^Y#yO0 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 z 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 z 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

ym2sWhMQ5 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ïO_wcQLr5@lbkJ1$6atJ^n3g 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

<)%Yyd6`kfctFG>j^BlgF#tnT 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%0Ai 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

?Yv!FOFah+cSyt~kLbWrOVVX>x(Cj+#9? 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

4tw*8;zL<6_ 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 literal 0 HcmV?d00001 diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_MetallicRoughness.png b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_MetallicRoughness.png new file mode 100644 index 0000000000000000000000000000000000000000..efd20260218a92d097c4005a8167dcdf08180664 GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7#Nv>)VXbLJAo8Sx}&cn1H;CC?mvmFK)yn< zN02WALzNl>LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-Aum$*pxH5<^{Qv*o zVCTB|KoQ0yZ+92Q|4h2~fE@M`PhVH|hb-*uO5zb)HRk|@%sgEjLn>~)J;=xi Date: Tue, 8 Oct 2019 10:44:17 +0100 Subject: [PATCH 008/170] Offset nodes. --- .../glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf index b310af99f..622754961 100644 --- a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf +++ b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf @@ -116,7 +116,7 @@ "buffer" : 0, "byteLength" : 576, "byteOffset" : 936, - "target" : 349626 + "target" : 34962 }, { "buffer" : 0, @@ -195,11 +195,13 @@ }, { "mesh" : 1, - "name" : "CubeInside" + "name" : "CubeInside", + "translation": [ 2.0, 0.0, 0.0 ] }, { "mesh" : 2, - "name" : "Lines" + "name" : "Lines", + "translation": [ -2.0, 0.0, 0.0 ] } ], "samplers" : [ From 8498310fa0014ff8bc9d54e366ceffa293917b8a Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 8 Oct 2019 11:35:03 +0100 Subject: [PATCH 009/170] A gltf v2 which exercises all the options. --- .../MarbleCube/Cube.gltf | 117 +++++++++++++++--- 1 file changed, 103 insertions(+), 14 deletions(-) diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf index 622754961..9d0ddddda 100644 --- a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf +++ b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf @@ -85,9 +85,29 @@ "bufferView" : 1, "byteOffset" : 0, "componentType" : 5126, - "count" : 5, + "count" : 36, "type" : "VEC3" - } + }, + { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 35, + "type" : "VEC3" + }, + { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 35, + "max" : [ + 35 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + } ], "asset" : { "generator" : "VKTS glTF 2.0 exporter", @@ -158,22 +178,17 @@ "primitives" : [ { "attributes" : { - "NORMAL" : 2, - "POSITION" : 1, - "TANGENT" : 3, - "TEXCOORD_0" : 4 + "POSITION" : 1 }, - "indices" : 0, - "material" : 0, "mode" : 4 } ] }, { - "name" : "CubeInside", + "name" : "TruncatedCube", "primitives" : [ { "attributes" : { - "POSITION" : 5 + "POSITION" : 6 }, "mode" : 4 } ] @@ -186,6 +201,55 @@ }, "mode" : 1 } ] + }, + { + "name" : "TruncatedLines", + "primitives" : [ { + "attributes" : { + "POSITION" : 6 + }, + "mode" : 1 + } ] + }, + { + "name" : "IndexedCube", + "primitives" : [ { + "attributes" : { + "POSITION" : 1 + }, + "mode" : 4, + "indices" : 0 + } ] + }, + { + "name" : "TruncatedIndexedCube", + "primitives" : [ { + "attributes" : { + "POSITION" : 1 + }, + "mode" : 4, + "indices" : 7 + } ] + }, + { + "name" : "IndexedLines", + "primitives" : [ { + "attributes" : { + "POSITION" : 5 + }, + "mode" : 1, + "indices" : 0 + } ] + }, + { + "name" : "TruncatedIndexedLines", + "primitives" : [ { + "attributes" : { + "POSITION" : 6 + }, + "mode" : 1, + "indices" : 7 + } ] } ], "nodes" : [ @@ -195,13 +259,38 @@ }, { "mesh" : 1, - "name" : "CubeInside", - "translation": [ 2.0, 0.0, 0.0 ] + "name" : "TruncatedCube", + "translation": [ 2.5, 0.0, 2.5 ] }, { "mesh" : 2, "name" : "Lines", - "translation": [ -2.0, 0.0, 0.0 ] + "translation": [ 2.5, 0.0, 0.0 ] + }, + { + "mesh" : 3, + "name" : "TruncatedLines", + "translation": [ 2.5, 0.0, -2.5 ] + }, + { + "mesh" : 4, + "name" : "IndexedCube", + "translation": [ -2.5, 0.0, 2.5 ] + }, + { + "mesh" : 5, + "name" : "TruncatedIndexedCube", + "translation": [ -2.5, 0.0, 0.0 ] + }, + { + "mesh" : 6, + "name" : "IndexedLines", + "translation": [ -2.5, 0.0, -2.5 ] + }, + { + "mesh" : 7, + "name" : "TruncatedIndexedLines", + "translation": [ 0.0, 0.0, -2.5 ] } ], "samplers" : [ @@ -211,7 +300,7 @@ "scenes" : [ { "nodes" : [ - 0, 1, 2 + 0, 1, 2, 3, 4, 5, 6, 7 ] } ], From ce4cb393028b40f712074d7c53930f477782bf96 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 8 Oct 2019 11:46:07 +0100 Subject: [PATCH 010/170] Make example minimal. --- .../IncorrectVertexArrays/MarbleCube/Cube.bin | Bin 1848 -> 514 bytes .../MarbleCube/Cube.gltf | 23 +----------------- .../MarbleCube/Cube_BaseColor.png | Bin 891995 -> 0 bytes .../MarbleCube/Cube_MetallicRoughness.png | Bin 319 -> 0 bytes 4 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_BaseColor.png delete mode 100644 test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_MetallicRoughness.png diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.bin b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.bin index 98a0dccbff0044f7f3998ef5136d13dccebcc78e..fa55b363a388c66673da35b547ab3a122e0a1d88 100644 GIT binary patch delta 7 OcmdnN*Tk}ci3tD-69NGM literal 1848 zcmcIhNm2tb3~bhfJ?uMSc>~4KPs1mEMde960o1bP(HKuA2XNJtrCwx71FT^k8`#7a zwlTpJJJ`h@_Hlqi9ASoIoZu8^IL8GpafNH#;1+kd#{=eg#1o$J0w4zY7Vc&|n16l0 zQy-?ur?FtB4=yfPuD7VX z5;xB7(7;Sr-&u>8Jo4)#7>G%Uo;*)0E?9JY6|29(Y9D7Rx`9{}dQ`h49^+}%_pJtJ ztm4FfzJ0u!_IJE&FD%Cze>GQcU$UQ-ayL_&Cjr_QXO3N-qSS9sYj0%%=P7=}q*l+< z$WuPOoN{3rA0>M_$hOJn7%7R^J}WQ%x1NlH0L;*{yi&^u+DhF1??e_j=B}p4VEj^Yl2u?KE-Wt!B}2w)_<= P_uQ+IN#7qKpQrc-3^+Dk diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf index 9d0ddddda..51424e938 100644 --- a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf +++ b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.gltf @@ -147,31 +147,10 @@ ], "buffers" : [ { - "byteLength" : 1848, + "byteLength" : 514, "uri" : "Cube.bin" } ], - "images" : [ - { - "uri" : "Cube_BaseColor.png" - }, - { - "uri" : "Cube_MetallicRoughness.png" - } - ], - "materials" : [ - { - "name" : "Cube", - "pbrMetallicRoughness" : { - "baseColorTexture" : { - "index" : 0 - }, - "metallicRoughnessTexture" : { - "index" : 1 - } - } - } - ], "meshes" : [ { "name" : "Cube", diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_BaseColor.png b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_BaseColor.png deleted file mode 100644 index 5e5cb2068fa85aec944bd75c981fa6420c1cea87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 891995 zcmWifeO!zC|HrSJ-BjCJNo}=hh>B9{Mvc;zD4e8oj+3ENS9CK@M{}1b?Yc_kCU=LJ zM05DYAzbK?bD~Srjf&=Q7&_WSxk)YE*KU5-@2~bpk6pX2>wWinzF(hxu`y9B8y6b@ z09Z?xEcyWeAo3#wSkcHogIUkV0an@crHjH>W+kkz$z0cBu`p|$l}fF%@|49N_s0W_ zqm2&@{hhxQDiqFKt#&n6y80DYYBr@Ioga|V@lSM^6B3|qTv5)Ij%m3GVY}K4MHm*Y zJb4m3_*I}@p_(7(6hupHurSNTmZVWjUx-=}6jZ3FH4FD1u=Y2On@;M*cK3JpmtqCS zPGTpEO0a@c1=#7+JlXK7LUD1W>g6p9lSe!!VlLua=_72?dTUM+IYg-mMW1Y0d|cc*QNiBUOQobTt1H4%@W z)EmstR?(b-oM>ULu7zT;Stz%`{p5hjTwZWg|FXM{Y2n`G<{C}Rs)68q^oXartyav< z-EFBiO!>&(&cl+Ln++2q!89K*frjY(jic;s9C|?P)@Lp@{6OgIMEUXnP{BtI# z-$EELJ%lH`AVu|7#SEGgt*cgng~81?2K;g?%)!HeSlxEL);VkEDQ9yIJ<=&4Ks~Uk z%~>>0%S}$6jOFIis{|jdXhDT-9b$hgoZ)Yr7%9;^Xb!FN6$?WZ{l8&{57T94kHQs1 z)`zb3X?E`?AxBolA$Iof)@4nYL*Nhx2JE2O-Jvih>pFGGqxDS>39z`kue>%u-akOz z!Eh0Fs-!^Q`8S(s$<1Al=#UhhUQcbHI;cAY7PQyWVqko{){!U%Uqut!8kogfH>nPo z{X%yQ9o3KA@nyCf^O#1-Ev3b>ew0zHC*vp}bm#c-@Sj#64PW@fUj0a;g}M7ym+->> z3g8I67#5d{G;c?k(foL(x56UKp;TPWkc_lf?>?q~zHfl}+YghN?z`47o4;*gR)+GK zAR9gzkLlBo-rlqkmOXPJ1H&e z+s9ez9ms2ar!Gm?)tQEj4jsTwIdF>z@^PFFu0_%gBs`D z)EP+pfP9OvW^DAVzOP(NgsR&N0xmnAkkda{#L=zH+WWa+MOa+n4x;Aqut0fzPl2-; zdTca&2!YiZs@hlR*vU`gSYKatn=g^mQctadrIFBprSYY}ISd}CzM$g5ZW^;dECvUR ziO6dmts*-W85=o+l^kQsf`#`$^)a?G5`FN*Fw_`D^GOXtO5v^mT8v6i8;}E@II6mt zUviWh@1qzSJ_^3~-BclFCZb71!)%K8mA634`rN_}u_8b&_lKW7Q55z`;KX~m*51L+ z&XXsvBx{xlXgw|YTM zGl(t2Y&&gbNh( z7X|Ue&BMpSV~?NIPn>QeZWb_Aq#5c0Atu`!R?@b$jA#PqbN~=6SR*ijV>nmrrZr*HWrK{ErbtvQuP3&kLQTD*# z@X;zR&YhNuG>n49Ihjag3iSo0c3QfO=-Xx@WTbRPG?4VYRSvZD|7q9O?7P?xA$o$*$Ytb?237KHrL0-OC85^EKHM$>RUcILFR zGFFK?QUcTyZGGt3E@ZTk)@l^5=4#QBc^*QCfc)m*&cu-gsXI^1#O1Cw$Wf zn!8V|!4Gi5oTdFaaHNRC5yQdw^sJ#S2lYsKx$~Y;D)+vE9+Zrh2s#zW`EE8(J<>rm z(1mz4$^xAbw>=J0A!<{eD8_oBxM=U*feI;{apHk@;~!n~?hERzh9hLQpE3Bqd=Cx*N`< z#KjSkBrtNkwvSkrf1n5xOpYU(yFG9sg%YdlOku$#+?=;&JAo(B;)coImd8uzz?=^{esqeZHiK229Rk&9 zOy57?g&%GB#`(xbJ~TdVGq9zzg|{|?JVq_ys9h!J0}OF&r$LOL8)AFf79YzXBEd`R z^wgmDlB6+?^pgont!XO{^SAm2@K#C0H*ai#d07hXj71N*LFwAZ$hvh<@eX9BZMx7O z^jZ-c{t!$*Vls^t>7SnWU>e21qx%7jxb0=ohfkW>UNoEs9%5&7<(uxUL;7~3e(2P!Q}=dc`86G2M{OlcEpV(|1) z%u$NSZ}fw2bVOl@kZlAjx)X_pW&!f5pMCsEI4c+FgT8d0hLRA5xK1$Ak65UML*l|j z$*t9>jbsW78DMIgz={<}me~aNpa5@Exj84zj#fHS-Y-yxAa3~w_c5eh=r=FCAF8}y zhC27yE5o>0$|FT=6iu3Hw6MKH!t3V?f4%`e>wcM0OFj~>>JDN{iG%cL4n63z8Rl)! zZELY=J<@6<3a13%$J7mmB1h>abdN~#>so|kD~%Bfw?H9t6P=awM!A$~k#n^u3v)DN zAmihWQ>_LEu8WUEhFmImG|JIxDGehn-5Fe0aTbl~W=os$^Ut(doBftFQn@3w*ul8i zUB<>iw)Bw+&b*nM-;xp=2Fz_YLm@vWDt3cGg}Fi@+Dt{t`VCwCa=?Ol0>Oo(agG)n z8$OF2US+3rHTwe--%0vAh(jms)Wcu@=Dz>%!MRtQ(?oc9H`}@PP^14Qp1io2!Gs7~ z7kn03Ql6*{9Ii*P*x6Z$CDk?CL??=K1JHjue37@NagzspX^RoAjOuOQO~@@zelAoY ziL~#(pN7;of!l&Lq^ePEDP(co`IW>?rZhOmY&;#lM9FJkvK}a`-+_cdV+T%ArQLpc zJy6{94l(xZ>BX1VohfMV`lM8-D-oePDGN_wL+lB0?8HET=I0(Fbf_Gow%pgp z1GaNQAQW5Z|GR2wWkwUUV9#eaZ@|2obRu%5mj`|y2#PhsA*D>h_P?S&U8E>Pct)|? zLY4NKsX@Q(M7RF|zz%rs7?`fy0zG>p=qe|k@bOCUc3KDg<>U2^`vJnV#y!D6#6G=P zV^1bBI6SzTn+s<9^bnLbW_k(SSpu$<1i)^Sp07=TQ=jw^uJ75%g9b_^UyIt;(KbGS z16r>qDxA&0oKD9{Nx-;L&l9c>%N{Pq?4{1%r!Xq_h<76h80mRw%Q_&n z)FK%%(Qk`t;jiz3)aM<<{xXxmb2|3QN&0;Nbj-(7Qk!FHHS~Yw(89n>TI_o0c>h~) z?FbRZz+bYxD>3RM2F_s=Z_qW-+;EP`k-L{T;f>FI(g61S3%OYY_~wV!$qFEH1_Pg- zZ0s)ykN$zF4d_Hh**$XxV8+KpVp*RD{%6C)VV1HQo0EYg^}A@704D~SJ(g+C+~+Ou z-7z{ojeyekn1JET`yj(T#s}%MzQlgsK_4oT6ijkhau(FCr4^1uA-+AGCwDMa4X;nG zAR4Ujlf!y-TH(pIL{h}^Y;)p?1}ct^_4Bk`AnrEt*CA{ySY~)9P>=Wu$YEihk%zy3 z52ey(t+qzGx>H97snSu1w|V+HNEZ#e+(0N!F&2!2Mn_zwZ6U@eqzrSPZ^lpe6T&c3|&$sdMDNJkYg*#8swWywQXgG&f zQBcbihqL@#k@dFHEOghrm)8^0MuEyQEvBBH(@uOp6RDv8iKJY3$kpDhc20d<+J>b6 zug%c+CKy?7Bicy0V99eiN))~*VhhmoLT~1pWj4%rTW&JRXx?J2T&+Y4LNEQ61de~` zF2BySNLX`_`P8AaO3ZP5Ez-BdPCK1;XuF>fGBvWioBH1V^?2%RpGUxN78;Wmt468Z z?sS4kro>g2zg<8-QB%x}m+bB#BK`1kM$ZSb94EIjr`JKuGRf9Nm>0=s@|kt-781fV z1o%)uzE}I>MI!88a_kDOXqYfKJpVhHHg}yfc76p>$KqO42>=hrz70P3uCQ^10OM_# zziT6NVd(G74(#e!9}!4z4j~l+Wb0#uhSy0^$1Zx|cbsd&9NM8R{b2SR3+lF1fG+4v z%SZ??(hu3)0J7~nuo4HlhZp|Ry5}CC{_2ZgG_ti#Wa)3P0EZ$?^n-PPmyKqxwVOP- z$dP-kop^e*mZ%wowGrd&=qVQL;OKSY`x_R5)*?pkK6o(3Q5I%7lc_6H(x<@hFsQJkuoOd}zLhug3c=MWJ~2r*uewGKv*KX)AH*}TQDg&bzhMc~SCKWKo#z*Usg<*MDp zG9K5gs$+BQnM9tI)^{B>b0u05fVYn_dr-r-TkuzU=4`a&{mDLJOP?6$*lhEa1s2$A zzfS@W*&5C4%QdLuZ2X5bXu?5yD&Jn;hh_l0ujvx;ZhBBxF8Hqv zV?U5RPBidvZ*nZ#Gj9x~2IGFF{tv(C@TX#A4KO^q8a@9rQOA6~)<|z1@g@u=s>|P$ zAoJ*AG-ZnX!d_>sCjtfenBf-tI47OV1OIIuHSU`L{q*74=^ez=M;(N#h)m?>2ZrH) z>4hgV%7Lg%5qET_$k}`Y3h`#D?4`PofG}Q(eH!+VFX`fG`dSIvfG@KCtOK|9hnw#R zn!Q-nYFt>R#GJK=nawvPQ5(oU@|(%P(CAoK?G>V*&$ji2 zK|DTDNEMbFDVdV$(E?(K#)}opwlSYCeMdi(z8eT~L1Bm~c$>SvdRM1=er4s1d;mYM zrZ5F@DjpUQM69vV%4wN4wdV0=qOtA?z`qFHevE#C18b~oG7w|_>;;HT8Ukm=D4@>r z1N#n>s;sB=ozWj1i*oJ1Or__PVwTSx+jdNzN{IKA@t>YZqTNIsv0)nfUjDcU#m zpbHZ9{c<$IUyP+1z@o}rW8viK(L^NMO)jHp!>Al-2gaHj`+=aeE-IFYw*u;qbh#DD z^Li{6lXXlENw(9n#>N(?2Rv3dpA~1f$T`Z@o8H#c%X{mnNK(UN)ioOb+dE3kEx=*4 zXq7Lf-mgj$AuITz-Te%uwH7;N_uf`>3E(_a7`8Dk)wi(tC&uCQ(%N0)wC9`Fk6KPT zh>DqIG|+Jg!TdJ-^%tEdER4Vxx=6_B>lIm{lD5a{DV4-(^s1?ks2ljQDt5&&fi{93 z^ctn=GmvTH0xe`3?+=k*8fWBJS4|d9gD#TQGiX>*NwnIe&xNB(r09?C=|pudE4}0! zV+-85`Un_^)A*KT9W>0B{AgQ__FubvnaO|sGU?-&@&@FWj22)&J5%RL3&9t&U7n8F z^8cCSV4r&A$0O@U2OI*ETUceOpzR+JZ@t2jS7?Vtj1dh2hUYE#zo9AGW5ECDw#awm zb8w-Bm43lm4zFz@%33Ji{JYqK8Sbi(@E;TV#P_L(3Q0f%2faZ5wG*D%ENuU4_u=p* zd?{k4Rs`#CzW|}bEr|Ei|KCJUD45+uoMp0B9=}@3Wglovq!D?)cIRK&&a=VZd(4HOM!5?6-WLY60NlD zvCrSdX(h6b(SpKOhdOF^pQ9Lx_ zBSAAMV%M{^KbqO;8iUndAbUqKanw;KbCE0ieTB=>Z(_|NWY;*mHz|x7WOl|1j!(ty zjJ7Ty6y!9z2R;8iar9m-@$`yVWwi9p#OrDNrBKjoCAL6SP7JC^a3F-TyH#gheZ_bY z!+UKm%*aO89@huRFJRWvqYQvoZ^6zx)uL|Es-wX=k}s}8!t|7`?_-^Zc+#p|=+Jy4 zwc=Pgkr3o7pB=*#{nTi+4d%$!*+_lR3ceZQg{h|f%O++W7Z5g+0-L|tib~;)e3NCO z04uQ;EpHq@iIL^2$%_8~9@1c)Z<#8acWuEsd5FCF6i2J19`pt$rZIK2NkXy0WHtp|#pfee<9t=^WReCjek%jd?s+$3n?V5N*;zfIZFlvDrt<(GB zKN@()EgizpdzLc&EcvLp*HpxOdF|&E(bit?to@SjmSfnlRmI@*r#me!A`?BjmQOUa zu0qmm0hZJS~@JNhH>hp$dP#zEL)0eEA3PWb zJbO+@)MZn&Sw|_Emy}qFMU1>&MTuEzrWXc#$ttHv!TgIIXv9^Le}bj%W9-s8GD4-N zc5)>@#+G9#To2iEjuwG!$ABm%=C+;qbR#1XJ(!D}|2{I(R@ryozv zf+t&~r!RRghGkp}S&8~#tv~&-FU%u|yZl(M3w)}CnM93PoKK4>4< zXjQg~X8XoMb-Gqe)OC5to5mQzt$twk=4irZ{AEV0@97e~>B=4Ei0cAqC9ckxsab`+3U)t`of;;Eu)OG3`*Q(Ngv!@6XuWZDpg>csT*Vc^Vc!B{lsmGJjPD6 z$hK9Z(g%d;YDP%1>%%OYu5;*4i9K?Zc0JLK?vBK${-zYvqw0NP^xoADV%pa}W;?NP z72r7nD&5bD>9*4#FW5&H%agtBcawkY5oqpNBj3#4y+C%!_4zY;1xM3F zVavI_bX-5`B=R5lHpHVPO+!{3JjD>b9u$aXlDlt?@^&u3Tc8L-3&+r{4~bc`Q#FHj z__Rh^&rg0}k?9oX_*~(R=&gFr2vL_xRRu%ySd5*wF&cj-To(v$LD?&fs!zV|NIuEb zY=G>&mInhiss!B%l4w}-&rPDlgqUbS*UVt{s8}*^kys}0yOvMXePOHBjcw@HbG6JJ z84Hp%!5YeN^(*w3sA{ypR_m7MT6qn`m~_&Zobo@^__B4%vW3wzUB7uSz1a zukCu@)E`%?0&NHT5)l?ub~Xi=Tk4#vfMO1V1Ks5UVyCVH3C?#pdAM&uO7-?WR~+F` zuKi(;*iE7Y#h`AK9@Sg{0T~5y{*aig`fhR&r>qUT_nk&#%+Qq{^X)+IW$3JQV&w4Y zGmPgwX{o?Zm6esM?Q@7!ZmfWT|4y?tgNz^@f0mGy?{Y|t=^JhNGz)un7Peu^%Dp#% z0S6CFM@`*AqM=rZr;S)wb_Z*Ia7Q90yo3jD-prfNt94EQvZDoIxwPxA^bWvq_1hZi zlMH}2LeO9aKGHz-t_lB9pxV4D2+8pi!Y_FysOwkNYSjjZNaU~)CRY@k3$9X~f;#sm znlG!Aj9~vv_LXh467|_`^vtVJhJjwesmT2I;30P*#G}=QkI}W#F$#b47~SPA7~_Tg z!?@Hv+FMU2D^ms>HD1k~v3Qa51U5MNM|?MEBjrw zLh9A^qqdXRQ@col4#U#l`~Z(>&ehnLGu-gbGD6q|UdtFCqz4W@VaLCj_E0r-mUTkQ zG$#M?2Y9%5@l5K21^@XHM{fx_upc=DJ_+iwj1Y7E+7d%yA5#+T$=9u5)FiPm2Z#al zD&iiD38Ymfu#lAE>6DnW;DB0S*!!78k`95*^^oh&U{`{n%2EEf-d8iuoo4vhnyr&L zdI^2|ffj$KOx-Rg-L@ACbZfkRa$K$ZYi6v%SyaS|wo{-R3hk?IQ)I;=;jd?EbN1=! z_-1y`6Mw^&{Mj3kiwsc#utrSO)8nsv8=jNp=~@-{8J0gRar}5cn=SCO%KK*~8}DZ@ z*_p`OQF^gMW`ZuzN7$AZc_KF#j0pz3ezDbgiewkQaBznQpm#)XXbnAmz(~EA;fg#P zW8*Os#!oC*p2yJIjkip-<=elyztb!Kx6;{JmrtIIDkf*Fg8(cXKr6Cpfsh!8Fz9L5 z;8D2sN7aUV7H`#|CV^oMfc)7^G})BW){~L1p`zzsMicfCwuq^o%AZNSnn>2mx>V?| z)iGgOveH8rDEgu5xc7qmstcZ)?JDany4L~7+fGEEgv9I{{uKdz zQrCk|=Hys__$3tnH4~%foDpV~L)m|mIyy;5b&76nRV|)P*wKdN3b^RgSa`uq;iNHi z4xT~05RerISo7;cW)HYon7@llB>4wv>|EqAbWw7@-jt?$Hz$VXJkJ@?+mx=LpV+Tj zHd%RU6uXyqm|!+C`C(nquvkzA~gEYaWhuILKi$1sCMQe)0&{mRp`C~YG9d7`crID>#A7lLmU2WBmMIS^u&DA zIy*}0xImTQk4unbXwH#Nin}dBwM~~9AkLh;E`<`^rw`WfH97xfsLoi>S??U=_7`Tz zv9ilIU0~VOx(p;sh@Rj<0j+Cw29At-dWvZL0X!(?;f{}3tq(iUImwZTp0#l-|Ac#9 z;g}_F(j@tkz3ggvQGa)0;RwlddGfczUr7X;HBLXd3X8(Jg+ndT$<$t zM*SIn;Jp&vdZkX6K(vXEEIz+(`a)tBHFibWQ9UeQgdRLufF0P!h~J#=)JPf|hS^9K z`eFpFh?Z>qM>RBGwO{Wce{zZ~wK7xYT!I_?==ixoC(*8YxU4UYQZPk6zmtvsFu~w| zbDCsN@j0843KYCbM9vo%z&8z?>KRADz%%t$(E`=tnnd)|cnJQ|w)FRR@S!D507rHc z=EV|@AX8O1jUoIsf7j!3bc$7wPDZM9uDr^+x)9*T6caW!p={Q3`kHF`Mm*oCJuh;X z~nXvzjh%2kDIc?wN_=>&H4B<3JZFw#z}RSiX0&@BpV14gg1vy=MW zf}S-8>n;^dm2Vtm$8HF}Wiq#OK~d|D2Z8+o$0&>W&K> zvaEQbGZ3GZN-L}vXk-G}`$^J$3^-~#1$(w2ns`eKk*~CoRsk*Px+C-P2d8%%Lt3@O1tTQitk+E4*t=3$5$k?>RA8KhWmyo2q;cU%uCQdrL z4uaQ`fU7aIl7qw(H?}-{OrUa!(^VN5I%unVY$GWBegJxAFPrh3o0~s<% zX@@j&v^$e2C+ZW!6e(E)!*2Q2Ld|1hu))fkp@4b(9j;=~2caA~GB6+vg)`eppW-ZE zYW$#8afasIF3ql~-y`dfP^A?)w8OsvQ72Jwn5VQo6~6Tm5onmAwWgFLMH5fS(E7s$ z>1UOFTTk)bm;xVqy%~79%tVhf7n9C1xTk%|UaX>=T!+rj7NF05p6Zv0XagWMd|XkD z4Y^&q#g0E=8$Uwn(LQVhq5$;3jcWA3S(LR(*KQ;4x5p8RqehHU^MrWG2(RiNny9;< z{@xS$KrO8`!aWPg*zUQmx*OuI3mp@0GHlF=l(*;wa8peiF_vnJ5c#u%;*i7935!d^ znObN)uPB$IQT5w1;S&0k!WmOmKMe#a}{bnt0wt zm1kDdkgw(|k+PGiz#h+V(v=C>@?@yW#x%i>{lMt?8CaV}+WUa(74MP4L6Jm#T&2Ih zf*8BbA(9p*=;~a8RP$;v%<@4UMT^DitfDWdn)NJFsIa9+Nq>S)KrpR8V@B9L%oUkF zPG>ffi=_Q@?UF2ZF%pL;^SWM;+pE?cNCqP?%E(dTTShTLGbyr6UVz!>~ug}76A?MaJwY1q?h=i%U6?8j;fWaKbW8{_U#T; zIqA<>mP(3RShT|WGl&+x%EAu3l#~E&vX2aHY8RCH+E-P-lVCmu`E$msF2-sUc{mCdn_>9e)(SEju#>JK)|CAP0E1>19V8$L{oXq-Bi{TEoF~JQ&_)QN;c| zB9?s!lfMTipCq<@<7lOzV{$z4)KT+rFj2>y!4tYFFsBb_=33xcw?HEd#=orx4n<=x ze!=rx>Lm(n7gmd%4*MZdZ^uGkheWd7|s#>Bt$6)YNtE1Y8D^C<4 zBh}j4nkL?{Lnkzb=zd?bNoOaLOC7ZMsHv9&(}RVn5;r-q>@>_hsjB~rT-(na5R=K$ z^VBc^7R7~cRa-FDFUZDGF#Y&e;JQey3X~)X9Ton|ti)KCGE}sw!dxx3fS((Cj#bI+ zxMyhwKF_=Xa}sX`V3}3`Cm-a!B|&;~hRU*sau;3As}7)R|4sp&PLQhfA2xET@iFW3 z7`$o~+>%$TI8{cdFlr9= zsa#O~7hjvS4*I$gT%H0&)oIaj1-JtSqiV2$LCI;fpPk<9ht6(jT#*nEs<3Xh5D5XX zhf&p3{N@-dp|Kv=cm!qygSuW{&1)}BsW7%PGIC9E_@1?Uz`)lAhH{lCOVYVHo~XzA zoWp>Z=X0pne1SO+jp|WHX)3tN32d1Z8_^wbsU5yed5HazEMYB8MIugF2d=RyZt*3~ z&Lg2?Bh;!^SaJ|xxd3xnF2<%zj_vLe$agz9kjqi{&@QxMhY~wQdduR%sJ&BnP4u$z zAvx=aXSp3|ApF71^6oe#`K1osg+`oYTCkDqT22kN(_#3loypsbjVTO$dx^~YlrLAw((gLJW>6_ z2AkK`qyw%UzOq^~eV1;T;+F`wLUq(3e;L%ts`;BL+TIGeyrNb-P!JpLTU0}fC1TX2 zMm7H1zEk!!T?GYH(QoAOiuKU7od~dk4o1Dgwo}UO*y5CPFxj|ZUYc$ z`4a320!0f*SEuo$brscSr3x;(gYL>gOSmEUZ?vE#nBxrj-_zt+lR{H7761Jm<+g;1 zIXcsWJYONq;jn#VDdwLg~p@DJtM(@}PrfbP^wWP!hSLdyft z7cu01@YFnP&XYUDi+REL;?bcmYjyHza+yPD3DFE(u6ac~^C9A9$d!&&t`e*2tr+!V zkPkA`ru0CzO?;x^-3JEkr=Nb+O&>4U)z4PVS*fz=_m%w&$v?V2f7?kN_6`F%Zn z+S~cnsro6fSol`5wvU1_0%}cY`VH8fO^XdTv9;fgj`5xgAs-t2H5QnY2i>l*z)^>l z=)L!cuVZhT(4>d9m07FNtvmTDGbme0t-8+AZs`U#9a|5w^?4_*gR2(6-43tNdr5JK z^p=S>*9T?Xk+A+&5NF(pg-7Vz@@Px=T6b)19_kj+hdK5t5I0-xb_AH)D0=Wr)0v)#m)nJ$WuDar9VlhAYbX?i=cIQsqb|Ag9SriU(`2pwtjN zR!__1>&Lz{_=16w^g9m zeAVB%KzC{Q--VLw^OA`AR@HVcvG6pbx~YdFpMAtp)MotpWd*`>sy+s47WTIMVt@P_eR-N8KXNIy zc24-4LhQqI+10QRy!}1rLu%GYZvg&%tL@p1$@CyAOa3>pP>~<^0H$9-dCutHMd)VA zM!*KR==}=ouVbBcT~CQ|zL%T@wokA8{X!iuyU+sj{+L>8q+QEjM>}-WOzGO1imcCP zY5%c6>4OTI?ZJS&%nTqTzqpJ@`CWmPSgs!?hLY2nBfX*E^j2c{31Rx1 z*bt)oZEfs)AZF+$`r#o_$4bCs#GegbOy*^m3dK)H;-!n5AUAr42yZm;Z z>|r6RDwiQmg-@=4I7iK?qs-#QJH*vozGMUk)#a>}r}AA?D%-}y*xl5!T3w4NIGUiBYO_5Bo$#Ou;U+xXnafK7*j z_~TuM;(i`4Q&m5#`qQVF_(TecLb2>WI=*DxC}ZUS&y!~J<0jolf}yMXPUCqRkS7hS zP`wFXYf^wO=c2ct=e;YL=iYQt&yh*3mD2D7!IFrQ>t`X(B4F)7zG`fa&S)k3(04sU zO!|Jja#D3Q!IzFuuPV)O+0t>_b_>&G*BI?WEx2}RJkhGQj+PS}91NkYwdH;2obM3d z$yGn_L`-UXKa)B5l8Amp=^e|@v@*iJPVhA@^_mB;iAy__Odetc0=(Sh)K9B)@;P)o zg|g<47Ur5i7*%9|Y#n2J4~D@GZ5arAzys${)>Km0$Vd8uJ(J+|%1 z|4iL&mbEVD#R?t%CQ%pbP8aUT?-GVD2rnd46To%jw&^;de_kdF*fAY2J)o^Q#j2!8 z=Iqqi`I8I0hpg5n1xjVhD`4rToRqBou32)cwLs0dYhcGXM>^II@E9srE=PXFMfUNq zwWzWcsyazkf~T;OIu9NGF_E<2$ac^}@FdvfavF54*F+uc+kyPj>mjTRzt=BTjV+ID zpj{iJUtO2dy$JCt_;_ryel4nBImdcDL0~0Qo&f&$GFCvlpl8>YR1&mg@r5QJNYr`P)H9d5H6+ z@2N2a;q=uPnQ8eFBBKV#6++o1*74V9_ALdFZEPn-b+qxXzOhEHBNm?Ym1&$cUw}Di z9TZml-_3CQ3Ak)6d^_3#aK8707+W+#kw*w8Yx{5_@(VvOo$-1)iJ9b*ty{@VwUh0j z$j+5m$+yv~mJF~x&jZ`h$Z3*-*)qRpCk~!|u=Sm4*5wF~6#+7k1KfuTS>*AE!SR2| z?*DFC?6lS<=yep>bCvXf^bjwEA;LLi?!M<;nmTIT?qTY7kbfNG$-gjhduBYMe)x#` z)~C^S&8XFD4`xEKb^8F*do&mBuALV?@gm&ORX(G@zUm-dxq^t20*sl{bgl}GW}a-( zJ25VVzfLIF@t|2}UZ5+bAm3<*Trih=D*cYspj?{9Fp;5)_jS-j$013h4%(0`ApYYR zSJcOLDS(Gm2bnDH;NYL=FG(Vlu}2a{AATj-dY<@xzoj@@=Q@>l$(~&)B;8|2?E}Ap z-WrjV$|W8A*cCQ<&r^4oIn}ZiF6zS=aU{nKBO7)uq%I-%!Q@FPmtY0=ZEX&Xui8hpnQoC0niyN(63IHdcL`jJd_XDGSm{WsI z)L%KY7*1Y=qlD$9iCnKKRhARymZtjX0(FU+1eqpmw{Fb7R&tC^3@ky%!%N&Q^;^v^ zrv%=kzMcZDnL5FihUbm8s-AjkdZ!|%6TIdN{JMfsygmpS&9_-alcga-!L567ahaztxQGcS+5D9mJaD?4Ku~~QM*)9W^l>zs#;5pQv9;#**s^+Lk(}s?znih&&!5pQD!=&mTt)(eoR5X@0 z4fqPqd1qv7d=Go2kd2oA9Q^+=HJ9YZKSR7Z#8YZ4eULP*H`_3yG`F`H-X$X@FrgOo z{^jmG$tR0g{f2XW>fajlyj?B2T|l0%M4#xhhI?4@=3|HTJUPqG^J@N+Yv7cpbvC8T zz}vRI@%J01+J?RXs<@{el&N>oU;dD^ybMpHk%tJKJv)rRIPW-p>iJj1+#iXY>dk6f zTGFiVb@Ry#l}(q=VPifn#yj6INB977P77I!X89 z47;ryIL#tTjuX?~3W)DX+5j=N&E^(}G@lI9!Uv99&?~X4vCLfRaBldV|B;?!aHXAv zGG!cG12S9R*P_caH>sj>(KWX%&JVgBjqvqY>emC*O`qY+gA%$DI1pKQSVaw16$Gjr zUt1*fGdW=9!>OcYK5k>4%hX~bZ%WnpltA(&Df?Gj;38@5J(^FXejP9+u%A_ZS?SDe zQiQ(|ah)G{Y42i;JyJ})JrQ+mNYwmpqZ$5RUmtc4&>3306~xtfglUNQb$T>8;Dc3i zrgFo5;0`Va8QgCa+)cUd}_<4%HcF=vvLFZO_bpfD>ne;_fG6zsw_Pqf@GG_Da{-#k6QE1$y3# zI8FdAzjsrd_KVSjKANBt3Pt#Vh35P_A21i80DBW}h8h3sCYGVF6yI`Sudrt4@L7HH zK^|c*(Iv&I7Q7(}Uq&HW#!=h%@ORlkND_4!UPJ6Ju-4*ZP;r#K?)SC~V!u_@EtIYO zGH#vD-3zSh&!yjPCH;6-!MJ>sx+WM%mzimCgaUmQs(5Pwd_(__qH~XHvH$=0b=Y>b z*0z#b=Mai?(ov;t4&_+6kt8+8hSZQOrLJp}kizYh6xYr7RyShUtq@%aIdr(lO>(*t zH7TvqxwhZ+`@g^TX#2cBulMuy{0w*7%4J5f=@iGk1xvO;TdT#(IMX9V_bo;D{ez%Y z6KUYw$H#kfUf>pU<*7`zGXIK|_Lwa-p68x}@*bN&5nCTAz8ZA}Jy;KvoRc&IC1{-T z_Z7^6jc;F!HQYK%~7G7$>t#9$pymJvH~-+(M&K4pE}4t;!8Fu z^c{G~=6EAK^N1e%ur344(uuzR458ke;fC3W->P9g4bZasujHXahF)=LWBm@SbsnLt ziIPN(F@%4f%4(*dmrk2?4+OrqPwI(!pqur5OwHg|!cv7ce&`CZyT1eT7^ zVMYS!^j2VO1X=B-Wvb6uH2RJ3;?q8-Y70R1&n(M4)@t;@Hfj-%sxy`>`UZ8b+`I|( zBGA;FOcZejovla>SD-rX3`TeS=9Go^SgUT**Jxb)b4z2Ri1Sl~q>gPEG>UI5M_Tnl z!ti&1>@in8rPt9t5jB@8LL;C~I|)>~2Y$Cm1-yetfx5Y#V8~@1+WJb|TZjMqohYw| z;!$Pm{uHdiDpq_+fxj>)U(PPGFnvS9E;!_}3d(r|7EO(LkcwPWiUVBG1`8s%I*}UB zl{z9)%)?j4Xmca$@y_!Z;+^;whGaFtu<2)-ef>yu)_%cKz6(?#oUQIU*8G{p-JBUu z8t;lf*kW7@Dtb7UGB9^^pPfF)@V7Vwmzn)^lnq+T8!d}p@uSx~W?l0WHK6v`eP*PX zLtm=mg+R+;_*<}~{!f~&ey~@6091c6K6z9ecN^ugq1}Jz;1D03J2=2bBLZ$I>P`-G zqGNk3%b#)7V@D9bTYwddl`~24wl59j&GN*|>9GHpbtI-t-htLR(nX_n8F2r__oxou zJuJFZhzENYd-mG;aSg773xOgZQJX;^oG`5w`1QSo_3N~JNHeAC->apT78uuwu&V7ii|zgitve*|@0lh$X`NU79^*W~I2&f6wzuw=CW6jWsAsOK z<4nWsv2(s2#aE>6sJR9+7b{u^#cfa05Ie&sFJ6E_qlY@}J>}|ofP8c9Hj0;7ct6>r zASi|B_kBw}@cAC6rW6l$aB%+LGP>?~wT+QWjUm^CL+}xreydEwE&1fL|9mCQL+rdW zB95ot(-SNGt_V&Sb5@^i8289p)a!(Ij*llkXBo>r?>CD~IS96;??-!$9uZ4)eTeK8 zQ}(RKO@$al&97m6wi&jUTTuckW?6V9ry%wFCgv~OF{5b2Aev(MAL2LuiI~YMFv}H- z7J+_~`@pndB6hQn_Ry9i#9fF?pi2wP8NadYS~M#b5X^x~y8zB~3C3#QP5!>zOy2V@v03Eq13-|ldMF7j!kRE z>(K`y^5m3}*s0n>8TkAhA-by+BK~smku+DaY{ctW_pIMsj05{`eFoZq8(+%n0W0v> zu@iKC+x8h`bJ`r>b$NiRNF5lFj=L?_b{|YSojfmYQlqF#tIa*)8hv@Vs=G)c5d+Lk*1O31he26lwxg6co*)l^60pfb#7%`ihqh zw_ITRJpui*6lO`o4l;4m9@1PCJ_@htok9E_5tNIJ$}HH8l1-4gR){WNfWy~CyAI-p zT$=M4*zP+Eg=oDzZ{v$r9@3t=Q|2j?f zioEGijUj(O^H}iw#mutz0iG(LXu62wEuL*kRz~Abt&4BzIW|FUV84ps3MnT*y7z~# z?6-k>kHrct=$i@i{UF!%OdrERH06+W+4kN~Aynl`%H~yIbOWUy##sHpd(rYxoMtAC>Hn2DRu7$NJuWA_x&@7BgqMl82ngt6Qpk8}fQ}%baV$QP~Ad2R) zIttNT8EAF~Uqt5}t&VDhITQB!#Pok|q!#3#weq7 z)b!Ng%E$K@*OER@GG}0&Ozp+b_pF z%+t29;%!mr4^uBL+iH4iGb<;#2j>3-6O?e51UP@#u;YI+#brkFxuPXPy7=c!D4S&##+6@l10`zk||CdxEIG?2wF@v$`EC9v7i4#Q_fg6QtQC& z&sk;w;cYXCc#_#ptTnt4l*SyGSJ_}q94G3DA0bo8J4e3|uNI_Bo&)i}J;7d~gG#j? z&WQ&Cjt3G$so|UYp~i`0T(9N9Q5g891z}mj#Wu_m1YT+h4LHoCm(@z*y*-P3yN=XM zFFrrazQz%8my_Xse9iAUl)npgGl8-lFGRPQ=80{6C}U7FnVx62Y$l(x%ZXP3=90Oz zN@DH{L#s@1={nGPY535fWh4t+ZY29wh{!dj0Ww=eHkl`9u}r1;)=Bp!s$#~&xifEr zFSBW8MIiNIpVa?->brQQwRV41DFL5lSj0fqAEpy7wfOf2;=D5~-#@PLT5AiO(9Bq> zgsqG5zuR#W8*P&#^;>yA%UP*}=}kObS(jh&sc!qS zgNH5iRN|4|FQ6w!8an8vdh+Z!v&j$%Tt6-{1&dJcgyBwWS{f1 zSVz;1wsusxlT%L_N>kLvp9*cQDS zn+>K@539cr%NQ(j>r%-^Wv-m*GH#e#6Mv0>S~#lL%)&SVxb|L;9jFzj{vi&zsi^Y+ zrhdLaG|Q%vI}LGr?7OXOrJKyaHnQ<1^vPiB&0Rp-;njM~e8w1j;eXYvc)xBqYtvcL z)hB4P(?kchO$yV_*3c$slcROIxsgX-XsnW>IlrBepa za#mT|!KGG;%NGB`IB6%%zF`k&f!HW9YZH(1aix4XEK+rLf(#s2{Adug`EPK9(^v)d zsaA{56`ZvQ0{0w6dDogHh|3%}_n8V_&Qra6&J4_J85?;=T)Ko+?Iq;vz=#PMr~^C0 z4|P^!CAat3W6PHkhavU9-x0Di8aI87t{XD7a7-f{{CDrpu@F7z7ZCeMdTV&{58}V3 znFLel?|;uI`^+_oyKlorpyW1S_J@tlBcpmW`!XX%eBT&dEhzUyP0|9ron_;{x@eaG z38e7^8N;wKLISKTz!mmM@f|{H{F{oz3qX zNC%24(!r2go$@0us+NDm9;DCwD4Q2xN3-J2c@MDHtE`kAb%fQ?r_3$T!8Ti&+fT2D z`hO2$*$tvL(=^0MQBM$ES zz@xvxh#E(_hW1K1VuWu$jBh{CGxHAuekI~uylWwf^F=SC8BkF-1N&|-tT2%6A1`0w zA+zcex+km_$N2-xT{XoY>xtbnMv0yy|1VK;LBBIxdq$8Mh!7O~=!OI~%BObkv7$ho zj#cnuGaPy!dUA zn=}UqP%Y)uEXMzFk`(9|p-XQAMWLds)|-I!T)e7G#N8R5;>7=$>$|&k63ad@?%DfE zgn!4_Hpyz(h70dzi2``2vzeu+C}}4s2v+hw!iAS#FyfnS0@HKFYgdBhw&q^*neF>; zDy-~9o{?BHKi`Mt{X%@#(vM#aY@Oi=zneS;BIblOiwDTbcf&8mU?-r8hl;2j#NVcPZyi>$l8nd=vlqvG z-X*GwX4Qhwnlk*vS5fv=vCA9UbJgz_6O+y62}&WBH(!0@lKX}pglV{BmrL_UVN{4 z&kTYL7+$_FpqLbn)vt9(f4iuNqDz3`BsgD>?z)3-_l(9{Vl0Qy0Gk-B>kpu0E3?)? z2i47m)@(6yLsO4e0ByHL*}_3__J5-6TPW8zm^7asK8e{s$KoMchat6fJ!t()gzF+K zAED8yd4ncpCoq1Q%L;?CKkeR7!;sCzR;KGm==was&V^&-O*aUd5|~zpz><_f{`ra) z@InAxTR)q^r+dUJ4}7#aHoF`*Q{xlUVyJafDzI%PqD!GhxWge#XA010aOg`p@<;7*Fm&qat7qdE^Z!zlU6vHYN#t;h!Ix{x;?aQkq)x{llYM#Y2ka-_apN1 zUjk}jJW;g|&72UR8t8AcmcFu)J=Bg_YsD^;(k>d|EQXuR>wAD~Eh4S0&Y)ydHTxg! z!A-5OUqB(4(b>*D@Qz^FI_c5YBjQUl+O67+qKQSlZklqYBxb0u%>kA!w&!cpvl4|B zXx8`DqUwFnz)ofG$wqNb1lhh$0#nvBP{2Ln%L^twuEdJ}oh?5Jo@9taOt89N^cDYw zC}5nZ8cQHQAxHSn1`w8?@Se6+W@@FHqJlKY)iq=6z zVo}vG{7EvNDi$p_vqy_s9_;Nq+1%8ZMeM2f1HUJLm5DLSE}jv%)%YV0)WW+^a~_tnN zt)CM+&656TZ$ZN7Vwsl}0o$?10b!sX2#wVOFHKyj-%ie|0;YGq9!nMgAr`2w4M2Z6 zmyYcOoE;^$VDxAB1nS;okESYCy@$}isJqq9b#TNgKk@ZE(h_Q z$Q!DKb={Y?$GT`oZ6sNyWp%JuC)D1pXPz#cK^*vSVNa}O4E!!Y3xuSJIb3n|66IIZ zB!-`<)Wt|uz_R^f)PcC8$>n2!&pjp&?;{OptE3kv)agu8b9~w>_}n zJS=mP^zo2T9yePy@;yT~s(5`GqA6UpcEH}f6V0LtArny+j!oZ3`a6+l`S@BF8=@!I zr197gVpBK-Ch?_@QA@vz^g!w~&Qul$!o{gzN90V$>iIsS;P*KcDR3Y?GAi^?>@z6v zKDW%t(C-EmKN0IUx(x~H##ntEQR+b~)74SNpQJ&jlk3fWwCh}nT^BKzRj!hC{HR7G z3IU>OUqaW+(&5rj%>0DYbSP_%sO^L@n1zqLuK=ylwmhC zIL}9Uj>P6?cjn-d*(1B5~FM;@=L|s-<3#JQH-$u0ko>f&vM=fKZRiH9L zuDruDgtE@i_+~qYQgv^m+XDTyO5Wu`ovB*T?^_jspRXrk*aF!)OX&q4X@I4ybCTTR zFzp}AwE81>_&LCgu@H798KQ83AFyfnSU%dEL82``4=8z zHoi=O0w=Aok(ZGfc!juRH)%PJPBkP?YN3Y}l)bzSQU$KxUr^2WU%>QwGi0kSHj5-_ z>fotS{%62N$0(e_Yj?h>=%47R3=7=|cu&S=&jrQg*?z*qR$@2AyaxmFh~Zetl!@%X z;FH#VopAmfzWlHG*&pqwA&8_ zp0I0lVAjU!fVxset`}=5CrxMM|HCBm7!(povr!3~lgaLeipn#GQA2YwP$Sfy4wYOr zh`c!y;tc6=W&!Ore)Ix~eho#>9%Ggj8#l_COaH;F7DnSw=3iSvE#5CG+N9_)6cmF{ zbY~r>W7hL$VAxCsZ>{1Zr`<%S<2Ehl7FaPl8-WNZ?hW7%y6A0&G^0;QuKq#Hp)oZn zr*SZy7Z}s$tdeYoFDH_BrbSTCY7vPN$y9Z$EyaK^84Vt%|YoYRlvP7K;R;FNAxJNUC)g8J!3{jrC=)-JTFgl zh6&OYA%`aH)Ne;gHLNbl9d+6*6f~!DXGmtz=0Syd?M%4J$g7_J z+ZEOn9KJwpnL1S~g-0?Xw1342(H%g0{7sM_1%2x4F^R03oz`O@j}OpJUMBg7g?f$$ z&p!w6oolfT=dHkcp?5*p^u7$e7&+zXfnGi#`pFYD+{9naBBN$VWI(T;&mzHi`ZpNg zu3l5xMO#gV$HB#=CCtE@!zM{5f7_GdokYVh+HeEkX(m5s0c(=xk#9IoISPNf8p3-P zKL2(BAvXq2PnkhX^CF*j(>b{;7IlcncV?U9<RsX|X0pX#WkZ%;wCy=+`)Pn!w&7R>UFlylp@Occ zmsVhXG5K{5xpWIP_n?J%&pmg{dYBkK4XS@ZN!7K!l23sD5rZVQ zopdRe4jj6CWopiw^!s4!GlT~C%x|=T_q@<%e=Bdw5?M#@>9I+ zy#*RKq_lcUb!HQxCbFmF{QfoixSTQL{(E!_dj)3<46WJ${JckdaK`NAH%*Gy)v=ml z*il~q^(vt31MJnr^)Ecd&Rcc1!BkpKik*d$ z3~h=XpR#NwZD#VSu~ty*&~*WGnIWbY5OHKqGHw6m_|5puNvoM+I*78#^_T1k+8!yp zFN&C2Hbflr&msY_PjR2hvu0} znn&%`?dBF+kJ#Y5Dlq4x*j)N6KWm}n#-OL{yPwqbkx+8u$GbRE^Vp5*_mDgSuBQUr zyF%u9)}XOGYP>-8#K3>4;dnMajmN`BzQAoq8+GXBBy?^OvDsF-%tFfdlP;U0kuGFY z=6*B*D3!C*20$4|o)Cng56byQ_#(rk#a0^9l04S5ikj8dg;rJ47C^eVkVqQ-j3tg3 z-9nO%nMl{zXs$7XB~Km!{$B;fzr0nqS{bejhK-^-^)0<_EOG&(_{?MEV~;`mKZ?uD zba2mXIuuDmZ2DUnzgm#a`OFe?){P`q?P|JAq`r7TP!Ab zU*b4%dJSN>jqEPMhc11gn9(*y^|3NJGz>HBzu`z;jjy z)(wY9T1R3#FIOm!yzWcMJtYXEQl&-Vrvk^)(K z;p;wM5S8x0+&aLBAmZ>D6Lpcj`jJ4r((FwW(|oeE&oAJ5D`K~g6FBJ%yUhJhxbbQR zGqBF$O*T~Pp~&6AD!jh^6TeKz{}}9b zW|-M{4B}>G8!mQ7znXbHHjEN6qs)w~)_sM-wu6ap7nHS5L_R>7_cxa1Gy z69!Jtqazww4&*S%VP$_A@> zWt)+*9{VzcudeO0mrk6n{lyE~vEx7&k*Uy&mUHl5y@}L|t(0O>up~`kJ{wD(xf2L^ zD?)Cgmv25)^q8v7fKdPvB?Rud(pY;Z^AE&sJ!|Pppy780`Km&+TZl0Y`La)j#go<{ z7Xn#v)o?uXI&d_mW%Sr<#|nz>@L5UtUO1`eRpr$k6v zIP`|B$&lI3#CTh12IviHHHg2=wZI%r6||NreZ28k;6AfNCi}3AY1A7b(g74zAU>} z#8JH?8PJ)7*}%J~QMgrXLY<_)Q~rM*B}^Qstr8YFeeYC?EyIrs$%zYvq7U1#?mG68 zdYor0tsk|Q49mIk-{?i#W~k6;@Yr4l%B|V~!F40mL~BDtM8^c31z$P4u|Rf6<$t zKb`szb{73Ug)j5szM05e8{H?csE-wK7gNwiJBoV(ugVbR@JREGo2g0}-4zQW^NqvZ z3QW?#@&A9UJKNE--r+N+IDY>b6dWFc3KZa{xGJRll}SW4Tv6n!LvEE4)J*uiM7&+2mRyOW{)9Pv9~j@;EdJc9G9TlA zzo6p^O%Pc6`4+szhYWS4)-Mfb@}gRLxbh9o0@-AG;1j;gAbr+Rch*od7{yA%C@Q7* zDNGGJZK6(2b*}~99aF&}Qd&PaCWw5xL#E)(fn1o((C;AUkBDTl7?JLpEc+W$U4y+N z&!UCau58M{kvtzuEEAL4AtT)7HL+|CnQKS-PbPocN?*}_1rw&#bDcqZxH7pE>}9DY zte1oy=}!Pk@)?Ec%)sYLP<={i>UXU_>$`8&QtCw*8R#u_^VU55yF!$mf|g{2FCMR6 z%kx^&%W0HSpoQhPX`?ypEg< z25*xN>K~MgdlRGaH7#h#7HWI^65{-;ZPa{g{KXtYc}=^3oEC#undga$Hh5reuZ)3+ znbhoG#AmifYa1hR{yCI=l)AJ=%yjb{-0VXAvxivnlp77E>Ry=PsTt6X`zvWDO*t#3 zzh}RAd1xl6W}YxD%SAb5{mlZ>jx?VUK`AUG)!EJ7vMJ7*srQ8V76Yn1U2DM8G)79? zmPcA7HJEGt|DehPig&iLa&h#V_)NDBuvDy{3qV}&aB9q==ap!{*$z}f%hmG^7 z4501ZS!`}AzME4aR9fvOwxi6+X|EWIt5hb>0~$PF&F0zRb7^ROKnpi| zer;Kg*dwE~$L)`m@4(!019!BpRR?uEnfCmUvYK8F+z@S>LB9+!QyNn3Mlq+($Uv)3 z5$6Go&7ht*j*$KHT_t(CO>xkdXU_~>r5RY_DBSs;S(~SlDe5jE36>1=$CGGPn6rB! zUEot8(19m_nrv;7)e!`47 zs*AFS>%ki5zAJeE7g%;#J6dH8s*SFt{$23Du2HpJ|5G%@0a7A;Wlr-Rq; z1BDY<1y@J-fsIVH!LhSQqYUBgO4qY3kFN(47BdS+tD&u*pelNdPMxY!!M4H7_O&$q z_m?M_YJfZM5NC@jpuTRX%~f1o{JA_m3xmtbjv|roF;^Mb$)*`I;|lcBHk|tv|8Edq z2AWLVLC$cN{qJYMVDY*bYM~6@rp|!shvJZ!#9^l2Bdtx@zZNT0Z0P7)R>>U}_mkqX zwdkh{x`Cdbo*GLR9b_l9Om^41!!5t8rC~yPL8WS=4Z|awY5!9#+BdVQ1qP0?>Ag1EN9N>P z4>Ru+ioLVm(hf>&S-$EIX71E6)|d2Z_})T(NCpEUfZ2jh*vb2p9fB*UoGzqjGcpbGsg*(!pTWMLsZ=b7kR zE_(UOerzBqjpZ{a%9iS(qFbV@Lt{{32H^G6MRv7qIkoUKK5ZenV49okRlg2KEJSM_ zi)ZhJ;kgse9ct#NRvAV$zJQ`f0RPE98$Mhh8UT6)4GTIHFL>#auycY)AJj^Of7%*N z{2RUa^!1J8t9MK{npLoIX=c=JSMpKF?u$|RbPKQTP!sE=VZm}>=|8$Lu743r>MHX> zP4a{l;5**fCL}j`A0ziPQ1z1|tF_ShC549-ntClVxcAkz?4k~FPt?chKr0H4UCe7* zP{S@5H^ln*qnG11k8ijqyyZ`U-%`VN_kBaUT+k~AZaUS?EW5p*A9*<)?z{yhFOj2M zPI%l;d)ensA8i6}Vi5TNJYuxx*T?nr5OMNT+0LWlm1_@xNjQCjGO800xqkGp^qZg8 zEplWk-WDl&I?#4HD?b6qDI7(vyRB!GRKdUefE@GNP!*DN!cqDmNF%wa7h-#^13#tY z=?&xpAF01(lDnC-+S*eaWK8)GjjYhz49Z!qM-Md6l5J_iFMHW0T70r;id1Z+K{=#l zUxz46dB8jcn|rtdEtyXqW1Gsn4W+u#UIF>OX@(L04EQ&+3_IQfmgysaGX9v5_9Luk zY!?D%&cwQCN$aT5wQHi=ejkY!-EOMgjC=3SnlxVe2Do04FnHh51I?n+zA@0=hcW$& zW#zjSib+7yES{AA-IsKy?}S@00-ldvO&CJWUhk4Lv!ld(|0a|2wZ|=!8qBor#*&G^ zy_G-tDp4zAGlPt_m;W?TjRR{d6|J+x$W%1+B%C;(5kVA0uo{7o>f6i3?@0wGU1J(X1b>ITf z_O!wSO^DpU;Jre5UBFWM{MddDcFkKq#=rMlX(}IL%c8+D+cx?cp8Q z>5-+oE(KkV;P?CO;d*++?En=Apf6C73j_NwPFz)r&#uKSCFJ=HGpm9-EHl75XWEz1En2fd2-L?@zL5(~$=o#wlB)Aa z9>Umcw0~gyr(j4gcT^`lwD^e-J75>UmQxM^@mV7 z+ddK#*O1e9&^kmL^+SWC=?)ql&Dr$!SyrBbLF-<^%ixNW4jK^dVlM)n#neWDY7cj7 zBptey;Sb(dpqpULuq>ELn=NII*Gi%!ro1wuGvM3SEuAo^vuG)03$w`Hq-Z+2NB5j2Y#BW0R3+h`D-UxwujS0J=`$MLH4lueG6h# zfpIzH@C35EdIp|(ns{X4MQ4jq1CJc*v=(x+Qb1-FBu#bFM14=B2cHB+$B*)G=)Ubtu#R zp(6CJjT?c&Y|y_5P-h=!mz~bEEVfMYdG`PBCRBkoKbX0aTgqRz5Z=X6sLm||bbWdX ziHW&%Z33r!)=Gxo`fi52xPAjGyjo-|&;OdJJ-tox42#g+29N4kx%7wWSB7$pK*<xIN4#K;P?x*6_;q+An?QHGdWN#VPtxa|VGH%bQwtRp6wHx7PhMo`4n zJG3c9-bv0GTfTc^snC#2X`qE7rzm>2EB&YR1>@y2Q9Dc4@-4a9>2_qp)O=56}n0TI1Vr} znAZP=uw~$;w?%W)mk^KO6$5F*tfpaRV4H2^GCj<7Q}6^s(7i|nTkeS)!%|nBy(*-~ zHqYWNYGy0V%R}B+gPX0$=gIgFU-F*_Jmtp);;nOl>@&w}Ov`E9DFA-0VtxvqVpKC2 zi)9A{!CBwu&6`ZCUcvwxRM)WjXX?S!0sN&xbk=YMS^;o7fumgvvvm9i{TgdpXn3Mw z(j7qMKB9w@jvKkjK)&p@mG-IAEanz!zDJHmTJf< z^7%d_;)+n5H2}1HbyT?z0p$SW&DS=-$3F&MwL)obz^3=WaN*vkP|bu2@rH9mvoW~< zMr7ye*HG6XGUZ1Pktz_KI*K!dTDv4lHCbk-ag+Z2IhN!e$*6SrLYE<2tL(#XC`^)G zPgb3H!G72q6&h-gwq}y4%D0;Cp()K3I)Ha!A9UVSYf)A@03X}T;w55#GNdI;CmWGj z>2b`X>h0`Q!eyPSWbRM;fr5o`#5zwG$+}4f<*xG=}(pv+@e8W#6OD!f7o{A(G2+ZRYet z81ZL!fk#=)rR&gN!Y`$5#)EI&S6k9B@?Vo|h<_%AXF~U8(QAtdeA4z~G+}aj5AiPx zFGP6ae$jBMc$ z6@OSk5#9zRCu_|z!sHaPPr99h-_ynBXzEws(MEH<;yEJ4D%ehOv0LhH!ClnMTf zrQVp;R(x@R1-9;q!;30yOK*m1HSQ4l9-E8ei>%a3O_HY5EL7E>%rZ`^J>912B{Rkt zwv(U^571hEjqua)A1DOs`%Lw-Uv4VJuu)9_?);d!|1Qzne1tI5;eV|l^DTLJtWI&~ z9hAkZj5`F}ufeyJ*W>f|5WkV8ozI{pKWQsC8B1vp=@?JWnXDn5>AMiO<{cjVrZf@% zG>6y~fcDAcu^amrq{!Wd@8$m=O7eMjv=m2-^@-juE)xm<$Ko@G$XQsI$!Fm z2S`18oJd`C+)NG)6Y4%enTXRkj+rRcT(U&AneId@7 zolGrI>_0hPcJH7`+FEDndE1l13xOH6z&$!Aa_`kCv#6FVaaK0=wim6N2d-3HKzH<8 zC%v31QyZzhyJ2@Bedr>c!zs*TrJ3%(CM-YLRq1)*&C^t8TaF6?vxt$T@l z=ekNB4Ez*+3tmM&{?)g}7YnE>vz(0fv89WBIHsm@e=w<9&yie$lKg1`$AA=z@O@() z9W$uKX`$yIJf7fIWDvAk;MK-!I?rxeJrOAA88nQ(%JdH%`u(H9C_g{nX!@1IMmS8N zJkV7M*v{rg#~ayPNA7;-tF8|+qkqz=^=XFfgx^TxEckm@1+k1q@4N;E=*V7)H|$2a zEFQVQRRtO}*#gsFiX7O{#N5LV!Fo2}Jtz|NVWF#mrFRvf_crEod$vjt+gY4zstiT{ zAhhO4G%@xRZ@#Z5qB#%g+6<$THT&#guHUL|u&hTvTXl-%zwrRq?_)2V)HO?H(f=ib zqO-5XT3^{`8+DY0dd_d5YNgRuHs&! zKC%24z$-v{E{ZZ?*=_6vBiCiHXl-pMtc3+C)bQsQ>c2DBjPS)WQOG^TfjV)>1I6BE z+W!W5$}}wXcdfm9H`YoG4K-R$xcU*RiXg`RhwoY_+Vx-nV*<}^;I~V@09_t(_+uSt z<%$$u($SBBT>#$k&|kN8Nc6RSw%>09|E9>$)u+Xg4EgsdGU-Y{V@FPRA6zGa<69r&fHEM>E>yKWD5M6m{{RP{4?&39*?gvIKPc)*6{_KUDlOY zF%u2tx4?J)mqDNOfBf^$G-cTT;8+*KCdBBP@fVoSyqDf*4of>91yD?y zeg(b*HRz7V(6tF1`(^2LEa%AcK4zfy9X^N9m-9xyDFGrna;_PdpT|Ib=r{7Nx zW!-_ndi?r7b+YcS-rAw@w}`8rmZCMSXoEM-JcK`ZgLlg25I^VMjr6NTVm-i+nL7BB zLHu_QTDyEl5wSaiesPO_Fl_I7;^kkW`%5FmzOA4jEFJ#!U=wVfUx5}iVAHpORR1%2 z?}$Woj#%dTVAXl_l_shZxdqfhwBTw1-F_IhC|hKkq%kg*FqWJ>y0HTmMLF;@9^CY5I&zy^!f+D$FLDQ8R8w_ zuT47G-i7C%$5i_qGVwaXd3bib-#328^M&BR0Z$eBHiCYVjahz-seWRfB@LsQKd^V3E1#(iyr8Z6Bl!5w(Le@NEx^eQcK-L>4QvNoP<;&gT;F4&KF#(+boPE`&!5xE1U-!*$(j&}1$zAylfF6z zFB5Nz(TS?#MXU0a5t+(%`2ivB?W(V=8p%Lsr=RYklcj$i2?$QSC{Ci4Wy6c5ROcT2 zpJ*z%Mvw2BhjJrUt~8Tm{#^%Hy&6QKm5-5=@Y0It^0ZUUF0zt3fy8nIkZ+hGZT7I& zzFo1}ay}I`J(RV2%M=zFp>2q}j+S=kpZy6B^w12*;T`Uy>sg^kp`vWjfCBv$x{lSk z4avC&_1d|~I`>c3N@J7hOWe-3JyhMr47^W3r0j*M-;;}9@wQHIhePs2rM(_-=>2IYyAGd1=3Dt23F%u+!@5)YJvJytk6n8uoMyu?t~i*Hd+VC{9!dMeD5>3XKT9R zDEb2J!h6~1?#@KAayhQ-7F7?xFI~wfx~cT#2CjVZNU_#R)Z33g_@)<^8iQHp6+r2l zZn%_-wH^`89!Jg*gwy+BTRq!IPW~gs*PIsl`e5()s3BWY2du>mw>qJ`?O<0u;&KPL z9*ERBK7jA!i+u;MsQ*=n;}~c}Kb)G3uQ@KtJ}&CbpkDf*BT1{VlKcuHGqXZZ{}pkO zRtt3feD{t>wLv+@(42!|#C(1rq1-XZlvnoNuE2I})1x1X>41;>4Jw+5R{7$EG`02L zSKQ8CC^Mkn2o7Oik&7%=7}FGrR6LR_X1XIX>v4#x2yRM;{XYOn2MslkXvQQZBK+@{ z^rb`(%(s#8#wEr4A4g~65X1lf@i}&Ps=Z3bc5Ee~bl?9IjrgZVuGS<7HFuZ|^Ih=md3kYx+o6u;OEjH>|x_ zys^d2t9%=`Rf?IV4$1&)jh!IQS5V*DWh*IROxkxqzJmcIECBKgIoEBAwfj#XKFVsa zBKZJ2W{!H4oqW4q@$4v*n1#3?0(5=Y-}RZ>*JVq8eNQj?Ey4WvFj+|*&N*+2*aDsmLLN&xnw(B#nXaHC{`x8`c zJ$`#$+9Z(&H-Bnu6`)z2hAI_P+KY*&N%AIqA3ZYJ^q*33hK~H@@)&f5#A0*yTMhB zG16c*U2LStIc!}j&$h08vtk+hz+UX)2Q)JgPr0K}Wm9awf&UmzncS`ep()+fdxUd7 z8>>9Ej+`eX_8R#-Lt?pLfZHO&7y^HXGM6YF(mQid?pPDHG29qzCy;JUimzr}(X9|yo)Dh!ZZW^}#QM_O4s~D@NoNN6gi?{)y{^fXf)eu)~ zhV=YxF#@{Z1>FcnjfY)>grk=N{B6*C6Wr429`^N7IF)Zkd{*H5&=BDL3Cyyfocw4b zzu+$qeCtkI+EA>|>u8OhNHb{})Z2TTVI46=>QXT?fA7TZK0H8v43UrJDkn`Sm{ZLz zA7CjBtmF-&wSVF$xux9GK^`Jf)(PcWbLB8YafMgw@a%L>dnB~;%xJk1k&OJYN!1Fh zG$Q@_xq7iP9)L5|XRwxm(Cw_CX-LdMMmV00t_6KhOS|g{XC`-aDKrthw50-k@0u69 zaSvFl02UNv;DK99F>dG43s^LRfn9~JG)ZSC`?7BhPQkePQs(mGZ=iPaH)f)h2Xrg} z1?n3>U;;x5L6k-o{+idOEVm^1%1FQ74@EkXs~>QgReK2H&rpYruK*Z}lMK#+>$HQc z@@f2HNv=gq)W@>*N5I{N*ME`=hej0bNKS=m9jtZ2T>O{H6fFw82jtbl|`iU%|z(xL(`=|{{l!7 z|HL3@mz7dFQM-M2C^_eDBFWvn1ATuF4)^cJON@ru)qz-wzfS#bHsC3rGhX|Q&LG3= z92A!N%0*+eUnWrJ)=#$=t=Sw2go?TDw2(Zu&}P2?_5XAP`x5FUBe#wYl> zy`C87*f6K!H{G_W@x2)`>qmSS2kH6L4Ahk^`vb(U<%o}fA39#@Y?U1>j}aYs>5J6= z=`iPO#&~*C<>6n&9O~zVb@*w{f&}8Djj`r6$JGU}c7rTGBK#wG$#{TkL@h^WlJCs5 zqyd#@BX8r$r;YOIEmGP9A%yOxlaJ1Rvgs=*JdAAL5JV=p!Kqio#(mKK5pq8q zyYQt!dFf|F^JxGIO8@Mux%A7rR5w*D@pl9AS_Z(o9xYb7U!H5JB_7m*!-TIsX=4d% z);~7*aT^yD054yuEhAUAcJYY)piM73N{`t4#iC#|D`DnXsBnt(@*(NIb0P30RR~a` z#H;55z6Sr{YvBbtqB0g0!MIZ@6>#_}nL5CUdt1X5*F(t*2lbM^46z>P6TmX?thq+D zjPux9JE-)dDMQ{0rnyhoiODhjE=q||MfvF>o#iEug^}xwHa5GKW7gVhM*lY~Wu zxMkiXG!{s`a+_heV0t>6ZIR2_6-`Wp-dqWtHDvJHvnRG?A1=p7rE*7W;sEQi-u6IwFcb*eDo(Z9${L4&<5x!Tew9c9^>EGa+2SJA zHSp5FQGCrhltC~YHP=SwGrENL-ZZ|1a4q~acM|D!Ci8ynlv7}>eCvSahV$dJGO?L# z;lO}M8)V_8Tk^4nu$qEf7rT?zGZOLh1hH`3c!Ca*1`zhn2l2A z*lR$^mg_*Eg^COsvMwHNRQGusvsJ;XPxiC(o|z(UwWh|#OZs#jR=P3%VLC^ae5{er z26o=mm3^$B{mlDsl7n{ic-cgLfRLqZ)HV2@u|V5O8Jt&h-V6FMM}Fn$%Tv*Kv)wZw zV5e#7yim=?XN+ghCRNemrf5AXOmBL%PFB?;l!G=NMdX|HM8ig$A3!Y@5k^2{2+Oq& zz7o8J&pQxJhV6IKm968*{u?%xd>uw&-VF`1%jE{jSThBSU%ZB0++^$X2nhIs_^<_K z_rCR{(Gxw$UFPywgJK4yrug@eew||<64b^Rdr(7Vx2q!`wAx3^Sra)_Wl&g&dynP4 z_;2AWJ~1_txIA52G6BDJ!Bd^Rlf?<*df2IA{fQ&YZ8+X#AqfUzeb~8eNW0ZAx6p7Q zz8c-=OI)^-Hk8Fka_%1sl((6Q6rLspqWi4Ea;d-dHn!P2;yfvNdMP85RXyBP?;$3aGjvXghP? z3qB6#tfdc9o9Wh=gBcY-T05~%5du3KQ|oi-JIsR`O9Y?mn)``d@H(AGObtFqx_Uvx zosamH#xvy3eZ;B3qgdtgByy@>9=SNsblf<4tAQVf%34EwUX=)0jTuA2I9gS{7tTDp z1B(eWNWCzg3ZbZR{)(Nhnptq8Q{PF@rx01)sSe|zEeYPB{Zan>Cy>>${bYyGUH55U z4XKJoBlm;K1)c>x+}3RyV9|frEvN#tNx08yJpWQC4nr0k9+5U2#dbDl$ZCGNSGnuX zi6d1|`%nf)JmC=B@qPt7-YjyBjn8IQfXxZ3(z^C4A$@Kd?U(0IPWGt)qgCp6URcp( z*2yY^B>dRx1;#uG96?3$c>7#oLGz4%($@$RA zwj5697p7N$;eVkmGIh$*psl}5N->?jnxzOvw16Qs*uR;c_B@c<(nFp$lGj-(N568X z8qNE51V-rIo+O6*Pq`DiKcvpARACsySNFd6oW}gLE+9V4|i(7+}sWHaGOie<&1x zWA!8?0yPVeo@W9ZiNSs@efJakd-a+%URa8`LZOOSz)E<=D&$W!2hmu7F|O(Kl6sh zoy3Nhz{^uU* zk3r#fXr<;J#w>{^dazpq*MXrCPU+Ge+&bsQ?5A*eF4~<>eAEhc6Y|OR=CVqzPm-W@ z))3?PU|TD!@1(8VpNkm-FnKjuP2{QeV`1TiP)V?aLn+c>8hU9%TuQWaH!vXY2R(()Zob^DKn(OQz}hZ7 zG)F}?KN)TY=j)jo(#UbVU*y8d`=s#4_X;HWJUe2&9uPiJdWo_-fI`h5 z9e=)w`uA`sT-1ITF4_cG?_jSsRHejt03sIy(8|3j1GsvdeVpr#n|A-U?PS7*ml$M4 zHF_r#EqSH?bGnC4cf)HpAo5rD-VNP0c(B=7^BJz#2ukXE*{S-k8PDn-mSV?Tlhj#( z&hlq^b!eLKS5unI-m+Ny-8gdCPI2w$Qd!kstkRoC#euxy3w_Q^{BhuF6S*ia0|+mW z?z@K1c?wv5hm*M+YZY97l9hWsO&B*gD2NeY7f+!GjNdxEQL#@Yya&xXgNGI0!{2=Z ztc*IP{^ua8-Gg4Qc|oMnn#kEF;TXT|EE@?Y?-cNHSATBvlS4;H``ceFDuB&G9Z)iT z1dMu?PCm9Q=r#x_&$N{!vjd1MMAH6P-z9MvdhapF$v%1m><*SAmJXVg!`8(W+?;Bu zzwRzO;-u=7lO(I0h>9AT4hbb?CL2Y__1p_S&&ysGFD1U`9G7$m2@l-uPZ_x$KCYh%V4X4<}m)T=Y+&J8j<@Wlt; zll@WD#5al3s$rGEbmqn9udsWzQucVeep~?(D+9}Z>P$6N3b^iH*tKyKV$-f)|BYR? zI!2tcTROR>3Hx&l3;+5T=)QU}%WMj9TS^%f1d;Pjp!RcZ@jcw)Z3eYY+YNj~%G69p zMWB)V1SH?&u6)P!- z;wEBAlv#d@dlU5DXJ`d*#gztky-B3|dlT`7)v5Ru>HktUHv6sXygBU&jF4)}b?nRBn-s@MeZ|(u`k)`v@o(j*eJ}wb zwM&qfo%sPI+! zTH)ia8}GlEmRckczIMdM4|wHjy4wjet+b_c!N@q(`-Q*=Yx$_z`N49q(QH*riGJx8R3uK&gxxKil!yw$NaTELDZ%a!a|?=W#$;qR1`<` z@Q*f1qnE2ARt>_9UA@dyy;QIGeDfOzO8+pA_O?bZpO}ib%-_A|33l-|-tqw0{14#l zM{knwAo7i)bf6u-tTJEQbO)I^5K690$P3KS5BecASQ$baYRYoO>T(qXYxi%A{EC$I zuzebza(=a~qs?Z7P>W+p1(+qqETa?g$@}ui=DBn;L?)M$_A~JAn}ij3o6*&glWdEx z_jfkg(pTb%kAa%CKopTdzBg1?&!Jgv%4M)$qiyh3wu?N(TMtaTN+b+2E*Q@IpIGnS z3^+R#f6!&GvE#K~Q-u*|W(69C3Zu8`>F5FD{MeX!5w%O(zWZfOEdc^7~Wc)z?wiX}{F zYW-t@c*T$~uLHQE;iS|tk+c*B1Aj0>I!{1IhS-g#e~Wxx!(~liseo~T#@Hxd9Wqgj z-D@kc?B~>309lTzu(zngiD4v)m5#1Av_0y_aAUUtyFBIbuX@&$n4|LoN4+Mu>Bu$r zZsYv1)NX67de&u`egS`uBzqlU{ zUwjYA?pO~6Iuh4geHH7Sw11b?kX~T%3YIdiV>5j)1X0M%(?cMtDUWnj5|?X6z)aRc z{HtTZAx^~Af%`Wcg5jOU14_JcD z@W9>$VF58C=w=fjaLfoc4<184W_V1VLwcq5P~E#FG@Rwf5LlM7Ql6oixj(^{PB#7~ zi@9nVCI4gQvlX&*T?YAuktLg;H%wKE$sOoD*-YC^7}gK`#wf_Kf-7+9nGSs-Im^P z0geRJ?Kd(9ROEL7@MI7~=BE8tD3@p&NPhT4y$sh)PbA=l3pNLN~C&)#w){%8(9b}#Jh{>$c&8|G6 zEko)6dkro}4s0I;jt?c`+^mzvpCHRrtos2mucQKwHpjO<5))SCn5n+@$uug@OP&f9 z*I4)rlAM|8#Kv-|{WD_C*88FkV9_8QOpy=y0kNXmKP!P-U!@K0s1Y0ha*M-%`YM<& zDsHD;n-)bcgqe@;=WM#%&Y{48^`lw6c004p-ny7`ih1`HSI2eS}%x%^B~_ z6GGE?ak{SKpw9^?AZ0;}c^wM+DO2%4HfrxWioA1Hy68Yc&^BRtwN>gjF(o9QQ)Q1g#a<}2)k!~^q!3NrPaOr)D_J%GFS%sTaAHgFod5)H~Kn{5@Qk^)UXn8X4) zE0zJS25iPlmTU_z@HkBF+Q(7!I2FuAW}Qg~i*{!SU(6)nMK;0ACB(Tt<39A%0J-g| z&^DM;WQN=d!tIT!tKad4?s{ANuy$c=25CiNqB)H|Xf2QV%d$2Qa61k9{y-b%Nf&J; zFWm&wPT67&|Di1pGT?*;U?r*b?C+zps(L;{Bk85XLbz7%;lHso6lESpgV&?HFKVGT!?LV#THW@jkA#4 zuhbUuLZuCtu{ZOG1^42}yH9@*@BB4Zm0-wQ!`jd6)3-Qz;md)9i!AZmmB5EALA@87 z;bB+?_p^UI^#Tuk9%ctD8Xmt#>0$Y2O761JiHwp8+p)%{grkZ^j_C0zJx6CdiyaQqwBfv!T_jk2r zB_RN{^7c+LtiB<-#sb~fPQEvToqd?eH(|rjB$Z(CgI=NhSOAqzoZl&ZV;U;0nyQYz zqKe@4!;K-_a!{zW_E(q~)HXoAr6bVqp&Kx_k}S#IBYURXGI2_- z%)QsaqZ7CEC$20cj93&t{Res4&T(X~>RXR=7<7w+XXUH1pAI8Q1^PhvNCI@}3Hm)O zHfo2|JhjcqSpgOT8asZ#PGRvkmL%}L&ZO=}2CH#35_`GFTHE4J+_Wa{{K1(4QVCCF zh4lTBQkxzeICF0~&@MJIftZZ=5toyA)yf;!fpvwj&1+75SD$`?ZSnizHWB4Z@z7AX zq!)CSF<z7Uo;UzBKp6aVFIQgy*^b41MgreKkDaoE{_li$|-_eEAO=3;aa#--Z8xW2& zUM@pyUa;#so*DeuKgdammCoD246uHl$T(vW0+l511vifwM66c{lcdj_|H8waq|Fb( z{gbIrtHx85g|==p{p;XZDwt_NEiz7xg0+58R6jQqe?t)QM X!vGkH5P)xhsehq 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­fR+#{clFA&3$g?ja*v#Q8eu^Y9C=}^Y#yO0 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 z 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 z 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
ym2sWhMQ5 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ïO_wcQLr5@lbkJ1$6atJ^n3g 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

<)%Yyd6`kfctFG>j^BlgF#tnT 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%0Ai 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

?Yv!FOFah+cSyt~kLbWrOVVX>x(Cj+#9? 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

4tw*8;zL<6_ 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 diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_MetallicRoughness.png b/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube_MetallicRoughness.png deleted file mode 100644 index efd20260218a92d097c4005a8167dcdf08180664..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7#Nv>)VXbLJAo8Sx}&cn1H;CC?mvmFK)yn< zN02WALzNl>LqiJ#!!Mvv!wUw6QUeBtR|yOZRx=nF#0%!^3bX-Aum$*pxH5<^{Qv*o zVCTB|KoQ0yZ+92Q|4h2~fE@M`PhVH|hb-*uO5zb)HRk|@%sgEjLn>~)J;=xi Date: Tue, 8 Oct 2019 12:51:08 +0100 Subject: [PATCH 011/170] Add bound checks. --- code/glTF/glTFImporter.cpp | 16 ++++++++++++++++ code/glTF2/glTF2Importer.cpp | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index 9ecd742f6..3a521554f 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -330,6 +330,10 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) case PrimitiveMode_LINES: { nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); @@ -353,6 +357,10 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) case PrimitiveMode_TRIANGLES: { nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); @@ -395,6 +403,10 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) case PrimitiveMode_LINES: { nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], i, i + 1); @@ -418,6 +430,10 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) case PrimitiveMode_TRIANGLES: { nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], i, i + 1, i + 2); diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index f8e52ae66..ac5698bd7 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -530,6 +530,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) case PrimitiveMode_LINES: { nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); @@ -553,6 +557,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) case PrimitiveMode_TRIANGLES: { nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); @@ -604,6 +612,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) case PrimitiveMode_LINES: { nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { SetFace(faces[i / 2], i, i + 1); @@ -627,6 +639,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) case PrimitiveMode_TRIANGLES: { nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { SetFace(faces[i / 3], i, i + 1, i + 2); From 5f8f5c32923ec8a5acfa8f6d3d8325b77c66f6ad Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 8 Oct 2019 12:51:31 +0100 Subject: [PATCH 012/170] Organize test models better. --- .vscode/launch.json | 19 ++ .../IncorrectVertexArrays}/Cube.bin | Bin .../glTF/IncorrectVertexArrays/Cube_v1.gltf | 293 ++++++++++++++++++ .../glTF2/IncorrectVertexArrays/Cube.bin | Bin 0 -> 514 bytes .../{MarbleCube => }/Cube.gltf | 0 5 files changed, 312 insertions(+) create mode 100644 .vscode/launch.json rename test/models/{glTF2/IncorrectVertexArrays/MarbleCube => glTF/IncorrectVertexArrays}/Cube.bin (100%) create mode 100644 test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf create mode 100644 test/models/glTF2/IncorrectVertexArrays/Cube.bin rename test/models/glTF2/IncorrectVertexArrays/{MarbleCube => }/Cube.gltf (100%) diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..7047f4581 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(Windows) Launch", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceFolder}/build/tools/assimp_cmd/assimpd.exe", + "args": ["export", "f:\\Test\\MarbleCube\\MarbleCube\\SimpleTexturedDirectx11\\Models\\MarbleCube\\Cube.gltf", "foo.fbx"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/build/tools/assimp_cmd", + "environment": [], + "externalConsole": false + } + ] +} \ No newline at end of file diff --git a/test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.bin b/test/models/glTF/IncorrectVertexArrays/Cube.bin similarity index 100% rename from test/models/glTF2/IncorrectVertexArrays/MarbleCube/Cube.bin rename to test/models/glTF/IncorrectVertexArrays/Cube.bin diff --git a/test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf b/test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf new file mode 100644 index 000000000..bb6196a99 --- /dev/null +++ b/test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf @@ -0,0 +1,293 @@ +{ + "accessors" : { + "accessor_0" : { + "bufferView" : "bufferView_0", + "byteOffset" : 0, + "componentType" : 5123, + "count" : 36, + "max" : [ + 35 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + }, + "accessor_1" : { + "bufferView" : "bufferView_1", + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + 1.000000, + 1.000001 + ], + "min" : [ + -1.000000, + -1.000000, + -1.000000 + ], + "type" : "VEC3" + }, + "accessor_2" : { + "bufferView" : "bufferView_2", + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + 1.000000, + 1.000000 + ], + "min" : [ + -1.000000, + -1.000000, + -1.000000 + ], + "type" : "VEC3" + }, + "accessor_3" : { + "bufferView" : "bufferView_3", + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + -0.000000, + -0.000000, + 1.000000 + ], + "min" : [ + 0.000000, + -0.000000, + -1.000000, + -1.000000 + ], + "type" : "VEC4" + }, + "accessor_4" : { + "bufferView" : "bufferView_4", + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + 1.000000 + ], + "min" : [ + -1.000000, + -1.000000 + ], + "type" : "VEC2" + }, + "accessor_5" : { + "bufferView" : "bufferView_1", + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "type" : "VEC3" + }, + "accessor_6" : { + "bufferView" : "bufferView_1", + "byteOffset" : 0, + "componentType" : 5126, + "count" : 35, + "type" : "VEC3" + }, + "accessor_7" : { + "bufferView" : "bufferView_0", + "byteOffset" : 0, + "componentType" : 5123, + "count" : 35, + "max" : [ + 35 + ], + "min" : [ + 0 + ], + "type" : "SCALAR" + } + }, + "asset" : { + "generator" : "VKTS glTF 2.0 exporter", + "version" : "1.0" + }, + "bufferViews" : { + "bufferView_0" : { + "buffer" : "buffer_0", + "byteLength" : 72, + "byteOffset" : 0, + "target" : 34963 + }, + "bufferView_1" : { + "buffer" : "buffer_0", + "byteLength" : 432, + "byteOffset" : 72, + "target" : 34962 + }, + "bufferView_2" : { + "buffer" : "buffer_0", + "byteLength" : 432, + "byteOffset" : 504, + "target" : 34962 + }, + "bufferView_3" : { + "buffer" : "buffer_0", + "byteLength" : 576, + "byteOffset" : 936, + "target" : 34962 + }, + "bufferView_4" : { + "buffer" : "buffer_0", + "byteLength" : 288, + "byteOffset" : 1512, + "target" : 34962 + } + }, + "buffers" : { + "buffer_0" : { + "byteLength" : 514, + "uri" : "Cube.bin" + } + }, + "meshes" : { + "mesh_0" : { + "name" : "Cube", + "primitives" : [ + { + "attributes" : { + "POSITION" : "accessor_1" + }, + "mode" : 4 + } + ] + }, + "mesh_1" : { + "name" : "TruncatedCube", + "primitives" : [ { + "attributes" : { + "POSITION" : "accessor_6" + }, + "mode" : 4 + } ] + }, + "mesh_2" : { + "name" : "Lines", + "primitives" : [ { + "attributes" : { + "POSITION" : "accessor_5" + }, + "mode" : 1 + } ] + }, + "mesh_3" : { + "name" : "TruncatedLines", + "primitives" : [ { + "attributes" : { + "POSITION" : "accessor_6" + }, + "mode" : 1 + } ] + }, + "mesh_4" : { + "name" : "IndexedCube", + "primitives" : [ { + "attributes" : { + "POSITION" : "accessor_1" + }, + "mode" : 4, + "indices" : "accessor_0" + } ] + }, + "mesh_5" : { + "name" : "TruncatedIndexedCube", + "primitives" : [ { + "attributes" : { + "POSITION" : "accessor_1" + }, + "mode" : 4, + "indices" : "accessor_7" + } ] + }, + "mesh_6" : { + "name" : "IndexedLines", + "primitives" : [ { + "attributes" : { + "POSITION" : "accessor_5" + }, + "mode" : 1, + "indices" : "accessor_0" + } ] + }, + "mesh_7" : { + "name" : "TruncatedIndexedLines", + "primitives" : [ { + "attributes" : { + "POSITION" : "accessor_6" + }, + "mode" : 1, + "indices" : "accessor_7" + } ] + } + }, + "nodes" : { + "node_0" : { + "meshes" : [ "mesh_0" ], + "name" : "Cube" + }, + "node_1" : { + "meshes" : [ "mesh_1" ], + "name" : "TruncatedCube", + "translation": [ 2.5, 0.0, 2.5 ] + }, + "node_2" : { + "meshes" : [ "mesh_2" ], + "name" : "Lines", + "translation": [ 2.5, 0.0, 0.0 ] + }, + "node_3" : { + "meshes" : [ "mesh_3" ], + "name" : "TruncatedLines", + "translation": [ 2.5, 0.0, -2.5 ] + }, + "node_4" : { + "meshes" : [ "mesh_4" ], + "name" : "IndexedCube", + "translation": [ -2.5, 0.0, 2.5 ] + }, + "node_5" : { + "meshes" : [ "mesh_5" ], + "name" : "TruncatedIndexedCube", + "translation": [ -2.5, 0.0, 0.0 ] + }, + "node_6" : { + "meshes" : [ "mesh_6" ], + "name" : "IndexedLines", + "translation": [ -2.5, 0.0, -2.5 ] + }, + "node_7" : { + "meshes" : [ "mesh_7" ], + "name" : "TruncatedIndexedLines", + "translation": [ 0.0, 0.0, -2.5 ] + } + }, + "scene" : "defaultScene", + "scenes" : { + "defaultScene" : { + "nodes" : [ + "node_0", "node_1", "node_2", "node_3", "node_4", "node_5", "node_6", "node_7" + ] + } + }, + "textures" : [ + { + "sampler" : 0, + "source" : 0 + }, + { + "sampler" : 0, + "source" : 1 + } + ] +} diff --git a/test/models/glTF2/IncorrectVertexArrays/Cube.bin b/test/models/glTF2/IncorrectVertexArrays/Cube.bin new file mode 100644 index 0000000000000000000000000000000000000000..fa55b363a388c66673da35b547ab3a122e0a1d88 GIT binary patch literal 514 zcmZ{fR}#W73`8G2^xiuhL`Nex%aJ$&L{7wbH0Hyz((0{jLxUzQ+H~mBBcsoNAtT02 zm@;F|f+Z`~Y}m46&w(Q+&Rn>1 Date: Tue, 8 Oct 2019 13:05:05 +0100 Subject: [PATCH 013/170] Add unit tests. --- .../glTF/IncorrectVertexArrays/Cube_v1.gltf | 14 ++--------- .../glTF2/IncorrectVertexArrays/Cube.gltf | 12 +-------- test/unit/utglTF2ImportExport.cpp | 23 +++++++++++++++++ test/unit/utglTFImportExport.cpp | 25 +++++++++++++++++++ 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf b/test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf index bb6196a99..c076c5bcb 100644 --- a/test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf +++ b/test/models/glTF/IncorrectVertexArrays/Cube_v1.gltf @@ -204,7 +204,7 @@ "name" : "TruncatedIndexedCube", "primitives" : [ { "attributes" : { - "POSITION" : "accessor_1" + "POSITION" : "accessor_6" }, "mode" : 4, "indices" : "accessor_7" @@ -279,15 +279,5 @@ "node_0", "node_1", "node_2", "node_3", "node_4", "node_5", "node_6", "node_7" ] } - }, - "textures" : [ - { - "sampler" : 0, - "source" : 0 - }, - { - "sampler" : 0, - "source" : 1 - } - ] + } } diff --git a/test/models/glTF2/IncorrectVertexArrays/Cube.gltf b/test/models/glTF2/IncorrectVertexArrays/Cube.gltf index 51424e938..0ca17e1e5 100644 --- a/test/models/glTF2/IncorrectVertexArrays/Cube.gltf +++ b/test/models/glTF2/IncorrectVertexArrays/Cube.gltf @@ -204,7 +204,7 @@ "name" : "TruncatedIndexedCube", "primitives" : [ { "attributes" : { - "POSITION" : 1 + "POSITION" : 6 }, "mode" : 4, "indices" : 7 @@ -282,15 +282,5 @@ 0, 1, 2, 3, 4, 5, 6, 7 ] } - ], - "textures" : [ - { - "sampler" : 0, - "source" : 0 - }, - { - "sampler" : 0, - "source" : 1 - } ] } diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 829d31451..6925098b9 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -382,6 +382,29 @@ TEST_F(utglTF2ImportExport, import_cameras) { EXPECT_NE(nullptr, scene); } +TEST_F(utglTF2ImportExport, incorrect_vertex_arrays) { + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/IncorrectVertexArrays/Cube.gltf", + aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 12u); + EXPECT_EQ(scene->mMeshes[1]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[1]->mNumFaces, 11u); + EXPECT_EQ(scene->mMeshes[2]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[2]->mNumFaces, 18u); + EXPECT_EQ(scene->mMeshes[3]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[3]->mNumFaces, 17u); + EXPECT_EQ(scene->mMeshes[4]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[4]->mNumFaces, 12u); + EXPECT_EQ(scene->mMeshes[5]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[5]->mNumFaces, 11u); + EXPECT_EQ(scene->mMeshes[6]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[6]->mNumFaces, 18u); + EXPECT_EQ(scene->mMeshes[7]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[7]->mNumFaces, 17u); +} + #ifndef ASSIMP_BUILD_NO_EXPORT TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { EXPECT_TRUE( exporterTest() ); diff --git a/test/unit/utglTFImportExport.cpp b/test/unit/utglTFImportExport.cpp index 562cb05b9..90f0758bb 100644 --- a/test/unit/utglTFImportExport.cpp +++ b/test/unit/utglTFImportExport.cpp @@ -46,6 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + using namespace Assimp; class utglTFImportExport : public AbstractImportExportBase { @@ -60,3 +62,26 @@ public: TEST_F( utglTFImportExport, importglTFFromFileTest ) { EXPECT_TRUE( importerTest() ); } + +TEST_F(utglTFImportExport, incorrect_vertex_arrays) { + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF/IncorrectVertexArrays/Cube_v1.gltf", + aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 12u); + EXPECT_EQ(scene->mMeshes[1]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[1]->mNumFaces, 11u); + EXPECT_EQ(scene->mMeshes[2]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[2]->mNumFaces, 18u); + EXPECT_EQ(scene->mMeshes[3]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[3]->mNumFaces, 17u); + EXPECT_EQ(scene->mMeshes[4]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[4]->mNumFaces, 12u); + EXPECT_EQ(scene->mMeshes[5]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[5]->mNumFaces, 11u); + EXPECT_EQ(scene->mMeshes[6]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[6]->mNumFaces, 18u); + EXPECT_EQ(scene->mMeshes[7]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[7]->mNumFaces, 17u); +} From f8bdb77de1e3d260b037c9bcda3cd7095ec9be81 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 8 Oct 2019 14:27:00 +0100 Subject: [PATCH 014/170] Remove unneeded file --- .vscode/launch.json | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 7047f4581..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "(Windows) Launch", - "type": "cppvsdbg", - "request": "launch", - "program": "${workspaceFolder}/build/tools/assimp_cmd/assimpd.exe", - "args": ["export", "f:\\Test\\MarbleCube\\MarbleCube\\SimpleTexturedDirectx11\\Models\\MarbleCube\\Cube.gltf", "foo.fbx"], - "stopAtEntry": false, - "cwd": "${workspaceFolder}/build/tools/assimp_cmd", - "environment": [], - "externalConsole": false - } - ] -} \ No newline at end of file From 3b3e34c36a49ddd94b50c5635b7892d004198f59 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 8 Oct 2019 15:15:16 +0100 Subject: [PATCH 015/170] Fix one byte memory leak. --- code/glTF/glTFImporter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index 3a521554f..9ec13ea69 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -170,6 +170,8 @@ void glTFImporter::ImportMaterials(glTF::Asset& r) { if (mScene->mNumMaterials == 0) { mScene->mNumMaterials = 1; + // Delete the array of length zero created above. + delete[] mScene->mMaterials; mScene->mMaterials = new aiMaterial*[1]; mScene->mMaterials[0] = new aiMaterial(); } From 059ee0e091f1c658c20202a9123bdf90fc7fa307 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Fri, 11 Oct 2019 16:28:14 +0100 Subject: [PATCH 016/170] Update assimp legal and version Will now report the major and minor versions specified in cmakelists --- code/Common/Version.cpp | 14 +++++--------- test/unit/utVersion.cpp | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/code/Common/Version.cpp b/code/Common/Version.cpp index 868cfb06a..cf1da7d5b 100644 --- a/code/Common/Version.cpp +++ b/code/Common/Version.cpp @@ -46,8 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "ScenePrivate.h" -static const unsigned int MajorVersion = 5; -static const unsigned int MinorVersion = 0; +#include "revision.h" // -------------------------------------------------------------------------------- // Legal information string - don't remove this. @@ -56,9 +55,9 @@ static const char* LEGAL_INFORMATION = "Open Asset Import Library (Assimp).\n" "A free C/C++ library to import various 3D file formats into applications\n\n" -"(c) 2008-2017, assimp team\n" +"(c) 2006-2019, assimp team\n" "License under the terms and conditions of the 3-clause BSD license\n" -"http://assimp.sourceforge.net\n" +"http://assimp.org\n" ; // ------------------------------------------------------------------------------------------------ @@ -70,13 +69,13 @@ ASSIMP_API const char* aiGetLegalString () { // ------------------------------------------------------------------------------------------------ // Get Assimp minor version ASSIMP_API unsigned int aiGetVersionMinor () { - return MinorVersion; + return VER_MINOR; } // ------------------------------------------------------------------------------------------------ // Get Assimp major version ASSIMP_API unsigned int aiGetVersionMajor () { - return MajorVersion; + return VER_MAJOR; } // ------------------------------------------------------------------------------------------------ @@ -104,9 +103,6 @@ ASSIMP_API unsigned int aiGetCompileFlags () { return flags; } -// include current build revision, which is even updated from time to time -- :-) -#include "revision.h" - // ------------------------------------------------------------------------------------------------ ASSIMP_API unsigned int aiGetVersionRevision() { return GitVersion; diff --git a/test/unit/utVersion.cpp b/test/unit/utVersion.cpp index 233b2fb0b..66e832baa 100644 --- a/test/unit/utVersion.cpp +++ b/test/unit/utVersion.cpp @@ -48,7 +48,7 @@ TEST_F( utVersion, aiGetLegalStringTest ) { EXPECT_NE( lv, nullptr ); std::string text( lv ); - size_t pos( text.find( std::string( "2017" ) ) ); + size_t pos( text.find( std::string( "2019" ) ) ); EXPECT_NE( pos, std::string::npos ); } From ce5c71d2e7d993823c674aa71f05b33d281a4e00 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Fri, 11 Oct 2019 18:57:38 +0100 Subject: [PATCH 017/170] Collada ZAE import must convert manifest and image paths Moved ConvertPath into ColladaParser and use it when reading all filenames from the XML Added more EXPECTS to the Collada tests --- code/Collada/ColladaHelper.h | 2 +- code/Collada/ColladaLoader.cpp | 56 ++--------------------- code/Collada/ColladaLoader.h | 5 +-- code/Collada/ColladaParser.cpp | 69 +++++++++++++++++++++++++++-- code/Collada/ColladaParser.h | 5 ++- test/unit/utColladaImportExport.cpp | 27 ++++++++++- 6 files changed, 100 insertions(+), 64 deletions(-) diff --git a/code/Collada/ColladaHelper.h b/code/Collada/ColladaHelper.h index 66cff2d20..b7d47da15 100644 --- a/code/Collada/ColladaHelper.h +++ b/code/Collada/ColladaHelper.h @@ -583,7 +583,7 @@ struct Image /** Embedded image data */ std::vector mImageData; - /** File format hint ofembedded image data */ + /** File format hint of embedded image data */ std::string mEmbeddedFormat; }; diff --git a/code/Collada/ColladaLoader.cpp b/code/Collada/ColladaLoader.cpp index 0fbc7d599..8327142bf 100644 --- a/code/Collada/ColladaLoader.cpp +++ b/code/Collada/ColladaLoader.cpp @@ -1735,6 +1735,7 @@ void ColladaLoader::BuildMaterials(ColladaParser& pParser, aiScene* /*pScene*/) // ------------------------------------------------------------------------------------------------ // Resolves the texture name for the given effect texture entry +// and loads the texture data aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParser, const Collada::Effect& pEffect, const std::string& pName) { @@ -1762,7 +1763,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse //set default texture file name result.Set(name + ".jpg"); - ConvertPath(result); + ColladaParser::ConvertPath(result); return result; } @@ -1781,7 +1782,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse // setup format hint - if (imIt->second.mEmbeddedFormat.length() > 3) { + if (imIt->second.mEmbeddedFormat.length() >= HINTMAXTEXTURELEN) { ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters"); } strncpy(tex->achFormatHint, imIt->second.mEmbeddedFormat.c_str(), 3); @@ -1802,61 +1803,10 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse } result.Set(imIt->second.mFileName); - ConvertPath(result); } return result; } -// ------------------------------------------------------------------------------------------------ -// Convert a path read from a collada file to the usual representation -void ColladaLoader::ConvertPath(aiString& ss) -{ - // TODO: collada spec, p 22. Handle URI correctly. - // For the moment we're just stripping the file:// away to make it work. - // Windows doesn't seem to be able to find stuff like - // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg' - if (0 == strncmp(ss.data, "file://", 7)) - { - ss.length -= 7; - memmove(ss.data, ss.data + 7, ss.length); - ss.data[ss.length] = '\0'; - } - - // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes... - // I need to filter it without destroying linux paths starting with "/somewhere" -#if defined( _MSC_VER ) - if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { -#else - if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') { -#endif - --ss.length; - ::memmove(ss.data, ss.data + 1, ss.length); - ss.data[ss.length] = 0; - } - - // find and convert all %xy special chars - char* out = ss.data; - for (const char* it = ss.data; it != ss.data + ss.length; /**/) - { - if (*it == '%' && (it + 3) < ss.data + ss.length) - { - // separate the number to avoid dragging in chars from behind into the parsing - char mychar[3] = { it[1], it[2], 0 }; - size_t nbr = strtoul16(mychar); - it += 3; - *out++ = (char)(nbr & 0xFF); - } - else - { - *out++ = *it++; - } - } - - // adjust length and terminator of the shortened string - *out = 0; - ss.length = (ptrdiff_t)(out - ss.data); -} - // ------------------------------------------------------------------------------------------------ // Reads a float value from an accessor and its data array. ai_real ColladaLoader::ReadFloat(const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const diff --git a/code/Collada/ColladaLoader.h b/code/Collada/ColladaLoader.h index dce46e06f..d8d3f4f52 100644 --- a/code/Collada/ColladaLoader.h +++ b/code/Collada/ColladaLoader.h @@ -94,7 +94,7 @@ public: public: /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override; + bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override; protected: /** Return importer meta information. @@ -184,9 +184,6 @@ protected: aiString FindFilenameForEffectTexture( const ColladaParser& pParser, const Collada::Effect& pEffect, const std::string& pName); - /** Converts a path read from a collada file to the usual representation */ - void ConvertPath( aiString& ss); - /** Reads a float value from an accessor and its data array. * @param pAccessor The accessor to use for reading * @param pData The data array to read from diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index 646ec473d..f80ed1417 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -183,13 +183,66 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) { if (filepath == nullptr) return std::string(); - return std::string(filepath); + aiString ai_str(filepath); + ConvertPath(ai_str); + + return std::string(ai_str.C_Str()); } } } return std::string(); } +// ------------------------------------------------------------------------------------------------ +// Convert a path read from a collada file to the usual representation +void ColladaParser::ConvertPath(aiString& ss) +{ + // TODO: collada spec, p 22. Handle URI correctly. + // For the moment we're just stripping the file:// away to make it work. + // Windows doesn't seem to be able to find stuff like + // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg' + if (0 == strncmp(ss.data, "file://", 7)) + { + ss.length -= 7; + memmove(ss.data, ss.data + 7, ss.length); + ss.data[ss.length] = '\0'; + } + + // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes... + // I need to filter it without destroying linux paths starting with "/somewhere" +#if defined( _MSC_VER ) + if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { +#else + if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') { +#endif + --ss.length; + ::memmove(ss.data, ss.data + 1, ss.length); + ss.data[ss.length] = 0; + } + + // find and convert all %xy special chars + char* out = ss.data; + for (const char* it = ss.data; it != ss.data + ss.length; /**/) + { + if (*it == '%' && (it + 3) < ss.data + ss.length) + { + // separate the number to avoid dragging in chars from behind into the parsing + char mychar[3] = { it[1], it[2], 0 }; + size_t nbr = strtoul16(mychar); + it += 3; + *out++ = (char)(nbr & 0xFF); + } + else + { + *out++ = *it++; + } + } + + // adjust length and terminator of the shortened string + *out = 0; + ss.length = (ptrdiff_t)(out - ss.data); +} + // ------------------------------------------------------------------------------------------------ // Read bool from text contents of current element bool ColladaParser::ReadBoolFromTextContent() @@ -1120,7 +1173,12 @@ void ColladaParser::ReadImage(Collada::Image& pImage) if (!mReader->isEmptyElement()) { // element content is filename - hopefully const char* sz = TestTextContent(); - if (sz)pImage.mFileName = sz; + if (sz) + { + aiString filepath(sz); + ConvertPath(filepath); + pImage.mFileName = filepath.C_Str(); + } TestClosing("init_from"); } if (!pImage.mFileName.length()) { @@ -1153,7 +1211,12 @@ void ColladaParser::ReadImage(Collada::Image& pImage) { // element content is filename - hopefully const char* sz = TestTextContent(); - if (sz)pImage.mFileName = sz; + if (sz) + { + aiString filepath(sz); + ConvertPath(filepath); + pImage.mFileName = filepath.C_Str(); + } TestClosing("ref"); } else if (IsElement("hex") && !pImage.mFileName.length()) diff --git a/code/Collada/ColladaParser.h b/code/Collada/ColladaParser.h index a2c9a4ff2..2c4adaead 100644 --- a/code/Collada/ColladaParser.h +++ b/code/Collada/ColladaParser.h @@ -66,12 +66,15 @@ namespace Assimp { friend class ColladaLoader; + /** Converts a path read from a collada file to the usual representation */ + static void ConvertPath(aiString& ss); + protected: /** Map for generic metadata as aiString */ typedef std::map StringMetaData; /** Constructor from XML file */ - ColladaParser( IOSystem* pIOHandler, const std::string& pFile); + ColladaParser(IOSystem* pIOHandler, const std::string& pFile); /** Destructor */ ~ColladaParser(); diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index 1a2a6bc9d..8a413d52b 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include +#include #include using namespace Assimp; @@ -53,7 +54,18 @@ public: virtual bool importerTest() { Assimp::Importer importer; const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure ); - return nullptr != scene; + if (scene == nullptr) + return false; + + // Expected number of items + EXPECT_EQ(scene->mNumMeshes, 1); + EXPECT_EQ(scene->mNumMaterials, 1); + EXPECT_EQ(scene->mNumAnimations, 0); + EXPECT_EQ(scene->mNumTextures, 0); + EXPECT_EQ(scene->mNumLights, 1); + EXPECT_EQ(scene->mNumCameras, 1); + + return true; } }; @@ -66,7 +78,18 @@ public: virtual bool importerTest() { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure); - return nullptr != scene; + if (scene == nullptr) + return false; + + // Expected number of items + EXPECT_EQ(scene->mNumMeshes, 1); + EXPECT_EQ(scene->mNumMaterials, 1); + EXPECT_EQ(scene->mNumAnimations, 0); + EXPECT_EQ(scene->mNumTextures, 1); + EXPECT_EQ(scene->mNumLights, 1); + EXPECT_EQ(scene->mNumCameras, 1); + + return true; } }; From 6a6ccc0fb0d537f9bbafd841428afe908773767d Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 14 Oct 2019 11:27:34 +0100 Subject: [PATCH 018/170] Rename ConvertPath() to UriDecodePath() --- code/Collada/ColladaLoader.cpp | 2 +- code/Collada/ColladaParser.cpp | 8 ++++---- code/Collada/ColladaParser.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/Collada/ColladaLoader.cpp b/code/Collada/ColladaLoader.cpp index 8327142bf..37529bc98 100644 --- a/code/Collada/ColladaLoader.cpp +++ b/code/Collada/ColladaLoader.cpp @@ -1763,7 +1763,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser& pParse //set default texture file name result.Set(name + ".jpg"); - ColladaParser::ConvertPath(result); + ColladaParser::UriDecodePath(result); return result; } diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index f80ed1417..4eece8327 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -184,7 +184,7 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) { return std::string(); aiString ai_str(filepath); - ConvertPath(ai_str); + UriDecodePath(ai_str); return std::string(ai_str.C_Str()); } @@ -195,7 +195,7 @@ std::string ColladaParser::ReadZaeManifest(ZipArchiveIOSystem &zip_archive) { // ------------------------------------------------------------------------------------------------ // Convert a path read from a collada file to the usual representation -void ColladaParser::ConvertPath(aiString& ss) +void ColladaParser::UriDecodePath(aiString& ss) { // TODO: collada spec, p 22. Handle URI correctly. // For the moment we're just stripping the file:// away to make it work. @@ -1176,7 +1176,7 @@ void ColladaParser::ReadImage(Collada::Image& pImage) if (sz) { aiString filepath(sz); - ConvertPath(filepath); + UriDecodePath(filepath); pImage.mFileName = filepath.C_Str(); } TestClosing("init_from"); @@ -1214,7 +1214,7 @@ void ColladaParser::ReadImage(Collada::Image& pImage) if (sz) { aiString filepath(sz); - ConvertPath(filepath); + UriDecodePath(filepath); pImage.mFileName = filepath.C_Str(); } TestClosing("ref"); diff --git a/code/Collada/ColladaParser.h b/code/Collada/ColladaParser.h index 2c4adaead..4e8c8fccf 100644 --- a/code/Collada/ColladaParser.h +++ b/code/Collada/ColladaParser.h @@ -67,7 +67,7 @@ namespace Assimp friend class ColladaLoader; /** Converts a path read from a collada file to the usual representation */ - static void ConvertPath(aiString& ss); + static void UriDecodePath(aiString& ss); protected: /** Map for generic metadata as aiString */ From d371a113fa4d9bb7815db347fcb4bfa70b019352 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 14 Oct 2019 12:10:47 +0100 Subject: [PATCH 019/170] /DEBUG:FULL is not a compiler flag --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcafb649f..c4d8cf4e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,7 +253,7 @@ ELSEIF(MSVC) IF(MSVC12) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() - SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /DEBUG:FULL /Zi") + SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /Zi") ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) IF(NOT HUNTER_ENABLED) SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}") From 198bc428fafff40cf3814d1a771173f8f19bcf91 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 14 Oct 2019 12:15:02 +0100 Subject: [PATCH 020/170] Fix some warnings in Collada import --- code/Collada/ColladaParser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index 4eece8327..1a7b96189 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -240,7 +240,8 @@ void ColladaParser::UriDecodePath(aiString& ss) // adjust length and terminator of the shortened string *out = 0; - ss.length = (ptrdiff_t)(out - ss.data); + ai_assert(out > ss.data); + ss.length = static_cast(out - ss.data); } // ------------------------------------------------------------------------------------------------ @@ -3119,7 +3120,7 @@ void ColladaParser::ReadMaterialVertexInputBinding(Collada::SemanticMappingTable } } -void Assimp::ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem& zip_archive) +void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem& zip_archive) { // Attempt to load any undefined Collada::Image in ImageLibrary for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) { From f4bd11279fbae18b1151dfc4b4c25c9cca9ddb04 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 14 Oct 2019 12:25:42 +0100 Subject: [PATCH 021/170] Update Collada ZAE tests to include encoded URIs --- test/models/Collada/duck.zae | Bin 132801 -> 132811 bytes test/unit/utColladaImportExport.cpp | 41 ++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/test/models/Collada/duck.zae b/test/models/Collada/duck.zae index 97823535522cba8aee8db7b75b0e99bcc39c3d73..7e6748cb0092e498298802d23d1d7608bb474b04 100644 GIT binary patch delta 100935 zcmV)6K*+zrjR?z)2!BvZ0|XQR000O8!(vWP_#8sCV}=0$kXHl%3;+NCWOZX}AbMeC zE@WY4w7qMuUB{88`Q3p3!-g6&m;ve>uDoYf$!fUmsu|DthLXFxs=o*{bz~7mkt&k1 zt;YQL$>)hY6y=Mo#`L(*O`UyNd#$`gyz#~xkstoYKYsDz_J8|_*KeM`dikRd(*5

fN^6#HK`NJRnaR2Ppix*EneR}`u_3xhK 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 wtseB-q9*h9l$0_RW_DhTTqTyJ|i8 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 delta 100924 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 diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index 8a413d52b..f07f9a274 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -53,7 +53,7 @@ class utColladaImportExport : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure ); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure); if (scene == nullptr) return false; @@ -76,18 +76,35 @@ TEST_F(utColladaImportExport, importBlenFromFileTest) { class utColladaZaeImportExport : public AbstractImportExportBase { public: virtual bool importerTest() { - Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure); - if (scene == nullptr) - return false; + { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.zae", aiProcess_ValidateDataStructure); + if (scene == nullptr) + return false; - // Expected number of items - EXPECT_EQ(scene->mNumMeshes, 1); - EXPECT_EQ(scene->mNumMaterials, 1); - EXPECT_EQ(scene->mNumAnimations, 0); - EXPECT_EQ(scene->mNumTextures, 1); - EXPECT_EQ(scene->mNumLights, 1); - EXPECT_EQ(scene->mNumCameras, 1); + // Expected number of items + EXPECT_EQ(scene->mNumMeshes, 1); + EXPECT_EQ(scene->mNumMaterials, 1); + EXPECT_EQ(scene->mNumAnimations, 0); + EXPECT_EQ(scene->mNumTextures, 1); + EXPECT_EQ(scene->mNumLights, 1); + EXPECT_EQ(scene->mNumCameras, 1); + } + + { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck_nomanifest.zae", aiProcess_ValidateDataStructure); + if (scene == nullptr) + return false; + + // Expected number of items + EXPECT_EQ(scene->mNumMeshes, 1); + EXPECT_EQ(scene->mNumMaterials, 1); + EXPECT_EQ(scene->mNumAnimations, 0); + EXPECT_EQ(scene->mNumTextures, 1); + EXPECT_EQ(scene->mNumLights, 1); + EXPECT_EQ(scene->mNumCameras, 1); + } return true; } From 17eb292d73e817d49a51b3e98a5cedbfdd923fdc Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 14 Oct 2019 14:49:57 +0100 Subject: [PATCH 022/170] Tests: Fix signed/unsigned warnings --- test/unit/utColladaImportExport.cpp | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index f07f9a274..8bce3a3dd 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -58,12 +58,12 @@ public: return false; // Expected number of items - EXPECT_EQ(scene->mNumMeshes, 1); - EXPECT_EQ(scene->mNumMaterials, 1); - EXPECT_EQ(scene->mNumAnimations, 0); - EXPECT_EQ(scene->mNumTextures, 0); - EXPECT_EQ(scene->mNumLights, 1); - EXPECT_EQ(scene->mNumCameras, 1); + EXPECT_EQ(scene->mNumMeshes, 1u); + EXPECT_EQ(scene->mNumMaterials, 1u); + EXPECT_EQ(scene->mNumAnimations, 0u); + EXPECT_EQ(scene->mNumTextures, 0u); + EXPECT_EQ(scene->mNumLights, 1u); + EXPECT_EQ(scene->mNumCameras, 1u); return true; } @@ -83,12 +83,12 @@ public: return false; // Expected number of items - EXPECT_EQ(scene->mNumMeshes, 1); - EXPECT_EQ(scene->mNumMaterials, 1); - EXPECT_EQ(scene->mNumAnimations, 0); - EXPECT_EQ(scene->mNumTextures, 1); - EXPECT_EQ(scene->mNumLights, 1); - EXPECT_EQ(scene->mNumCameras, 1); + EXPECT_EQ(scene->mNumMeshes, 1u); + EXPECT_EQ(scene->mNumMaterials, 1u); + EXPECT_EQ(scene->mNumAnimations, 0u); + EXPECT_EQ(scene->mNumTextures, 1u); + EXPECT_EQ(scene->mNumLights, 1u); + EXPECT_EQ(scene->mNumCameras, 1u); } { @@ -98,12 +98,12 @@ public: return false; // Expected number of items - EXPECT_EQ(scene->mNumMeshes, 1); - EXPECT_EQ(scene->mNumMaterials, 1); - EXPECT_EQ(scene->mNumAnimations, 0); - EXPECT_EQ(scene->mNumTextures, 1); - EXPECT_EQ(scene->mNumLights, 1); - EXPECT_EQ(scene->mNumCameras, 1); + EXPECT_EQ(scene->mNumMeshes, 1u); + EXPECT_EQ(scene->mNumMaterials, 1u); + EXPECT_EQ(scene->mNumAnimations, 0u); + EXPECT_EQ(scene->mNumTextures, 1u); + EXPECT_EQ(scene->mNumLights, 1u); + EXPECT_EQ(scene->mNumCameras, 1u); } return true; From e6a051d953351927d29cec580badbb96ce7d15f2 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Wed, 16 Oct 2019 19:06:57 +1100 Subject: [PATCH 023/170] Fix compilation on VS2013 due to compiler bug with brace initialisers. This fixes issue #2678. --- code/Common/BaseImporter.cpp | 15 ++++++++++++++- include/assimp/BaseImporter.h | 15 ++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index b77bbfe23..5c1e60554 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -67,7 +67,20 @@ using namespace Assimp; // Constructor to be privately used by Importer BaseImporter::BaseImporter() AI_NO_EXCEPT : m_progress() { - // nothing to do here + /** + * Assimp Importer + * unit conversions available + * if you need another measurment unit add it below. + * it's currently defined in assimp that we prefer meters. + * + * NOTE: Initialised here rather than in the header file + * to workaround a VS2013 bug with brace initialisers + * */ + importerUnits[ImporterUnits::M] = 1.0; + importerUnits[ImporterUnits::CM] = 0.01; + importerUnits[ImporterUnits::MM] = 0.001; + importerUnits[ImporterUnits::INCHES] = 0.0254; + importerUnits[ImporterUnits::FEET] = 0.3048; } // ------------------------------------------------------------------------------------------------ diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index bd0451be3..ad8a3dafd 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -196,16 +196,13 @@ public: /** * Assimp Importer * unit conversions available - * if you need another measurment unit add it below. - * it's currently defined in assimp that we prefer meters. + * NOTE: Valid options are initialised in the + * constructor in the implementation file to + * work around a VS2013 compiler bug if support + * for that compiler is dropped in the future + * initialisation can be moved back here * */ - std::map importerUnits = { - {ImporterUnits::M, 1}, - {ImporterUnits::CM, 0.01}, - {ImporterUnits::MM, 0.001}, - {ImporterUnits::INCHES, 0.0254}, - {ImporterUnits::FEET, 0.3048} - }; + std::map importerUnits; virtual void SetApplicationUnits( const ImporterUnits& unit ) { From 9aa9238e7e97e702c7dd152598449e1518692d5b Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Fri, 18 Oct 2019 14:40:41 +1100 Subject: [PATCH 024/170] Copy texture data before handing on to asset which then handles freeing of the memory. This prevents the memory being released twice which was throwing an error. Fixes issue #2714. --- code/glTF2/glTF2Exporter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index 4724c2ef4..dc0b76443 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -320,7 +320,9 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe if (path[0] == '*') { // embedded aiTexture* tex = mScene->mTextures[atoi(&path[1])]; - uint8_t* data = reinterpret_cast(tex->pcData); + // copy data since lifetime control is handed over to the asset + uint8_t* data = new uint8_t[tex->mWidth]; + memcpy(data, tex->pcData, tex->mWidth); texture->source->SetData(data, tex->mWidth, *mAsset); if (tex->achFormatHint[0]) { From fa1dc3b8f1603622d33ba3010b9ed5962e8f39c4 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 18 Oct 2019 13:02:32 -0700 Subject: [PATCH 025/170] Fix CMake import Using CMake 3.15 & Visual Studio 2019 to build on windows produced a cmake configuration which was unable to be used by clients. Investigating this I was eventually able to determine this was caused by a mismatch in the target properties. Specifically, it was setting the TYPE property to STATIC_LIBRARY even though it was building as a SHARED_LIBRARY. This in turn was because the if clause on line `if(@BUILD_SHARED_LIBS@)` of this file was evaluating to `if (ON)` which was then not properly evaluated while under the CMake 2.6 policy. Explicitly setting the `CMP0012` policy to NEW fixes the problem. --- assimpTargets.cmake.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assimpTargets.cmake.in b/assimpTargets.cmake.in index ab1a8d2c7..afef9cbd1 100644 --- a/assimpTargets.cmake.in +++ b/assimpTargets.cmake.in @@ -5,6 +5,9 @@ if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) endif() cmake_policy(PUSH) cmake_policy(VERSION 2.6) +# Required for the evaluation of "if(@BUILD_SHARED_LIBS@)" below to function +cmake_policy(SET CMP0012 NEW) + #---------------------------------------------------------------- # Generated CMake target import file. #---------------------------------------------------------------- From c350d4f487308ba02ccf559bfab4521b9ff690b0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 19 Oct 2019 12:08:57 +0200 Subject: [PATCH 026/170] Update ColladaExporter.cpp Small review findings. --- code/Collada/ColladaExporter.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index c366fa72e..a93dfa59a 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -94,28 +94,29 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p // ------------------------------------------------------------------------------------------------ // Encodes a string into a valid XML ID using the xsd:ID schema qualifications. -const std::string XMLIDEncode(const std::string& name) -{ +static const std::string XMLIDEncode(const std::string& name) { const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-."; const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char); - if (name.length() == 0) + if (name.length() == 0) { return name; + } std::stringstream idEncoded; // xsd:ID must start with letter or underscore - if (!((name[0] >= 'A' && name[0] <= 'z') || name[0] == '_')) + if (!((name[0] >= 'A' && name[0] <= 'z') || name[0] == '_')) { idEncoded << '_'; + } - for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) - { + for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) { // xsd:ID can only contain letters, digits, underscores, hyphens and periods - if (strchr(XML_ID_CHARS, *it) != nullptr) + if (strchr(XML_ID_CHARS, *it) != nullptr) { idEncoded << *it; - else - // Select placeholder character based on invalid character to prevent name collisions + } else { + // Select placeholder character based on invalid character to prevent name collisions idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT]; + } } return idEncoded.str(); From 31e885a47ae59c161e2d8faebb3568d9b4b98f79 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Oct 2019 20:24:23 +0200 Subject: [PATCH 027/170] Update appveyor.yml Reenable VS2013 --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index df16431bd..39525f59d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,6 +14,7 @@ matrix: fast_finish: true image: + - Visual Studio 2013 - Visual Studio 2015 - Visual Studio 2017 - Visual Studio 2019 From 41ab019cbf14137f2105c46c47adf49011f9bb2b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 23 Oct 2019 22:42:19 +0200 Subject: [PATCH 028/170] Update appveyor.yml Add missing cmake build target. --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 39525f59d..fa0a125f0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,11 +30,13 @@ install: - set PATH=C:\Ruby24-x64\bin;%PATH% - set CMAKE_DEFINES -DASSIMP_WERROR=ON - if [%COMPILER%]==[MinGW] set PATH=C:\MinGW\bin;%PATH% + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013 - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" set CMAKE_GENERATOR_NAME=Visual Studio 16 2019 - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" -A %platform% . - # Rename sh.exe as sh.exe in PATH interferes with MinGW + # Rename sh.exe as sh.exe in PATH interferes with MinGW - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 + - rename "C:\Program Files\Git\usr\bin\sh.exe" "sh2.exe" - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5" - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe From 822be33408533b4f861d69dbc9aa9abd6c237f45 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Fri, 25 Oct 2019 12:17:43 +1100 Subject: [PATCH 029/170] Move pbrSG glossinessFactor into the correct material extension object. Fixes issue #2724. --- code/glTF2/glTF2AssetWriter.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2AssetWriter.inl b/code/glTF2/glTF2AssetWriter.inl index 5d1b22064..b3148f798 100644 --- a/code/glTF2/glTF2AssetWriter.inl +++ b/code/glTF2/glTF2AssetWriter.inl @@ -358,7 +358,7 @@ namespace glTF2 { WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); if (pbrSG.glossinessFactor != 1) { - WriteFloat(obj, pbrSG.glossinessFactor, "glossinessFactor", w.mAl); + WriteFloat(pbrSpecularGlossiness, pbrSG.glossinessFactor, "glossinessFactor", w.mAl); } WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl); From cbd4e8bc220b1c79bed6aa788c758a69853b0376 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Fri, 25 Oct 2019 12:19:28 +1100 Subject: [PATCH 030/170] Fix inconsistent indentation in previous commit. --- code/glTF2/glTF2AssetWriter.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2AssetWriter.inl b/code/glTF2/glTF2AssetWriter.inl index b3148f798..44a1d3e73 100644 --- a/code/glTF2/glTF2AssetWriter.inl +++ b/code/glTF2/glTF2AssetWriter.inl @@ -358,7 +358,7 @@ namespace glTF2 { WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); if (pbrSG.glossinessFactor != 1) { - WriteFloat(pbrSpecularGlossiness, pbrSG.glossinessFactor, "glossinessFactor", w.mAl); + WriteFloat(pbrSpecularGlossiness, pbrSG.glossinessFactor, "glossinessFactor", w.mAl); } WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl); From 5f58ef82b93c7f6fd9c0c08c3f8d739db0a29047 Mon Sep 17 00:00:00 2001 From: Rem Date: Fri, 25 Oct 2019 10:18:27 +0300 Subject: [PATCH 031/170] prevent accidental lower casing material names in ReplaceDefaultMaterial --- code/3DS/3DSConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/3DS/3DSConverter.cpp b/code/3DS/3DSConverter.cpp index 2176b75fc..3c3da36a3 100644 --- a/code/3DS/3DSConverter.cpp +++ b/code/3DS/3DSConverter.cpp @@ -72,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() unsigned int idx( NotSet ); for (unsigned int i = 0; i < mScene->mMaterials.size();++i) { - std::string &s = mScene->mMaterials[i].mName; + std::string s = mScene->mMaterials[i].mName; for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) { *it = static_cast< char >( ::tolower( *it ) ); } From 2d086fd23627289fc5fecf87ffd0ecb22640be86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20D=C3=BCmig?= Date: Fri, 25 Oct 2019 15:10:54 +0200 Subject: [PATCH 032/170] ColladaParser: fix handling of empty XML-elements --- code/Collada/ColladaParser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index 646ec473d..fc7ab8c2f 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -3236,6 +3236,10 @@ void ColladaParser::TestOpening(const char* pName) // Tests for the closing tag of the given element, throws an exception if not found void ColladaParser::TestClosing(const char* pName) { + // check if we have an empty (self-closing) element + if (mReader->isEmptyElement()) + return; + // check if we're already on the closing tag and return right away if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp(mReader->getNodeName(), pName) == 0) return; From 5baff40edc754efbf0c98120aa08cf1d67b771a6 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Wed, 2 Oct 2019 19:44:30 +0100 Subject: [PATCH 033/170] Git ignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 9dcb6623d..65a54aaeb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,10 @@ build .project *.kdev4* +# build artefacts +*.o +*.a + # Visual Studio *.sln *.ncb From b5f659c98d86c82ff29ff4c4a8faf92271ff9618 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Wed, 2 Oct 2019 19:44:58 +0100 Subject: [PATCH 034/170] Added clang format --- .clang-format | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..eba6d586f --- /dev/null +++ b/.clang-format @@ -0,0 +1,127 @@ +# Commented out parameters are those with the same value as base LLVM style +# We can uncomment them if we want to change their value, or enforce the +# chosen value in case the base style changes (last sync: Clang 6.0.1). +--- +### General config, applies to all languages ### +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +# AlignEscapedNewlines: Right +# AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +# AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: true +# AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +# AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +# BinPackArguments: true +# BinPackParameters: true +# BraceWrapping: +# AfterClass: false +# AfterControlStatement: false +# AfterEnum: false +# AfterFunction: false +# AfterNamespace: false +# AfterObjCDeclaration: false +# AfterStruct: false +# AfterUnion: false +# AfterExternBlock: false +# BeforeCatch: false +# BeforeElse: false +# IndentBraces: false +# SplitEmptyFunction: true +# SplitEmptyRecord: true +# SplitEmptyNamespace: true +# BreakBeforeBinaryOperators: None +# BreakBeforeBraces: Attach +# BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +# BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +# BreakStringLiterals: true +ColumnLimit: 0 +# CommentPragmas: '^ IWYU pragma:' +# CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# FixNamespaceComments: true +# ForEachMacros: +# - foreach +# - Q_FOREACH +# - BOOST_FOREACH +# IncludeBlocks: Preserve +IncludeCategories: + - Regex: '".*"' + Priority: 1 + - Regex: '^<.*\.h>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 +# IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +# IndentPPDirectives: None +IndentWidth: 4 +# IndentWrappedFunctionNames: false +# JavaScriptQuotes: Leave +# JavaScriptWrapImports: true +# KeepEmptyLinesAtTheStartOfBlocks: true +# MacroBlockBegin: '' +# MacroBlockEnd: '' +# MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# PenaltyBreakAssignment: 2 +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +# PointerAlignment: Right +# RawStringFormats: +# - Delimiter: pb +# Language: TextProto +# BasedOnStyle: google +# ReflowComments: true +# SortIncludes: true +# SortUsingDeclarations: true +# SpaceAfterCStyleCast: false +# SpaceAfterTemplateKeyword: true +# SpaceBeforeAssignmentOperators: true +# SpaceBeforeParens: ControlStatements +# SpaceInEmptyParentheses: false +# SpacesBeforeTrailingComments: 1 +# SpacesInAngles: false +# SpacesInContainerLiterals: true +# SpacesInCStyleCastParentheses: false +# SpacesInParentheses: false +# SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Always +--- +### C++ specific config ### +Language: Cpp +Standard: Cpp11 +--- +### ObjC specific config ### +Language: ObjC +Standard: Cpp11 +ObjCBlockIndentWidth: 4 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +--- +### Java specific config ### +Language: Java +# BreakAfterJavaFieldAnnotations: false +... From 168ae22ad4dc3f079b4efff7d77be02b1f1b99c5 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sat, 26 Oct 2019 16:28:51 +0100 Subject: [PATCH 035/170] Implemented easy armature lookup This lets you directly retrieve the node a bone links to and informs you of the armature directly This also fixes a bug with bone name being made unique which causes them to become not 1:1 what the modeller has imported. --- code/FBX/FBXConverter.cpp | 458 +++++++++++++++++++++++++++++--------- code/FBX/FBXConverter.h | 69 ++++-- code/FBX/FBXImporter.cpp | 194 ++++++++-------- include/assimp/mesh.h | 19 +- 4 files changed, 515 insertions(+), 225 deletions(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index b8601a2a5..f8225f2e5 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -68,7 +68,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include +#include namespace Assimp { namespace FBX { @@ -120,6 +121,46 @@ namespace Assimp { ConvertGlobalSettings(); TransferDataToScene(); + // Now convert all bone positions to the correct mOffsetMatrix + std::vector bones; + std::vector nodes; + std::map bone_stack; + BuildBoneList(out->mRootNode, out->mRootNode, out, bones); + BuildNodeList(out->mRootNode, nodes ); + + + BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); + + std::cout << "Bone stack size: " << bone_stack.size() << std::endl; + + for( std::pair kvp : bone_stack ) + { + aiBone *bone = kvp.first; + aiNode *bone_node = kvp.second; + std::cout << "active node lookup: " << bone->mName.C_Str() << std::endl; + // lcl transform grab - done in generate_nodes :) + + //bone->mOffsetMatrix = bone_node->mTransformation; + aiNode * armature = GetArmatureRoot(bone_node, bones); + + ai_assert(armature); + + // set up bone armature id + bone->mArmature = armature; + + // set this bone node to be referenced properly + ai_assert(bone_node); + bone->mNode = bone_node; + + // apply full hierarchy to transform for basic offset + while( bone_node->mParent ) + { + bone->mRestMatrix = bone_node->mTransformation * bone->mRestMatrix; + bone_node = bone_node->mParent; + } + } + + // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE // to make sure the scene passes assimp's validation. FBX files // need not contain geometry (i.e. camera animations, raw armatures). @@ -138,6 +179,167 @@ namespace Assimp { std::for_each(textures.begin(), textures.end(), Util::delete_fun()); } + /* Returns the armature root node */ + /* This is required to be detected for a bone initially, it will recurse up until it cannot find another + * bone and return the node + * No known failure points. (yet) + */ + aiNode * FBXConverter::GetArmatureRoot(aiNode *bone_node, std::vector &bone_list) + { + while(bone_node) + { + if(!IsBoneNode(bone_node->mName, bone_list)) + { + std::cout << "Found valid armature: " << bone_node->mName.C_Str() << std::endl; + return bone_node; + } + + bone_node = bone_node->mParent; + } + + std::cout << "can't find armature! node: " << bone_node << std::endl; + + return NULL; + } + + /* Simple IsBoneNode check if this could be a bone */ + bool FBXConverter::IsBoneNode(const aiString &bone_name, std::vector& bones ) + { + for( aiBone *bone : bones) + { + if(bone->mName == bone_name) + { + return true; + } + } + + return false; + } + + + /* Pop this node by name from the stack if found */ + /* Used in multiple armature situations with duplicate node / bone names */ + /* Known flaw: cannot have nodes with bone names, will be fixed in later release */ + /* (serious to be fixed) Known flaw: nodes which have more than one bone could be prematurely dropped from stack */ + aiNode* FBXConverter::GetNodeFromStack(const aiString &node_name, std::vector &nodes) + { + std::vector::iterator iter; + aiNode *found = NULL; + for( iter = nodes.begin(); iter < nodes.end(); ++iter ) + { + aiNode *element = *iter; + ai_assert(element); + // node valid and node name matches + if(element->mName == node_name) + { + found = element; + break; + } + } + + if(found != NULL) { + // now pop the element from the node list + nodes.erase(iter); + + return found; + } + return NULL; + } + + /* Prepare flat node list which can be used for non recursive lookups later */ + void FBXConverter::BuildNodeList(aiNode *current_node, std::vector &nodes) + { + assert(current_node); + + for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) + { + aiNode *child = current_node->mChildren[nodeId]; + assert(child); + + nodes.push_back(child); + + BuildNodeList(child, nodes); + } + } + + /* Reprocess all nodes to calculate bone transforms properly based on the REAL mOffsetMatrix not the local. */ + /* Before this would use mesh transforms which is wrong for bone transforms */ + /* Before this would work for simple character skeletons but not complex meshes with multiple origins */ + /* Source: sketch fab log cutter fbx */ + void FBXConverter::BuildBoneList(aiNode *current_node, const aiNode * root_node, const aiScene *scene, std::vector &bones ) + { + assert(scene); + for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) + { + aiNode *child = current_node->mChildren[nodeId]; + assert(child); + + // check for bones + for( unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) + { + assert(child->mMeshes); + unsigned int mesh_index = child->mMeshes[meshId]; + aiMesh *mesh = scene->mMeshes[ mesh_index ]; + assert(mesh); + + for( unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) + { + aiBone *bone = mesh->mBones[boneId]; + ai_assert(bone); + + // duplicate meshes exist with the same bones sometimes :) + // so this must be detected + if( std::find(bones.begin(), bones.end(), bone) == bones.end() ) + { + // add the element once + bones.push_back(bone); + } + } + + // find mesh and get bones + // then do recursive lookup for bones in root node hierarchy + } + + BuildBoneList(child, root_node, scene, bones); + } + } + + /* A bone stack allows us to have multiple armatures, with the same bone names + * A bone stack allows us also to retrieve bones true transform even with duplicate names :) + */ + void FBXConverter::BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene, + const std::vector &bones, + std::map &bone_stack, + std::vector &node_stack ) + { + ai_assert(scene); + ai_assert(root_node); + ai_assert(!node_stack.empty()); + + for( aiBone * bone : bones) + { + ai_assert(bone); + aiNode* node = GetNodeFromStack(bone->mName, node_stack); + if(node == NULL) + { + node_stack.clear(); + BuildNodeList(out->mRootNode, node_stack ); + std::cout << "Resetting bone stack: null element " << bone->mName.C_Str() << std::endl; + + node = GetNodeFromStack(bone->mName, node_stack); + + if(!node) { + std::cout << "serious import issue armature failed to be detected?" << std::endl; + continue; + } + } + + std::cout << "Successfully added bone to stack and have valid armature: " << bone->mName.C_Str() << std::endl; + + bone_stack.insert(std::pair(bone, node)); + } + } + void FBXConverter::ConvertRootNode() { out->mRootNode = new aiNode(); std::string unique_name; @@ -145,7 +347,7 @@ namespace Assimp { out->mRootNode->mName.Set(unique_name); // root has ID 0 - ConvertNodes(0L, *out->mRootNode); + ConvertNodes(0L, out->mRootNode, out->mRootNode); } static std::string getAncestorBaseName(const aiNode* node) @@ -179,8 +381,11 @@ namespace Assimp { GetUniqueName(original_name, unique_name); return unique_name; } - - void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) { + /// todo: pre-build node hierarchy + /// todo: get bone from stack + /// todo: make map of aiBone* to aiNode* + /// then update convert clusters to the new format + void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) { const std::vector& conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); std::vector nodes; @@ -191,62 +396,69 @@ namespace Assimp { try { for (const Connection* con : conns) { - // ignore object-property links if (con->PropertyName().length()) { - continue; + // really important we document why this is ignored. + FBXImporter::LogInfo("ignoring property link - no docs on why this is ignored"); + continue; //? } + // convert connection source object into Object base class const Object* const object = con->SourceObject(); if (nullptr == object) { - FBXImporter::LogWarn("failed to convert source object for Model link"); + FBXImporter::LogError("failed to convert source object for Model link"); continue; } + // FBX Model::Cube, Model::Bone001, etc elements + // This detects if we can cast the object into this model structure. const Model* const model = dynamic_cast(object); if (nullptr != model) { nodes_chain.clear(); post_nodes_chain.clear(); - aiMatrix4x4 new_abs_transform = parent_transform; - - std::string unique_name = MakeUniqueNodeName(model, parent); - + aiMatrix4x4 new_abs_transform = parent->mTransformation; + std::string node_name = FixNodeName(model->Name()); // even though there is only a single input node, the design of // assimp (or rather: the complicated transformation chain that // is employed by fbx) means that we may need multiple aiNode's // to represent a fbx node's transformation. - const bool need_additional_node = GenerateTransformationNodeChain(*model, unique_name, nodes_chain, post_nodes_chain); + + // generate node transforms - this includes pivot data + // if need_additional_node is true then you t + const bool need_additional_node = GenerateTransformationNodeChain(*model, node_name, nodes_chain, post_nodes_chain); + + // assert that for the current node we must have at least a single transform ai_assert(nodes_chain.size()); if (need_additional_node) { - nodes_chain.push_back(new aiNode(unique_name)); + nodes_chain.push_back(new aiNode(node_name)); } //setup metadata on newest node SetupNodeMetadata(*model, *nodes_chain.back()); // link all nodes in a row - aiNode* last_parent = &parent; - for (aiNode* prenode : nodes_chain) { - ai_assert(prenode); + aiNode* last_parent = parent; + for (aiNode* child : nodes_chain) { + ai_assert(child); - if (last_parent != &parent) { + if (last_parent != parent) { last_parent->mNumChildren = 1; last_parent->mChildren = new aiNode*[1]; - last_parent->mChildren[0] = prenode; + last_parent->mChildren[0] = child; } - prenode->mParent = last_parent; - last_parent = prenode; + child->mParent = last_parent; + last_parent = child; - new_abs_transform *= prenode->mTransformation; + new_abs_transform *= child->mTransformation; } // attach geometry - ConvertModel(*model, *nodes_chain.back(), new_abs_transform); + ConvertModel(*model, nodes_chain.back(), root_node, new_abs_transform); // check if there will be any child nodes const std::vector& child_conns @@ -258,7 +470,7 @@ namespace Assimp { for (aiNode* postnode : post_nodes_chain) { ai_assert(postnode); - if (last_parent != &parent) { + if (last_parent != parent) { last_parent->mNumChildren = 1; last_parent->mChildren = new aiNode*[1]; last_parent->mChildren[0] = postnode; @@ -280,15 +492,15 @@ namespace Assimp { ); } - // attach sub-nodes (if any) - ConvertNodes(model->ID(), *last_parent, new_abs_transform); + // recursion call - child nodes + ConvertNodes(model->ID(), last_parent, root_node); if (doc.Settings().readLights) { - ConvertLights(*model, unique_name); + ConvertLights(*model, node_name); } if (doc.Settings().readCameras) { - ConvertCameras(*model, unique_name); + ConvertCameras(*model, node_name); } nodes.push_back(nodes_chain.front()); @@ -297,10 +509,10 @@ namespace Assimp { } if (nodes.size()) { - parent.mChildren = new aiNode*[nodes.size()](); - parent.mNumChildren = static_cast(nodes.size()); + parent->mChildren = new aiNode*[nodes.size()](); + parent->mNumChildren = static_cast(nodes.size()); - std::swap_ranges(nodes.begin(), nodes.end(), parent.mChildren); + std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren); } } catch (std::exception&) { @@ -803,7 +1015,7 @@ namespace Assimp { // is_complex needs to be consistent with NeedsComplexTransformationChain() // or the interplay between this code and the animation converter would // not be guaranteed. - ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0)); + //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0)); // now, if we have more than just Translation, Scaling and Rotation, // we need to generate a full node chain to accommodate for assimp's @@ -905,7 +1117,8 @@ namespace Assimp { } } - void FBXConverter::ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform) + void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { const std::vector& geos = model.GetGeometry(); @@ -917,11 +1130,12 @@ namespace Assimp { const MeshGeometry* const mesh = dynamic_cast(geo); const LineGeometry* const line = dynamic_cast(geo); if (mesh) { - const std::vector& indices = ConvertMesh(*mesh, model, node_global_transform, nd); + const std::vector& indices = ConvertMesh(*mesh, model, parent, root_node, + absolute_transform); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); } else if (line) { - const std::vector& indices = ConvertLine(*line, model, node_global_transform, nd); + const std::vector& indices = ConvertLine(*line, model, parent, root_node); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); } else { @@ -930,15 +1144,16 @@ namespace Assimp { } if (meshes.size()) { - nd.mMeshes = new unsigned int[meshes.size()](); - nd.mNumMeshes = static_cast(meshes.size()); + parent->mMeshes = new unsigned int[meshes.size()](); + parent->mNumMeshes = static_cast(meshes.size()); - std::swap_ranges(meshes.begin(), meshes.end(), nd.mMeshes); + std::swap_ranges(meshes.begin(), meshes.end(), parent->mMeshes); } } - std::vector FBXConverter::ConvertMesh(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + std::vector + FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { std::vector temp; @@ -962,18 +1177,18 @@ namespace Assimp { const MatIndexArray::value_type base = mindices[0]; for (MatIndexArray::value_type index : mindices) { if (index != base) { - return ConvertMeshMultiMaterial(mesh, model, node_global_transform, nd); + return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform); } } } // faster code-path, just copy the data - temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform, nd)); + temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node)); return temp; } std::vector FBXConverter::ConvertLine(const LineGeometry& line, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + aiNode *parent, aiNode *root_node) { std::vector temp; @@ -984,7 +1199,7 @@ namespace Assimp { return temp; } - aiMesh* const out_mesh = SetupEmptyMesh(line, nd); + aiMesh* const out_mesh = SetupEmptyMesh(line, root_node); out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; // copy vertices @@ -1019,7 +1234,7 @@ namespace Assimp { return temp; } - aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode& nd) + aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode *parent) { aiMesh* const out_mesh = new aiMesh(); meshes.push_back(out_mesh); @@ -1036,17 +1251,18 @@ namespace Assimp { } else { - out_mesh->mName = nd.mName; + out_mesh->mName = parent->mName; } return out_mesh; } - unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, + const aiMatrix4x4 &absolute_transform, aiNode *parent, + aiNode *root_node) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); - aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent); const std::vector& vertices = mesh.GetVertices(); const std::vector& faces = mesh.GetFaceIndexCounts(); @@ -1164,7 +1380,8 @@ namespace Assimp { } if (doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { - ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION); + ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, NO_MATERIAL_SEPARATION, + nullptr); } std::vector animMeshes; @@ -1209,8 +1426,10 @@ namespace Assimp { return static_cast(meshes.size() - 1); } - std::vector FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) + std::vector + FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, + aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { const MatIndexArray& mindices = mesh.GetMaterialIndices(); ai_assert(mindices.size()); @@ -1221,7 +1440,7 @@ namespace Assimp { for (MatIndexArray::value_type index : mindices) { if (had.find(index) == had.end()) { - indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform, nd)); + indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform)); had.insert(index); } } @@ -1229,12 +1448,12 @@ namespace Assimp { return indices; } - unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform, - aiNode& nd) + unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, + MatIndexArray::value_type index, + aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { - aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent); const MatIndexArray& mindices = mesh.GetMaterialIndices(); const std::vector& vertices = mesh.GetVertices(); @@ -1399,7 +1618,7 @@ namespace Assimp { ConvertMaterialForMesh(out_mesh, model, mesh, index); if (process_weights) { - ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping); + ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, index, &reverseMapping); } std::vector animMeshes; @@ -1449,10 +1668,10 @@ namespace Assimp { return static_cast(meshes.size() - 1); } - void FBXConverter::ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, - const aiMatrix4x4& node_global_transform, - unsigned int materialIndex, - std::vector* outputVertStartIndices) + void FBXConverter::ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, + const aiMatrix4x4 &absolute_transform, + aiNode *parent, aiNode *root_node, unsigned int materialIndex, + std::vector *outputVertStartIndices) { ai_assert(geo.DeformerSkin()); @@ -1463,13 +1682,12 @@ namespace Assimp { const Skin& sk = *geo.DeformerSkin(); std::vector bones; - bones.reserve(sk.Clusters().size()); const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; ai_assert(no_mat_check || outputVertStartIndices); try { - + // iterate over the sub deformers for (const Cluster* cluster : sk.Clusters()) { ai_assert(cluster); @@ -1483,6 +1701,7 @@ namespace Assimp { index_out_indices.clear(); out_indices.clear(); + // now check if *any* of these weights is contained in the output mesh, // taking notes so we don't need to do it twice. for (WeightIndexArray::value_type index : indices) { @@ -1520,68 +1739,107 @@ namespace Assimp { } } } - + // if we found at least one, generate the output bones // XXX this could be heavily simplified by collecting the bone // data in a single step. - ConvertCluster(bones, model, *cluster, out_indices, index_out_indices, - count_out_indices, node_global_transform); + ConvertCluster(bones, cluster, out_indices, index_out_indices, + count_out_indices, absolute_transform, parent, root_node); } + + bone_map.clear(); } - catch (std::exception&) { + catch (std::exception&e) { std::for_each(bones.begin(), bones.end(), Util::delete_fun()); throw; } if (bones.empty()) { + out->mBones = nullptr; + out->mNumBones = 0; return; + } else { + out->mBones = new aiBone *[bones.size()](); + out->mNumBones = static_cast(bones.size()); + + std::swap_ranges(bones.begin(), bones.end(), out->mBones); } - - out->mBones = new aiBone*[bones.size()](); - out->mNumBones = static_cast(bones.size()); - - std::swap_ranges(bones.begin(), bones.end(), out->mBones); } - void FBXConverter::ConvertCluster(std::vector& bones, const Model& /*model*/, const Cluster& cl, - std::vector& out_indices, - std::vector& index_out_indices, - std::vector& count_out_indices, - const aiMatrix4x4& node_global_transform) + const aiNode* FBXConverter::GetNodeByName( const aiString& name, aiNode *current_node ) { + aiNode * iter = current_node; + //printf("Child count: %d", iter->mNumChildren); + return iter; + } - aiBone* const bone = new aiBone(); - bones.push_back(bone); + void FBXConverter::ConvertCluster(std::vector &local_mesh_bones, const Cluster *cl, + std::vector &out_indices, std::vector &index_out_indices, + std::vector &count_out_indices, const aiMatrix4x4 &absolute_transform, + aiNode *parent, aiNode *root_node) { + assert(cl); // make sure cluster valid + std::string deformer_name = cl->TargetNode()->Name(); + aiString bone_name = aiString(FixNodeName(deformer_name)); - bone->mName = FixNodeName(cl.TargetNode()->Name()); + aiBone *bone = NULL; - bone->mOffsetMatrix = cl.TransformLink(); - bone->mOffsetMatrix.Inverse(); + if (bone_map.count(deformer_name)) { + std::cout << "retrieved bone from lookup " << bone_name.C_Str() << ". Deformer: " << deformer_name + << std::endl; + bone = bone_map[deformer_name]; + } else { + std::cout << "created new bone " << bone_name.C_Str() << ". Deformer: " << deformer_name << std::endl; + bone = new aiBone(); + bone->mName = bone_name; - bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform; + // store local transform link for post processing + bone->mOffsetMatrix = cl->TransformLink(); + bone->mOffsetMatrix.Inverse(); - bone->mNumWeights = static_cast(out_indices.size()); - aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; + aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform; - const size_t no_index_sentinel = std::numeric_limits::max(); - const WeightArray& weights = cl.GetWeights(); + bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset - const size_t c = index_out_indices.size(); - for (size_t i = 0; i < c; ++i) { - const size_t index_index = index_out_indices[i]; - if (index_index == no_index_sentinel) { - continue; + // + // Now calculate the aiVertexWeights + // + + aiVertexWeight *cursor = nullptr; + + bone->mNumWeights = static_cast(out_indices.size()); + cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; + + const size_t no_index_sentinel = std::numeric_limits::max(); + const WeightArray& weights = cl->GetWeights(); + + const size_t c = index_out_indices.size(); + for (size_t i = 0; i < c; ++i) { + const size_t index_index = index_out_indices[i]; + + if (index_index == no_index_sentinel) { + continue; + } + + const size_t cc = count_out_indices[i]; + for (size_t j = 0; j < cc; ++j) { + // cursor runs from first element relative to the start + // or relative to the start of the next indexes. + aiVertexWeight& out_weight = *cursor++; + + out_weight.mVertexId = static_cast(out_indices[index_index + j]); + out_weight.mWeight = weights[i]; + } } - const size_t cc = count_out_indices[i]; - for (size_t j = 0; j < cc; ++j) { - aiVertexWeight& out_weight = *cursor++; - - out_weight.mVertexId = static_cast(out_indices[index_index + j]); - out_weight.mWeight = weights[i]; - } + bone_map.insert(std::pair(deformer_name, bone)); } + + std::cout << "bone research: Indicies size: " << out_indices.size() << std::endl; + + // lookup must be populated in case something goes wrong + // this also allocates bones to mesh instance outside + local_mesh_bones.push_back(bone); } void FBXConverter::ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo, diff --git a/code/FBX/FBXConverter.h b/code/FBX/FBXConverter.h index 77ced1950..619da92c1 100644 --- a/code/FBX/FBXConverter.h +++ b/code/FBX/FBXConverter.h @@ -123,7 +123,7 @@ private: // ------------------------------------------------------------------------------------------------ // collect and assign child nodes - void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4()); + void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node); // ------------------------------------------------------------------------------------------------ void ConvertLights(const Model& model, const std::string &orig_name ); @@ -179,32 +179,35 @@ private: void SetupNodeMetadata(const Model& model, aiNode& nd); // ------------------------------------------------------------------------------------------------ - void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform); + void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed - std::vector ConvertMesh(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + std::vector + ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ std::vector ConvertLine(const LineGeometry& line, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + aiNode *parent, aiNode *root_node); // ------------------------------------------------------------------------------------------------ - aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode& nd); + aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent); // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, + const aiMatrix4x4 &absolute_transform, aiNode *parent, + aiNode *root_node); // ------------------------------------------------------------------------------------------------ - std::vector ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd); + std::vector + ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform, aiNode& nd); + unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index, + aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform); // ------------------------------------------------------------------------------------------------ static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits::max() */ @@ -217,17 +220,17 @@ private: * - outputVertStartIndices is only used when a material index is specified, it gives for * each output vertex the DOM index it maps to. */ - void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, - const aiMatrix4x4& node_global_transform = aiMatrix4x4(), - unsigned int materialIndex = NO_MATERIAL_SEPARATION, - std::vector* outputVertStartIndices = NULL); - + void ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, + aiNode *parent = NULL, aiNode *root_node = NULL, + unsigned int materialIndex = NO_MATERIAL_SEPARATION, + std::vector *outputVertStartIndices = NULL); + // lookup + static const aiNode* GetNodeByName( const aiString& name, aiNode *current_node ); // ------------------------------------------------------------------------------------------------ - void ConvertCluster(std::vector& bones, const Model& /*model*/, const Cluster& cl, - std::vector& out_indices, - std::vector& index_out_indices, - std::vector& count_out_indices, - const aiMatrix4x4& node_global_transform); + void ConvertCluster(std::vector &local_mesh_bones, const Cluster *cl, + std::vector &out_indices, std::vector &index_out_indices, + std::vector &count_out_indices, const aiMatrix4x4 &absolute_transform, + aiNode *parent, aiNode *root_node); // ------------------------------------------------------------------------------------------------ void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo, @@ -452,10 +455,30 @@ private: using NodeNameCache = std::unordered_map; NodeNameCache mNodeNames; + // Deformer name is not the same as a bone name - it does contain the bone name though :) + // Deformer names in FBX are always unique in an FBX file. + std::map bone_map; + double anim_fps; aiScene* const out; const FBX::Document& doc; + + static void BuildBoneList(aiNode *current_node, const aiNode *root_node, const aiScene *scene, + std::vector& bones); + + void BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene, + const std::vector &bones, + std::map &bone_stack, + std::vector &node_stack ); + + static void BuildNodeList(aiNode *current_node, std::vector &nodes); + + static aiNode *GetNodeFromStack(const aiString &node_name, std::vector &nodes); + + static aiNode *GetArmatureRoot(aiNode *bone_node, std::vector &bone_list); + + static bool IsBoneNode(const aiString &bone_name, std::vector &bones); }; } diff --git a/code/FBX/FBXImporter.cpp b/code/FBX/FBXImporter.cpp index c8c1a6853..afcc1ddc7 100644 --- a/code/FBX/FBXImporter.cpp +++ b/code/FBX/FBXImporter.cpp @@ -48,26 +48,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXImporter.h" -#include "FBXTokenizer.h" -#include "FBXParser.h" -#include "FBXUtil.h" -#include "FBXDocument.h" #include "FBXConverter.h" +#include "FBXDocument.h" +#include "FBXParser.h" +#include "FBXTokenizer.h" +#include "FBXUtil.h" -#include #include -#include +#include #include +#include namespace Assimp { -template<> -const char* LogFunctions::Prefix() { - static auto prefix = "FBX: "; - return prefix; +template <> +const char *LogFunctions::Prefix() { + static auto prefix = "FBX: "; + return prefix; } -} +} // namespace Assimp using namespace Assimp; using namespace Assimp::Formatter; @@ -76,131 +76,123 @@ using namespace Assimp::FBX; namespace { static const aiImporterDesc desc = { - "Autodesk FBX Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "fbx" + "Autodesk FBX Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour, + 0, + 0, + 0, + 0, + "fbx" }; } // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by #Importer -FBXImporter::FBXImporter() -{ +FBXImporter::FBXImporter() { } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -FBXImporter::~FBXImporter() -{ +FBXImporter::~FBXImporter() { } // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string& extension = GetExtension(pFile); - if (extension == std::string( desc.mFileExtensions ) ) { - return true; - } +bool FBXImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { + const std::string &extension = GetExtension(pFile); + if (extension == std::string(desc.mFileExtensions)) { + return true; + } - else if ((!extension.length() || checkSig) && pIOHandler) { - // at least ASCII-FBX files usually have a 'FBX' somewhere in their head - const char* tokens[] = {"fbx"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; + else if ((!extension.length() || checkSig) && pIOHandler) { + // at least ASCII-FBX files usually have a 'FBX' somewhere in their head + const char *tokens[] = { "fbx" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); + } + return false; } // ------------------------------------------------------------------------------------------------ // List all extensions handled by this loader -const aiImporterDesc* FBXImporter::GetInfo () const -{ - return &desc; +const aiImporterDesc *FBXImporter::GetInfo() const { + return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties for the loader -void FBXImporter::SetupProperties(const Importer* pImp) -{ - settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true); - settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false); - settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true); - settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true); - settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true); - settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true); - settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true); - settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false); - settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true); - settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true); - settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); - settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); - settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); +void FBXImporter::SetupProperties(const Importer *pImp) { + settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true); + settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false); + settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true); + settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true); + settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true); + settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true); + settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true); + settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false); + settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true); + settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true); + settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); + settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); + settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - std::unique_ptr stream(pIOHandler->Open(pFile,"rb")); - if (!stream) { - ThrowException("Could not open file for reading"); - } +void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr stream(pIOHandler->Open(pFile, "rb")); + if (!stream) { + ThrowException("Could not open file for reading"); + } - // read entire file into memory - no streaming for this, fbx - // files can grow large, but the assimp output data structure - // then becomes very large, too. Assimp doesn't support - // streaming for its output data structures so the net win with - // streaming input data would be very low. - std::vector contents; - contents.resize(stream->FileSize()+1); - stream->Read( &*contents.begin(), 1, contents.size()-1 ); - contents[ contents.size() - 1 ] = 0; - const char* const begin = &*contents.begin(); + // read entire file into memory - no streaming for this, fbx + // files can grow large, but the assimp output data structure + // then becomes very large, too. Assimp doesn't support + // streaming for its output data structures so the net win with + // streaming input data would be very low. + std::vector contents; + contents.resize(stream->FileSize() + 1); + stream->Read(&*contents.begin(), 1, contents.size() - 1); + contents[contents.size() - 1] = 0; + const char *const begin = &*contents.begin(); - // broadphase tokenizing pass in which we identify the core - // syntax elements of FBX (brackets, commas, key:value mappings) - TokenList tokens; - try { + // broadphase tokenizing pass in which we identify the core + // syntax elements of FBX (brackets, commas, key:value mappings) + TokenList tokens; + try { - bool is_binary = false; - if (!strncmp(begin,"Kaydara FBX Binary",18)) { - is_binary = true; - TokenizeBinary(tokens,begin,contents.size()); - } - else { - Tokenize(tokens,begin); - } + bool is_binary = false; + if (!strncmp(begin, "Kaydara FBX Binary", 18)) { + is_binary = true; + TokenizeBinary(tokens, begin, contents.size()); + } else { + Tokenize(tokens, begin); + } - // use this information to construct a very rudimentary - // parse-tree representing the FBX scope structure - Parser parser(tokens, is_binary); + // use this information to construct a very rudimentary + // parse-tree representing the FBX scope structure + Parser parser(tokens, is_binary); - // take the raw parse-tree and convert it to a FBX DOM - Document doc(parser,settings); + // take the raw parse-tree and convert it to a FBX DOM + Document doc(parser, settings); - // convert the FBX DOM to aiScene - ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones); + // convert the FBX DOM to aiScene + ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones); - // size relative to cm - float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor(); + // size relative to cm + float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor(); - // Set FBX file scale is relative to CM must be converted to M for - // assimp universal format (M) - SetFileScale( size_relative_to_cm * 0.01f); + // Set FBX file scale is relative to CM must be converted to M for + // assimp universal format (M) + SetFileScale(size_relative_to_cm * 0.01f); - std::for_each(tokens.begin(),tokens.end(),Util::delete_fun()); - } - catch(std::exception&) { - std::for_each(tokens.begin(),tokens.end(),Util::delete_fun()); - throw; - } + std::for_each(tokens.begin(), tokens.end(), Util::delete_fun()); + } catch (std::exception &) { + std::for_each(tokens.begin(), tokens.end(), Util::delete_fun()); + throw; + } } #endif // !ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index eb30ad5df..e652a6927 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -252,6 +252,9 @@ struct aiVertexWeight { }; +// Forward declare aiNode (pointer use only) +struct aiNode; + // --------------------------------------------------------------------------- /** @brief A single bone of a mesh. * @@ -268,6 +271,12 @@ struct aiBone { //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS. unsigned int mNumWeights; + // The bone armature node - used for skeleton conversion + C_STRUCT aiNode* mArmature; + + // The bone node in the scene - used for skeleton conversion + C_STRUCT aiNode* mNode; + //! The influence weights of this bone, by vertex index. C_STRUCT aiVertexWeight* mWeights; @@ -284,6 +293,11 @@ struct aiBone { */ C_STRUCT aiMatrix4x4 mOffsetMatrix; + /** Matrix used for the global rest transform + * This tells you directly the rest without extending as required in most game engine implementations + * */ + C_STRUCT aiMatrix4x4 mRestMatrix; + #ifdef __cplusplus //! Default constructor @@ -773,7 +787,10 @@ struct aiMesh // DO NOT REMOVE THIS ADDITIONAL CHECK if (mNumBones && mBones) { for( unsigned int a = 0; a < mNumBones; a++) { - delete mBones[a]; + if(mBones[a]) + { + delete mBones[a]; + } } delete [] mBones; } From 6ea97a1282835ef43e25044a5053882bbf285d7a Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sat, 26 Oct 2019 17:27:07 +0100 Subject: [PATCH 036/170] Updated test cases to test import of names This now doesn't overwrite names anymore as this would cause nasty bugs application side. We can now support these by default without having to handle them as edge cases. --- test/unit/utFBXImporterExporter.cpp | 39 ++++++++--------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index 1445e3c3e..e73733a0d 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -76,6 +76,7 @@ TEST_F( utFBXImporterExporter, importBareBoxWithoutColorsAndTextureCoords ) { EXPECT_EQ(mesh->mNumVertices, 36u); } + TEST_F(utFBXImporterExporter, importCubesWithNoNames) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_nonames.fbx", aiProcess_ValidateDataStructure); @@ -86,26 +87,6 @@ TEST_F(utFBXImporterExporter, importCubesWithNoNames) { ASSERT_STREQ(root->mName.C_Str(), "RootNode"); ASSERT_TRUE(root->mChildren); ASSERT_EQ(root->mNumChildren, 2u); - - const auto child0 = root->mChildren[0]; - ASSERT_TRUE(child0); - ASSERT_STREQ(child0->mName.C_Str(), "RootNode001"); - ASSERT_TRUE(child0->mChildren); - ASSERT_EQ(child0->mNumChildren, 1u); - - const auto child00 = child0->mChildren[0]; - ASSERT_TRUE(child00); - ASSERT_STREQ(child00->mName.C_Str(), "RootNode001001"); - - const auto child1 = root->mChildren[1]; - ASSERT_TRUE(child1); - ASSERT_STREQ(child1->mName.C_Str(), "RootNode002"); - ASSERT_TRUE(child1->mChildren); - ASSERT_EQ(child1->mNumChildren, 1u); - - const auto child10 = child1->mChildren[0]; - ASSERT_TRUE(child10); - ASSERT_STREQ(child10->mName.C_Str(), "RootNode002001"); } TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) { @@ -137,7 +118,7 @@ TEST_F(utFBXImporterExporter, importCubesWithUnicodeDuplicatedNames) { const auto child10 = child1->mChildren[0]; ASSERT_TRUE(child10); - ASSERT_STREQ(child10->mName.C_Str(), "\xd0\x9a\xd1\x83\xd0\xb1\x31""001"); + ASSERT_STREQ(child10->mName.C_Str(), "\xd0\x9a\xd1\x83\xd0\xb1\x31"); } TEST_F(utFBXImporterExporter, importCubesComplexTransform) { @@ -168,14 +149,14 @@ TEST_F(utFBXImporterExporter, importCubesComplexTransform) { auto parent = child1; const size_t chain_length = 8u; const char* chainStr[chain_length] = { - "Cube1001_$AssimpFbx$_Translation", - "Cube1001_$AssimpFbx$_RotationPivot", - "Cube1001_$AssimpFbx$_RotationPivotInverse", - "Cube1001_$AssimpFbx$_ScalingOffset", - "Cube1001_$AssimpFbx$_ScalingPivot", - "Cube1001_$AssimpFbx$_Scaling", - "Cube1001_$AssimpFbx$_ScalingPivotInverse", - "Cube1001" + "Cube1_$AssimpFbx$_Translation", + "Cube1_$AssimpFbx$_RotationPivot", + "Cube1_$AssimpFbx$_RotationPivotInverse", + "Cube1_$AssimpFbx$_ScalingOffset", + "Cube1_$AssimpFbx$_ScalingPivot", + "Cube1_$AssimpFbx$_Scaling", + "Cube1_$AssimpFbx$_ScalingPivotInverse", + "Cube1" }; for (size_t i = 0; i < chain_length; ++i) { ASSERT_TRUE(parent->mChildren); From 93efe4197aff5f46358545dd6b890ca454e8bfcd Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sat, 26 Oct 2019 18:09:26 +0100 Subject: [PATCH 037/170] Removed redundant rest matrix and fixed assert compile error --- code/FBX/FBXConverter.cpp | 21 +++++++-------------- include/assimp/mesh.h | 5 ----- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index f8225f2e5..0d754a638 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -151,13 +151,6 @@ namespace Assimp { // set this bone node to be referenced properly ai_assert(bone_node); bone->mNode = bone_node; - - // apply full hierarchy to transform for basic offset - while( bone_node->mParent ) - { - bone->mRestMatrix = bone_node->mTransformation * bone->mRestMatrix; - bone_node = bone_node->mParent; - } } @@ -249,12 +242,12 @@ namespace Assimp { /* Prepare flat node list which can be used for non recursive lookups later */ void FBXConverter::BuildNodeList(aiNode *current_node, std::vector &nodes) { - assert(current_node); + ai_assert(current_node); for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { aiNode *child = current_node->mChildren[nodeId]; - assert(child); + ai_assert(child); nodes.push_back(child); @@ -268,19 +261,19 @@ namespace Assimp { /* Source: sketch fab log cutter fbx */ void FBXConverter::BuildBoneList(aiNode *current_node, const aiNode * root_node, const aiScene *scene, std::vector &bones ) { - assert(scene); + ai_assert(scene); for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { aiNode *child = current_node->mChildren[nodeId]; - assert(child); + ai_assert(child); // check for bones for( unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) { - assert(child->mMeshes); + ai_assert(child->mMeshes); unsigned int mesh_index = child->mMeshes[meshId]; aiMesh *mesh = scene->mMeshes[ mesh_index ]; - assert(mesh); + ai_assert(mesh); for( unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) { @@ -1777,7 +1770,7 @@ namespace Assimp { std::vector &out_indices, std::vector &index_out_indices, std::vector &count_out_indices, const aiMatrix4x4 &absolute_transform, aiNode *parent, aiNode *root_node) { - assert(cl); // make sure cluster valid + ai_assert(cl); // make sure cluster valid std::string deformer_name = cl->TargetNode()->Name(); aiString bone_name = aiString(FixNodeName(deformer_name)); diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index e652a6927..617835e51 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -293,11 +293,6 @@ struct aiBone { */ C_STRUCT aiMatrix4x4 mOffsetMatrix; - /** Matrix used for the global rest transform - * This tells you directly the rest without extending as required in most game engine implementations - * */ - C_STRUCT aiMatrix4x4 mRestMatrix; - #ifdef __cplusplus //! Default constructor From 46cdd81d754bb602dabd3a3a026607bc2759e37e Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sat, 26 Oct 2019 18:47:48 +0100 Subject: [PATCH 038/170] Added ArmaturePopulate scale process for all formats --- code/CMakeLists.txt | 2 + code/FBX/FBXConverter.cpp | 194 ------------------ code/PostProcessing/ArmaturePopulate.cpp | 247 +++++++++++++++++++++++ code/PostProcessing/ArmaturePopulate.h | 111 ++++++++++ include/assimp/postprocess.h | 12 ++ 5 files changed, 372 insertions(+), 194 deletions(-) create mode 100644 code/PostProcessing/ArmaturePopulate.cpp create mode 100644 code/PostProcessing/ArmaturePopulate.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index eec805b54..2c030abbb 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -670,6 +670,8 @@ SET( PostProcessing_SRCS PostProcessing/MakeVerboseFormat.h PostProcessing/ScaleProcess.cpp PostProcessing/ScaleProcess.h + PostProcessing/ArmaturePopulate.cpp + PostProcessing/ArmaturePopulate.h PostProcessing/GenBoundingBoxesProcess.cpp PostProcessing/GenBoundingBoxesProcess.h ) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 0d754a638..88abd6721 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -121,39 +121,6 @@ namespace Assimp { ConvertGlobalSettings(); TransferDataToScene(); - // Now convert all bone positions to the correct mOffsetMatrix - std::vector bones; - std::vector nodes; - std::map bone_stack; - BuildBoneList(out->mRootNode, out->mRootNode, out, bones); - BuildNodeList(out->mRootNode, nodes ); - - - BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); - - std::cout << "Bone stack size: " << bone_stack.size() << std::endl; - - for( std::pair kvp : bone_stack ) - { - aiBone *bone = kvp.first; - aiNode *bone_node = kvp.second; - std::cout << "active node lookup: " << bone->mName.C_Str() << std::endl; - // lcl transform grab - done in generate_nodes :) - - //bone->mOffsetMatrix = bone_node->mTransformation; - aiNode * armature = GetArmatureRoot(bone_node, bones); - - ai_assert(armature); - - // set up bone armature id - bone->mArmature = armature; - - // set this bone node to be referenced properly - ai_assert(bone_node); - bone->mNode = bone_node; - } - - // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE // to make sure the scene passes assimp's validation. FBX files // need not contain geometry (i.e. camera animations, raw armatures). @@ -172,167 +139,6 @@ namespace Assimp { std::for_each(textures.begin(), textures.end(), Util::delete_fun()); } - /* Returns the armature root node */ - /* This is required to be detected for a bone initially, it will recurse up until it cannot find another - * bone and return the node - * No known failure points. (yet) - */ - aiNode * FBXConverter::GetArmatureRoot(aiNode *bone_node, std::vector &bone_list) - { - while(bone_node) - { - if(!IsBoneNode(bone_node->mName, bone_list)) - { - std::cout << "Found valid armature: " << bone_node->mName.C_Str() << std::endl; - return bone_node; - } - - bone_node = bone_node->mParent; - } - - std::cout << "can't find armature! node: " << bone_node << std::endl; - - return NULL; - } - - /* Simple IsBoneNode check if this could be a bone */ - bool FBXConverter::IsBoneNode(const aiString &bone_name, std::vector& bones ) - { - for( aiBone *bone : bones) - { - if(bone->mName == bone_name) - { - return true; - } - } - - return false; - } - - - /* Pop this node by name from the stack if found */ - /* Used in multiple armature situations with duplicate node / bone names */ - /* Known flaw: cannot have nodes with bone names, will be fixed in later release */ - /* (serious to be fixed) Known flaw: nodes which have more than one bone could be prematurely dropped from stack */ - aiNode* FBXConverter::GetNodeFromStack(const aiString &node_name, std::vector &nodes) - { - std::vector::iterator iter; - aiNode *found = NULL; - for( iter = nodes.begin(); iter < nodes.end(); ++iter ) - { - aiNode *element = *iter; - ai_assert(element); - // node valid and node name matches - if(element->mName == node_name) - { - found = element; - break; - } - } - - if(found != NULL) { - // now pop the element from the node list - nodes.erase(iter); - - return found; - } - return NULL; - } - - /* Prepare flat node list which can be used for non recursive lookups later */ - void FBXConverter::BuildNodeList(aiNode *current_node, std::vector &nodes) - { - ai_assert(current_node); - - for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) - { - aiNode *child = current_node->mChildren[nodeId]; - ai_assert(child); - - nodes.push_back(child); - - BuildNodeList(child, nodes); - } - } - - /* Reprocess all nodes to calculate bone transforms properly based on the REAL mOffsetMatrix not the local. */ - /* Before this would use mesh transforms which is wrong for bone transforms */ - /* Before this would work for simple character skeletons but not complex meshes with multiple origins */ - /* Source: sketch fab log cutter fbx */ - void FBXConverter::BuildBoneList(aiNode *current_node, const aiNode * root_node, const aiScene *scene, std::vector &bones ) - { - ai_assert(scene); - for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) - { - aiNode *child = current_node->mChildren[nodeId]; - ai_assert(child); - - // check for bones - for( unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) - { - ai_assert(child->mMeshes); - unsigned int mesh_index = child->mMeshes[meshId]; - aiMesh *mesh = scene->mMeshes[ mesh_index ]; - ai_assert(mesh); - - for( unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) - { - aiBone *bone = mesh->mBones[boneId]; - ai_assert(bone); - - // duplicate meshes exist with the same bones sometimes :) - // so this must be detected - if( std::find(bones.begin(), bones.end(), bone) == bones.end() ) - { - // add the element once - bones.push_back(bone); - } - } - - // find mesh and get bones - // then do recursive lookup for bones in root node hierarchy - } - - BuildBoneList(child, root_node, scene, bones); - } - } - - /* A bone stack allows us to have multiple armatures, with the same bone names - * A bone stack allows us also to retrieve bones true transform even with duplicate names :) - */ - void FBXConverter::BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene, - const std::vector &bones, - std::map &bone_stack, - std::vector &node_stack ) - { - ai_assert(scene); - ai_assert(root_node); - ai_assert(!node_stack.empty()); - - for( aiBone * bone : bones) - { - ai_assert(bone); - aiNode* node = GetNodeFromStack(bone->mName, node_stack); - if(node == NULL) - { - node_stack.clear(); - BuildNodeList(out->mRootNode, node_stack ); - std::cout << "Resetting bone stack: null element " << bone->mName.C_Str() << std::endl; - - node = GetNodeFromStack(bone->mName, node_stack); - - if(!node) { - std::cout << "serious import issue armature failed to be detected?" << std::endl; - continue; - } - } - - std::cout << "Successfully added bone to stack and have valid armature: " << bone->mName.C_Str() << std::endl; - - bone_stack.insert(std::pair(bone, node)); - } - } - void FBXConverter::ConvertRootNode() { out->mRootNode = new aiNode(); std::string unique_name; diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp new file mode 100644 index 000000000..1892645a9 --- /dev/null +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -0,0 +1,247 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#include "ArmaturePopulate.h" + +#include +#include +#include +#include + +namespace Assimp { + +bool ArmaturePopulate::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_PopulateArmatureData) != 0; +} + +void ArmaturePopulate::SetupProperties(const Importer *pImp) { + // do nothing +} + +void ArmaturePopulate::Execute(aiScene *out) { + + // Now convert all bone positions to the correct mOffsetMatrix + std::vector bones; + std::vector nodes; + std::map bone_stack; + BuildBoneList(out->mRootNode, out->mRootNode, out, bones); + BuildNodeList(out->mRootNode, nodes); + + BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); + + ASSIMP_LOG_DEBUG_F("Bone stack size: %ld\n", bone_stack.size()); + + for (std::pair kvp : bone_stack) { + aiBone *bone = kvp.first; + aiNode *bone_node = kvp.second; + ASSIMP_LOG_DEBUG_F("active node lookup: %s\n", bone->mName.C_Str()); + // lcl transform grab - done in generate_nodes :) + + // bone->mOffsetMatrix = bone_node->mTransformation; + aiNode *armature = GetArmatureRoot(bone_node, bones); + + ai_assert(armature); + + // set up bone armature id + bone->mArmature = armature; + + // set this bone node to be referenced properly + ai_assert(bone_node); + bone->mNode = bone_node; + } +} + +/* Returns the armature root node */ +/* This is required to be detected for a bone initially, it will recurse up + * until it cannot find another bone and return the node No known failure + * points. (yet) + */ +aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, + std::vector &bone_list) { + while (bone_node) { + if (!IsBoneNode(bone_node->mName, bone_list)) { + ASSIMP_LOG_DEBUG_F("Found valid armature: %s\n", bone_node->mName.C_Str()); + return bone_node; + } + + bone_node = bone_node->mParent; + } + + ASSIMP_LOG_WARN_F("can't find armature! node: %s\n", bone_node->mName.C_Str()); + + return NULL; +} + +/* Simple IsBoneNode check if this could be a bone */ +bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, + std::vector &bones) { + for (aiBone *bone : bones) { + if (bone->mName == bone_name) { + return true; + } + } + + return false; +} + +/* Pop this node by name from the stack if found */ +/* Used in multiple armature situations with duplicate node / bone names */ +/* Known flaw: cannot have nodes with bone names, will be fixed in later release + */ +/* (serious to be fixed) Known flaw: nodes which have more than one bone could + * be prematurely dropped from stack */ +aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, + std::vector &nodes) { + std::vector::iterator iter; + aiNode *found = NULL; + for (iter = nodes.begin(); iter < nodes.end(); ++iter) { + aiNode *element = *iter; + ai_assert(element); + // node valid and node name matches + if (element->mName == node_name) { + found = element; + break; + } + } + + if (found != NULL) { + // now pop the element from the node list + nodes.erase(iter); + + return found; + } + return NULL; +} + +/* Prepare flat node list which can be used for non recursive lookups later */ +void ArmaturePopulate::BuildNodeList(const aiNode *current_node, + std::vector &nodes) { + ai_assert(current_node); + + for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { + aiNode *child = current_node->mChildren[nodeId]; + ai_assert(child); + + nodes.push_back(child); + + BuildNodeList(child, nodes); + } +} + +/* Reprocess all nodes to calculate bone transforms properly based on the REAL + * mOffsetMatrix not the local. */ +/* Before this would use mesh transforms which is wrong for bone transforms */ +/* Before this would work for simple character skeletons but not complex meshes + * with multiple origins */ +/* Source: sketch fab log cutter fbx */ +void ArmaturePopulate::BuildBoneList(aiNode *current_node, + const aiNode *root_node, + const aiScene *scene, + std::vector &bones) { + ai_assert(scene); + for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { + aiNode *child = current_node->mChildren[nodeId]; + ai_assert(child); + + // check for bones + for (unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) { + ai_assert(child->mMeshes); + unsigned int mesh_index = child->mMeshes[meshId]; + aiMesh *mesh = scene->mMeshes[mesh_index]; + ai_assert(mesh); + + for (unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) { + aiBone *bone = mesh->mBones[boneId]; + ai_assert(bone); + + // duplicate meshes exist with the same bones sometimes :) + // so this must be detected + if (std::find(bones.begin(), bones.end(), bone) == bones.end()) { + // add the element once + bones.push_back(bone); + } + } + + // find mesh and get bones + // then do recursive lookup for bones in root node hierarchy + } + + BuildBoneList(child, root_node, scene, bones); + } +} + +/* A bone stack allows us to have multiple armatures, with the same bone names + * A bone stack allows us also to retrieve bones true transform even with + * duplicate names :) + */ +void ArmaturePopulate::BuildBoneStack(aiNode *current_node, + const aiNode *root_node, + const aiScene *scene, + const std::vector &bones, + std::map &bone_stack, + std::vector &node_stack) { + ai_assert(scene); + ai_assert(root_node); + ai_assert(!node_stack.empty()); + + for (aiBone *bone : bones) { + ai_assert(bone); + aiNode *node = GetNodeFromStack(bone->mName, node_stack); + if (node == NULL) { + node_stack.clear(); + BuildNodeList(root_node, node_stack); + ASSIMP_LOG_DEBUG_F("Resetting bone stack: null element %s\n", bone->mName.C_Str()); + + node = GetNodeFromStack(bone->mName, node_stack); + + if (!node) { + ASSIMP_LOG_ERROR("serious import issue armature failed to be detected"); + continue; + } + } + + ASSIMP_LOG_DEBUG_F("Successfully added bone to stack and have valid armature: %s\n", bone->mName.C_Str()); + + bone_stack.insert(std::pair(bone, node)); + } +} + +} // Namespace Assimp diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h new file mode 100644 index 000000000..d84fbe09b --- /dev/null +++ b/code/PostProcessing/ArmaturePopulate.h @@ -0,0 +1,111 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef SCALE_PROCESS_H_ +#define SCALE_PROCESS_H_ + +#include "Common/BaseProcess.h" +#include +#include + +struct aiNode; +struct aiBone; + +#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT) +# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f +#endif // !! AI_DEBONE_THRESHOLD + +namespace Assimp { + +// --------------------------------------------------------------------------- +/** ScaleProcess: Class to rescale the whole model. + * Now rescales animations, bones, and blend shapes properly. + * Please note this will not write to 'scale' transform it will rewrite mesh + * and matrixes so that your scale values + * from your model package are preserved, so this is completely intentional + * bugs should be reported as soon as they are found. +*/ +class ASSIMP_API ArmaturePopulate : public BaseProcess { +public: + /// The default class constructor. + ArmaturePopulate() : BaseProcess() + {} + + /// The class destructor. + virtual ~ArmaturePopulate() + {} + + /// Overwritten, @see BaseProcess + virtual bool IsActive( unsigned int pFlags ) const; + + /// Overwritten, @see BaseProcess + virtual void SetupProperties( const Importer* pImp ); + + /// Overwritten, @see BaseProcess + virtual void Execute( aiScene* pScene ); + + static aiNode *GetArmatureRoot(aiNode *bone_node, + std::vector &bone_list); + + static bool IsBoneNode(const aiString &bone_name, + std::vector &bones); + + static aiNode *GetNodeFromStack(const aiString &node_name, + std::vector &nodes); + + static void BuildNodeList(const aiNode *current_node, + std::vector &nodes); + + static void BuildBoneList(aiNode *current_node, const aiNode *root_node, + const aiScene *scene, + std::vector &bones); + + static void BuildBoneStack(aiNode *current_node, const aiNode *root_node, + const aiScene *scene, + const std::vector &bones, + std::map &bone_stack, + std::vector &node_stack); +}; + +} // Namespace Assimp + + +#endif // SCALE_PROCESS_H_ \ No newline at end of file diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index 77d387c7e..2af48aedd 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -537,6 +537,18 @@ enum aiPostProcessSteps */ aiProcess_Debone = 0x4000000, + + // ------------------------------------------------------------------------- + /** + * This step generically populates aiBone->mArmature and aiBone->mNode generically + * The point of these is it saves you later having to calculate these elements + * This is useful when handling rest information or skin information + * If you have multiple armatures on your models we strongly recommend enabling this + * Instead of writing your own multi-root, multi-armature lookups we have done the + * hard work for you :) + */ + aiProcess_PopulateArmatureData = 0x5000000, + // ------------------------------------------------------------------------- /**


This step will perform a global scale of the model. * From 514257f58700385c15d23b27c11a7240cd433550 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sat, 26 Oct 2019 19:48:34 +0100 Subject: [PATCH 039/170] Added unit tests for ArmaturePopulate when used (added huestos model to tests) Added clear documentation for this too to explain, you need to enable it to make it available Signed-off-by: RevoluPowered --- code/Common/PostStepRegistry.cpp | 7 ++ code/PostProcessing/ArmaturePopulate.cpp | 14 +++- code/PostProcessing/ArmaturePopulate.h | 16 ++--- include/assimp/mesh.h | 4 ++ test/CMakeLists.txt | 1 + test/models/FBX/huesitos.fbx | Bin 0 -> 111564 bytes test/unit/utArmaturePopulate.cpp | 82 +++++++++++++++++++++++ 7 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 test/models/FBX/huesitos.fbx create mode 100644 test/unit/utArmaturePopulate.cpp diff --git a/code/Common/PostStepRegistry.cpp b/code/Common/PostStepRegistry.cpp index ef58f8ddf..8ff4af040 100644 --- a/code/Common/PostStepRegistry.cpp +++ b/code/Common/PostStepRegistry.cpp @@ -131,11 +131,15 @@ corresponding preprocessor flag to selectively disable steps. #if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) # include "PostProcessing/ScaleProcess.h" #endif +#if (!defined ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS) +# include "PostProcessing/ArmaturePopulate.h" +#endif #if (!defined ASSIMP_BUILD_NO_GENBOUNDINGBOXES_PROCESS) # include "PostProcessing/GenBoundingBoxesProcess.h" #endif + namespace Assimp { // ------------------------------------------------------------------------------------------------ @@ -180,6 +184,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) out.push_back( new ScaleProcess()); #endif +#if (!defined ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS) + out.push_back( new ArmaturePopulate()); +#endif #if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS) out.push_back( new PretransformVertices()); #endif diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 1892645a9..11fffc399 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -48,6 +48,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { +/// The default class constructor. +ArmaturePopulate::ArmaturePopulate() : BaseProcess() +{} + +/// The class destructor. +ArmaturePopulate::~ArmaturePopulate() +{} + bool ArmaturePopulate::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_PopulateArmatureData) != 0; } @@ -104,9 +112,9 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, bone_node = bone_node->mParent; } - - ASSIMP_LOG_WARN_F("can't find armature! node: %s\n", bone_node->mName.C_Str()); - + + ASSIMP_LOG_WARN("GetArmatureRoot() can't find armature!"); + return NULL; } diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h index d84fbe09b..30bfc7509 100644 --- a/code/PostProcessing/ArmaturePopulate.h +++ b/code/PostProcessing/ArmaturePopulate.h @@ -39,20 +39,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -#ifndef SCALE_PROCESS_H_ -#define SCALE_PROCESS_H_ +#ifndef ARMATURE_POPULATE_H_ +#define ARMATURE_POPULATE_H_ #include "Common/BaseProcess.h" +#include #include #include + struct aiNode; struct aiBone; -#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT) -# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f -#endif // !! AI_DEBONE_THRESHOLD - namespace Assimp { // --------------------------------------------------------------------------- @@ -66,12 +64,10 @@ namespace Assimp { class ASSIMP_API ArmaturePopulate : public BaseProcess { public: /// The default class constructor. - ArmaturePopulate() : BaseProcess() - {} + ArmaturePopulate(); /// The class destructor. - virtual ~ArmaturePopulate() - {} + virtual ~ArmaturePopulate(); /// Overwritten, @see BaseProcess virtual bool IsActive( unsigned int pFlags ) const; diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 617835e51..bde69ac9b 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -271,12 +271,16 @@ struct aiBone { //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS. unsigned int mNumWeights; +#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS // The bone armature node - used for skeleton conversion + // you must enable aiProcess_PopulateArmatureData to populate this C_STRUCT aiNode* mArmature; // The bone node in the scene - used for skeleton conversion + // you must enable aiProcess_PopulateArmatureData to populate this C_STRUCT aiNode* mNode; +#endif //! The influence weights of this bone, by vertex index. C_STRUCT aiVertexWeight* mWeights; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 913813c3b..f59ce000a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -148,6 +148,7 @@ SET( POST_PROCESSES unit/utRemoveRedundantMaterials.cpp unit/utRemoveVCProcess.cpp unit/utScaleProcess.cpp + unit/utArmaturePopulate.cpp unit/utJoinVertices.cpp unit/utRemoveComments.cpp unit/utRemoveComponent.cpp diff --git a/test/models/FBX/huesitos.fbx b/test/models/FBX/huesitos.fbx new file mode 100644 index 0000000000000000000000000000000000000000..646271392e5fbd5c3a069498778fb70ba302ebef GIT binary patch literal 111564 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 BGFAWp literal 0 HcmV?d00001 diff --git a/test/unit/utArmaturePopulate.cpp b/test/unit/utArmaturePopulate.cpp new file mode 100644 index 000000000..4aaf8aa7c --- /dev/null +++ b/test/unit/utArmaturePopulate.cpp @@ -0,0 +1,82 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "TestModelFactory.h" + + +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include +#include +#include +#include + +#include "PostProcessing/ArmaturePopulate.h" + +namespace Assimp { +namespace UnitTest { + +class utArmaturePopulate : public ::testing::Test { + // empty +}; + +TEST_F( utArmaturePopulate, importCheckForArmatureTest) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/huesitos.fbx", aiProcess_ValidateDataStructure | aiProcess_PopulateArmatureData); + EXPECT_NE( nullptr, scene ); + EXPECT_EQ(scene->mNumMeshes, 1u); + aiMesh* mesh = scene->mMeshes[0]; + EXPECT_EQ(mesh->mNumFaces, 68u); + EXPECT_EQ(mesh->mNumVertices, 256u); + EXPECT_GT(mesh->mNumBones, 0u); + + aiBone* exampleBone = mesh->mBones[0]; + EXPECT_NE(exampleBone, nullptr); + EXPECT_NE(exampleBone->mArmature, nullptr); + EXPECT_NE(exampleBone->mNode, nullptr); +} + +} // Namespace UnitTest +} // Namespace Assimp From a30936954ef49236397938305e9c05e57670203c Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 27 Oct 2019 11:21:23 +0000 Subject: [PATCH 040/170] Best to check the number of children before checking the actual array --- code/Common/scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/scene.cpp b/code/Common/scene.cpp index 2acb348d8..315581504 100644 --- a/code/Common/scene.cpp +++ b/code/Common/scene.cpp @@ -68,7 +68,7 @@ aiNode::aiNode(const std::string& name) aiNode::~aiNode() { // delete all children recursively // to make sure we won't crash if the data is invalid ... - if (mChildren && mNumChildren) + if (mNumChildren && mChildren) { for (unsigned int a = 0; a < mNumChildren; a++) delete mChildren[a]; From 5d0c63391b729cd7c839a9d8088625d1716c5fa5 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 27 Oct 2019 11:21:49 +0000 Subject: [PATCH 041/170] Explicitly set the size of the parent node if we have no children --- code/FBX/FBXConverter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 88abd6721..8f916a25b 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -313,6 +313,12 @@ namespace Assimp { std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren); } + else + { + parent->mNumChildren = 0; + parent->mChildren = nullptr; + } + } catch (std::exception&) { Util::delete_fun deleter; From 9c8d8357046e4d422b1ba20ffcf3b2da072c7774 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 27 Oct 2019 11:29:56 +0000 Subject: [PATCH 042/170] Explicitly use nullptr --- code/Common/scene.cpp | 16 ++++++++-------- code/FBX/FBXConverter.cpp | 20 ++++++++++---------- code/PostProcessing/ArmaturePopulate.cpp | 12 ++++++------ include/assimp/mesh.h | 18 +++++++++--------- include/assimp/scene.h | 22 +++++++++++----------- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/code/Common/scene.cpp b/code/Common/scene.cpp index 315581504..d15619acf 100644 --- a/code/Common/scene.cpp +++ b/code/Common/scene.cpp @@ -44,23 +44,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. aiNode::aiNode() : mName("") -, mParent(NULL) +, mParent(nullptr) , mNumChildren(0) -, mChildren(NULL) +, mChildren(nullptr) , mNumMeshes(0) -, mMeshes(NULL) -, mMetaData(NULL) { +, mMeshes(nullptr) +, mMetaData(nullptr) { // empty } aiNode::aiNode(const std::string& name) : mName(name) -, mParent(NULL) +, mParent(nullptr) , mNumChildren(0) -, mChildren(NULL) +, mChildren(nullptr) , mNumMeshes(0) -, mMeshes(NULL) -, mMetaData(NULL) { +, mMeshes(nullptr) +, mMetaData(nullptr) { // empty } diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 8f916a25b..20344331c 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -1134,7 +1134,7 @@ namespace Assimp { binormals = &tempBinormals; } else { - binormals = NULL; + binormals = nullptr; } } @@ -1184,7 +1184,7 @@ namespace Assimp { ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]); } - if (doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { + if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) { ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, NO_MATERIAL_SEPARATION, nullptr); } @@ -1264,7 +1264,7 @@ namespace Assimp { const std::vector& vertices = mesh.GetVertices(); const std::vector& faces = mesh.GetFaceIndexCounts(); - const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != NULL; + const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != nullptr; unsigned int count_faces = 0; unsigned int count_vertices = 0; @@ -1324,7 +1324,7 @@ namespace Assimp { binormals = &tempBinormals; } else { - binormals = NULL; + binormals = nullptr; } } @@ -1513,9 +1513,9 @@ namespace Assimp { unsigned int count = 0; const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count); - // ToOutputVertexIndex only returns NULL if index is out of bounds + // ToOutputVertexIndex only returns nullptr if index is out of bounds // which should never happen - ai_assert(out_idx != NULL); + ai_assert(out_idx != nullptr); index_out_indices.push_back(no_index_sentinel); count_out_indices.push_back(0); @@ -1586,7 +1586,7 @@ namespace Assimp { std::string deformer_name = cl->TargetNode()->Name(); aiString bone_name = aiString(FixNodeName(deformer_name)); - aiBone *bone = NULL; + aiBone *bone = nullptr; if (bone_map.count(deformer_name)) { std::cout << "retrieved bone from lookup " << bone_name.C_Str() << ". Deformer: " << deformer_name @@ -2740,7 +2740,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa // sanity check whether the input is ok static void validateAnimCurveNodes(const std::vector& curves, bool strictMode) { - const Object* target(NULL); + const Object* target(nullptr); for (const AnimationCurveNode* node : curves) { if (!target) { target = node->Target(); @@ -2771,7 +2771,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa #ifdef ASSIMP_BUILD_DEBUG validateAnimCurveNodes(curves, doc.Settings().strictMode); #endif - const AnimationCurveNode* curve_node = NULL; + const AnimationCurveNode* curve_node = nullptr; for (const AnimationCurveNode* node : curves) { ai_assert(node); @@ -3619,7 +3619,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa ai_assert(!out->mMeshes); ai_assert(!out->mNumMeshes); - // note: the trailing () ensures initialization with NULL - not + // note: the trailing () ensures initialization with nullptr - not // many C++ users seem to know this, so pointing it out to avoid // confusion why this code works. diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 11fffc399..c677b193a 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -115,7 +115,7 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, ASSIMP_LOG_WARN("GetArmatureRoot() can't find armature!"); - return NULL; + return nullptr; } /* Simple IsBoneNode check if this could be a bone */ @@ -139,7 +139,7 @@ bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, std::vector &nodes) { std::vector::iterator iter; - aiNode *found = NULL; + aiNode *found = nullptr; for (iter = nodes.begin(); iter < nodes.end(); ++iter) { aiNode *element = *iter; ai_assert(element); @@ -150,13 +150,13 @@ aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, } } - if (found != NULL) { + if (found != nullptr) { // now pop the element from the node list nodes.erase(iter); return found; } - return NULL; + return nullptr; } /* Prepare flat node list which can be used for non recursive lookups later */ @@ -233,10 +233,10 @@ void ArmaturePopulate::BuildBoneStack(aiNode *current_node, for (aiBone *bone : bones) { ai_assert(bone); aiNode *node = GetNodeFromStack(bone->mName, node_stack); - if (node == NULL) { + if (node == nullptr) { node_stack.clear(); BuildNodeList(root_node, node_stack); - ASSIMP_LOG_DEBUG_F("Resetting bone stack: null element %s\n", bone->mName.C_Str()); + ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element %s\n", bone->mName.C_Str()); node = GetNodeFromStack(bone->mName, node_stack); diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index bde69ac9b..fbf2a857a 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -435,11 +435,11 @@ struct aiAnimMesh /**Anim Mesh name */ C_STRUCT aiString mName; - /** Replacement for aiMesh::mVertices. If this array is non-NULL, + /** Replacement for aiMesh::mVertices. If this array is non-nullptr, * it *must* contain mNumVertices entries. The corresponding - * array in the host mesh must be non-NULL as well - animation + * array in the host mesh must be non-nullptr as well - animation * meshes may neither add or nor remove vertex components (if - * a replacement array is NULL and the corresponding source + * a replacement array is nullptr and the corresponding source * array is not, the source data is taken instead)*/ C_STRUCT aiVector3D* mVertices; @@ -613,7 +613,7 @@ struct aiMesh C_STRUCT aiVector3D* mVertices; /** Vertex normals. - * The array contains normalized vectors, NULL if not present. + * The array contains normalized vectors, nullptr if not present. * The array is mNumVertices in size. Normals are undefined for * point and line primitives. A mesh consisting of points and * lines only may not have normal vectors. Meshes with mixed @@ -636,7 +636,7 @@ struct aiMesh /** Vertex tangents. * The tangent of a vertex points in the direction of the positive - * X texture axis. The array contains normalized vectors, NULL if + * X texture axis. The array contains normalized vectors, nullptr if * not present. The array is mNumVertices in size. A mesh consisting * of points and lines only may not have normal vectors. Meshes with * mixed primitive types (i.e. lines and triangles) may have @@ -650,7 +650,7 @@ struct aiMesh /** Vertex bitangents. * The bitangent of a vertex points in the direction of the positive - * Y texture axis. The array contains normalized vectors, NULL if not + * Y texture axis. The array contains normalized vectors, nullptr if not * present. The array is mNumVertices in size. * @note If the mesh contains tangents, it automatically also contains * bitangents. @@ -659,14 +659,14 @@ struct aiMesh /** Vertex color sets. * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex - * colors per vertex. NULL if not present. Each array is + * colors per vertex. nullptr if not present. Each array is * mNumVertices in size if present. */ C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; /** Vertex texture coords, also known as UV channels. * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per - * vertex. NULL if not present. The array is mNumVertices in size. + * vertex. nullptr if not present. The array is mNumVertices in size. */ C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; @@ -688,7 +688,7 @@ struct aiMesh C_STRUCT aiFace* mFaces; /** The number of bones this mesh contains. - * Can be 0, in which case the mBones array is NULL. + * Can be 0, in which case the mBones array is nullptr. */ unsigned int mNumBones; diff --git a/include/assimp/scene.h b/include/assimp/scene.h index e69c81803..b76709eb1 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -110,13 +110,13 @@ struct ASSIMP_API aiNode /** The transformation relative to the node's parent. */ C_STRUCT aiMatrix4x4 mTransformation; - /** Parent node. NULL if this node is the root node. */ + /** Parent node. nullptr if this node is the root node. */ C_STRUCT aiNode* mParent; /** The number of child nodes of this node. */ unsigned int mNumChildren; - /** The child nodes of this node. NULL if mNumChildren is 0. */ + /** The child nodes of this node. nullptr if mNumChildren is 0. */ C_STRUCT aiNode** mChildren; /** The number of meshes of this node. */ @@ -127,7 +127,7 @@ struct ASSIMP_API aiNode */ unsigned int* mMeshes; - /** Metadata associated with this node or NULL if there is no metadata. + /** Metadata associated with this node or nullptr if there is no metadata. * Whether any metadata is generated depends on the source file format. See the * @link importer_notes @endlink page for more information on every source file * format. Importers that don't document any metadata don't write any. @@ -149,7 +149,7 @@ struct ASSIMP_API aiNode * of the scene. * * @param name Name to search for - * @return NULL or a valid Node if the search was successful. + * @return nullptr or a valid Node if the search was successful. */ inline const aiNode* FindNode(const aiString& name) const { @@ -344,7 +344,7 @@ struct aiScene #ifdef __cplusplus - //! Default constructor - set everything to 0/NULL + //! Default constructor - set everything to 0/nullptr ASSIMP_API aiScene(); //! Destructor @@ -353,33 +353,33 @@ struct aiScene //! Check whether the scene contains meshes //! Unless no special scene flags are set this will always be true. inline bool HasMeshes() const { - return mMeshes != NULL && mNumMeshes > 0; + return mMeshes != nullptr && mNumMeshes > 0; } //! Check whether the scene contains materials //! Unless no special scene flags are set this will always be true. inline bool HasMaterials() const { - return mMaterials != NULL && mNumMaterials > 0; + return mMaterials != nullptr && mNumMaterials > 0; } //! Check whether the scene contains lights inline bool HasLights() const { - return mLights != NULL && mNumLights > 0; + return mLights != nullptr && mNumLights > 0; } //! Check whether the scene contains textures inline bool HasTextures() const { - return mTextures != NULL && mNumTextures > 0; + return mTextures != nullptr && mNumTextures > 0; } //! Check whether the scene contains cameras inline bool HasCameras() const { - return mCameras != NULL && mNumCameras > 0; + return mCameras != nullptr && mNumCameras > 0; } //! Check whether the scene contains animations inline bool HasAnimations() const { - return mAnimations != NULL && mNumAnimations > 0; + return mAnimations != nullptr && mNumAnimations > 0; } //! Returns a short filename from a full path From 212bcfe75c15bc21a14a715fa4e06886a41d944a Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 27 Oct 2019 12:27:54 +0000 Subject: [PATCH 043/170] Test disable cache --- code/PostProcessing/ArmaturePopulate.cpp | 3 ++- test/unit/utArmaturePopulate.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index c677b193a..5de2a3870 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include namespace Assimp { @@ -76,7 +77,7 @@ void ArmaturePopulate::Execute(aiScene *out) { BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); ASSIMP_LOG_DEBUG_F("Bone stack size: %ld\n", bone_stack.size()); - + std::cout << "post process for armature population has run!" << std::endl; for (std::pair kvp : bone_stack) { aiBone *bone = kvp.first; aiNode *bone_node = kvp.second; diff --git a/test/unit/utArmaturePopulate.cpp b/test/unit/utArmaturePopulate.cpp index 4aaf8aa7c..835d3fdb9 100644 --- a/test/unit/utArmaturePopulate.cpp +++ b/test/unit/utArmaturePopulate.cpp @@ -64,7 +64,7 @@ class utArmaturePopulate : public ::testing::Test { TEST_F( utArmaturePopulate, importCheckForArmatureTest) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/huesitos.fbx", aiProcess_ValidateDataStructure | aiProcess_PopulateArmatureData); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/huesitos.fbx", aiProcess_PopulateArmatureData); EXPECT_NE( nullptr, scene ); EXPECT_EQ(scene->mNumMeshes, 1u); aiMesh* mesh = scene->mMeshes[0]; From a9a0d4d29b8875f37da55b8e8d621732be24e471 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 27 Oct 2019 13:53:11 +0000 Subject: [PATCH 044/170] Tidying order of function calls and fixed debug statements --- code/PostProcessing/ArmaturePopulate.cpp | 176 ++++++++++++----------- 1 file changed, 94 insertions(+), 82 deletions(-) diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 5de2a3870..75daeb6b5 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -76,12 +76,12 @@ void ArmaturePopulate::Execute(aiScene *out) { BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); - ASSIMP_LOG_DEBUG_F("Bone stack size: %ld\n", bone_stack.size()); - std::cout << "post process for armature population has run!" << std::endl; + ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size()); + for (std::pair kvp : bone_stack) { aiBone *bone = kvp.first; aiNode *bone_node = kvp.second; - ASSIMP_LOG_DEBUG_F("active node lookup: %s\n", bone->mName.C_Str()); + ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str()); // lcl transform grab - done in generate_nodes :) // bone->mOffsetMatrix = bone_node->mTransformation; @@ -98,82 +98,6 @@ void ArmaturePopulate::Execute(aiScene *out) { } } -/* Returns the armature root node */ -/* This is required to be detected for a bone initially, it will recurse up - * until it cannot find another bone and return the node No known failure - * points. (yet) - */ -aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, - std::vector &bone_list) { - while (bone_node) { - if (!IsBoneNode(bone_node->mName, bone_list)) { - ASSIMP_LOG_DEBUG_F("Found valid armature: %s\n", bone_node->mName.C_Str()); - return bone_node; - } - - bone_node = bone_node->mParent; - } - - ASSIMP_LOG_WARN("GetArmatureRoot() can't find armature!"); - - return nullptr; -} - -/* Simple IsBoneNode check if this could be a bone */ -bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, - std::vector &bones) { - for (aiBone *bone : bones) { - if (bone->mName == bone_name) { - return true; - } - } - - return false; -} - -/* Pop this node by name from the stack if found */ -/* Used in multiple armature situations with duplicate node / bone names */ -/* Known flaw: cannot have nodes with bone names, will be fixed in later release - */ -/* (serious to be fixed) Known flaw: nodes which have more than one bone could - * be prematurely dropped from stack */ -aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, - std::vector &nodes) { - std::vector::iterator iter; - aiNode *found = nullptr; - for (iter = nodes.begin(); iter < nodes.end(); ++iter) { - aiNode *element = *iter; - ai_assert(element); - // node valid and node name matches - if (element->mName == node_name) { - found = element; - break; - } - } - - if (found != nullptr) { - // now pop the element from the node list - nodes.erase(iter); - - return found; - } - return nullptr; -} - -/* Prepare flat node list which can be used for non recursive lookups later */ -void ArmaturePopulate::BuildNodeList(const aiNode *current_node, - std::vector &nodes) { - ai_assert(current_node); - - for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { - aiNode *child = current_node->mChildren[nodeId]; - ai_assert(child); - - nodes.push_back(child); - - BuildNodeList(child, nodes); - } -} /* Reprocess all nodes to calculate bone transforms properly based on the REAL * mOffsetMatrix not the local. */ @@ -217,6 +141,21 @@ void ArmaturePopulate::BuildBoneList(aiNode *current_node, } } +/* Prepare flat node list which can be used for non recursive lookups later */ +void ArmaturePopulate::BuildNodeList(const aiNode *current_node, + std::vector &nodes) { + ai_assert(current_node); + + for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { + aiNode *child = current_node->mChildren[nodeId]; + ai_assert(child); + + nodes.push_back(child); + + BuildNodeList(child, nodes); + } +} + /* A bone stack allows us to have multiple armatures, with the same bone names * A bone stack allows us also to retrieve bones true transform even with * duplicate names :) @@ -237,20 +176,93 @@ void ArmaturePopulate::BuildBoneStack(aiNode *current_node, if (node == nullptr) { node_stack.clear(); BuildNodeList(root_node, node_stack); - ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element %s\n", bone->mName.C_Str()); + ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); node = GetNodeFromStack(bone->mName, node_stack); if (!node) { - ASSIMP_LOG_ERROR("serious import issue armature failed to be detected"); + ASSIMP_LOG_ERROR("serious import issue node for bone was not detected"); continue; } } - ASSIMP_LOG_DEBUG_F("Successfully added bone to stack and have valid armature: %s\n", bone->mName.C_Str()); + ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); bone_stack.insert(std::pair(bone, node)); } } + +/* Returns the armature root node */ +/* This is required to be detected for a bone initially, it will recurse up + * until it cannot find another bone and return the node No known failure + * points. (yet) + */ +aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, + std::vector &bone_list) { + while (bone_node) { + if (!IsBoneNode(bone_node->mName, bone_list)) { + ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); + return bone_node; + } + + bone_node = bone_node->mParent; + } + + ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!"); + + return nullptr; +} + + + +/* Simple IsBoneNode check if this could be a bone */ +bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, + std::vector &bones) { + for (aiBone *bone : bones) { + if (bone->mName == bone_name) { + return true; + } + } + + return false; +} + +/* Pop this node by name from the stack if found */ +/* Used in multiple armature situations with duplicate node / bone names */ +/* Known flaw: cannot have nodes with bone names, will be fixed in later release + */ +/* (serious to be fixed) Known flaw: nodes which have more than one bone could + * be prematurely dropped from stack */ +aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, + std::vector &nodes) { + std::vector::iterator iter; + aiNode *found = nullptr; + for (iter = nodes.begin(); iter < nodes.end(); ++iter) { + aiNode *element = *iter; + ai_assert(element); + // node valid and node name matches + if (element->mName == node_name) { + found = element; + break; + } + } + + if (found != nullptr) { + ASSIMP_LOG_INFO_F("Removed node from stack: ", found->mName.C_Str()); + // now pop the element from the node list + nodes.erase(iter); + + return found; + } + + // unique names can cause this problem + ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!"); + + return nullptr; +} + + + + } // Namespace Assimp From 5155efe888530daaee69ec098f9627f7a14a9e68 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 27 Oct 2019 13:53:43 +0000 Subject: [PATCH 045/170] Fixed bitmask issue We are approaching the limit for the number of post processes --- include/assimp/postprocess.h | 23 +++++++++++++---------- test/unit/utArmaturePopulate.cpp | 3 ++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index 2af48aedd..4b6732e80 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -320,6 +320,19 @@ enum aiPostProcessSteps */ aiProcess_FixInfacingNormals = 0x2000, + + + // ------------------------------------------------------------------------- + /** + * This step generically populates aiBone->mArmature and aiBone->mNode generically + * The point of these is it saves you later having to calculate these elements + * This is useful when handling rest information or skin information + * If you have multiple armatures on your models we strongly recommend enabling this + * Instead of writing your own multi-root, multi-armature lookups we have done the + * hard work for you :) + */ + aiProcess_PopulateArmatureData = 0x4000, + // ------------------------------------------------------------------------- /**
This step splits meshes with more than one primitive type in * homogeneous sub-meshes. @@ -538,16 +551,6 @@ enum aiPostProcessSteps aiProcess_Debone = 0x4000000, - // ------------------------------------------------------------------------- - /** - * This step generically populates aiBone->mArmature and aiBone->mNode generically - * The point of these is it saves you later having to calculate these elements - * This is useful when handling rest information or skin information - * If you have multiple armatures on your models we strongly recommend enabling this - * Instead of writing your own multi-root, multi-armature lookups we have done the - * hard work for you :) - */ - aiProcess_PopulateArmatureData = 0x5000000, // ------------------------------------------------------------------------- /**
This step will perform a global scale of the model. diff --git a/test/unit/utArmaturePopulate.cpp b/test/unit/utArmaturePopulate.cpp index 835d3fdb9..8eb577d61 100644 --- a/test/unit/utArmaturePopulate.cpp +++ b/test/unit/utArmaturePopulate.cpp @@ -64,7 +64,8 @@ class utArmaturePopulate : public ::testing::Test { TEST_F( utArmaturePopulate, importCheckForArmatureTest) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/huesitos.fbx", aiProcess_PopulateArmatureData); + unsigned int mask = aiProcess_PopulateArmatureData | aiProcess_ValidateDataStructure; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/huesitos.fbx", mask); EXPECT_NE( nullptr, scene ); EXPECT_EQ(scene->mNumMeshes, 1u); aiMesh* mesh = scene->mMeshes[0]; From d7d79db0ac2a55f3138bcc1bc1799f00646f0b61 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 27 Oct 2019 12:57:47 +0000 Subject: [PATCH 046/170] Tests should always debug log --- test/unit/Main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/Main.cpp b/test/unit/Main.cpp index 5ba5c487d..333fd655d 100644 --- a/test/unit/Main.cpp +++ b/test/unit/Main.cpp @@ -16,7 +16,7 @@ int main(int argc, char* argv[]) // create a logger from both CPP Assimp::DefaultLogger::create("AssimpLog_Cpp.txt",Assimp::Logger::VERBOSE, - aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE); + aiDefaultLogStream_STDOUT | aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE); // .. and C. They should smoothly work together aiEnableVerboseLogging(AI_TRUE); From 0baec5f0bd726dc2cd40317abc1015bd6add6c93 Mon Sep 17 00:00:00 2001 From: bzt Date: Tue, 29 Oct 2019 14:14:00 +0100 Subject: [PATCH 047/170] Added M3D format support --- Readme.md | 1 + code/CMakeLists.txt | 12 + code/Common/Exporter.cpp | 7 + code/Common/ImporterRegistry.cpp | 6 + code/M3D/M3DExporter.cpp | 392 +++++++++++ code/M3D/M3DExporter.h | 98 +++ code/M3D/M3DImporter.cpp | 734 +++++++++++++++++++++ code/M3D/M3DImporter.h | 106 +++ code/M3D/M3DMaterials.h | 106 +++ code/M3D/m3d.h | 1 + test/models/M3D/README.md | 14 + test/models/M3D/WusonBlitz0.m3d | Bin 0 -> 29223 bytes test/models/M3D/WusonBlitz1.m3d | Bin 0 -> 35058 bytes test/models/M3D/WusonBlitz2.m3d | Bin 0 -> 42228 bytes test/models/M3D/aliveai_character.m3d | Bin 0 -> 2532 bytes test/models/M3D/cube_normals.m3d | Bin 0 -> 156 bytes test/models/M3D/cube_usemtl.m3d | Bin 0 -> 249 bytes test/models/M3D/cube_with_vertexcolors.a3d | 33 + test/models/M3D/cube_with_vertexcolors.m3d | Bin 0 -> 228 bytes test/models/M3D/mobs_dwarves_character.m3d | Bin 0 -> 11255 bytes test/models/M3D/suzanne.m3d | Bin 0 -> 11645 bytes 21 files changed, 1510 insertions(+) create mode 100644 code/M3D/M3DExporter.cpp create mode 100644 code/M3D/M3DExporter.h create mode 100644 code/M3D/M3DImporter.cpp create mode 100644 code/M3D/M3DImporter.h create mode 100644 code/M3D/M3DMaterials.h create mode 120000 code/M3D/m3d.h create mode 100644 test/models/M3D/README.md create mode 100644 test/models/M3D/WusonBlitz0.m3d create mode 100644 test/models/M3D/WusonBlitz1.m3d create mode 100644 test/models/M3D/WusonBlitz2.m3d create mode 100644 test/models/M3D/aliveai_character.m3d create mode 100644 test/models/M3D/cube_normals.m3d create mode 100644 test/models/M3D/cube_usemtl.m3d create mode 100644 test/models/M3D/cube_with_vertexcolors.a3d create mode 100644 test/models/M3D/cube_with_vertexcolors.m3d create mode 100644 test/models/M3D/mobs_dwarves_character.m3d create mode 100644 test/models/M3D/suzanne.m3d diff --git a/Readme.md b/Readme.md index f749993fd..f02a3b617 100644 --- a/Readme.md +++ b/Readme.md @@ -67,6 +67,7 @@ __Importers__: - [LWO](https://en.wikipedia.org/wiki/LightWave_3D) - LWS - LXO +- [M3D](https://gitlab.com/bztsrc/model3d) - MD2 - MD3 - MD5 diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index eec805b54..910a43562 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -407,6 +407,18 @@ ADD_ASSIMP_IMPORTER( LWS LWS/LWSLoader.h ) +ADD_ASSIMP_IMPORTER( M3D + M3D/M3DMaterials.h + M3D/M3DImporter.h + M3D/M3DImporter.cpp + M3D/m3d.h +) + +ADD_ASSIMP_EXPORTER( M3D + M3D/M3DExporter.h + M3D/M3DExporter.cpp +) + ADD_ASSIMP_IMPORTER( MD2 MD2/MD2FileData.h MD2/MD2Loader.cpp diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 34d49c472..4ce1a2bd8 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -102,6 +102,8 @@ void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperti void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); +void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneA3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*); // ------------------------------------------------------------------------------------------------ @@ -179,6 +181,11 @@ Exporter::ExportFormatEntry gExporters[] = Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ), #endif +#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER + Exporter::ExportFormatEntry( "m3d", "Model 3D (binary)", "m3d", &ExportSceneM3D, 0 ), + Exporter::ExportFormatEntry( "a3d", "Model 3D (ascii)", "m3d", &ExportSceneA3D, 0 ), +#endif + #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ), #endif diff --git a/code/Common/ImporterRegistry.cpp b/code/Common/ImporterRegistry.cpp index 32ac3b416..b9f28f035 100644 --- a/code/Common/ImporterRegistry.cpp +++ b/code/Common/ImporterRegistry.cpp @@ -197,6 +197,9 @@ corresponding preprocessor flag to selectively disable formats. #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER # include "MMD/MMDImporter.h" #endif +#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER +# include "M3D/M3DImporter.h" +#endif #ifndef ASSIMP_BUILD_NO_STEP_IMPORTER # include "Importer/StepFile/StepFileImporter.h" #endif @@ -223,6 +226,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER) out.push_back( new Discreet3DSImporter()); #endif +#if (!defined ASSIMP_BUILD_NO_M3D_IMPORTER) + out.push_back( new M3DImporter()); +#endif #if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER) out.push_back( new MD3Importer()); #endif diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp new file mode 100644 index 000000000..35cae078a --- /dev/null +++ b/code/M3D/M3DExporter.cpp @@ -0,0 +1,392 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team +Copyright (c) 2019 bzt + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER + +#define M3D_IMPLEMENTATION +#define M3D_NOIMPORTER +#define M3D_EXPORTER +#define M3D_ASCII +#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER +#define M3D_NODUP +#endif + +// Header files, standard library. +#include // shared_ptr +#include +#include + +#include // aiGetVersion +#include +#include +#include +#include // StreamWriterLE +#include // DeadlyExportError +#include // aiTextureType +#include +#include +#include "M3DExporter.h" +#include "M3DMaterials.h" + +// RESOURCES: +// https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md +// https://gitlab.com/bztsrc/model3d/blob/master/docs/a3d_format.md + +/* + * Currently supports static meshes, vertex colors, materials, textures + * + * For animation, it would require the following conversions: + * - aiNode (bones) -> m3d_t.bone (with parent id, position vector and oriantation quaternion) + * - aiMesh.aiBone -> m3d_t.skin (per vertex, with bone id, weight pairs) + * - aiAnimation -> m3d_action (frame with timestamp and list of bone id, position, orientation + * triplets, instead of per bone timestamp + lists) + */ +using namespace Assimp; + +namespace Assimp { + + // --------------------------------------------------------------------- + // Worker function for exporting a scene to binary M3D. + // Prototyped and registered in Exporter.cpp + void ExportSceneM3D ( + const char* pFile, + IOSystem* pIOSystem, + const aiScene* pScene, + const ExportProperties* pProperties + ){ + // initialize the exporter + M3DExporter exporter(pScene, pProperties); + + // perform binary export + exporter.doExport(pFile, pIOSystem, false); + } + + // --------------------------------------------------------------------- + // Worker function for exporting a scene to ASCII A3D. + // Prototyped and registered in Exporter.cpp + void ExportSceneA3D ( + const char* pFile, + IOSystem* pIOSystem, + const aiScene* pScene, + const ExportProperties* pProperties + + ){ + // initialize the exporter + M3DExporter exporter(pScene, pProperties); + + // perform ascii export + exporter.doExport(pFile, pIOSystem, true); + } + +} // end of namespace Assimp + +// ------------------------------------------------------------------------------------------------ +M3DExporter::M3DExporter ( const aiScene* pScene, const ExportProperties* pProperties ) +: mScene(pScene) +, mProperties(pProperties) +, outfile() +, m3d(nullptr) { } + +// ------------------------------------------------------------------------------------------------ +void M3DExporter::doExport ( + const char* pFile, + IOSystem* pIOSystem, + bool toAscii +){ + // TODO: convert mProperties into M3D_EXP_* flags + (void)mProperties; + + // open the indicated file for writing (in binary / ASCII mode) + outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb")); + if (!outfile) { + throw DeadlyExportError( "could not open output .m3d file: " + std::string(pFile) ); + } + + // use malloc() here because m3d_free() will call free() + m3d = (m3d_t*)malloc(sizeof(m3d_t)); + if(!m3d) { + throw DeadlyExportError( "memory allocation error" ); + } + memset(m3d, 0, sizeof(m3d_t)); + m3d->name = _m3d_safestr((char*)&mScene->mRootNode->mName.data, 2); + + // Create a model from assimp structures + aiMatrix4x4 m; + NodeWalk(mScene->mRootNode, m); + + // serialize the structures + unsigned int size; + unsigned char *output = m3d_save(m3d, M3D_EXP_FLOAT, + M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), &size); + m3d_free(m3d); + if(!output || size < 8) { + throw DeadlyExportError( "unable to serialize into Model 3D" ); + } + + // Write out serialized model + outfile->Write(output, size, 1); + + // explicitly release file pointer, + // so we don't have to rely on class destruction. + outfile.reset(); +} + +// ------------------------------------------------------------------------------------------------ +// recursive node walker +void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) +{ + unsigned int i, j, k, l, n, mi, idx; + aiMatrix4x4 nm = m * pNode->mTransformation; + m3dv_t vertex; + m3dti_t ti; + + for(i = 0; i < pNode->mNumMeshes; i++) { + const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]]; + + mi = (M3D_INDEX)-1U; + if(mScene->mMaterials) { + // get the material for this mesh + mi = addMaterial(mScene->mMaterials[mesh->mMaterialIndex]); + } + // iterate through the mesh faces + for(j = 0; j < mesh->mNumFaces; j++) { + const aiFace* face = &(mesh->mFaces[j]); + // only triangle meshes supported for now + if(face->mNumIndices != 3) { + throw DeadlyExportError( "use aiProcess_Triangulate before export" ); + } + // add triangle to the output + n = m3d->numface++; + m3d->face = (m3df_t*)M3D_REALLOC(m3d->face, + m3d->numface * sizeof(m3df_t)); + if(!m3d->face) { + throw DeadlyExportError( "memory allocation error" ); + } + /* set all index to -1 by default */ + memset(&m3d->face[n], 255, sizeof(m3df_t)); + m3d->face[n].materialid = mi; + for(k = 0; k < face->mNumIndices; k++) { + // get the vertex's index + l = face->mIndices[k]; + // multiply the position vector by the transformation matrix + aiVector3D v = mesh->mVertices[l]; + v *= nm; + memset(&vertex, 0, sizeof(m3dv_t)); + vertex.x = v.x; + vertex.y = v.y; + vertex.z = v.z; + vertex.w = 1.0; + // add color if defined + if(mesh->HasVertexColors(0)) + vertex.color = mkColor(&mesh->mColors[0][l]); + // save the vertex to the output + m3d->vertex = _m3d_addvrtx(m3d->vertex, &m3d->numvertex, + &vertex, &idx); + m3d->face[n].vertex[k] = (M3D_INDEX)idx; + // do we have texture coordinates? + if(mesh->HasTextureCoords(0)) { + ti.u = mesh->mTextureCoords[0][l].x; + ti.v = mesh->mTextureCoords[0][l].y; + m3d->tmap = _m3d_addtmap(m3d->tmap, &m3d->numtmap, &ti, + &idx); + m3d->face[n].texcoord[k] = (M3D_INDEX)idx; + } + // do we have normal vectors? + if(mesh->HasNormals()) { + vertex.color = 0; + vertex.x = mesh->mNormals[l].x; + vertex.y = mesh->mNormals[l].y; + vertex.z = mesh->mNormals[l].z; + m3d->vertex = _m3d_addnorm(m3d->vertex, &m3d->numvertex, + &vertex, &idx); + m3d->face[n].normal[k] = (M3D_INDEX)idx; + } + } + } + } + // repeat for the children nodes + for (i = 0; i < pNode->mNumChildren; i++) { + NodeWalk(pNode->mChildren[i], nm); + } +} + +// ------------------------------------------------------------------------------------------------ +// convert aiColor4D into uint32_t +uint32_t M3DExporter::mkColor(aiColor4D* c) +{ + return ((uint8_t)(c->a*255) << 24L) | + ((uint8_t)(c->b*255) << 16L) | + ((uint8_t)(c->g*255) << 8L) | + ((uint8_t)(c->r*255) << 0L); +} + +// ------------------------------------------------------------------------------------------------ +// add a material to the output +M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) +{ + unsigned int i, j, k, mi = -1U; + aiColor4D c; + aiString name; + ai_real f; + char *fn; + + if(mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length && + strcmp((char*)&name.data, AI_DEFAULT_MATERIAL_NAME)) { + // check if we have saved a material by this name. This has to be done + // because only the referenced materials should be added to the output + for(i = 0; i < m3d->nummaterial; i++) + if(!strcmp((char*)&name.data, m3d->material[i].name)) { + mi = i; + break; + } + // if not found, add the material to the output + if(mi == -1U) { + mi = m3d->nummaterial++; + m3d->material = (m3dm_t*)M3D_REALLOC(m3d->material, m3d->nummaterial + * sizeof(m3dm_t)); + if(!m3d->material) { + throw DeadlyExportError( "memory allocation error" ); + } + m3d->material[mi].name = _m3d_safestr((char*)&name.data, 0); + m3d->material[mi].numprop = 0; + m3d->material[mi].prop = NULL; + // iterate through the material property table and see what we got + for(k = 0; + k < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); + k++) { + if(m3d_propertytypes[k].format == m3dpf_map) + continue; + if(aiProps[k].pKey) { + switch(m3d_propertytypes[k].format) { + case m3dpf_color: + if(mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, c) == AI_SUCCESS) + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, mkColor(&c)); + break; + case m3dpf_float: + if(mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, f) == AI_SUCCESS) + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, + /* not (uint32_t)f, because we don't want to convert + * it, we want to see it as 32 bits of memory */ + *((uint32_t*)&f)); + break; + case m3dpf_uint8: + if(mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, j) == AI_SUCCESS) { + // special conversion for illumination model property + if(m3d_propertytypes[k].id == m3dp_il) { + switch(j) { + case aiShadingMode_NoShading: j = 0; break; + case aiShadingMode_Phong: j = 2; break; + default: j = 1; break; + } + } + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, j); + } + break; + default: + if(mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, j) == AI_SUCCESS) + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, j); + break; + } + } + if(aiTxProps[k].pKey && + mat->GetTexture((aiTextureType)aiTxProps[k].type, + aiTxProps[k].index, &name, NULL, NULL, NULL, + NULL, NULL) == AI_SUCCESS) { + for(j = name.length-1; j > 0 && name.data[j]!='.'; j++); + if(j && name.data[j]=='.' && + (name.data[j+1]=='p' || name.data[j+1]=='P') && + (name.data[j+1]=='n' || name.data[j+1]=='N') && + (name.data[j+1]=='g' || name.data[j+1]=='G')) + name.data[j]=0; + // do we have this texture saved already? + fn = _m3d_safestr((char*)&name.data, 0); + for(j = 0, i = -1U; j < m3d->numtexture; j++) + if(!strcmp(fn, m3d->texture[j].name)) { + i = j; + free(fn); + break; + } + if(i == -1U) { + i = m3d->numtexture++; + m3d->texture = (m3dtx_t*)M3D_REALLOC( + m3d->texture, + m3d->numtexture * sizeof(m3dtx_t)); + if(!m3d->texture) { + throw DeadlyExportError( "memory allocation error" ); + } + // we don't need the texture itself, only its name + m3d->texture[i].name = fn; + m3d->texture[i].w = 0; + m3d->texture[i].h = 0; + m3d->texture[i].d = NULL; + } + addProp(&m3d->material[mi], + m3d_propertytypes[k].id + 128, i); + } + } + } + } + return mi; +} + +// ------------------------------------------------------------------------------------------------ +// add a material property to the output +void M3DExporter::addProp(m3dm_t *m, uint8_t type, uint32_t value) +{ + unsigned int i; + i = m->numprop++; + m->prop = (m3dp_t*)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t)); + if(!m->prop) { throw DeadlyExportError( "memory allocation error" ); } + m->prop[i].type = type; + m->prop[i].value.num = value; +} + +#endif // ASSIMP_BUILD_NO_M3D_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/M3D/M3DExporter.h b/code/M3D/M3DExporter.h new file mode 100644 index 000000000..dfcff8bc9 --- /dev/null +++ b/code/M3D/M3DExporter.h @@ -0,0 +1,98 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team +Copyright (c) 2019 bzt + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file M3DExporter.h +* @brief Declares the exporter class to write a scene to a Model 3D file +*/ +#ifndef AI_M3DEXPORTER_H_INC +#define AI_M3DEXPORTER_H_INC + +#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER + +#include "m3d.h" + +#include +//#include +#include // StreamWriterLE +#include // DeadlyExportError + +#include // shared_ptr + +struct aiScene; +struct aiNode; +struct aiMaterial; +struct aiFace; + +namespace Assimp +{ + class IOSystem; + class IOStream; + class ExportProperties; + + // --------------------------------------------------------------------- + /** Helper class to export a given scene to an M3D file. */ + // --------------------------------------------------------------------- + class M3DExporter + { + public: + /// Constructor for a specific scene to export + M3DExporter(const aiScene* pScene, const ExportProperties* pProperties); + // call this to do the actual export + void doExport(const char* pFile, IOSystem* pIOSystem, bool toAscii); + + private: + const aiScene* mScene; // the scene to export + const ExportProperties* mProperties; // currently unused + std::shared_ptr outfile; // file to write to + m3d_t *m3d; // model for the C library to convert to + + // helper to do the recursive walking + void NodeWalk(const aiNode* pNode, aiMatrix4x4 m); + uint32_t mkColor(aiColor4D* c); + M3D_INDEX addMaterial(const aiMaterial *mat); + void addProp(m3dm_t *m, uint8_t type, uint32_t value); + }; +} + +#endif // ASSIMP_BUILD_NO_M3D_EXPORTER + +#endif // AI_M3DEXPORTER_H_INC diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp new file mode 100644 index 000000000..76ba51364 --- /dev/null +++ b/code/M3D/M3DImporter.cpp @@ -0,0 +1,734 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team +Copyright (c) 2019 bzt + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER + +#define M3D_IMPLEMENTATION +#define M3D_ASCII + +#include +#include +#include +#include +#include +#include +#include +#include +#include "M3DImporter.h" +#include "M3DMaterials.h" + +// RESOURCES: +// https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md +// https://gitlab.com/bztsrc/model3d/blob/master/docs/a3d_format.md + +/* + Unfortunately aiNode has bone structures and meshes too, yet we can't assign + the mesh to a bone aiNode as a skin may refer to several aiNodes. Therefore + I've decided to import into this structure: + + aiScene->mRootNode + | |->mMeshes (all the meshes) + | \->children (empty if there's no skeleton imported, no meshes) + | \->skeleton root aiNode* + | |->bone aiNode + | | \->subbone aiNode + | |->bone aiNode + | | ... + | \->bone aiNode + \->mMeshes[] + \->aiBone, referencing mesh-less aiNodes from above + + * - normally one, but if a model has several skeleton roots, then all of them + are listed in aiScene->mRootNode->children, but all without meshes +*/ + +static const aiImporterDesc desc = { + "Model 3D Importer", + "", + "", + "", + aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, + "m3d a3d" +}; + +// workaround: the SDK expects a C callback, but we want to use Assimp::IOSystem to implement that +extern "C" { + struct Assimp::IOSystem* m3dimporter_pIOHandler; + + unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { + ai_assert( nullptr != fn ); + ai_assert( nullptr != size ); + std::string file(fn); + std::unique_ptr pStream( m3dimporter_pIOHandler->Open( file, "rb")); + size_t fileSize = pStream->FileSize(); + // should be allocated with malloc(), because the library will call free() to deallocate + unsigned char *data = (unsigned char*)malloc(fileSize); + if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) { + pStream.reset(); + *size = 0; + // don't throw a deadly exception, it's not fatal if we can't read an external asset + return nullptr; + } + pStream.reset(); + *size = (int)fileSize; + return data; + } +} + +namespace Assimp { + +using namespace std; + +// ------------------------------------------------------------------------------------------------ +// Default constructor +M3DImporter::M3DImporter() +: mScene(nullptr) +, m3d(nullptr) { } + +// ------------------------------------------------------------------------------------------------ +// Destructor. +M3DImporter::~M3DImporter() {} + +// ------------------------------------------------------------------------------------------------ +// Returns true, if file is a binary or ASCII Model 3D file. +bool M3DImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler , bool checkSig) const { + const std::string extension = GetExtension(pFile); + + if (extension == "m3d" || extension == "a3d") + return true; + else if (!extension.length() || checkSig) { + if (!pIOHandler) { + return true; + } + /* + * don't use CheckMagicToken because that checks with swapped bytes too, leading to false + * positives. This magic is not uint32_t, but char[4], so memcmp is the best way + + const char* tokens[] = {"3DMO", "3dmo"}; + return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); + */ + std::unique_ptr pStream (pIOHandler->Open(pFile, "rb")); + unsigned char data[4]; + if(4 != pStream->Read(data,1,4)) { + return false; + } + return !memcmp(data, "3DMO", 4) /* bin */ || !memcmp(data, "3dmo", 4) /* ASCII */; + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +const aiImporterDesc* M3DImporter::GetInfo() const { + return &desc; +} + +// ------------------------------------------------------------------------------------------------ +// Model 3D import implementation +void M3DImporter::InternReadFile( const std::string &file, aiScene* pScene, IOSystem* pIOHandler) { + // Read file into memory + std::unique_ptr pStream( pIOHandler->Open( file, "rb")); + if( !pStream.get() ) { + throw DeadlyImportError( "Failed to open file " + file + "." ); + } + + // Get the file-size and validate it, throwing an exception when fails + size_t fileSize = pStream->FileSize(); + if( fileSize < 8 ) { + throw DeadlyImportError( "M3D-file " + file + " is too small." ); + } + unsigned char data[fileSize]; + if(fileSize != pStream->Read(data,1,fileSize)) { + throw DeadlyImportError( "Failed to read the file " + file + "." ); + } + + // Get the path for external assets + std::string folderName( "./" ); + std::string::size_type pos = file.find_last_of( "\\/" ); + if ( pos != std::string::npos ) { + folderName = file.substr( 0, pos ); + if ( !folderName.empty() ) { + pIOHandler->PushDirectory( folderName ); + } + } + // pass this IOHandler to the C callback + m3dimporter_pIOHandler = pIOHandler; + + //DefaultLogger::create("/dev/stderr", Logger::VERBOSE); + ASSIMP_LOG_DEBUG_F("M3D: loading ", file); + + // let the C SDK do the hard work for us + m3d = m3d_load(&data[0], m3dimporter_readfile, free, nullptr); + m3dimporter_pIOHandler = nullptr; + if( !m3d ) { + throw DeadlyImportError( "Unable to parse " + file + " as M3D." ); + } + + // create the root node + pScene->mRootNode = new aiNode; + pScene->mRootNode->mName = aiString(std::string(std::string(m3d->name))); + pScene->mRootNode->mTransformation = aiMatrix4x4(); + pScene->mRootNode->mNumChildren = 0; + mScene = pScene; + + ASSIMP_LOG_DEBUG("M3D: root node " + std::string(m3d->name)); + + // now we just have to fill up the Assimp structures in pScene + importMaterials(); + importTextures(); + importBones(-1U, pScene->mRootNode); + importMeshes(); + importAnimations(); + + // we don't need the SDK's version any more + m3d_free(m3d); + + // Pop directory stack + if ( pIOHandler->StackSize() > 0 ) { + pIOHandler->PopDirectory(); + } +} + +// ------------------------------------------------------------------------------------------------ +// convert materials. properties are converted using a static table in M3DMaterials.h +void M3DImporter::importMaterials() +{ + unsigned int i, j, k, l, n; + m3dm_t *m; + aiString name = aiString(AI_DEFAULT_MATERIAL_NAME); + aiColor4D c; + ai_real f; + + ai_assert(mScene != nullptr); + ai_assert(m3d != nullptr); + + mScene->mNumMaterials = m3d->nummaterial + 1; + mScene->mMaterials = new aiMaterial*[ m3d->nummaterial + 1 ]; + + ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); + + // add a default material as first + aiMaterial* mat = new aiMaterial; + mat->AddProperty( &name, AI_MATKEY_NAME ); + c.a = 1.0; c.b = c.g = c.r = 0.6; + mat->AddProperty( &c, 1, AI_MATKEY_COLOR_DIFFUSE); + mScene->mMaterials[0] = mat; + + for(i = 0; i < m3d->nummaterial; i++) { + m = &m3d->material[i]; + aiMaterial* mat = new aiMaterial; + name.Set(std::string(m->name)); + mat->AddProperty( &name, AI_MATKEY_NAME ); + for(j = 0; j < m->numprop; j++) { + // look up property type + // 0 - 127 scalar values, + // 128 - 255 the same properties but for texture maps + k = 256; + for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) + if(m->prop[j].type == m3d_propertytypes[l].id || + m->prop[j].type == m3d_propertytypes[l].id + 128) { + k = l; + break; + } + // should never happen, but be safe than sorry + if(k == 256) continue; + + // scalar properties + if(m->prop[j].type < 128 && aiProps[k].pKey) { + switch(m3d_propertytypes[k].format) { + case m3dpf_color: + c = mkColor(m->prop[j].value.color); + mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + case m3dpf_float: + f = m->prop[j].value.fnum; + mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + default: + n = m->prop[j].value.num; + if(m->prop[j].type == m3dp_il) { + switch(n) { + case 0: n = aiShadingMode_NoShading; break; + case 2: n = aiShadingMode_Phong; break; + default: n = aiShadingMode_Gouraud; break; + } + } + mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + } + } + // texture map properties + if(m->prop[j].type >= 128 && aiTxProps[k].pKey && + // extra check, should never happen, do we have the refered texture? + m->prop[j].value.textureid < m3d->numtexture && + m3d->texture[m->prop[j].value.textureid].name) { + name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); + mat->AddProperty(&name, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + n = 0; + mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); + } + } + mScene->mMaterials[i + 1] = mat; + } +} + +// ------------------------------------------------------------------------------------------------ +// import textures, this is the simplest of all +void M3DImporter::importTextures() +{ + unsigned int i; + m3dtx_t *t; + + ai_assert(mScene != nullptr); + ai_assert(m3d != nullptr); + + mScene->mNumTextures = m3d->numtexture; + ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); + + if(!m3d->numtexture) + return; + + mScene->mTextures = new aiTexture*[m3d->numtexture]; + for(i = 0; i < m3d->numtexture; i++) { + t = &m3d->texture[i]; + aiTexture *tx = new aiTexture; + strcpy(tx->achFormatHint, "rgba8888"); + tx->mFilename = aiString(std::string(t->name) + ".png"); + tx->mWidth = t->w; + tx->mHeight = t->h; + tx->pcData = new aiTexel[ tx->mWidth*tx->mHeight ]; + memcpy(tx->pcData, t->d, tx->mWidth*tx->mHeight*4); + mScene->mTextures[i] = tx; + } +} + +// ------------------------------------------------------------------------------------------------ +// this is tricky. M3D has a global vertex and UV list, and faces are indexing them +// individually. In assimp there're per mesh vertex and UV lists, and they must be +// indexed simultaneously. +void M3DImporter::importMeshes() +{ + unsigned int i, j, k, l, numpoly = 3, lastMat = -2U; + std::vector *meshes = new std::vector(); + std::vector *faces = nullptr; + std::vector *vertices = nullptr; + std::vector *normals = nullptr; + std::vector *texcoords = nullptr; + std::vector *colors = nullptr; + std::vector *vertexids = nullptr; + aiMesh *pMesh = nullptr; + + ai_assert(mScene != nullptr); + ai_assert(m3d != nullptr); + ai_assert(mScene->mRootNode != nullptr); + + ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + + for(i = 0; i < m3d->numface; i++) { + // we must switch mesh if material changes + if(lastMat != m3d->face[i].materialid) { + lastMat = m3d->face[i].materialid; + if(pMesh && vertices->size() && faces->size()) { + populateMesh(pMesh, faces, vertices, normals, texcoords, colors, vertexids); + meshes->push_back(pMesh); + delete vertexids; // this is not stored in pMesh, just to collect bone vertices + } + pMesh = new aiMesh; + pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + pMesh->mMaterialIndex = lastMat + 1; + faces = new std::vector(); + vertices = new std::vector(); + normals = new std::vector(); + texcoords = new std::vector(); + colors = new std::vector(); + vertexids = new std::vector(); + } + // add a face to temporary vector + aiFace *pFace = new aiFace; + pFace->mNumIndices = numpoly; + pFace->mIndices = new unsigned int[numpoly]; + for(j = 0; j < numpoly; j++) { + aiVector3D pos, uv, norm; + k = vertices->size(); + pFace->mIndices[j] = k; + l = m3d->face[i].vertex[j]; + pos.x = m3d->vertex[l].x; + pos.y = m3d->vertex[l].y; + pos.z = m3d->vertex[l].z; + vertices->push_back(pos); + colors->push_back(mkColor(m3d->vertex[l].color)); + // add a bone to temporary vector + if(m3d->vertex[l].skinid != -1U &&m3d->vertex[l].skinid != -2U && m3d->skin && m3d->bone) { + // this is complicated, because M3D stores a list of bone id / weight pairs per + // vertex but assimp uses lists of local vertex id/weight pairs per local bone list + vertexids->push_back(l); + } + l = m3d->face[i].texcoord[j]; + if(l != -1U) { + uv.x = m3d->tmap[l].u; + uv.y = m3d->tmap[l].v; + uv.z = 0.0; + texcoords->push_back(uv); + } + l = m3d->face[i].normal[j]; + if(l != -1U) { + norm.x = m3d->vertex[l].x; + norm.y = m3d->vertex[l].y; + norm.z = m3d->vertex[l].z; + normals->push_back(norm); + } + } + faces->push_back(*pFace); + delete pFace; + } + // if there's data left in the temporary vectors, flush them + if(pMesh && vertices->size() && faces->size()) { + populateMesh(pMesh, faces, vertices, normals, texcoords, colors, vertexids); + meshes->push_back(pMesh); + } + + // create global mesh list in scene + mScene->mNumMeshes = meshes->size(); + mScene->mMeshes = new aiMesh*[mScene->mNumMeshes]; + std::copy(meshes->begin(), meshes->end(), mScene->mMeshes); + + // create mesh indeces in root node + mScene->mRootNode->mNumMeshes = meshes->size(); + mScene->mRootNode->mMeshes = new unsigned int[meshes->size()]; + for(i = 0; i < meshes->size(); i++) { + mScene->mRootNode->mMeshes[i] = i; + } + + delete meshes; + if(faces) delete faces; + if(vertices) delete vertices; + if(normals) delete normals; + if(texcoords) delete texcoords; + if(colors) delete colors; + if(vertexids) delete vertexids; +} + +// ------------------------------------------------------------------------------------------------ +// a reentrant node parser. Otherwise this is simple +void M3DImporter::importBones(unsigned int parentid, aiNode *pParent) +{ + unsigned int i, n; + + ai_assert(pParent != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d != nullptr); + + ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); + + for(n = 0, i = parentid + 1; i < m3d->numbone; i++) + if(m3d->bone[i].parent == parentid) n++; + pParent->mChildren = new aiNode*[n]; + + for(i = parentid + 1; i < m3d->numbone; i++) { + if(m3d->bone[i].parent == parentid) { + aiNode *pChild = new aiNode; + pChild->mParent = pParent; + pChild->mName = aiString(std::string(m3d->bone[i].name)); + convertPose(&pChild->mTransformation, m3d->bone[i].pos, m3d->bone[i].ori); + pChild->mNumChildren = 0; + pParent->mChildren[pParent->mNumChildren] = pChild; + pParent->mNumChildren++; + importBones(i, pChild); + } + } +} + +// ------------------------------------------------------------------------------------------------ +// this is another headache. M3D stores list of changed bone id/position/orientation triplets and +// a timestamp per frame, but assimp needs timestamp and lists of position, orientation lists per +// bone, so we have to convert between the two conceptually different representation forms +void M3DImporter::importAnimations() +{ + unsigned int i, j, k, l, n, pos, ori; + double t; + m3da_t *a; + + ai_assert(mScene != nullptr); + ai_assert(m3d != nullptr); + + mScene->mNumAnimations = m3d->numaction; + + ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); + + if(!m3d->numaction || !m3d->numbone) + return; + + mScene->mAnimations = new aiAnimation*[m3d->numaction]; + for(i = 0; i < m3d->numaction; i++) { + a = &m3d->action[i]; + aiAnimation *pAnim = new aiAnimation; + pAnim->mName = aiString(std::string(a->name)); + pAnim->mDuration = ((double)a->durationmsec) / 10; + pAnim->mTicksPerSecond = 100; + // now we know how many bones are referenced in this animation + pAnim->mNumChannels = m3d->numbone; + pAnim->mChannels = new aiNodeAnim*[pAnim->mNumChannels]; + for(l = 0; l < m3d->numbone; l++) { + pAnim->mChannels[l] = new aiNodeAnim; + pAnim->mChannels[l]->mNodeName = aiString(std::string(m3d->bone[l].name)); + // now n is the size of positions / orientations arrays + pAnim->mChannels[l]->mNumPositionKeys = pAnim->mChannels[l]->mNumRotationKeys = a->numframe; + pAnim->mChannels[l]->mPositionKeys = new aiVectorKey[a->numframe]; + pAnim->mChannels[l]->mRotationKeys = new aiQuatKey[a->numframe]; + pos = m3d->bone[l].pos; + ori = m3d->bone[l].ori; + for(j = n = 0; j < a->numframe; j++) { + t = ((double)a->frame[j].msec) / 10; + for(k = 0; k < a->frame[j].numtransform; k++) { + if(a->frame[j].transform[k].boneid == l) { + pos = a->frame[j].transform[k].pos; + ori = a->frame[j].transform[k].ori; + } + } + m3dv_t *v = &m3d->vertex[pos]; + m3dv_t *q = &m3d->vertex[ori]; + pAnim->mChannels[l]->mPositionKeys[j].mTime = t; + pAnim->mChannels[l]->mPositionKeys[j].mValue.x = v->x; + pAnim->mChannels[l]->mPositionKeys[j].mValue.y = v->y; + pAnim->mChannels[l]->mPositionKeys[j].mValue.z = v->z; + pAnim->mChannels[l]->mRotationKeys[j].mTime = t; + pAnim->mChannels[l]->mRotationKeys[j].mValue.w = q->w; + pAnim->mChannels[l]->mRotationKeys[j].mValue.x = q->x; + pAnim->mChannels[l]->mRotationKeys[j].mValue.y = q->y; + pAnim->mChannels[l]->mRotationKeys[j].mValue.z = q->z; + }// foreach frame + }// foreach bones + mScene->mAnimations[i] = pAnim; + } +} + +// ------------------------------------------------------------------------------------------------ +// convert uint32_t into aiColor4D +aiColor4D M3DImporter::mkColor(uint32_t c) { + aiColor4D color; + color.a = ((float)((c >> 24)&0xff)) / 255; + color.b = ((float)((c >> 16)&0xff)) / 255; + color.g = ((float)((c >> 8)&0xff)) / 255; + color.r = ((float)((c >> 0)&0xff)) / 255; + return color; +} + +// ------------------------------------------------------------------------------------------------ +// convert a position id and orientation id into a 4 x 4 transformation matrix +void M3DImporter::convertPose(aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) +{ + ai_assert(m != nullptr); + ai_assert(m3d != nullptr); + ai_assert(posid != -1U && posid < m3d->numvertex); + ai_assert(orientid != -1U && orientid < m3d->numvertex); + m3dv_t *p = &m3d->vertex[posid]; + m3dv_t *q = &m3d->vertex[orientid]; + + /* quaternion to matrix. Do NOT use aiQuaternion to aiMatrix3x3, gives bad results */ + if(q->x == 0.0 && q->y == 0.0 && q->z >= 0.7071065 && q->z <= 0.7071075 && q->w == 0.0) { + m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0; + m->a1 = m->b2 = m->c3 = -1.0; + } else { + m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); if(m->a1 > -1e-7 && m->a1 < 1e-7) m->a1 = 0.0; + m->a2 = 2 * (q->x * q->y - q->z * q->w); if(m->a2 > -1e-7 && m->a2 < 1e-7) m->a2 = 0.0; + m->a3 = 2 * (q->x * q->z + q->y * q->w); if(m->a3 > -1e-7 && m->a3 < 1e-7) m->a3 = 0.0; + m->b1 = 2 * (q->x * q->y + q->z * q->w); if(m->b1 > -1e-7 && m->b1 < 1e-7) m->b1 = 0.0; + m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); if(m->b2 > -1e-7 && m->b2 < 1e-7) m->b2 = 0.0; + m->b3 = 2 * (q->y * q->z - q->x * q->w); if(m->b3 > -1e-7 && m->b3 < 1e-7) m->b3 = 0.0; + m->c1 = 2 * (q->x * q->z - q->y * q->w); if(m->c1 > -1e-7 && m->c1 < 1e-7) m->c1 = 0.0; + m->c2 = 2 * (q->y * q->z + q->x * q->w); if(m->c2 > -1e-7 && m->c2 < 1e-7) m->c2 = 0.0; + m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); if(m->c3 > -1e-7 && m->c3 < 1e-7) m->c3 = 0.0; + } + + /* set translation */ + m->a4 = p->x; m->b4 = p->y; m->c4 = p->z; + + m->d1 = 0; m->d2 = 0; m->d3 = 0; m->d4 = 1; +} + +// ------------------------------------------------------------------------------------------------ +// find a node by name +aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) +{ + unsigned int i; + + ai_assert(pNode != nullptr); + ai_assert(mScene != nullptr); + + if(pNode->mName == name) + return pNode; + for(i = 0; i < pNode->mNumChildren; i++) { + aiNode *pChild = findNode(pNode->mChildren[i], name); + if(pChild) return pChild; + } + return nullptr; +} + +// ------------------------------------------------------------------------------------------------ +// fills up offsetmatrix in mBones +void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) +{ + ai_assert(pNode != nullptr); + ai_assert(mScene != nullptr); + + if(pNode->mParent) { + calculateOffsetMatrix(pNode->mParent, m); + *m *= pNode->mTransformation; + } else { + *m = pNode->mTransformation; + } +} + +// ------------------------------------------------------------------------------------------------ +// because M3D has a global mesh, global vertex ids and stores materialid on the face, we need +// temporary lists to collect data for an aiMesh, which requires local arrays and local indeces +// this function fills up an aiMesh with those temporary lists +void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::vector *vertices, + std::vector *normals, std::vector *texcoords, std::vector *colors, + std::vector *vertexids) { + unsigned int i, j, k, s; + aiNode *pNode; + + ai_assert(pMesh != nullptr); + ai_assert(faces != nullptr); + ai_assert(vertices != nullptr); + ai_assert(normals != nullptr); + ai_assert(texcoords != nullptr); + ai_assert(colors != nullptr); + ai_assert(vertexids != nullptr); + ai_assert(m3d != nullptr); + + ASSIMP_LOG_DEBUG_F("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), + " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); + + if(vertices->size() && faces->size()) { + pMesh->mNumFaces = faces->size(); + pMesh->mFaces = new aiFace[pMesh->mNumFaces]; + std::copy(faces->begin(), faces->end(), pMesh->mFaces); + pMesh->mNumVertices = vertices->size(); + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + std::copy(vertices->begin(), vertices->end(), pMesh->mVertices); + if(normals->size() == vertices->size()) { + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + std::copy(normals->begin(), normals->end(), pMesh->mNormals); + } + if(texcoords->size() == vertices->size()) { + pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices]; + std::copy(texcoords->begin(), texcoords->end(), pMesh->mTextureCoords[0]); + pMesh->mNumUVComponents[0] = 2; + } + if(colors->size() == vertices->size()) { + pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices]; + std::copy(colors->begin(), colors->end(), pMesh->mColors[0]); + } + // this is complicated, because M3D stores a list of bone id / weight pairs per + // vertex but assimp uses lists of local vertex id/weight pairs per local bone list + pMesh->mNumBones = m3d->numbone; + /* we need aiBone with mOffsetMatrix for bones without weights as well */ + if(pMesh->mNumBones) { + pMesh->mBones = new aiBone*[pMesh->mNumBones]; + for(i = 0; i < m3d->numbone; i++) { + pMesh->mBones[i] = new aiBone; + pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name)); + pMesh->mBones[i]->mNumWeights = 0; + pNode = findNode(mScene->mRootNode, pMesh->mBones[i]->mName); + if(pNode) { + calculateOffsetMatrix(pNode, &pMesh->mBones[i]->mOffsetMatrix); + pMesh->mBones[i]->mOffsetMatrix.Inverse(); + } else + pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); + } + if(vertexids->size()) { + // first count how many vertices we have per bone + for(i = 0; i < vertexids->size(); i++) { + s = m3d->vertex[vertexids->at(i)].skinid; + if(s != -1U && s!= -2U) { + for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); + for(j = 0; j < pMesh->mNumBones; j++) { + if(pMesh->mBones[j]->mName == name) { + pMesh->mBones[j]->mNumWeights++; + break; + } + } + } + } + } + // allocate mWeights + for(j = 0; j < pMesh->mNumBones; j++) { + aiBone *pBone = pMesh->mBones[j]; + if(pBone->mNumWeights) { + pBone->mWeights = new aiVertexWeight[pBone->mNumWeights]; + pBone->mNumWeights = 0; + } + } + // fill up with data + for(i = 0; i < vertexids->size(); i++) { + s = m3d->vertex[vertexids->at(i)].skinid; + if(s != -1U && s!= -2U) { + for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); + for(j = 0; j < pMesh->mNumBones; j++) { + if(pMesh->mBones[j]->mName == name) { + aiBone *pBone = pMesh->mBones[j]; + pBone->mWeights[pBone->mNumWeights].mVertexId = i; + pBone->mWeights[pBone->mNumWeights].mWeight = m3d->skin[s].weight[k]; + pBone->mNumWeights++; + break; + } + } + } // foreach skin + } + } // foreach vertexids + } + } + } +} + +// ------------------------------------------------------------------------------------------------ + +} // Namespace Assimp + +#endif // !! ASSIMP_BUILD_NO_M3D_IMPORTER diff --git a/code/M3D/M3DImporter.h b/code/M3D/M3DImporter.h new file mode 100644 index 000000000..06cc757b6 --- /dev/null +++ b/code/M3D/M3DImporter.h @@ -0,0 +1,106 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team +Copyright (c) 2019 bzt + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file M3DImporter.h +* @brief Declares the importer class to read a scene from a Model 3D file +*/ +#ifndef AI_M3DIMPORTER_H_INC +#define AI_M3DIMPORTER_H_INC + +#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER + +#include "m3d.h" +#include +#include +#include + +struct aiMesh; +struct aiNode; +struct aiMaterial; +struct aiFace; + +namespace Assimp { + +class M3DImporter : public BaseImporter { +public: + /// \brief Default constructor + M3DImporter(); + + /// \brief Destructor + ~M3DImporter(); + +public: + /// \brief Returns whether the class can handle the format of the given file. + /// \remark See BaseImporter::CanRead() for details. + bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; + +private: + aiScene* mScene; // the scene to import to + m3d_t *m3d; // model for the C library to convert from + + //! \brief Appends the supported extension. + const aiImporterDesc* GetInfo () const; + + //! \brief File import implementation. + void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); + + void importMaterials(); + void importTextures(); + void importMeshes(); + void importBones(unsigned int parentid, aiNode *pParent); + void importAnimations(); + + // helper functions + aiColor4D mkColor(uint32_t c); + void convertPose(aiMatrix4x4 *m, unsigned int posid, unsigned int orientid); + aiNode *findNode(aiNode *pNode, aiString name); + void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m); + void populateMesh(aiMesh *pMesh, std::vector *faces, std::vector *verteces, + std::vector *normals, std::vector *texcoords, std::vector *colors, + std::vector *vertexids); +}; + +} // Namespace Assimp + +#endif // ASSIMP_BUILD_NO_M3D_IMPORTER + +#endif // AI_M3DIMPORTER_H_INC diff --git a/code/M3D/M3DMaterials.h b/code/M3D/M3DMaterials.h new file mode 100644 index 000000000..86a802021 --- /dev/null +++ b/code/M3D/M3DMaterials.h @@ -0,0 +1,106 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team +Copyright (c) 2019 bzt + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file M3DMaterials.h +* @brief Declares the Assimp and Model 3D file material type relations +*/ +#ifndef AI_M3DMATERIALS_H_INC +#define AI_M3DMATERIALS_H_INC + +/* + * In the m3d.h header, there's a static array which defines the material + * properties, called m3d_propertytypes. These must have the same size, and + * list the matching Assimp materials for those properties. Used by both the + * M3DImporter and the M3DExporter, so you have to define these relations + * only once. D.R.Y. and K.I.S.S. + */ +typedef struct { + char *pKey; + unsigned int type; + unsigned int index; +} aiMatProp; + +/* --- Scalar Properties --- !!!!! must match m3d_propertytypes !!!!! */ +static aiMatProp aiProps[] = { + { AI_MATKEY_COLOR_DIFFUSE }, /* m3dp_Kd */ + { AI_MATKEY_COLOR_AMBIENT }, /* m3dp_Ka */ + { AI_MATKEY_COLOR_SPECULAR }, /* m3dp_Ks */ + { AI_MATKEY_SHININESS }, /* m3dp_Ns */ + { AI_MATKEY_COLOR_EMISSIVE }, /* m3dp_Ke */ + { AI_MATKEY_COLOR_REFLECTIVE }, /* m3dp_Tf */ + { AI_MATKEY_BUMPSCALING }, /* m3dp_Km */ + { AI_MATKEY_OPACITY }, /* m3dp_d */ + { AI_MATKEY_SHADING_MODEL }, /* m3dp_il */ + + { NULL, 0, 0 }, /* m3dp_Pr */ + { AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */ + { NULL, 0, 0 }, /* m3dp_Ps */ + { AI_MATKEY_REFRACTI }, /* m3dp_Ni */ + { NULL, 0, 0 }, + { NULL, 0, 0 }, + { NULL, 0, 0 }, + { NULL, 0, 0 } +}; + +/* --- Texture Map Properties --- !!!!! must match m3d_propertytypes !!!!! */ +static aiMatProp aiTxProps[] = { + { AI_MATKEY_TEXTURE_DIFFUSE(0) }, /* m3dp_map_Kd */ + { AI_MATKEY_TEXTURE_AMBIENT(0) }, /* m3dp_map_Ka */ + { AI_MATKEY_TEXTURE_SPECULAR(0) }, /* m3dp_map_Ks */ + { AI_MATKEY_TEXTURE_SHININESS(0) }, /* m3dp_map_Ns */ + { AI_MATKEY_TEXTURE_EMISSIVE(0) }, /* m3dp_map_Ke */ + { NULL, 0, 0 }, /* m3dp_map_Tf */ + { AI_MATKEY_TEXTURE_HEIGHT(0) }, /* m3dp_bump */ + { AI_MATKEY_TEXTURE_OPACITY(0) }, /* m3dp_map_d */ + { AI_MATKEY_TEXTURE_REFLECTION(0) }, /* m3dp_refl */ + + { AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */ + { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */ + { NULL, 0, 0 }, /* m3dp_map_Ps */ + { AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION,0) },/* m3dp_map_Ni */ + { NULL, 0, 0 }, + { NULL, 0, 0 }, + { NULL, 0, 0 }, + { NULL, 0, 0 } +}; + +#endif // AI_M3DMATERIALS_H_INC diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h new file mode 120000 index 000000000..bb58a6d64 --- /dev/null +++ b/code/M3D/m3d.h @@ -0,0 +1 @@ +../../../m3d.h \ No newline at end of file diff --git a/test/models/M3D/README.md b/test/models/M3D/README.md new file mode 100644 index 000000000..144d1ec64 --- /dev/null +++ b/test/models/M3D/README.md @@ -0,0 +1,14 @@ +Model 3D Samples +================ + + aliveai_character.m3d - from Minetest aliveai mod (textures, animations, original 47k, m3d 2.5k) + cube.m3d - smallest possible example, 119 bytes only + cube_normals.m3d - cube with normal vectors, 159 bytes + cube_usemtl.m3d - converted from Assimp sample OBJ by the same name, cube with materials + cube_with_vertexcolors.m3d - converted from Assimp sample OBJ by the same name, cube with vertex colors + cube_with_vertexcolors.a3d - same, but saved in ASCII variant with Windows line endings (\r\n) + mobs_dwarves_character.m3d - from Minetest mobs_dwarves mod (with Assimp artifacts converted perfectly too...) + suzanne.m3d - exported from Blender (monkey face, with normals and texture UVs and materials) + WusonBlitz0.m3d - from Assimp sample by the same name (was 87k, triangle mesh) with int8 coordinates, minor quality degradation + WusonBlitz1.m3d - same, but uses int16 coordinates (no noticable difference to the original, but just 35k) + WusonBlitz2.m3d - same, but with 32 bit floating point numbers (same precision as the original, half the file size, 42k) diff --git a/test/models/M3D/WusonBlitz0.m3d b/test/models/M3D/WusonBlitz0.m3d new file mode 100644 index 0000000000000000000000000000000000000000..29a397b7915ba06070c728840890f2099b3d001e GIT binary patch literal 29223 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 literal 0 HcmV?d00001 diff --git a/test/models/M3D/WusonBlitz1.m3d b/test/models/M3D/WusonBlitz1.m3d new file mode 100644 index 0000000000000000000000000000000000000000..3661252576ba84b860410277330b71d6fb4fbf08 GIT binary patch literal 35058 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 literal 0 HcmV?d00001 diff --git a/test/models/M3D/WusonBlitz2.m3d b/test/models/M3D/WusonBlitz2.m3d new file mode 100644 index 0000000000000000000000000000000000000000..682876816c37b3d05a5aba27d5267661759bf692 GIT binary patch literal 42228 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 literal 0 HcmV?d00001 diff --git a/test/models/M3D/suzanne.m3d b/test/models/M3D/suzanne.m3d new file mode 100644 index 0000000000000000000000000000000000000000..9bc64d7d787a4cd7c135af96c71cc0c6d8c463f5 GIT binary patch literal 11645 zcmW+*WmuG569z>PkS^&G>F#cMrE5XTRYIC2q`RcMyPKs`TDrSqVQH3JKpMXF`**In zW@qNy_tbfoS58IEn;i+sZ3U3wYM7#cKj7-p&%qRGByAIFY(Rt={tClbx;EuKfl0V| zV8?e|4YR0X!OXbqo<-CoNWR*0`8_eoz} zul3(?VbQZcAairz7gv+<;S1reoHhHS!2|=&$f})ZO4?1P1%o!eZL5{ z9T!Zi$DdEmR|2=Am4#ZiHr3FYDDFutoddAlN?aJFxJapiZKD<9_M_AKMGdggo|N3LVR)9;0EMzQ+Z&<{wmSXF1*N zjvj-kj2>LF=C{x0HabwRQbp`NR&u4)uy1##A@?}sSKF};YLRY^eI_~B&)=t310lzf z_ZPKKv!1??hl;QC_m69yGBMx1iwh;@o%9E#*NdB|m+o!^Vm>~tS^c-lxr%L_MRlY2 zxKsslQ92V6*d0%tT?G#w&`uP*;p^x_Ks+_Mc9jJ$KhZ+S(?Lc4cCmfjf7hltk zxM}LSJ1!CN`})$wg0I!WO?x+Z^mIO@7lu(cvI@b)A)VAbET%upZWN0o9~o~uVy9^j zY0rK|ay;1`Ud;d-Uc`3i3l~Lv((bK}1lNH_7n)Et+b-4j3obH$w9pgcsnoL9E^1X{ zT(c7If8OMHMyio7T!v)Rdpu8h%f*n)_?$l5#5k;He|{(!B`6~h#XjZZcDE0?2vcKx zrjTUY%5dRqdSE%+-KqZVwR*BUSFQQ=@b>V0x)(zAJbS*MO@6-<`<)=U-^ZbE`*uVLrziN#bO!9mm6?q;j-5*0!!koz^sq&Nxx3o7?etzmRhs6UtnXk`8E;&_wS!md0!Vjb9{K}fVB#LerJbuL5jWd!(1Da zZw%KhO&0s+u)X!2AsZ6(MV5{~_amDW@bd|*8bp`q+RRRp0VXjEkj0u$9oty~SYLQc z=S@gCwJAEc?}%hYBSYQA9sYX~bnPVLbu<`FU0UakO1EVb@6vC!0<(fjmw)e7^Z#A2 z(ymaQ$4bJ{Cii(fsnlScb;OT$5r5q6p{_qN8^|hk*jbFigTZWWf6SUIk#X47nU2+I z)I)zXWj(9`drN+1WDBJ2cL=qOR>noFvfX>h241VA`2Mb#R-Le@KP&R4ys4^&{Pr3B ztv2@l@sgewmD=m{+%K?~q;TBVYva5>X2RQJxn60O_*!qlWOzH{m)-l8!(~dfQ>E1n zYws@awsbzL-@SsCYwa7w2kh6trTdjC4ug1C7Xv|?ekYg*$63>H>uy=ZCpIr1hs9vd z@iVcr^>wgI)bfTKEEOwi(YN7fn~0lLfj!Cq4lSQx6=n0bU53FD78t9jTDP*;Z5IYX zJ|OD~_FD28!A{}lZPJs$e&rVrjjI5lj*fwZ+3;G@F0oopla1zuS)SJOqunsc8z0Vx zlk5S8PbAOBi<9ok*OT}I?;a16Hm0K%#2}}Q%?rntYph^}n%}lWgl_k;s9i&fAbOQ}oPC6Euj*rZb6A(=<27`W?^@{5 z$B9Frp2Iw>gF}FaDU4tt5o%99DgPX{%T_Dcf0_a>vJMb#cjH+dHWO~Kr#oBSNOtP~ z6gD0Yf6%0Qk2`9x$PZ;T?pVS%!*?(GylHK`8ros>FZ5UTJzCDdunFR57&F2J6Pjt*J|Vmuw&w%8JeI{7tIkl49_YT z^+%(gKP|hr07W@ZGOb=o*zF=!_~v20z{eq$&zbKH;%_31=v;K2hYdRR4ApFSYqvDJ zQs*GV%R##Qm6K6@O~eMx%J?_l>d`l$S!@FIY-uU|$$Klt1bsi`3(q??zEf~C`7LPy zG+UAyJVh!A1VI`hqhUszf4$OF*I?2pDVT)5wv^aJzUj9m{U8n>w`oEbtzIFeWAWO? z*9pQt&XyCnZOS$+2TEzrnGAp9mvSxHh3p+L1qd=~;vQ2nkA>|uX@JRaR-Dn2Ce!-T zHzBH^o-OO`mXSHswQs64IRuhQk4pJnboZg8Sgki{-z4Z<%9m`WPf`i`wphuWy69*P z?d(|p?rYvQEP;*d3%%kKbvGcX4~bYib)(xY7f-5QpN@%Z2aCMI6VZS+W0uQFEd%Qd zhPFztNZOX;*2_A*{(J0&?kjrz>Z?||6K4iFRMQF?y&sFyC3n2l?uDK5Lsg*FI2Ju^ z(f?HinzT5mdfHLZn0$QJyl4*1(P#bDHdi&2r8u`og;ssRc3~dT^?@$=#^_|=!a2h! zP?a{5$tUr46xOtv1+A`3>-OX*cKoSKG57(^A@kO`AHx3p>EcFEacjF6N7rsSZ8Yh0 zJT6Map5Y=U!dL&X`}S`;?PvIuM4aqH;tnfRkU+B8odpf`dfV^7MXXr^9h>+i{MNPa z?8Ec8zLC)8Gm=0f{_++3pnPA~};( z_`3HF;2}4TlY57zTiyPcFpK^?1yB3p#GDj(GLcE^(RFsa#>k|SdxR!@Bc%{=!X zB=H1RqJK7a>ZB&Yv7BsOyuaYD?J*8iY}l@6^njbyn)RVRuKzltI30HFLk(pYVa$%$ zzuF@=t`1}Wt-JyA@Wmds80D51wVzH3GlbjucG4p92$S@pU1OmSYubn?YdE?6?tlWR0NhzvJR)!(&6yQ)lr=%pAqNVpgjQ_S%fT zuPJcL#ooInG4m9$lA(FIXo=)M{gcj{U-w5Y`O_|ECjgrnnw({0dtBk2px5Yjz z5Q47ATfr)Z%io3hHXOw@hdawVijosoW(f&nKYoY{Fls%+Zcccay)3oRIP4qgfsvp0 z+KiRL*u9GAb-@XL*_QAQ-}1+o*2 zFgw{?;+B+zFWNsj0yS+am+FMGJ%dTMd5ufLu*B(ozHm!0x}-1tQ8JC$m`($Qv2!f2 zg{M3fijicKPr?lGA^5ABHvVZ2Ub&wQI$4{FzwpvWtLT6Pd?T(kLCMF$SZ(J_K-V7MChL2Zrw8q|% z=qT;EP5U)uCoQF8 z4<^Q-P_SMHWllQLFj`+S$to9HbhVx0)`_uF=rxh4(Z<1qLH`2&DpMgpkZnGtIgFh_ zpxnZsbB!(RCJYOoT!YD9={DL+?if&O7T&l&RP5lTbL>;wBYh%NWz0H3)TU`;-~V@w zwi!J{@x@B%#jzhq<700js+#wHf=Co-GhODFn9x1h$IC99=vXXPi_?Sk)=+knG z*$1S3He8-8p>Cgu2%vLYxiF08=5L+OY|H%M!+9YX-lg(5WZ>K~F{acGJpNkyL+wpk zuXXEEQ@Nppxkv_k(z0P{-(tTc!*kJVGxz>-Ekk36pyQH+r7;{6Cu0mC5u%MqYtgrE z{<*gKC_lWmF`ClW3ulg7%xV!w^fKRW;i2yt4u9J zQI?P;BVProE2n4TWZ09E&0#`g3(yWJheY)Aaj=uK+d$HP*qw$k34$SxRZGDcqvt-t zX!Sc3?=ZiNH^xjPU3V%j3~LI!*@eWYZJB6h)9wyd*=fRYP|i<@xjB(jl40hzHb`h-wo4Wbs85dC)TM|o&9fu!tX;y}Mptq;51vVfmKbJZAv zA-ZS%3*9hC-W}HI%sFziP0A>k;Cc5BI!WvczGdw{n>t`}1$zY<44B#14;Z+2-ugy# z={#aV1*_}AG9Y?GpLhQ{!P=DEI&NY8G4Vc&UQ1`FjY4eTIKERi%9gtj0y z{On>*^+hnG%$jd977o{Z&PW6$!6hrQ_ai+m#l+yax}EbGz|x%I`QJKQoc)t{zB23E zk5WfbN$_6HXO~@NRcxz)voIs3zX=#F`11wDwQO`@z_C z6>}j9p&g7aQ{y&O&0GP45$g;te>%3?JB-mzug>_ZG=-xQs=k`HafI!M=deH1U7SU{ zlpc_URjoc@QY4a%`$lxIxx@ixJ|_EHo)gJ#2Mr*m=Ckwm25h+}@=45~)l<-Mhqc|>Mk zB2&_07x6>P09wz``DMiX^PM3xgnpMYfYaW5IY9(13)*sxCkA{JhL$7=kE6F8*{5KT zwDby3^7a8)o++lmgzGlUKzr5BJXxof`HkYW5*gybA5EL2&}w2|#bA^6Pmjye!tHlb z2C6KXy(go?%{8|weZUXT#uxjpS93EoMamnJhl?7yDs| zl(WN89X(595tFSX5G@@+jvhJf+wMOl5EZi#%-P8P1N?Qecsr+r_Tc zn!uOF1-#_Sath53jyY$l^$qtfn-HkNy~K&Z^VB@<9$NS6=G;Y(^K2Tu1SVNY!-UqrfA9h4glt)pRPkylfwe48tH!A}`jb=75)flwr}<0#|dK%yID-73rh$i_yi+{IIoMR2Y7ln-y z1A-avJv6^Uq*l8Vd9k8EA3ETuD_-RTGyWe@!4JhVUn4C)V)5yMLA30Re6=$#ItVjR z@UAlyUNNOZPGGk}M$HLI{f1xE=yERy`I@dW<5t(O+;dB4*;FtfIt+6a=!`I>ncoa6 z-D(?oaOQQRv%2MTUq2-~qdi-hz5NRR-JwE#s0Ez&kekwxJhXUepQfVWybP7bigEa4 zs6ft(=Fo7;ZGJA7B^>%Lu~5uPUG{Dq(u43*WHyz z7nE}`eogqZ2!KIi4>Cj;)n)gO40tv`6$@STuO~%xHDve2d62;h*j#5Cy)lVB)I|;! zfZ*FU9?lJ3DzH>A85Le>gS^}n=!AsspjiTwWk(8v=deSQgP}L?MH^kYr}aH3_d3)h z2wujuGUd_7y>h2Lgxo;oupRicoJ?ks@;M-Rzf9*p51n*CeD3@}bzEc> z|5UkE)(88Ja)JN83X*kw)@)mrYLowDRdKOu%GH!X$s;0)Wp!)Bquj>dIrxs>GYZ0} z#MyhC!W?U<-b)=@D^YqO%ku_%zbtylP{^vzRFjfd!eCD&+Fu7SXm*;VKL0r_uq0BF zo!}(W|8J#oi_<_(N||TR&d5%?g?cYAzRX*1Th}xk$p4(q<_FvRrF@lv%HQzz!l2IH zj{K#%GE21lH!J3T_Qj3aiI{p)(_5nZV3)?5sd9`nGmApnI=&GhxLftBt15Jwx$_}H z=$k`vtxz!@K{Zy7;}jX@^h;NHKPgiaykh#`{~qe+q3Mye$;tqUraL zp*>e|=(I8J>gf^!c|l}UyqFg}S7FRbBABDo@3pdj?tSy2qoR!{f8{H17KC{fss}C2e2DtZp&td||Z;JKR1uybz>p z3)i>;mld$^?ZReUKk7$l17bP_uhCbL|GvX1L4Nv17JrHqb)c|~?r{A2cLrZ^jxxa? zyIhuIB$Y#R0$D1AwA|`bSL)uJ%ujao2fvsihhm~eVk3(0g6E|%LJhyw8uHMK+4FwI zlt7eUG0dD5Q#O`JDrw0TA#buenLZ;?%3*j>QMBttEJ zFCIXgw$Gp2p)ifvu+*Md|_v|h2zR+5E{dkAif8i&NSMOKEy8>nYRETw;$d?b?vQYYV9qnH=HWD2Bn@>NaV#|xxYU+I-@brp~Akw+C6iOWxO&P{D>6Ut-7 zv_6Avq9Acq`h?zU2IDwa^tQZ`aaFdZKE)?{B=As^;1@;Fv6l9Al#7doS!J4-w=M|~ ziU>du(QJ_#h5tJxJAKE}8emJHDydp)krS(U%qeVY{*H ze=8zlx3FJkkDVuqYBfG1?WP9?5s>nWsrr^)kt3Bz zHiR7H3oBCr@f8l@h0|}u^MLp-{q+ZR!pS8g#jGDgqGth40gs=5|4_wiDF4$uYWdr4 zqI4mrhAG|4mfAqGW((yB3`75|NyjRTAI=rX?c#yy5WEQ@}m-yT&( zMLbsi2(dn}Ke>=AVm^?JiWSdR8a9og!(eq#;@rY653miwDz;kCZKl=krOTDS#jdtg z(qhL1$28<=uRf7s!hbsO-42! ziX_;|+2xIF37zXLo3Ndmsp6=bIIbHyZ1}EyzG$n3-!I+I={8cu`7|M4H@~)#_1O8Y zLC;KPAue979|If=m4$6>3i32ibw%J&o089(EYJr42V+)0@+}>4TK47Cs91(xhi)!j zBnbSN-dDK^#~%TUj4B65Xl{h0eum@D?t zwly06mFPbI>aVZOx9QVonSwS39?ciGjf$WW@RQYGh3@ICh6*)39NaM+Y zIBeF|lZ;*dv*uN&N->UUgDu+qkdKYl0Rdu5l4znVvWPs9%h8Xy{j!=SQJ=HQaTWY? zzIaBr{C>^F`%BQaW; zp+!37f4(CYFC;m3)J0v#??gkNn|zABBY%`x{qlbNjz?!92#g4Qu|kt%v-*(}OKI9f zDdTi(`0!!8-lx+$oOsCYvf-E>^Mtoy$U}~JHSa3M$oNG;2@L!ZGVK^uT{AhO2*cAe z3z@ZQ8<0@21_R9%raYoRHIuWSmd{=yZ0b0tezf&>{%2sORL?o>5_ML?IjahDUDmZ| zF8{lvYguiR|CfKH1~KA6AtkxL6i`6nWK?M~Z7XyuG7DFF4=1q1GEhl}LRXygiTJ0t zcT>tVXzv-vQR+OpJEhTV=~=rfD-|SgmYWakzv|!(3Q^aBW;I}VIi`>}I> zY)WSH5Q&N^N`{h8&JR_YQdq~HIFs0==Y3w20Y{-KzF!ExD~wK~g3EFJS^jjsobU8T z4rF$tL%CD9d4GN~sWMTOs&IPcVBwwo8GhEXp5@ix&0}TW65y2fdj!m!vm?&0^ks@i%xWDUW{mh+v2j! zKK=U}&rJ6v%;(;Pc3*q zu#4A}=CSlSzwn%j#!o8Uhzsj>KS?1^ko=U?q}5$|l9M;oxZx#oqKbo_lCW&OTCXPD z@%k(nt=RfaFk8mZQqW%}OQAjTA!=k#H_53>%U!qUNt!6Ddgr62nQp&IJ{Ka_|E!yq zAJMH5mhX8v3np2$q}!3rYl0O%%shQ=G)l}+b2cHxd^NJQ9U;KdE2==7+{V zoOziDMx?hC+X?iSE(kg~m9|Q};cw_Cw&Q60S-NGiE@o9EK0|EKc1O6M+n;eOV29iY z0JIzYhd#mhTYgS;dng=qMywUThs5ty_YfjtK|#N%wT6Fm5X+C)-F`YMmDS5)LHgMX zv?*!l&QsZq)*X-b5QtqDwi3;)U)!^mm0S*Ka5jf~v?;k<_ud6lT-#fJs7mXW@Ha=S zTW%PC(T`t0w-~Wncf}YecvJp}8?+I&TpY#r)7yzV^RatRn}VHUHRo*nq{7>w0v$md)2^C&-%3@8 z?y;WwS=7>pALW+DG9QOh-BFxke{Q?0yAKd$JCQhz7CR=(=>{Gu*RSU8PS7n0*uMw>j;>vgsC^jE*`oVig!lmSZV1KY> z_Nr`83NR$7Jp@+h%%g-&OqoxZ*hsjVA4WXV2i>NeQg|no+^=MnfYzE%UwQ98-f*P& z*dt21eoMhM&PNmcvTT$O{HdDztBQ7KQ`a?ZKscs(@b~+(s;Qv%>(E=!Da+HT7~K~W z-xg~=Zjdd##IRAx@C1FpwMhSZZkc|+#!{RoBE8PujuHN3HtnP&` zolMZ@AO@BOb!)JWLEqc&93Bn94l~5um$?91TVxVb9Fdr}6DzV+h2ohdB2dNU z0(V9ps2;}>)uHP4u7m|1lJ0 zPZ7J}7iHt3eGYI*5=73(FT_9ipw2wSLLMx%#AsHK3kbmYrwH)>9)Q807>LYUAV#2_ zYc^HI!~e}L(fm~biXxi6S%H*zo)KUxOwk14tqcWRr!mDM{RZQ$zAfGwu6~dX>4#WF zMR9-W03CFeK52xmSplvt8D;?%DmLQB|D5om=`)ma8BA5pd^sRlA~y5J4I$2q=%g1S z-TgKNvPjC6S?F0~(h8)Isz4$7^!70tF8rRz;u25${iT;2?ttDPp2Jwb*H65?oC)+k z?rOwU3xZlJ5iFasQ(p%uAG8m4h*h2V-yEEXJpB_Vx8t=#UgDc)kB~OSCm2@? z7GUe_k2Y-7JexRR#OH}kg7K?T=IOtIhvQEXA+AOyMdIRV?Ec_kH8$-NUjKPaphCQb_s|*Fp*mZ&u-sgxC)8pUAVmh0>6Lm z*HIkSZYnTDgHDk`{nC2uaw~C$&=^47(|%s+d&qOh+3}#9Zmn~2XNjo4)(4&sROh+=W{QIcQVgljU>Xh;y1sw{85$A5X+%(pRnDPFsc=kzOAq;`> zr9=H%rUE`V*}i8yOK%t|ji`I*I}2KXS&T zDZUrENsS_%X%KZ&vjmw5&lCo~tQ==D=6|6YrLi zkQpz?o5YjL0;R~U294D+EbCuVbYs$FgSyZ{kbX!rQ)Oc05?uu$6XdZ&wWT90i~vF< ziFHVl{!WUMw0#bH2pEW8n`dWRhHgJ<-@jJIo=_8~#v9ao_f?J*FSFlc0V;&E==Ri(FK|B8FFqC|e69K&VvF8m@M(S2x_^O!|;1Cy;^$TTy|TY6t0`!cZb&KUA#8 zAY!6c7ZH(puTmp2vi~g;5d2nq#76qf2pU_=1jQK7t`pZKE?QARJuV^X7s?_xu7ZCW zA_Z}tmDsyZ-8+7h)ARm93#oA7Z;mw^i9xayCoF;};b^wZo*^+myqs8bUVlV`OuvN* z3U@*fQS=9b94(Td$Tk!4` zFKMh@Cwpqd>kS{#8?}RhUq<#fi3z&O)n$GCw-zZ*>5`y5XM9g@P|05HynaiJ;PsFR z^eP<90hdkj!f!@H0*w#{I^VAW^yX@c$%cp=IU39x*M6{XH zFM>F9>ffIau((fuB~A8#x!#i0h_Yd z{A-tQwTD8=V{tmN2FZGlrpeW~kiL9Y{IgX>2`Vqd|Bqmb&rQort~M6OtB=rDu3gE7-lw76+xJ9 zN&BQhOtr}18JP-Xe00 z$^<1bSB9b?Qd7;%6VZA%XevTwD+qB?$^U5(BrVIJm|_hW-esl>%q(aoD==sOXJGJ* z>|4O1F0n$F9ZU=eZVmTzrnDVXi)@M)4BfU9f>>-*=`mCFIcUX!8XP7on=jvs_Fb!z znS?mZiCR|b#(o&-`PN}9&ccp>N3n<|;2L#8>W<=A_%4+!Q*R`bF8WDnQDA|0DBVjL zYl*0+PpUijMlp=`6_HNM1Yk^(!Eg#xdTwZDH3bsWbrmjEmvt51ktO|Lk4=M|xP-Ki zgpDfqYlbJ3^$9uuwSz@cGBSOBvz@wsanE`>0vr{@yp|0RIz3D@LT(JmkS;RA9n8wz zAeAYic*pdvhP_;dLU7iD5lbIcaCW38SANYA_9Osp+0_Y0bKON0`bN?=rFQVDyG2r2 zPlp&hZw=S(K5xDf8cnSitYb+UiOYmuWY%4L@b)`#U>%Y}UcG=o6_*{j}&)s88?17bmzUum@^toQx7Nl4I0dn=b)p8M+ znPSlj6l%!*o*3w_*otk>l`9D^lL}}0{EEn@569O>YnnnQ4&v>+(OV(!pfqGT4diNNRo*On4~eZzuxFyL+UH zP+q~YUP*^x?NF_FHN5+zF8oHF{k`;@IyS14jPRQp^i%?ol`oV-A^6gptg)|)`f5CK z0s5$7$WX=1?+h{-F;Y^7hy118+)SkYZ(WcW3~T=4p~>e_ymP@soC9g9&O(JYH1yu> z5cK`R=b#aZRWp;r?SkeX19m?r!lWp~!ZexH{V&w3Udx4)<09AQ1z~FE>Ll7re~fef zN7P%UT7P1^MLZeSRNoPs@5%qZxzHHq&iH&+l`a}1)^=0K0uFtE=VcP{gy|J$64ga3 zOI6&-eEb;{i(dMZA`U&WzC4!M!dcbN9(gt2>6H`4og5Z`Hb>E9tKkpTyKtF1^y3~6 z{VnAnokJX4>QLC-TcQ>mE*iy_O+tXnn-VVQrhKA3a!-Eb+qWcrNs7`GC=qq6G={in zJ^4YH@9_~_wrrkg2XAaMm;ce4GL~@phxtX4xgn(z_CM8JO}PGJjFGg#U0t|P!$_5% W?QqGf)qqRRMyLE2$&$JCoc{se_CU4( literal 0 HcmV?d00001 From a622e109a0739435e3e2f05bfbedba0e8385282d Mon Sep 17 00:00:00 2001 From: bzt Date: Tue, 29 Oct 2019 18:42:10 +0100 Subject: [PATCH 048/170] Fixed PR Quality Review Issues --- code/M3D/M3DExporter.cpp | 9 +- code/M3D/M3DImporter.cpp | 11 +- code/M3D/m3d.h | 4530 +++++++++++++++++++++++++++++++++++++- 3 files changed, 4539 insertions(+), 11 deletions(-) mode change 120000 => 100644 code/M3D/m3d.h diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index 35cae078a..d25b91891 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -174,15 +174,14 @@ void M3DExporter::doExport ( // recursive node walker void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) { - unsigned int i, j, k, l, n, mi, idx; + unsigned int i, j, k, l, n, idx; aiMatrix4x4 nm = m * pNode->mTransformation; m3dv_t vertex; m3dti_t ti; for(i = 0; i < pNode->mNumMeshes; i++) { const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]]; - - mi = (M3D_INDEX)-1U; + unsigned int mi = (M3D_INDEX)-1U; if(mScene->mMaterials) { // get the material for this mesh mi = addMaterial(mScene->mMaterials[mesh->mMaterialIndex]); @@ -263,7 +262,7 @@ uint32_t M3DExporter::mkColor(aiColor4D* c) // add a material to the output M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) { - unsigned int i, j, k, mi = -1U; + unsigned int i, j, mi = -1U; aiColor4D c; aiString name; ai_real f; @@ -290,7 +289,7 @@ M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) m3d->material[mi].numprop = 0; m3d->material[mi].prop = NULL; // iterate through the material property table and see what we got - for(k = 0; + for(unsigned int k = 0; k < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); k++) { if(m3d_propertytypes[k].format == m3dpf_map) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 76ba51364..d34cd982f 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -486,7 +486,7 @@ void M3DImporter::importBones(unsigned int parentid, aiNode *pParent) // bone, so we have to convert between the two conceptually different representation forms void M3DImporter::importAnimations() { - unsigned int i, j, k, l, n, pos, ori; + unsigned int i, j, k, l, pos, ori; double t; m3da_t *a; @@ -511,6 +511,7 @@ void M3DImporter::importAnimations() pAnim->mNumChannels = m3d->numbone; pAnim->mChannels = new aiNodeAnim*[pAnim->mNumChannels]; for(l = 0; l < m3d->numbone; l++) { + unsigned int n; pAnim->mChannels[l] = new aiNodeAnim; pAnim->mChannels[l]->mNodeName = aiString(std::string(m3d->bone[l].name)); // now n is the size of positions / orientations arrays @@ -628,8 +629,7 @@ void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::vector *vertices, std::vector *normals, std::vector *texcoords, std::vector *colors, std::vector *vertexids) { - unsigned int i, j, k, s; - aiNode *pNode; + unsigned int i, j, k; ai_assert(pMesh != nullptr); ai_assert(faces != nullptr); @@ -670,6 +670,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v if(pMesh->mNumBones) { pMesh->mBones = new aiBone*[pMesh->mNumBones]; for(i = 0; i < m3d->numbone; i++) { + aiNode *pNode; pMesh->mBones[i] = new aiBone; pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name)); pMesh->mBones[i]->mNumWeights = 0; @@ -683,7 +684,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v if(vertexids->size()) { // first count how many vertices we have per bone for(i = 0; i < vertexids->size(); i++) { - s = m3d->vertex[vertexids->at(i)].skinid; + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if(s != -1U && s!= -2U) { for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); @@ -706,7 +707,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v } // fill up with data for(i = 0; i < vertexids->size(); i++) { - s = m3d->vertex[vertexids->at(i)].skinid; + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if(s != -1U && s!= -2U) { for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h deleted file mode 120000 index bb58a6d64..000000000 --- a/code/M3D/m3d.h +++ /dev/null @@ -1 +0,0 @@ -../../../m3d.h \ No newline at end of file diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h new file mode 100644 index 000000000..e7eccc5b2 --- /dev/null +++ b/code/M3D/m3d.h @@ -0,0 +1,4529 @@ +/* + * m3d.h + * + * Copyright (C) 2019 bzt (bztsrc@gitlab) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * @brief ANSI C89 / C++11 single header importer / exporter SDK for the Model 3D (.M3D) format + * https://gitlab.com/bztsrc/model3d + * + * PNG decompressor included from (with minor modifications to make it C89 valid): + * stb_image - v2.13 - public domain image loader - http://nothings.org/stb_image.h + * + * @version: 1.0.0 + */ + +#ifndef _M3D_H_ +#define _M3D_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*** configuration ***/ +#ifndef M3D_MALLOC +# define M3D_MALLOC(sz) malloc(sz) +#endif +#ifndef M3D_REALLOC +# define M3D_REALLOC(p,nsz) realloc(p,nsz) +#endif +#ifndef M3D_FREE +# define M3D_FREE(p) free(p) +#endif +#ifndef M3D_LOG +# define M3D_LOG(x) +#endif +#ifndef M3D_APIVERSION +#define M3D_APIVERSION 0x0100 +#ifndef M3D_DOUBLE +typedef float M3D_FLOAT; +#else +typedef double M3D_FLOAT; +#endif +#if !defined(M3D_SMALLINDEX) +typedef uint32_t M3D_INDEX; +#define M3D_INDEXMAX 0xfffffffe +#else +typedef uint16_t M3D_INDEX; +#define M3D_INDEXMAX 0xfffe +#endif +#ifndef M3D_NUMBONE +#define M3D_NUMBONE 4 +#endif +#ifndef M3D_BONEMAXLEVEL +#define M3D_BONEMAXLEVEL 8 +#endif + +/*** File format structures ***/ + +/** + * M3D file format structure + * 3DMO m3dchunk_t file header chunk, may followed by compressed data + * HEAD m3dhdr_t model header chunk + * n x m3dchunk_t more chunks follow + * CMAP color map chunk (optional) + * TMAP texture map chunk (optional) + * VRTS vertex data chunk (optional if it's a material library) + * BONE bind-pose skeleton, bone hierarchy chunk (optional) + * n x m3db_t contains propably more, but at least one bone + * MTRL* material chunk(s), can be more (optional) + * n x m3dp_t each material contains propapbly more, but at least one property + * the properties are configurable with a static array, see m3d_propertytypes + * n x m3dchunk_t at least one, but maybe more face chunks + * PROC* procedural face, or + * MESH* triangle mesh (vertex index list) + * ACTN* action chunk(s), animation-pose skeletons, can be more (optional) + * n x m3dfr_t each action contains probably more, but at least one frame + * n x m3dtr_t each frame contains probably more, but at least one transformation + * ASET* inlined asset chunk(s), can be more (optional) + * OMD3 end chunk + */ +typedef struct { + char magic[4]; + uint32_t length; + float scale; /* deliberately not M3D_FLOAT */ + uint32_t types; +} __attribute__((packed)) m3dhdr_t; + +typedef struct { + char magic[4]; + uint32_t length; +} __attribute__((packed)) m3dchunk_t; + +/*** in-memory model structure ***/ + +/* textmap entry */ +typedef struct { + M3D_FLOAT u; + M3D_FLOAT v; +} m3dti_t; + +/* texture */ +typedef struct { + char *name; /* texture name */ + uint32_t *d; /* pixels data */ + uint16_t w; /* width */ + uint16_t h; /* height */ +} __attribute__((packed)) m3dtx_t; + +typedef struct { + M3D_INDEX vertexid; + M3D_FLOAT weight; +} m3dw_t; + +/* bone entry */ +typedef struct { + M3D_INDEX parent; /* parent bone index */ + char *name; /* name for this bone */ + M3D_INDEX pos; /* vertex index position */ + M3D_INDEX ori; /* vertex index orientation (quaternion) */ + M3D_INDEX numweight; /* number of controlled vertices */ + m3dw_t *weight; /* weights for those vertices */ + M3D_FLOAT mat4[16]; /* transformation matrix */ +} m3db_t; + +/* skin: bone per vertex entry */ +typedef struct { + M3D_INDEX boneid[M3D_NUMBONE]; + M3D_FLOAT weight[M3D_NUMBONE]; +} m3ds_t; + +/* vertex entry */ +typedef struct { + M3D_FLOAT x; /* 3D coordinates and weight */ + M3D_FLOAT y; + M3D_FLOAT z; + M3D_FLOAT w; + uint32_t color; /* default vertex color */ + M3D_INDEX skinid; /* skin index */ +} m3dv_t; + +/* material property formats */ +enum { + m3dpf_color, + m3dpf_uint8, + m3dpf_uint16, + m3dpf_uint32, + m3dpf_float, + m3dpf_map +}; +typedef struct { + uint8_t format; + uint8_t id; +#ifdef M3D_ASCII +#define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) } + char *key; +#else +#define M3D_PROPERTYDEF(f,i,n) { (f), (i) } +#endif +} m3dpd_t; + +/* material properties */ +/* You shouldn't change the first 8 display and first 4 physical property. Assign the rest as you like. */ +enum { + m3dp_Kd = 0, /* scalar display properties */ + m3dp_Ka, + m3dp_Ks, + m3dp_Ns, + m3dp_Ke, + m3dp_Tf, + m3dp_Km, + m3dp_d, + m3dp_il, + + m3dp_Pr = 64, /* scalar physical properties */ + m3dp_Pm, + m3dp_Ps, + m3dp_Ni, + + m3dp_map_Kd = 128, /* textured display map properties */ + m3dp_map_Ka, + m3dp_map_Ks, + m3dp_map_Ns, + m3dp_map_Ke, + m3dp_map_Tf, + m3dp_map_Km, /* bump map */ + m3dp_map_D, + m3dp_map_il, /* reflection map */ + + m3dp_map_Pr = 192, /* textured physical map properties */ + m3dp_map_Pm, + m3dp_map_Ps, + m3dp_map_Ni +}; +enum { /* aliases */ + m3dp_bump = m3dp_map_Km, + m3dp_refl = m3dp_map_Pm +}; + +/* material property */ +typedef struct { + uint8_t type; /* property type, see "m3dp_*" enumeration */ + union { + uint32_t color; /* if value is a color, m3dpf_color */ + uint32_t num; /* if value is a number, m3dpf_uint8, m3pf_uint16, m3dpf_uint32 */ + float fnum; /* if value is a floating point number, m3dpf_float */ + M3D_INDEX textureid; /* if value is a texture, m3dpf_map */ + } value; +} m3dp_t; + +/* material entry */ +typedef struct { + char *name; /* name of the material */ + uint8_t numprop; /* number of properties */ + m3dp_t *prop; /* properties array */ +} m3dm_t; + +/* face entry */ +typedef struct { + M3D_INDEX materialid; /* material index */ + M3D_INDEX vertex[3]; /* 3D points of the triangle in CCW order */ + M3D_INDEX normal[3]; /* normal vectors */ + M3D_INDEX texcoord[3]; /* UV coordinates */ +} m3df_t; + +/* frame transformations entry */ +typedef struct { + M3D_INDEX boneid; /* selects a node in bone hierarchy */ + M3D_INDEX pos; /* vertex index new position */ + M3D_INDEX ori; /* vertex index new orientation (quaternion) */ +} m3dtr_t; + +/* animation frame entry */ +typedef struct { + uint32_t msec; /* frame's position on the timeline, timestamp */ + M3D_INDEX numtransform; /* number of transformations in this frame */ + m3dtr_t *transform; /* transformations */ +} m3dfr_t; + +/* model action entry */ +typedef struct { + char *name; /* name of the action */ + uint32_t durationmsec; /* duration in millisec (1/1000 sec) */ + M3D_INDEX numframe; /* number of frames in this animation */ + m3dfr_t *frame; /* frames array */ +} m3da_t; + +/* inlined asset */ +typedef struct { + char *name; /* asset name (same pointer as in texture[].name) */ + uint8_t *data; /* compressed asset data */ + uint32_t length; /* compressed data length */ +} __attribute__((packed)) m3di_t; + +/*** in-memory model structure ***/ +#define M3D_FLG_FREERAW (1<<0) +#define M3D_FLG_FREESTR (1<<1) +#define M3D_FLG_MTLLIB (1<<2) + +typedef struct { + m3dhdr_t *raw; /* pointer to raw data */ + char flags; /* internal flags */ + char errcode; /* returned error code */ + char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fi_s; /* decoded sizes for types */ + char *name; /* name of the model, like "Utah teapot" */ + char *license; /* usage condition or license, like "MIT", "LGPL" or "BSD-3clause" */ + char *author; /* nickname, email, homepage or github URL etc. */ + char *desc; /* comments, descriptions. May contain '\n' newline character */ + M3D_FLOAT scale; /* the model's bounding cube's size in SI meters */ + M3D_INDEX numcmap; + uint32_t *cmap; /* color map */ + M3D_INDEX numtmap; + m3dti_t *tmap; /* texture map indices */ + M3D_INDEX numtexture; + m3dtx_t *texture; /* uncompressed textures */ + M3D_INDEX numbone; + m3db_t *bone; /* bone hierarchy */ + M3D_INDEX numvertex; + m3dv_t *vertex; /* vertex data */ + M3D_INDEX numskin; + m3ds_t *skin; /* skin data */ + M3D_INDEX nummaterial; + m3dm_t *material; /* material list */ + M3D_INDEX numface; + m3df_t *face; /* model face, triangle mesh */ + M3D_INDEX numaction; + m3da_t *action; /* action animations */ + M3D_INDEX numinlined; + m3di_t *inlined; /* inlined assets */ + M3D_INDEX numunknown; + m3dchunk_t **unknown; /* unknown chunks, application / engine specific data probably */ +} m3d_t; + +/*** export parameters ***/ +#define M3D_EXP_INT8 0 +#define M3D_EXP_INT16 1 +#define M3D_EXP_FLOAT 2 +#define M3D_EXP_DOUBLE 3 + +#define M3D_EXP_NOCMAP (1<<0) +#define M3D_EXP_NOMATERIAL (1<<1) +#define M3D_EXP_NOFACE (1<<2) +#define M3D_EXP_NONORMAL (1<<3) +#define M3D_EXP_NOTXTCRD (1<<4) +#define M3D_EXP_FLIPTXTCRD (1<<5) +#define M3D_EXP_NORECALC (1<<6) +#define M3D_EXP_IDOSUCK (1<<7) +#define M3D_EXP_NOBONE (1<<8) +#define M3D_EXP_NOACTION (1<<9) +#define M3D_EXP_INLINE (1<<10) +#define M3D_EXP_EXTRA (1<<11) +#define M3D_EXP_NOZLIB (1<<14) +#define M3D_EXP_ASCII (1<<15) + +/*** error codes ***/ +#define M3D_SUCCESS 0 +#define M3D_ERR_ALLOC -1 +#define M3D_ERR_BADFILE -2 +#define M3D_ERR_UNIMPL -65 +#define M3D_ERR_UNKPROP -66 +#define M3D_ERR_UNKMESH -67 +#define M3D_ERR_UNKIMG -68 +#define M3D_ERR_UNKFRAME -69 +#define M3D_ERR_TRUNC -70 +#define M3D_ERR_CMAP -71 +#define M3D_ERR_TMAP -72 +#define M3D_ERR_VRTS -73 +#define M3D_ERR_BONE -74 +#define M3D_ERR_MTRL -75 + +#define M3D_ERR_ISFATAL(x) ((x) < 0 && (x) > -65) + +/* callbacks */ +typedef unsigned char *(*m3dread_t)(char *filename, unsigned int *size); /* read file contents into buffer */ +typedef void (*m3dfree_t)(void *buffer); /* free file contents buffer */ +typedef int (*m3dtxsc_t)(const char *name, const void *script, uint32_t len, m3dtx_t *output); /* interpret texture script */ +typedef int (*m3dprsc_t)(const char *name, const void *script, uint32_t len, m3d_t *model); /* interpret surface script */ +#endif /* ifndef M3D_APIVERSION */ + +/*** C prototypes ***/ +/* import / export */ +m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d_t *mtllib); +unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size); +void m3d_free(m3d_t *model); +/* generate animation pose skeleton */ +m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t *skeleton); +m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec); + +/* private prototypes used by both importer and exporter */ +m3ds_t *_m3d_addskin(m3ds_t *skin, uint32_t *numskin, m3ds_t *s, uint32_t *idx); +m3dv_t *_m3d_addnorm(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx); +char *_m3d_safestr(char *in, int morelines); + +/*** C implementation ***/ +#ifdef M3D_IMPLEMENTATION +#if !defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER) +/* property definitions */ +static m3dpd_t m3d_propertytypes[] = { + M3D_PROPERTYDEF(m3dpf_color, m3dp_Kd, "Kd"), /* diffuse color */ + M3D_PROPERTYDEF(m3dpf_color, m3dp_Ka, "Ka"), /* ambient color */ + M3D_PROPERTYDEF(m3dpf_color, m3dp_Ks, "Ks"), /* specular color */ + M3D_PROPERTYDEF(m3dpf_float, m3dp_Ns, "Ns"), /* specular exponent */ + M3D_PROPERTYDEF(m3dpf_color, m3dp_Ke, "Ke"), /* emissive (emitting light of this color) */ + M3D_PROPERTYDEF(m3dpf_color, m3dp_Tf, "Tf"), /* transmission color */ + M3D_PROPERTYDEF(m3dpf_float, m3dp_Km, "Km"), /* bump strength */ + M3D_PROPERTYDEF(m3dpf_float, m3dp_d, "d"), /* dissolve (transparency) */ + M3D_PROPERTYDEF(m3dpf_uint8, m3dp_il, "il"), /* illumination model (informational, ignored by PBR-shaders) */ + + M3D_PROPERTYDEF(m3dpf_float, m3dp_Pr, "Pr"), /* roughness */ + M3D_PROPERTYDEF(m3dpf_float, m3dp_Pm, "Pm"), /* metallic, also reflection */ + M3D_PROPERTYDEF(m3dpf_float, m3dp_Ps, "Ps"), /* sheen */ + M3D_PROPERTYDEF(m3dpf_float, m3dp_Ni, "Ni"), /* index of refraction (optical density) */ + + /* aliases, note that "map_*" aliases are handled automatically */ + M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Km, "bump"), + M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Pm, "refl") +}; +#endif + +#include +#include + +#if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H) +/* PNG decompressor from + + stb_image - v2.23 - public domain image loader - http://nothings.org/stb_image.h +*/ +static const char *stbi__g_failure_reason; + +enum +{ + STBI_default = 0, + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; + +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#define STBI_ASSERT(v) +#define STBI_NOTUSED(v) (void)sizeof(v) +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) +#define STBI_MALLOC(sz) M3D_MALLOC(sz) +#define STBI_REALLOC(p,newsz) M3D_REALLOC(p,newsz) +#define STBI_FREE(p) M3D_FREE(p) +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) + +__inline__ static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + return 0; +} + +__inline__ static int stbi__at_eof(stbi__context *s) +{ + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#define stbi__err(x,y) stbi__errstr(y) +static int stbi__errstr(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +__inline__ static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + return a <= 2147483647 - b; +} + +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; + return a <= 2147483647/b; +} + +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + stbi__err("outofmem", "Out of memory"); + return NULL; + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + stbi__err("outofmem", "Out of memory"); + return NULL; + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +#define STBI__ZFAST_BITS 9 +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +__inline__ static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +__inline__ static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +__inline__ static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +__inline__ static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +__inline__ static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137]; + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +__inline__ static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); + return 1; +} + +static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; +static void stbi__init_zdefaults(void) +{ + int i; + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +__inline__ static int stbi__check_png_header(stbi__context *s) +{ + static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + if (s->img_x == x && s->img_y == y) { + if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } else { + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + } + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior = cur - stride; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; + filter_bytes = 1; + width = img_width_bytes; + } + + if (j == 0) filter = first_row_filter[filter]; + + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; + cur[filter_bytes+1] = 255; + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + if (depth == 16) { + cur = a->out + stride*j; + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + p[0] = p[2] * 255 / a; + p[1] = p[1] * 255 / a; + p[2] = t * 255 / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + bpl = (s->img_x * z->depth + 7) / 8; + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + s->img_n = pal_img_n; + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + return stbi__err("invalid_chunk", "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) { stbi__err("bad req_comp", "Internal error"); return NULL; } + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + ri->bits_per_channel = p->depth; + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} +#endif + +#if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H) +/* zlib_compressor from + + stb_image_write - v1.13 - public domain - http://nothings.org/stb/stb_image_write.h +*/ +typedef unsigned char stbiw_uc; +typedef unsigned short stbiw_us; + +typedef uint16_t stbiw_uint16; +typedef int16_t stbiw_int16; +typedef uint32_t stbiw_uint32; +typedef int32_t stbiw_int32; + +#define STBIW_MALLOC(s) M3D_MALLOC(s) +#define STBIW_REALLOC(p,ns) M3D_REALLOC(p,ns) +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#define STBIW_FREE M3D_FREE +#define STBIW_MEMMOVE memmove +#define STBIW_UCHAR (uint8_t) +#define STBIW_ASSERT(x) +#define stbiw__sbraw(a) ((int *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); + stbiw__sbpush(out, 0x5e); + stbiw__zlib_add(1,1); + stbiw__zlib_add(1,2); + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + { + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +} +#endif + +#define M3D_CHUNKMAGIC(m, a,b,c,d) ((m)[0]==(a) && (m)[1]==(b) && (m)[2]==(c) && (m)[3]==(d)) + +#ifdef M3D_ASCII +#include /* get sprintf */ +#include /* sprintf and strtod cares about number locale */ +#endif + +#if !defined(M3D_NOIMPORTER) && defined(M3D_ASCII) +/* helper functions for the ASCII parser */ +static char *_m3d_findarg(char *s) { + while(s && *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n') s++; + while(s && *s && (*s == ' ' || *s == '\t')) s++; + return s; +} +static char *_m3d_findnl(char *s) { + while(s && *s && *s != '\r' && *s != '\n') s++; + if(*s == '\r') s++; + if(*s == '\n') s++; + return s; +} +static char *_m3d_gethex(char *s, uint32_t *ret) +{ + if(*s == '#') s++; + *ret = 0; + for(; *s; s++) { + if(*s >= '0' && *s <= '9') { *ret <<= 4; *ret += (uint32_t)(*s-'0'); } + else if(*s >= 'a' && *s <= 'f') { *ret <<= 4; *ret += (uint32_t)(*s-'a'+10); } + else if(*s >= 'A' && *s <= 'F') { *ret <<= 4; *ret += (uint32_t)(*s-'A'+10); } + else break; + } + return _m3d_findarg(s); +} +static char *_m3d_getint(char *s, uint32_t *ret) +{ + char *e = s; + if(!s || !*s) return s; + for(; *e >= '0' && *e <= '9'; e++); + *ret = atoi(s); + return e; +} +static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) +{ + char *e = s; + if(!s || !*s) return s; + for(; *e == '-' || *e == '+' || *e == '.' || (*e >= '0' && *e <= '9') || *e == 'e' || *e == 'E'; e++); + *ret = (M3D_FLOAT)strtod(s, NULL); + return _m3d_findarg(e); +} +#endif +#if !defined(M3D_NODUP) && (defined(M3D_ASCII) || defined(M3D_EXPORTER)) +m3ds_t *_m3d_addskin(m3ds_t *skin, uint32_t *numskin, m3ds_t *s, uint32_t *idx) +{ + uint32_t i; + M3D_FLOAT w = (M3D_FLOAT)0.0; + for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) + w += s->weight[i]; + if(w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) + for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) + s->weight[i] /= w; + if(skin) { + for(i = 0; i < *numskin; i++) + if(!memcmp(&skin[i], s, sizeof(m3ds_t))) { *idx = i; return skin; } + } + skin = (m3ds_t*)M3D_REALLOC(skin, ((*numskin) + 1) * sizeof(m3ds_t)); + memcpy(&skin[*numskin], s, sizeof(m3ds_t)); + *idx = *numskin; + (*numskin)++; + return skin; +} +/* add vertex to list, only compare x,y,z */ +m3dv_t *_m3d_addnorm(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) +{ + uint32_t i; + if(v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0; + if(v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0; + if(v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0; + if(v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0; + if(vrtx) { + for(i = 0; i < *numvrtx; i++) + if(vrtx[i].x == v->x && vrtx[i].y == v->y && vrtx[i].z == v->z) { *idx = i; return vrtx; } + } + vrtx = (m3dv_t*)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t)); + memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t)); + vrtx[*numvrtx].color = 0; + vrtx[*numvrtx].w = (M3D_FLOAT)1.0; + *idx = *numvrtx; + (*numvrtx)++; + return vrtx; +} +/* helper function to create safe strings */ +char *_m3d_safestr(char *in, int morelines) +{ + char *out, *o, *i = in; + int l; + if(!in || !*in) { + out = (char*)M3D_MALLOC(1); + if(!out) return NULL; + out[0] =0; + } else { + for(o = in, l = 0; *o && ((morelines & 1) || (*o != '\r' && *o != '\n')) && l < 256; o++, l++); + out = o = (char*)M3D_MALLOC(l+1); + if(!out) return NULL; + while(*i == ' ' || *i == '\t' || *i == '\r' || (morelines && *i == '\n')) i++; + for(; *i && (morelines || (*i != '\r' && *i != '\n')); i++) { + if(*i == '\r') continue; + if(*i == '\n') { + if(morelines >= 3 && o > out && *(o-1) == '\n') break; + if(i > in && *(i-1) == '\n') continue; + if(morelines & 1) { + if(morelines == 1) *o++ = '\r'; + *o++ = '\n'; + } else + break; + } else + if(*i == ' ' || *i == '\t') { + *o++ = morelines? ' ' : '_'; + } else + *o++ = !morelines && (*i == '/' || *i == '\\') ? '_' : *i; + } + for(; o > out && (*(o-1) == ' ' || *(o-1) == '\t' || *(o-1) == '\r' || *(o-1) == '\n'); o--); + *o = 0; + out = (char*)M3D_REALLOC(out, (uint64_t)o - (uint64_t)out + 1); + } + return out; +} +#endif +#ifndef M3D_NOIMPORTER +/* helper function to load and decode/generate a texture */ +M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char *fn) +{ + unsigned int i, len = 0, w, h; + unsigned char *buff = NULL; + char *fn2; + stbi__context s; + stbi__result_info ri; + + for(i = 0; i < model->numtexture; i++) + if(!strcmp(fn, model->texture[i].name)) return i; + if(readfilecb) { + i = strlen(fn); + if(i < 5 || fn[i - 4] != '.') { + fn2 = (char*)M3D_MALLOC(i + 5); + if(!fn2) { model->errcode = M3D_ERR_ALLOC; return -1U; } + memcpy(fn2, fn, i); + memcpy(fn2+i, ".png", 5); + buff = (*readfilecb)(fn2, &len); + M3D_FREE(fn2); + } + if(!buff) + buff = (*readfilecb)(fn, &len); + } + if(!buff && model->inlined) { + for(i = 0; i < model->numinlined; i++) + if(!strcmp(fn, model->inlined[i].name)) { + buff = model->inlined[i].data; + len = model->inlined[i].length; + freecb = NULL; + break; + } + } + if(!buff) return -1U; + i = model->numtexture++; + model->texture = (m3dtx_t*)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t)); + if(!model->texture) { + if(freecb) (*freecb)(buff); + model->errcode = M3D_ERR_ALLOC; return -1U; + } + model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL; + if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') { + s.read_from_callbacks = 0; + s.img_buffer = s.img_buffer_original = (stbi_uc *) buff; + s.img_buffer_end = s.img_buffer_original_end = (stbi_uc *) buff+len; + w = h = 0; + model->texture[i].d = (uint32_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, STBI_rgb_alpha, &ri); + } else { +#ifdef M3D_TX_INTERP + if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) { + M3D_LOG("Unable to generate texture"); + M3D_LOG(fn); + } +#else + M3D_LOG("Unimplemented interpreter"); + M3D_LOG(fn); +#endif + } + if(freecb) (*freecb)(buff); + if(!model->texture[i].d || !w || !h) { + if(model->texture[i].d) M3D_FREE(model->texture[i].d); + model->errcode = M3D_ERR_UNKIMG; + model->numtexture--; + return -1U; + } + model->texture[i].w = w; + model->texture[i].h = h; + model->texture[i].name = fn; + return i; +} + +/* helper function to load and generate a procedural surface */ +void _m3d_getpr(m3d_t *model, __attribute__((unused)) m3dread_t readfilecb, __attribute__((unused)) m3dfree_t freecb, + __attribute__((unused)) char *fn) +{ +#ifdef M3D_PR_INTERP + unsigned int i, len = 0; + unsigned char *buff = readfilecb ? (*readfilecb)(fn, &len) : NULL; + + if(!buff && model->inlined) { + for(i = 0; i < model->numinlined; i++) + if(!strcmp(fn, model->inlined[i].name)) { + buff = model->inlined[i].data; + len = model->inlined[i].length; + freecb = NULL; + break; + } + } + if(!buff || !len || (model->errcode = M3D_PR_INTERP(fn, buff, len, model)) != M3D_SUCCESS) { + M3D_LOG("Unable to generate procedural surface"); + M3D_LOG(fn); + model->errcode = M3D_ERR_UNKIMG; + } + if(freecb && buff) (*freecb)(buff); +#else + M3D_LOG("Unimplemented interpreter"); + M3D_LOG(fn); + model->errcode = M3D_ERR_UNIMPL; +#endif +} +/* helpers to read indices from data stream */ +#define M3D_GETSTR(x) do{offs=0;data=_m3d_getidx(data,model->si_s,&offs);x=offs?((char*)model->raw+16+offs):NULL;}while(0) +__inline__ static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_INDEX *idx) +{ + switch(type) { + case 1: *idx = data[0] > 253 ? (int8_t)data[0] : data[0]; data++; break; + case 2: *idx = *((uint16_t*)data) > 65533 ? *((int16_t*)data) : *((uint16_t*)data); data += 2; break; + case 4: *idx = *((int32_t*)data); data += 4; break; + } + return data; +} + +/* fast inverse square root calculation. returns 1/sqrt(x) */ +static M3D_FLOAT _m3d_rsq(M3D_FLOAT x) +{ +#ifdef M3D_DOUBLE + return ((M3D_FLOAT)15.0/(M3D_FLOAT)8.0) + ((M3D_FLOAT)-5.0/(M3D_FLOAT)4.0)*x + ((M3D_FLOAT)3.0/(M3D_FLOAT)8.0)*x*x; +#else + /* John Carmack's */ + float x2 = x * 0.5f; + *((uint32_t*)&x) = (0x5f3759df - (*((uint32_t*)&x) >> 1)); + return x * (1.5f - (x2 * x * x)); +#endif +} + +#ifndef M3D_NOANIMATION +/* multiply 4 x 4 matrices. Do not use float *r[16] as argument, because some compilers misinterpret that as + * 16 pointers each pointing to a float, but we need a single pointer to 16 floats. */ +void _m3d_mul(M3D_FLOAT *r, M3D_FLOAT *a, M3D_FLOAT *b) +{ + r[ 0] = b[ 0] * a[ 0] + b[ 4] * a[ 1] + b[ 8] * a[ 2] + b[12] * a[ 3]; + r[ 1] = b[ 1] * a[ 0] + b[ 5] * a[ 1] + b[ 9] * a[ 2] + b[13] * a[ 3]; + r[ 2] = b[ 2] * a[ 0] + b[ 6] * a[ 1] + b[10] * a[ 2] + b[14] * a[ 3]; + r[ 3] = b[ 3] * a[ 0] + b[ 7] * a[ 1] + b[11] * a[ 2] + b[15] * a[ 3]; + r[ 4] = b[ 0] * a[ 4] + b[ 4] * a[ 5] + b[ 8] * a[ 6] + b[12] * a[ 7]; + r[ 5] = b[ 1] * a[ 4] + b[ 5] * a[ 5] + b[ 9] * a[ 6] + b[13] * a[ 7]; + r[ 6] = b[ 2] * a[ 4] + b[ 6] * a[ 5] + b[10] * a[ 6] + b[14] * a[ 7]; + r[ 7] = b[ 3] * a[ 4] + b[ 7] * a[ 5] + b[11] * a[ 6] + b[15] * a[ 7]; + r[ 8] = b[ 0] * a[ 8] + b[ 4] * a[ 9] + b[ 8] * a[10] + b[12] * a[11]; + r[ 9] = b[ 1] * a[ 8] + b[ 5] * a[ 9] + b[ 9] * a[10] + b[13] * a[11]; + r[10] = b[ 2] * a[ 8] + b[ 6] * a[ 9] + b[10] * a[10] + b[14] * a[11]; + r[11] = b[ 3] * a[ 8] + b[ 7] * a[ 9] + b[11] * a[10] + b[15] * a[11]; + r[12] = b[ 0] * a[12] + b[ 4] * a[13] + b[ 8] * a[14] + b[12] * a[15]; + r[13] = b[ 1] * a[12] + b[ 5] * a[13] + b[ 9] * a[14] + b[13] * a[15]; + r[14] = b[ 2] * a[12] + b[ 6] * a[13] + b[10] * a[14] + b[14] * a[15]; + r[15] = b[ 3] * a[12] + b[ 7] * a[13] + b[11] * a[14] + b[15] * a[15]; +} +/* calculate 4 x 4 matrix inverse */ +void _m3d_inv(M3D_FLOAT *m) +{ + M3D_FLOAT r[16]; + M3D_FLOAT det = + m[ 0]*m[ 5]*m[10]*m[15] - m[ 0]*m[ 5]*m[11]*m[14] + m[ 0]*m[ 6]*m[11]*m[13] - m[ 0]*m[ 6]*m[ 9]*m[15] + + m[ 0]*m[ 7]*m[ 9]*m[14] - m[ 0]*m[ 7]*m[10]*m[13] - m[ 1]*m[ 6]*m[11]*m[12] + m[ 1]*m[ 6]*m[ 8]*m[15] + - m[ 1]*m[ 7]*m[ 8]*m[14] + m[ 1]*m[ 7]*m[10]*m[12] - m[ 1]*m[ 4]*m[10]*m[15] + m[ 1]*m[ 4]*m[11]*m[14] + + m[ 2]*m[ 7]*m[ 8]*m[13] - m[ 2]*m[ 7]*m[ 9]*m[12] + m[ 2]*m[ 4]*m[ 9]*m[15] - m[ 2]*m[ 4]*m[11]*m[13] + + m[ 2]*m[ 5]*m[11]*m[12] - m[ 2]*m[ 5]*m[ 8]*m[15] - m[ 3]*m[ 4]*m[ 9]*m[14] + m[ 3]*m[ 4]*m[10]*m[13] + - m[ 3]*m[ 5]*m[10]*m[12] + m[ 3]*m[ 5]*m[ 8]*m[14] - m[ 3]*m[ 6]*m[ 8]*m[13] + m[ 3]*m[ 6]*m[ 9]*m[12]; + if(det == (M3D_FLOAT)0.0 || det == (M3D_FLOAT)-0.0) det = (M3D_FLOAT)1.0; else det = (M3D_FLOAT)1.0 / det; + r[ 0] = det *(m[ 5]*(m[10]*m[15] - m[11]*m[14]) + m[ 6]*(m[11]*m[13] - m[ 9]*m[15]) + m[ 7]*(m[ 9]*m[14] - m[10]*m[13])); + r[ 1] = -det*(m[ 1]*(m[10]*m[15] - m[11]*m[14]) + m[ 2]*(m[11]*m[13] - m[ 9]*m[15]) + m[ 3]*(m[ 9]*m[14] - m[10]*m[13])); + r[ 2] = det *(m[ 1]*(m[ 6]*m[15] - m[ 7]*m[14]) + m[ 2]*(m[ 7]*m[13] - m[ 5]*m[15]) + m[ 3]*(m[ 5]*m[14] - m[ 6]*m[13])); + r[ 3] = -det*(m[ 1]*(m[ 6]*m[11] - m[ 7]*m[10]) + m[ 2]*(m[ 7]*m[ 9] - m[ 5]*m[11]) + m[ 3]*(m[ 5]*m[10] - m[ 6]*m[ 9])); + r[ 4] = -det*(m[ 4]*(m[10]*m[15] - m[11]*m[14]) + m[ 6]*(m[11]*m[12] - m[ 8]*m[15]) + m[ 7]*(m[ 8]*m[14] - m[10]*m[12])); + r[ 5] = det *(m[ 0]*(m[10]*m[15] - m[11]*m[14]) + m[ 2]*(m[11]*m[12] - m[ 8]*m[15]) + m[ 3]*(m[ 8]*m[14] - m[10]*m[12])); + r[ 6] = -det*(m[ 0]*(m[ 6]*m[15] - m[ 7]*m[14]) + m[ 2]*(m[ 7]*m[12] - m[ 4]*m[15]) + m[ 3]*(m[ 4]*m[14] - m[ 6]*m[12])); + r[ 7] = det *(m[ 0]*(m[ 6]*m[11] - m[ 7]*m[10]) + m[ 2]*(m[ 7]*m[ 8] - m[ 4]*m[11]) + m[ 3]*(m[ 4]*m[10] - m[ 6]*m[ 8])); + r[ 8] = det *(m[ 4]*(m[ 9]*m[15] - m[11]*m[13]) + m[ 5]*(m[11]*m[12] - m[ 8]*m[15]) + m[ 7]*(m[ 8]*m[13] - m[ 9]*m[12])); + r[ 9] = -det*(m[ 0]*(m[ 9]*m[15] - m[11]*m[13]) + m[ 1]*(m[11]*m[12] - m[ 8]*m[15]) + m[ 3]*(m[ 8]*m[13] - m[ 9]*m[12])); + r[10] = det *(m[ 0]*(m[ 5]*m[15] - m[ 7]*m[13]) + m[ 1]*(m[ 7]*m[12] - m[ 4]*m[15]) + m[ 3]*(m[ 4]*m[13] - m[ 5]*m[12])); + r[11] = -det*(m[ 0]*(m[ 5]*m[11] - m[ 7]*m[ 9]) + m[ 1]*(m[ 7]*m[ 8] - m[ 4]*m[11]) + m[ 3]*(m[ 4]*m[ 9] - m[ 5]*m[ 8])); + r[12] = -det*(m[ 4]*(m[ 9]*m[14] - m[10]*m[13]) + m[ 5]*(m[10]*m[12] - m[ 8]*m[14]) + m[ 6]*(m[ 8]*m[13] - m[ 9]*m[12])); + r[13] = det *(m[ 0]*(m[ 9]*m[14] - m[10]*m[13]) + m[ 1]*(m[10]*m[12] - m[ 8]*m[14]) + m[ 2]*(m[ 8]*m[13] - m[ 9]*m[12])); + r[14] = -det*(m[ 0]*(m[ 5]*m[14] - m[ 6]*m[13]) + m[ 1]*(m[ 6]*m[12] - m[ 4]*m[14]) + m[ 2]*(m[ 4]*m[13] - m[ 5]*m[12])); + r[15] = det *(m[ 0]*(m[ 5]*m[10] - m[ 6]*m[ 9]) + m[ 1]*(m[ 6]*m[ 8] - m[ 4]*m[10]) + m[ 2]*(m[ 4]*m[ 9] - m[ 5]*m[ 8])); + memcpy(m, &r, sizeof(r)); +} +/* compose a coloumn major 4 x 4 matrix from vec3 position and vec4 orientation/rotation quaternion */ +void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) +{ + if(q->x == (M3D_FLOAT)0.0 && q->y == (M3D_FLOAT)0.0 && q->z >=(M3D_FLOAT) 0.7071065 && q->z <= (M3D_FLOAT)0.7071075 && + q->w == (M3D_FLOAT)0.0) { + r[ 1] = r[ 2] = r[ 4] = r[ 6] = r[ 8] = r[ 9] = (M3D_FLOAT)0.0; + r[ 0] = r[ 5] = r[10] = (M3D_FLOAT)-1.0; + } else { + r[ 0] = 1 - 2 * (q->y * q->y + q->z * q->z); if(r[ 0]>(M3D_FLOAT)-1e-7 && r[ 0]<(M3D_FLOAT)1e-7) r[ 0]=(M3D_FLOAT)0.0; + r[ 1] = 2 * (q->x * q->y - q->z * q->w); if(r[ 1]>(M3D_FLOAT)-1e-7 && r[ 1]<(M3D_FLOAT)1e-7) r[ 1]=(M3D_FLOAT)0.0; + r[ 2] = 2 * (q->x * q->z + q->y * q->w); if(r[ 2]>(M3D_FLOAT)-1e-7 && r[ 2]<(M3D_FLOAT)1e-7) r[ 2]=(M3D_FLOAT)0.0; + r[ 4] = 2 * (q->x * q->y + q->z * q->w); if(r[ 4]>(M3D_FLOAT)-1e-7 && r[ 4]<(M3D_FLOAT)1e-7) r[ 4]=(M3D_FLOAT)0.0; + r[ 5] = 1 - 2 * (q->x * q->x + q->z * q->z); if(r[ 5]>(M3D_FLOAT)-1e-7 && r[ 5]<(M3D_FLOAT)1e-7) r[ 5]=(M3D_FLOAT)0.0; + r[ 6] = 2 * (q->y * q->z - q->x * q->w); if(r[ 6]>(M3D_FLOAT)-1e-7 && r[ 6]<(M3D_FLOAT)1e-7) r[ 6]=(M3D_FLOAT)0.0; + r[ 8] = 2 * (q->x * q->z - q->y * q->w); if(r[ 8]>(M3D_FLOAT)-1e-7 && r[ 8]<(M3D_FLOAT)1e-7) r[ 8]=(M3D_FLOAT)0.0; + r[ 9] = 2 * (q->y * q->z + q->x * q->w); if(r[ 9]>(M3D_FLOAT)-1e-7 && r[ 9]<(M3D_FLOAT)1e-7) r[ 9]=(M3D_FLOAT)0.0; + r[10] = 1 - 2 * (q->x * q->x + q->y * q->y); if(r[10]>(M3D_FLOAT)-1e-7 && r[10]<(M3D_FLOAT)1e-7) r[10]=(M3D_FLOAT)0.0; + } + r[ 3] = p->x; r[ 7] = p->y; r[11] = p->z; + r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1; +} +#endif + +/** + * Function to decode a Model 3D into in-memory format + */ +m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d_t *mtllib) +{ + unsigned char *end, *chunk, *buff, weights[8]; + unsigned int i, j, k, n, am, len = 0, reclen, offs, numnorm = 0; + char *material; + m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb, vn; + m3d_t *model; + M3D_INDEX mi, *ni = NULL, *vi = NULL; + M3D_FLOAT w, r[16]; + m3dtx_t *tx; + m3dm_t *m; + m3da_t *a; + m3db_t *b; + m3di_t *t; + m3ds_t *sk; +#ifdef M3D_ASCII + m3ds_t s; + M3D_INDEX bi[M3D_BONEMAXLEVEL+1], level; + const char *ol; + char *ptr, *pe; +#endif + + if(!data || (!M3D_CHUNKMAGIC(data, '3','D','M','O') +#ifdef M3D_ASCII + && !M3D_CHUNKMAGIC(data, '3','d','m','o') +#endif + )) return NULL; + model = (m3d_t*)M3D_MALLOC(sizeof(m3d_t)); + if(!model) { + M3D_LOG("Out of memory"); + return NULL; + } + memset(model, 0, sizeof(m3d_t)); + + if(mtllib) { + model->nummaterial = mtllib->nummaterial; + model->material = mtllib->material; + model->numtexture = mtllib->numtexture; + model->texture = mtllib->texture; + model->flags |= M3D_FLG_MTLLIB; + } +#ifdef M3D_ASCII + /* ASCII variant? */ + if(M3D_CHUNKMAGIC(data, '3','d','m','o')) { + model->errcode = M3D_ERR_BADFILE; + model->flags |= M3D_FLG_FREESTR; + model->raw = (m3dhdr_t*)data; + ptr = (char*)data; + ol = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); + /* parse header. Don't use sscanf, that's incredibly slow */ + ptr = _m3d_findarg(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + pe = _m3d_findnl(ptr); + model->scale = (float)strtod(ptr, NULL); ptr = pe; + if(model->scale <= (M3D_FLOAT)0.0) model->scale = (M3D_FLOAT)1.0; + model->name = _m3d_safestr(ptr, 0); ptr = _m3d_findnl(ptr); + if(!*ptr) goto asciiend; + model->license = _m3d_safestr(ptr, 2); ptr = _m3d_findnl(ptr); + if(!*ptr) goto asciiend; + model->author = _m3d_safestr(ptr, 2); ptr = _m3d_findnl(ptr); + if(!*ptr) goto asciiend; + model->desc = _m3d_safestr(ptr, 3); + while(*ptr) { + while(*ptr && *ptr!='\n') ptr++; + ptr++; if(*ptr=='\r') ptr++; + if(*ptr == '\n') break; + } + + /* the main chunk reader loop */ + while(*ptr) { + while(*ptr && (*ptr == '\r' || *ptr == '\n')) ptr++; + if(!*ptr || (ptr[0]=='E' && ptr[1]=='n' && ptr[2]=='d')) break; + /* make sure there's at least one data row */ + pe = ptr; ptr = _m3d_findnl(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + /* texture map chunk */ + if(!memcmp(pe, "Textmap", 7)) { + if(model->tmap) { M3D_LOG("More texture map chunks, should be unique"); goto asciiend; } + while(*ptr && *ptr != '\r' && *ptr != '\n') { + i = model->numtmap++; + model->tmap = (m3dti_t*)M3D_REALLOC(model->tmap, model->numtmap * sizeof(m3dti_t)); + if(!model->tmap) goto memerr; + ptr = _m3d_getfloat(ptr, &model->tmap[i].u); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + ptr = _m3d_getfloat(ptr, &model->tmap[i].v); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + ptr = _m3d_findnl(ptr); + } + } else + /* vertex chunk */ + if(!memcmp(pe, "Vertex", 6)) { + if(model->vertex) { M3D_LOG("More vertex chunks, should be unique"); goto asciiend; } + while(*ptr && *ptr != '\r' && *ptr != '\n') { + i = model->numvertex++; + model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t)); + if(!model->vertex) goto memerr; + model->vertex[i].skinid = (M3D_INDEX)-1U; + model->vertex[i].color = 0; + ptr = _m3d_getfloat(ptr, &model->vertex[i].x); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + ptr = _m3d_getfloat(ptr, &model->vertex[i].y); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + ptr = _m3d_getfloat(ptr, &model->vertex[i].z); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + ptr = _m3d_getfloat(ptr, &model->vertex[i].w); + if(model->vertex[i].w != 1.0) model->vertex[i].skinid = (M3D_INDEX)-2U; + if(!*ptr) goto asciiend; + if(*ptr == '#') { + ptr = _m3d_gethex(ptr, &model->vertex[i].color); + if(!*ptr) goto asciiend; + } + /* parse skin */ + memset(&s, 0, sizeof(m3ds_t)); + for(j = 0; j < M3D_NUMBONE && *ptr && *ptr != '\r' && *ptr != '\n'; j++) { + ptr = _m3d_findarg(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + ptr = _m3d_getint(ptr, &k); + s.boneid[j] = (M3D_INDEX)k; + if(*ptr == ':') { + ptr++; + ptr = _m3d_getfloat(ptr, &s.weight[j]); + } else if(!j) + s.weight[j] = (M3D_FLOAT)1.0; + if(!*ptr) goto asciiend; + } + if(s.boneid[0] != (M3D_INDEX)-1U && s.weight[0] > (M3D_FLOAT)0.0) { + model->skin = _m3d_addskin(model->skin, &model->numskin, &s, &k); + model->vertex[i].skinid = (M3D_INDEX)k; + } + ptr = _m3d_findnl(ptr); + } + } else + /* Skeleton, bone hierarchy */ + if(!memcmp(pe, "Bones", 5)) { + if(model->bone) { M3D_LOG("More bones chunks, should be unique"); goto asciiend; } + bi[0] = (M3D_INDEX)-1U; + while(*ptr && *ptr != '\r' && *ptr != '\n') { + i = model->numbone++; + model->bone = (m3db_t*)M3D_REALLOC(model->bone, model->numbone * sizeof(m3db_t)); + if(!model->bone) goto memerr; + for(level = 0; *ptr == '/'; ptr++, level++); + if(level > M3D_BONEMAXLEVEL || !*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + bi[level+1] = i; + model->bone[i].numweight = 0; + model->bone[i].weight = NULL; + model->bone[i].parent = bi[level]; + ptr = _m3d_getint(ptr, &k); + ptr = _m3d_findarg(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + model->bone[i].pos = (M3D_INDEX)k; + ptr = _m3d_getint(ptr, &k); + ptr = _m3d_findarg(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + model->bone[i].ori = (M3D_INDEX)k; + pe = _m3d_safestr(ptr, 0); + if(!pe || !*pe) goto asciiend; + model->bone[i].name = pe; + ptr = _m3d_findnl(ptr); + } + } else + /* material chunk */ + if(!memcmp(pe, "Material", 8)) { + pe = _m3d_findarg(pe); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + pe = _m3d_safestr(pe, 0); + if(!pe || !*pe) goto asciiend; + for(i = 0; i < model->nummaterial; i++) + if(!strcmp(pe, model->material[i].name)) { + M3D_LOG("Multiple definitions for material"); + M3D_LOG(pe); + M3D_FREE(pe); + pe = NULL; + while(*ptr && *ptr != '\r' && *ptr != '\n') ptr = _m3d_findnl(ptr); + break; + } + if(!pe) continue; + i = model->nummaterial++; + if(model->flags & M3D_FLG_MTLLIB) { + m = model->material; + model->material = (m3dm_t*)M3D_MALLOC(model->nummaterial * sizeof(m3dm_t)); + if(!model->material) goto memerr; + memcpy(model->material, m, (model->nummaterial - 1) * sizeof(m3dm_t)); + if(model->texture) { + tx = model->texture; + model->texture = (m3dtx_t*)M3D_MALLOC(model->numtexture * sizeof(m3dtx_t)); + if(!model->texture) goto memerr; + memcpy(model->texture, tx, model->numtexture * sizeof(m3dm_t)); + } + model->flags &= ~M3D_FLG_MTLLIB; + } else { + model->material = (m3dm_t*)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t)); + if(!model->material) goto memerr; + } + m = &model->material[i]; + m->name = pe; + m->numprop = 0; + m->prop = NULL; + while(*ptr && *ptr != '\r' && *ptr != '\n') { + k = n = 256; + if(*ptr == 'm' && *(ptr+1) == 'a' && *(ptr+2) == 'p' && *(ptr+3) == '_') { + k = m3dpf_map; + ptr += 4; + } + for(j = 0; j < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); j++) + if(!memcmp(ptr, m3d_propertytypes[j].key, strlen(m3d_propertytypes[j].key))) { + n = m3d_propertytypes[j].id; + if(k != m3dpf_map) k = m3d_propertytypes[j].format; + break; + } + if(n != 256 && k != 256) { + ptr = _m3d_findarg(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + j = m->numprop++; + m->prop = (m3dp_t*)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t)); + if(!m->prop) goto memerr; + m->prop[j].type = n; + switch(k) { + case m3dpf_color: ptr = _m3d_gethex(ptr, &m->prop[j].value.color); break; + case m3dpf_uint8: + case m3dpf_uint16: + case m3dpf_uint32: ptr = _m3d_getint(ptr, &m->prop[j].value.num); break; + case m3dpf_float: ptr = _m3d_getfloat(ptr, &m->prop[j].value.fnum); break; + case m3dpf_map: + pe = _m3d_safestr(ptr, 0); + if(!pe || !*pe) goto asciiend; + m->prop[j].value.textureid = _m3d_gettx(model, readfilecb, freecb, pe); + if(model->errcode == M3D_ERR_ALLOC) { M3D_FREE(pe); goto memerr; } + if(m->prop[j].value.textureid == (M3D_INDEX)-1U) { + M3D_LOG("Texture not found"); + M3D_LOG(pe); + m->numprop--; + } + M3D_FREE(pe); + break; + } + } else { + M3D_LOG("Unknown material property in"); + M3D_LOG(m->name); + model->errcode = M3D_ERR_UNKPROP; + } + ptr = _m3d_findnl(ptr); + } + if(!m->numprop) model->nummaterial--; + } else + /* procedural, not implemented yet, skip chunk */ + if(!memcmp(pe, "Procedural", 10)) { + pe = _m3d_safestr(ptr, 0); + _m3d_getpr(model, readfilecb, freecb, pe); + M3D_FREE(pe); + while(*ptr && *ptr != '\r' && *ptr != '\n') ptr = _m3d_findnl(ptr); + } else + /* mesh */ + if(!memcmp(pe, "Mesh", 4)) { + mi = (M3D_INDEX)-1U; + while(*ptr && *ptr != '\r' && *ptr != '\n') { + if(*ptr == 'u') { + ptr = _m3d_findarg(ptr); + if(!*ptr) goto asciiend; + mi = (M3D_INDEX)-1U; + if(*ptr != '\r' && *ptr != '\n') { + pe = _m3d_safestr(ptr, 0); + if(!pe || !*pe) goto asciiend; + for(j = 0; j < model->nummaterial; j++) + if(!strcmp(pe, model->material[j].name)) { + mi = (M3D_INDEX)j; + break; + } + M3D_FREE(pe); + } + } else { + i = model->numface++; + model->face = (m3df_t*)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t)); + if(!model->face) goto memerr; + memset(&model->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */ + model->face[i].materialid = mi; + /* hardcoded triangles. */ + for(j = 0; j < 3; j++) { + /* vertex */ + ptr = _m3d_getint(ptr, &k); + model->face[i].vertex[j] = (M3D_INDEX)k; + if(!*ptr) goto asciiend; + if(*ptr == '/') { + ptr++; + if(*ptr != '/') { + /* texcoord */ + ptr = _m3d_getint(ptr, &k); + model->face[i].texcoord[j] = (M3D_INDEX)k; + if(!*ptr) goto asciiend; + } + if(*ptr == '/') { + ptr++; + /* normal */ + ptr = _m3d_getint(ptr, &k); + model->face[i].normal[j] = (M3D_INDEX)k; + if(!*ptr) goto asciiend; + } + } + ptr = _m3d_findarg(ptr); + } + } + ptr = _m3d_findnl(ptr); + } + } else + /* action */ + if(!memcmp(pe, "Action", 6)) { + pe = _m3d_findarg(pe); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + pe = _m3d_getint(pe, &k); + pe = _m3d_findarg(pe); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + pe = _m3d_safestr(pe, 0); + if(!pe || !*pe) goto asciiend; + i = model->numaction++; + model->action = (m3da_t*)M3D_REALLOC(model->action, model->numaction * sizeof(m3da_t)); + if(!model->action) goto memerr; + a = &model->action[i]; + a->name = pe; + a->durationmsec = k; + /* skip the first frame marker as there's always at least one frame */ + a->numframe = 1; + a->frame = (m3dfr_t*)M3D_MALLOC(sizeof(m3dfr_t)); + if(!a->frame) goto memerr; + a->frame[0].msec = 0; + a->frame[0].numtransform = 0; + a->frame[0].transform = NULL; + i = 0; + if(*ptr == 'f') + ptr = _m3d_findnl(ptr); + while(*ptr && *ptr != '\r' && *ptr != '\n') { + if(*ptr == 'f') { + i = a->numframe++; + a->frame = (m3dfr_t*)M3D_REALLOC(a->frame, a->numframe * sizeof(m3dfr_t)); + if(!a->frame) goto memerr; + ptr = _m3d_findarg(ptr); + ptr = _m3d_getint(ptr, &a->frame[i].msec); + a->frame[i].numtransform = 0; + a->frame[i].transform = NULL; + } else { + j = a->frame[i].numtransform++; + a->frame[i].transform = (m3dtr_t*)M3D_REALLOC(a->frame[i].transform, + a->frame[i].numtransform * sizeof(m3dtr_t)); + if(!a->frame[i].transform) goto memerr; + ptr = _m3d_getint(ptr, &k); + ptr = _m3d_findarg(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + a->frame[i].transform[j].boneid = (M3D_INDEX)k; + ptr = _m3d_getint(ptr, &k); + ptr = _m3d_findarg(ptr); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + a->frame[i].transform[j].pos = (M3D_INDEX)k; + ptr = _m3d_getint(ptr, &k); + if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + a->frame[i].transform[j].ori = (M3D_INDEX)k; + } + ptr = _m3d_findnl(ptr); + } + } else + /* extra chunks */ + if(!memcmp(pe, "Extra", 5)) { + pe = _m3d_findarg(pe); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + buff = (unsigned char*)_m3d_findnl(ptr); + k = ((uint32_t)((uint64_t)buff - (uint64_t)ptr) / 3) + 1; + i = model->numunknown++; + model->unknown = (m3dchunk_t**)M3D_REALLOC(model->unknown, model->numunknown * sizeof(m3dchunk_t*)); + if(!model->unknown) goto memerr; + model->unknown[i] = (m3dchunk_t*)M3D_MALLOC(k + sizeof(m3dchunk_t)); + if(!model->unknown[i]) goto memerr; + memcpy(&model->unknown[i]->magic, pe, 4); + model->unknown[i]->length = sizeof(m3dchunk_t); + pe = (char*)model->unknown[i] + sizeof(m3dchunk_t); + while(*ptr && *ptr != '\r' && *ptr != '\n') { + ptr = _m3d_gethex(ptr, &k); + *pe++ = (uint8_t)k; + model->unknown[i]->length++; + } + } else + goto asciiend; + } + model->errcode = M3D_SUCCESS; +asciiend: + setlocale(LC_NUMERIC, ol); + goto postprocess; + } + /* Binary variant */ +#endif + if(!M3D_CHUNKMAGIC(data + 8, 'H','E','A','D')) { + stbi__g_failure_reason = "Corrupt file"; + buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data+8, ((m3dchunk_t*)data)->length-8, + 4096, (int*)&len, 1); + if(!buff || !len || !M3D_CHUNKMAGIC(buff, 'H','E','A','D')) { + M3D_LOG(stbi__g_failure_reason); + if(buff) M3D_FREE(buff); + M3D_FREE(model); + return NULL; + } + buff = (unsigned char*)M3D_REALLOC(buff, len); + model->flags |= M3D_FLG_FREERAW; /* mark that we have to free the raw buffer */ + data = buff; + } else { + len = ((m3dhdr_t*)data)->length; + data += 8; + } + model->raw = (m3dhdr_t*)data; + end = data + len; + + /* parse header */ + data += sizeof(m3dhdr_t); + M3D_LOG(data); + model->name = (char*)data; + for(; data < end && *data; data++) {}; data++; + model->license = (char*)data; + for(; data < end && *data; data++) {}; data++; + model->author = (char*)data; + for(; data < end && *data; data++) {}; data++; + model->desc = (char*)data; + chunk = (unsigned char*)model->raw + model->raw->length; + model->scale = (M3D_FLOAT)model->raw->scale; + if(model->scale <= (M3D_FLOAT)0.0) model->scale = (M3D_FLOAT)1.0; + model->vc_s = 1 << ((model->raw->types >> 0) & 3); /* vertex coordinate size */ + model->vi_s = 1 << ((model->raw->types >> 2) & 3); /* vertex index size */ + model->si_s = 1 << ((model->raw->types >> 4) & 3); /* string offset size */ + model->ci_s = 1 << ((model->raw->types >> 6) & 3); /* color index size */ + model->ti_s = 1 << ((model->raw->types >> 8) & 3); /* tmap index size */ + model->bi_s = 1 << ((model->raw->types >>10) & 3); /* bone index size */ + model->nb_s = 1 << ((model->raw->types >>12) & 3); /* number of bones per vertex */ + model->sk_s = 1 << ((model->raw->types >>14) & 3); /* skin index size */ + model->fi_s = 1 << ((model->raw->types >>16) & 3); /* frame counter size */ + if(model->ci_s == 8) model->ci_s = 0; /* optional indices */ + if(model->ti_s == 8) model->ti_s = 0; + if(model->bi_s == 8) model->bi_s = 0; + if(model->sk_s == 8) model->sk_s = 0; + if(model->fi_s == 8) model->fi_s = 0; + + /* variable limit checks */ + if(sizeof(M3D_FLOAT) == 4 && model->vc_s > 4) { + M3D_LOG("Double precision coordinates not supported, truncating to float..."); + model->errcode = M3D_ERR_TRUNC; + } + if(sizeof(M3D_INDEX) == 2 && (model->vi_s > 2 || model->si_s == 4 || model->ci_s == 4 || model->ti_s == 4 || + model->bi_s == 4 || model->sk_s == 4 || model->fi_s == 4)) { + M3D_LOG("32 bit indices not supported, unable to load model"); + M3D_FREE(model); + return NULL; + } + if(model->vi_s > 4 || model->si_s > 4) { + M3D_LOG("Invalid index size, unable to load model"); + M3D_FREE(model); + return NULL; + } + if(model->nb_s > M3D_NUMBONE) { + M3D_LOG("Model has more bones per vertex than importer supports"); + model->errcode = M3D_ERR_TRUNC; + } + + /* look for inlined assets in advance, material and procedural chunks may need them */ + buff = chunk; + while(buff < end && !M3D_CHUNKMAGIC(buff, 'O','M','D','3')) { + data = buff; + len = ((m3dchunk_t*)data)->length; + if(len < sizeof(m3dchunk_t)) { + M3D_LOG("Invalid chunk size"); + break; + } + buff += len; + len -= sizeof(m3dchunk_t) + model->si_s; + + /* inlined assets */ + if(M3D_CHUNKMAGIC(data, 'A','S','E','T') && len > 0) { + M3D_LOG("Inlined asset"); + i = model->numinlined++; + model->inlined = (m3di_t*)M3D_REALLOC(model->inlined, model->numinlined * sizeof(m3di_t)); + if(!model->inlined) { +memerr: M3D_LOG("Out of memory"); + model->errcode = M3D_ERR_ALLOC; + return model; + } + data += sizeof(m3dchunk_t); + t = &model->inlined[i]; + M3D_GETSTR(t->name); + M3D_LOG(t->name); + t->data = (uint8_t*)data; + t->length = len; + } + } + + /* parse chunks */ + while(chunk < end && !M3D_CHUNKMAGIC(chunk, 'O','M','D','3')) { + data = chunk; + len = ((m3dchunk_t*)chunk)->length; + if(len < sizeof(m3dchunk_t)) { + M3D_LOG("Invalid chunk size"); + break; + } + chunk += len; + len -= sizeof(m3dchunk_t); + + /* color map */ + if(M3D_CHUNKMAGIC(data, 'C','M','A','P')) { + M3D_LOG("Color map"); + if(model->cmap) { M3D_LOG("More color map chunks, should be unique"); model->errcode = M3D_ERR_CMAP; break; } + if(model->ci_s >= 4) { M3D_LOG("Color map chunk, shouldn't be any"); model->errcode = M3D_ERR_CMAP; break; } + model->numcmap = len / sizeof(uint32_t); + model->cmap = (uint32_t*)(data + sizeof(m3dchunk_t)); + } else + /* texture map */ + if(M3D_CHUNKMAGIC(data, 'T','M','A','P')) { + M3D_LOG("Texture map"); + if(model->tmap) { M3D_LOG("More texture map chunks, should be unique"); model->errcode = M3D_ERR_TMAP; break; } + reclen = model->vc_s + model->vc_s; + model->numtmap = len / reclen; + model->tmap = (m3dti_t*)M3D_MALLOC(model->numtmap * sizeof(m3dti_t)); + if(!model->tmap) goto memerr; + for(i = 0, data += sizeof(m3dchunk_t); data < chunk; i++) { + switch(model->vc_s) { + case 1: + model->tmap[i].u = (M3D_FLOAT)(data[0]) / 255; + model->tmap[i].v = (M3D_FLOAT)(data[1]) / 255; + break; + case 2: + model->tmap[i].u = (M3D_FLOAT)(*((int16_t*)(data+0))) / 65535; + model->tmap[i].v = (M3D_FLOAT)(*((int16_t*)(data+2))) / 65535; + break; + case 4: + model->tmap[i].u = (M3D_FLOAT)(*((float*)(data+0))); + model->tmap[i].v = (M3D_FLOAT)(*((float*)(data+4))); + break; + case 8: + model->tmap[i].u = (M3D_FLOAT)(*((double*)(data+0))); + model->tmap[i].v = (M3D_FLOAT)(*((double*)(data+8))); + break; + } + data += reclen; + } + } else + /* vertex list */ + if(M3D_CHUNKMAGIC(data, 'V','R','T','S')) { + M3D_LOG("Vertex list"); + if(model->vertex) { M3D_LOG("More vertex chunks, should be unique"); model->errcode = M3D_ERR_VRTS; break; } + if(model->ci_s && model->ci_s < 4 && !model->cmap) model->errcode = M3D_ERR_CMAP; + reclen = model->ci_s + model->sk_s + 4 * model->vc_s; + model->numvertex = len / reclen; + model->vertex = (m3dv_t*)M3D_MALLOC(model->numvertex * sizeof(m3dv_t)); + if(!model->vertex) goto memerr; + memset(model->vertex, 0, model->numvertex * sizeof(m3dv_t)); + for(i = 0, data += sizeof(m3dchunk_t); data < chunk && i < model->numvertex; i++) { + switch(model->vc_s) { + case 1: + model->vertex[i].x = (M3D_FLOAT)((int8_t)data[0]) / 127; + model->vertex[i].y = (M3D_FLOAT)((int8_t)data[1]) / 127; + model->vertex[i].z = (M3D_FLOAT)((int8_t)data[2]) / 127; + model->vertex[i].w = (M3D_FLOAT)((int8_t)data[3]) / 127; + data += 4; + break; + case 2: + model->vertex[i].x = (M3D_FLOAT)(*((int16_t*)(data+0))) / 32767; + model->vertex[i].y = (M3D_FLOAT)(*((int16_t*)(data+2))) / 32767; + model->vertex[i].z = (M3D_FLOAT)(*((int16_t*)(data+4))) / 32767; + model->vertex[i].w = (M3D_FLOAT)(*((int16_t*)(data+6))) / 32767; + data += 8; + break; + case 4: + model->vertex[i].x = (M3D_FLOAT)(*((float*)(data+0))); + model->vertex[i].y = (M3D_FLOAT)(*((float*)(data+4))); + model->vertex[i].z = (M3D_FLOAT)(*((float*)(data+8))); + model->vertex[i].w = (M3D_FLOAT)(*((float*)(data+12))); + data += 16; + break; + case 8: + model->vertex[i].x = (M3D_FLOAT)(*((double*)(data+0))); + model->vertex[i].y = (M3D_FLOAT)(*((double*)(data+8))); + model->vertex[i].z = (M3D_FLOAT)(*((double*)(data+16))); + model->vertex[i].w = (M3D_FLOAT)(*((double*)(data+24))); + data += 32; + break; + } + switch(model->ci_s) { + case 1: model->vertex[i].color = model->cmap ? model->cmap[data[0]] : 0; data++; break; + case 2: model->vertex[i].color = model->cmap ? model->cmap[*((uint16_t*)data)] : 0; data += 2; break; + case 4: model->vertex[i].color = *((uint32_t*)data); data += 4; break; + /* case 8: break; */ + } + model->vertex[i].skinid = (M3D_INDEX)-1U; + data = _m3d_getidx(data, model->sk_s, &model->vertex[i].skinid); + } + } else + /* skeleton: bone hierarchy and skin */ + if(M3D_CHUNKMAGIC(data, 'B','O','N','E')) { + M3D_LOG("Skeleton"); + if(model->bone) { M3D_LOG("More bone chunks, should be unique"); model->errcode = M3D_ERR_BONE; break; } + if(model->bi_s > 4) { M3D_LOG("Bone chunk, shouldn't be any"); model->errcode=M3D_ERR_BONE; break; } + if(!model->vertex) { M3D_LOG("No vertex chunk before bones"); model->errcode = M3D_ERR_VRTS; break; } + data += sizeof(m3dchunk_t); + model->numbone = 0; + data = _m3d_getidx(data, model->bi_s, &model->numbone); + if(model->numbone) { + model->bone = (m3db_t*)M3D_MALLOC(model->numbone * sizeof(m3db_t)); + if(!model->bone) goto memerr; + } + model->numskin = 0; + data = _m3d_getidx(data, model->sk_s, &model->numskin); + if(model->numskin) { + model->skin = (m3ds_t*)M3D_MALLOC(model->numskin * sizeof(m3ds_t)); + if(!model->skin) goto memerr; + for(i = 0; i < model->numskin; i++) + for(j = 0; j < M3D_NUMBONE; j++) { + model->skin[i].boneid[j] = (M3D_INDEX)-1U; + model->skin[i].weight[j] = (M3D_FLOAT)0.0; + } + } + /* read bone hierarchy */ + for(i = 0; i < model->numbone; i++) { + data = _m3d_getidx(data, model->bi_s, &model->bone[i].parent); + M3D_GETSTR(model->bone[i].name); + data = _m3d_getidx(data, model->vi_s, &model->bone[i].pos); + data = _m3d_getidx(data, model->vi_s, &model->bone[i].ori); + model->bone[i].numweight = 0; + model->bone[i].weight = NULL; + } + /* read skin definitions */ + for(i = 0; data < chunk && i < model->numskin; i++) { + memset(&weights, 0, sizeof(weights)); + if(model->nb_s == 1) weights[0] = 255; + else { + memcpy(&weights, data, model->nb_s); + data += model->nb_s; + } + for(j = 0; j < (unsigned int)model->nb_s; j++) { + if(weights[j]) { + if(j >= M3D_NUMBONE) + data += model->bi_s; + else { + model->skin[i].weight[j] = (M3D_FLOAT)(weights[j]) / 255; + data = _m3d_getidx(data, model->bi_s, &model->skin[i].boneid[j]); + } + } + } + } + } else + /* material */ + if(M3D_CHUNKMAGIC(data, 'M','T','R','L')) { + data += sizeof(m3dchunk_t); + M3D_GETSTR(material); + M3D_LOG("Material"); + M3D_LOG(material); + if(model->ci_s < 4 && !model->numcmap) model->errcode = M3D_ERR_CMAP; + for(i = 0; i < model->nummaterial; i++) + if(!strcmp(material, model->material[i].name)) { + model->errcode = M3D_ERR_MTRL; + M3D_LOG("Multiple definitions for material"); + M3D_LOG(material); + material = NULL; + break; + } + if(material) { + i = model->nummaterial++; + if(model->flags & M3D_FLG_MTLLIB) { + m = model->material; + model->material = (m3dm_t*)M3D_MALLOC(model->nummaterial * sizeof(m3dm_t)); + if(!model->material) goto memerr; + memcpy(model->material, m, (model->nummaterial - 1) * sizeof(m3dm_t)); + if(model->texture) { + tx = model->texture; + model->texture = (m3dtx_t*)M3D_MALLOC(model->numtexture * sizeof(m3dtx_t)); + if(!model->texture) goto memerr; + memcpy(model->texture, tx, model->numtexture * sizeof(m3dm_t)); + } + model->flags &= ~M3D_FLG_MTLLIB; + } else { + model->material = (m3dm_t*)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t)); + if(!model->material) goto memerr; + } + m = &model->material[i]; + m->numprop = 0; + m->prop = NULL; + m->name = material; + m->prop = (m3dp_t*)M3D_REALLOC(m->prop, (len / 2) * sizeof(m3dp_t)); + if(!m->prop) goto memerr; + while(data < chunk) { + i = m->numprop++; + m->prop[i].type = *data++; + m->prop[i].value.num = 0; + if(m->prop[i].type >= 128) + k = m3dpf_map; + else { + for(k = 256, j = 0; j < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); j++) + if(m->prop[i].type == m3d_propertytypes[j].id) { k = m3d_propertytypes[j].format; break; } + } + switch(k) { + case m3dpf_color: + switch(model->ci_s) { + case 1: m->prop[i].value.color = model->cmap ? model->cmap[data[0]] : 0; data++; break; + case 2: m->prop[i].value.color = model->cmap ? model->cmap[*((uint16_t*)data)] : 0; data += 2; break; + case 4: m->prop[i].value.color = *((uint32_t*)data); data += 4; break; + } + break; + + case m3dpf_uint8: m->prop[i].value.num = *data++; break; + case m3dpf_uint16:m->prop[i].value.num = *((uint16_t*)data); data += 2; break; + case m3dpf_uint32:m->prop[i].value.num = *((uint32_t*)data); data += 4; break; + case m3dpf_float: m->prop[i].value.fnum = *((float*)data); data += 4; break; + + case m3dpf_map: + M3D_GETSTR(material); + m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, material); + if(model->errcode == M3D_ERR_ALLOC) goto memerr; + if(m->prop[i].value.textureid == (M3D_INDEX)-1U) { + M3D_LOG("Texture not found"); + M3D_LOG(material); + m->numprop--; + } + break; + + default: + M3D_LOG("Unknown material property in"); + M3D_LOG(m->name); + model->errcode = M3D_ERR_UNKPROP; + data = chunk; + break; + } + } + m->prop = (m3dp_t*)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t)); + if(!m->prop) goto memerr; + } + } else + /* face */ + if(M3D_CHUNKMAGIC(data, 'P','R','O','C')) { + /* procedural surface */ + M3D_GETSTR(material); + M3D_LOG("Procedural surface"); + M3D_LOG(material); + _m3d_getpr(model, readfilecb, freecb, material); + } else + if(M3D_CHUNKMAGIC(data, 'M','E','S','H')) { + M3D_LOG("Mesh data"); + /* mesh */ + data += sizeof(m3dchunk_t); + mi = (M3D_INDEX)-1U; + am = model->numface; + while(data < chunk) { + k = *data++; + n = k >> 4; + k &= 15; + if(!n) { + /* use material */ + mi = (M3D_INDEX)-1U; + M3D_GETSTR(material); + if(material) { + for(j = 0; j < model->nummaterial; j++) + if(!strcmp(material, model->material[j].name)) { + mi = (M3D_INDEX)j; + break; + } + if(mi == (M3D_INDEX)-1U) model->errcode = M3D_ERR_MTRL; + } + continue; + } + if(n != 3) { M3D_LOG("Only triangle mesh supported for now"); model->errcode = M3D_ERR_UNKMESH; return model; } + i = model->numface++; + if(model->numface > am) { + am = model->numface + 4095; + model->face = (m3df_t*)M3D_REALLOC(model->face, am * sizeof(m3df_t)); + if(!model->face) goto memerr; + } + memset(&model->face[i], 255, sizeof(m3df_t)); /* set all index to -1 by default */ + model->face[i].materialid = mi; + for(j = 0; j < n; j++) { + /* vertex */ + data = _m3d_getidx(data, model->vi_s, &model->face[i].vertex[j]); + /* texcoord */ + if(k & 1) + data = _m3d_getidx(data, model->ti_s, &model->face[i].texcoord[j]); + /* normal */ + if(k & 2) + data = _m3d_getidx(data, model->vi_s, &model->face[i].normal[j]); + } + } + model->face = (m3df_t*)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t)); + } else + /* action */ + if(M3D_CHUNKMAGIC(data, 'A','C','T','N')) { + M3D_LOG("Action"); + i = model->numaction++; + model->action = (m3da_t*)M3D_REALLOC(model->action, model->numaction * sizeof(m3da_t)); + if(!model->action) goto memerr; + a = &model->action[i]; + data += sizeof(m3dchunk_t); + M3D_GETSTR(a->name); + M3D_LOG(a->name); + a->numframe = *((uint16_t*)data); data += 2; + if(a->numframe < 1) { + model->numaction--; + } else { + a->durationmsec = *((uint32_t*)data); data += 4; + a->frame = (m3dfr_t*)M3D_MALLOC(a->numframe * sizeof(m3dfr_t)); + if(!a->frame) goto memerr; + for(i = 0; data < chunk && i < a->numframe; i++) { + a->frame[i].msec = *((uint32_t*)data); data += 4; + a->frame[i].numtransform = 0; a->frame[i].transform = NULL; + data = _m3d_getidx(data, model->fi_s, &a->frame[i].numtransform); + if(a->frame[i].numtransform > 0) { + a->frame[i].transform = (m3dtr_t*)M3D_MALLOC(a->frame[i].numtransform * sizeof(m3dtr_t)); + for(j = 0; j < a->frame[i].numtransform; j++) { + data = _m3d_getidx(data, model->bi_s, &a->frame[i].transform[j].boneid); + data = _m3d_getidx(data, model->vi_s, &a->frame[i].transform[j].pos); + data = _m3d_getidx(data, model->vi_s, &a->frame[i].transform[j].ori); + } + } + } + } + } else { + i = model->numunknown++; + model->unknown = (m3dchunk_t**)M3D_REALLOC(model->unknown, model->numunknown * sizeof(m3dchunk_t*)); + if(!model->unknown) goto memerr; + model->unknown[i] = (m3dchunk_t*)data; + } + } + /* calculate normals, normalize skin weights, create bone/vertex cross-references and calculate transform matrices */ +postprocess: + if(model) { + if(model->numface && model->face) { + memset(&vn, 0, sizeof(m3dv_t)); + /* if they are missing, calculate triangle normals into a temporary buffer */ + for(i = numnorm = 0; i < model->numface; i++) + if(model->face[i].normal[0] == -1U) { + v0 = &model->vertex[model->face[i].vertex[0]]; v1 = &model->vertex[model->face[i].vertex[1]]; + v2 = &model->vertex[model->face[i].vertex[2]]; + va.x = v1->x - v0->x; va.y = v1->y - v0->y; va.z = v1->z - v0->z; + vb.x = v2->x - v0->x; vb.y = v2->y - v0->y; vb.z = v2->z - v0->z; + vn.x = (va.y * vb.z) - (va.z * vb.y); + vn.y = (va.z * vb.x) - (va.x * vb.z); + vn.z = (va.x * vb.y) - (va.y * vb.x); + w = _m3d_rsq((vn.x * vn.x) + (vn.y * vn.y) + (vn.z * vn.z)); + vn.x *= w; vn.y *= w; vn.z *= w; + norm = _m3d_addnorm(norm, &numnorm, &vn, &j); + if(!ni) { + ni = (M3D_INDEX*)M3D_MALLOC(model->numface * sizeof(M3D_INDEX)); + if(!ni) goto memerr; + } + ni[i] = j; + } + if(ni && norm) { + vi = (M3D_INDEX*)M3D_MALLOC(model->numvertex * sizeof(M3D_INDEX)); + if(!vi) goto memerr; + /* for each vertex, take the average of the temporary normals and use that */ + for(i = 0, n = model->numvertex; i < n; i++) { + memset(&vn, 0, sizeof(m3dv_t)); + for(j = 0; j < model->numface; j++) + for(k = 0; k < 3; k++) + if(model->face[j].vertex[k] == i) { + vn.x += norm[ni[j]].x; + vn.y += norm[ni[j]].y; + vn.z += norm[ni[j]].z; + } + w = _m3d_rsq((vn.x * vn.x) + (vn.y * vn.y) + (vn.z * vn.z)); + vn.x *= w; vn.y *= w; vn.z *= w; + vn.skinid = -1U; + model->vertex = _m3d_addnorm(model->vertex, &model->numvertex, &vn, &vi[i]); + } + for(j = 0; j < model->numface; j++) + for(k = 0; k < 3; k++) + model->face[j].normal[k] = vi[model->face[j].vertex[k]]; + M3D_FREE(norm); + M3D_FREE(ni); + M3D_FREE(vi); + } + } + if(model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) { + for(i = 0; i < model->numvertex; i++) { + if(model->vertex[i].skinid < M3D_INDEXMAX) { + sk = &model->skin[model->vertex[i].skinid]; + w = (M3D_FLOAT)0.0; + for(j = 0; j < M3D_NUMBONE && sk->boneid[j] != (M3D_INDEX)-1U && sk->weight[j] > (M3D_FLOAT)0.0; j++) + w += sk->weight[j]; + for(j = 0; j < M3D_NUMBONE && sk->boneid[j] != (M3D_INDEX)-1U && sk->weight[j] > (M3D_FLOAT)0.0; j++) { + sk->weight[j] /= w; + b = &model->bone[sk->boneid[j]]; + k = b->numweight++; + b->weight = (m3dw_t*)M3D_REALLOC(b->weight, b->numweight * sizeof(m3da_t)); + if(!b->weight) goto memerr; + b->weight[k].vertexid = i; + b->weight[k].weight = sk->weight[j]; + } + } + } +#ifndef M3D_NOANIMATION + for(i = 0; i < model->numbone; i++) { + b = &model->bone[i]; + if(model->bone[i].parent == (M3D_INDEX)-1U) { + _m3d_mat((M3D_FLOAT*)&b->mat4, &model->vertex[b->pos], &model->vertex[b->ori]); + } else { + _m3d_mat((M3D_FLOAT*)&r, &model->vertex[b->pos], &model->vertex[b->ori]); + _m3d_mul((M3D_FLOAT*)&b->mat4, (M3D_FLOAT*)&model->bone[b->parent].mat4, (M3D_FLOAT*)&r); + } + } + for(i = 0; i < model->numbone; i++) + _m3d_inv((M3D_FLOAT*)&model->bone[i].mat4); +#endif + } + } + return model; +} + +/** + * Calculates skeletons for animation frames, returns a working copy (should be freed after use) + */ +m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t *skeleton) +{ + unsigned int i; + M3D_INDEX s = frameid; + m3dfr_t *fr; + + if(!model || !model->numbone || !model->bone || (actionid != (M3D_INDEX)-1U && (!model->action || + actionid >= model->numaction || frameid >= model->action[actionid].numframe))) { + model->errcode = M3D_ERR_UNKFRAME; + return skeleton; + } + model->errcode = M3D_SUCCESS; + if(!skeleton) { + skeleton = (m3dtr_t*)M3D_MALLOC(model->numbone * sizeof(m3dtr_t)); + if(!skeleton) { + model->errcode = M3D_ERR_ALLOC; + return NULL; + } + goto gen; + } + if(actionid == (M3D_INDEX)-1U || !frameid) { +gen: s = 0; + for(i = 0; i < model->numbone; i++) { + skeleton[i].boneid = i; + skeleton[i].pos = model->bone[i].pos; + skeleton[i].ori = model->bone[i].ori; + } + } + if(actionid < model->numaction && (frameid || !model->action[actionid].frame[0].msec)) { + for(; s <= frameid; s++) { + fr = &model->action[actionid].frame[s]; + for(i = 0; i < fr->numtransform; i++) { + skeleton[fr->transform[i].boneid].pos = fr->transform[i].pos; + skeleton[fr->transform[i].boneid].ori = fr->transform[i].ori; + } + } + } + return skeleton; +} + +#ifndef M3D_NOANIMATION +/** + * Returns interpolated animation-pose, a working copy (should be freed after use) + */ +m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) +{ + unsigned int i, j, l; + M3D_FLOAT r[16], t, d; + m3db_t *ret; + m3dv_t *v, *p, *f; + m3dtr_t *tmp; + m3dfr_t *fr; + + if(!model || !model->numbone || !model->bone) { + model->errcode = M3D_ERR_UNKFRAME; + return NULL; + } + ret = (m3db_t*)M3D_MALLOC(model->numbone * sizeof(m3db_t)); + if(!ret) { + model->errcode = M3D_ERR_ALLOC; + return NULL; + } + memcpy(ret, model->bone, model->numbone * sizeof(m3db_t)); + for(i = 0; i < model->numbone; i++) + _m3d_inv((M3D_FLOAT*)&ret[i].mat4); + if(!model->action || actionid >= model->numaction) { + model->errcode = M3D_ERR_UNKFRAME; + return ret; + } + msec %= model->action[actionid].durationmsec; + model->errcode = M3D_SUCCESS; + fr = &model->action[actionid].frame[0]; + for(j = l = 0; j < model->action[actionid].numframe && model->action[actionid].frame[j].msec <= msec; j++) { + fr = &model->action[actionid].frame[j]; + l = fr->msec; + for(i = 0; i < fr->numtransform; i++) { + ret[fr->transform[i].boneid].pos = fr->transform[i].pos; + ret[fr->transform[i].boneid].ori = fr->transform[i].ori; + } + } + if(l != msec) { + model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t)); + if(!model->vertex) { + free(ret); + model->errcode = M3D_ERR_ALLOC; + return NULL; + } + tmp = (m3dtr_t*)M3D_MALLOC(model->numbone * sizeof(m3dtr_t)); + if(tmp) { + for(i = 0; i < model->numbone; i++) { + tmp[i].pos = ret[i].pos; + tmp[i].ori = ret[i].ori; + } + fr = &model->action[actionid].frame[j % model->action[actionid].numframe]; + t = l >= fr->msec ? (M3D_FLOAT)1.0 : (M3D_FLOAT)(msec - l) / (M3D_FLOAT)(fr->msec - l); + for(i = 0; i < fr->numtransform; i++) { + tmp[fr->transform[i].boneid].pos = fr->transform[i].pos; + tmp[fr->transform[i].boneid].ori = fr->transform[i].ori; + } + for(i = 0, j = model->numvertex; i < model->numbone; i++) { + /* LERP interpolation of position */ + if(ret[i].pos != tmp[i].pos) { + p = &model->vertex[ret[i].pos]; + f = &model->vertex[tmp[i].pos]; + v = &model->vertex[j]; + v->x = p->x + t * (f->x - p->x); + v->y = p->y + t * (f->y - p->y); + v->z = p->z + t * (f->z - p->z); + ret[i].pos = j++; + } + /* NLERP interpolation of orientation (could have used SLERP, that's nicer, but slower) */ + if(ret[i].ori != tmp[i].ori) { + p = &model->vertex[ret[i].ori]; + f = &model->vertex[tmp[i].ori]; + v = &model->vertex[j]; + d = (p->w * f->w + p->x * f->x + p->y * f->y + p->z * f->z < 0) ? -1 : 1; + v->x = p->x + t * (d*f->x - p->x); + v->y = p->y + t * (d*f->y - p->y); + v->z = p->z + t * (d*f->z - p->z); + v->w = p->w + t * (d*f->w - p->w); + d = _m3d_rsq(v->w * v->w + v->x * v->x + v->y * v->y + v->z * v->z); + v->x *= d; v->y *= d; v->z *= d; v->w *= d; + ret[i].ori = j++; + } + } + M3D_FREE(tmp); + } + } + for(i = 0; i < model->numbone; i++) { + if(ret[i].parent == (M3D_INDEX)-1U) { + _m3d_mat((M3D_FLOAT*)&ret[i].mat4, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]); + } else { + _m3d_mat((M3D_FLOAT*)&r, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]); + _m3d_mul((M3D_FLOAT*)&ret[i].mat4, (M3D_FLOAT*)&ret[ret[i].parent].mat4, (M3D_FLOAT*)&r); + } + } + return ret; +} + +#endif /* M3D_NOANIMATION */ + +#endif /* M3D_IMPLEMENTATION */ + +#if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER)) +/** + * Free the in-memory model + */ +void m3d_free(m3d_t *model) +{ + unsigned int i, j; + + if(!model) return; +#ifdef M3D_ASCII + /* if model imported from ASCII, we have to free all strings as well */ + if(model->flags & M3D_FLG_FREESTR) { + if(model->name) M3D_FREE(model->name); + if(model->license) M3D_FREE(model->license); + if(model->author) M3D_FREE(model->author); + if(model->desc) M3D_FREE(model->desc); + if(model->bone) + for(i = 0; i < model->numbone; i++) + if(model->bone[i].name) + M3D_FREE(model->bone[i].name); + if(model->material) + for(i = 0; i < model->nummaterial; i++) + if(model->material[i].name) + M3D_FREE(model->material[i].name); + if(model->action) + for(i = 0; i < model->numaction; i++) + if(model->action[i].name) + M3D_FREE(model->action[i].name); + if(model->texture) + for(i = 0; i < model->numtexture; i++) + if(model->texture[i].name) + M3D_FREE(model->texture[i].name); + if(model->unknown) + for(i = 0; i < model->numunknown; i++) + if(model->unknown[i]) + M3D_FREE(model->unknown[i]); + } +#endif + if(model->flags & M3D_FLG_FREERAW) M3D_FREE(model->raw); + + if(model->tmap) M3D_FREE(model->tmap); + if(model->bone) { + for(i = 0; i < model->numbone; i++) + if(model->bone[i].weight) + M3D_FREE(model->bone[i].weight); + M3D_FREE(model->bone); + } + if(model->skin) M3D_FREE(model->skin); + if(model->vertex) M3D_FREE(model->vertex); + if(model->face) M3D_FREE(model->face); + if(model->material && !(model->flags & M3D_FLG_MTLLIB)) { + for(i = 0; i < model->nummaterial; i++) + if(model->material[i].prop) M3D_FREE(model->material[i].prop); + M3D_FREE(model->material); + } + if(model->texture) { + for(i = 0; i < model->numtexture; i++) + if(model->texture[i].d) M3D_FREE(model->texture[i].d); + M3D_FREE(model->texture); + } + if(model->action) { + for(i = 0; i < model->numaction; i++) { + if(model->action[i].frame) { + for(j = 0; j < model->action[i].numframe; j++) + if(model->action[i].frame[j].transform) M3D_FREE(model->action[i].frame[j].transform); + M3D_FREE(model->action[i].frame); + } + } + M3D_FREE(model->action); + } + if(model->inlined) M3D_FREE(model->inlined); + if(model->unknown) M3D_FREE(model->unknown); + free(model); +} +#endif + +#ifdef M3D_EXPORTER +typedef struct { + char *str; + uint32_t offs; +} m3dstr_t; + +/* create unique list of strings */ +static m3dstr_t *_m3d_addstr(m3dstr_t *str, uint32_t *numstr, char *s) +{ + uint32_t i; + if(!s || !*s) return str; + if(str) { + for(i = 0; i < *numstr; i++) + if(str[i].str == s || !strcmp(str[i].str, s)) return str; + } + str = (m3dstr_t*)M3D_REALLOC(str, ((*numstr) + 1) * sizeof(m3dstr_t)); + str[*numstr].str = s; + str[*numstr].offs = 0; + (*numstr)++; + return str; +} + +/* add strings to header */ +m3dhdr_t *_m3d_addhdr(m3dhdr_t *h, m3dstr_t *s) +{ + int i; + char *safe = _m3d_safestr(s->str, 0); + i = strlen(safe); + h = (m3dhdr_t*)M3D_REALLOC(h, h->length + i+1); + if(!h) { M3D_FREE(safe); return NULL; } + memcpy((uint8_t*)h + h->length, safe, i+1); + s->offs = h->length - 16; + h->length += i+1; + M3D_FREE(safe); + return h; +} + +/* return offset of string */ +static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s) +{ + uint32_t i; + char *safe; + if(!s || !*s) return 0; + if(str) { + safe = _m3d_safestr(s, 0); + if(!safe) return 0; + if(!*safe) { + free(safe); + return 0; + } + for(i = 0; i < numstr; i++) + if(!strcmp(str[i].str, s)) { + free(safe); + return str[i].offs; + } + free(safe); + } + return 0; +} + +/* compare two colors by HSV value */ +__inline__ static int _m3d_cmapcmp(const void *a, const void *b) +{ + uint8_t *A = (uint8_t*)a, *B = (uint8_t*)b; + register int m, vA, vB; + /* get HSV value for A */ + m = A[2] < A[1]? A[2] : A[1]; if(A[0] < m) m = A[0]; + vA = A[2] > A[1]? A[2] : A[1]; if(A[0] > vA) vA = A[0]; + /* get HSV value for B */ + m = B[2] < B[1]? B[2] : B[1]; if(B[0] < m) m = B[0]; + vB = B[2] > B[1]? B[2] : B[1]; if(B[0] > vB) vB = B[0]; + return vA - vB; +} + +/* create sorted list of colors */ +static uint32_t *_m3d_addcmap(uint32_t *cmap, uint32_t *numcmap, uint32_t color) +{ + uint32_t i; + if(cmap) { + for(i = 0; i < *numcmap; i++) + if(cmap[i] == color) return cmap; + } + cmap = (uint32_t*)M3D_REALLOC(cmap, ((*numcmap) + 1) * sizeof(uint32_t)); + for(i = 0; i < *numcmap && _m3d_cmapcmp(&color, &cmap[i]) > 0; i++); + if(i < *numcmap) memmove(&cmap[i+1], &cmap[i], ((*numcmap) - i)*sizeof(uint32_t)); + cmap[i] = color; + (*numcmap)++; + return cmap; +} + +/* look up a color and return its index */ +static uint32_t _m3d_cmapidx(uint32_t *cmap, uint32_t numcmap, uint32_t color) +{ + uint32_t i; + for(i = 0; i < numcmap; i++) + if(cmap[i] == color) return i; + return 0; +} + +/* add vertex to list */ +static m3dv_t *_m3d_addvrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) +{ + uint32_t i; + if(v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0; + if(v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0; + if(v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0; + if(v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0; + if(vrtx) { + for(i = 0; i < *numvrtx; i++) + if(!memcmp(&vrtx[i], v, sizeof(m3dv_t))) { *idx = i; return vrtx; } + } + vrtx = (m3dv_t*)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t)); + memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t)); + *idx = *numvrtx; + (*numvrtx)++; + return vrtx; +} + +/* add texture map to list */ +static m3dti_t *_m3d_addtmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *t, uint32_t *idx) +{ + uint32_t i; + if(tmap) { + for(i = 0; i < *numtmap; i++) + if(!memcmp(&tmap[i], t, sizeof(m3dti_t))) { *idx = i; return tmap; } + } + tmap = (m3dti_t*)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t)); + memcpy(&tmap[*numtmap], t, sizeof(m3dti_t)); + *idx = *numtmap; + (*numtmap)++; + return tmap; +} + +/* add material to list */ +static m3dm_t **_m3d_addmtrl(m3dm_t **mtrl, uint32_t *nummtrl, m3dm_t *m, uint32_t *idx) +{ + uint32_t i; + if(mtrl) { + for(i = 0; i < *nummtrl; i++) + if(mtrl[i]->name == m->name || !strcmp(mtrl[i]->name, m->name)) { *idx = i; return mtrl; } + } + mtrl = (m3dm_t**)M3D_REALLOC(mtrl, ((*nummtrl) + 1) * sizeof(m3dm_t*)); + mtrl[*nummtrl] = m; + *idx = *nummtrl; + (*nummtrl)++; + return mtrl; +} + +/* add index to output */ +static unsigned char *_m3d_addidx(unsigned char *out, char type, uint32_t idx) { + switch(type) { + case 1: *out++ = (uint8_t)(idx); break; + case 2: *((uint16_t*)out) = (uint16_t)(idx); out += 2; break; + case 4: *((uint32_t*)out) = (uint32_t)(idx); out += 4; break; + /* case 0: case 8: break; */ + } + return out; +} + +/* round a vertex position */ +static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) +{ + register int t; + /* copy additional attributes */ + if(src != dst) memcpy(dst, src, sizeof(m3dv_t)); + /* round according to quality */ + switch(quality) { + case M3D_EXP_INT8: + t = src->x * 127; dst->x = (M3D_FLOAT)t / 127; + t = src->y * 127; dst->y = (M3D_FLOAT)t / 127; + t = src->z * 127; dst->z = (M3D_FLOAT)t / 127; + t = src->w * 127; dst->w = (M3D_FLOAT)t / 127; + break; + case M3D_EXP_INT16: + t = src->x * 32767; dst->x = (M3D_FLOAT)t / 32767; + t = src->y * 32767; dst->y = (M3D_FLOAT)t / 32767; + t = src->z * 32767; dst->z = (M3D_FLOAT)t / 32767; + t = src->w * 32767; dst->w = (M3D_FLOAT)t / 32767; + break; + } +} + +#ifdef M3D_ASCII +/* add a bone to ascii output */ +static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX parent, uint32_t level) +{ + uint32_t i, j; + char *sn; + + if(level > M3D_BONEMAXLEVEL || !bone) return ptr; + for(i = 0; i < numbone; i++) { + if(bone[i].parent == parent) { + for(j = 0; j < level; j++) *ptr++ = '/'; + sn = _m3d_safestr(bone[i].name, 0); + ptr += sprintf(ptr, "%d %d %s\r\n", bone[i].pos, bone[i].ori, sn); + M3D_FREE(sn); + ptr = _m3d_prtbone(ptr, bone, numbone, i, level + 1); + } + } + return ptr; +} +#endif + +/** + * Function to encode an in-memory model into on storage Model 3D format + */ +unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size) +{ +#ifdef M3D_ASCII + const char *ol; + char *ptr; +#endif + char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fi_s; + char *sn = NULL, *sl = NULL, *sa = NULL, *sd = NULL; + unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE]; + unsigned int i, j, k, l, len, chunklen, *length; + register float scale = 0.0f, min_x, max_x, min_y, max_y, min_z, max_z; + uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, numtmap = 0, numbone = 0; + uint32_t numskin = 0, numactn = 0, *actn = NULL, numstr = 0, nummtrl = 0, maxt = 0; + m3dstr_t *str = NULL; + m3dv_t *vrtx = NULL, vertex; + m3dti_t *tmap = NULL, tcoord; + m3db_t *bone = NULL; + m3ds_t *skin = NULL; + m3df_t *face = NULL; + m3dhdr_t *h = NULL; + m3dm_t *m, **mtrl = NULL; + m3da_t *a; + M3D_INDEX last; + + if(!model) { + if(size) *size = 0; + return NULL; + } + model->errcode = M3D_SUCCESS; +#ifdef M3D_ASCII + if(flags & M3D_EXP_ASCII) quality = M3D_EXP_DOUBLE; +#endif + /* collect array elements that are actually referenced */ + if(model->numface && model->face && !(flags & M3D_EXP_NOFACE)) { + face = (m3df_t*)M3D_MALLOC(model->numface * sizeof(m3df_t)); + if(!face) goto memerr; + memset(face, 255, model->numface * sizeof(m3df_t)); + last = (M3D_INDEX)-1U; + for(i = 0; i < model->numface; i++) { + face[i].materialid = (M3D_INDEX)-1U; + if(!(flags & M3D_EXP_NOMATERIAL) && model->face[i].materialid != last) { + last = model->face[i].materialid; + if(last < model->nummaterial) { + mtrl = _m3d_addmtrl(mtrl, &nummtrl, &model->material[last], &face[i].materialid); + if(!mtrl) goto memerr; + } + } + for(j = 0; j < 3; j++) { + k = model->face[i].vertex[j]; + if(quality < M3D_EXP_FLOAT) { + _m3d_round(quality, &model->vertex[k], &vertex); + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &idx); + } else + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[k], &idx); + if(!vrtx) goto memerr; + face[i].vertex[j] = (M3D_INDEX)idx; + if(!(flags & M3D_EXP_NOCMAP)) { + cmap = _m3d_addcmap(cmap, &numcmap, model->vertex[k].color); + if(!cmap) goto memerr; + } + k = model->face[i].normal[j]; + if(k < model->numvertex && !(flags & M3D_EXP_NONORMAL)) { + if(quality < M3D_EXP_FLOAT) { + _m3d_round(quality, &model->vertex[k], &vertex); + vrtx = _m3d_addnorm(vrtx, &numvrtx, &vertex, &idx); + } else + vrtx = _m3d_addnorm(vrtx, &numvrtx, &model->vertex[k], &idx); + if(!vrtx) goto memerr; + face[i].normal[j] = (M3D_INDEX)idx; + } + k = model->face[i].texcoord[j]; + if(k < model->numtmap) { + switch(quality) { + case M3D_EXP_INT8: + l = model->tmap[k].u * 255; tcoord.u = (M3D_FLOAT)l / 255; + l = model->tmap[k].v * 255; tcoord.v = (M3D_FLOAT)l / 255; + break; + case M3D_EXP_INT16: + l = model->tmap[k].u * 65535; tcoord.u = (M3D_FLOAT)l / 65535; + l = model->tmap[k].v * 65535; tcoord.v = (M3D_FLOAT)l / 65535; + break; + default: + tcoord.u = model->tmap[k].u; + tcoord.v = model->tmap[k].v; + break; + } + if(flags & M3D_EXP_FLIPTXTCRD) + tcoord.v = (M3D_FLOAT)1.0 - tcoord.v; + tmap = _m3d_addtmap(tmap, &numtmap, &tcoord, &idx); + if(!tmap) goto memerr; + face[i].texcoord[j] = (M3D_INDEX)idx; + } + } + /* convert from CW to CCW */ + if(flags & M3D_EXP_IDOSUCK) { + j = face[i].vertex[1]; + face[i].vertex[1] = face[i].vertex[2]; + face[i].vertex[2] = face[i].vertex[1]; + j = face[i].normal[1]; + face[i].normal[1] = face[i].normal[2]; + face[i].normal[2] = face[i].normal[1]; + j = face[i].texcoord[1]; + face[i].texcoord[1] = face[i].texcoord[2]; + face[i].texcoord[2] = face[i].texcoord[1]; + } + } + } else if(!(flags & M3D_EXP_NOMATERIAL)) { + /* without a face, simply add all materials, because it can be an mtllib */ + nummtrl = model->nummaterial; + } + /* add colors to color map and texture names to string table */ + for(i = 0; i < nummtrl; i++) { + m = !mtrl ? &model->material[i] : mtrl[i]; + str = _m3d_addstr(str, &numstr, m->name); + if(!str) goto memerr; + for(j = 0; j < mtrl[i]->numprop; j++) { + if(!(flags & M3D_EXP_NOCMAP) && m->prop[j].type < 128) { + for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) { + if(m->prop[j].type == m3d_propertytypes[l].id && m3d_propertytypes[l].format == m3dpf_color) { + cmap = _m3d_addcmap(cmap, &numcmap, m->prop[j].value.color); + if(!cmap) goto memerr; + break; + } + } + } + if(m->prop[j].type >= 128 && m->prop[j].value.textureid < model->numtexture && + model->texture[m->prop[j].value.textureid].name) { + str = _m3d_addstr(str, &numstr, model->texture[m->prop[j].value.textureid].name); + if(!str) goto memerr; + } + } + } + /* get bind-pose skeleton and skin */ + if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) { + numbone = model->numbone; + bone = (m3db_t*)M3D_MALLOC(model->numbone * sizeof(m3db_t)); + if(!bone) goto memerr; + memset(bone, 0, model->numbone * sizeof(m3db_t)); + for(i = 0; i < model->numbone; i++) { + bone[i].parent = model->bone[i].parent; + bone[i].name = model->bone[i].name; + str = _m3d_addstr(str, &numstr, bone[i].name); + if(!str) goto memerr; + if(quality < M3D_EXP_FLOAT) { + _m3d_round(quality, &model->vertex[model->bone[i].pos], &vertex); + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &k); + } else + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[model->bone[i].pos], &k); + if(!vrtx) goto memerr; + bone[i].pos = (M3D_INDEX)k; + if(quality < M3D_EXP_FLOAT) { + _m3d_round(quality, &model->vertex[model->bone[i].ori], &vertex); + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &k); + } else + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[model->bone[i].ori], &k); + if(!vrtx) goto memerr; + bone[i].ori = (M3D_INDEX)k; + } + } + /* actions, animated skeleton poses */ + if(model->numaction && model->action && !(flags & M3D_EXP_NOACTION)) { + for(j = 0; j < model->numaction; j++) { + a = &model->action[j]; + str = _m3d_addstr(str, &numstr, a->name); + if(!str) goto memerr; + if(a->numframe > 65535) a->numframe = 65535; + for(i = 0; i < a->numframe; i++) { + l = numactn; + numactn += (a->frame[i].numtransform * 2); + if(a->frame[i].numtransform > maxt) + maxt = a->frame[i].numtransform; + actn = (uint32_t*)M3D_REALLOC(actn, numactn * sizeof(uint32_t)); + if(!actn) goto memerr; + for(k = 0; k < a->frame[i].numtransform; k++) { + if(quality < M3D_EXP_FLOAT) { + _m3d_round(quality, &model->vertex[a->frame[i].transform[k].pos], &vertex); + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &actn[l++]); + if(!vrtx) goto memerr; + _m3d_round(quality, &model->vertex[a->frame[i].transform[k].ori], &vertex); + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &actn[l++]); + } else { + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[a->frame[i].transform[k].pos], &actn[l++]); + if(!vrtx) goto memerr; + vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[a->frame[i].transform[k].ori], &actn[l++]); + } + if(!vrtx) goto memerr; + } + } + } + } + /* normalize bounding cube and collect referenced skin records */ + if(numvrtx) { + min_x = min_y = min_z = 1e10; + max_x = max_y = max_z = -1e10; + j = model->numskin && model->skin && !(flags & M3D_EXP_NOBONE); + for(i = 0; i < numvrtx; i++) { + if(j && model->numskin && model->skin && vrtx[i].skinid < M3D_INDEXMAX) { + skin = _m3d_addskin(skin, &numskin, &model->skin[vrtx[i].skinid], &idx); + if(!skin) goto memerr; + vrtx[i].skinid = idx; + } + if(vrtx[i].skinid == (M3D_INDEX)-2U) continue; + if(vrtx[i].x > max_x) max_x = vrtx[i].x; + if(vrtx[i].x < min_x) min_x = vrtx[i].x; + if(vrtx[i].y > max_y) max_y = vrtx[i].y; + if(vrtx[i].y < min_y) min_y = vrtx[i].y; + if(vrtx[i].z > max_z) max_z = vrtx[i].z; + if(vrtx[i].z < min_z) min_z = vrtx[i].z; + } + if(min_x < 0.0f) min_x = -min_x; + if(max_x < 0.0f) max_x = -max_x; + if(min_y < 0.0f) min_y = -min_y; + if(max_y < 0.0f) max_y = -max_y; + if(min_z < 0.0f) min_z = -min_z; + if(max_z < 0.0f) max_z = -max_z; + scale = min_x; + if(max_x > scale) scale = max_x; + if(min_y > scale) scale = min_y; + if(max_y > scale) scale = max_y; + if(min_z > scale) scale = min_z; + if(max_z > scale) scale = max_z; + if(scale == 0.0f) scale = 1.0f; + if(scale != 1.0f && !(flags & M3D_EXP_NORECALC)) { + for(i = 0; i < numvrtx; i++) { + if(vrtx[i].skinid == (M3D_INDEX)-2U) continue; + vrtx[i].x /= scale; + vrtx[i].y /= scale; + vrtx[i].z /= scale; + } + } + } + /* if there's only one black color, don't store it */ + if(numcmap == 1 && cmap && !cmap[0]) numcmap = 0; + /* at least 3 UV coordinate required for texture mapping */ + if(numtmap < 3 && tmap) numtmap = 0; + /* meta info */ + sn = _m3d_safestr(model->name && *model->name ? model->name : (char*)"(noname)", 2); + sl = _m3d_safestr(model->license ? model->license : (char*)"MIT", 2); + sa = _m3d_safestr(model->author ? model->author : getenv("LOGNAME"), 2); + if(!sn || !sl || !sa) { +memerr: if(face) M3D_FREE(face); + if(cmap) M3D_FREE(cmap); + if(tmap) M3D_FREE(tmap); + if(mtrl) M3D_FREE(mtrl); + if(vrtx) M3D_FREE(vrtx); + if(bone) M3D_FREE(bone); + if(skin) M3D_FREE(skin); + if(actn) M3D_FREE(actn); + if(sn) M3D_FREE(sn); + if(sl) M3D_FREE(sl); + if(sa) M3D_FREE(sa); + if(sd) M3D_FREE(sd); + if(out) M3D_FREE(out); + if(str) M3D_FREE(str); + if(h) M3D_FREE(h); + M3D_LOG("Out of memory"); + model->errcode = M3D_ERR_ALLOC; + return NULL; + } + if(model->scale > (M3D_FLOAT)0.0) scale = (float)model->scale; + if(scale <= 0.0f) scale = 1.0f; +#ifdef M3D_ASCII + if(flags & M3D_EXP_ASCII) { + /* use CRLF to make model creators on Win happy... */ + sd = _m3d_safestr(model->desc, 1); + if(!sd) goto memerr; + ol = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); + /* header */ + len = 64 + strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd); + out = (unsigned char*)M3D_MALLOC(len); + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr = (char*)out; + ptr += sprintf(ptr, "3dmodel %g\r\n%s\r\n%s\r\n%s\r\n%s\r\n\r\n", scale, + sn, sl, sa, sd); + M3D_FREE(sn); M3D_FREE(sl); M3D_FREE(sa); M3D_FREE(sd); + sn = sl = sa = sd = NULL; + /* texture map */ + if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) { + ptr -= (uint64_t)out; len = (uint64_t)ptr + numtmap * 32 + 12; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Textmap\r\n"); + for(i = 0; i < numtmap; i++) + ptr += sprintf(ptr, "%g %g\r\n", tmap[i].u, tmap[i].v); + ptr += sprintf(ptr, "\r\n"); + } + /* vertex chunk */ + if(numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) { + ptr -= (uint64_t)out; len = (uint64_t)ptr + numvrtx * 128 + 10; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Vertex\r\n"); + for(i = 0; i < numvrtx; i++) { + ptr += sprintf(ptr, "%g %g %g %g", vrtx[i].x, vrtx[i].y, vrtx[i].z, vrtx[i].w); + if(!(flags & M3D_EXP_NOCMAP) && vrtx[i].color) + ptr += sprintf(ptr, " #%08x", vrtx[i].color); + if(!(flags & M3D_EXP_NOBONE) && numbone && numskin && vrtx[i].skinid != (M3D_INDEX)-1U && + vrtx[i].skinid != (M3D_INDEX)-2U) { + if(skin[vrtx[i].skinid].weight[0] == (M3D_FLOAT)1.0) + ptr += sprintf(ptr, " %d", skin[vrtx[i].skinid].boneid[0]); + else + for(j = 0; j < M3D_NUMBONE && skin[vrtx[i].skinid].boneid[j] != (M3D_INDEX)-1U && + skin[vrtx[i].skinid].weight[j] > (M3D_FLOAT)0.0; j++) + ptr += sprintf(ptr, " %d:%g", skin[vrtx[i].skinid].boneid[j], + skin[vrtx[i].skinid].weight[j]); + } + ptr += sprintf(ptr, "\r\n"); + } + ptr += sprintf(ptr, "\r\n"); + } + /* bones chunk */ + if(numbone && bone && !(flags & M3D_EXP_NOBONE)) { + ptr -= (uint64_t)out; len = (uint64_t)ptr + 9; + for(i = 0; i < numbone; i++) { + len += strlen(bone[i].name) + 128; + } + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Bones\r\n"); + ptr = _m3d_prtbone(ptr, bone, numbone, (M3D_INDEX)-1U, 0); + ptr += sprintf(ptr, "\r\n"); + } + /* materials */ + if(nummtrl && !(flags & M3D_EXP_NOMATERIAL)) { + for(j = 0; j < nummtrl; j++) { + m = !mtrl ? &model->material[j] : mtrl[j]; + sn = _m3d_safestr(m->name, 0); + if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 12; + for(i = 0; i < m->numprop; i++) { + if(m->prop[i].type < 128) + len += 32; + else if(m->prop[i].value.textureid < model->numtexture && model->texture[m->prop[i].value.textureid].name) + len += strlen(model->texture[m->prop[i].value.textureid].name) + 16; + } + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Material %s\r\n", sn); + M3D_FREE(sn); sn = NULL; + for(i = 0; i < m->numprop; i++) { + k = 256; + if(m->prop[i].type >= 128) { + for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) + if(m->prop[i].type == m3d_propertytypes[l].id) { + sn = m3d_propertytypes[l].key; + break; + } + if(!sn) + for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) + if(m->prop[i].type - 128 == m3d_propertytypes[l].id) { + sn = m3d_propertytypes[l].key; + break; + } + k = sn ? m3dpf_map : 256; + } else { + for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) + if(m->prop[i].type == m3d_propertytypes[l].id) { + sn = m3d_propertytypes[l].key; + k = m3d_propertytypes[l].format; + break; + } + } + switch(k) { + case m3dpf_color: ptr += sprintf(ptr, "%s #%08x\r\n", sn, m->prop[i].value.color); break; + case m3dpf_uint8: + case m3dpf_uint16: + case m3dpf_uint32: ptr += sprintf(ptr, "%s %d\r\n", sn, m->prop[i].value.num); break; + case m3dpf_float: ptr += sprintf(ptr, "%s %g\r\n", sn, m->prop[i].value.fnum); break; + case m3dpf_map: + if(m->prop[i].value.textureid < model->numtexture && + model->texture[m->prop[i].value.textureid].name) { + sl = _m3d_safestr(model->texture[m->prop[i].value.textureid].name, 0); + if(!sl) { setlocale(LC_NUMERIC, ol); goto memerr; } + if(*sl) + ptr += sprintf(ptr, "map_%s %s\r\n", sn, sl); + M3D_FREE(sn); M3D_FREE(sl); sl = NULL; + } + break; + } + sn = NULL; + } + ptr += sprintf(ptr, "\r\n"); + } + } + /* mesh face */ + if(model->numface && face && !(flags & M3D_EXP_NOFACE)) { + ptr -= (uint64_t)out; len = (uint64_t)ptr + model->numface * 128 + 6; + last = (M3D_INDEX)-1U; + if(!(flags & M3D_EXP_NOMATERIAL)) + for(i = 0; i < model->numface; i++) { + if(face[i].materialid != last) { + last = face[i].materialid; + if(last < nummtrl) + len += strlen(mtrl[last]->name); + len += 6; + } + } + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Mesh\r\n"); + last = (M3D_INDEX)-1U; + for(i = 0; i < model->numface; i++) { + if(!(flags & M3D_EXP_NOMATERIAL) && face[i].materialid != last) { + last = face[i].materialid; + if(last < nummtrl) { + sn = _m3d_safestr(mtrl[last]->name, 0); + if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "use %s\r\n", sn); + M3D_FREE(sn); sn = NULL; + } else + ptr += sprintf(ptr, "use\r\n"); + } + /* hardcoded triangles. Should be repeated as many times as the number of edges in polygon */ + for(j = 0; j < 3; j++) { + ptr += sprintf(ptr, "%s%d", j?" ":"", face[i].vertex[j]); + if(!(flags & M3D_EXP_NOTXTCRD) && (face[i].texcoord[j] != (M3D_INDEX)-1U)) + ptr += sprintf(ptr, "/%d", face[i].texcoord[j]); + if(!(flags & M3D_EXP_NONORMAL) && (face[i].normal[j] != (M3D_INDEX)-1U)) + ptr += sprintf(ptr, "%s/%d", + (flags & M3D_EXP_NOTXTCRD) || (face[i].texcoord[j] == (M3D_INDEX)-1U)? "/" : "", + face[i].normal[j]); + } + ptr += sprintf(ptr, "\r\n"); + } + ptr += sprintf(ptr, "\r\n"); + } + /* actions */ + if(model->numaction && model->action && numactn && actn && !(flags & M3D_EXP_NOACTION)) { + l = 0; + for(j = 0; j < model->numaction; j++) { + a = &model->action[j]; + sn = _m3d_safestr(a->name, 0); + if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 48; + for(i = 0; i < a->numframe; i++) + len += a->frame[i].numtransform * 128 + 8; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Action %d %s\r\n", a->durationmsec, sn); + M3D_FREE(sn); sn = NULL; + if(a->numframe > 65535) a->numframe = 65535; + for(i = 0; i < a->numframe; i++) { + ptr += sprintf(ptr, "frame %d\r\n", a->frame[i].msec); + for(k = 0; k < a->frame[i].numtransform; k++) { + ptr += sprintf(ptr, "%d %d %d\r\n", a->frame[i].transform[k].boneid, actn[l], actn[l + 1]); + l += 2; + } + } + ptr += sprintf(ptr, "\r\n"); + } + } + /* extra info */ + if(model->numunknown && (flags & M3D_EXP_EXTRA)) { + for(i = 0; i < model->numunknown; i++) { + if(model->unknown[i]->length < 9) continue; + ptr -= (uint64_t)out; len = (uint64_t)ptr + 17 + model->unknown[i]->length * 3; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Extra %c%c%c%c\r\n", + model->unknown[i]->magic[0] > ' ' ? model->unknown[i]->magic[0] : '_', + model->unknown[i]->magic[1] > ' ' ? model->unknown[i]->magic[1] : '_', + model->unknown[i]->magic[2] > ' ' ? model->unknown[i]->magic[2] : '_', + model->unknown[i]->magic[3] > ' ' ? model->unknown[i]->magic[3] : '_'); + for(j = 0; j < model->unknown[i]->length; j++) + ptr += sprintf(ptr, "%02x ", *((unsigned char *)model->unknown + sizeof(m3dchunk_t) + j)); + ptr--; + ptr += sprintf(ptr, "\r\n\r\n"); + } + } + setlocale(LC_NUMERIC, ol); + len = (uint64_t)ptr - (uint64_t)out; + out = (unsigned char*)M3D_REALLOC(out, len + 1); + if(!out) goto memerr; + out[len] = 0; + } else +#endif + { + /* stricly only use LF (newline) in binary */ + sd = _m3d_safestr(model->desc, 3); + if(!sd) goto memerr; + /* header */ + h = (m3dhdr_t*)M3D_MALLOC(sizeof(m3dhdr_t) + strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd) + 4); + if(!h) goto memerr; + memcpy((uint8_t*)h, "HEAD", 4); + h->length = sizeof(m3dhdr_t); + h->scale = scale; + i = strlen(sn); memcpy((uint8_t*)h + h->length, sn, i+1); h->length += i+1; M3D_FREE(sn); + i = strlen(sl); memcpy((uint8_t*)h + h->length, sl, i+1); h->length += i+1; M3D_FREE(sl); + i = strlen(sa); memcpy((uint8_t*)h + h->length, sa, i+1); h->length += i+1; M3D_FREE(sa); + i = strlen(sd); memcpy((uint8_t*)h + h->length, sd, i+1); h->length += i+1; M3D_FREE(sd); + sn = sl = sa = sd = NULL; + len = 0; + if(!bone) numbone = 0; + if(skin) + for(i = 0; i < numskin; i++) { + for(j = k = 0; j < M3D_NUMBONE; j++) + if(skin[i].boneid[j] != (M3D_INDEX)-1U && skin[i].weight[j] > (M3D_FLOAT)0.0) k++; + if(k > len) len = k; + } + else + numskin = 0; + if(model->inlined) + for(i = 0; i < model->numinlined; i++) { + if(model->inlined[i].name && *model->inlined[i].name && model->inlined[i].length > 0) { + str = _m3d_addstr(str, &numstr, model->inlined[i].name); + if(!str) goto memerr; + } + } + if(str) + for(i = 0; i < numstr; i++) { + h = _m3d_addhdr(h, &str[i]); + if(!h) goto memerr; + } + vc_s = quality == M3D_EXP_INT8? 1 : (quality == M3D_EXP_INT16? 2 : (quality == M3D_EXP_DOUBLE? 8 : 4)); + vi_s = numvrtx < 254 ? 1 : (numvrtx < 65534 ? 2 : 4); + si_s = h->length - 16 < 254 ? 1 : (h->length - 16 < 65534 ? 2 : 4); + ci_s = !numcmap || !cmap ? 0 : (numcmap < 254 ? 1 : (numcmap < 65534 ? 2 : 4)); + ti_s = !numtmap || !tmap ? 0 : (numtmap < 254 ? 1 : (numtmap < 65534 ? 2 : 4)); + bi_s = !numbone || !bone ? 0 : (numbone < 254 ? 1 : (numbone < 65534 ? 2 : 4)); + nb_s = len < 2 ? 1 : (len == 2 ? 2 : (len <= 4 ? 4 : 8)); + sk_s = !numbone || !numskin ? 0 : (numskin < 254 ? 1 : (numskin < 65534 ? 2 : 4)); + fi_s = maxt < 254 ? 1 : (maxt < 65534 ? 2 : 4); + h->types = (vc_s == 8 ? (3<<0) : (vc_s == 2 ? (1<<0) : (vc_s == 1 ? (0<<0) : (2<<0)))) | + (vi_s == 2 ? (1<<2) : (vi_s == 1 ? (0<<2) : (2<<2))) | + (si_s == 2 ? (1<<4) : (si_s == 1 ? (0<<4) : (2<<4))) | + (ci_s == 2 ? (1<<6) : (ci_s == 1 ? (0<<6) : (ci_s == 4 ? (2<<6) : (3<<6)))) | + (ti_s == 2 ? (1<<8) : (ti_s == 1 ? (0<<8) : (ti_s == 4 ? (2<<8) : (3<<8)))) | + (bi_s == 2 ? (1<<10): (bi_s == 1 ? (0<<10): (bi_s == 4 ? (2<<10) : (3<<10)))) | + (nb_s == 2 ? (1<<12): (nb_s == 1 ? (0<<12): (2<<12))) | + (sk_s == 2 ? (1<<14): (sk_s == 1 ? (0<<14): (sk_s == 4 ? (2<<14) : (3<<14)))) | + (fi_s == 2 ? (1<<16): (fi_s == 1 ? (0<<16): (2<<16))) ; + len = h->length; + /* color map */ + if(numcmap && cmap && ci_s < 4 && !(flags & M3D_EXP_NOCMAP)) { + chunklen = 8 + numcmap * sizeof(uint32_t); + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "CMAP", 4); + *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + memcpy((uint8_t*)h + len + 8, cmap, chunklen - 8); + len += chunklen; + } else numcmap = 0; + /* texture map */ + if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) { + chunklen = 8 + numtmap * vc_s * 2; + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "TMAP", 4); + *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + out = (uint8_t*)h + len + 8; + for(i = 0; i < numtmap; i++) { + switch(vc_s) { + case 1: *out++ = (uint8_t)(tmap[i].u * 255); *out++ = (uint8_t)(tmap[i].v * 255); break; + case 2: + *((uint16_t*)out) = (uint16_t)(tmap[i].u * 65535); out += 2; + *((uint16_t*)out) = (uint16_t)(tmap[i].v * 65535); out += 2; + break; + case 4: *((float*)out) = tmap[i].u; out += 4; *((float*)out) = tmap[i].v; out += 4; break; + case 8: *((double*)out) = tmap[i].u; out += 8; *((double*)out) = tmap[i].v; out += 8; break; + } + } + out = NULL; + len += chunklen; + } + /* vertex */ + if(numvrtx && vrtx) { + chunklen = 8 + numvrtx * (ci_s + sk_s + 4 * vc_s); + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "VRTS", 4); + *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + out = (uint8_t*)h + len + 8; + for(i = 0; i < numvrtx; i++) { + switch(vc_s) { + case 1: + *out++ = (int8_t)(vrtx[i].x * 127); + *out++ = (int8_t)(vrtx[i].y * 127); + *out++ = (int8_t)(vrtx[i].z * 127); + *out++ = (int8_t)(vrtx[i].w * 127); + break; + case 2: + *((int16_t*)out) = (int16_t)(vrtx[i].x * 32767); out += 2; + *((int16_t*)out) = (int16_t)(vrtx[i].y * 32767); out += 2; + *((int16_t*)out) = (int16_t)(vrtx[i].z * 32767); out += 2; + *((int16_t*)out) = (int16_t)(vrtx[i].w * 32767); out += 2; + break; + case 4: + *((float*)out) = vrtx[i].x; out += 4; + *((float*)out) = vrtx[i].y; out += 4; + *((float*)out) = vrtx[i].z; out += 4; + *((float*)out) = vrtx[i].w; out += 4; + break; + case 8: + *((double*)out) = vrtx[i].x; out += 8; + *((double*)out) = vrtx[i].y; out += 8; + *((double*)out) = vrtx[i].z; out += 8; + *((double*)out) = vrtx[i].w; out += 8; + break; + } + idx = _m3d_cmapidx(cmap, numcmap, vrtx[i].color); + switch(ci_s) { + case 1: *out++ = (uint8_t)(idx); break; + case 2: *((uint16_t*)out) = (uint16_t)(idx); out += 2; break; + case 4: *((uint32_t*)out) = vrtx[i].color; out += 4; break; + } + out = _m3d_addidx(out, sk_s, numbone && numskin ? vrtx[i].skinid : -1U); + } + out = NULL; + len += chunklen; + } + /* bones chunk */ + if(numbone && bone && !(flags & M3D_EXP_NOBONE)) { + i = 8 + bi_s + sk_s + numbone * (bi_s + si_s + 2*vi_s); + chunklen = i + numskin * nb_s * (bi_s + 1); + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "BONE", 4); + length = (uint32_t*)((uint8_t*)h + len + 4); + out = (uint8_t*)h + len + 8; + out = _m3d_addidx(out, bi_s, numbone); + out = _m3d_addidx(out, sk_s, numskin); + for(i = 0; i < numbone; i++) { + out = _m3d_addidx(out, bi_s, bone[i].parent); + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, bone[i].name)); + out = _m3d_addidx(out, vi_s, bone[i].pos); + out = _m3d_addidx(out, vi_s, bone[i].ori); + } + if(numskin && skin && sk_s) { + for(i = 0; i < numskin; i++) { + memset(&weights, 0, nb_s); + for(j = 0; j < (uint32_t)nb_s && skin[i].boneid[j] != (M3D_INDEX)-1U && + skin[i].weight[j] > (M3D_FLOAT)0.0; j++) + weights[j] = (uint8_t)(skin[i].weight[j] * 255); + switch(nb_s) { + case 1: weights[0] = 255; break; + case 2: *((uint16_t*)out) = *((uint16_t*)&weights[0]); out += 2; break; + case 4: *((uint32_t*)out) = *((uint32_t*)&weights[0]); out += 4; break; + case 8: *((uint64_t*)out) = *((uint64_t*)&weights[0]); out += 8; break; + } + for(j = 0; j < (uint32_t)nb_s && skin[i].boneid[j] != (M3D_INDEX)-1U && + skin[i].weight[j] > (M3D_FLOAT)0.0; j++) { + out = _m3d_addidx(out, bi_s, skin[i].boneid[j]); + *length += bi_s; + } + } + } + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + out = NULL; + len += *length; + } + /* materials */ + if(nummtrl && !(flags & M3D_EXP_NOMATERIAL)) { + for(j = 0; j < nummtrl; j++) { + m = !mtrl ? &model->material[j] : mtrl[j]; + chunklen = 12 + si_s + m->numprop * 5; + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "MTRL", 4); + length = (uint32_t*)((uint8_t*)h + len + 4); + out = (uint8_t*)h + len + 8; + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, m->name)); + for(i = 0; i < m->numprop; i++) { + if(m->prop[i].type >= 128) { + if(m->prop[i].value.textureid >= model->numtexture || + !model->texture[m->prop[i].value.textureid].name) continue; + k = m3dpf_map; + } else { + for(k = 256, l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) + if(m->prop[i].type == m3d_propertytypes[l].id) { k = m3d_propertytypes[l].format; break; } + } + if(k == 256) continue; + *out++ = m->prop[i].type; + switch(k) { + case m3dpf_color: + if(!(flags & M3D_EXP_NOCMAP)) { + idx = _m3d_cmapidx(cmap, numcmap, m->prop[i].value.color); + switch(ci_s) { + case 1: *out++ = (uint8_t)(idx); break; + case 2: *((uint16_t*)out) = (uint16_t)(idx); out += 2; break; + case 4: *((uint32_t*)out) = (uint32_t)(m->prop[i].value.color); out += 4; break; + } + } else out--; + break; + case m3dpf_uint8: *out++ = m->prop[i].value.num; break; + case m3dpf_uint16: *((uint16_t*)out) = m->prop[i].value.num; out += 2; break; + case m3dpf_uint32: *((uint32_t*)out) = m->prop[i].value.num; out += 4; break; + case m3dpf_float: *((float*)out) = m->prop[i].value.fnum; out += 4; break; + + case m3dpf_map: + idx = _m3d_stridx(str, numstr, model->texture[m->prop[i].value.textureid].name); + out = _m3d_addidx(out, si_s, idx); + break; + } + } + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + len += *length; + out = NULL; + } + } + /* mesh face */ + if(model->numface && face && !(flags & M3D_EXP_NOFACE)) { + chunklen = 8 + si_s + model->numface * (6 * vi_s + 3 * ti_s + si_s + 1); + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "MESH", 4); + length = (uint32_t*)((uint8_t*)h + len + 4); + out = (uint8_t*)h + len + 8; + last = (M3D_INDEX)-1U; + for(i = 0; i < model->numface; i++) { + if(!(flags & M3D_EXP_NOMATERIAL) && face[i].materialid != last) { + last = face[i].materialid; + if(last < nummtrl) { + idx = _m3d_stridx(str, numstr, !mtrl ? model->material[last].name : mtrl[last]->name); + if(idx) { + *out++ = 0; + out = _m3d_addidx(out, si_s, idx); + } + } + } + /* hardcoded triangles. */ + k = (3 << 4) | + (((flags & M3D_EXP_NOTXTCRD) || ti_s == 8 || (face[i].texcoord[0] == (M3D_INDEX)-1U && + face[i].texcoord[1] == (M3D_INDEX)-1U && face[i].texcoord[2] == (M3D_INDEX)-1U)) ? 0 : 1) | + (((flags & M3D_EXP_NONORMAL) || (face[i].normal[0] == (M3D_INDEX)-1U && + face[i].normal[1] == (M3D_INDEX)-1U && face[i].normal[2] == (M3D_INDEX)-1U)) ? 0 : 2); + *out++ = k; + for(j = 0; j < 3; j++) { + out = _m3d_addidx(out, vi_s, face[i].vertex[j]); + if(k & 1) + out = _m3d_addidx(out, ti_s, face[i].texcoord[j]); + if(k & 2) + out = _m3d_addidx(out, vi_s, face[i].normal[j]); + } + } + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + len += *length; + out = NULL; + } + /* actions */ + if(model->numaction && model->action && numactn && actn && numbone && bone && !(flags & M3D_EXP_NOACTION)) { + l = 0; + for(j = 0; j < model->numaction; j++) { + a = &model->action[j]; + chunklen = 14 + si_s + a->numframe * (4 + fi_s + maxt * (bi_s + 2 * vi_s)); + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "ACTN", 4); + length = (uint32_t*)((uint8_t*)h + len + 4); + out = (uint8_t*)h + len + 8; + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, a->name)); + *((uint16_t*)out) = (uint16_t)(a->numframe); out += 2; + *((uint32_t*)out) = (uint32_t)(a->durationmsec); out += 4; + for(i = 0; i < a->numframe; i++) { + *((uint32_t*)out) = (uint32_t)(a->frame[i].msec); out += 4; + out = _m3d_addidx(out, fi_s, a->frame[i].numtransform); + for(k = 0; k < a->frame[i].numtransform; k++) { + out = _m3d_addidx(out, bi_s, a->frame[i].transform[k].boneid); + out = _m3d_addidx(out, vi_s, actn[l++]); + out = _m3d_addidx(out, vi_s, actn[l++]); + } + } + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + len += *length; + out = NULL; + } + } + /* inlined assets */ + if(model->numinlined && model->inlined && (flags & M3D_EXP_INLINE)) { + for(j = 0; j < model->numinlined; j++) { + if(!model->inlined[j].name || !*model->inlined[j].name || !model->inlined[j].length) + continue; + chunklen = 8 + si_s + model->inlined[j].length; + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "ASET", 4); + *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + out = (uint8_t*)h + len + 8; + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->inlined[j].name)); + memcpy(out, model->inlined[j].data, model->inlined[j].length); + out = NULL; + len += chunklen; + } + } + /* extra chunks */ + if(model->numunknown && model->unknown && (flags & M3D_EXP_EXTRA)) { + for(j = 0; j < model->numunknown; j++) { + if(!model->unknown[j] || model->unknown[j]->length < 8) + continue; + chunklen = model->unknown[j]->length; + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, model->unknown[j], chunklen); + len += chunklen; + } + } + /* add end chunk */ + h = (m3dhdr_t*)M3D_REALLOC(h, len + 4); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "OMD3", 4); + len += 4; + /* zlib compress */ + if(!(flags & M3D_EXP_NOZLIB)) { + z = stbi_zlib_compress((unsigned char *)h, len, (int*)&l, 9); + if(z && l > 0) { len = l; M3D_FREE(h); h = (m3dhdr_t*)z; } + } + /* add file header at the begining */ + len += 8; + out = (unsigned char*)M3D_MALLOC(len); + if(!out) goto memerr; + memcpy(out, "3DMO", 4); + *((uint32_t*)(out + 4)) = len; + memcpy(out + 8, h, len - 8); + } + if(size) *size = out ? len : 0; + if(face) M3D_FREE(face); + if(cmap) M3D_FREE(cmap); + if(tmap) M3D_FREE(tmap); + if(mtrl) M3D_FREE(mtrl); + if(vrtx) M3D_FREE(vrtx); + if(bone) M3D_FREE(bone); + if(skin) M3D_FREE(skin); + if(actn) M3D_FREE(actn); + if(str) M3D_FREE(str); + if(h) M3D_FREE(h); + return out; +} +#endif + +#endif + +#ifdef __cplusplus +} + +#include +#include +#include + +/*** C++ wrapper class ***/ +namespace M3D { +#ifdef M3D_IMPLEMENTATION + + class Model { + public: + m3d_t *model; + + public: + Model() { + this->model = (m3d_t*)malloc(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t)); + } + Model(__attribute__((unused)) const std::string &data, __attribute__((unused)) m3dread_t ReadFileCB, + __attribute__((unused)) m3dfree_t FreeCB, __attribute__((unused)) M3D::Model mtllib) { +#ifndef M3D_NOIMPORTER + this->model = m3d_load((unsigned char *)data.data(), ReadFileCB, FreeCB, mtllib.model); +#else + Model(); +#endif + } + Model(__attribute__((unused)) const std::vector data, __attribute__((unused)) m3dread_t ReadFileCB, + __attribute__((unused)) m3dfree_t FreeCB, __attribute__((unused)) M3D::Model mtllib) { +#ifndef M3D_NOIMPORTER + this->model = m3d_load((unsigned char *)&data[0], ReadFileCB, FreeCB, mtllib.model); +#else + Model(); +#endif + } + ~Model() { m3d_free(this->model); } + + public: + m3d_t *getCStruct() { return this->model; } + std::string getName() { return std::string(this->model->name); } + void setName(std::string name) { this->model->name = (char*)name.c_str(); } + std::string getLicense() { return std::string(this->model->license); } + void setLicense(std::string license) { this->model->license = (char*)license.c_str(); } + std::string getAuthor() { return std::string(this->model->author); } + void setAuthor(std::string author) { this->model->author = (char*)author.c_str(); } + std::string getDescription() { return std::string(this->model->desc); } + void setDescription(std::string desc) { this->model->desc = (char*)desc.c_str(); } + float getScale() { return this->model->scale; } + void setScale(float scale) { this->model->scale = scale; } + std::vector getColorMap() { return this->model->cmap ? std::vector(this->model->cmap, + this->model->cmap + this->model->numcmap) : std::vector(); } + std::vector getTextureMap() { return this->model->tmap ? std::vector(this->model->tmap, + this->model->tmap + this->model->numtmap) : std::vector(); } + std::vector getTextures() { return this->model->texture ? std::vector(this->model->texture, + this->model->texture + this->model->numtexture) : std::vector(); } + std::string getTextureName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numtexture ? + std::string(this->model->texture[idx].name) : nullptr; } + std::vector getBones() { return this->model->bone ? std::vector(this->model->bone, this->model->bone + + this->model->numbone) : std::vector(); } + std::string getBoneName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numbone ? + std::string(this->model->bone[idx].name) : nullptr; } + std::vector getMaterials() { return this->model->material ? std::vector(this->model->material, + this->model->material + this->model->nummaterial) : std::vector(); } + std::string getMaterialName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->nummaterial ? + std::string(this->model->material[idx].name) : nullptr; } + int getMaterialPropertyInt(int idx, int type) { + if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 0 || type >= 127 || + !this->model->material[idx].prop) return -1; + for (int i = 0; i < this->model->material[idx].numprop; i++) { + if (this->model->material[idx].prop[i].type == type) + return this->model->material[idx].prop[i].value.num; + } + return -1; + } + uint32_t getMaterialPropertyColor(int idx, int type) { return this->getMaterialPropertyInt(idx, type); } + float getMaterialPropertyFloat(int idx, int type) { + if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 0 || type >= 127 || + !this->model->material[idx].prop) return -1.0f; + for (int i = 0; i < this->model->material[idx].numprop; i++) { + if (this->model->material[idx].prop[i].type == type) + return this->model->material[idx].prop[i].value.num; + } + return -1.0f; + } + m3dtx_t* getMaterialPropertyMap(int idx, int type) { + if (idx < 0 || (unsigned int)idx >= this->model->nummaterial || type < 128 || type > 255 || + !this->model->material[idx].prop) return nullptr; + for (int i = 0; i < this->model->material[idx].numprop; i++) { + if (this->model->material[idx].prop[i].type == type) + return this->model->material[idx].prop[i].value.textureid < this->model->numtexture ? + &this->model->texture[this->model->material[idx].prop[i].value.textureid] : nullptr; + } + return nullptr; + } + std::vector getVertices() { return this->model->vertex ? std::vector(this->model->vertex, + this->model->vertex + this->model->numvertex) : std::vector(); } + std::vector getFace() { return this->model->face ? std::vector(this->model->face, this->model->face + + this->model->numface) : std::vector(); } + std::vector getSkin() { return this->model->skin ? std::vector(this->model->skin, this->model->skin + + this->model->numskin) : std::vector(); } + std::vector getActions() { return this->model->action ? std::vector(this->model->action, + this->model->action + this->model->numaction) : std::vector(); } + std::string getActionName(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ? + std::string(this->model->action[aidx].name) : nullptr; } + unsigned int getActionDuration(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ? + this->model->action[aidx].durationmsec : 0; } + std::vector getActionFrames(int aidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction ? + std::vector(this->model->action[aidx].frame, this->model->action[aidx].frame + + this->model->action[aidx].numframe) : std::vector(); } + unsigned int getActionFrameTimestamp(int aidx, int fidx) { return aidx >= 0 && (unsigned int)aidx < this->model->numaction? + (fidx >= 0 && (unsigned int)fidx < this->model->action[aidx].numframe ? + this->model->action[aidx].frame[fidx].msec : 0) : 0; } + std::vector getActionFrameTransforms(int aidx, int fidx) { + return aidx >= 0 && (unsigned int)aidx < this->model->numaction ? ( + fidx >= 0 && (unsigned int)fidx < this->model->action[aidx].numframe ? + std::vector(this->model->action[aidx].frame[fidx].transform, + this->model->action[aidx].frame[fidx].transform + this->model->action[aidx].frame[fidx].numtransform) : + std::vector()) : std::vector(); } + std::vector getActionFrame(int aidx, int fidx, std::vector skeleton) { + m3dtr_t *pose = m3d_frame(this->model, (unsigned int)aidx, (unsigned int)fidx, + skeleton.size() ? &skeleton[0] : nullptr); + return std::vector(pose, pose + this->model->numbone); } + std::vector getActionPose(int aidx, unsigned int msec) { + m3db_t *pose = m3d_pose(this->model, (unsigned int)aidx, (unsigned int)msec); + return std::vector(pose, pose + this->model->numbone); } + std::vector getInlinedAssets() { return this->model->inlined ? std::vector(this->model->inlined, + this->model->inlined + this->model->numinlined) : std::vector(); } + std::vector> getUnknowns() { return this->model->unknown ? + std::vector>(this->model->unknown, + this->model->unknown + this->model->numunknown) : std::vector>(); } + std::vector Save(__attribute__((unused)) int quality, __attribute__((unused)) int flags) { +#ifdef M3D_EXPORTER + unsigned int size; + unsigned char *ptr = m3d_save(this->model, quality, flags, &size); + return ptr && size ? std::vector(ptr, ptr + size) : std::vector(); +#else + return std::vector(); +#endif + } + }; + +#else + class Model { + public: + m3d_t *model; + + public: + Model(const std::string &data, m3dread_t ReadFileCB, m3dfree_t FreeCB); + Model(const std::vector data, m3dread_t ReadFileCB, m3dfree_t FreeCB); + Model(); + ~Model(); + + public: + m3d_t *getCStruct(); + std::string getName(); + void setName(std::string name); + std::string getLicense(); + void setLicense(std::string license); + std::string getAuthor(); + void setAuthor(std::string author); + std::string getDescription(); + void setDescription(std::string desc); + float getScale(); + void setScale(float scale); + std::vector getColorMap(); + std::vector getTextureMap(); + std::vector getTextures(); + std::string getTextureName(int idx); + std::vector getBones(); + std::string getBoneName(int idx); + std::vector getMaterials(); + std::string getMaterialName(int idx); + int getMaterialPropertyInt(int idx, int type); + uint32_t getMaterialPropertyColor(int idx, int type); + float getMaterialPropertyFloat(int idx, int type); + m3dtx_t* getMaterialPropertyMap(int idx, int type); + std::vector getVertices(); + std::vector getFace(); + std::vector getSkin(); + std::vector getActions(); + std::string getActionName(int aidx); + unsigned int getActionDuration(int aidx); + std::vector getActionFrames(int aidx); + unsigned int getActionFrameTimestamp(int aidx, int fidx); + std::vector getActionFrameTransforms(int aidx, int fidx); + std::vector getActionFrame(int aidx, int fidx, std::vector skeleton); + std::vector getActionPose(int aidx, unsigned int msec); + std::vector getInlinedAssets(); + std::vector> getUnknowns(); + std::vector Save(int quality, int flags); + }; + +#endif /* impl */ +} + +#endif /* __cplusplus */ + +#endif From 02a63f8b1070e71bc9ee67d611d18078966451aa Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Tue, 29 Oct 2019 20:21:16 +0000 Subject: [PATCH 049/170] Fixed template being used in file --- code/PostProcessing/ArmaturePopulate.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/code/PostProcessing/ArmaturePopulate.h b/code/PostProcessing/ArmaturePopulate.h index 30bfc7509..aa1ad7c80 100644 --- a/code/PostProcessing/ArmaturePopulate.h +++ b/code/PostProcessing/ArmaturePopulate.h @@ -54,12 +54,17 @@ struct aiBone; namespace Assimp { // --------------------------------------------------------------------------- -/** ScaleProcess: Class to rescale the whole model. - * Now rescales animations, bones, and blend shapes properly. - * Please note this will not write to 'scale' transform it will rewrite mesh - * and matrixes so that your scale values - * from your model package are preserved, so this is completely intentional - * bugs should be reported as soon as they are found. +/** Armature Populate: This is a post process designed + * To save you time when importing models into your game engines + * This was originally designed only for fbx but will work with other formats + * it is intended to auto populate aiBone data with armature and the aiNode + * This is very useful when dealing with skinned meshes + * or when dealing with many different skeletons + * It's off by default but recommend that you try it and use it + * It should reduce down any glue code you have in your + * importers + * You can contact RevoluPowered + * For more info about this */ class ASSIMP_API ArmaturePopulate : public BaseProcess { public: From 5b18baf88351f2e1a8f9ee88088fac7d2298d73b Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 00:55:54 +0100 Subject: [PATCH 050/170] Fixed issues with MSVC --- code/M3D/M3DExporter.cpp | 13 +++--- code/M3D/M3DImporter.cpp | 6 +-- code/M3D/m3d.h | 89 ++++++++++++++++++++++------------------ 3 files changed, 61 insertions(+), 47 deletions(-) diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index d25b91891..9e774fa7f 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -142,11 +142,10 @@ void M3DExporter::doExport ( } // use malloc() here because m3d_free() will call free() - m3d = (m3d_t*)malloc(sizeof(m3d_t)); + m3d = (m3d_t*)calloc(1, sizeof(m3d_t)); if(!m3d) { throw DeadlyExportError( "memory allocation error" ); } - memset(m3d, 0, sizeof(m3d_t)); m3d->name = _m3d_safestr((char*)&mScene->mRootNode->mName.data, 2); // Create a model from assimp structures @@ -201,7 +200,9 @@ void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) throw DeadlyExportError( "memory allocation error" ); } /* set all index to -1 by default */ - memset(&m3d->face[n], 255, sizeof(m3df_t)); + m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] = + m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] = + m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = -1U; m3d->face[n].materialid = mi; for(k = 0; k < face->mNumIndices; k++) { // get the vertex's index @@ -209,11 +210,12 @@ void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) // multiply the position vector by the transformation matrix aiVector3D v = mesh->mVertices[l]; v *= nm; - memset(&vertex, 0, sizeof(m3dv_t)); vertex.x = v.x; vertex.y = v.y; vertex.z = v.z; vertex.w = 1.0; + vertex.color = 0; + vertex.skinid = -1U; // add color if defined if(mesh->HasVertexColors(0)) vertex.color = mkColor(&mesh->mColors[0][l]); @@ -262,7 +264,7 @@ uint32_t M3DExporter::mkColor(aiColor4D* c) // add a material to the output M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) { - unsigned int i, j, mi = -1U; + unsigned int i, mi = -1U; aiColor4D c; aiString name; ai_real f; @@ -292,6 +294,7 @@ M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) for(unsigned int k = 0; k < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); k++) { + unsigned int j; if(m3d_propertytypes[k].format == m3dpf_map) continue; if(aiProps[k].pKey) { diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index d34cd982f..d732387ce 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -629,7 +629,7 @@ void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::vector *vertices, std::vector *normals, std::vector *texcoords, std::vector *colors, std::vector *vertexids) { - unsigned int i, j, k; + unsigned int i, j; ai_assert(pMesh != nullptr); ai_assert(faces != nullptr); @@ -684,7 +684,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v if(vertexids->size()) { // first count how many vertices we have per bone for(i = 0; i < vertexids->size(); i++) { - unsigned int s = m3d->vertex[vertexids->at(i)].skinid; + unsigned int s = m3d->vertex[vertexids->at(i)].skinid, k; if(s != -1U && s!= -2U) { for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); @@ -707,7 +707,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v } // fill up with data for(i = 0; i < vertexids->size(); i++) { - unsigned int s = m3d->vertex[vertexids->at(i)].skinid; + unsigned int s = m3d->vertex[vertexids->at(i)].skinid, k; if(s != -1U && s!= -2U) { for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index e7eccc5b2..82238f6d6 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -74,6 +74,15 @@ typedef uint16_t M3D_INDEX; #ifndef M3D_BONEMAXLEVEL #define M3D_BONEMAXLEVEL 8 #endif +#ifndef _MSC_VER +#define _inline __inline__ +#define _pack __attribute__((packed)) +#define _unused __attribute__((unused)) +#else +#define _inline +#define _pack +#define _unused +#endif /*** File format structures ***/ @@ -104,12 +113,12 @@ typedef struct { uint32_t length; float scale; /* deliberately not M3D_FLOAT */ uint32_t types; -} __attribute__((packed)) m3dhdr_t; +} _pack m3dhdr_t; typedef struct { char magic[4]; uint32_t length; -} __attribute__((packed)) m3dchunk_t; +} _pack m3dchunk_t; /*** in-memory model structure ***/ @@ -125,7 +134,7 @@ typedef struct { uint32_t *d; /* pixels data */ uint16_t w; /* width */ uint16_t h; /* height */ -} __attribute__((packed)) m3dtx_t; +} _pack m3dtx_t; typedef struct { M3D_INDEX vertexid; @@ -179,7 +188,7 @@ typedef struct { #endif } m3dpd_t; -/* material properties */ +/* material property types */ /* You shouldn't change the first 8 display and first 4 physical property. Assign the rest as you like. */ enum { m3dp_Kd = 0, /* scalar display properties */ @@ -216,6 +225,7 @@ enum { /* aliases */ m3dp_bump = m3dp_map_Km, m3dp_refl = m3dp_map_Pm }; +extern m3dpd_t m3d_propertytypes[]; /* material property */ typedef struct { @@ -243,7 +253,7 @@ typedef struct { M3D_INDEX texcoord[3]; /* UV coordinates */ } m3df_t; -/* frame transformations entry */ +/* frame transformations / working copy skeleton entry */ typedef struct { M3D_INDEX boneid; /* selects a node in bone hierarchy */ M3D_INDEX pos; /* vertex index new position */ @@ -270,7 +280,7 @@ typedef struct { char *name; /* asset name (same pointer as in texture[].name) */ uint8_t *data; /* compressed asset data */ uint32_t length; /* compressed data length */ -} __attribute__((packed)) m3di_t; +} m3di_t; /*** in-memory model structure ***/ #define M3D_FLG_FREERAW (1<<0) @@ -374,8 +384,8 @@ char *_m3d_safestr(char *in, int morelines); /*** C implementation ***/ #ifdef M3D_IMPLEMENTATION #if !defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER) -/* property definitions */ -static m3dpd_t m3d_propertytypes[] = { +/* material property definitions */ +m3dpd_t m3d_propertytypes[] = { M3D_PROPERTYDEF(m3dpf_color, m3dp_Kd, "Kd"), /* diffuse color */ M3D_PROPERTYDEF(m3dpf_color, m3dp_Ka, "Ka"), /* ambient color */ M3D_PROPERTYDEF(m3dpf_color, m3dp_Ks, "Ks"), /* specular color */ @@ -462,14 +472,14 @@ typedef struct #define STBI_FREE(p) M3D_FREE(p) #define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) -__inline__ static stbi_uc stbi__get8(stbi__context *s) +_inline static stbi_uc stbi__get8(stbi__context *s) { if (s->img_buffer < s->img_buffer_end) return *s->img_buffer++; return 0; } -__inline__ static int stbi__at_eof(stbi__context *s) +_inline static int stbi__at_eof(stbi__context *s) { return s->img_buffer >= s->img_buffer_end; } @@ -512,7 +522,7 @@ static int stbi__errstr(const char *str) return 0; } -__inline__ static void *stbi__malloc(size_t size) +_inline static void *stbi__malloc(size_t size) { return STBI_MALLOC(size); } @@ -662,7 +672,7 @@ typedef struct stbi__uint16 value[288]; } stbi__zhuffman; -__inline__ static int stbi__bitreverse16(int n) +_inline static int stbi__bitreverse16(int n) { n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); @@ -671,7 +681,7 @@ __inline__ static int stbi__bitreverse16(int n) return n; } -__inline__ static int stbi__bit_reverse(int v, int bits) +_inline static int stbi__bit_reverse(int v, int bits) { STBI_ASSERT(bits <= 16); return stbi__bitreverse16(v) >> (16-bits); @@ -737,7 +747,7 @@ typedef struct stbi__zhuffman z_length, z_distance; } stbi__zbuf; -__inline__ static stbi_uc stbi__zget8(stbi__zbuf *z) +_inline static stbi_uc stbi__zget8(stbi__zbuf *z) { if (z->zbuffer >= z->zbuffer_end) return 0; return *z->zbuffer++; @@ -752,7 +762,7 @@ static void stbi__fill_bits(stbi__zbuf *z) } while (z->num_bits <= 24); } -__inline__ static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) { unsigned int k; if (z->num_bits < n) stbi__fill_bits(z); @@ -777,7 +787,7 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) return z->value[b]; } -__inline__ static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) { int b,s; if (a->num_bits < 16) stbi__fill_bits(a); @@ -915,7 +925,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a) return 1; } -__inline__ static int stbi__parse_uncompressed_block(stbi__zbuf *a) +_inline static int stbi__parse_uncompressed_block(stbi__zbuf *a) { stbi_uc header[4]; int len,nlen,k; @@ -1034,7 +1044,7 @@ static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) return c; } -__inline__ static int stbi__check_png_header(stbi__context *s) +_inline static int stbi__check_png_header(stbi__context *s) { static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; int i; @@ -2008,8 +2018,11 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char s.read_from_callbacks = 0; s.img_buffer = s.img_buffer_original = (stbi_uc *) buff; s.img_buffer_end = s.img_buffer_original_end = (stbi_uc *) buff+len; + /* don't use model->texture[i].w directly, it's a uint16_t */ w = h = 0; model->texture[i].d = (uint32_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, STBI_rgb_alpha, &ri); + model->texture[i].w = w; + model->texture[i].h = h; } else { #ifdef M3D_TX_INTERP if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) { @@ -2022,21 +2035,18 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char #endif } if(freecb) (*freecb)(buff); - if(!model->texture[i].d || !w || !h) { - if(model->texture[i].d) M3D_FREE(model->texture[i].d); + if(!model->texture[i].d) { + M3D_FREE(model->texture[i].d); model->errcode = M3D_ERR_UNKIMG; model->numtexture--; return -1U; } - model->texture[i].w = w; - model->texture[i].h = h; model->texture[i].name = fn; return i; } /* helper function to load and generate a procedural surface */ -void _m3d_getpr(m3d_t *model, __attribute__((unused)) m3dread_t readfilecb, __attribute__((unused)) m3dfree_t freecb, - __attribute__((unused)) char *fn) +void _m3d_getpr(m3d_t *model, _unused m3dread_t readfilecb, _unused m3dfree_t freecb, _unused char *fn) { #ifdef M3D_PR_INTERP unsigned int i, len = 0; @@ -2065,7 +2075,7 @@ void _m3d_getpr(m3d_t *model, __attribute__((unused)) m3dread_t readfilecb, __at } /* helpers to read indices from data stream */ #define M3D_GETSTR(x) do{offs=0;data=_m3d_getidx(data,model->si_s,&offs);x=offs?((char*)model->raw+16+offs):NULL;}while(0) -__inline__ static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_INDEX *idx) +_inline static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_INDEX *idx) { switch(type) { case 1: *idx = data[0] > 253 ? (int8_t)data[0] : data[0]; data++; break; @@ -2606,8 +2616,8 @@ asciiend: M3D_LOG("Double precision coordinates not supported, truncating to float..."); model->errcode = M3D_ERR_TRUNC; } - if(sizeof(M3D_INDEX) == 2 && (model->vi_s > 2 || model->si_s == 4 || model->ci_s == 4 || model->ti_s == 4 || - model->bi_s == 4 || model->sk_s == 4 || model->fi_s == 4)) { + if(sizeof(M3D_INDEX) == 2 && (model->vi_s > 2 || model->si_s > 2 || model->ci_s > 2 || model->ti_s > 2 || + model->bi_s > 2 || model->sk_s > 2 || model->fi_s > 2)) { M3D_LOG("32 bit indices not supported, unable to load model"); M3D_FREE(model); return NULL; @@ -2667,15 +2677,16 @@ memerr: M3D_LOG("Out of memory"); /* color map */ if(M3D_CHUNKMAGIC(data, 'C','M','A','P')) { M3D_LOG("Color map"); - if(model->cmap) { M3D_LOG("More color map chunks, should be unique"); model->errcode = M3D_ERR_CMAP; break; } - if(model->ci_s >= 4) { M3D_LOG("Color map chunk, shouldn't be any"); model->errcode = M3D_ERR_CMAP; break; } + if(model->cmap) { M3D_LOG("More color map chunks, should be unique"); model->errcode = M3D_ERR_CMAP; continue; } + if(!model->ci_s) { M3D_LOG("Color map chunk, shouldn't be any"); model->errcode = M3D_ERR_CMAP; continue; } model->numcmap = len / sizeof(uint32_t); model->cmap = (uint32_t*)(data + sizeof(m3dchunk_t)); } else /* texture map */ if(M3D_CHUNKMAGIC(data, 'T','M','A','P')) { M3D_LOG("Texture map"); - if(model->tmap) { M3D_LOG("More texture map chunks, should be unique"); model->errcode = M3D_ERR_TMAP; break; } + if(model->tmap) { M3D_LOG("More texture map chunks, should be unique"); model->errcode = M3D_ERR_TMAP; continue; } + if(!model->ti_s) { M3D_LOG("Texture map chunk, shouldn't be any"); model->errcode = M3D_ERR_TMAP; continue; } reclen = model->vc_s + model->vc_s; model->numtmap = len / reclen; model->tmap = (m3dti_t*)M3D_MALLOC(model->numtmap * sizeof(m3dti_t)); @@ -2705,7 +2716,7 @@ memerr: M3D_LOG("Out of memory"); /* vertex list */ if(M3D_CHUNKMAGIC(data, 'V','R','T','S')) { M3D_LOG("Vertex list"); - if(model->vertex) { M3D_LOG("More vertex chunks, should be unique"); model->errcode = M3D_ERR_VRTS; break; } + if(model->vertex) { M3D_LOG("More vertex chunks, should be unique"); model->errcode = M3D_ERR_VRTS; continue; } if(model->ci_s && model->ci_s < 4 && !model->cmap) model->errcode = M3D_ERR_CMAP; reclen = model->ci_s + model->sk_s + 4 * model->vc_s; model->numvertex = len / reclen; @@ -2756,8 +2767,8 @@ memerr: M3D_LOG("Out of memory"); /* skeleton: bone hierarchy and skin */ if(M3D_CHUNKMAGIC(data, 'B','O','N','E')) { M3D_LOG("Skeleton"); - if(model->bone) { M3D_LOG("More bone chunks, should be unique"); model->errcode = M3D_ERR_BONE; break; } - if(model->bi_s > 4) { M3D_LOG("Bone chunk, shouldn't be any"); model->errcode=M3D_ERR_BONE; break; } + if(model->bone) { M3D_LOG("More bone chunks, should be unique"); model->errcode = M3D_ERR_BONE; continue; } + if(!model->bi_s) { M3D_LOG("Bone chunk, shouldn't be any"); model->errcode=M3D_ERR_BONE; continue; } if(!model->vertex) { M3D_LOG("No vertex chunk before bones"); model->errcode = M3D_ERR_VRTS; break; } data += sizeof(m3dchunk_t); model->numbone = 0; @@ -3353,7 +3364,7 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s) } /* compare two colors by HSV value */ -__inline__ static int _m3d_cmapcmp(const void *a, const void *b) +_inline static int _m3d_cmapcmp(const void *a, const void *b) { uint8_t *A = (uint8_t*)a, *B = (uint8_t*)b; register int m, vA, vB; @@ -4348,16 +4359,16 @@ namespace M3D { Model() { this->model = (m3d_t*)malloc(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t)); } - Model(__attribute__((unused)) const std::string &data, __attribute__((unused)) m3dread_t ReadFileCB, - __attribute__((unused)) m3dfree_t FreeCB, __attribute__((unused)) M3D::Model mtllib) { + Model(_unused const std::string &data, _unused m3dread_t ReadFileCB, + _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) { #ifndef M3D_NOIMPORTER this->model = m3d_load((unsigned char *)data.data(), ReadFileCB, FreeCB, mtllib.model); #else Model(); #endif } - Model(__attribute__((unused)) const std::vector data, __attribute__((unused)) m3dread_t ReadFileCB, - __attribute__((unused)) m3dfree_t FreeCB, __attribute__((unused)) M3D::Model mtllib) { + Model(_unused const std::vector data, _unused m3dread_t ReadFileCB, + _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) { #ifndef M3D_NOIMPORTER this->model = m3d_load((unsigned char *)&data[0], ReadFileCB, FreeCB, mtllib.model); #else @@ -4459,7 +4470,7 @@ namespace M3D { std::vector> getUnknowns() { return this->model->unknown ? std::vector>(this->model->unknown, this->model->unknown + this->model->numunknown) : std::vector>(); } - std::vector Save(__attribute__((unused)) int quality, __attribute__((unused)) int flags) { + std::vector Save(_unused int quality, _unused int flags) { #ifdef M3D_EXPORTER unsigned int size; unsigned char *ptr = m3d_save(this->model, quality, flags, &size); From 1c23d2e8de13738d06ee84de5861a0cbc4300ff4 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 01:11:34 +0100 Subject: [PATCH 051/170] More reduced scope fix by wasting more memory... --- code/M3D/M3DExporter.cpp | 10 +++++----- code/M3D/M3DImporter.cpp | 11 ++++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index 9e774fa7f..9ba48b125 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -264,7 +264,7 @@ uint32_t M3DExporter::mkColor(aiColor4D* c) // add a material to the output M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) { - unsigned int i, mi = -1U; + unsigned int mi = -1U; aiColor4D c; aiString name; ai_real f; @@ -274,13 +274,14 @@ M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) strcmp((char*)&name.data, AI_DEFAULT_MATERIAL_NAME)) { // check if we have saved a material by this name. This has to be done // because only the referenced materials should be added to the output - for(i = 0; i < m3d->nummaterial; i++) + for(unsigned int i = 0; i < m3d->nummaterial; i++) if(!strcmp((char*)&name.data, m3d->material[i].name)) { mi = i; break; } // if not found, add the material to the output if(mi == -1U) { + unsigned int k; mi = m3d->nummaterial++; m3d->material = (m3dm_t*)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t)); @@ -291,9 +292,7 @@ M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) m3d->material[mi].numprop = 0; m3d->material[mi].prop = NULL; // iterate through the material property table and see what we got - for(unsigned int k = 0; - k < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); - k++) { + for(k = 0; k < 15; k++) { unsigned int j; if(m3d_propertytypes[k].format == m3dpf_map) continue; @@ -341,6 +340,7 @@ M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) mat->GetTexture((aiTextureType)aiTxProps[k].type, aiTxProps[k].index, &name, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) { + unsigned int i; for(j = name.length-1; j > 0 && name.data[j]!='.'; j++); if(j && name.data[j]=='.' && (name.data[j+1]=='p' || name.data[j+1]=='P') && diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index d732387ce..873c51f97 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -629,7 +629,6 @@ void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::vector *vertices, std::vector *normals, std::vector *texcoords, std::vector *colors, std::vector *vertexids) { - unsigned int i, j; ai_assert(pMesh != nullptr); ai_assert(faces != nullptr); @@ -644,6 +643,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); if(vertices->size() && faces->size()) { + unsigned int i; pMesh->mNumFaces = faces->size(); pMesh->mFaces = new aiFace[pMesh->mNumFaces]; std::copy(faces->begin(), faces->end(), pMesh->mFaces); @@ -682,11 +682,12 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } if(vertexids->size()) { + unsigned int j; // first count how many vertices we have per bone for(i = 0; i < vertexids->size(); i++) { - unsigned int s = m3d->vertex[vertexids->at(i)].skinid, k; + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if(s != -1U && s!= -2U) { - for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + for(unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); for(j = 0; j < pMesh->mNumBones; j++) { if(pMesh->mBones[j]->mName == name) { @@ -707,9 +708,9 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v } // fill up with data for(i = 0; i < vertexids->size(); i++) { - unsigned int s = m3d->vertex[vertexids->at(i)].skinid, k; + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if(s != -1U && s!= -2U) { - for(k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + for(unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); for(j = 0; j < pMesh->mNumBones; j++) { if(pMesh->mBones[j]->mName == name) { From 7ed621b53f08fb9e4b3c0ff76c615ef44a70d58c Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 01:14:20 +0100 Subject: [PATCH 052/170] More reduced scope fix by wasting more memory... --- code/M3D/m3d.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 82238f6d6..d8d0602f6 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -225,7 +225,6 @@ enum { /* aliases */ m3dp_bump = m3dp_map_Km, m3dp_refl = m3dp_map_Pm }; -extern m3dpd_t m3d_propertytypes[]; /* material property */ typedef struct { @@ -385,7 +384,7 @@ char *_m3d_safestr(char *in, int morelines); #ifdef M3D_IMPLEMENTATION #if !defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER) /* material property definitions */ -m3dpd_t m3d_propertytypes[] = { +static m3dpd_t m3d_propertytypes[] = { M3D_PROPERTYDEF(m3dpf_color, m3dp_Kd, "Kd"), /* diffuse color */ M3D_PROPERTYDEF(m3dpf_color, m3dp_Ka, "Ka"), /* ambient color */ M3D_PROPERTYDEF(m3dpf_color, m3dp_Ks, "Ks"), /* specular color */ From 5a7928704141e4f2c39a4a108b410b0051a2a298 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 01:21:15 +0100 Subject: [PATCH 053/170] More reduced scope fix, what's wrong with reusing i as a loop variable? --- code/M3D/M3DImporter.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 873c51f97..980171f73 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -643,7 +643,6 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); if(vertices->size() && faces->size()) { - unsigned int i; pMesh->mNumFaces = faces->size(); pMesh->mFaces = new aiFace[pMesh->mNumFaces]; std::copy(faces->begin(), faces->end(), pMesh->mFaces); @@ -669,7 +668,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v /* we need aiBone with mOffsetMatrix for bones without weights as well */ if(pMesh->mNumBones) { pMesh->mBones = new aiBone*[pMesh->mNumBones]; - for(i = 0; i < m3d->numbone; i++) { + for(unsigned int i = 0; i < m3d->numbone; i++) { aiNode *pNode; pMesh->mBones[i] = new aiBone; pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name)); @@ -682,7 +681,7 @@ void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::v pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } if(vertexids->size()) { - unsigned int j; + unsigned int i, j; // first count how many vertices we have per bone for(i = 0; i < vertexids->size(); i++) { unsigned int s = m3d->vertex[vertexids->at(i)].skinid; From 60e9157699fcc3c0c00a3fcd024ae455eee05f05 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 01:37:28 +0100 Subject: [PATCH 054/170] Fixed AI_MATKEY list string constant issue. My gcc didn't comply about this --- code/M3D/M3DMaterials.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/M3D/M3DMaterials.h b/code/M3D/M3DMaterials.h index 86a802021..b3c91ab7a 100644 --- a/code/M3D/M3DMaterials.h +++ b/code/M3D/M3DMaterials.h @@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * only once. D.R.Y. and K.I.S.S. */ typedef struct { - char *pKey; + const char *pKey; unsigned int type; unsigned int index; } aiMatProp; From 0ff3e4015728b3d208c6c2199b11e1425a8434d4 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 02:35:51 +0100 Subject: [PATCH 055/170] Fixed clang's casting issue and MSVC's buffer allocation problem --- code/M3D/M3DImporter.cpp | 8 +++++--- code/M3D/m3d.h | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 980171f73..fcff49df7 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -96,13 +96,14 @@ static const aiImporterDesc desc = { // workaround: the SDK expects a C callback, but we want to use Assimp::IOSystem to implement that extern "C" { - struct Assimp::IOSystem* m3dimporter_pIOHandler; + void* m3dimporter_pIOHandler; unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { ai_assert( nullptr != fn ); ai_assert( nullptr != size ); std::string file(fn); - std::unique_ptr pStream( m3dimporter_pIOHandler->Open( file, "rb")); + std::unique_ptr pStream( + (reinterpret_cast(m3dimporter_pIOHandler))->Open( file, "rb")); size_t fileSize = pStream->FileSize(); // should be allocated with malloc(), because the library will call free() to deallocate unsigned char *data = (unsigned char*)malloc(fileSize); @@ -179,7 +180,8 @@ void M3DImporter::InternReadFile( const std::string &file, aiScene* pScene, IOSy if( fileSize < 8 ) { throw DeadlyImportError( "M3D-file " + file + " is too small." ); } - unsigned char data[fileSize]; + std::unique_ptr _buffer (new unsigned char[fileSize]); + unsigned char *data( _buffer.get() ); if(fileSize != pStream->Read(data,1,fileSize)) { throw DeadlyImportError( "Failed to read the file " + file + "." ); } diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index d8d0602f6..b43f0721c 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -1987,7 +1987,7 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char i = strlen(fn); if(i < 5 || fn[i - 4] != '.') { fn2 = (char*)M3D_MALLOC(i + 5); - if(!fn2) { model->errcode = M3D_ERR_ALLOC; return -1U; } + if(!fn2) { model->errcode = M3D_ERR_ALLOC; return (M3D_INDEX)-1U; } memcpy(fn2, fn, i); memcpy(fn2+i, ".png", 5); buff = (*readfilecb)(fn2, &len); @@ -2005,12 +2005,12 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char break; } } - if(!buff) return -1U; + if(!buff) return (M3D_INDEX)-1U; i = model->numtexture++; model->texture = (m3dtx_t*)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t)); if(!model->texture) { if(freecb) (*freecb)(buff); - model->errcode = M3D_ERR_ALLOC; return -1U; + model->errcode = M3D_ERR_ALLOC; return (M3D_INDEX)-1U; } model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL; if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') { @@ -2038,7 +2038,7 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char M3D_FREE(model->texture[i].d); model->errcode = M3D_ERR_UNKIMG; model->numtexture--; - return -1U; + return (M3D_INDEX)-1U; } model->texture[i].name = fn; return i; @@ -3198,7 +3198,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) p = &model->vertex[ret[i].ori]; f = &model->vertex[tmp[i].ori]; v = &model->vertex[j]; - d = (p->w * f->w + p->x * f->x + p->y * f->y + p->z * f->z < 0) ? -1 : 1; + d = (p->w * f->w + p->x * f->x + p->y * f->y + p->z * f->z < 0) ? (M3D_FLOAT)-1.0 : (M3D_FLOAT)1.0; v->x = p->x + t * (d*f->x - p->x); v->y = p->y + t * (d*f->y - p->y); v->z = p->z + t * (d*f->z - p->z); @@ -4419,7 +4419,7 @@ namespace M3D { !this->model->material[idx].prop) return -1.0f; for (int i = 0; i < this->model->material[idx].numprop; i++) { if (this->model->material[idx].prop[i].type == type) - return this->model->material[idx].prop[i].value.num; + return this->model->material[idx].prop[i].value.fnum; } return -1.0f; } From 37cc29c020c9ddad25bdee11e2fcb2734da2aa38 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 03:04:33 +0100 Subject: [PATCH 056/170] Fixed clang's problem with register keyword --- code/M3D/m3d.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index b43f0721c..cccfa1a0f 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -83,6 +83,10 @@ typedef uint16_t M3D_INDEX; #define _pack #define _unused #endif +#ifndef __cplusplus +#define _register register +#define _register +#endif /*** File format structures ***/ @@ -3366,7 +3370,7 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s) _inline static int _m3d_cmapcmp(const void *a, const void *b) { uint8_t *A = (uint8_t*)a, *B = (uint8_t*)b; - register int m, vA, vB; + _register int m, vA, vB; /* get HSV value for A */ m = A[2] < A[1]? A[2] : A[1]; if(A[0] < m) m = A[0]; vA = A[2] > A[1]? A[2] : A[1]; if(A[0] > vA) vA = A[0]; @@ -3464,7 +3468,7 @@ static unsigned char *_m3d_addidx(unsigned char *out, char type, uint32_t idx) { /* round a vertex position */ static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) { - register int t; + _register int t; /* copy additional attributes */ if(src != dst) memcpy(dst, src, sizeof(m3dv_t)); /* round according to quality */ @@ -3518,7 +3522,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size char *sn = NULL, *sl = NULL, *sa = NULL, *sd = NULL; unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE]; unsigned int i, j, k, l, len, chunklen, *length; - register float scale = 0.0f, min_x, max_x, min_y, max_y, min_z, max_z; + float scale = 0.0f, min_x, max_x, min_y, max_y, min_z, max_z; uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, numtmap = 0, numbone = 0; uint32_t numskin = 0, numactn = 0, *actn = NULL, numstr = 0, nummtrl = 0, maxt = 0; m3dstr_t *str = NULL; From 3bf81375dac4d0dd3a66a12333e3134723515aa3 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 30 Oct 2019 03:06:24 +0100 Subject: [PATCH 057/170] Fixed clang's problem with register keyword --- code/M3D/m3d.h | 1 + 1 file changed, 1 insertion(+) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index cccfa1a0f..eed66d3e5 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -85,6 +85,7 @@ typedef uint16_t M3D_INDEX; #endif #ifndef __cplusplus #define _register register +#else #define _register #endif From 805bc2e766fa215f858af1ac787b2766e65f6e4c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 31 Oct 2019 20:18:39 +0100 Subject: [PATCH 058/170] Update ColladaParser.cpp Add missing brackets. --- code/Collada/ColladaParser.cpp | 69 +++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index fc7ab8c2f..d5e4382a5 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -3170,13 +3170,12 @@ void ColladaParser::ReadScene() // ------------------------------------------------------------------------------------------------ // Aborts the file reading with an exception -AI_WONT_RETURN void ColladaParser::ThrowException(const std::string& pError) const -{ +AI_WONT_RETURN void ColladaParser::ThrowException(const std::string& pError) const { throw DeadlyImportError(format() << "Collada: " << mFileName << " - " << pError); } -void ColladaParser::ReportWarning(const char* msg, ...) -{ - ai_assert(NULL != msg); + +void ColladaParser::ReportWarning(const char* msg, ...) { + ai_assert(nullptr != msg); va_list args; va_start(args, msg); @@ -3191,11 +3190,11 @@ void ColladaParser::ReportWarning(const char* msg, ...) // ------------------------------------------------------------------------------------------------ // Skips all data until the end node of the current element -void ColladaParser::SkipElement() -{ +void ColladaParser::SkipElement() { // nothing to skip if it's an - if (mReader->isEmptyElement()) + if (mReader->isEmptyElement()) { return; + } // reroute SkipElement(mReader->getNodeName()); @@ -3203,67 +3202,75 @@ void ColladaParser::SkipElement() // ------------------------------------------------------------------------------------------------ // Skips all data until the end node of the given element -void ColladaParser::SkipElement(const char* pElement) -{ +void ColladaParser::SkipElement(const char* pElement) { // copy the current node's name because it'a pointer to the reader's internal buffer, // which is going to change with the upcoming parsing std::string element = pElement; - while (mReader->read()) - { - if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - if (mReader->getNodeName() == element) + while (mReader->read()) { + if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + if (mReader->getNodeName() == element) { break; + } + } } } // ------------------------------------------------------------------------------------------------ // Tests for an opening element of the given name, throws an exception if not found -void ColladaParser::TestOpening(const char* pName) -{ +void ColladaParser::TestOpening(const char* pName) { // read element start - if (!mReader->read()) + if (!mReader->read()) { ThrowException(format() << "Unexpected end of file while beginning of <" << pName << "> element."); + } // whitespace in front is ok, just read again if found - if (mReader->getNodeType() == irr::io::EXN_TEXT) - if (!mReader->read()) + if (mReader->getNodeType() == irr::io::EXN_TEXT) { + if (!mReader->read()) { ThrowException(format() << "Unexpected end of file while reading beginning of <" << pName << "> element."); + } + } - if (mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp(mReader->getNodeName(), pName) != 0) + if (mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp(mReader->getNodeName(), pName) != 0) { ThrowException(format() << "Expected start of <" << pName << "> element."); + } } // ------------------------------------------------------------------------------------------------ // Tests for the closing tag of the given element, throws an exception if not found -void ColladaParser::TestClosing(const char* pName) -{ +void ColladaParser::TestClosing(const char* pName) { // check if we have an empty (self-closing) element - if (mReader->isEmptyElement()) + if (mReader->isEmptyElement()) { return; + } // check if we're already on the closing tag and return right away - if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp(mReader->getNodeName(), pName) == 0) + if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp(mReader->getNodeName(), pName) == 0) { return; + } // if not, read some more - if (!mReader->read()) + if (!mReader->read()) { ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element."); + } // whitespace in front is ok, just read again if found - if (mReader->getNodeType() == irr::io::EXN_TEXT) - if (!mReader->read()) + if (mReader->getNodeType() == irr::io::EXN_TEXT) { + if (!mReader->read()) { ThrowException(format() << "Unexpected end of file while reading end of <" << pName << "> element."); + } + } // but this has the be the closing tag, or we're lost - if (mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp(mReader->getNodeName(), pName) != 0) + if (mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp(mReader->getNodeName(), pName) != 0) { ThrowException(format() << "Expected end of <" << pName << "> element."); + } } // ------------------------------------------------------------------------------------------------ // Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes -int ColladaParser::GetAttribute(const char* pAttr) const -{ +int ColladaParser::GetAttribute(const char* pAttr) const { int index = TestAttribute(pAttr); - if (index != -1) + if (index != -1) { return index; + } // attribute not found -> throw an exception ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">."); From 8ebd48442eab97ea1567ff819c082d84abd22852 Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 1 Nov 2019 03:39:36 +0100 Subject: [PATCH 059/170] Made the M3D SDK C++ wrapper optional --- code/M3D/m3d.h | 93 +++++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index eed66d3e5..7218f83e7 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -1899,26 +1899,7 @@ static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) return _m3d_findarg(e); } #endif -#if !defined(M3D_NODUP) && (defined(M3D_ASCII) || defined(M3D_EXPORTER)) -m3ds_t *_m3d_addskin(m3ds_t *skin, uint32_t *numskin, m3ds_t *s, uint32_t *idx) -{ - uint32_t i; - M3D_FLOAT w = (M3D_FLOAT)0.0; - for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) - w += s->weight[i]; - if(w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) - for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) - s->weight[i] /= w; - if(skin) { - for(i = 0; i < *numskin; i++) - if(!memcmp(&skin[i], s, sizeof(m3ds_t))) { *idx = i; return skin; } - } - skin = (m3ds_t*)M3D_REALLOC(skin, ((*numskin) + 1) * sizeof(m3ds_t)); - memcpy(&skin[*numskin], s, sizeof(m3ds_t)); - *idx = *numskin; - (*numskin)++; - return skin; -} +#if !defined(M3D_NODUP) && (!defined(M3D_NONORMALS) || defined(M3D_EXPORTER)) /* add vertex to list, only compare x,y,z */ m3dv_t *_m3d_addnorm(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) { @@ -1939,6 +1920,27 @@ m3dv_t *_m3d_addnorm(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) (*numvrtx)++; return vrtx; } +#endif +#if !defined(M3D_NODUP) && (defined(M3D_ASCII) || defined(M3D_EXPORTER)) +m3ds_t *_m3d_addskin(m3ds_t *skin, uint32_t *numskin, m3ds_t *s, uint32_t *idx) +{ + uint32_t i; + M3D_FLOAT w = (M3D_FLOAT)0.0; + for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) + w += s->weight[i]; + if(w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) + for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) + s->weight[i] /= w; + if(skin) { + for(i = 0; i < *numskin; i++) + if(!memcmp(&skin[i], s, sizeof(m3ds_t))) { *idx = i; return skin; } + } + skin = (m3ds_t*)M3D_REALLOC(skin, ((*numskin) + 1) * sizeof(m3ds_t)); + memcpy(&skin[*numskin], s, sizeof(m3ds_t)); + *idx = *numskin; + (*numskin)++; + return skin; +} /* helper function to create safe strings */ char *_m3d_safestr(char *in, int morelines) { @@ -2089,19 +2091,6 @@ _inline static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_IN return data; } -/* fast inverse square root calculation. returns 1/sqrt(x) */ -static M3D_FLOAT _m3d_rsq(M3D_FLOAT x) -{ -#ifdef M3D_DOUBLE - return ((M3D_FLOAT)15.0/(M3D_FLOAT)8.0) + ((M3D_FLOAT)-5.0/(M3D_FLOAT)4.0)*x + ((M3D_FLOAT)3.0/(M3D_FLOAT)8.0)*x*x; -#else - /* John Carmack's */ - float x2 = x * 0.5f; - *((uint32_t*)&x) = (0x5f3759df - (*((uint32_t*)&x) >> 1)); - return x * (1.5f - (x2 * x * x)); -#endif -} - #ifndef M3D_NOANIMATION /* multiply 4 x 4 matrices. Do not use float *r[16] as argument, because some compilers misinterpret that as * 16 pointers each pointing to a float, but we need a single pointer to 16 floats. */ @@ -2176,6 +2165,20 @@ void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1; } #endif +#if !defined(M3D_NOANIMATION) || !defined(M3D_NONORMALS) +/* fast inverse square root calculation. returns 1/sqrt(x) */ +static M3D_FLOAT _m3d_rsq(M3D_FLOAT x) +{ +#ifdef M3D_DOUBLE + return ((M3D_FLOAT)15.0/(M3D_FLOAT)8.0) + ((M3D_FLOAT)-5.0/(M3D_FLOAT)4.0)*x + ((M3D_FLOAT)3.0/(M3D_FLOAT)8.0)*x*x; +#else + /* John Carmack's */ + float x2 = x * 0.5f; + *((uint32_t*)&x) = (0x5f3759df - (*((uint32_t*)&x) >> 1)); + return x * (1.5f - (x2 * x * x)); +#endif +} +#endif /** * Function to decode a Model 3D into in-memory format @@ -2183,12 +2186,19 @@ void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d_t *mtllib) { unsigned char *end, *chunk, *buff, weights[8]; - unsigned int i, j, k, n, am, len = 0, reclen, offs, numnorm = 0; + unsigned int i, j, k, n, am, len = 0, reclen, offs; char *material; +#ifndef M3D_NONORMALS + unsigned int numnorm = 0; m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb, vn; + M3D_INDEX *ni = NULL, *vi = NULL; +#endif m3d_t *model; - M3D_INDEX mi, *ni = NULL, *vi = NULL; - M3D_FLOAT w, r[16]; + M3D_INDEX mi; + M3D_FLOAT w; +#ifndef M3D_NOANIMATION + M3D_FLOAT r[16]; +#endif m3dtx_t *tx; m3dm_t *m; m3da_t *a; @@ -3000,8 +3010,11 @@ memerr: M3D_LOG("Out of memory"); } } /* calculate normals, normalize skin weights, create bone/vertex cross-references and calculate transform matrices */ +#ifdef M3D_ASCII postprocess: +#endif if(model) { +#ifndef M3D_NONORMALS if(model->numface && model->face) { memset(&vn, 0, sizeof(m3dv_t)); /* if they are missing, calculate triangle normals into a temporary buffer */ @@ -3049,7 +3062,9 @@ postprocess: M3D_FREE(vi); } } +#endif if(model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) { +#ifndef M3D_NOWEIGHTS for(i = 0; i < model->numvertex; i++) { if(model->vertex[i].skinid < M3D_INDEXMAX) { sk = &model->skin[model->vertex[i].skinid]; @@ -3067,6 +3082,7 @@ postprocess: } } } +#endif #ifndef M3D_NOANIMATION for(i = 0; i < model->numbone; i++) { b = &model->bone[i]; @@ -4317,7 +4333,7 @@ memerr: if(face) M3D_FREE(face); /* zlib compress */ if(!(flags & M3D_EXP_NOZLIB)) { z = stbi_zlib_compress((unsigned char *)h, len, (int*)&l, 9); - if(z && l > 0) { len = l; M3D_FREE(h); h = (m3dhdr_t*)z; } + if(z && l > 0 && l < len) { len = l; M3D_FREE(h); h = (m3dhdr_t*)z; } } /* add file header at the begining */ len += 8; @@ -4346,7 +4362,7 @@ memerr: if(face) M3D_FREE(face); #ifdef __cplusplus } - +#ifdef M3D_CPPWRAPPER #include #include #include @@ -4538,6 +4554,7 @@ namespace M3D { #endif /* impl */ } +#endif #endif /* __cplusplus */ From 55c2a3edb9377bf325b2a5606b52f4ac8d094513 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Fri, 1 Nov 2019 12:29:54 +0000 Subject: [PATCH 060/170] FBX orphant embedded textures --- code/FBX/FBXCompileConfig.h | 8 + code/FBX/FBXConverter.cpp | 57 +- code/FBX/FBXConverter.h | 14 +- code/FBX/FBXDocument.h | 34 +- .../FBX/box_orphant_embedded_texture.fbx | 723 ++++++++++++++++++ test/unit/utFBXImporterExporter.cpp | 20 + 6 files changed, 845 insertions(+), 11 deletions(-) create mode 100644 test/models/FBX/box_orphant_embedded_texture.fbx diff --git a/code/FBX/FBXCompileConfig.h b/code/FBX/FBXCompileConfig.h index 3a3841fa5..03536a182 100644 --- a/code/FBX/FBXCompileConfig.h +++ b/code/FBX/FBXCompileConfig.h @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_FBX_COMPILECONFIG_H #include +#include // #if _MSC_VER > 1500 || (defined __GNUC___) @@ -54,16 +55,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # else # define fbx_unordered_map map # define fbx_unordered_multimap multimap +# define fbx_unordered_set set +# define fbx_unordered_multiset multiset #endif #ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP # include +# include # if _MSC_VER > 1600 # define fbx_unordered_map unordered_map # define fbx_unordered_multimap unordered_multimap +# define fbx_unordered_set unordered_set +# define fbx_unordered_multiset unordered_multiset # else # define fbx_unordered_map tr1::unordered_map # define fbx_unordered_multimap tr1::unordered_multimap +# define fbx_unordered_set tr1::unordered_set +# define fbx_unordered_multiset tr1::unordered_multiset # endif #endif diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 20344331c..d8a22d9f7 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -97,6 +97,14 @@ namespace Assimp { // populate the node_anim_chain_bits map, which is needed // to determine which nodes need to be generated. ConvertAnimations(); + // Embedded textures in FBX could be connected to nothing but to itself, + // for instance Texture -> Video connection only but not to the main graph, + // The idea here is to traverse all objects to find these Textures and convert them, + // so later during material conversion it will find converted texture in the textures_converted array. + if (doc.Settings().readTextures) + { + ConvertOrphantEmbeddedTextures(); + } ConvertRootNode(); if (doc.Settings().readAllMaterials) { @@ -1774,7 +1782,7 @@ namespace Assimp { bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found) unsigned int index; - VideoMap::const_iterator it = textures_converted.find(media); + VideoMap::const_iterator it = textures_converted.find(*media); if (it != textures_converted.end()) { index = (*it).second; textureReady = true; @@ -1782,7 +1790,7 @@ namespace Assimp { else { if (media->ContentLength() > 0) { index = ConvertVideo(*media); - textures_converted[media] = index; + textures_converted[*media] = index; textureReady = true; } } @@ -2306,13 +2314,13 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa if (media != nullptr && media->ContentLength() > 0) { unsigned int index; - VideoMap::const_iterator it = textures_converted.find(media); + VideoMap::const_iterator it = textures_converted.find(*media); if (it != textures_converted.end()) { index = (*it).second; } else { index = ConvertVideo(*media); - textures_converted[media] = index; + textures_converted[*media] = index; } // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) @@ -3666,6 +3674,47 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa } } + void FBXConverter::ConvertOrphantEmbeddedTextures() + { + // in C++14 it could be: + // for (auto&& [id, object] : objects) + for (auto&& id_and_object : doc.Objects()) + { + auto&& id = std::get<0>(id_and_object); + auto&& object = std::get<1>(id_and_object); + // If an object doesn't have parent + if (doc.ConnectionsBySource().count(id) == 0) + { + const Texture* realTexture = nullptr; + try + { + const auto& element = object->GetElement(); + const Token& key = element.KeyToken(); + const char* obtype = key.begin(); + const size_t length = static_cast(key.end() - key.begin()); + if (strncmp(obtype, "Texture", length) == 0) + { + const Texture* texture = static_cast(object->Get()); + if (texture->Media() && texture->Media()->ContentLength() > 0) + { + realTexture = texture; + } + } + } + catch (...) + { + // do nothing + } + if (realTexture) + { + const Video* media = realTexture->Media(); + unsigned int index = ConvertVideo(*media); + textures_converted[*media] = index; + } + } + } + } + // ------------------------------------------------------------------------------------------------ void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones) { diff --git a/code/FBX/FBXConverter.h b/code/FBX/FBXConverter.h index 619da92c1..46693bdca 100644 --- a/code/FBX/FBXConverter.h +++ b/code/FBX/FBXConverter.h @@ -427,6 +427,10 @@ private: // copy generated meshes, animations, lights, cameras and textures to the output scene void TransferDataToScene(); + // ------------------------------------------------------------------------------------------------ + // FBX file could have embedded textures not connected to anything + void ConvertOrphantEmbeddedTextures(); + private: // 0: not assigned yet, others: index is value - 1 unsigned int defaultMaterialIndex; @@ -438,21 +442,21 @@ private: std::vector cameras; std::vector textures; - using MaterialMap = std::map; + using MaterialMap = std::fbx_unordered_map; MaterialMap materials_converted; - using VideoMap = std::map; + using VideoMap = std::fbx_unordered_map; VideoMap textures_converted; - using MeshMap = std::map >; + using MeshMap = std::fbx_unordered_map >; MeshMap meshes_converted; // fixed node name -> which trafo chain components have animations? - using NodeAnimBitMap = std::map ; + using NodeAnimBitMap = std::fbx_unordered_map ; NodeAnimBitMap node_anim_chain_bits; // number of nodes with the same name - using NodeNameCache = std::unordered_map; + using NodeNameCache = std::fbx_unordered_map; NodeNameCache mNodeNames; // Deformer name is not the same as a bone name - it does contain the bone name though :) diff --git a/code/FBX/FBXDocument.h b/code/FBX/FBXDocument.h index 18e5c38f1..51c98da49 100644 --- a/code/FBX/FBXDocument.h +++ b/code/FBX/FBXDocument.h @@ -637,6 +637,15 @@ public: return ptr; } + bool operator==(const Video& other) const + { + return ( + type == other.type + && relativeFileName == other.relativeFileName + && fileName == other.fileName + ); + } + private: std::string type; std::string relativeFileName; @@ -1005,10 +1014,10 @@ public: // during their entire lifetime (Document). FBX files have // up to many thousands of objects (most of which we never use), // so the memory overhead for them should be kept at a minimum. -typedef std::map ObjectMap; +typedef std::fbx_unordered_map ObjectMap; typedef std::fbx_unordered_map > PropertyTemplateMap; -typedef std::multimap ConnectionMap; +typedef std::fbx_unordered_multimap ConnectionMap; /** DOM class for global document settings, a single instance per document can * be accessed via Document.Globals(). */ @@ -1177,4 +1186,25 @@ private: } // Namespace FBX } // Namespace Assimp +namespace std +{ + template <> + struct hash + { + std::size_t operator()(const Assimp::FBX::Video& video) const + { + using std::size_t; + using std::hash; + using std::string; + + size_t res = 17; + res = res * 31 + hash()(video.Name()); + res = res * 31 + hash()(video.RelativeFilename()); + res = res * 31 + hash()(video.Type()); + + return res; + } + }; +} + #endif // INCLUDED_AI_FBX_DOCUMENT_H diff --git a/test/models/FBX/box_orphant_embedded_texture.fbx b/test/models/FBX/box_orphant_embedded_texture.fbx new file mode 100644 index 000000000..d874751d0 --- /dev/null +++ b/test/models/FBX/box_orphant_embedded_texture.fbx @@ -0,0 +1,723 @@ +; FBX 7.5.0 project file +; ---------------------------------------------------- + +FBXHeaderExtension: { + FBXHeaderVersion: 1003 + FBXVersion: 7500 + CreationTimeStamp: { + Version: 1000 + Year: 2019 + Month: 3 + Day: 1 + Hour: 12 + Minute: 46 + Second: 3 + Millisecond: 995 + } + Creator: "FBX SDK/FBX Plugins version 2018.1.1" + SceneInfo: "SceneInfo::GlobalInfo", "UserData" { + Type: "UserData" + Version: 100 + MetaData: { + Version: 100 + Title: "" + Subject: "" + Author: "" + Keywords: "" + Revision: "" + Comment: "" + } + Properties70: { + P: "DocumentUrl", "KString", "Url", "", "U:\Some\Absolute\Path\box_embedded_texture.fbx" + P: "SrcDocumentUrl", "KString", "Url", "", "U:\Some\Absolute\Path\box_embedded_texture.fbx" + P: "Original", "Compound", "", "" + P: "Original|ApplicationVendor", "KString", "", "", "Autodesk" + P: "Original|ApplicationName", "KString", "", "", "Maya" + P: "Original|ApplicationVersion", "KString", "", "", "201800" + P: "Original|DateTime_GMT", "DateTime", "", "", "01/03/2019 12:46:03.994" + P: "Original|FileName", "KString", "", "", "U:\Some\Absolute\Path\box_embedded_texture.fbx" + P: "LastSaved", "Compound", "", "" + P: "LastSaved|ApplicationVendor", "KString", "", "", "Autodesk" + P: "LastSaved|ApplicationName", "KString", "", "", "Maya" + P: "LastSaved|ApplicationVersion", "KString", "", "", "201800" + P: "LastSaved|DateTime_GMT", "DateTime", "", "", "01/03/2019 12:46:03.994" + P: "Original|ApplicationActiveProject", "KString", "", "", "U:\Some\Absolute\Path" + } + } +} +GlobalSettings: { + Version: 1000 + Properties70: { + P: "UpAxis", "int", "Integer", "",1 + P: "UpAxisSign", "int", "Integer", "",1 + P: "FrontAxis", "int", "Integer", "",2 + P: "FrontAxisSign", "int", "Integer", "",1 + P: "CoordAxis", "int", "Integer", "",0 + P: "CoordAxisSign", "int", "Integer", "",1 + P: "OriginalUpAxis", "int", "Integer", "",1 + P: "OriginalUpAxisSign", "int", "Integer", "",1 + P: "UnitScaleFactor", "double", "Number", "",100 + P: "OriginalUnitScaleFactor", "double", "Number", "",1 + P: "AmbientColor", "ColorRGB", "Color", "",0,0,0 + P: "DefaultCamera", "KString", "", "", "Producer Perspective" + P: "TimeMode", "enum", "", "",6 + P: "TimeProtocol", "enum", "", "",2 + P: "SnapOnFrameMode", "enum", "", "",0 + P: "TimeSpanStart", "KTime", "Time", "",0 + P: "TimeSpanStop", "KTime", "Time", "",153953860000 + P: "CustomFrameRate", "double", "Number", "",-1 + P: "TimeMarker", "Compound", "", "" + P: "CurrentTimeMarker", "int", "Integer", "",-1 + } +} + +; Documents Description +;------------------------------------------------------------------ + +Documents: { + Count: 1 + Document: 2957686739424, "", "Scene" { + Properties70: { + P: "SourceObject", "object", "", "" + P: "ActiveAnimStackName", "KString", "", "", "Take 001" + } + RootNode: 0 + } +} + +; Document References +;------------------------------------------------------------------ + +References: { +} + +; Object definitions +;------------------------------------------------------------------ + +Definitions: { + Version: 100 + Count: 17 + ObjectType: "GlobalSettings" { + Count: 1 + } + ObjectType: "AnimationStack" { + Count: 1 + PropertyTemplate: "FbxAnimStack" { + Properties70: { + P: "Description", "KString", "", "", "" + P: "LocalStart", "KTime", "Time", "",0 + P: "LocalStop", "KTime", "Time", "",0 + P: "ReferenceStart", "KTime", "Time", "",0 + P: "ReferenceStop", "KTime", "Time", "",0 + } + } + } + ObjectType: "AnimationLayer" { + Count: 1 + PropertyTemplate: "FbxAnimLayer" { + Properties70: { + P: "Weight", "Number", "", "A",100 + P: "Mute", "bool", "", "",0 + P: "Solo", "bool", "", "",0 + P: "Lock", "bool", "", "",0 + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BlendMode", "enum", "", "",0 + P: "RotationAccumulationMode", "enum", "", "",0 + P: "ScaleAccumulationMode", "enum", "", "",0 + P: "BlendModeBypass", "ULongLong", "", "",0 + } + } + } + ObjectType: "Geometry" { + Count: 1 + PropertyTemplate: "FbxMesh" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BBoxMin", "Vector3D", "Vector", "",0,0,0 + P: "BBoxMax", "Vector3D", "Vector", "",0,0,0 + P: "Primary Visibility", "bool", "", "",1 + P: "Casts Shadows", "bool", "", "",1 + P: "Receive Shadows", "bool", "", "",1 + } + } + } + ObjectType: "Material" { + Count: 1 + PropertyTemplate: "FbxSurfacePhong" { + Properties70: { + P: "ShadingModel", "KString", "", "", "Phong" + P: "MultiLayer", "bool", "", "",0 + P: "EmissiveColor", "Color", "", "A",0,0,0 + P: "EmissiveFactor", "Number", "", "A",1 + P: "AmbientColor", "Color", "", "A",0.2,0.2,0.2 + P: "AmbientFactor", "Number", "", "A",1 + P: "DiffuseColor", "Color", "", "A",0.8,0.8,0.8 + P: "DiffuseFactor", "Number", "", "A",1 + P: "Bump", "Vector3D", "Vector", "",0,0,0 + P: "NormalMap", "Vector3D", "Vector", "",0,0,0 + P: "BumpFactor", "double", "Number", "",1 + P: "TransparentColor", "Color", "", "A",0,0,0 + P: "TransparencyFactor", "Number", "", "A",0 + P: "DisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "DisplacementFactor", "double", "Number", "",1 + P: "VectorDisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "VectorDisplacementFactor", "double", "Number", "",1 + P: "SpecularColor", "Color", "", "A",0.2,0.2,0.2 + P: "SpecularFactor", "Number", "", "A",1 + P: "ShininessExponent", "Number", "", "A",20 + P: "ReflectionColor", "Color", "", "A",0,0,0 + P: "ReflectionFactor", "Number", "", "A",1 + } + } + } + ObjectType: "Texture" { + Count: 1 + PropertyTemplate: "FbxFileTexture" { + Properties70: { + P: "TextureTypeUse", "enum", "", "",0 + P: "Texture alpha", "Number", "", "A",1 + P: "CurrentMappingType", "enum", "", "",0 + P: "WrapModeU", "enum", "", "",0 + P: "WrapModeV", "enum", "", "",0 + P: "UVSwap", "bool", "", "",0 + P: "PremultiplyAlpha", "bool", "", "",1 + P: "Translation", "Vector", "", "A",0,0,0 + P: "Rotation", "Vector", "", "A",0,0,0 + P: "Scaling", "Vector", "", "A",1,1,1 + P: "TextureRotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "TextureScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "CurrentTextureBlendMode", "enum", "", "",1 + P: "UVSet", "KString", "", "", "default" + P: "UseMaterial", "bool", "", "",0 + P: "UseMipMap", "bool", "", "",0 + } + } + } + ObjectType: "Model" { + Count: 1 + PropertyTemplate: "FbxNode" { + Properties70: { + P: "QuaternionInterpolate", "enum", "", "",0 + P: "RotationOffset", "Vector3D", "Vector", "",0,0,0 + P: "RotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "ScalingOffset", "Vector3D", "Vector", "",0,0,0 + P: "ScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "TranslationActive", "bool", "", "",0 + P: "TranslationMin", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMax", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMinX", "bool", "", "",0 + P: "TranslationMinY", "bool", "", "",0 + P: "TranslationMinZ", "bool", "", "",0 + P: "TranslationMaxX", "bool", "", "",0 + P: "TranslationMaxY", "bool", "", "",0 + P: "TranslationMaxZ", "bool", "", "",0 + P: "RotationOrder", "enum", "", "",0 + P: "RotationSpaceForLimitOnly", "bool", "", "",0 + P: "RotationStiffnessX", "double", "Number", "",0 + P: "RotationStiffnessY", "double", "Number", "",0 + P: "RotationStiffnessZ", "double", "Number", "",0 + P: "AxisLen", "double", "Number", "",10 + P: "PreRotation", "Vector3D", "Vector", "",0,0,0 + P: "PostRotation", "Vector3D", "Vector", "",0,0,0 + P: "RotationActive", "bool", "", "",0 + P: "RotationMin", "Vector3D", "Vector", "",0,0,0 + P: "RotationMax", "Vector3D", "Vector", "",0,0,0 + P: "RotationMinX", "bool", "", "",0 + P: "RotationMinY", "bool", "", "",0 + P: "RotationMinZ", "bool", "", "",0 + P: "RotationMaxX", "bool", "", "",0 + P: "RotationMaxY", "bool", "", "",0 + P: "RotationMaxZ", "bool", "", "",0 + P: "InheritType", "enum", "", "",0 + P: "ScalingActive", "bool", "", "",0 + P: "ScalingMin", "Vector3D", "Vector", "",0,0,0 + P: "ScalingMax", "Vector3D", "Vector", "",1,1,1 + P: "ScalingMinX", "bool", "", "",0 + P: "ScalingMinY", "bool", "", "",0 + P: "ScalingMinZ", "bool", "", "",0 + P: "ScalingMaxX", "bool", "", "",0 + P: "ScalingMaxY", "bool", "", "",0 + P: "ScalingMaxZ", "bool", "", "",0 + P: "GeometricTranslation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricRotation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricScaling", "Vector3D", "Vector", "",1,1,1 + P: "MinDampRangeX", "double", "Number", "",0 + P: "MinDampRangeY", "double", "Number", "",0 + P: "MinDampRangeZ", "double", "Number", "",0 + P: "MaxDampRangeX", "double", "Number", "",0 + P: "MaxDampRangeY", "double", "Number", "",0 + P: "MaxDampRangeZ", "double", "Number", "",0 + P: "MinDampStrengthX", "double", "Number", "",0 + P: "MinDampStrengthY", "double", "Number", "",0 + P: "MinDampStrengthZ", "double", "Number", "",0 + P: "MaxDampStrengthX", "double", "Number", "",0 + P: "MaxDampStrengthY", "double", "Number", "",0 + P: "MaxDampStrengthZ", "double", "Number", "",0 + P: "PreferedAngleX", "double", "Number", "",0 + P: "PreferedAngleY", "double", "Number", "",0 + P: "PreferedAngleZ", "double", "Number", "",0 + P: "LookAtProperty", "object", "", "" + P: "UpVectorProperty", "object", "", "" + P: "Show", "bool", "", "",1 + P: "NegativePercentShapeSupport", "bool", "", "",1 + P: "DefaultAttributeIndex", "int", "Integer", "",-1 + P: "Freeze", "bool", "", "",0 + P: "LODBox", "bool", "", "",0 + P: "Lcl Translation", "Lcl Translation", "", "A",0,0,0 + P: "Lcl Rotation", "Lcl Rotation", "", "A",0,0,0 + P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1 + P: "Visibility", "Visibility", "", "A",1 + P: "Visibility Inheritance", "Visibility Inheritance", "", "",1 + } + } + } + ObjectType: "AnimationCurveNode" { + Count: 8 + PropertyTemplate: "FbxAnimCurveNode" { + Properties70: { + P: "d", "Compound", "", "" + } + } + } + ObjectType: "CollectionExclusive" { + Count: 1 + PropertyTemplate: "FbxDisplayLayer" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "Show", "bool", "", "",1 + P: "Freeze", "bool", "", "",0 + P: "LODBox", "bool", "", "",0 + } + } + } + ObjectType: "Video" { + Count: 1 + PropertyTemplate: "FbxVideo" { + Properties70: { + P: "Path", "KString", "XRefUrl", "", "" + P: "RelPath", "KString", "XRefUrl", "", "" + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "ClipIn", "KTime", "Time", "",0 + P: "ClipOut", "KTime", "Time", "",0 + P: "Offset", "KTime", "Time", "",0 + P: "PlaySpeed", "double", "Number", "",0 + P: "FreeRunning", "bool", "", "",0 + P: "Loop", "bool", "", "",0 + P: "Mute", "bool", "", "",0 + P: "AccessMode", "enum", "", "",0 + P: "ImageSequence", "bool", "", "",0 + P: "ImageSequenceOffset", "int", "Integer", "",0 + P: "FrameRate", "double", "Number", "",0 + P: "LastFrame", "int", "Integer", "",0 + P: "Width", "int", "Integer", "",0 + P: "Height", "int", "Integer", "",0 + P: "StartFrame", "int", "Integer", "",0 + P: "StopFrame", "int", "Integer", "",0 + P: "InterlaceMode", "enum", "", "",0 + } + } + } +} + +; Object properties +;------------------------------------------------------------------ + +Objects: { + Geometry: 2957764348544, "Geometry::", "Mesh" { + Vertices: *24 { + a: -0.5,-0.5,-0.5,0.5,-0.50000011920929,-0.5,-0.5,0.50000011920929,-0.5,0.5,0.50000011920929,-0.5,-0.5,-0.500000059604645,0.5,0.5,-0.500000059604645,0.5,-0.5,0.500000059604645,0.5,0.5,0.500000059604645,0.5 + } + PolygonVertexIndex: *24 { + a: 0,2,3,-2,4,5,7,-7,0,1,5,-5,1,3,7,-6,3,2,6,-8,2,0,4,-7 + } + Edges: *12 { + a: 0,1,2,3,4,5,6,7,9,11,13,17 + } + GeometryVersion: 124 + LayerElementNormal: 0 { + Version: 102 + Name: "" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Normals: *72 { + a: 0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,1,0,0,1,0,0,1,0,0,1,-5.96046447753906e-08,-1,0,-5.96046447753906e-08,-1,0,-5.96046447753906e-08,-1,0,-5.96046447753906e-08,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,5.96046447753906e-08,0,1,5.96046447753906e-08,0,1,5.96046447753906e-08,0,1,5.96046447753906e-08,-1,0,0,-1,0,0,-1,0,0,-1,0,0 + } + NormalsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + } + LayerElementBinormal: 0 { + Version: 102 + Name: "UVChannel_1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Binormals: *72 { + a: 1.19209289550781e-07,1,0,5.96046447753906e-08,1,0,0,1,0,5.96046447753906e-08,1,0,0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,0,1,0,0,1,0,0,1,0,0,1,-0,0,1,-0,0,1,-0,0,1,-0,0,1,-0,-5.96046447753906e-08,1,-0,-5.96046447753906e-08,1,-0,-5.96046447753906e-08,1,-0,-5.96046447753906e-08,1,0,0,1,0,0,1,0,0,1,0,0,1 + } + BinormalsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + + } + LayerElementBinormal: 1 { + Version: 102 + Name: "UVChannel_3" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Binormals: *72 { + a: -1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-0,0,-1,-0,0,-1,0,-0,-1,-0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,5.96046447753906e-08,-1,0,5.96046447753906e-08,-1,0,5.96046447753906e-08,-1,0,5.96046447753906e-08,-1,-0,0,-1,-0,0,-1,-0,0,-1,-0,0,-1 + } + BinormalsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + + } + LayerElementTangent: 0 { + Version: 102 + Name: "UVChannel_1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Tangents: *72 { + a: -1,1.19209289550781e-07,0,-1,5.96046447753906e-08,0,-1,-0,0,-1,5.96046447753906e-08,0,1,-0,-0,1,-0,0,1,-0,0,1,-0,0,1,-5.96046447753906e-08,-0,1,-5.96046447753906e-08,0,1,-5.96046447753906e-08,0,1,-5.96046447753906e-08,0,-0,1,-0,0,1,-0,0,1,-0,0,1,-0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,-0,0,-1,-0,0,-1,0,0,-1,0,0,-1,0 + } + TangentsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + } + LayerElementTangent: 1 { + Version: 102 + Name: "UVChannel_3" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Tangents: *72 { + a: -0,-1,0,-0,-1,0,-0,-1,0,-0,-1,0,0,1,0,0,1,0,-0,1,-0,0,1,0,-1,5.96046447753906e-08,0,-1,5.96046447753906e-08,0,-1,5.96046447753906e-08,-0,-1,5.96046447753906e-08,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,-0,-0,1,-0,-0,1,-0,-0,1,-0,-0,0,1,-0,0,1,-0,0,1,-0,0,1,-0 + } + TangentsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + } + LayerElementUV: 0 { + Version: 101 + Name: "UVChannel_1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "IndexToDirect" + UV: *48 { + a: 1,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1 + } + UVIndex: *24 { + a: 0,2,3,1,4,5,7,6,8,9,11,10,12,13,15,14,16,17,19,18,20,21,23,22 + } + } + LayerElementUV: 1 { + Version: 101 + Name: "UVChannel_3" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "IndexToDirect" + UV: *48 { + a: 0.28125,0.28125,0,0.28125,0,0,0.28125,0,0.34375,1,0.34375,0.71875,0.625,0.71875,0.625,1,0.28125,0.65625,0,0.65625,0,0.375,0.28125,0.375,0.625,0.28125,0.34375,0.28125,0.34375,0,0.625,0,0.28125,1,0,1,0,0.71875,0.28125,0.71875,0.625,0.65625,0.34375,0.65625,0.34375,0.375,0.625,0.375 + } + UVIndex: *24 { + a: 0,1,2,3,4,5,6,7,20,21,22,23,8,9,10,11,16,17,18,19,12,13,14,15 + } + } + LayerElementSmoothing: 0 { + Version: 102 + Name: "" + MappingInformationType: "ByEdge" + ReferenceInformationType: "Direct" + Smoothing: *12 { + a: 0,0,0,0,0,0,0,0,0,0,0,0 + } + } + LayerElementMaterial: 0 { + Version: 101 + Name: "" + MappingInformationType: "AllSame" + ReferenceInformationType: "IndexToDirect" + Materials: *1 { + a: 0 + } + } + Layer: 0 { + Version: 100 + LayerElement: { + Type: "LayerElementNormal" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementBinormal" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementTangent" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementMaterial" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementSmoothing" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementUV" + TypedIndex: 0 + } + } + Layer: 1 { + Version: 100 + LayerElement: { + Type: "LayerElementBinormal" + TypedIndex: 1 + } + LayerElement: { + Type: "LayerElementTangent" + TypedIndex: 1 + } + LayerElement: { + Type: "LayerElementUV" + TypedIndex: 1 + } + } + } + Model: 2957618625584, "Model::Box", "Mesh" { + Version: 232 + Properties70: { + P: "RotationActive", "bool", "", "",1 + P: "InheritType", "enum", "", "",1 + P: "ScalingMax", "Vector3D", "Vector", "",0,0,0 + P: "DefaultAttributeIndex", "int", "Integer", "",0 + P: "Lcl Translation", "Lcl Translation", "", "A",0,0.5,2.18556946492754e-06 + P: "Lcl Rotation", "Lcl Rotation", "", "A",-90,0,0 + P: "currentUVSet", "KString", "", "U", "UVChannel_1" + P: "mr displacement use global settings", "Bool", "", "A+U",1 + P: "mr displacement view dependent", "Bool", "", "A+U",1 + P: "mr displacement method", "Integer", "", "A+U",6,6,6 + P: "mr displacement smoothing on", "Bool", "", "A+U",1 + P: "mr displacement edge length", "Number", "", "A+U",2,2,2 + P: "mr displacement max displace", "Number", "", "A+U",20,20,20 + P: "mr displacement parametric subdivision level", "Integer", "", "A+U",5,5,5 + P: "MaxHandle", "Integer", "", "A+UH",1,0,0 + } + Shading: T + Culling: "CullingOff" + } + Material: 2957776713840, "Material::Default", "" { + Version: 102 + ShadingModel: "phong" + MultiLayer: 0 + Properties70: { + P: "AmbientColor", "Color", "", "A",0,0,0 + P: "DiffuseColor", "Color", "", "A",1,1,1 + P: "TransparencyFactor", "Number", "", "A",1 + P: "SpecularColor", "Color", "", "A",0,0,0 + P: "ShininessExponent", "Number", "", "A",2 + P: "Emissive", "Vector3D", "Vector", "",0,0,0 + P: "Ambient", "Vector3D", "Vector", "",0,0,0 + P: "Diffuse", "Vector3D", "Vector", "",1,1,1 + P: "Specular", "Vector3D", "Vector", "",0,0,0 + P: "Shininess", "double", "Number", "",2 + P: "Opacity", "double", "Number", "",1 + P: "Reflectivity", "double", "Number", "",0 + } + } + Video: 2957776707120, "Video::Map #2", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "U:/Some/Absolute/Primitives/GridGrey.tga" + P: "RelPath", "KString", "XRefUrl", "", "..\Primitives\GridGrey.tga" + } + UseMipMap: 0 + Filename: "U:/Some/Absolute/Primitives/GridGrey.tga" + RelativeFilename: "..\Primitives\GridGrey.tga" + } + Video: 2957776707121, "Video::Map #2", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "U:/Some/Absolute/Primitives/GridGrey.tga" + P: "RelPath", "KString", "XRefUrl", "", "..\Primitives\GridGrey.tga" + } + UseMipMap: 0 + Filename: "U:/Some/Absolute/Primitives/GridGrey.tga" + RelativeFilename: "..\Primitives\GridGrey.tga" + Content: , + "AAAKAAAAAAAAAAAAAAEAARgAh+rq6v+Pj4/wj4+Phurq6ofq6uq2dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+3dHR0hurq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6gCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+Pj/+Pj4//j4+P/4+Pj/+Pj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj48Aj4+PvXR0dIGPj4+9dHR0gY+Pj710dHSBj4+PvXR0dACPj4//j4+P/4+Pj/+Pj4//j4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+PAI+Pj710dHSBj4+PvXR0dIGPj4+9dHR0gY+Pj710dHQAj4+P/4+Pj/+Pj4//j4+P/4+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+PjwCPj4+9dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+9dHR0AI+Pj4Hq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6oHq6uq8dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+8dHR0gerq6ofq6uq2dHR0gY+Pj710dHSBj4+PvXR0dIGPj4+3dHR0hurq6ofq6ur/j4+P8I+Pj4bq6uo=" + } + Texture: 2957776714320, "Texture::Map #2", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Map #2" + Properties70: { + P: "CurrentTextureBlendMode", "enum", "", "",0 + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Map #2" + FileName: "U:/Some/Absolute/Primitives/GridGrey.tga" + RelativeFilename: "..\Primitives\GridGrey.tga" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2957776714321, "Texture::Map #2", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Map #2" + Properties70: { + P: "CurrentTextureBlendMode", "enum", "", "",0 + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Map #2" + FileName: "U:/Some/Absolute/Primitives/GridGrey.tga" + RelativeFilename: "..\Primitives\GridGrey.tga" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + AnimationStack: 2957627494560, "AnimStack::Take 001", "" { + Properties70: { + P: "LocalStop", "KTime", "Time", "",153953860000 + P: "ReferenceStop", "KTime", "Time", "",153953860000 + } + } + AnimationCurveNode: 2957627500176, "AnimCurveNode::mr displacement use global settings", "" { + Properties70: { + P: "d|mr displacement use global settings", "Bool", "", "A",1 + } + } + AnimationCurveNode: 2957627490192, "AnimCurveNode::mr displacement view dependent", "" { + Properties70: { + P: "d|mr displacement view dependent", "Bool", "", "A",1 + } + } + AnimationCurveNode: 2957627487904, "AnimCurveNode::mr displacement method", "" { + Properties70: { + P: "d|mr displacement method", "Integer", "", "A",6 + } + } + AnimationCurveNode: 2957627492688, "AnimCurveNode::mr displacement smoothing on", "" { + Properties70: { + P: "d|mr displacement smoothing on", "Bool", "", "A",1 + } + } + AnimationCurveNode: 2957627492064, "AnimCurveNode::mr displacement edge length", "" { + Properties70: { + P: "d|mr displacement edge length", "Number", "", "A",2 + } + } + AnimationCurveNode: 2957627492896, "AnimCurveNode::mr displacement max displace", "" { + Properties70: { + P: "d|mr displacement max displace", "Number", "", "A",20 + } + } + AnimationCurveNode: 2957627492272, "AnimCurveNode::mr displacement parametric subdivision level", "" { + Properties70: { + P: "d|mr displacement parametric subdivision level", "Integer", "", "A",5 + } + } + AnimationCurveNode: 2957627488320, "AnimCurveNode::MaxHandle", "" { + Properties70: { + P: "d|MaxHandle", "Integer", "", "A",1 + } + } + AnimationLayer: 2957566198176, "AnimLayer::BaseLayer", "" { + } + CollectionExclusive: 2959111896352, "DisplayLayer::Box", "DisplayLayer" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.607999980449677,0,0.157000005245209 + } + } +} + +; Object connections +;------------------------------------------------------------------ + +Connections: { + + ;Model::Box, Model::RootNode + C: "OO",2957618625584,0 + + ;AnimLayer::BaseLayer, AnimStack::Take 001 + C: "OO",2957566198176,2957627494560 + + ;AnimCurveNode::mr displacement use global settings, AnimLayer::BaseLayer + C: "OO",2957627500176,2957566198176 + + ;AnimCurveNode::mr displacement view dependent, AnimLayer::BaseLayer + C: "OO",2957627490192,2957566198176 + + ;AnimCurveNode::mr displacement method, AnimLayer::BaseLayer + C: "OO",2957627487904,2957566198176 + + ;AnimCurveNode::mr displacement smoothing on, AnimLayer::BaseLayer + C: "OO",2957627492688,2957566198176 + + ;AnimCurveNode::mr displacement edge length, AnimLayer::BaseLayer + C: "OO",2957627492064,2957566198176 + + ;AnimCurveNode::mr displacement max displace, AnimLayer::BaseLayer + C: "OO",2957627492896,2957566198176 + + ;AnimCurveNode::mr displacement parametric subdivision level, AnimLayer::BaseLayer + C: "OO",2957627492272,2957566198176 + + ;AnimCurveNode::MaxHandle, AnimLayer::BaseLayer + C: "OO",2957627488320,2957566198176 + + ;Texture::Map #2, Material::Default + C: "OP",2957776714320,2957776713840, "DiffuseColor" + + ;Video::Map #2, Texture::Map #2 + C: "OO",2957776707120,2957776714320 + + ;Video::Map #2, Texture::Map #2 + C: "OO",2957776707121,2957776714321 + + ;Geometry::, Model::Box + C: "OO",2957764348544,2957618625584 + + ;Material::Default, Model::Box + C: "OO",2957776713840,2957618625584 + + ;AnimCurveNode::mr displacement use global settings, Model::Box + C: "OP",2957627500176,2957618625584, "mr displacement use global settings" + + ;AnimCurveNode::mr displacement view dependent, Model::Box + C: "OP",2957627490192,2957618625584, "mr displacement view dependent" + + ;AnimCurveNode::mr displacement method, Model::Box + C: "OP",2957627487904,2957618625584, "mr displacement method" + + ;AnimCurveNode::mr displacement smoothing on, Model::Box + C: "OP",2957627492688,2957618625584, "mr displacement smoothing on" + + ;AnimCurveNode::mr displacement edge length, Model::Box + C: "OP",2957627492064,2957618625584, "mr displacement edge length" + + ;AnimCurveNode::mr displacement max displace, Model::Box + C: "OP",2957627492896,2957618625584, "mr displacement max displace" + + ;AnimCurveNode::mr displacement parametric subdivision level, Model::Box + C: "OP",2957627492272,2957618625584, "mr displacement parametric subdivision level" + + ;AnimCurveNode::MaxHandle, Model::Box + C: "OP",2957627488320,2957618625584, "MaxHandle" + + ;Model::Box, DisplayLayer::Box + C: "OO",2957618625584,2959111896352 +} +;Takes section +;---------------------------------------------------- + +Takes: { + Current: "Take 001" + Take: "Take 001" { + FileName: "Take_001.tak" + LocalTime: 0,153953860000 + ReferenceTime: 0,153953860000 + } +} diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index e73733a0d..43dc40e88 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -263,3 +263,23 @@ TEST_F(utFBXImporterExporter, fbxTokenizeTestTest) { //const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/transparentTest2.fbx", aiProcess_ValidateDataStructure); //EXPECT_NE(nullptr, scene); } + +TEST_F(utFBXImporterExporter, importOrphantEmbeddedTextureTest) { + // see https://github.com/assimp/assimp/issues/1957 + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/box_orphant_embedded_texture.fbx", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(1u, scene->mNumMaterials); + aiMaterial *mat = scene->mMaterials[0]; + ASSERT_NE(nullptr, mat); + + aiString path; + aiTextureMapMode modes[2]; + ASSERT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes)); + ASSERT_STREQ(path.C_Str(), "..\\Primitives\\GridGrey.tga"); + + ASSERT_EQ(1u, scene->mNumTextures); + ASSERT_TRUE(scene->mTextures[0]->pcData); + ASSERT_EQ(9026u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression used for a texture."; +} From 536fea1c8d091f8763b13e807216323f1fdd632a Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Fri, 1 Nov 2019 14:50:30 +0000 Subject: [PATCH 061/170] operator less for old compilers --- code/FBX/FBXDocument.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/FBX/FBXDocument.h b/code/FBX/FBXDocument.h index 51c98da49..a60d7d9ef 100644 --- a/code/FBX/FBXDocument.h +++ b/code/FBX/FBXDocument.h @@ -646,6 +646,11 @@ public: ); } + bool operator<(const Video& other) const + { + return std::tie(type, relativeFileName, fileName) < std::tie(other.type, other.relativeFileName, other.fileName); + } + private: std::string type; std::string relativeFileName; From 82f926971b5220e6662f8b3726c8736944854e99 Mon Sep 17 00:00:00 2001 From: tanolino Date: Fri, 1 Nov 2019 17:01:52 +0100 Subject: [PATCH 062/170] Update CXMLReaderImpl.h Issues with German locale number converter expecting German numbers. In Germany we have numbers like #,## instead of #.## . Thus a unit conversion in COLLADA of 0.01 (centimeter) turned out to be 0.00. --- contrib/irrXML/CXMLReaderImpl.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contrib/irrXML/CXMLReaderImpl.h b/contrib/irrXML/CXMLReaderImpl.h index 6f3bec5fa..a125312a1 100644 --- a/contrib/irrXML/CXMLReaderImpl.h +++ b/contrib/irrXML/CXMLReaderImpl.h @@ -15,6 +15,9 @@ #include //using namespace Assimp; +// For locale independent number conversion +#include +#include #ifdef _DEBUG #define IRR_DEBUGPRINT(x) printf((x)); @@ -178,8 +181,11 @@ public: return 0; core::stringc c = attrvalue; - return static_cast(atof(c.c_str())); - //return fast_atof(c.c_str()); + std::istringstream sstr(c.c_str()); + sstr.imbue(std::locale("C")); // Locale free number convert + float fNum; + sstr >> fNum; + return fNum; } From 7d9e9aadbbceb8be0aaf50c7fcd6990715f32242 Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 1 Nov 2019 17:21:24 +0100 Subject: [PATCH 063/170] Asked modifications and unit test --- code/M3D/M3DExporter.cpp | 17 +++--- code/M3D/M3DMaterials.h | 4 +- code/M3D/m3d.h | 22 ++++--- test/CMakeLists.txt | 1 + test/models/M3D/README.md | 14 ----- test/models/M3D/aliveai_character.m3d | Bin 2532 -> 0 bytes test/models/M3D/mobs_dwarves_character.m3d | Bin 11255 -> 0 bytes test/unit/utM3DImportExport.cpp | 68 +++++++++++++++++++++ 8 files changed, 93 insertions(+), 33 deletions(-) delete mode 100644 test/models/M3D/README.md delete mode 100644 test/models/M3D/aliveai_character.m3d delete mode 100644 test/models/M3D/mobs_dwarves_character.m3d create mode 100644 test/unit/utM3DImportExport.cpp diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index 9ba48b125..c22943396 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -173,12 +173,9 @@ void M3DExporter::doExport ( // recursive node walker void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) { - unsigned int i, j, k, l, n, idx; aiMatrix4x4 nm = m * pNode->mTransformation; - m3dv_t vertex; - m3dti_t ti; - for(i = 0; i < pNode->mNumMeshes; i++) { + for(unsigned int i = 0; i < pNode->mNumMeshes; i++) { const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]]; unsigned int mi = (M3D_INDEX)-1U; if(mScene->mMaterials) { @@ -186,7 +183,8 @@ void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) mi = addMaterial(mScene->mMaterials[mesh->mMaterialIndex]); } // iterate through the mesh faces - for(j = 0; j < mesh->mNumFaces; j++) { + for(unsigned int j = 0; j < mesh->mNumFaces; j++) { + unsigned int n; const aiFace* face = &(mesh->mFaces[j]); // only triangle meshes supported for now if(face->mNumIndices != 3) { @@ -204,9 +202,12 @@ void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] = m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = -1U; m3d->face[n].materialid = mi; - for(k = 0; k < face->mNumIndices; k++) { + for(unsigned int k = 0; k < face->mNumIndices; k++) { // get the vertex's index - l = face->mIndices[k]; + unsigned int l = face->mIndices[k]; + unsigned int idx; + m3dv_t vertex; + m3dti_t ti; // multiply the position vector by the transformation matrix aiVector3D v = mesh->mVertices[l]; v *= nm; @@ -245,7 +246,7 @@ void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) } } // repeat for the children nodes - for (i = 0; i < pNode->mNumChildren; i++) { + for (unsigned int i = 0; i < pNode->mNumChildren; i++) { NodeWalk(pNode->mChildren[i], nm); } } diff --git a/code/M3D/M3DMaterials.h b/code/M3D/M3DMaterials.h index b3c91ab7a..fa02cf42b 100644 --- a/code/M3D/M3DMaterials.h +++ b/code/M3D/M3DMaterials.h @@ -60,7 +60,7 @@ typedef struct { } aiMatProp; /* --- Scalar Properties --- !!!!! must match m3d_propertytypes !!!!! */ -static aiMatProp aiProps[] = { +static const aiMatProp aiProps[] = { { AI_MATKEY_COLOR_DIFFUSE }, /* m3dp_Kd */ { AI_MATKEY_COLOR_AMBIENT }, /* m3dp_Ka */ { AI_MATKEY_COLOR_SPECULAR }, /* m3dp_Ks */ @@ -82,7 +82,7 @@ static aiMatProp aiProps[] = { }; /* --- Texture Map Properties --- !!!!! must match m3d_propertytypes !!!!! */ -static aiMatProp aiTxProps[] = { +static const aiMatProp aiTxProps[] = { { AI_MATKEY_TEXTURE_DIFFUSE(0) }, /* m3dp_map_Kd */ { AI_MATKEY_TEXTURE_AMBIENT(0) }, /* m3dp_map_Ka */ { AI_MATKEY_TEXTURE_SPECULAR(0) }, /* m3dp_map_Ks */ diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 7218f83e7..b28dd5d2a 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -2144,6 +2144,10 @@ void _m3d_inv(M3D_FLOAT *m) memcpy(m, &r, sizeof(r)); } /* compose a coloumn major 4 x 4 matrix from vec3 position and vec4 orientation/rotation quaternion */ +#ifndef M3D_EPSILON +/* carefully choosen for IEEE 754 don't change */ +#define M3D_EPSILON ((M3D_FLOAT)1e-7) +#endif void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) { if(q->x == (M3D_FLOAT)0.0 && q->y == (M3D_FLOAT)0.0 && q->z >=(M3D_FLOAT) 0.7071065 && q->z <= (M3D_FLOAT)0.7071075 && @@ -2151,15 +2155,15 @@ void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) r[ 1] = r[ 2] = r[ 4] = r[ 6] = r[ 8] = r[ 9] = (M3D_FLOAT)0.0; r[ 0] = r[ 5] = r[10] = (M3D_FLOAT)-1.0; } else { - r[ 0] = 1 - 2 * (q->y * q->y + q->z * q->z); if(r[ 0]>(M3D_FLOAT)-1e-7 && r[ 0]<(M3D_FLOAT)1e-7) r[ 0]=(M3D_FLOAT)0.0; - r[ 1] = 2 * (q->x * q->y - q->z * q->w); if(r[ 1]>(M3D_FLOAT)-1e-7 && r[ 1]<(M3D_FLOAT)1e-7) r[ 1]=(M3D_FLOAT)0.0; - r[ 2] = 2 * (q->x * q->z + q->y * q->w); if(r[ 2]>(M3D_FLOAT)-1e-7 && r[ 2]<(M3D_FLOAT)1e-7) r[ 2]=(M3D_FLOAT)0.0; - r[ 4] = 2 * (q->x * q->y + q->z * q->w); if(r[ 4]>(M3D_FLOAT)-1e-7 && r[ 4]<(M3D_FLOAT)1e-7) r[ 4]=(M3D_FLOAT)0.0; - r[ 5] = 1 - 2 * (q->x * q->x + q->z * q->z); if(r[ 5]>(M3D_FLOAT)-1e-7 && r[ 5]<(M3D_FLOAT)1e-7) r[ 5]=(M3D_FLOAT)0.0; - r[ 6] = 2 * (q->y * q->z - q->x * q->w); if(r[ 6]>(M3D_FLOAT)-1e-7 && r[ 6]<(M3D_FLOAT)1e-7) r[ 6]=(M3D_FLOAT)0.0; - r[ 8] = 2 * (q->x * q->z - q->y * q->w); if(r[ 8]>(M3D_FLOAT)-1e-7 && r[ 8]<(M3D_FLOAT)1e-7) r[ 8]=(M3D_FLOAT)0.0; - r[ 9] = 2 * (q->y * q->z + q->x * q->w); if(r[ 9]>(M3D_FLOAT)-1e-7 && r[ 9]<(M3D_FLOAT)1e-7) r[ 9]=(M3D_FLOAT)0.0; - r[10] = 1 - 2 * (q->x * q->x + q->y * q->y); if(r[10]>(M3D_FLOAT)-1e-7 && r[10]<(M3D_FLOAT)1e-7) r[10]=(M3D_FLOAT)0.0; + r[ 0] = 1 - 2 * (q->y * q->y + q->z * q->z); if(r[ 0]>-M3D_EPSILON && r[ 0]x * q->y - q->z * q->w); if(r[ 1]>-M3D_EPSILON && r[ 1]x * q->z + q->y * q->w); if(r[ 2]>-M3D_EPSILON && r[ 2]x * q->y + q->z * q->w); if(r[ 4]>-M3D_EPSILON && r[ 4]x * q->x + q->z * q->z); if(r[ 5]>-M3D_EPSILON && r[ 5]y * q->z - q->x * q->w); if(r[ 6]>-M3D_EPSILON && r[ 6]x * q->z - q->y * q->w); if(r[ 8]>-M3D_EPSILON && r[ 8]y * q->z + q->x * q->w); if(r[ 9]>-M3D_EPSILON && r[ 9]x * q->x + q->y * q->y); if(r[10]>-M3D_EPSILON && r[10]x; r[ 7] = p->y; r[11] = p->z; r[12] = 0; r[13] = 0; r[14] = 0; r[15] = 1; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 913813c3b..c0babe9b7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -118,6 +118,7 @@ SET( IMPORTERS unit/utColladaImportExport.cpp unit/utCSMImportExport.cpp unit/utB3DImportExport.cpp + unit/utM3DImportExport.cpp unit/utMDCImportExport.cpp unit/utAssbinImportExport.cpp unit/ImportExport/utAssjsonImportExport.cpp diff --git a/test/models/M3D/README.md b/test/models/M3D/README.md deleted file mode 100644 index 144d1ec64..000000000 --- a/test/models/M3D/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Model 3D Samples -================ - - aliveai_character.m3d - from Minetest aliveai mod (textures, animations, original 47k, m3d 2.5k) - cube.m3d - smallest possible example, 119 bytes only - cube_normals.m3d - cube with normal vectors, 159 bytes - cube_usemtl.m3d - converted from Assimp sample OBJ by the same name, cube with materials - cube_with_vertexcolors.m3d - converted from Assimp sample OBJ by the same name, cube with vertex colors - cube_with_vertexcolors.a3d - same, but saved in ASCII variant with Windows line endings (\r\n) - mobs_dwarves_character.m3d - from Minetest mobs_dwarves mod (with Assimp artifacts converted perfectly too...) - suzanne.m3d - exported from Blender (monkey face, with normals and texture UVs and materials) - WusonBlitz0.m3d - from Assimp sample by the same name (was 87k, triangle mesh) with int8 coordinates, minor quality degradation - WusonBlitz1.m3d - same, but uses int16 coordinates (no noticable difference to the original, but just 35k) - WusonBlitz2.m3d - same, but with 32 bit floating point numbers (same precision as the original, half the file size, 42k) diff --git a/test/models/M3D/aliveai_character.m3d b/test/models/M3D/aliveai_character.m3d deleted file mode 100644 index f4c170300bcb40712693f3e4cb7586f9c462b1c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2532 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 diff --git a/test/unit/utM3DImportExport.cpp b/test/unit/utM3DImportExport.cpp new file mode 100644 index 000000000..c3a0fb08c --- /dev/null +++ b/test/unit/utM3DImportExport.cpp @@ -0,0 +1,68 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utM3DImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/WusonBlitz0.m3d", aiProcess_ValidateDataStructure ); +#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER + return nullptr != scene; +#else + return nullptr == scene; +#endif // ASSIMP_BUILD_NO_M3D_IMPORTER + } +}; + +TEST_F( utM3DImportExport, importM3DFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} From 7201ebdcccb9758f9e44d7ca896dfa99627e8e53 Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 1 Nov 2019 21:52:11 +0100 Subject: [PATCH 064/170] Make Clang happy --- code/M3D/m3d.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index b28dd5d2a..9ace802ef 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -2085,8 +2085,8 @@ _inline static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_IN { switch(type) { case 1: *idx = data[0] > 253 ? (int8_t)data[0] : data[0]; data++; break; - case 2: *idx = *((uint16_t*)data) > 65533 ? *((int16_t*)data) : *((uint16_t*)data); data += 2; break; - case 4: *idx = *((int32_t*)data); data += 4; break; + case 2: *idx = (uint16_t)((data[1]<<8)|data[0]) > 65533 ? (int16_t)((data[1]<<8)|data[0]) : (uint16_t)((data[1]<<8)|data[0]); data += 2; break; + case 4: *idx = (int32_t)((data[3]<<24)|(data[2]<<16)|(data[1]<<8)|data[0]); data += 4; break; } return data; } @@ -2751,10 +2751,10 @@ memerr: M3D_LOG("Out of memory"); data += 4; break; case 2: - model->vertex[i].x = (M3D_FLOAT)(*((int16_t*)(data+0))) / 32767; - model->vertex[i].y = (M3D_FLOAT)(*((int16_t*)(data+2))) / 32767; - model->vertex[i].z = (M3D_FLOAT)(*((int16_t*)(data+4))) / 32767; - model->vertex[i].w = (M3D_FLOAT)(*((int16_t*)(data+6))) / 32767; + model->vertex[i].x = (M3D_FLOAT)((int16_t)((data[1]<<8)|data[0])) / 32767; + model->vertex[i].y = (M3D_FLOAT)((int16_t)((data[3]<<8)|data[2])) / 32767; + model->vertex[i].z = (M3D_FLOAT)((int16_t)((data[5]<<8)|data[4])) / 32767; + model->vertex[i].w = (M3D_FLOAT)((int16_t)((data[7]<<8)|data[6])) / 32767; data += 8; break; case 4: From c890a4d5214c89e1d96d32c7f220f6cd1bc8e0ca Mon Sep 17 00:00:00 2001 From: thewoz Date: Tue, 5 Nov 2019 16:36:03 +0100 Subject: [PATCH 065/170] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 65a54aaeb..e975976bf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build .project *.kdev4* +.DS_Store # build artefacts *.o From adec426b7cc477890f9def19da9a2df6433db135 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Tue, 5 Nov 2019 17:11:56 +0000 Subject: [PATCH 066/170] Fix for exporting fbx bigger than 2GB --- code/Common/DefaultIOStream.cpp | 33 +++++++++++++++++++++++++++++++-- code/FBX/FBXCommon.h | 7 ++++--- code/FBX/FBXExportNode.cpp | 14 +++++++------- code/FBX/FBXExporter.cpp | 4 ++-- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/code/Common/DefaultIOStream.cpp b/code/Common/DefaultIOStream.cpp index 1c100b618..829b44731 100644 --- a/code/Common/DefaultIOStream.cpp +++ b/code/Common/DefaultIOStream.cpp @@ -52,6 +52,35 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; +namespace +{ + template + size_t select_ftell(FILE* file) + { + return ::ftell(file); + } + + template + int select_fseek(FILE* file, int64_t offset, int origin) + { + return ::fseek(file, static_cast(offset), origin); + } + +#if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) + template<> + size_t select_ftell<8>(FILE* file) + { + return ::_ftelli64(file); + } + + template<> + int select_fseek<8>(FILE* file, int64_t offset, int origin) + { + return ::_fseeki64(file, offset, origin); + } +#endif +} + // ---------------------------------------------------------------------------------- DefaultIOStream::~DefaultIOStream() { @@ -93,7 +122,7 @@ aiReturn DefaultIOStream::Seek(size_t pOffset, aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET"); // do the seek - return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); + return (0 == select_fseek(mFile, (int64_t)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); } // ---------------------------------------------------------------------------------- @@ -102,7 +131,7 @@ size_t DefaultIOStream::Tell() const if (!mFile) { return 0; } - return ::ftell(mFile); + return select_ftell(mFile); } // ---------------------------------------------------------------------------------- diff --git a/code/FBX/FBXCommon.h b/code/FBX/FBXCommon.h index e51644913..b28601c74 100644 --- a/code/FBX/FBXCommon.h +++ b/code/FBX/FBXCommon.h @@ -50,9 +50,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { - const std::string NULL_RECORD = { // 13 null bytes - '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0' - }; // who knows why + const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit + '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', + '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0' + }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?) const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import const int64_t SECOND = 46186158000; // FBX's kTime unit diff --git a/code/FBX/FBXExportNode.cpp b/code/FBX/FBXExportNode.cpp index 06c89cee4..9b29995cc 100644 --- a/code/FBX/FBXExportNode.cpp +++ b/code/FBX/FBXExportNode.cpp @@ -325,9 +325,9 @@ void FBX::Node::BeginBinary(Assimp::StreamWriterLE &s) this->start_pos = s.Tell(); // placeholders for end pos and property section info - s.PutU4(0); // end pos - s.PutU4(0); // number of properties - s.PutU4(0); // total property section length + s.PutU8(0); // end pos + s.PutU8(0); // number of properties + s.PutU8(0); // total property section length // node name s.PutU1(uint8_t(name.size())); // length of node name @@ -352,9 +352,9 @@ void FBX::Node::EndPropertiesBinary( size_t pos = s.Tell(); ai_assert(pos > property_start); size_t property_section_size = pos - property_start; - s.Seek(start_pos + 4); - s.PutU4(uint32_t(num_properties)); - s.PutU4(uint32_t(property_section_size)); + s.Seek(start_pos + 8); // 8 bytes of uint64_t of end_pos + s.PutU8(num_properties); + s.PutU8(property_section_size); s.Seek(pos); } @@ -375,7 +375,7 @@ void FBX::Node::EndBinary( // now go back and write initial pos this->end_pos = s.Tell(); s.Seek(start_pos); - s.PutU4(uint32_t(end_pos)); + s.PutU8(end_pos); s.Seek(end_pos); } diff --git a/code/FBX/FBXExporter.cpp b/code/FBX/FBXExporter.cpp index 9316dc4f0..9767f9a0a 100644 --- a/code/FBX/FBXExporter.cpp +++ b/code/FBX/FBXExporter.cpp @@ -81,8 +81,8 @@ using namespace Assimp::FBX; // some constants that we'll use for writing metadata namespace Assimp { namespace FBX { - const std::string EXPORT_VERSION_STR = "7.4.0"; - const uint32_t EXPORT_VERSION_INT = 7400; // 7.4 == 2014/2015 + const std::string EXPORT_VERSION_STR = "7.5.0"; + const uint32_t EXPORT_VERSION_INT = 7500; // 7.5 == 2016+ // FBX files have some hashed values that depend on the creation time field, // but for now we don't actually know how to generate these. // what we can do is set them to a known-working version. From ddf7c0ad8f6ede4742ab65de9c0cfba86262dd02 Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Tue, 5 Nov 2019 17:34:32 -0800 Subject: [PATCH 067/170] avoid weighting vertex repeatedly when joining identical vertices --- code/Common/Exporter.cpp | 3 +-- code/FBX/FBXExporter.cpp | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 4ce1a2bd8..8b224369d 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -452,8 +452,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties; - pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again); - exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); + pProp->SetPropertyBool("bJoinIdenticalVertices", pp & aiProcess_JoinIdenticalVertices); exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); pimpl->mProgressHandler->UpdateFileWrite(4, 4); diff --git a/code/FBX/FBXExporter.cpp b/code/FBX/FBXExporter.cpp index 9767f9a0a..413d1d6c8 100644 --- a/code/FBX/FBXExporter.cpp +++ b/code/FBX/FBXExporter.cpp @@ -1860,6 +1860,7 @@ void FBXExporter::WriteObjects () sdnode.AddChild("Version", int32_t(100)); sdnode.AddChild("UserData", "", ""); + std::set setWeightedVertex; // add indices and weights, if any if (b) { std::vector subdef_indices; @@ -1867,7 +1868,8 @@ void FBXExporter::WriteObjects () int32_t last_index = -1; for (size_t wi = 0; wi < b->mNumWeights; ++wi) { int32_t vi = vertex_indices[b->mWeights[wi].mVertexId]; - if (vi == last_index) { + bool bIsWeightedAlready = (setWeightedVertex.find(vi) != setWeightedVertex.end()); + if (vi == last_index || bIsWeightedAlready) { // only for vertices we exported to fbx // TODO, FIXME: this assumes identically-located vertices // will always deform in the same way. @@ -1877,6 +1879,7 @@ void FBXExporter::WriteObjects () // identical vertex. continue; } + setWeightedVertex.insert(vi); subdef_indices.push_back(vi); subdef_weights.push_back(b->mWeights[wi].mWeight); last_index = vi; From b63285f9adada054957b0755ff496fc9f8c7b2c5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 9 Nov 2019 11:12:47 +0100 Subject: [PATCH 068/170] closes https://github.com/assimp/assimp/issues/2684: normalize path --- assimpTargets-release.cmake.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assimpTargets-release.cmake.in b/assimpTargets-release.cmake.in index 95253a4eb..79b643a9a 100644 --- a/assimpTargets-release.cmake.in +++ b/assimpTargets-release.cmake.in @@ -34,6 +34,8 @@ if(MSVC) endif() endif() set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) + + file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX) if(ASSIMP_BUILD_SHARED_LIBS) set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@") @@ -73,6 +75,7 @@ else() endif() set_target_properties(assimp::assimp PROPERTIES IMPORTED_SONAME_RELEASE "${sharedLibraryName}" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) From 58729b1b3d781f591655194b3b1b4665d09ae8da Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 9 Nov 2019 11:28:56 +0100 Subject: [PATCH 069/170] fix debug-target. --- assimpTargets-debug.cmake.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assimpTargets-debug.cmake.in b/assimpTargets-debug.cmake.in index 466759929..e4ccbfba9 100644 --- a/assimpTargets-debug.cmake.in +++ b/assimpTargets-debug.cmake.in @@ -35,6 +35,8 @@ if(MSVC) endif() set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) + file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX) + if(ASSIMP_BUILD_SHARED_LIBS) set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") From 031d3b648ea98bdc6b61b4925bdc1137ff5fcb95 Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Sun, 10 Nov 2019 08:23:17 +0100 Subject: [PATCH 070/170] defs: use noexcept only for C++11 and more --- include/assimp/defs.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/assimp/defs.h b/include/assimp/defs.h index 6f2f8ae88..d8fc98179 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -306,7 +306,11 @@ static const ai_real ai_epsilon = (ai_real) 0.00001; #define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type)) #ifndef _MSC_VER -# define AI_NO_EXCEPT noexcept +# if __cplusplus >= 201103L // C++11 +# define AI_NO_EXCEPT noexcept +# else +# define AI_NO_EXCEPT +# endif #else # if (_MSC_VER >= 1915 ) # define AI_NO_EXCEPT noexcept From aa25c815bddd168ec6d1ac0d353c061428d28e27 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 10 Nov 2019 09:47:50 +0100 Subject: [PATCH 071/170] closes https://github.com/assimp/assimp/issues/1320: make sure build works with all exporter disabled. --- code/Common/Exporter.cpp | 127 ++++++++++++++++++------------------ include/assimp/Exporter.hpp | 2 - 2 files changed, 64 insertions(+), 65 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 4ce1a2bd8..8a95ceae5 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -106,97 +106,88 @@ void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperti void ExportSceneA3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*); -// ------------------------------------------------------------------------------------------------ -// global array of all export formats which Assimp supports in its current build -Exporter::ExportFormatEntry gExporters[] = -{ + +static void setupExporterArray(std::vector &exporters) { #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER - Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada ), + exporters.push_back(Exporter::ExportFormatEntry("collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada)); #endif #ifndef ASSIMP_BUILD_NO_X_EXPORTER - Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile, - aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs ), + exporters.push_back(Exporter::ExportFormatEntry("x", "X Files", "x", &ExportSceneXFile, + aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs)); #endif #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER - Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0 ), + exporters.push_back(Exporter::ExportFormatEntry("stp", "Step Files", "stp", &ExportSceneStep, 0)); #endif #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER - Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, - aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ), - Exporter::ExportFormatEntry( "objnomtl", "Wavefront OBJ format without material file", "obj", &ExportSceneObjNoMtl, - aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ), + exporters.push_back(Exporter::ExportFormatEntry("obj", "Wavefront OBJ format", "obj", &ExportSceneObj, + aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */)); + exporters.push_back(Exporter::ExportFormatEntry("objnomtl", "Wavefront OBJ format without material file", "obj", &ExportSceneObjNoMtl, + aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */)); #endif #ifndef ASSIMP_BUILD_NO_STL_EXPORTER - Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL, - aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices - ), - Exporter::ExportFormatEntry( "stlb", "Stereolithography (binary)", "stl" , &ExportSceneSTLBinary, - aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices - ), + exporters.push_back(Exporter::ExportFormatEntry("stl", "Stereolithography", "stl", &ExportSceneSTL, + aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices)); + exporters.push_back(Exporter::ExportFormatEntry("stlb", "Stereolithography (binary)", "stl", &ExportSceneSTLBinary, + aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices)); #endif #ifndef ASSIMP_BUILD_NO_PLY_EXPORTER - Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly, - aiProcess_PreTransformVertices - ), - Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary, - aiProcess_PreTransformVertices - ), + exporters.push_back(Exporter::ExportFormatEntry("ply", "Stanford Polygon Library", "ply", &ExportScenePly, + aiProcess_PreTransformVertices)); + exporters.push_back(Exporter::ExportFormatEntry("plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary, + aiProcess_PreTransformVertices)); #endif #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER - Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS, - aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices ), + exporters.push_back(Exporter::ExportFormatEntry("3ds", "Autodesk 3DS (legacy)", "3ds", &ExportScene3DS, + aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices)); #endif #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER - Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), + exporters.push_back(Exporter::ExportFormatEntry("gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2, + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType)); + exporters.push_back(Exporter::ExportFormatEntry("glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2, + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType)); + exporters.push_back(Exporter::ExportFormatEntry("gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType)); + exporters.push_back(Exporter::ExportFormatEntry("glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType)); #endif #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER - Exporter::ExportFormatEntry( "assbin", "Assimp Binary File", "assbin" , &ExportSceneAssbin, 0 ), + exporters.push_back(Exporter::ExportFormatEntry("assbin", "Assimp Binary File", "assbin", &ExportSceneAssbin, 0)); #endif #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER - Exporter::ExportFormatEntry( "assxml", "Assimp XML Document", "assxml" , &ExportSceneAssxml, 0 ), + exporters.push_back(Exporter::ExportFormatEntry("assxml", "Assimp XML Document", "assxml", &ExportSceneAssxml, 0)); #endif #ifndef ASSIMP_BUILD_NO_X3D_EXPORTER - Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ), + exporters.push_back(Exporter::ExportFormatEntry("x3d", "Extensible 3D", "x3d", &ExportSceneX3D, 0)); #endif #ifndef ASSIMP_BUILD_NO_FBX_EXPORTER - Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ), - Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ), + exporters.push_back(Exporter::ExportFormatEntry("fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0)); + exporters.push_back(Exporter::ExportFormatEntry("fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0)); #endif #ifndef ASSIMP_BUILD_NO_M3D_EXPORTER - Exporter::ExportFormatEntry( "m3d", "Model 3D (binary)", "m3d", &ExportSceneM3D, 0 ), - Exporter::ExportFormatEntry( "a3d", "Model 3D (ascii)", "m3d", &ExportSceneA3D, 0 ), + exporters.push_back(Exporter::ExportFormatEntry("m3d", "Model 3D (binary)", "m3d", &ExportSceneM3D, 0)); + exporters.push_back(Exporter::ExportFormatEntry("a3d", "Model 3D (ascii)", "m3d", &ExportSceneA3D, 0)); #endif #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER - Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ), + exporters.push_back(Exporter::ExportFormatEntry("3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0)); #endif #ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER - Exporter::ExportFormatEntry( "assjson", "Assimp JSON Document", "json", &ExportAssimp2Json, 0) + exporters.push_back(Exporter::ExportFormatEntry("assjson", "Assimp JSON Document", "json", &ExportAssimp2Json, 0)); #endif -}; - -#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0])) - +} class ExporterPimpl { public: @@ -212,10 +203,7 @@ public: GetPostProcessingStepInstanceList(mPostProcessingSteps); // grab all built-in exporters - if ( 0 != ( ASSIMP_NUM_EXPORTERS ) ) { - mExporters.resize( ASSIMP_NUM_EXPORTERS ); - std::copy( gExporters, gExporters + ASSIMP_NUM_EXPORTERS, mExporters.begin() ); - } + setupExporterArray(mExporters); } ~ExporterPimpl() { @@ -259,24 +247,28 @@ Exporter :: Exporter() // ------------------------------------------------------------------------------------------------ Exporter::~Exporter() { - FreeBlob(); + ai_assert(nullptr != pimpl); + FreeBlob(); delete pimpl; } // ------------------------------------------------------------------------------------------------ void Exporter::SetIOHandler( IOSystem* pIOHandler) { - pimpl->mIsDefaultIOHandler = !pIOHandler; + ai_assert(nullptr != pimpl); + pimpl->mIsDefaultIOHandler = !pIOHandler; pimpl->mIOSystem.reset(pIOHandler); } // ------------------------------------------------------------------------------------------------ IOSystem* Exporter::GetIOHandler() const { - return pimpl->mIOSystem.get(); + ai_assert(nullptr != pimpl); + return pimpl->mIOSystem.get(); } // ------------------------------------------------------------------------------------------------ bool Exporter::IsDefaultIOHandler() const { - return pimpl->mIsDefaultIOHandler; + ai_assert(nullptr != pimpl); + return pimpl->mIsDefaultIOHandler; } // ------------------------------------------------------------------------------------------------ @@ -302,6 +294,7 @@ void Exporter::SetProgressHandler(ProgressHandler* pHandler) { // ------------------------------------------------------------------------------------------------ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing, const ExportProperties* pProperties) { + ai_assert(nullptr != pimpl); if (pimpl->blob) { delete pimpl->blob; pimpl->blob = nullptr; @@ -326,7 +319,7 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { ASSIMP_BEGIN_EXCEPTION_REGION(); - + ai_assert(nullptr != pimpl); // when they create scenes from scratch, users will likely create them not in verbose // format. They will likely not be aware that there is a flag in the scene to indicate // this, however. To avoid surprises and bug reports, we check for duplicates in @@ -473,11 +466,13 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c // ------------------------------------------------------------------------------------------------ const char* Exporter::GetErrorString() const { + ai_assert(nullptr != pimpl); return pimpl->mError.c_str(); } // ------------------------------------------------------------------------------------------------ void Exporter::FreeBlob() { + ai_assert(nullptr != pimpl); delete pimpl->blob; pimpl->blob = nullptr; @@ -486,30 +481,34 @@ void Exporter::FreeBlob() { // ------------------------------------------------------------------------------------------------ const aiExportDataBlob* Exporter::GetBlob() const { - return pimpl->blob; + ai_assert(nullptr != pimpl); + return pimpl->blob; } // ------------------------------------------------------------------------------------------------ const aiExportDataBlob* Exporter::GetOrphanedBlob() const { - const aiExportDataBlob* tmp = pimpl->blob; + ai_assert(nullptr != pimpl); + const aiExportDataBlob *tmp = pimpl->blob; pimpl->blob = nullptr; return tmp; } // ------------------------------------------------------------------------------------------------ size_t Exporter::GetExportFormatCount() const { + ai_assert(nullptr != pimpl); return pimpl->mExporters.size(); } // ------------------------------------------------------------------------------------------------ const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const { - if (index >= GetExportFormatCount()) { + ai_assert(nullptr != pimpl); + if (index >= GetExportFormatCount()) { return nullptr; } // Return from static storage if the requested index is built-in. - if (index < sizeof(gExporters) / sizeof(gExporters[0])) { - return &gExporters[index].mDescription; + if (index < pimpl->mExporters.size()) { + return &pimpl->mExporters[index].mDescription; } return &pimpl->mExporters[index].mDescription; @@ -517,7 +516,8 @@ const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) c // ------------------------------------------------------------------------------------------------ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) { - for(const ExportFormatEntry& e : pimpl->mExporters) { + ai_assert(nullptr != pimpl); + for (const ExportFormatEntry &e : pimpl->mExporters) { if (!strcmp(e.mDescription.id,desc.mDescription.id)) { return aiReturn_FAILURE; } @@ -529,7 +529,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) { // ------------------------------------------------------------------------------------------------ void Exporter::UnregisterExporter(const char* id) { - for(std::vector::iterator it = pimpl->mExporters.begin(); + ai_assert(nullptr != pimpl); + for (std::vector::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) { if (!strcmp((*it).mDescription.id,id)) { pimpl->mExporters.erase(it); diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index 2612e1f9d..20e7c6c6f 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, From 04db5cd5ea8f2c2095df06e11b5899796f225da6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 14 Nov 2019 21:11:53 +0100 Subject: [PATCH 072/170] closes https://github.com/assimp/assimp/issues/2119: initial version. --- code/glTF/glTFAsset.inl | 3 --- code/glTF/glTFCommon.h | 17 +++++++---------- code/glTF2/glTF2Asset.h | 6 +++++- code/glTF2/glTF2Asset.inl | 23 ++++++++++++++++++----- code/glTF2/glTF2Exporter.h | 1 + 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/code/glTF/glTFAsset.inl b/code/glTF/glTFAsset.inl index f31781a3f..25cf1873c 100644 --- a/code/glTF/glTFAsset.inl +++ b/code/glTF/glTFAsset.inl @@ -1427,9 +1427,6 @@ inline void Asset::ReadExtensionsUsed(Document& doc) } } - #define CHECK_EXT(EXT) \ - if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; - CHECK_EXT(KHR_binary_glTF); CHECK_EXT(KHR_materials_common); diff --git a/code/glTF/glTFCommon.h b/code/glTF/glTFCommon.h index d9edee75e..b2e28d580 100644 --- a/code/glTF/glTFCommon.h +++ b/code/glTF/glTFCommon.h @@ -188,7 +188,7 @@ namespace glTFCommon { size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out); inline - size_t DecodeBase64(const char* in, uint8_t*& out) { + size_t DecodeBase64(const char* in, uint8_t*& out) { return DecodeBase64(in, strlen(in), out); } @@ -221,25 +221,22 @@ namespace glTFCommon { }; inline - char EncodeCharBase64(uint8_t b) { + char EncodeCharBase64(uint8_t b) { return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)]; } inline - uint8_t DecodeCharBase64(char c) { + uint8_t DecodeCharBase64(char c) { return DATA::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs? - /*if (c >= 'A' && c <= 'Z') return c - 'A'; - if (c >= 'a' && c <= 'z') return c - 'a' + 26; - if (c >= '0' && c <= '9') return c - '0' + 52; - if (c == '+') return 62; - if (c == '/') return 63; - return 64; // '-' */ } size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out); void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out); - } + } // namespace Util + +#define CHECK_EXT(EXT) \ + if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; } diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index 15c4c44fa..60a393170 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -685,6 +685,10 @@ namespace glTF2 Ref texture; unsigned int index; unsigned int texCoord = 0; + + float offset[2]; + float rotation; + float scale[2]; }; struct NormalTextureInfo : TextureInfo @@ -1024,7 +1028,7 @@ namespace glTF2 bool KHR_materials_pbrSpecularGlossiness; bool KHR_materials_unlit; bool KHR_lights_punctual; - + bool KHR_texture_transform; } extensionsUsed; AssetMetadata asset; diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 6b47b1607..310fcde06 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -800,8 +800,20 @@ inline void Texture::Read(Value& obj, Asset& r) } namespace { - inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) - { + inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) { + if (r.extensionsUsed.KHR_texture_transform) { + if (Value *extensions = FindObject(*prop, "extensions")) { + if (Value *pKHR_texture_transform = FindObject(*extensions, "KHR_texture_transform")) { + if (Value *array = FindArray(*pKHR_texture_transform, "offset")) { + out.offset[0] = (*array)[0].GetFloat(); + out.offset[1] = (*array)[1].GetFloat(); + } + ReadMember(*pKHR_texture_transform, "rotation", out.rotation); + ReadMember(*pKHR_texture_transform, "scale", *out.scale); + } + } + } + if (Value* index = FindUInt(*prop, "index")) { out.texture = r.textures.Retrieve(index->GetUint()); } @@ -877,6 +889,9 @@ inline void Material::Read(Value& material, Asset& r) } } + if (r.extensionsUsed.KHR_texture_transform) { + } + unlit = nullptr != FindObject(*extensions, "KHR_materials_unlit"); } } @@ -1463,12 +1478,10 @@ inline void Asset::ReadExtensionsUsed(Document& doc) } } - #define CHECK_EXT(EXT) \ - if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; - CHECK_EXT(KHR_materials_pbrSpecularGlossiness); CHECK_EXT(KHR_materials_unlit); CHECK_EXT(KHR_lights_punctual); + CHECK_EXT(KHR_texture_transform); #undef CHECK_EXT } diff --git a/code/glTF2/glTF2Exporter.h b/code/glTF2/glTF2Exporter.h index 2dc083709..b527c4bc9 100644 --- a/code/glTF2/glTF2Exporter.h +++ b/code/glTF2/glTF2Exporter.h @@ -74,6 +74,7 @@ namespace glTF2 struct Texture; // Vec/matrix types, as raw float arrays + typedef float (vec2)[2]; typedef float (vec3)[3]; typedef float (vec4)[4]; } From 74080a083ad4764485bc633156dd37d0416281a0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 14 Nov 2019 21:15:30 +0100 Subject: [PATCH 073/170] add texture-transfrm unittest. --- test/models/glTF2/textureTransform/Arrow.png | Bin 0 -> 867 bytes .../models/glTF2/textureTransform/Correct.png | Bin 0 -> 2457 bytes test/models/glTF2/textureTransform/Error.png | Bin 0 -> 2273 bytes .../models/glTF2/textureTransform/License.txt | 0 .../glTF2/textureTransform/NotSupported.png | Bin 0 -> 3291 bytes .../textureTransform/TextureTransformTest.bin | Bin 0 -> 136 bytes .../TextureTransformTest.gltf | 540 ++++++++++++++++++ test/models/glTF2/textureTransform/UV.png | Bin 0 -> 12345 bytes test/unit/utglTF2ImportExport.cpp | 7 + 9 files changed, 547 insertions(+) create mode 100644 test/models/glTF2/textureTransform/Arrow.png create mode 100644 test/models/glTF2/textureTransform/Correct.png create mode 100644 test/models/glTF2/textureTransform/Error.png create mode 100644 test/models/glTF2/textureTransform/License.txt create mode 100644 test/models/glTF2/textureTransform/NotSupported.png create mode 100644 test/models/glTF2/textureTransform/TextureTransformTest.bin create mode 100644 test/models/glTF2/textureTransform/TextureTransformTest.gltf create mode 100644 test/models/glTF2/textureTransform/UV.png diff --git a/test/models/glTF2/textureTransform/Arrow.png b/test/models/glTF2/textureTransform/Arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..fe3405b3f6b14ffdc920bc0f4f30560cabcbab39 GIT binary patch literal 867 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrVAk?aJ56J?j$lS^=gjZ_g@TqW zaQReo#@OwU{5ebgCEMCMJT~8a;-RrdgX`zf#0#yxL)Q;a@-sk40k#~WxL&^iVd z1_nkNG8?wL7TC>aTp-zK$i^^BP{s4n_S?B442yQ9`bRI_!+Sh;ipY*&d}^#?Whhux|hU{RJu8Z@=7~*iy!F?biAEizS#1`x>l{J5ExW zf1b0J$K|`;f;^Vvk3ZfncB(TMcx&kp`}o1@Z}Mj)E^J^9*(%J_emH+WcO{R-^BU*N zXAL*$2n$ZUne*+F--itL9s8wUl2_L` zFCVYk6mXw+1zP}+KHgBp5UR*g%EPe0iAAxG@hiirO;c>ntNI3Oo({Szk&zLdlfCv$ znf1;0-;>thB?JXa{Z~BZ-(r;Vc*+0fuRQIl+8DL{$1T4wKipM-07^X zlU{#~y8SmdKI;Vst03QEK`~Uy| literal 0 HcmV?d00001 diff --git a/test/models/glTF2/textureTransform/Correct.png b/test/models/glTF2/textureTransform/Correct.png new file mode 100644 index 0000000000000000000000000000000000000000..e332824fbc00f15ed290ac891bf18dedf74415e5 GIT binary patch literal 2457 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 L1NF*>w&DK)(UL^| literal 0 HcmV?d00001 diff --git a/test/models/glTF2/textureTransform/License.txt b/test/models/glTF2/textureTransform/License.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/models/glTF2/textureTransform/NotSupported.png b/test/models/glTF2/textureTransform/NotSupported.png new file mode 100644 index 0000000000000000000000000000000000000000..721e7fd765079c7f2111254145c49e1dbec124d3 GIT binary patch literal 3291 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 literal 0 HcmV?d00001 diff --git a/test/models/glTF2/textureTransform/TextureTransformTest.bin b/test/models/glTF2/textureTransform/TextureTransformTest.bin new file mode 100644 index 0000000000000000000000000000000000000000..6765a13008a0b763d65a217da7fd651a66c2f056 GIT binary patch literal 136 zcmY+6fe8R048x)x=4*cDYc4uL3ngVM1t!qLO1{~jk~i-IjO@ub=lkEu?%A$UDPgHv Fcmbi}2l)U1 literal 0 HcmV?d00001 diff --git a/test/models/glTF2/textureTransform/TextureTransformTest.gltf b/test/models/glTF2/textureTransform/TextureTransformTest.gltf new file mode 100644 index 000000000..6dde51d9a --- /dev/null +++ b/test/models/glTF2/textureTransform/TextureTransformTest.gltf @@ -0,0 +1,540 @@ +{ + "accessors": [ + { + "bufferView": 0, + "componentType": 5126, + "count": 4, + "type": "VEC3", + "max": [ + 0.5, + 0.5, + 0.0 + ], + "min": [ + -0.5, + -0.5, + 0.0 + ], + "name": "Positions" + }, + { + "bufferView": 1, + "componentType": 5126, + "count": 4, + "type": "VEC2", + "name": "UV0" + }, + { + "bufferView": 2, + "componentType": 5126, + "count": 4, + "type": "VEC2", + "name": "UV1" + }, + { + "bufferView": 3, + "componentType": 5125, + "count": 6, + "type": "SCALAR", + "name": "Indices" + } + ], + "asset": { + "version": "2.0" + }, + "buffers": [ + { + "uri": "TextureTransformTest.bin", + "byteLength": 136 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteLength": 48, + "name": "Positions" + }, + { + "buffer": 0, + "byteOffset": 48, + "byteLength": 32, + "name": "UV0" + }, + { + "buffer": 0, + "byteOffset": 80, + "byteLength": 32, + "name": "UV1" + }, + { + "buffer": 0, + "byteOffset": 112, + "byteLength": 24, + "name": "Indices" + } + ], + "extensionsUsed": [ + "KHR_texture_transform" + ], + "images": [ + { + "uri": "UV.png" + }, + { + "uri": "Arrow.png" + }, + { + "uri": "Correct.png" + }, + { + "uri": "NotSupported.png" + }, + { + "uri": "Error.png" + } + ], + "materials": [ + { + "name": "Offset U", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "extensions": { + "KHR_texture_transform": { + "offset": [ + 0.5, + 0.0 + ] + } + } + }, + "metallicFactor": 0 + } + }, + { + "name": "Offset V", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "extensions": { + "KHR_texture_transform": { + "offset": [ + 0.0, + 0.5 + ] + } + } + }, + "metallicFactor": 0 + } + }, + { + "name": "Offset UV", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "extensions": { + "KHR_texture_transform": { + "offset": [ + 0.5, + 0.5 + ] + } + } + }, + "metallicFactor": 0 + } + }, + { + "name": "Rotation", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 1, + "extensions": { + "KHR_texture_transform": { + "rotation": 0.39269908169872415480783042290994 + } + } + }, + "metallicFactor": 0 + } + }, + { + "name": "Scale", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 1, + "extensions": { + "KHR_texture_transform": { + "scale": [ + 1.5, + 1.5 + ] + } + } + }, + "metallicFactor": 0 + } + }, + { + "name": "All", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 1, + "extensions": { + "KHR_texture_transform": { + "offset": [ + -0.2, + -0.1 + ], + "rotation": 0.3, + "scale": [ + 1.5, + 1.5 + ] + } + } + }, + "metallicFactor": 0 + } + }, + { + "name": "Correct", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 2 + }, + "metallicFactor": 0 + } + }, + { + "name": "NotSupported", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 3 + }, + "metallicFactor": 0 + } + }, + { + "name": "Error", + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 4 + }, + "metallicFactor": 0 + } + } + ], + "meshes": [ + { + "name": "Offset U", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 2 + }, + "indices": 3, + "material": 0 + } + ] + }, + { + "name": "Offset V", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 2 + }, + "indices": 3, + "material": 1 + } + ] + }, + { + "name": "Offset UV", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 2 + }, + "indices": 3, + "material": 2 + } + ] + }, + { + "name": "Rotation", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 1 + }, + "indices": 3, + "material": 3 + } + ] + }, + { + "name": "Scale", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 1 + }, + "indices": 3, + "material": 4 + } + ] + }, + { + "name": "All", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 1 + }, + "indices": 3, + "material": 5 + } + ] + }, + { + "name": "Correct Marker", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 1 + }, + "indices": 3, + "material": 6 + } + ] + }, + { + "name": "Not Supported Marker", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 1 + }, + "indices": 3, + "material": 7 + } + ] + }, + { + "name": "Error Marker", + "primitives": [ + { + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 1 + }, + "indices": 3, + "material": 8 + } + ] + } + ], + "nodes": [ + { + "name": "Offset U", + "mesh": 0, + "translation": [ + -1.1, + 0.55, + 0 + ] + }, + { + "name": "Offset V", + "mesh": 1, + "translation": [ + 0, + 0.55, + 0 + ] + }, + { + "name": "Offset UV", + "mesh": 2, + "translation": [ + 1.1, + 0.55, + 0 + ] + }, + { + "name": "Rotation", + "mesh": 3, + "translation": [ + -1.1, + -0.55, + 0 + ], + "children": [ + 4, + 5, + 6 + ] + }, + { + "name": "Rotation - Correct", + "mesh": 6, + "translation": [ + -0.07904822439840125109869401756656, + -0.51626748576241543174100150833647, + 0.01 + ], + "scale": [ + 0.15, + 0.15, + 0.15 + ] + }, + { + "name": "Rotation - Not Supported", + "mesh": 7, + "translation": [ + 0.27781745930520227684092879831533, + -0.27781745930520227684092879831533, + 0.01 + ], + "scale": [ + 0.15, + 0.15, + 0.15 + ] + }, + { + "name": "Rotation - Error", + "mesh": 8, + "translation": [ + 0.51626748576241543174100150833647, + 0.07904822439840125109869401756656, + 0.01 + ], + "scale": [ + 0.15, + 0.15, + 0.15 + ] + }, + { + "name": "Scale", + "mesh": 4, + "translation": [ + 0, + -0.55, + 0 + ], + "children": [ + 8, + 9 + ] + }, + { + "name": "Scale - Correct", + "mesh": 6, + "translation": [ + 0.01854497287013485122728586554355, + -0.01854497287013485122728586554355, + 0.01 + ], + "scale": [ + 0.1, + 0.1, + 0.1 + ] + }, + { + "name": "Scale - Not Supported", + "mesh": 7, + "translation": [ + 0.27781745930520227684092879831533, + -0.27781745930520227684092879831533, + 0.01 + ], + "scale": [ + 0.15, + 0.15, + 0.15 + ] + }, + { + "name": "All", + "mesh": 5, + "translation": [ + 1.1, + -0.55, + 0 + ], + "children": [ + 11 + ] + }, + { + "name": "All - Correct", + "mesh": 6, + "translation": [ + -0.07, + -0.25, + 0.01 + ], + "scale": [ + 0.1, + 0.1, + 0.1 + ] + } + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0, + 1, + 2, + 3, + 7, + 10 + ] + } + ], + "textures": [ + { + "source": 0, + "sampler": 0 + }, + { + "source": 1, + "sampler": 0 + }, + { + "source": 2 + }, + { + "source": 3 + }, + { + "source": 4 + } + ], + "samplers": [ + { + "wrapS": 33071, + "wrapT": 33071, + "magFilter": 9729, + "minFilter": 9729 + } + ] +} \ No newline at end of file diff --git a/test/models/glTF2/textureTransform/UV.png b/test/models/glTF2/textureTransform/UV.png new file mode 100644 index 0000000000000000000000000000000000000000..c1a6d4d370c48c7e42ea7337dc5acb4376e5c92f GIT binary patch literal 12345 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[7]->mNumFaces, 17u); } +TEST_F( utglTF2ImportExport, texture_transform_test ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/textureTransform/TextureTransformTest.gltf", + aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} + #ifndef ASSIMP_BUILD_NO_EXPORT TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { EXPECT_TRUE( exporterTest() ); From 17946e26efd2b408f0b5e9bd08615a3a992611ca Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 15 Nov 2019 18:35:33 +0100 Subject: [PATCH 074/170] add missing setup of texture transform in aiMaterial. --- code/glTF2/glTF2Asset.inl | 12 ++++++++++-- code/glTF2/glTF2Importer.cpp | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 310fcde06..35f285d85 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -802,14 +802,22 @@ inline void Texture::Read(Value& obj, Asset& r) namespace { inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) { if (r.extensionsUsed.KHR_texture_transform) { - if (Value *extensions = FindObject(*prop, "extensions")) { + out.scale[0] = 1; + out.scale[1] = 1; + out.offset[0] = 0; + out.offset[1] = 0; + out.rotation = 0; + if (Value *extensions = FindObject(*prop, "extensions")) { if (Value *pKHR_texture_transform = FindObject(*extensions, "KHR_texture_transform")) { if (Value *array = FindArray(*pKHR_texture_transform, "offset")) { out.offset[0] = (*array)[0].GetFloat(); out.offset[1] = (*array)[1].GetFloat(); } ReadMember(*pKHR_texture_transform, "rotation", out.rotation); - ReadMember(*pKHR_texture_transform, "scale", *out.scale); + if (Value *array = FindArray(*pKHR_texture_transform, "scale")) { + out.scale[0] = (*array)[0].GetFloat(); + out.scale[1] = (*array)[1].GetFloat(); + } } } } diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index b3141fd96..8d88260db 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -206,6 +206,14 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); } + aiUVTransform transform; + transform.mTranslation.x = prop.offset[0]; + transform.mTranslation.y = prop.offset[0]; + transform.mRotation = prop.rotation; + transform.mScaling.x = prop.scale[0]; + transform.mScaling.y = prop.scale[1]; + mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot); + mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); From a8182d86cb4c6af514d3d286bf96907a349c3e60 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 15 Nov 2019 19:38:37 +0100 Subject: [PATCH 075/170] fix initialization + some vs2019 compiler warnings. --- code/glTF2/glTF2Asset.inl | 23 ++++++++++++++--------- code/glTF2/glTF2Importer.cpp | 6 +++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 35f285d85..5bc241342 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -802,22 +802,27 @@ inline void Texture::Read(Value& obj, Asset& r) namespace { inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) { if (r.extensionsUsed.KHR_texture_transform) { - out.scale[0] = 1; - out.scale[1] = 1; - out.offset[0] = 0; - out.offset[1] = 0; - out.rotation = 0; if (Value *extensions = FindObject(*prop, "extensions")) { if (Value *pKHR_texture_transform = FindObject(*extensions, "KHR_texture_transform")) { if (Value *array = FindArray(*pKHR_texture_transform, "offset")) { out.offset[0] = (*array)[0].GetFloat(); out.offset[1] = (*array)[1].GetFloat(); - } - ReadMember(*pKHR_texture_transform, "rotation", out.rotation); - if (Value *array = FindArray(*pKHR_texture_transform, "scale")) { + } else { + out.offset[0] = 0; + out.offset[1] = 0; + } + + if (!ReadMember(*pKHR_texture_transform, "rotation", out.rotation)) { + out.rotation = 0; + } + + if (Value *array = FindArray(*pKHR_texture_transform, "scale")) { out.scale[0] = (*array)[0].GetFloat(); out.scale[1] = (*array)[1].GetFloat(); - } + } else { + out.scale[0] = 1; + out.scale[1] = 1; + } } } } diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 8d88260db..91b758c48 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -622,7 +622,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) nFaces = count / 2; if (nFaces * 2 != count) { ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); - count = nFaces * 2; + count = (unsigned int) nFaces * 2; } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 2) { @@ -649,7 +649,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) nFaces = count / 3; if (nFaces * 3 != count) { ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); - count = nFaces * 3; + count = (unsigned int) nFaces * 3; } faces = new aiFace[nFaces]; for (unsigned int i = 0; i < count; i += 3) { @@ -1134,7 +1134,7 @@ aiMeshMorphAnim* CreateMeshMorphAnim(glTF2::Asset& r, Node& node, AnimationSampl samplers.weight->output->ExtractData(values); anim->mNumKeys = static_cast(samplers.weight->input->count); - const unsigned int numMorphs = samplers.weight->output->count / anim->mNumKeys; + const unsigned int numMorphs = (unsigned int)samplers.weight->output->count / anim->mNumKeys; anim->mKeys = new aiMeshMorphKey[anim->mNumKeys]; unsigned int k = 0u; From 3a8cb442f39efee20425dfe6d5ae65bfc5ba6e48 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 15 Nov 2019 20:52:13 +0100 Subject: [PATCH 076/170] closes https://github.com/assimp/assimp/issues/2681: add dx11-sample to cmake. --- CMakeLists.txt | 2 +- .../SimpleTexturedDirectx11/CMakeLists.txt | 48 ++++++ .../SimpleTexturedDirectx11.sln | 28 ---- .../SimpleTexturedDirectx11/ModelLoader.cpp | 2 + .../SimpleTexturedDirectx11.vcxproj | 146 ------------------ .../SimpleTexturedDirectx11.vcxproj.filters | 50 ------ 6 files changed, 51 insertions(+), 225 deletions(-) create mode 100644 samples/SimpleTexturedDirectx11/CMakeLists.txt delete mode 100644 samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln delete mode 100644 samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj delete mode 100644 samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters diff --git a/CMakeLists.txt b/CMakeLists.txt index 693d6f16a..7a94ddf68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ OPTION( ASSIMP_BUILD_ASSIMP_TOOLS ) OPTION ( ASSIMP_BUILD_SAMPLES "If the official samples are built as well (needs Glut)." - OFF + ON ) OPTION ( ASSIMP_BUILD_TESTS "If the test suite for Assimp is built in addition to the library." diff --git a/samples/SimpleTexturedDirectx11/CMakeLists.txt b/samples/SimpleTexturedDirectx11/CMakeLists.txt new file mode 100644 index 000000000..a463ee282 --- /dev/null +++ b/samples/SimpleTexturedDirectx11/CMakeLists.txt @@ -0,0 +1,48 @@ +FIND_PACKAGE(DirectX) + +IF ( MSVC ) + SET(M_LIB) +ELSE ( MSVC ) + find_library(M_LIB m) +ENDIF ( MSVC ) + +if ( MSVC ) + ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) + REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE ) +endif ( MSVC ) + +INCLUDE_DIRECTORIES( + ${Assimp_SOURCE_DIR}/include + ${Assimp_SOURCE_DIR}/code + ${OPENGL_INCLUDE_DIR} + ${GLUT_INCLUDE_DIR} + ${Assimp_SOURCE_DIR}/samples/freeglut/include +) + +LINK_DIRECTORIES( + ${Assimp_BINARY_DIR} + ${Assimp_BINARY_DIR}/lib +) + +ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32 + SimpleTexturedDirectx11/Mesh.h + SimpleTexturedDirectx11/ModelLoader.cpp + SimpleTexturedDirectx11/ModelLoader.h + #SimpleTexturedDirectx11/PixelShader.hlsl + SimpleTexturedDirectx11/TextureLoader.cpp + SimpleTexturedDirectx11/TextureLoader.h + #SimpleTexturedDirectx11/VertexShader.hlsl + SimpleTexturedDirectx11/main.cpp +) + +SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) + +TARGET_LINK_LIBRARIES( assimp_simpletextureddirectx11 assimp ${DirectX_LIBRARY} comctl32.lib winmm.lib ) +SET_TARGET_PROPERTIES( assimp_simpletextureddirectx11 PROPERTIES + OUTPUT_NAME assimp_simpletextureddirectx11 +) + +INSTALL( TARGETS assimp_simpletextureddirectx11 + DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev +) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln deleted file mode 100644 index 381ac8f94..000000000 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexturedDirectx11", "SimpleTexturedDirectx11\SimpleTexturedDirectx11.vcxproj", "{E3B160B5-E71F-4F3F-9310-B8F156F736D8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.ActiveCfg = Debug|x64 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.Build.0 = Debug|x64 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.ActiveCfg = Debug|Win32 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.Build.0 = Debug|Win32 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.ActiveCfg = Release|x64 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.Build.0 = Release|x64 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.ActiveCfg = Release|Win32 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp index a2d3faeb3..10ba07a98 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp @@ -180,6 +180,8 @@ string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat { return "textures are on disk"; } + + return "."; } int ModelLoader::getTextureIndex(aiString * str) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj deleted file mode 100644 index 6584b7d7c..000000000 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj +++ /dev/null @@ -1,146 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {E3B160B5-E71F-4F3F-9310-B8F156F736D8} - SimpleTexturedDirectx11 - 10.0.14393.0 - - - - Application - true - v141 - MultiByte - - - Application - false - v141 - true - MultiByte - - - Application - true - v141 - MultiByte - - - Application - false - v141 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - $(IncludePath);E:\OpenGL VS Files\include - $(LibraryPath);E:\OpenGL VS Files\lib - - - - Level3 - Disabled - true - - - assimp-vc140-mt.lib;%(AdditionalDependencies) - - - - - Level3 - Disabled - true - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - - - - - - - - - - Pixel - Pixel - Pixel - Pixel - - - Vertex - Vertex - Vertex - Vertex - - - - - - - - - - - \ No newline at end of file diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters deleted file mode 100644 index 3568b73c5..000000000 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters +++ /dev/null @@ -1,50 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {b6a86d3e-70a5-4d1e-ba05-c20902300206} - - - - - Source Files - - - Source Files - - - Source Files - - - - - Shaders - - - Shaders - - - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file From 4ad2368116f984e2ba36f32083f649dbba175fcc Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 15 Nov 2019 21:46:09 +0100 Subject: [PATCH 077/170] disable samples per default. --- CMakeLists.txt | 2 +- samples/SimpleTexturedDirectx11/CMakeLists.txt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a94ddf68..693d6f16a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ OPTION( ASSIMP_BUILD_ASSIMP_TOOLS ) OPTION ( ASSIMP_BUILD_SAMPLES "If the official samples are built as well (needs Glut)." - ON + OFF ) OPTION ( ASSIMP_BUILD_TESTS "If the test suite for Assimp is built in addition to the library." diff --git a/samples/SimpleTexturedDirectx11/CMakeLists.txt b/samples/SimpleTexturedDirectx11/CMakeLists.txt index a463ee282..373b5a9db 100644 --- a/samples/SimpleTexturedDirectx11/CMakeLists.txt +++ b/samples/SimpleTexturedDirectx11/CMakeLists.txt @@ -2,8 +2,6 @@ FIND_PACKAGE(DirectX) IF ( MSVC ) SET(M_LIB) -ELSE ( MSVC ) - find_library(M_LIB m) ENDIF ( MSVC ) if ( MSVC ) From 2eed8b18208d93000ae5b23339f7ecb4672fda8e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 16 Nov 2019 08:08:57 +0100 Subject: [PATCH 078/170] TextureTransform: set material transform only when the extension is provided. --- code/glTF2/glTF2Asset.h | 11 +- code/glTF2/glTF2Asset.inl | 23 +- code/glTF2/glTF2Importer.cpp | 2006 +++++++++++++++++----------------- 3 files changed, 1001 insertions(+), 1039 deletions(-) diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index 60a393170..831a763cd 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -685,10 +685,13 @@ namespace glTF2 Ref texture; unsigned int index; unsigned int texCoord = 0; - - float offset[2]; - float rotation; - float scale[2]; + + bool textureTransformSupported = false; + struct TextureTransformExt { + float offset[2]; + float rotation; + float scale[2]; + } TextureTransformExt_t; }; struct NormalTextureInfo : TextureInfo diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 5bc241342..4259022e9 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -803,25 +803,26 @@ namespace { inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) { if (r.extensionsUsed.KHR_texture_transform) { if (Value *extensions = FindObject(*prop, "extensions")) { - if (Value *pKHR_texture_transform = FindObject(*extensions, "KHR_texture_transform")) { + out.textureTransformSupported = true; + if (Value *pKHR_texture_transform = FindObject(*extensions, "KHR_texture_transform")) { if (Value *array = FindArray(*pKHR_texture_transform, "offset")) { - out.offset[0] = (*array)[0].GetFloat(); - out.offset[1] = (*array)[1].GetFloat(); + out.TextureTransformExt_t.offset[0] = (*array)[0].GetFloat(); + out.TextureTransformExt_t.offset[1] = (*array)[1].GetFloat(); } else { - out.offset[0] = 0; - out.offset[1] = 0; + out.TextureTransformExt_t.offset[0] = 0; + out.TextureTransformExt_t.offset[1] = 0; } - if (!ReadMember(*pKHR_texture_transform, "rotation", out.rotation)) { - out.rotation = 0; + if (!ReadMember(*pKHR_texture_transform, "rotation", out.TextureTransformExt_t.rotation)) { + out.TextureTransformExt_t.rotation = 0; } if (Value *array = FindArray(*pKHR_texture_transform, "scale")) { - out.scale[0] = (*array)[0].GetFloat(); - out.scale[1] = (*array)[1].GetFloat(); + out.TextureTransformExt_t.scale[0] = (*array)[0].GetFloat(); + out.TextureTransformExt_t.scale[1] = (*array)[1].GetFloat(); } else { - out.scale[0] = 1; - out.scale[1] = 1; + out.TextureTransformExt_t.scale[0] = 1; + out.TextureTransformExt_t.scale[1] = 1; } } } diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 91b758c48..3dffa4b27 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -43,18 +43,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER #include "glTF2/glTF2Importer.h" +#include "PostProcessing/MakeVerboseFormat.h" #include "glTF2/glTF2Asset.h" #include "glTF2/glTF2AssetWriter.h" -#include "PostProcessing/MakeVerboseFormat.h" +#include #include #include -#include -#include #include -#include #include -#include +#include +#include +#include #include #include @@ -67,11 +67,11 @@ using namespace glTF2; using namespace glTFCommon; namespace { - // generate bi-tangents from normals and tangents according to spec - struct Tangent { - aiVector3D xyz; - ai_real w; - }; +// generate bi-tangents from normals and tangents according to spec +struct Tangent { + aiVector3D xyz; + ai_real w; +}; } // namespace // @@ -79,66 +79,63 @@ namespace { // static const aiImporterDesc desc = { - "glTF2 Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, - 0, - 0, - 0, - 0, - "gltf glb" + "glTF2 Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + 0, + 0, + 0, + 0, + "gltf glb" }; -glTF2Importer::glTF2Importer() -: BaseImporter() -, meshOffsets() -, embeddedTexIdxs() -, mScene( NULL ) { - // empty +glTF2Importer::glTF2Importer() : + BaseImporter(), + meshOffsets(), + embeddedTexIdxs(), + mScene(NULL) { + // empty } glTF2Importer::~glTF2Importer() { - // empty + // empty } -const aiImporterDesc* glTF2Importer::GetInfo() const -{ - return &desc; +const aiImporterDesc *glTF2Importer::GetInfo() const { + return &desc; } -bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool /* checkSig */) const -{ - const std::string &extension = GetExtension(pFile); +bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { + const std::string &extension = GetExtension(pFile); - if (extension != "gltf" && extension != "glb") - return false; + if (extension != "gltf" && extension != "glb") + return false; - if (pIOHandler) { - glTF2::Asset asset(pIOHandler); - asset.Load(pFile, extension == "glb"); - std::string version = asset.asset.version; - return !version.empty() && version[0] == '2'; - } + if (pIOHandler) { + glTF2::Asset asset(pIOHandler); + asset.Load(pFile, extension == "glb"); + std::string version = asset.asset.version; + return !version.empty() && version[0] == '2'; + } - return false; + return false; } -static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) -{ - switch (gltfWrapMode) { - case SamplerWrap::Mirrored_Repeat: - return aiTextureMapMode_Mirror; +static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) { + switch (gltfWrapMode) { + case SamplerWrap::Mirrored_Repeat: + return aiTextureMapMode_Mirror; - case SamplerWrap::Clamp_To_Edge: - return aiTextureMapMode_Clamp; + case SamplerWrap::Clamp_To_Edge: + return aiTextureMapMode_Clamp; - case SamplerWrap::UNSET: - case SamplerWrap::Repeat: - default: - return aiTextureMapMode_Wrap; - } + case SamplerWrap::UNSET: + case SamplerWrap::Repeat: + default: + return aiTextureMapMode_Wrap; + } } /*static void CopyValue(const glTF2::vec3& v, aiColor3D& out) @@ -180,1190 +177,1151 @@ static void CopyValue(const glTF2::vec4& v, aiQuaternion& out) o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15]; }*/ -inline void SetMaterialColorProperty(Asset& /*r*/, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx) -{ - aiColor4D col; - CopyValue(prop, col); - mat->AddProperty(&col, 1, pKey, type, idx); +inline void SetMaterialColorProperty(Asset & /*r*/, vec4 &prop, aiMaterial *mat, const char *pKey, unsigned int type, unsigned int idx) { + aiColor4D col; + CopyValue(prop, col); + mat->AddProperty(&col, 1, pKey, type, idx); } -inline void SetMaterialColorProperty(Asset& /*r*/, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx) -{ - aiColor4D col; - glTFCommon::CopyValue(prop, col); - mat->AddProperty(&col, 1, pKey, type, idx); +inline void SetMaterialColorProperty(Asset & /*r*/, vec3 &prop, aiMaterial *mat, const char *pKey, unsigned int type, unsigned int idx) { + aiColor4D col; + glTFCommon::CopyValue(prop, col); + mat->AddProperty(&col, 1, pKey, type, idx); } -inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& /*r*/, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0) -{ - if (prop.texture && prop.texture->source) { - aiString uri(prop.texture->source->uri); +inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset & /*r*/, glTF2::TextureInfo prop, aiMaterial *mat, aiTextureType texType, unsigned int texSlot = 0) { + if (prop.texture && prop.texture->source) { + aiString uri(prop.texture->source->uri); - int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; - if (texIdx != -1) { // embedded - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) - uri.data[0] = '*'; - uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); - } + int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; + if (texIdx != -1) { // embedded + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + uri.data[0] = '*'; + uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); + } - aiUVTransform transform; - transform.mTranslation.x = prop.offset[0]; - transform.mTranslation.y = prop.offset[0]; - transform.mRotation = prop.rotation; - transform.mScaling.x = prop.scale[0]; - transform.mScaling.y = prop.scale[1]; - mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot); + if (prop.textureTransformSupported) { + aiUVTransform transform; + transform.mTranslation.x = prop.TextureTransformExt_t.offset[0]; + transform.mTranslation.y = prop.TextureTransformExt_t.offset[0]; + transform.mRotation = prop.TextureTransformExt_t.rotation; + transform.mScaling.x = prop.TextureTransformExt_t.scale[0]; + transform.mScaling.y = prop.TextureTransformExt_t.scale[1]; + mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot); + } - mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); - mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); + mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); + mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); - if (prop.texture->sampler) { - Ref sampler = prop.texture->sampler; + if (prop.texture->sampler) { + Ref sampler = prop.texture->sampler; - aiString name(sampler->name); - aiString id(sampler->id); + aiString name(sampler->name); + aiString id(sampler->id); - mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot)); - mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot)); + mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot)); + mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot)); - aiTextureMapMode wrapS = ConvertWrappingMode(sampler->wrapS); - aiTextureMapMode wrapT = ConvertWrappingMode(sampler->wrapT); - mat->AddProperty(&wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); - mat->AddProperty(&wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); + aiTextureMapMode wrapS = ConvertWrappingMode(sampler->wrapS); + aiTextureMapMode wrapT = ConvertWrappingMode(sampler->wrapT); + mat->AddProperty(&wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); + mat->AddProperty(&wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); - if (sampler->magFilter != SamplerMagFilter::UNSET) { - mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot)); - } + if (sampler->magFilter != SamplerMagFilter::UNSET) { + mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot)); + } - if (sampler->minFilter != SamplerMinFilter::UNSET) { - mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot)); - } - } - } + if (sampler->minFilter != SamplerMinFilter::UNSET) { + mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot)); + } + } + } } -inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::NormalTextureInfo& prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0) -{ - SetMaterialTextureProperty( embeddedTexIdxs, r, (glTF2::TextureInfo) prop, mat, texType, texSlot ); +inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset &r, glTF2::NormalTextureInfo &prop, aiMaterial *mat, aiTextureType texType, unsigned int texSlot = 0) { + SetMaterialTextureProperty(embeddedTexIdxs, r, (glTF2::TextureInfo)prop, mat, texType, texSlot); - if (prop.texture && prop.texture->source) { - mat->AddProperty(&prop.scale, 1, AI_MATKEY_GLTF_TEXTURE_SCALE(texType, texSlot)); - } + if (prop.texture && prop.texture->source) { + mat->AddProperty(&prop.scale, 1, AI_MATKEY_GLTF_TEXTURE_SCALE(texType, texSlot)); + } } -inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::OcclusionTextureInfo& prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0) -{ - SetMaterialTextureProperty( embeddedTexIdxs, r, (glTF2::TextureInfo) prop, mat, texType, texSlot ); +inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset &r, glTF2::OcclusionTextureInfo &prop, aiMaterial *mat, aiTextureType texType, unsigned int texSlot = 0) { + SetMaterialTextureProperty(embeddedTexIdxs, r, (glTF2::TextureInfo)prop, mat, texType, texSlot); - if (prop.texture && prop.texture->source) { - mat->AddProperty(&prop.strength, 1, AI_MATKEY_GLTF_TEXTURE_STRENGTH(texType, texSlot)); - } + if (prop.texture && prop.texture->source) { + mat->AddProperty(&prop.strength, 1, AI_MATKEY_GLTF_TEXTURE_STRENGTH(texType, texSlot)); + } } -static aiMaterial* ImportMaterial(std::vector& embeddedTexIdxs, Asset& r, Material& mat) -{ - aiMaterial* aimat = new aiMaterial(); +static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, Material &mat) { + aiMaterial *aimat = new aiMaterial(); - if (!mat.name.empty()) { - aiString str(mat.name); + if (!mat.name.empty()) { + aiString str(mat.name); - aimat->AddProperty(&str, AI_MATKEY_NAME); - } + aimat->AddProperty(&str, AI_MATKEY_NAME); + } - SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); - SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR); + SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); - aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR); - aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR); + aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR); + aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR); - float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor; - roughnessAsShininess *= roughnessAsShininess * 1000; - aimat->AddProperty(&roughnessAsShininess, 1, AI_MATKEY_SHININESS); + float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor; + roughnessAsShininess *= roughnessAsShininess * 1000; + aimat->AddProperty(&roughnessAsShininess, 1, AI_MATKEY_SHININESS); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE); - SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE); + SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE); - aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); + aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); - aiString alphaMode(mat.alphaMode); - aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE); - aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF); + aiString alphaMode(mat.alphaMode); + aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE); + aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF); - //pbrSpecularGlossiness - if (mat.pbrSpecularGlossiness.isPresent) { - PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value; + //pbrSpecularGlossiness + if (mat.pbrSpecularGlossiness.isPresent) { + PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value; - aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS); - SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); - SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR); + aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS); + SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR); - float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f; - aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS); - aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR); + float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f; + aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS); + aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE); + SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE); - SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR); - } - if (mat.unlit) { - aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT); - } + SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR); + } + if (mat.unlit) { + aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT); + } - return aimat; + return aimat; } -void glTF2Importer::ImportMaterials(glTF2::Asset& r) -{ - const unsigned int numImportedMaterials = unsigned(r.materials.Size()); - Material defaultMaterial; +void glTF2Importer::ImportMaterials(glTF2::Asset &r) { + const unsigned int numImportedMaterials = unsigned(r.materials.Size()); + Material defaultMaterial; - mScene->mNumMaterials = numImportedMaterials + 1; - mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials]; - mScene->mMaterials[numImportedMaterials] = ImportMaterial(embeddedTexIdxs, r, defaultMaterial); + mScene->mNumMaterials = numImportedMaterials + 1; + mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; + mScene->mMaterials[numImportedMaterials] = ImportMaterial(embeddedTexIdxs, r, defaultMaterial); - for (unsigned int i = 0; i < numImportedMaterials; ++i) { - mScene->mMaterials[i] = ImportMaterial(embeddedTexIdxs, r, r.materials[i]); - } + for (unsigned int i = 0; i < numImportedMaterials; ++i) { + mScene->mMaterials[i] = ImportMaterial(embeddedTexIdxs, r, r.materials[i]); + } } - -static inline void SetFace(aiFace& face, int a) -{ - face.mNumIndices = 1; - face.mIndices = new unsigned int[1]; - face.mIndices[0] = a; +static inline void SetFace(aiFace &face, int a) { + face.mNumIndices = 1; + face.mIndices = new unsigned int[1]; + face.mIndices[0] = a; } -static inline void SetFace(aiFace& face, int a, int b) -{ - face.mNumIndices = 2; - face.mIndices = new unsigned int[2]; - face.mIndices[0] = a; - face.mIndices[1] = b; +static inline void SetFace(aiFace &face, int a, int b) { + face.mNumIndices = 2; + face.mIndices = new unsigned int[2]; + face.mIndices[0] = a; + face.mIndices[1] = b; } -static inline void SetFace(aiFace& face, int a, int b, int c) -{ - face.mNumIndices = 3; - face.mIndices = new unsigned int[3]; - face.mIndices[0] = a; - face.mIndices[1] = b; - face.mIndices[2] = c; +static inline void SetFace(aiFace &face, int a, int b, int c) { + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + face.mIndices[0] = a; + face.mIndices[1] = b; + face.mIndices[2] = c; } #ifdef ASSIMP_BUILD_DEBUG -static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts) -{ - for (unsigned i = 0; i < nFaces; ++i) { - for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { - unsigned idx = faces[i].mIndices[j]; - if (idx >= nVerts) - return false; - } - } - return true; +static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsigned nVerts) { + for (unsigned i = 0; i < nFaces; ++i) { + for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { + unsigned idx = faces[i].mIndices[j]; + if (idx >= nVerts) + return false; + } + } + return true; } #endif // ASSIMP_BUILD_DEBUG -void glTF2Importer::ImportMeshes(glTF2::Asset& r) -{ - std::vector meshes; +void glTF2Importer::ImportMeshes(glTF2::Asset &r) { + std::vector meshes; - unsigned int k = 0; + unsigned int k = 0; - for (unsigned int m = 0; m < r.meshes.Size(); ++m) { - Mesh& mesh = r.meshes[m]; + for (unsigned int m = 0; m < r.meshes.Size(); ++m) { + Mesh &mesh = r.meshes[m]; - meshOffsets.push_back(k); - k += unsigned(mesh.primitives.size()); + meshOffsets.push_back(k); + k += unsigned(mesh.primitives.size()); - for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { - Mesh::Primitive& prim = mesh.primitives[p]; + for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { + Mesh::Primitive &prim = mesh.primitives[p]; - aiMesh* aim = new aiMesh(); - meshes.push_back(aim); + aiMesh *aim = new aiMesh(); + meshes.push_back(aim); - aim->mName = mesh.name.empty() ? mesh.id : mesh.name; + aim->mName = mesh.name.empty() ? mesh.id : mesh.name; - if (mesh.primitives.size() > 1) { - ai_uint32& len = aim->mName.length; - aim->mName.data[len] = '-'; - len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); - } + if (mesh.primitives.size() > 1) { + ai_uint32 &len = aim->mName.length; + aim->mName.data[len] = '-'; + len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); + } - switch (prim.mode) { - case PrimitiveMode_POINTS: - aim->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; + switch (prim.mode) { + case PrimitiveMode_POINTS: + aim->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; - case PrimitiveMode_LINES: - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: - aim->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aim->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; - case PrimitiveMode_TRIANGLES: - case PrimitiveMode_TRIANGLE_STRIP: - case PrimitiveMode_TRIANGLE_FAN: - aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + } - } + Mesh::Primitive::Attributes &attr = prim.attributes; - Mesh::Primitive::Attributes& attr = prim.attributes; + if (attr.position.size() > 0 && attr.position[0]) { + aim->mNumVertices = static_cast(attr.position[0]->count); + attr.position[0]->ExtractData(aim->mVertices); + } - if (attr.position.size() > 0 && attr.position[0]) { - aim->mNumVertices = static_cast(attr.position[0]->count); - attr.position[0]->ExtractData(aim->mVertices); - } + if (attr.normal.size() > 0 && attr.normal[0]) { + attr.normal[0]->ExtractData(aim->mNormals); - if (attr.normal.size() > 0 && attr.normal[0]) { - attr.normal[0]->ExtractData(aim->mNormals); + // only extract tangents if normals are present + if (attr.tangent.size() > 0 && attr.tangent[0]) { + // generate bitangents from normals and tangents according to spec + Tangent *tangents = nullptr; - // only extract tangents if normals are present - if (attr.tangent.size() > 0 && attr.tangent[0]) { - // generate bitangents from normals and tangents according to spec - Tangent *tangents = nullptr; + attr.tangent[0]->ExtractData(tangents); - attr.tangent[0]->ExtractData(tangents); + aim->mTangents = new aiVector3D[aim->mNumVertices]; + aim->mBitangents = new aiVector3D[aim->mNumVertices]; - aim->mTangents = new aiVector3D[aim->mNumVertices]; - aim->mBitangents = new aiVector3D[aim->mNumVertices]; + for (unsigned int i = 0; i < aim->mNumVertices; ++i) { + aim->mTangents[i] = tangents[i].xyz; + aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w; + } - for (unsigned int i = 0; i < aim->mNumVertices; ++i) { - aim->mTangents[i] = tangents[i].xyz; - aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w; - } + delete[] tangents; + } + } - delete [] tangents; - } - } + for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { + if (attr.color[c]->count != aim->mNumVertices) { + DefaultLogger::get()->warn("Color stream size in mesh \"" + mesh.name + + "\" does not match the vertex count"); + continue; + } + attr.color[c]->ExtractData(aim->mColors[c]); + } + for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { + if (attr.texcoord[tc]->count != aim->mNumVertices) { + DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + + "\" does not match the vertex count"); + continue; + } - for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { - if (attr.color[c]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Color stream size in mesh \"" + mesh.name + - "\" does not match the vertex count"); - continue; - } - attr.color[c]->ExtractData(aim->mColors[c]); - } - for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { - if (attr.texcoord[tc]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + - "\" does not match the vertex count"); - continue; - } + attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); + aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); - attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); - aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); + aiVector3D *values = aim->mTextureCoords[tc]; + for (unsigned int i = 0; i < aim->mNumVertices; ++i) { + values[i].y = 1 - values[i].y; // Flip Y coords + } + } - aiVector3D* values = aim->mTextureCoords[tc]; - for (unsigned int i = 0; i < aim->mNumVertices; ++i) { - values[i].y = 1 - values[i].y; // Flip Y coords - } - } + std::vector &targets = prim.targets; + if (targets.size() > 0) { + aim->mNumAnimMeshes = (unsigned int)targets.size(); + aim->mAnimMeshes = new aiAnimMesh *[aim->mNumAnimMeshes]; + for (size_t i = 0; i < targets.size(); i++) { + aim->mAnimMeshes[i] = aiCreateAnimMesh(aim); + aiAnimMesh &aiAnimMesh = *(aim->mAnimMeshes[i]); + Mesh::Primitive::Target &target = targets[i]; - std::vector& targets = prim.targets; - if (targets.size() > 0) { - aim->mNumAnimMeshes = (unsigned int)targets.size(); - aim->mAnimMeshes = new aiAnimMesh*[aim->mNumAnimMeshes]; - for (size_t i = 0; i < targets.size(); i++) { - aim->mAnimMeshes[i] = aiCreateAnimMesh(aim); - aiAnimMesh& aiAnimMesh = *(aim->mAnimMeshes[i]); - Mesh::Primitive::Target& target = targets[i]; + if (target.position.size() > 0) { + aiVector3D *positionDiff = nullptr; + target.position[0]->ExtractData(positionDiff); + for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { + aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId]; + } + delete[] positionDiff; + } + if (target.normal.size() > 0) { + aiVector3D *normalDiff = nullptr; + target.normal[0]->ExtractData(normalDiff); + for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { + aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId]; + } + delete[] normalDiff; + } + if (target.tangent.size() > 0) { + Tangent *tangent = nullptr; + attr.tangent[0]->ExtractData(tangent); - if (target.position.size() > 0) { - aiVector3D *positionDiff = nullptr; - target.position[0]->ExtractData(positionDiff); - for(unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { - aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId]; - } - delete [] positionDiff; - } - if (target.normal.size() > 0) { - aiVector3D *normalDiff = nullptr; - target.normal[0]->ExtractData(normalDiff); - for(unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) { - aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId]; - } - delete [] normalDiff; - } - if (target.tangent.size() > 0) { - Tangent *tangent = nullptr; - attr.tangent[0]->ExtractData(tangent); + aiVector3D *tangentDiff = nullptr; + target.tangent[0]->ExtractData(tangentDiff); - aiVector3D *tangentDiff = nullptr; - target.tangent[0]->ExtractData(tangentDiff); + for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) { + tangent[vertexId].xyz += tangentDiff[vertexId]; + aiAnimMesh.mTangents[vertexId] = tangent[vertexId].xyz; + aiAnimMesh.mBitangents[vertexId] = (aiAnimMesh.mNormals[vertexId] ^ tangent[vertexId].xyz) * tangent[vertexId].w; + } + delete[] tangent; + delete[] tangentDiff; + } + if (mesh.weights.size() > i) { + aiAnimMesh.mWeight = mesh.weights[i]; + } + } + } - for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) { - tangent[vertexId].xyz += tangentDiff[vertexId]; - aiAnimMesh.mTangents[vertexId] = tangent[vertexId].xyz; - aiAnimMesh.mBitangents[vertexId] = (aiAnimMesh.mNormals[vertexId] ^ tangent[vertexId].xyz) * tangent[vertexId].w; - } - delete [] tangent; - delete [] tangentDiff; - } - if (mesh.weights.size() > i) { - aiAnimMesh.mWeight = mesh.weights[i]; - } - } - } + aiFace *faces = 0; + size_t nFaces = 0; + if (prim.indices) { + size_t count = prim.indices->count; - aiFace* faces = 0; - size_t nFaces = 0; + Accessor::Indexer data = prim.indices->GetIndexer(); + ai_assert(data.IsValid()); - if (prim.indices) { - size_t count = prim.indices->count; + switch (prim.mode) { + case PrimitiveMode_POINTS: { + nFaces = count; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFace(faces[i], data.GetUInt(i)); + } + break; + } - Accessor::Indexer data = prim.indices->GetIndexer(); - ai_assert(data.IsValid()); + case PrimitiveMode_LINES: { + nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); + } + break; + } - switch (prim.mode) { - case PrimitiveMode_POINTS: { - nFaces = count; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; ++i) { - SetFace(faces[i], data.GetUInt(i)); - } - break; - } + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); + for (unsigned int i = 2; i < count; ++i) { + SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } - case PrimitiveMode_LINES: { - nFaces = count / 2; - if (nFaces * 2 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); - count = nFaces * 2; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 2) { - SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); - } - break; - } + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < nFaces; ++i) { + //The ordering is to ensure that the triangles are all drawn with the same orientation + if ((i + 1) % 2 == 0) { + //For even n, vertices n + 1, n, and n + 2 define triangle n + SetFace(faces[i], data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); + } else { + //For odd n, vertices n, n+1, and n+2 define triangle n + SetFace(faces[i], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 1; i < nFaces; ++i) { + SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); + } + break; + } + } else { // no indices provided so directly generate from counts - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: { - nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); - for (unsigned int i = 2; i < count; ++i) { - SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); - } - if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); - } - break; - } + // use the already determined count as it includes checks + unsigned int count = aim->mNumVertices; - case PrimitiveMode_TRIANGLES: { - nFaces = count / 3; - if (nFaces * 3 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); - count = nFaces * 3; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 3) { - SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); - } - break; - } - case PrimitiveMode_TRIANGLE_STRIP: { - nFaces = count - 2; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < nFaces; ++i) { - //The ordering is to ensure that the triangles are all drawn with the same orientation - if ((i + 1) % 2 == 0) - { - //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFace(faces[i], data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); - } - else - { - //For odd n, vertices n, n+1, and n+2 define triangle n - SetFace(faces[i], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); - } - } - break; - } - case PrimitiveMode_TRIANGLE_FAN: - nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); - for (unsigned int i = 1; i < nFaces; ++i) { - SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i + 2)); - } - break; - } - } - else { // no indices provided so directly generate from counts + switch (prim.mode) { + case PrimitiveMode_POINTS: { + nFaces = count; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFace(faces[i], i); + } + break; + } - // use the already determined count as it includes checks - unsigned int count = aim->mNumVertices; + case PrimitiveMode_LINES: { + nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = (unsigned int)nFaces * 2; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFace(faces[i / 2], i, i + 1); + } + break; + } - switch (prim.mode) { - case PrimitiveMode_POINTS: { - nFaces = count; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; ++i) { - SetFace(faces[i], i); - } - break; - } + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + SetFace(faces[0], 0, 1); + for (unsigned int i = 2; i < count; ++i) { + SetFace(faces[i - 1], faces[i - 2].mIndices[1], i); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } - case PrimitiveMode_LINES: { - nFaces = count / 2; - if (nFaces * 2 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); - count = (unsigned int) nFaces * 2; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 2) { - SetFace(faces[i / 2], i, i + 1); - } - break; - } + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = (unsigned int)nFaces * 3; + } + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFace(faces[i / 3], i, i + 1, i + 2); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < nFaces; ++i) { + //The ordering is to ensure that the triangles are all drawn with the same orientation + if ((i + 1) % 2 == 0) { + //For even n, vertices n + 1, n, and n + 2 define triangle n + SetFace(faces[i], i + 1, i, i + 2); + } else { + //For odd n, vertices n, n+1, and n+2 define triangle n + SetFace(faces[i], i, i + 1, i + 2); + } + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], 0, 1, 2); + for (unsigned int i = 1; i < nFaces; ++i) { + SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); + } + break; + } + } - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: { - nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - faces = new aiFace[nFaces]; - SetFace(faces[0], 0, 1); - for (unsigned int i = 2; i < count; ++i) { - SetFace(faces[i - 1], faces[i - 2].mIndices[1], i); - } - if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); - } - break; - } + if (faces) { + aim->mFaces = faces; + aim->mNumFaces = static_cast(nFaces); + ai_assert(CheckValidFacesIndices(faces, static_cast(nFaces), aim->mNumVertices)); + } - case PrimitiveMode_TRIANGLES: { - nFaces = count / 3; - if (nFaces * 3 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); - count = (unsigned int) nFaces * 3; - } - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 3) { - SetFace(faces[i / 3], i, i + 1, i + 2); - } - break; - } - case PrimitiveMode_TRIANGLE_STRIP: { - nFaces = count - 2; - faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < nFaces; ++i) { - //The ordering is to ensure that the triangles are all drawn with the same orientation - if ((i+1) % 2 == 0) - { - //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFace(faces[i], i+1, i, i+2); - } - else - { - //For odd n, vertices n, n+1, and n+2 define triangle n - SetFace(faces[i], i, i+1, i+2); - } - } - break; - } - case PrimitiveMode_TRIANGLE_FAN: - nFaces = count - 2; - faces = new aiFace[nFaces]; - SetFace(faces[0], 0, 1, 2); - for (unsigned int i = 1; i < nFaces; ++i) { - SetFace(faces[i], faces[0].mIndices[0], faces[i - 1].mIndices[2], i + 2); - } - break; - } - } + if (prim.material) { + aim->mMaterialIndex = prim.material.GetIndex(); + } else { + aim->mMaterialIndex = mScene->mNumMaterials - 1; + } + } + } - if (faces) { - aim->mFaces = faces; - aim->mNumFaces = static_cast(nFaces); - ai_assert(CheckValidFacesIndices(faces, static_cast(nFaces), aim->mNumVertices)); - } + meshOffsets.push_back(k); - if (prim.material) { - aim->mMaterialIndex = prim.material.GetIndex(); - } - else { - aim->mMaterialIndex = mScene->mNumMaterials - 1; - } - - } - } - - meshOffsets.push_back(k); - - CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); + CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); } -void glTF2Importer::ImportCameras(glTF2::Asset& r) -{ - if (!r.cameras.Size()) return; +void glTF2Importer::ImportCameras(glTF2::Asset &r) { + if (!r.cameras.Size()) return; - mScene->mNumCameras = r.cameras.Size(); - mScene->mCameras = new aiCamera*[r.cameras.Size()]; + mScene->mNumCameras = r.cameras.Size(); + mScene->mCameras = new aiCamera *[r.cameras.Size()]; - for (size_t i = 0; i < r.cameras.Size(); ++i) { - Camera& cam = r.cameras[i]; + for (size_t i = 0; i < r.cameras.Size(); ++i) { + Camera &cam = r.cameras[i]; - aiCamera* aicam = mScene->mCameras[i] = new aiCamera(); + aiCamera *aicam = mScene->mCameras[i] = new aiCamera(); - // cameras point in -Z by default, rest is specified in node transform - aicam->mLookAt = aiVector3D(0.f,0.f,-1.f); + // cameras point in -Z by default, rest is specified in node transform + aicam->mLookAt = aiVector3D(0.f, 0.f, -1.f); - if (cam.type == Camera::Perspective) { + if (cam.type == Camera::Perspective) { - aicam->mAspect = cam.cameraProperties.perspective.aspectRatio; - aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect); - aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar; - aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear; - } else { - aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar; - aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear; - aicam->mHorizontalFOV = 0.0; - aicam->mAspect = 1.0f; - if (0.f != cam.cameraProperties.ortographic.ymag ) { - aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag; - } - } - } + aicam->mAspect = cam.cameraProperties.perspective.aspectRatio; + aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect); + aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar; + aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear; + } else { + aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar; + aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear; + aicam->mHorizontalFOV = 0.0; + aicam->mAspect = 1.0f; + if (0.f != cam.cameraProperties.ortographic.ymag) { + aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag; + } + } + } } -void glTF2Importer::ImportLights(glTF2::Asset& r) -{ - if (!r.lights.Size()) - return; +void glTF2Importer::ImportLights(glTF2::Asset &r) { + if (!r.lights.Size()) + return; - mScene->mNumLights = r.lights.Size(); - mScene->mLights = new aiLight*[r.lights.Size()]; + mScene->mNumLights = r.lights.Size(); + mScene->mLights = new aiLight *[r.lights.Size()]; - for (size_t i = 0; i < r.lights.Size(); ++i) { - Light& light = r.lights[i]; + for (size_t i = 0; i < r.lights.Size(); ++i) { + Light &light = r.lights[i]; - aiLight* ail = mScene->mLights[i] = new aiLight(); + aiLight *ail = mScene->mLights[i] = new aiLight(); - switch (light.type) - { - case Light::Directional: - ail->mType = aiLightSource_DIRECTIONAL; break; - case Light::Point: - ail->mType = aiLightSource_POINT; break; - case Light::Spot: - ail->mType = aiLightSource_SPOT; break; - } + switch (light.type) { + case Light::Directional: + ail->mType = aiLightSource_DIRECTIONAL; + break; + case Light::Point: + ail->mType = aiLightSource_POINT; + break; + case Light::Spot: + ail->mType = aiLightSource_SPOT; + break; + } - if (ail->mType != aiLightSource_POINT) - { - ail->mDirection = aiVector3D(0.0f, 0.0f, -1.0f); - ail->mUp = aiVector3D(0.0f, 1.0f, 0.0f); - } + if (ail->mType != aiLightSource_POINT) { + ail->mDirection = aiVector3D(0.0f, 0.0f, -1.0f); + ail->mUp = aiVector3D(0.0f, 1.0f, 0.0f); + } - vec3 colorWithIntensity = { light.color[0] * light.intensity, light.color[1] * light.intensity, light.color[2] * light.intensity }; - CopyValue(colorWithIntensity, ail->mColorAmbient); - CopyValue(colorWithIntensity, ail->mColorDiffuse); - CopyValue(colorWithIntensity, ail->mColorSpecular); + vec3 colorWithIntensity = { light.color[0] * light.intensity, light.color[1] * light.intensity, light.color[2] * light.intensity }; + CopyValue(colorWithIntensity, ail->mColorAmbient); + CopyValue(colorWithIntensity, ail->mColorDiffuse); + CopyValue(colorWithIntensity, ail->mColorSpecular); - if (ail->mType == aiLightSource_DIRECTIONAL) - { - ail->mAttenuationConstant = 1.0; - ail->mAttenuationLinear = 0.0; - ail->mAttenuationQuadratic = 0.0; - } - else - { - //in PBR attenuation is calculated using inverse square law which can be expressed - //using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters - //this is correct equation for the case when range (see - //https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual) - //is not present. When range is not present it is assumed that it is infinite and so numerator is 1. - //When range is present then numerator might be any value in range [0,1] and then assimps equation - //will not suffice. In this case range is added into metadata in ImportNode function - //and its up to implementation to read it when it wants to - ail->mAttenuationConstant = 0.0; - ail->mAttenuationLinear = 0.0; - ail->mAttenuationQuadratic = 1.0; - } + if (ail->mType == aiLightSource_DIRECTIONAL) { + ail->mAttenuationConstant = 1.0; + ail->mAttenuationLinear = 0.0; + ail->mAttenuationQuadratic = 0.0; + } else { + //in PBR attenuation is calculated using inverse square law which can be expressed + //using assimps equation: 1/(att0 + att1 * d + att2 * d*d) with the following parameters + //this is correct equation for the case when range (see + //https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual) + //is not present. When range is not present it is assumed that it is infinite and so numerator is 1. + //When range is present then numerator might be any value in range [0,1] and then assimps equation + //will not suffice. In this case range is added into metadata in ImportNode function + //and its up to implementation to read it when it wants to + ail->mAttenuationConstant = 0.0; + ail->mAttenuationLinear = 0.0; + ail->mAttenuationQuadratic = 1.0; + } - if (ail->mType == aiLightSource_SPOT) - { - ail->mAngleInnerCone = light.innerConeAngle; - ail->mAngleOuterCone = light.outerConeAngle; - } - } + if (ail->mType == aiLightSource_SPOT) { + ail->mAngleInnerCone = light.innerConeAngle; + ail->mAngleOuterCone = light.outerConeAngle; + } + } } -static void GetNodeTransform(aiMatrix4x4& matrix, const glTF2::Node& node) { - if (node.matrix.isPresent) { - CopyValue(node.matrix.value, matrix); - } - else { - if (node.translation.isPresent) { - aiVector3D trans; - CopyValue(node.translation.value, trans); - aiMatrix4x4 t; - aiMatrix4x4::Translation(trans, t); - matrix = matrix * t; - } +static void GetNodeTransform(aiMatrix4x4 &matrix, const glTF2::Node &node) { + if (node.matrix.isPresent) { + CopyValue(node.matrix.value, matrix); + } else { + if (node.translation.isPresent) { + aiVector3D trans; + CopyValue(node.translation.value, trans); + aiMatrix4x4 t; + aiMatrix4x4::Translation(trans, t); + matrix = matrix * t; + } - if (node.rotation.isPresent) { - aiQuaternion rot; - CopyValue(node.rotation.value, rot); - matrix = matrix * aiMatrix4x4(rot.GetMatrix()); - } + if (node.rotation.isPresent) { + aiQuaternion rot; + CopyValue(node.rotation.value, rot); + matrix = matrix * aiMatrix4x4(rot.GetMatrix()); + } - if (node.scale.isPresent) { - aiVector3D scal(1.f); - CopyValue(node.scale.value, scal); - aiMatrix4x4 s; - aiMatrix4x4::Scaling(scal, s); - matrix = matrix * s; - } - } + if (node.scale.isPresent) { + aiVector3D scal(1.f); + CopyValue(node.scale.value, scal); + aiMatrix4x4 s; + aiMatrix4x4::Scaling(scal, s); + matrix = matrix * s; + } + } } -static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector>& map) -{ - Mesh::Primitive::Attributes& attr = primitive.attributes; - if (attr.weight.empty() || attr.joint.empty()) { - return; - } - if (attr.weight[0]->count != attr.joint[0]->count) { - return; - } +static void BuildVertexWeightMapping(Mesh::Primitive &primitive, std::vector> &map) { + Mesh::Primitive::Attributes &attr = primitive.attributes; + if (attr.weight.empty() || attr.joint.empty()) { + return; + } + if (attr.weight[0]->count != attr.joint[0]->count) { + return; + } - size_t num_vertices = attr.weight[0]->count; + size_t num_vertices = attr.weight[0]->count; - struct Weights { float values[4]; }; - Weights* weights = nullptr; - attr.weight[0]->ExtractData(weights); + struct Weights { + float values[4]; + }; + Weights *weights = nullptr; + attr.weight[0]->ExtractData(weights); - struct Indices8 { uint8_t values[4]; }; - struct Indices16 { uint16_t values[4]; }; - Indices8* indices8 = nullptr; - Indices16* indices16 = nullptr; - if (attr.joint[0]->GetElementSize() == 4) { - attr.joint[0]->ExtractData(indices8); - }else { - attr.joint[0]->ExtractData(indices16); - } - // - if (nullptr == indices8 && nullptr == indices16) { - // Something went completely wrong! - ai_assert(false); - return; - } + struct Indices8 { + uint8_t values[4]; + }; + struct Indices16 { + uint16_t values[4]; + }; + Indices8 *indices8 = nullptr; + Indices16 *indices16 = nullptr; + if (attr.joint[0]->GetElementSize() == 4) { + attr.joint[0]->ExtractData(indices8); + } else { + attr.joint[0]->ExtractData(indices16); + } + // + if (nullptr == indices8 && nullptr == indices16) { + // Something went completely wrong! + ai_assert(false); + return; + } - for (size_t i = 0; i < num_vertices; ++i) { - for (int j = 0; j < 4; ++j) { - const unsigned int bone = (indices8!=nullptr) ? indices8[i].values[j] : indices16[i].values[j]; - const float weight = weights[i].values[j]; - if (weight > 0 && bone < map.size()) { - map[bone].reserve(8); - map[bone].emplace_back(static_cast(i), weight); - } - } - } + for (size_t i = 0; i < num_vertices; ++i) { + for (int j = 0; j < 4; ++j) { + const unsigned int bone = (indices8 != nullptr) ? indices8[i].values[j] : indices16[i].values[j]; + const float weight = weights[i].values[j]; + if (weight > 0 && bone < map.size()) { + map[bone].reserve(8); + map[bone].emplace_back(static_cast(i), weight); + } + } + } - delete[] weights; - delete[] indices8; - delete[] indices16; + delete[] weights; + delete[] indices8; + delete[] indices16; } -static std::string GetNodeName(const Node& node) -{ - return node.name.empty() ? node.id : node.name; +static std::string GetNodeName(const Node &node) { + return node.name.empty() ? node.id : node.name; } -aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& meshOffsets, glTF2::Ref& ptr) -{ - Node& node = *ptr; +aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector &meshOffsets, glTF2::Ref &ptr) { + Node &node = *ptr; - aiNode* ainode = new aiNode(GetNodeName(node)); + aiNode *ainode = new aiNode(GetNodeName(node)); - if (!node.children.empty()) { - ainode->mNumChildren = unsigned(node.children.size()); - ainode->mChildren = new aiNode*[ainode->mNumChildren]; + if (!node.children.empty()) { + ainode->mNumChildren = unsigned(node.children.size()); + ainode->mChildren = new aiNode *[ainode->mNumChildren]; - for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { - aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]); - child->mParent = ainode; - ainode->mChildren[i] = child; - } - } + for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { + aiNode *child = ImportNode(pScene, r, meshOffsets, node.children[i]); + child->mParent = ainode; + ainode->mChildren[i] = child; + } + } - GetNodeTransform(ainode->mTransformation, node); + GetNodeTransform(ainode->mTransformation, node); - if (!node.meshes.empty()) { - // GLTF files contain at most 1 mesh per node. - assert(node.meshes.size() == 1); - int mesh_idx = node.meshes[0].GetIndex(); - int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx]; + if (!node.meshes.empty()) { + // GLTF files contain at most 1 mesh per node. + assert(node.meshes.size() == 1); + int mesh_idx = node.meshes[0].GetIndex(); + int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx]; - ainode->mNumMeshes = count; - ainode->mMeshes = new unsigned int[count]; + ainode->mNumMeshes = count; + ainode->mMeshes = new unsigned int[count]; - if (node.skin) { - for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { - aiMesh* mesh = pScene->mMeshes[meshOffsets[mesh_idx]+primitiveNo]; - mesh->mNumBones = static_cast(node.skin->jointNames.size()); - mesh->mBones = new aiBone*[mesh->mNumBones]; + if (node.skin) { + for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { + aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo]; + mesh->mNumBones = static_cast(node.skin->jointNames.size()); + mesh->mBones = new aiBone *[mesh->mNumBones]; - // GLTF and Assimp choose to store bone weights differently. - // GLTF has each vertex specify which bones influence the vertex. - // Assimp has each bone specify which vertices it has influence over. - // To convert this data, we first read over the vertex data and pull - // out the bone-to-vertex mapping. Then, when creating the aiBones, - // we copy the bone-to-vertex mapping into the bone. This is unfortunate - // both because it's somewhat slow and because, for many applications, - // we then need to reconvert the data back into the vertex-to-bone - // mapping which makes things doubly-slow. - std::vector> weighting(mesh->mNumBones); - BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); + // GLTF and Assimp choose to store bone weights differently. + // GLTF has each vertex specify which bones influence the vertex. + // Assimp has each bone specify which vertices it has influence over. + // To convert this data, we first read over the vertex data and pull + // out the bone-to-vertex mapping. Then, when creating the aiBones, + // we copy the bone-to-vertex mapping into the bone. This is unfortunate + // both because it's somewhat slow and because, for many applications, + // we then need to reconvert the data back into the vertex-to-bone + // mapping which makes things doubly-slow. + std::vector> weighting(mesh->mNumBones); + BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); - mat4* pbindMatrices = nullptr; - node.skin->inverseBindMatrices->ExtractData(pbindMatrices); + mat4 *pbindMatrices = nullptr; + node.skin->inverseBindMatrices->ExtractData(pbindMatrices); - for (uint32_t i = 0; i < mesh->mNumBones; ++i) { - aiBone* bone = new aiBone(); + for (uint32_t i = 0; i < mesh->mNumBones; ++i) { + aiBone *bone = new aiBone(); - Ref joint = node.skin->jointNames[i]; - if (!joint->name.empty()) { - bone->mName = joint->name; - } else { - // Assimp expects each bone to have a unique name. - static const std::string kDefaultName = "bone_"; - char postfix[10] = {0}; - ASSIMP_itoa10(postfix, i); - bone->mName = (kDefaultName + postfix); - } - GetNodeTransform(bone->mOffsetMatrix, *joint); + Ref joint = node.skin->jointNames[i]; + if (!joint->name.empty()) { + bone->mName = joint->name; + } else { + // Assimp expects each bone to have a unique name. + static const std::string kDefaultName = "bone_"; + char postfix[10] = { 0 }; + ASSIMP_itoa10(postfix, i); + bone->mName = (kDefaultName + postfix); + } + GetNodeTransform(bone->mOffsetMatrix, *joint); - CopyValue(pbindMatrices[i], bone->mOffsetMatrix); + CopyValue(pbindMatrices[i], bone->mOffsetMatrix); - std::vector& weights = weighting[i]; + std::vector &weights = weighting[i]; - bone->mNumWeights = static_cast(weights.size()); - if (bone->mNumWeights > 0) { - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); - } else { - // Assimp expects all bones to have at least 1 weight. - bone->mWeights = new aiVertexWeight[1]; - bone->mNumWeights = 1; - bone->mWeights->mVertexId = 0; - bone->mWeights->mWeight = 0.f; - } - mesh->mBones[i] = bone; - } + bone->mNumWeights = static_cast(weights.size()); + if (bone->mNumWeights > 0) { + bone->mWeights = new aiVertexWeight[bone->mNumWeights]; + memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); + } else { + // Assimp expects all bones to have at least 1 weight. + bone->mWeights = new aiVertexWeight[1]; + bone->mNumWeights = 1; + bone->mWeights->mVertexId = 0; + bone->mWeights->mWeight = 0.f; + } + mesh->mBones[i] = bone; + } - if (pbindMatrices) { - delete[] pbindMatrices; - } - } - } + if (pbindMatrices) { + delete[] pbindMatrices; + } + } + } - int k = 0; - for (unsigned int j = meshOffsets[mesh_idx]; j < meshOffsets[mesh_idx + 1]; ++j, ++k) { - ainode->mMeshes[k] = j; - } - } + int k = 0; + for (unsigned int j = meshOffsets[mesh_idx]; j < meshOffsets[mesh_idx + 1]; ++j, ++k) { + ainode->mMeshes[k] = j; + } + } - if (node.camera) { - pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; - } + if (node.camera) { + pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; + } - if (node.light) { - pScene->mLights[node.light.GetIndex()]->mName = ainode->mName; + if (node.light) { + pScene->mLights[node.light.GetIndex()]->mName = ainode->mName; - //range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual - //it is added to meta data of parent node, because there is no other place to put it - if (node.light->range.isPresent) - { - ainode->mMetaData = aiMetadata::Alloc(1); - ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value); - } - } + //range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual + //it is added to meta data of parent node, because there is no other place to put it + if (node.light->range.isPresent) { + ainode->mMetaData = aiMetadata::Alloc(1); + ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value); + } + } - return ainode; + return ainode; } -void glTF2Importer::ImportNodes(glTF2::Asset& r) -{ - if (!r.scene) return; +void glTF2Importer::ImportNodes(glTF2::Asset &r) { + if (!r.scene) return; - std::vector< Ref > rootNodes = r.scene->nodes; + std::vector> rootNodes = r.scene->nodes; - // The root nodes - unsigned int numRootNodes = unsigned(rootNodes.size()); - if (numRootNodes == 1) { // a single root node: use it - mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); - } - else if (numRootNodes > 1) { // more than one root node: create a fake root - aiNode* root = new aiNode("ROOT"); - root->mChildren = new aiNode*[numRootNodes]; - for (unsigned int i = 0; i < numRootNodes; ++i) { - aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); - node->mParent = root; - root->mChildren[root->mNumChildren++] = node; - } - mScene->mRootNode = root; - } - - //if (!mScene->mRootNode) { - // mScene->mRootNode = new aiNode("EMPTY"); - //} + // The root nodes + unsigned int numRootNodes = unsigned(rootNodes.size()); + if (numRootNodes == 1) { // a single root node: use it + mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); + } else if (numRootNodes > 1) { // more than one root node: create a fake root + aiNode *root = new aiNode("ROOT"); + root->mChildren = new aiNode *[numRootNodes]; + for (unsigned int i = 0; i < numRootNodes; ++i) { + aiNode *node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); + node->mParent = root; + root->mChildren[root->mNumChildren++] = node; + } + mScene->mRootNode = root; + } } struct AnimationSamplers { - AnimationSamplers() - : translation(nullptr) - , rotation(nullptr) - , scale(nullptr) - , weight(nullptr) { - // empty - } + AnimationSamplers() : + translation(nullptr), + rotation(nullptr), + scale(nullptr), + weight(nullptr) { + // empty + } - Animation::Sampler* translation; - Animation::Sampler* rotation; - Animation::Sampler* scale; - Animation::Sampler* weight; + Animation::Sampler *translation; + Animation::Sampler *rotation; + Animation::Sampler *scale; + Animation::Sampler *weight; }; -aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers) -{ - aiNodeAnim* anim = new aiNodeAnim(); - anim->mNodeName = GetNodeName(node); +aiNodeAnim *CreateNodeAnim(glTF2::Asset &r, Node &node, AnimationSamplers &samplers) { + aiNodeAnim *anim = new aiNodeAnim(); + anim->mNodeName = GetNodeName(node); - static const float kMillisecondsFromSeconds = 1000.f; + static const float kMillisecondsFromSeconds = 1000.f; - if (samplers.translation) { - float* times = nullptr; - samplers.translation->input->ExtractData(times); - aiVector3D* values = nullptr; - samplers.translation->output->ExtractData(values); - anim->mNumPositionKeys = static_cast(samplers.translation->input->count); - anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; - for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) { - anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds; - anim->mPositionKeys[i].mValue = values[i]; - } - delete[] times; - delete[] values; - } else if (node.translation.isPresent) { - anim->mNumPositionKeys = 1; - anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; - anim->mPositionKeys->mTime = 0.f; - anim->mPositionKeys->mValue.x = node.translation.value[0]; - anim->mPositionKeys->mValue.y = node.translation.value[1]; - anim->mPositionKeys->mValue.z = node.translation.value[2]; - } + if (samplers.translation) { + float *times = nullptr; + samplers.translation->input->ExtractData(times); + aiVector3D *values = nullptr; + samplers.translation->output->ExtractData(values); + anim->mNumPositionKeys = static_cast(samplers.translation->input->count); + anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; + for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) { + anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds; + anim->mPositionKeys[i].mValue = values[i]; + } + delete[] times; + delete[] values; + } else if (node.translation.isPresent) { + anim->mNumPositionKeys = 1; + anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; + anim->mPositionKeys->mTime = 0.f; + anim->mPositionKeys->mValue.x = node.translation.value[0]; + anim->mPositionKeys->mValue.y = node.translation.value[1]; + anim->mPositionKeys->mValue.z = node.translation.value[2]; + } - if (samplers.rotation) { - float* times = nullptr; - samplers.rotation->input->ExtractData(times); - aiQuaternion* values = nullptr; - samplers.rotation->output->ExtractData(values); - anim->mNumRotationKeys = static_cast(samplers.rotation->input->count); - anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; - for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) { - anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds; - anim->mRotationKeys[i].mValue.x = values[i].w; - anim->mRotationKeys[i].mValue.y = values[i].x; - anim->mRotationKeys[i].mValue.z = values[i].y; - anim->mRotationKeys[i].mValue.w = values[i].z; - } - delete[] times; - delete[] values; - } else if (node.rotation.isPresent) { - anim->mNumRotationKeys = 1; - anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; - anim->mRotationKeys->mTime = 0.f; - anim->mRotationKeys->mValue.x = node.rotation.value[0]; - anim->mRotationKeys->mValue.y = node.rotation.value[1]; - anim->mRotationKeys->mValue.z = node.rotation.value[2]; - anim->mRotationKeys->mValue.w = node.rotation.value[3]; - } + if (samplers.rotation) { + float *times = nullptr; + samplers.rotation->input->ExtractData(times); + aiQuaternion *values = nullptr; + samplers.rotation->output->ExtractData(values); + anim->mNumRotationKeys = static_cast(samplers.rotation->input->count); + anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; + for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) { + anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds; + anim->mRotationKeys[i].mValue.x = values[i].w; + anim->mRotationKeys[i].mValue.y = values[i].x; + anim->mRotationKeys[i].mValue.z = values[i].y; + anim->mRotationKeys[i].mValue.w = values[i].z; + } + delete[] times; + delete[] values; + } else if (node.rotation.isPresent) { + anim->mNumRotationKeys = 1; + anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; + anim->mRotationKeys->mTime = 0.f; + anim->mRotationKeys->mValue.x = node.rotation.value[0]; + anim->mRotationKeys->mValue.y = node.rotation.value[1]; + anim->mRotationKeys->mValue.z = node.rotation.value[2]; + anim->mRotationKeys->mValue.w = node.rotation.value[3]; + } - if (samplers.scale) { - float* times = nullptr; - samplers.scale->input->ExtractData(times); - aiVector3D* values = nullptr; - samplers.scale->output->ExtractData(values); - anim->mNumScalingKeys = static_cast(samplers.scale->input->count); - anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys]; - for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) { - anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds; - anim->mScalingKeys[i].mValue = values[i]; - } - delete[] times; - delete[] values; - } else if (node.scale.isPresent) { - anim->mNumScalingKeys = 1; - anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys]; - anim->mScalingKeys->mTime = 0.f; - anim->mScalingKeys->mValue.x = node.scale.value[0]; - anim->mScalingKeys->mValue.y = node.scale.value[1]; - anim->mScalingKeys->mValue.z = node.scale.value[2]; - } + if (samplers.scale) { + float *times = nullptr; + samplers.scale->input->ExtractData(times); + aiVector3D *values = nullptr; + samplers.scale->output->ExtractData(values); + anim->mNumScalingKeys = static_cast(samplers.scale->input->count); + anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys]; + for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) { + anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds; + anim->mScalingKeys[i].mValue = values[i]; + } + delete[] times; + delete[] values; + } else if (node.scale.isPresent) { + anim->mNumScalingKeys = 1; + anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys]; + anim->mScalingKeys->mTime = 0.f; + anim->mScalingKeys->mValue.x = node.scale.value[0]; + anim->mScalingKeys->mValue.y = node.scale.value[1]; + anim->mScalingKeys->mValue.z = node.scale.value[2]; + } - return anim; + return anim; } -aiMeshMorphAnim* CreateMeshMorphAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers) -{ - aiMeshMorphAnim* anim = new aiMeshMorphAnim(); - anim->mName = GetNodeName(node); +aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset &r, Node &node, AnimationSamplers &samplers) { + aiMeshMorphAnim *anim = new aiMeshMorphAnim(); + anim->mName = GetNodeName(node); - static const float kMillisecondsFromSeconds = 1000.f; + static const float kMillisecondsFromSeconds = 1000.f; - if (nullptr != samplers.weight) { - float* times = nullptr; - samplers.weight->input->ExtractData(times); - float* values = nullptr; - samplers.weight->output->ExtractData(values); - anim->mNumKeys = static_cast(samplers.weight->input->count); + if (nullptr != samplers.weight) { + float *times = nullptr; + samplers.weight->input->ExtractData(times); + float *values = nullptr; + samplers.weight->output->ExtractData(values); + anim->mNumKeys = static_cast(samplers.weight->input->count); - const unsigned int numMorphs = (unsigned int)samplers.weight->output->count / anim->mNumKeys; + const unsigned int numMorphs = (unsigned int)samplers.weight->output->count / anim->mNumKeys; - anim->mKeys = new aiMeshMorphKey[anim->mNumKeys]; - unsigned int k = 0u; - for (unsigned int i = 0u; i < anim->mNumKeys; ++i) { - anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds; - anim->mKeys[i].mNumValuesAndWeights = numMorphs; - anim->mKeys[i].mValues = new unsigned int[numMorphs]; - anim->mKeys[i].mWeights = new double[numMorphs]; + anim->mKeys = new aiMeshMorphKey[anim->mNumKeys]; + unsigned int k = 0u; + for (unsigned int i = 0u; i < anim->mNumKeys; ++i) { + anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds; + anim->mKeys[i].mNumValuesAndWeights = numMorphs; + anim->mKeys[i].mValues = new unsigned int[numMorphs]; + anim->mKeys[i].mWeights = new double[numMorphs]; - for (unsigned int j = 0u; j < numMorphs; ++j, ++k) { - anim->mKeys[i].mValues[j] = j; - anim->mKeys[i].mWeights[j] = ( 0.f > values[k] ) ? 0.f : values[k]; - } - } + for (unsigned int j = 0u; j < numMorphs; ++j, ++k) { + anim->mKeys[i].mValues[j] = j; + anim->mKeys[i].mWeights[j] = (0.f > values[k]) ? 0.f : values[k]; + } + } - delete[] times; - delete[] values; - } + delete[] times; + delete[] values; + } - return anim; + return anim; } -std::unordered_map GatherSamplers(Animation& anim) -{ - std::unordered_map samplers; - for (unsigned int c = 0; c < anim.channels.size(); ++c) { - Animation::Channel& channel = anim.channels[c]; - if (channel.sampler >= static_cast(anim.samplers.size())) { - continue; - } +std::unordered_map GatherSamplers(Animation &anim) { + std::unordered_map samplers; + for (unsigned int c = 0; c < anim.channels.size(); ++c) { + Animation::Channel &channel = anim.channels[c]; + if (channel.sampler >= static_cast(anim.samplers.size())) { + continue; + } - const unsigned int node_index = channel.target.node.GetIndex(); + const unsigned int node_index = channel.target.node.GetIndex(); - AnimationSamplers& sampler = samplers[node_index]; - if (channel.target.path == AnimationPath_TRANSLATION) { - sampler.translation = &anim.samplers[channel.sampler]; - } else if (channel.target.path == AnimationPath_ROTATION) { - sampler.rotation = &anim.samplers[channel.sampler]; - } else if (channel.target.path == AnimationPath_SCALE) { - sampler.scale = &anim.samplers[channel.sampler]; - } else if (channel.target.path == AnimationPath_WEIGHTS) { - sampler.weight = &anim.samplers[channel.sampler]; - } - } + AnimationSamplers &sampler = samplers[node_index]; + if (channel.target.path == AnimationPath_TRANSLATION) { + sampler.translation = &anim.samplers[channel.sampler]; + } else if (channel.target.path == AnimationPath_ROTATION) { + sampler.rotation = &anim.samplers[channel.sampler]; + } else if (channel.target.path == AnimationPath_SCALE) { + sampler.scale = &anim.samplers[channel.sampler]; + } else if (channel.target.path == AnimationPath_WEIGHTS) { + sampler.weight = &anim.samplers[channel.sampler]; + } + } - return samplers; + return samplers; } -void glTF2Importer::ImportAnimations(glTF2::Asset& r) -{ - if (!r.scene) return; +void glTF2Importer::ImportAnimations(glTF2::Asset &r) { + if (!r.scene) return; - mScene->mNumAnimations = r.animations.Size(); - if (mScene->mNumAnimations == 0) { - return; - } + mScene->mNumAnimations = r.animations.Size(); + if (mScene->mNumAnimations == 0) { + return; + } - mScene->mAnimations = new aiAnimation*[mScene->mNumAnimations]; - for (unsigned int i = 0; i < r.animations.Size(); ++i) { - Animation& anim = r.animations[i]; + mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations]; + for (unsigned int i = 0; i < r.animations.Size(); ++i) { + Animation &anim = r.animations[i]; - aiAnimation* ai_anim = new aiAnimation(); - ai_anim->mName = anim.name; - ai_anim->mDuration = 0; - ai_anim->mTicksPerSecond = 0; + aiAnimation *ai_anim = new aiAnimation(); + ai_anim->mName = anim.name; + ai_anim->mDuration = 0; + ai_anim->mTicksPerSecond = 0; - std::unordered_map samplers = GatherSamplers(anim); + std::unordered_map samplers = GatherSamplers(anim); - uint32_t numChannels = 0u; - uint32_t numMorphMeshChannels = 0u; + uint32_t numChannels = 0u; + uint32_t numMorphMeshChannels = 0u; - for (auto& iter : samplers) { - if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) { - ++numChannels; - } - if (nullptr != iter.second.weight) { - ++numMorphMeshChannels; - } - } + for (auto &iter : samplers) { + if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) { + ++numChannels; + } + if (nullptr != iter.second.weight) { + ++numMorphMeshChannels; + } + } - ai_anim->mNumChannels = numChannels; - if (ai_anim->mNumChannels > 0) { - ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels]; - int j = 0; - for (auto& iter : samplers) { - if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) { - ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second); - ++j; - } - } - } + ai_anim->mNumChannels = numChannels; + if (ai_anim->mNumChannels > 0) { + ai_anim->mChannels = new aiNodeAnim *[ai_anim->mNumChannels]; + int j = 0; + for (auto &iter : samplers) { + if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) { + ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second); + ++j; + } + } + } - ai_anim->mNumMorphMeshChannels = numMorphMeshChannels; - if (ai_anim->mNumMorphMeshChannels > 0) { - ai_anim->mMorphMeshChannels = new aiMeshMorphAnim*[ai_anim->mNumMorphMeshChannels]; - int j = 0; - for (auto& iter : samplers) { - if (nullptr != iter.second.weight) { - ai_anim->mMorphMeshChannels[j] = CreateMeshMorphAnim(r, r.nodes[iter.first], iter.second); - ++j; - } - } - } + ai_anim->mNumMorphMeshChannels = numMorphMeshChannels; + if (ai_anim->mNumMorphMeshChannels > 0) { + ai_anim->mMorphMeshChannels = new aiMeshMorphAnim *[ai_anim->mNumMorphMeshChannels]; + int j = 0; + for (auto &iter : samplers) { + if (nullptr != iter.second.weight) { + ai_anim->mMorphMeshChannels[j] = CreateMeshMorphAnim(r, r.nodes[iter.first], iter.second); + ++j; + } + } + } - // Use the latest keyframe for the duration of the animation - double maxDuration = 0; - unsigned int maxNumberOfKeys = 0; - for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) { - auto chan = ai_anim->mChannels[j]; - if (chan->mNumPositionKeys) { - auto lastPosKey = chan->mPositionKeys[chan->mNumPositionKeys - 1]; - if (lastPosKey.mTime > maxDuration) { - maxDuration = lastPosKey.mTime; - } - maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumPositionKeys); - } - if (chan->mNumRotationKeys) { - auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1]; - if (lastRotKey.mTime > maxDuration) { - maxDuration = lastRotKey.mTime; - } - maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumRotationKeys); - } - if (chan->mNumScalingKeys) { - auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1]; - if (lastScaleKey.mTime > maxDuration) { - maxDuration = lastScaleKey.mTime; - } - maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumScalingKeys); - } - } + // Use the latest keyframe for the duration of the animation + double maxDuration = 0; + unsigned int maxNumberOfKeys = 0; + for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) { + auto chan = ai_anim->mChannels[j]; + if (chan->mNumPositionKeys) { + auto lastPosKey = chan->mPositionKeys[chan->mNumPositionKeys - 1]; + if (lastPosKey.mTime > maxDuration) { + maxDuration = lastPosKey.mTime; + } + maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumPositionKeys); + } + if (chan->mNumRotationKeys) { + auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1]; + if (lastRotKey.mTime > maxDuration) { + maxDuration = lastRotKey.mTime; + } + maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumRotationKeys); + } + if (chan->mNumScalingKeys) { + auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1]; + if (lastScaleKey.mTime > maxDuration) { + maxDuration = lastScaleKey.mTime; + } + maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumScalingKeys); + } + } - for (unsigned int j = 0; j < ai_anim->mNumMorphMeshChannels; ++j) { - const auto* const chan = ai_anim->mMorphMeshChannels[j]; + for (unsigned int j = 0; j < ai_anim->mNumMorphMeshChannels; ++j) { + const auto *const chan = ai_anim->mMorphMeshChannels[j]; - if (0u != chan->mNumKeys) { - const auto& lastKey = chan->mKeys[chan->mNumKeys - 1u]; - if (lastKey.mTime > maxDuration) { - maxDuration = lastKey.mTime; - } - maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumKeys); - } - } + if (0u != chan->mNumKeys) { + const auto &lastKey = chan->mKeys[chan->mNumKeys - 1u]; + if (lastKey.mTime > maxDuration) { + maxDuration = lastKey.mTime; + } + maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumKeys); + } + } - ai_anim->mDuration = maxDuration; - ai_anim->mTicksPerSecond = 1000.0; + ai_anim->mDuration = maxDuration; + ai_anim->mTicksPerSecond = 1000.0; - mScene->mAnimations[i] = ai_anim; - } + mScene->mAnimations[i] = ai_anim; + } } -void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r) -{ - embeddedTexIdxs.resize(r.images.Size(), -1); +void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { + embeddedTexIdxs.resize(r.images.Size(), -1); - int numEmbeddedTexs = 0; - for (size_t i = 0; i < r.images.Size(); ++i) { - if (r.images[i].HasData()) - numEmbeddedTexs += 1; - } + int numEmbeddedTexs = 0; + for (size_t i = 0; i < r.images.Size(); ++i) { + if (r.images[i].HasData()) + numEmbeddedTexs += 1; + } - if (numEmbeddedTexs == 0) - return; + if (numEmbeddedTexs == 0) + return; - mScene->mTextures = new aiTexture*[numEmbeddedTexs]; + mScene->mTextures = new aiTexture *[numEmbeddedTexs]; - // Add the embedded textures - for (size_t i = 0; i < r.images.Size(); ++i) { - Image &img = r.images[i]; - if (!img.HasData()) continue; + // Add the embedded textures + for (size_t i = 0; i < r.images.Size(); ++i) { + Image &img = r.images[i]; + if (!img.HasData()) continue; - int idx = mScene->mNumTextures++; - embeddedTexIdxs[i] = idx; + int idx = mScene->mNumTextures++; + embeddedTexIdxs[i] = idx; - aiTexture* tex = mScene->mTextures[idx] = new aiTexture(); + aiTexture *tex = mScene->mTextures[idx] = new aiTexture(); - size_t length = img.GetDataLength(); - void* data = img.StealData(); + size_t length = img.GetDataLength(); + void *data = img.StealData(); - tex->mWidth = static_cast(length); - tex->mHeight = 0; - tex->pcData = reinterpret_cast(data); + tex->mWidth = static_cast(length); + tex->mHeight = 0; + tex->pcData = reinterpret_cast(data); - if (!img.mimeType.empty()) { - const char* ext = strchr(img.mimeType.c_str(), '/') + 1; - if (ext) { - if (strcmp(ext, "jpeg") == 0) ext = "jpg"; + if (!img.mimeType.empty()) { + const char *ext = strchr(img.mimeType.c_str(), '/') + 1; + if (ext) { + if (strcmp(ext, "jpeg") == 0) ext = "jpg"; - size_t len = strlen(ext); - if (len <= 3) { - strcpy(tex->achFormatHint, ext); - } - } - } - } + size_t len = strlen(ext); + if (len <= 3) { + strcpy(tex->achFormatHint, ext); + } + } + } + } } -void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - // clean all member arrays - meshOffsets.clear(); - embeddedTexIdxs.clear(); +void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { + // clean all member arrays + meshOffsets.clear(); + embeddedTexIdxs.clear(); - this->mScene = pScene; + this->mScene = pScene; - // read the asset file - glTF2::Asset asset(pIOHandler); - asset.Load(pFile, GetExtension(pFile) == "glb"); + // read the asset file + glTF2::Asset asset(pIOHandler); + asset.Load(pFile, GetExtension(pFile) == "glb"); - // - // Copy the data out - // + // + // Copy the data out + // - ImportEmbeddedTextures(asset); - ImportMaterials(asset); + ImportEmbeddedTextures(asset); + ImportMaterials(asset); - ImportMeshes(asset); + ImportMeshes(asset); - ImportCameras(asset); - ImportLights(asset); + ImportCameras(asset); + ImportLights(asset); - ImportNodes(asset); + ImportNodes(asset); - ImportAnimations(asset); + ImportAnimations(asset); - if (pScene->mNumMeshes == 0) { - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } + if (pScene->mNumMeshes == 0) { + pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + } } #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER - From 17257cd2aeed5de4b86b95fc258f79436a860ff2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 16 Nov 2019 15:51:26 +0100 Subject: [PATCH 079/170] just a try, i dunno have a clue ... --- code/Common/DefaultLogger.cpp | 4 ++-- code/Material/MaterialSystem.cpp | 6 +++--- code/PostProcessing/ValidateDataStructure.cpp | 11 +++++++---- code/glTF2/glTF2Importer.cpp | 6 +++--- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/code/Common/DefaultLogger.cpp b/code/Common/DefaultLogger.cpp index de3528d2b..eee53bd7c 100644 --- a/code/Common/DefaultLogger.cpp +++ b/code/Common/DefaultLogger.cpp @@ -107,7 +107,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, return nullptr; #endif - // Platform-independent default streams + // Platform-independent default streams case aiDefaultLogStream_STDERR: return new StdOStreamLogStream(std::cerr); case aiDefaultLogStream_STDOUT: @@ -121,7 +121,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, }; // For compilers without dead code path detection - return NULL; + return nullptr; } // ---------------------------------------------------------------------------------- diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index 0be6e9f7b..fabd9415a 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -471,12 +471,12 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput, aiPropertyTypeInfo pType ) { - ai_assert( pInput != NULL ); - ai_assert( pKey != NULL ); + ai_assert( pInput != nullptr ); + ai_assert(pKey != nullptr ); ai_assert( 0 != pSizeInBytes ); if ( 0 == pSizeInBytes ) { - + return AI_FAILURE; } // first search the list whether there is already an entry with this key diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index 75d1b6ef7..b7f56a582 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -603,15 +603,18 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, ReportError("%s #%i is set, but there are only %i %s textures", szType,iIndex,iNumIndices,szType); } - if (!iNumIndices)return; + if (!iNumIndices) { + return; + } std::vector mappings(iNumIndices); // Now check whether all UV indices are valid ... bool bNoSpecified = true; - for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) - { + for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) { aiMaterialProperty* prop = pMaterial->mProperties[i]; - if (prop->mSemantic != type)continue; + if (prop->mSemantic != type) { + continue; + } if ((int)prop->mIndex >= iNumIndices) { diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 3dffa4b27..584a2717f 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -200,6 +200,9 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); } + mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); + mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); + if (prop.textureTransformSupported) { aiUVTransform transform; transform.mTranslation.x = prop.TextureTransformExt_t.offset[0]; @@ -210,9 +213,6 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot); } - mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); - mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); - if (prop.texture->sampler) { Ref sampler = prop.texture->sampler; From 75204e20bdc9a2a71cc1c183d14c549576e3d1f4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 16 Nov 2019 19:22:37 +0100 Subject: [PATCH 080/170] fix invalid setup for texture enum. --- code/glTF2/glTF2Importer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 584a2717f..43eabdab7 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -201,7 +201,6 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset } mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); - mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); if (prop.textureTransformSupported) { aiUVTransform transform; From 41ae01a6b2545699a2d5ec1b93e20f957e5fe3cc Mon Sep 17 00:00:00 2001 From: bzt Date: Mon, 18 Nov 2019 03:04:52 +0100 Subject: [PATCH 081/170] Upgraded to newest SDK and improved texture import --- code/M3D/M3DExporter.cpp | 37 +- code/M3D/M3DExporter.h | 2 + code/M3D/M3DImporter.cpp | 64 +- code/M3D/M3DMaterials.h | 4 +- code/M3D/m3d.h | 2287 ++++++++++++++++++++++--------- test/unit/utM3DImportExport.cpp | 2 +- 6 files changed, 1745 insertions(+), 651 deletions(-) diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index c22943396..b1c7ebdba 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -169,6 +169,33 @@ void M3DExporter::doExport ( outfile.reset(); } + +// ------------------------------------------------------------------------------------------------ +// helper to add a vertex (private to NodeWalk) +m3dv_t *M3DExporter::AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) +{ + if(v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0; + if(v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0; + if(v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0; + if(v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0; + vrtx = (m3dv_t*)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t)); + memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t)); + *idx = *numvrtx; + (*numvrtx)++; + return vrtx; +} + +// ------------------------------------------------------------------------------------------------ +// helper to add a tmap (private to NodeWalk) +m3dti_t *M3DExporter::AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx) +{ + tmap = (m3dti_t*)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t)); + memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t)); + *idx = *numtmap; + (*numtmap)++; + return tmap; +} + // ------------------------------------------------------------------------------------------------ // recursive node walker void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) @@ -221,25 +248,23 @@ void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) if(mesh->HasVertexColors(0)) vertex.color = mkColor(&mesh->mColors[0][l]); // save the vertex to the output - m3d->vertex = _m3d_addvrtx(m3d->vertex, &m3d->numvertex, + m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx); m3d->face[n].vertex[k] = (M3D_INDEX)idx; // do we have texture coordinates? if(mesh->HasTextureCoords(0)) { ti.u = mesh->mTextureCoords[0][l].x; ti.v = mesh->mTextureCoords[0][l].y; - m3d->tmap = _m3d_addtmap(m3d->tmap, &m3d->numtmap, &ti, - &idx); + m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx); m3d->face[n].texcoord[k] = (M3D_INDEX)idx; } // do we have normal vectors? if(mesh->HasNormals()) { - vertex.color = 0; vertex.x = mesh->mNormals[l].x; vertex.y = mesh->mNormals[l].y; vertex.z = mesh->mNormals[l].z; - m3d->vertex = _m3d_addnorm(m3d->vertex, &m3d->numvertex, - &vertex, &idx); + vertex.color = 0; + m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx); m3d->face[n].normal[k] = (M3D_INDEX)idx; } } diff --git a/code/M3D/M3DExporter.h b/code/M3D/M3DExporter.h index dfcff8bc9..58d8d597e 100644 --- a/code/M3D/M3DExporter.h +++ b/code/M3D/M3DExporter.h @@ -87,6 +87,8 @@ namespace Assimp // helper to do the recursive walking void NodeWalk(const aiNode* pNode, aiMatrix4x4 m); + m3dv_t *AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx); + m3dti_t *AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx); uint32_t mkColor(aiColor4D* c); M3D_INDEX addMaterial(const aiMaterial *mat); void addProp(m3dm_t *m, uint8_t type, uint32_t value); diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index fcff49df7..0156950c3 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -44,6 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define M3D_IMPLEMENTATION #define M3D_ASCII +#define M3D_NONORMALS /* leave the post-processing to Assimp */ +#define M3D_NOWEIGHTS +#define M3D_NOANIMATION #include #include @@ -104,16 +107,21 @@ extern "C" { std::string file(fn); std::unique_ptr pStream( (reinterpret_cast(m3dimporter_pIOHandler))->Open( file, "rb")); - size_t fileSize = pStream->FileSize(); - // should be allocated with malloc(), because the library will call free() to deallocate - unsigned char *data = (unsigned char*)malloc(fileSize); - if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) { + size_t fileSize = 0; + unsigned char *data = NULL; + // sometimes pStream is nullptr for some reason (should be an empty object returning nothing I guess) + if(pStream) { + fileSize = pStream->FileSize(); + // should be allocated with malloc(), because the library will call free() to deallocate + data = (unsigned char*)malloc(fileSize); + if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) { + pStream.reset(); + *size = 0; + // don't throw a deadly exception, it's not fatal if we can't read an external asset + return nullptr; + } pStream.reset(); - *size = 0; - // don't throw a deadly exception, it's not fatal if we can't read an external asset - return nullptr; } - pStream.reset(); *size = (int)fileSize; return data; } @@ -307,7 +315,7 @@ void M3DImporter::importMaterials() m->prop[j].value.textureid < m3d->numtexture && m3d->texture[m->prop[j].value.textureid].name) { name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); - mat->AddProperty(&name, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index); n = 0; mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); } @@ -321,6 +329,7 @@ void M3DImporter::importMaterials() void M3DImporter::importTextures() { unsigned int i; + const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" }; m3dtx_t *t; ai_assert(mScene != nullptr); @@ -334,14 +343,29 @@ void M3DImporter::importTextures() mScene->mTextures = new aiTexture*[m3d->numtexture]; for(i = 0; i < m3d->numtexture; i++) { + unsigned int j, k; t = &m3d->texture[i]; + if(!t->w || !t->h || !t->f || !t->d) continue; aiTexture *tx = new aiTexture; - strcpy(tx->achFormatHint, "rgba8888"); + strcpy(tx->achFormatHint, formatHint[t->f - 1]); tx->mFilename = aiString(std::string(t->name) + ".png"); tx->mWidth = t->w; tx->mHeight = t->h; tx->pcData = new aiTexel[ tx->mWidth*tx->mHeight ]; - memcpy(tx->pcData, t->d, tx->mWidth*tx->mHeight*4); + for(j = k = 0; j < tx->mWidth*tx->mHeight; j++) { + switch(t->f) { + case 1: tx->pcData[j].g = t->d[k++]; break; + case 2: tx->pcData[j].g = t->d[k++]; tx->pcData[j].a = t->d[k++]; break; + case 3: + tx->pcData[j].r = t->d[k++]; tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; tx->pcData[j].a = 255; + break; + case 4: + tx->pcData[j].r = t->d[k++]; tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; tx->pcData[j].a = t->d[k++]; + break; + } + } mScene->mTextures[i] = tx; } } @@ -574,15 +598,15 @@ void M3DImporter::convertPose(aiMatrix4x4 *m, unsigned int posid, unsigned int o m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0; m->a1 = m->b2 = m->c3 = -1.0; } else { - m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); if(m->a1 > -1e-7 && m->a1 < 1e-7) m->a1 = 0.0; - m->a2 = 2 * (q->x * q->y - q->z * q->w); if(m->a2 > -1e-7 && m->a2 < 1e-7) m->a2 = 0.0; - m->a3 = 2 * (q->x * q->z + q->y * q->w); if(m->a3 > -1e-7 && m->a3 < 1e-7) m->a3 = 0.0; - m->b1 = 2 * (q->x * q->y + q->z * q->w); if(m->b1 > -1e-7 && m->b1 < 1e-7) m->b1 = 0.0; - m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); if(m->b2 > -1e-7 && m->b2 < 1e-7) m->b2 = 0.0; - m->b3 = 2 * (q->y * q->z - q->x * q->w); if(m->b3 > -1e-7 && m->b3 < 1e-7) m->b3 = 0.0; - m->c1 = 2 * (q->x * q->z - q->y * q->w); if(m->c1 > -1e-7 && m->c1 < 1e-7) m->c1 = 0.0; - m->c2 = 2 * (q->y * q->z + q->x * q->w); if(m->c2 > -1e-7 && m->c2 < 1e-7) m->c2 = 0.0; - m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); if(m->c3 > -1e-7 && m->c3 < 1e-7) m->c3 = 0.0; + m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); if(m->a1 > -M3D_EPSILON && m->a1 < M3D_EPSILON) m->a1 = 0.0; + m->a2 = 2 * (q->x * q->y - q->z * q->w); if(m->a2 > -M3D_EPSILON && m->a2 < M3D_EPSILON) m->a2 = 0.0; + m->a3 = 2 * (q->x * q->z + q->y * q->w); if(m->a3 > -M3D_EPSILON && m->a3 < M3D_EPSILON) m->a3 = 0.0; + m->b1 = 2 * (q->x * q->y + q->z * q->w); if(m->b1 > -M3D_EPSILON && m->b1 < M3D_EPSILON) m->b1 = 0.0; + m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); if(m->b2 > -M3D_EPSILON && m->b2 < M3D_EPSILON) m->b2 = 0.0; + m->b3 = 2 * (q->y * q->z - q->x * q->w); if(m->b3 > -M3D_EPSILON && m->b3 < M3D_EPSILON) m->b3 = 0.0; + m->c1 = 2 * (q->x * q->z - q->y * q->w); if(m->c1 > -M3D_EPSILON && m->c1 < M3D_EPSILON) m->c1 = 0.0; + m->c2 = 2 * (q->y * q->z + q->x * q->w); if(m->c2 > -M3D_EPSILON && m->c2 < M3D_EPSILON) m->c2 = 0.0; + m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); if(m->c3 > -M3D_EPSILON && m->c3 < M3D_EPSILON) m->c3 = 0.0; } /* set translation */ diff --git a/code/M3D/M3DMaterials.h b/code/M3D/M3DMaterials.h index fa02cf42b..3d6fe246d 100644 --- a/code/M3D/M3DMaterials.h +++ b/code/M3D/M3DMaterials.h @@ -75,7 +75,7 @@ static const aiMatProp aiProps[] = { { AI_MATKEY_REFLECTIVITY }, /* m3dp_Pm */ { NULL, 0, 0 }, /* m3dp_Ps */ { AI_MATKEY_REFRACTI }, /* m3dp_Ni */ - { NULL, 0, 0 }, + { NULL, 0, 0 }, /* m3dp_Nt */ { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 } @@ -97,7 +97,7 @@ static const aiMatProp aiTxProps[] = { { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */ { NULL, 0, 0 }, /* m3dp_map_Ps */ { AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION,0) },/* m3dp_map_Ni */ - { NULL, 0, 0 }, + { NULL, 0, 0 }, /* m3dp_map_Nt */ { NULL, 0, 0 }, { NULL, 0, 0 }, { NULL, 0, 0 } diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 9ace802ef..767e15d5a 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -58,8 +58,15 @@ extern "C" { #define M3D_APIVERSION 0x0100 #ifndef M3D_DOUBLE typedef float M3D_FLOAT; +#ifndef M3D_EPSILON +/* carefully choosen for IEEE 754 don't change */ +#define M3D_EPSILON ((M3D_FLOAT)1e-7) +#endif #else typedef double M3D_FLOAT; +#ifndef M3D_EPSILON +#define M3D_EPSILON ((M3D_FLOAT)1e-14) +#endif #endif #if !defined(M3D_SMALLINDEX) typedef uint32_t M3D_INDEX; @@ -96,23 +103,35 @@ typedef uint16_t M3D_INDEX; * 3DMO m3dchunk_t file header chunk, may followed by compressed data * HEAD m3dhdr_t model header chunk * n x m3dchunk_t more chunks follow + * PRVW preview chunk (optional) * CMAP color map chunk (optional) * TMAP texture map chunk (optional) * VRTS vertex data chunk (optional if it's a material library) * BONE bind-pose skeleton, bone hierarchy chunk (optional) * n x m3db_t contains propably more, but at least one bone + * n x m3ds_t skin group records * MTRL* material chunk(s), can be more (optional) * n x m3dp_t each material contains propapbly more, but at least one property * the properties are configurable with a static array, see m3d_propertytypes * n x m3dchunk_t at least one, but maybe more face chunks * PROC* procedural face, or - * MESH* triangle mesh (vertex index list) + * MESH* triangle mesh (vertex index list) or + * SHPE* mathematical shapes like parameterized surfaces + * LBLS* annotation label chunks, can be more (optional) * ACTN* action chunk(s), animation-pose skeletons, can be more (optional) * n x m3dfr_t each action contains probably more, but at least one frame * n x m3dtr_t each frame contains probably more, but at least one transformation * ASET* inlined asset chunk(s), can be more (optional) * OMD3 end chunk + * + * Typical chunks for a game engine: 3DMO, HEAD, CMAP, TMAP, VRTS, BONE, MTRL, MESH, ACTN, OMD3 + * Typical chunks for CAD software: 3DMO, HEAD, PRVW, CMAP, TMAP, VRTS, MTRL, SHPE, LBLS, OMD3 */ +#ifdef _MSC_VER +#pragma pack(push) +#pragma pack(1) +#endif + typedef struct { char magic[4]; uint32_t length; @@ -125,6 +144,10 @@ typedef struct { uint32_t length; } _pack m3dchunk_t; +#ifdef _MSC_VER +#pragma pack(pop) +#endif + /*** in-memory model structure ***/ /* textmap entry */ @@ -132,19 +155,23 @@ typedef struct { M3D_FLOAT u; M3D_FLOAT v; } m3dti_t; +#define m3d_textureindex_t m3dti_t /* texture */ typedef struct { char *name; /* texture name */ - uint32_t *d; /* pixels data */ + uint8_t *d; /* pixels data */ uint16_t w; /* width */ uint16_t h; /* height */ -} _pack m3dtx_t; + uint8_t f; /* format, 1 = grayscale, 2 = grayscale+alpha, 3 = rgb, 4 = rgba */ +} m3dtx_t; +#define m3d_texturedata_t m3dtx_t typedef struct { M3D_INDEX vertexid; M3D_FLOAT weight; } m3dw_t; +#define m3d_weight_t m3dw_t /* bone entry */ typedef struct { @@ -156,12 +183,14 @@ typedef struct { m3dw_t *weight; /* weights for those vertices */ M3D_FLOAT mat4[16]; /* transformation matrix */ } m3db_t; +#define m3d_bone_t m3db_t /* skin: bone per vertex entry */ typedef struct { M3D_INDEX boneid[M3D_NUMBONE]; M3D_FLOAT weight[M3D_NUMBONE]; } m3ds_t; +#define m3d_skin_t m3ds_t /* vertex entry */ typedef struct { @@ -171,7 +200,11 @@ typedef struct { M3D_FLOAT w; uint32_t color; /* default vertex color */ M3D_INDEX skinid; /* skin index */ +#ifdef M3D_VERTEXTYPE + uint8_t type; +#endif } m3dv_t; +#define m3d_vertex_t m3dv_t /* material property formats */ enum { @@ -210,6 +243,7 @@ enum { m3dp_Pm, m3dp_Ps, m3dp_Ni, + m3dp_Nt, m3dp_map_Kd = 128, /* textured display map properties */ m3dp_map_Ka, @@ -224,7 +258,8 @@ enum { m3dp_map_Pr = 192, /* textured physical map properties */ m3dp_map_Pm, m3dp_map_Ps, - m3dp_map_Ni + m3dp_map_Ni, + m3dp_map_Nt }; enum { /* aliases */ m3dp_bump = m3dp_map_Km, @@ -241,6 +276,7 @@ typedef struct { M3D_INDEX textureid; /* if value is a texture, m3dpf_map */ } value; } m3dp_t; +#define m3d_property_t m3dp_t /* material entry */ typedef struct { @@ -248,6 +284,7 @@ typedef struct { uint8_t numprop; /* number of properties */ m3dp_t *prop; /* properties array */ } m3dm_t; +#define m3d_material_t m3dm_t /* face entry */ typedef struct { @@ -256,6 +293,107 @@ typedef struct { M3D_INDEX normal[3]; /* normal vectors */ M3D_INDEX texcoord[3]; /* UV coordinates */ } m3df_t; +#define m3d_face_t m3df_t + +/* shape command types. must match the row in m3d_commandtypes */ +enum { + /* special commands */ + m3dc_use = 0, /* use material */ + m3dc_inc, /* include another shape */ + m3dc_mesh, /* include part of polygon mesh */ + /* approximations */ + m3dc_div, /* subdivision by constant resolution for both u, v */ + m3dc_sub, /* subdivision by constant, different for u and v */ + m3dc_len, /* spacial subdivision by maxlength */ + m3dc_dist, /* subdivision by maxdistance and maxangle */ + /* modifiers */ + m3dc_degu, /* degree for both u, v */ + m3dc_deg, /* separate degree for u and v */ + m3dc_rangeu, /* range for u */ + m3dc_range, /* range for u and v */ + m3dc_paru, /* u parameters (knots) */ + m3dc_parv, /* v parameters */ + m3dc_trim, /* outer trimming curve */ + m3dc_hole, /* inner trimming curve */ + m3dc_scrv, /* spacial curve */ + m3dc_sp, /* special points */ + /* helper curves */ + m3dc_bez1, /* Bezier 1D */ + m3dc_bsp1, /* B-spline 1D */ + m3dc_bez2, /* bezier 2D */ + m3dc_bsp2, /* B-spline 2D */ + /* surfaces */ + m3dc_bezun, /* Bezier 3D with control, UV, normal */ + m3dc_bezu, /* with control and UV */ + m3dc_bezn, /* with control and normal */ + m3dc_bez, /* control points only */ + m3dc_nurbsun, /* B-spline 3D */ + m3dc_nurbsu, + m3dc_nurbsn, + m3dc_nurbs, + m3dc_conn, /* connect surfaces */ + /* geometrical */ + m3dc_line, + m3dc_polygon, + m3dc_circle, + m3dc_cylinder, + m3dc_shpere, + m3dc_torus, + m3dc_cube +}; + +/* shape command argument types */ +enum { + m3dcp_mi_t = 1, /* material index */ + m3dcp_hi_t, /* shape index */ + m3dcp_fi_t, /* face index */ + m3dcp_ti_t, /* texture map index */ + m3dcp_vi_t, /* vertex index */ + m3dcp_qi_t, /* vertex index for quaternions */ + m3dcp_vc_t, /* coordinate or radius, float scalar */ + m3dcp_i1_t, /* int8 scalar */ + m3dcp_i2_t, /* int16 scalar */ + m3dcp_i4_t, /* int32 scalar */ + m3dcp_va_t /* variadic arguments */ +}; + +#define M3D_CMDMAXARG 8 /* if you increase this, add more arguments to the macro below */ +typedef struct { +#ifdef M3D_ASCII +#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } } + char *key; +#else +#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } } +#endif + uint8_t p; + uint8_t a[M3D_CMDMAXARG]; +} m3dcd_t; + +/* shape command */ +typedef struct { + uint16_t type; /* shape type */ + uint32_t *arg; /* arguments array */ +} m3dc_t; +#define m3d_shapecommand_t m3dc_t + +/* shape entry */ +typedef struct { + char *name; /* name of the mathematical shape */ + M3D_INDEX group; /* group this shape belongs to or -1 */ + uint32_t numcmd; /* number of commands */ + m3dc_t *cmd; /* commands array */ +} m3dh_t; +#define m3d_shape_t m3dh_t + +/* label entry */ +typedef struct { + char *name; /* name of the annotation group or NULL */ + char *lang; /* language code or NULL */ + char *text; /* the label text */ + uint32_t color; /* color */ + M3D_INDEX vertexid; /* the vertex the label refers to */ +} m3dl_t; +#define m3d_label_t m3dl_t /* frame transformations / working copy skeleton entry */ typedef struct { @@ -263,6 +401,7 @@ typedef struct { M3D_INDEX pos; /* vertex index new position */ M3D_INDEX ori; /* vertex index new orientation (quaternion) */ } m3dtr_t; +#define m3d_transform_t m3dtr_t /* animation frame entry */ typedef struct { @@ -270,6 +409,7 @@ typedef struct { M3D_INDEX numtransform; /* number of transformations in this frame */ m3dtr_t *transform; /* transformations */ } m3dfr_t; +#define m3d_frame_t m3dfr_t /* model action entry */ typedef struct { @@ -278,6 +418,7 @@ typedef struct { M3D_INDEX numframe; /* number of frames in this animation */ m3dfr_t *frame; /* frames array */ } m3da_t; +#define m3d_action_t m3da_t /* inlined asset */ typedef struct { @@ -285,17 +426,19 @@ typedef struct { uint8_t *data; /* compressed asset data */ uint32_t length; /* compressed data length */ } m3di_t; +#define m3d_inlinedasset_t m3di_t /*** in-memory model structure ***/ #define M3D_FLG_FREERAW (1<<0) #define M3D_FLG_FREESTR (1<<1) #define M3D_FLG_MTLLIB (1<<2) +#define M3D_FLG_GENNORM (1<<3) typedef struct { m3dhdr_t *raw; /* pointer to raw data */ char flags; /* internal flags */ char errcode; /* returned error code */ - char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fi_s; /* decoded sizes for types */ + char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s,fi_s; /* decoded sizes for types */ char *name; /* name of the model, like "Utah teapot" */ char *license; /* usage condition or license, like "MIT", "LGPL" or "BSD-3clause" */ char *author; /* nickname, email, homepage or github URL etc. */ @@ -316,13 +459,18 @@ typedef struct { M3D_INDEX nummaterial; m3dm_t *material; /* material list */ M3D_INDEX numface; - m3df_t *face; /* model face, triangle mesh */ + m3df_t *face; /* model face, polygon (triangle) mesh */ + M3D_INDEX numshape; + m3dh_t *shape; /* model face, shape commands */ + M3D_INDEX numlabel; + m3dl_t *label; /* annotation labels */ M3D_INDEX numaction; m3da_t *action; /* action animations */ M3D_INDEX numinlined; m3di_t *inlined; /* inlined assets */ - M3D_INDEX numunknown; - m3dchunk_t **unknown; /* unknown chunks, application / engine specific data probably */ + M3D_INDEX numextra; + m3dchunk_t **extra; /* unknown chunks, application / engine specific data probably */ + m3di_t preview; /* preview chunk */ } m3d_t; /*** export parameters ***/ @@ -355,12 +503,14 @@ typedef struct { #define M3D_ERR_UNKMESH -67 #define M3D_ERR_UNKIMG -68 #define M3D_ERR_UNKFRAME -69 -#define M3D_ERR_TRUNC -70 -#define M3D_ERR_CMAP -71 -#define M3D_ERR_TMAP -72 -#define M3D_ERR_VRTS -73 -#define M3D_ERR_BONE -74 -#define M3D_ERR_MTRL -75 +#define M3D_ERR_UNKCMD -70 +#define M3D_ERR_TRUNC -71 +#define M3D_ERR_CMAP -72 +#define M3D_ERR_TMAP -73 +#define M3D_ERR_VRTS -74 +#define M3D_ERR_BONE -75 +#define M3D_ERR_MTRL -76 +#define M3D_ERR_SHPE -77 #define M3D_ERR_ISFATAL(x) ((x) < 0 && (x) > -65) @@ -381,8 +531,6 @@ m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec); /* private prototypes used by both importer and exporter */ -m3ds_t *_m3d_addskin(m3ds_t *skin, uint32_t *numskin, m3ds_t *s, uint32_t *idx); -m3dv_t *_m3d_addnorm(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx); char *_m3d_safestr(char *in, int morelines); /*** C implementation ***/ @@ -404,11 +552,58 @@ static m3dpd_t m3d_propertytypes[] = { M3D_PROPERTYDEF(m3dpf_float, m3dp_Pm, "Pm"), /* metallic, also reflection */ M3D_PROPERTYDEF(m3dpf_float, m3dp_Ps, "Ps"), /* sheen */ M3D_PROPERTYDEF(m3dpf_float, m3dp_Ni, "Ni"), /* index of refraction (optical density) */ + M3D_PROPERTYDEF(m3dpf_float, m3dp_Nt, "Nt"), /* thickness of face in millimeter, for printing */ /* aliases, note that "map_*" aliases are handled automatically */ M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Km, "bump"), M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Pm, "refl") }; +/* shape command definitions. if more commands start with the same string, the longer must come first */ +static m3dcd_t m3d_commandtypes[] = { + /* technical */ + M3D_CMDDEF(m3dc_use, "use", 1, m3dcp_mi_t, 0, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_inc, "inc", 3, m3dcp_hi_t, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vi_t, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_mesh, "mesh", 1, m3dcp_fi_t, m3dcp_fi_t, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vi_t, 0, 0, 0), + /* approximations */ + M3D_CMDDEF(m3dc_div, "div", 1, m3dcp_vc_t, 0, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_sub, "sub", 2, m3dcp_vc_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_len, "len", 1, m3dcp_vc_t, 0, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_dist, "dist", 2, m3dcp_vc_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0), + /* modifiers */ + M3D_CMDDEF(m3dc_degu, "degu", 1, m3dcp_i1_t, 0, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_deg, "deg", 2, m3dcp_i1_t, m3dcp_i1_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_rangeu, "rangeu", 1, m3dcp_ti_t, 0, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_range, "range", 2, m3dcp_ti_t, m3dcp_ti_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_paru, "paru", 2, m3dcp_va_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_parv, "parv", 2, m3dcp_va_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_trim, "trim", 3, m3dcp_va_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_hole, "hole", 3, m3dcp_va_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_scrv, "scrv", 3, m3dcp_va_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_sp, "sp", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + /* helper curves */ + M3D_CMDDEF(m3dc_bez1, "bez1", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_bsp1, "bsp1", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_bez2, "bez2", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_bsp2, "bsp2", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + /* surfaces */ + M3D_CMDDEF(m3dc_bezun, "bezun", 4, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, m3dcp_vi_t, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_bezu, "bezu", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_bezn, "bezn", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_bez, "bez", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_nurbsun, "nurbsun", 4, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, m3dcp_vi_t, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_nurbsu, "nurbsu", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_ti_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_nurbsn, "nurbsn", 3, m3dcp_va_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_nurbs, "nurbs", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_conn, "conn", 6, m3dcp_i2_t, m3dcp_ti_t, m3dcp_i2_t, m3dcp_i2_t, m3dcp_ti_t, m3dcp_i2_t, 0, 0), + /* geometrical */ + M3D_CMDDEF(m3dc_line, "line", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_polygon, "polygon", 2, m3dcp_va_t, m3dcp_vi_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_circle, "circle", 3, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_cylinder,"cylinder",6, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, 0, 0), + M3D_CMDDEF(m3dc_shpere, "shpere", 2, m3dcp_vi_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_torus, "torus", 4, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, m3dcp_vc_t, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_cube, "cube", 3, m3dcp_vi_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0) +}; #endif #include @@ -1885,7 +2080,7 @@ static char *_m3d_gethex(char *s, uint32_t *ret) static char *_m3d_getint(char *s, uint32_t *ret) { char *e = s; - if(!s || !*s) return s; + if(!s || !*s || *s == '\r' || *s == '\n') return s; for(; *e >= '0' && *e <= '9'; e++); *ret = atoi(s); return e; @@ -1893,54 +2088,13 @@ static char *_m3d_getint(char *s, uint32_t *ret) static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) { char *e = s; - if(!s || !*s) return s; + if(!s || !*s || *s == '\r' || *s == '\n') return s; for(; *e == '-' || *e == '+' || *e == '.' || (*e >= '0' && *e <= '9') || *e == 'e' || *e == 'E'; e++); *ret = (M3D_FLOAT)strtod(s, NULL); return _m3d_findarg(e); } #endif -#if !defined(M3D_NODUP) && (!defined(M3D_NONORMALS) || defined(M3D_EXPORTER)) -/* add vertex to list, only compare x,y,z */ -m3dv_t *_m3d_addnorm(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) -{ - uint32_t i; - if(v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0; - if(v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0; - if(v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0; - if(v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0; - if(vrtx) { - for(i = 0; i < *numvrtx; i++) - if(vrtx[i].x == v->x && vrtx[i].y == v->y && vrtx[i].z == v->z) { *idx = i; return vrtx; } - } - vrtx = (m3dv_t*)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t)); - memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t)); - vrtx[*numvrtx].color = 0; - vrtx[*numvrtx].w = (M3D_FLOAT)1.0; - *idx = *numvrtx; - (*numvrtx)++; - return vrtx; -} -#endif #if !defined(M3D_NODUP) && (defined(M3D_ASCII) || defined(M3D_EXPORTER)) -m3ds_t *_m3d_addskin(m3ds_t *skin, uint32_t *numskin, m3ds_t *s, uint32_t *idx) -{ - uint32_t i; - M3D_FLOAT w = (M3D_FLOAT)0.0; - for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) - w += s->weight[i]; - if(w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) - for(i = 0; i < M3D_NUMBONE && s->weight[i] > (M3D_FLOAT)0.0; i++) - s->weight[i] /= w; - if(skin) { - for(i = 0; i < *numskin; i++) - if(!memcmp(&skin[i], s, sizeof(m3ds_t))) { *idx = i; return skin; } - } - skin = (m3ds_t*)M3D_REALLOC(skin, ((*numskin) + 1) * sizeof(m3ds_t)); - memcpy(&skin[*numskin], s, sizeof(m3ds_t)); - *idx = *numskin; - (*numskin)++; - return skin; -} /* helper function to create safe strings */ char *_m3d_safestr(char *in, int morelines) { @@ -1985,12 +2139,26 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char unsigned int i, len = 0, w, h; unsigned char *buff = NULL; char *fn2; +#ifdef STBI__PNG_TYPE stbi__context s; stbi__result_info ri; +#endif + /* do we have loaded this texture already? */ for(i = 0; i < model->numtexture; i++) if(!strcmp(fn, model->texture[i].name)) return i; - if(readfilecb) { + /* see if it's inlined in the model */ + if(model->inlined) { + for(i = 0; i < model->numinlined; i++) + if(!strcmp(fn, model->inlined[i].name)) { + buff = model->inlined[i].data; + len = model->inlined[i].length; + freecb = NULL; + break; + } + } + /* try to load from external source */ + if(!buff && readfilecb) { i = strlen(fn); if(i < 5 || fn[i - 4] != '.') { fn2 = (char*)M3D_MALLOC(i + 5); @@ -2003,32 +2171,30 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char if(!buff) buff = (*readfilecb)(fn, &len); } - if(!buff && model->inlined) { - for(i = 0; i < model->numinlined; i++) - if(!strcmp(fn, model->inlined[i].name)) { - buff = model->inlined[i].data; - len = model->inlined[i].length; - freecb = NULL; - break; - } - } if(!buff) return (M3D_INDEX)-1U; + /* add to textures array */ i = model->numtexture++; model->texture = (m3dtx_t*)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t)); if(!model->texture) { if(freecb) (*freecb)(buff); - model->errcode = M3D_ERR_ALLOC; return (M3D_INDEX)-1U; + model->errcode = M3D_ERR_ALLOC; + return (M3D_INDEX)-1U; } + model->texture[i].name = fn; model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL; if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') { +#ifdef STBI__PNG_TYPE s.read_from_callbacks = 0; s.img_buffer = s.img_buffer_original = (stbi_uc *) buff; s.img_buffer_end = s.img_buffer_original_end = (stbi_uc *) buff+len; /* don't use model->texture[i].w directly, it's a uint16_t */ - w = h = 0; - model->texture[i].d = (uint32_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, STBI_rgb_alpha, &ri); + w = h = len = 0; + ri.bits_per_channel = 8; + model->texture[i].d = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, 0, &ri); model->texture[i].w = w; model->texture[i].h = h; + model->texture[i].f = (uint8_t)len; +#endif } else { #ifdef M3D_TX_INTERP if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) { @@ -2041,13 +2207,8 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char #endif } if(freecb) (*freecb)(buff); - if(!model->texture[i].d) { - M3D_FREE(model->texture[i].d); + if(!model->texture[i].d) model->errcode = M3D_ERR_UNKIMG; - model->numtexture--; - return (M3D_INDEX)-1U; - } - model->texture[i].name = fn; return i; } @@ -2085,8 +2246,8 @@ _inline static unsigned char *_m3d_getidx(unsigned char *data, char type, M3D_IN { switch(type) { case 1: *idx = data[0] > 253 ? (int8_t)data[0] : data[0]; data++; break; - case 2: *idx = (uint16_t)((data[1]<<8)|data[0]) > 65533 ? (int16_t)((data[1]<<8)|data[0]) : (uint16_t)((data[1]<<8)|data[0]); data += 2; break; - case 4: *idx = (int32_t)((data[3]<<24)|(data[2]<<16)|(data[1]<<8)|data[0]); data += 4; break; + case 2: *idx = *((uint16_t*)data) > 65533 ? *((int16_t*)data) : *((uint16_t*)data); data += 2; break; + case 4: *idx = *((int32_t*)data); data += 4; break; } return data; } @@ -2144,10 +2305,6 @@ void _m3d_inv(M3D_FLOAT *m) memcpy(m, &r, sizeof(r)); } /* compose a coloumn major 4 x 4 matrix from vec3 position and vec4 orientation/rotation quaternion */ -#ifndef M3D_EPSILON -/* carefully choosen for IEEE 754 don't change */ -#define M3D_EPSILON ((M3D_FLOAT)1e-7) -#endif void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) { if(q->x == (M3D_FLOAT)0.0 && q->y == (M3D_FLOAT)0.0 && q->z >=(M3D_FLOAT) 0.7071065 && q->z <= (M3D_FLOAT)0.7071075 && @@ -2190,30 +2347,35 @@ static M3D_FLOAT _m3d_rsq(M3D_FLOAT x) m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d_t *mtllib) { unsigned char *end, *chunk, *buff, weights[8]; - unsigned int i, j, k, n, am, len = 0, reclen, offs; - char *material; -#ifndef M3D_NONORMALS - unsigned int numnorm = 0; - m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb, vn; - M3D_INDEX *ni = NULL, *vi = NULL; -#endif + unsigned int i, j, k, l, n, am, len = 0, reclen, offs; + char *name, *lang; + float f; m3d_t *model; M3D_INDEX mi; M3D_FLOAT w; + m3dcd_t *cd; + m3dtx_t *tx; + m3dh_t *h; + m3dm_t *m; + m3da_t *a; + m3di_t *t; +#ifndef M3D_NONORMALS + m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb; +#endif #ifndef M3D_NOANIMATION M3D_FLOAT r[16]; #endif - m3dtx_t *tx; - m3dm_t *m; - m3da_t *a; +#if !defined(M3D_NOWEIGHTS) || !defined(M3D_NOANIMATION) m3db_t *b; - m3di_t *t; +#endif +#ifndef M3D_NOWEIGHTS m3ds_t *sk; +#endif #ifdef M3D_ASCII m3ds_t s; M3D_INDEX bi[M3D_BONEMAXLEVEL+1], level; const char *ol; - char *ptr, *pe; + char *ptr, *pe, *fn; #endif if(!data || (!M3D_CHUNKMAGIC(data, '3','D','M','O') @@ -2250,13 +2412,14 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d pe = _m3d_findnl(ptr); model->scale = (float)strtod(ptr, NULL); ptr = pe; if(model->scale <= (M3D_FLOAT)0.0) model->scale = (M3D_FLOAT)1.0; - model->name = _m3d_safestr(ptr, 0); ptr = _m3d_findnl(ptr); + model->name = _m3d_safestr(ptr, 2); ptr = _m3d_findnl(ptr); if(!*ptr) goto asciiend; model->license = _m3d_safestr(ptr, 2); ptr = _m3d_findnl(ptr); if(!*ptr) goto asciiend; model->author = _m3d_safestr(ptr, 2); ptr = _m3d_findnl(ptr); if(!*ptr) goto asciiend; - model->desc = _m3d_safestr(ptr, 3); + if(*ptr != '\r' && *ptr != '\n') + model->desc = _m3d_safestr(ptr, 3); while(*ptr) { while(*ptr && *ptr!='\n') ptr++; ptr++; if(*ptr=='\r') ptr++; @@ -2270,6 +2433,17 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d /* make sure there's at least one data row */ pe = ptr; ptr = _m3d_findnl(ptr); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + /* Preview chunk */ + if(!memcmp(pe, "Preview", 7)) { + if(readfilecb) { + pe = _m3d_safestr(ptr, 0); + if(!pe || !*pe) goto asciiend; + model->preview.data = (*readfilecb)(pe, &model->preview.length); + M3D_FREE(pe); + } + while(*ptr && *ptr != '\r' && *ptr != '\n') + ptr = _m3d_findnl(ptr); + } else /* texture map chunk */ if(!memcmp(pe, "Textmap", 7)) { if(model->tmap) { M3D_LOG("More texture map chunks, should be unique"); goto asciiend; } @@ -2279,8 +2453,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(!model->tmap) goto memerr; ptr = _m3d_getfloat(ptr, &model->tmap[i].u); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; - ptr = _m3d_getfloat(ptr, &model->tmap[i].v); - if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; + _m3d_getfloat(ptr, &model->tmap[i].v); ptr = _m3d_findnl(ptr); } } else @@ -2291,8 +2464,10 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d i = model->numvertex++; model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t)); if(!model->vertex) goto memerr; + memset(&model->vertex[i], 0, sizeof(m3dv_t)); model->vertex[i].skinid = (M3D_INDEX)-1U; model->vertex[i].color = 0; + model->vertex[i].w = (M3D_FLOAT)1.0; ptr = _m3d_getfloat(ptr, &model->vertex[i].x); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; ptr = _m3d_getfloat(ptr, &model->vertex[i].y); @@ -2300,7 +2475,6 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d ptr = _m3d_getfloat(ptr, &model->vertex[i].z); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; ptr = _m3d_getfloat(ptr, &model->vertex[i].w); - if(model->vertex[i].w != 1.0) model->vertex[i].skinid = (M3D_INDEX)-2U; if(!*ptr) goto asciiend; if(*ptr == '#') { ptr = _m3d_gethex(ptr, &model->vertex[i].color); @@ -2308,7 +2482,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d } /* parse skin */ memset(&s, 0, sizeof(m3ds_t)); - for(j = 0; j < M3D_NUMBONE && *ptr && *ptr != '\r' && *ptr != '\n'; j++) { + for(j = 0, w = (M3D_FLOAT)0.0; j < M3D_NUMBONE && *ptr && *ptr != '\r' && *ptr != '\n'; j++) { ptr = _m3d_findarg(ptr); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; ptr = _m3d_getint(ptr, &k); @@ -2316,12 +2490,25 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(*ptr == ':') { ptr++; ptr = _m3d_getfloat(ptr, &s.weight[j]); + w += s.weight[j]; } else if(!j) s.weight[j] = (M3D_FLOAT)1.0; if(!*ptr) goto asciiend; } if(s.boneid[0] != (M3D_INDEX)-1U && s.weight[0] > (M3D_FLOAT)0.0) { - model->skin = _m3d_addskin(model->skin, &model->numskin, &s, &k); + if(w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) + for(j = 0; j < M3D_NUMBONE && s.weight[j] > (M3D_FLOAT)0.0; j++) + s.weight[j] /= w; + k = -1U; + if(model->skin) { + for(j = 0; j < model->numskin; j++) + if(!memcmp(&model->skin[j], &s, sizeof(m3ds_t))) { k = j; break; } + } + if(k == -1U) { + k = model->numskin++; + model->skin = (m3ds_t*)M3D_REALLOC(model->skin, model->numskin * sizeof(m3ds_t)); + memcpy(&model->skin[k], &s, sizeof(m3ds_t)); + } model->vertex[i].skinid = (M3D_INDEX)k; } ptr = _m3d_findnl(ptr); @@ -2349,6 +2536,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d ptr = _m3d_findarg(ptr); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; model->bone[i].ori = (M3D_INDEX)k; + model->vertex[k].skinid = (M3D_INDEX)-2U; pe = _m3d_safestr(ptr, 0); if(!pe || !*pe) goto asciiend; model->bone[i].name = pe; @@ -2410,7 +2598,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d j = m->numprop++; m->prop = (m3dp_t*)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t)); if(!m->prop) goto memerr; - m->prop[j].type = n; + m->prop[j].type = n + (k == m3dpf_map && n < 128 ? 128 : 0); switch(k) { case m3dpf_color: ptr = _m3d_gethex(ptr, &m->prop[j].value.color); break; case m3dpf_uint8: @@ -2439,7 +2627,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d } if(!m->numprop) model->nummaterial--; } else - /* procedural, not implemented yet, skip chunk */ + /* procedural */ if(!memcmp(pe, "Procedural", 10)) { pe = _m3d_safestr(ptr, 0); _m3d_getpr(model, readfilecb, freecb, pe); @@ -2458,11 +2646,16 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d pe = _m3d_safestr(ptr, 0); if(!pe || !*pe) goto asciiend; for(j = 0; j < model->nummaterial; j++) - if(!strcmp(pe, model->material[j].name)) { - mi = (M3D_INDEX)j; - break; - } - M3D_FREE(pe); + if(!strcmp(pe, model->material[j].name)) { mi = (M3D_INDEX)j; break; } + if(mi == (M3D_INDEX)-1U && !(model->flags & M3D_FLG_MTLLIB)) { + mi = model->nummaterial++; + model->material = (m3dm_t*)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t)); + if(!model->material) goto memerr; + model->material[mi].name = pe; + model->material[mi].numprop = 1; + model->material[mi].prop = NULL; + } else + M3D_FREE(pe); } } else { i = model->numface++; @@ -2498,6 +2691,137 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d ptr = _m3d_findnl(ptr); } } else + /* mathematical shape */ + if(!memcmp(pe, "Shape", 5)) { + pe = _m3d_findarg(pe); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + pe = _m3d_safestr(pe, 0); + if(!pe || !*pe) goto asciiend; + i = model->numshape++; + model->shape = (m3dh_t*)M3D_REALLOC(model->shape, model->numshape * sizeof(m3ds_t)); + if(!model->shape) goto memerr; + h = &model->shape[i]; + h->name = pe; + h->group = (M3D_INDEX)-1U; + h->numcmd = 0; + h->cmd = NULL; + while(*ptr && *ptr != '\r' && *ptr != '\n') { + if(!memcmp(ptr, "group", 5)) { + ptr = _m3d_findarg(ptr); + ptr = _m3d_getint(ptr, &h->group); + ptr = _m3d_findnl(ptr); + if(h->group != (M3D_INDEX)-1U && h->group >= model->numbone) { + M3D_LOG("Unknown bone id as shape group in shape"); + M3D_LOG(pe); + h->group = (M3D_INDEX)-1U; + model->errcode = M3D_ERR_SHPE; + } + continue; + } + for(cd = NULL, k = 0; k < (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])); k++) { + j = strlen(m3d_commandtypes[k].key); + if(!memcmp(ptr, m3d_commandtypes[k].key, j) && (ptr[j] == ' ' || ptr[j] == '\r' || ptr[j] == '\n')) + { cd = &m3d_commandtypes[k]; break; } + } + if(cd) { + j = h->numcmd++; + h->cmd = (m3dc_t*)M3D_REALLOC(h->cmd, h->numcmd * sizeof(m3dc_t)); + if(!h->cmd) goto memerr; + h->cmd[j].type = k; + h->cmd[j].arg = (uint32_t*)M3D_MALLOC(cd->p * sizeof(uint32_t)); + if(!h->cmd[j].arg) goto memerr; + memset(h->cmd[j].arg, 0, cd->p * sizeof(uint32_t)); + for(k = n = 0, l = cd->p; k < l; k++) { + ptr = _m3d_findarg(ptr); + if(!*ptr) goto asciiend; + if(*ptr == '[') { + ptr = _m3d_findarg(ptr + 1); + if(!*ptr) goto asciiend; + } + if(*ptr == ']' || *ptr == '\r' || *ptr == '\n') break; + switch(cd->a[((k - n) % (cd->p - n)) + n]) { + case m3dcp_mi_t: + mi = (M3D_INDEX)-1U; + if(*ptr != '\r' && *ptr != '\n') { + pe = _m3d_safestr(ptr, 0); + if(!pe || !*pe) goto asciiend; + for(n = 0; n < model->nummaterial; n++) + if(!strcmp(pe, model->material[n].name)) { mi = (M3D_INDEX)n; break; } + if(mi == (M3D_INDEX)-1U && !(model->flags & M3D_FLG_MTLLIB)) { + mi = model->nummaterial++; + model->material = (m3dm_t*)M3D_REALLOC(model->material, + model->nummaterial * sizeof(m3dm_t)); + if(!model->material) goto memerr; + model->material[mi].name = pe; + model->material[mi].numprop = 1; + model->material[mi].prop = NULL; + } else + M3D_FREE(pe); + } + h->cmd[j].arg[k] = mi; + break; + case m3dcp_vc_t: + _m3d_getfloat(ptr, &w); + h->cmd[j].arg[k] = *((uint32_t*)&w); + break; + case m3dcp_va_t: + ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]); + n = k + 1; l += (h->cmd[j].arg[k] - 1) * (cd->p - k - 1); + h->cmd[j].arg = (uint32_t*)M3D_REALLOC(h->cmd[j].arg, l * sizeof(uint32_t)); + if(!h->cmd[j].arg) goto memerr; + memset(&h->cmd[j].arg[k + 1], 0, (l - k - 1) * sizeof(uint32_t)); + break; + case m3dcp_qi_t: + ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]); + model->vertex[h->cmd[i].arg[k]].skinid = (M3D_INDEX)-2U; + break; + default: + ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]); + break; + } + } + } else { + M3D_LOG("Unknown shape command in"); + M3D_LOG(h->name); + model->errcode = M3D_ERR_UNKCMD; + } + ptr = _m3d_findnl(ptr); + } + if(!h->numcmd) model->numshape--; + } else + /* annotation labels */ + if(!memcmp(pe, "Labels", 6)) { + pe = _m3d_findarg(pe); + if(!*pe) goto asciiend; + if(*pe == '\r' || *pe == '\n') pe = NULL; + else pe = _m3d_safestr(pe, 0); + k = 0; fn = NULL; + while(*ptr && *ptr != '\r' && *ptr != '\n') { + if(*ptr == 'c') { + ptr = _m3d_findarg(ptr); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + ptr = _m3d_gethex(ptr, &k); + } else + if(*ptr == 'l') { + ptr = _m3d_findarg(ptr); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + fn = _m3d_safestr(ptr, 2); + } else { + i = model->numlabel++; + model->label = (m3dl_t*)M3D_REALLOC(model->label, model->numlabel * sizeof(m3dl_t)); + if(!model->label) goto memerr; + model->label[i].name = pe; + model->label[i].lang = fn; + model->label[i].color = k; + ptr = _m3d_getint(ptr, &j); + model->label[i].vertexid = (M3D_INDEX)j; + ptr = _m3d_findarg(ptr); + if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; + model->label[i].text = _m3d_safestr(ptr, 2); + } + ptr = _m3d_findnl(ptr); + } + } else /* action */ if(!memcmp(pe, "Action", 6)) { pe = _m3d_findarg(pe); @@ -2548,6 +2872,33 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d ptr = _m3d_getint(ptr, &k); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; a->frame[i].transform[j].ori = (M3D_INDEX)k; + model->vertex[k].skinid = (M3D_INDEX)-2U; + } + ptr = _m3d_findnl(ptr); + } + } else + /* inlined assets chunk */ + if(!memcmp(pe, "Assets", 6)) { + while(*ptr && *ptr != '\r' && *ptr != '\n') { + if(readfilecb) { + pe = _m3d_safestr(ptr, 2); + if(!pe || !*pe) goto asciiend; + i = model->numinlined++; + model->inlined = (m3di_t*)M3D_REALLOC(model->inlined, model->numinlined * sizeof(m3di_t)); + if(!model->inlined) goto memerr; + t = &model->inlined[i]; + model->inlined[i].data = (*readfilecb)(pe, &model->inlined[i].length); + if(model->inlined[i].data) { + fn = strrchr(pe, '.'); + if(fn && (fn[1] == 'p' || fn[1] == 'P') && (fn[2] == 'n' || fn[2] == 'N') && + (fn[3] == 'g' || fn[3] == 'G')) *fn = 0; + fn = strrchr(pe, '/'); + if(!fn) fn = strrchr(pe, '\\'); + if(!fn) fn = pe; else fn++; + model->inlined[i].name = _m3d_safestr(fn, 0); + } else + model->numinlined--; + M3D_FREE(pe); } ptr = _m3d_findnl(ptr); } @@ -2558,18 +2909,18 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; buff = (unsigned char*)_m3d_findnl(ptr); k = ((uint32_t)((uint64_t)buff - (uint64_t)ptr) / 3) + 1; - i = model->numunknown++; - model->unknown = (m3dchunk_t**)M3D_REALLOC(model->unknown, model->numunknown * sizeof(m3dchunk_t*)); - if(!model->unknown) goto memerr; - model->unknown[i] = (m3dchunk_t*)M3D_MALLOC(k + sizeof(m3dchunk_t)); - if(!model->unknown[i]) goto memerr; - memcpy(&model->unknown[i]->magic, pe, 4); - model->unknown[i]->length = sizeof(m3dchunk_t); - pe = (char*)model->unknown[i] + sizeof(m3dchunk_t); + i = model->numextra++; + model->extra = (m3dchunk_t**)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t*)); + if(!model->extra) goto memerr; + model->extra[i] = (m3dchunk_t*)M3D_MALLOC(k + sizeof(m3dchunk_t)); + if(!model->extra[i]) goto memerr; + memcpy(&model->extra[i]->magic, pe, 4); + model->extra[i]->length = sizeof(m3dchunk_t); + pe = (char*)model->extra[i] + sizeof(m3dchunk_t); while(*ptr && *ptr != '\r' && *ptr != '\n') { ptr = _m3d_gethex(ptr, &k); *pe++ = (uint8_t)k; - model->unknown[i]->length++; + model->extra[i]->length++; } } else goto asciiend; @@ -2622,11 +2973,15 @@ asciiend: model->bi_s = 1 << ((model->raw->types >>10) & 3); /* bone index size */ model->nb_s = 1 << ((model->raw->types >>12) & 3); /* number of bones per vertex */ model->sk_s = 1 << ((model->raw->types >>14) & 3); /* skin index size */ - model->fi_s = 1 << ((model->raw->types >>16) & 3); /* frame counter size */ + model->fc_s = 1 << ((model->raw->types >>16) & 3); /* frame counter size */ + model->hi_s = 1 << ((model->raw->types >>18) & 3); /* shape index size */ + model->fi_s = 1 << ((model->raw->types >>20) & 3); /* face index size */ if(model->ci_s == 8) model->ci_s = 0; /* optional indices */ if(model->ti_s == 8) model->ti_s = 0; if(model->bi_s == 8) model->bi_s = 0; if(model->sk_s == 8) model->sk_s = 0; + if(model->fc_s == 8) model->fc_s = 0; + if(model->hi_s == 8) model->hi_s = 0; if(model->fi_s == 8) model->fi_s = 0; /* variable limit checks */ @@ -2635,7 +2990,7 @@ asciiend: model->errcode = M3D_ERR_TRUNC; } if(sizeof(M3D_INDEX) == 2 && (model->vi_s > 2 || model->si_s > 2 || model->ci_s > 2 || model->ti_s > 2 || - model->bi_s > 2 || model->sk_s > 2 || model->fi_s > 2)) { + model->bi_s > 2 || model->sk_s > 2 || model->fc_s > 2 || model->hi_s > 2 || model->fi_s > 2)) { M3D_LOG("32 bit indices not supported, unable to load model"); M3D_FREE(model); return NULL; @@ -2646,7 +3001,7 @@ asciiend: return NULL; } if(model->nb_s > M3D_NUMBONE) { - M3D_LOG("Model has more bones per vertex than importer supports"); + M3D_LOG("Model has more bones per vertex than what importer configured to support"); model->errcode = M3D_ERR_TRUNC; } @@ -2692,6 +3047,11 @@ memerr: M3D_LOG("Out of memory"); chunk += len; len -= sizeof(m3dchunk_t); + /* preview chunk */ + if(M3D_CHUNKMAGIC(data, 'P','R','V','W') && len > 0) { + model->preview.length = len; + model->preview.data = data + sizeof(m3dchunk_t); + } else /* color map */ if(M3D_CHUNKMAGIC(data, 'C','M','A','P')) { M3D_LOG("Color map"); @@ -2751,10 +3111,10 @@ memerr: M3D_LOG("Out of memory"); data += 4; break; case 2: - model->vertex[i].x = (M3D_FLOAT)((int16_t)((data[1]<<8)|data[0])) / 32767; - model->vertex[i].y = (M3D_FLOAT)((int16_t)((data[3]<<8)|data[2])) / 32767; - model->vertex[i].z = (M3D_FLOAT)((int16_t)((data[5]<<8)|data[4])) / 32767; - model->vertex[i].w = (M3D_FLOAT)((int16_t)((data[7]<<8)|data[6])) / 32767; + model->vertex[i].x = (M3D_FLOAT)(*((int16_t*)(data+0))) / 32767; + model->vertex[i].y = (M3D_FLOAT)(*((int16_t*)(data+2))) / 32767; + model->vertex[i].z = (M3D_FLOAT)(*((int16_t*)(data+4))) / 32767; + model->vertex[i].w = (M3D_FLOAT)(*((int16_t*)(data+6))) / 32767; data += 8; break; case 4: @@ -2797,15 +3157,6 @@ memerr: M3D_LOG("Out of memory"); } model->numskin = 0; data = _m3d_getidx(data, model->sk_s, &model->numskin); - if(model->numskin) { - model->skin = (m3ds_t*)M3D_MALLOC(model->numskin * sizeof(m3ds_t)); - if(!model->skin) goto memerr; - for(i = 0; i < model->numskin; i++) - for(j = 0; j < M3D_NUMBONE; j++) { - model->skin[i].boneid[j] = (M3D_INDEX)-1U; - model->skin[i].weight[j] = (M3D_FLOAT)0.0; - } - } /* read bone hierarchy */ for(i = 0; i < model->numbone; i++) { data = _m3d_getidx(data, model->bi_s, &model->bone[i].parent); @@ -2816,41 +3167,55 @@ memerr: M3D_LOG("Out of memory"); model->bone[i].weight = NULL; } /* read skin definitions */ - for(i = 0; data < chunk && i < model->numskin; i++) { - memset(&weights, 0, sizeof(weights)); - if(model->nb_s == 1) weights[0] = 255; - else { - memcpy(&weights, data, model->nb_s); - data += model->nb_s; - } - for(j = 0; j < (unsigned int)model->nb_s; j++) { - if(weights[j]) { - if(j >= M3D_NUMBONE) - data += model->bi_s; - else { - model->skin[i].weight[j] = (M3D_FLOAT)(weights[j]) / 255; - data = _m3d_getidx(data, model->bi_s, &model->skin[i].boneid[j]); + if(model->numskin) { + model->skin = (m3ds_t*)M3D_MALLOC(model->numskin * sizeof(m3ds_t)); + if(!model->skin) goto memerr; + for(i = 0; data < chunk && i < model->numskin; i++) { + for(j = 0; j < M3D_NUMBONE; j++) { + model->skin[i].boneid[j] = (M3D_INDEX)-1U; + model->skin[i].weight[j] = (M3D_FLOAT)0.0; + } + memset(&weights, 0, sizeof(weights)); + if(model->nb_s == 1) weights[0] = 255; + else { + memcpy(&weights, data, model->nb_s); + data += model->nb_s; + } + for(j = 0, w = (M3D_FLOAT)0.0; j < (unsigned int)model->nb_s; j++) { + if(weights[j]) { + if(j >= M3D_NUMBONE) + data += model->bi_s; + else { + model->skin[i].weight[j] = (M3D_FLOAT)(weights[j]) / 255; + w += model->skin[i].weight[j]; + data = _m3d_getidx(data, model->bi_s, &model->skin[i].boneid[j]); + } } } + /* this can occur if model has more bones than what the importer is configured to handle */ + if(w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) { + for(j = 0; j < M3D_NUMBONE; j++) + model->skin[i].weight[j] /= w; + } } } } else /* material */ if(M3D_CHUNKMAGIC(data, 'M','T','R','L')) { data += sizeof(m3dchunk_t); - M3D_GETSTR(material); + M3D_GETSTR(name); M3D_LOG("Material"); - M3D_LOG(material); + M3D_LOG(name); if(model->ci_s < 4 && !model->numcmap) model->errcode = M3D_ERR_CMAP; for(i = 0; i < model->nummaterial; i++) - if(!strcmp(material, model->material[i].name)) { + if(!strcmp(name, model->material[i].name)) { model->errcode = M3D_ERR_MTRL; M3D_LOG("Multiple definitions for material"); - M3D_LOG(material); - material = NULL; + M3D_LOG(name); + name = NULL; break; } - if(material) { + if(name) { i = model->nummaterial++; if(model->flags & M3D_FLG_MTLLIB) { m = model->material; @@ -2870,9 +3235,8 @@ memerr: M3D_LOG("Out of memory"); } m = &model->material[i]; m->numprop = 0; - m->prop = NULL; - m->name = material; - m->prop = (m3dp_t*)M3D_REALLOC(m->prop, (len / 2) * sizeof(m3dp_t)); + m->name = name; + m->prop = (m3dp_t*)M3D_MALLOC((len / 2) * sizeof(m3dp_t)); if(!m->prop) goto memerr; while(data < chunk) { i = m->numprop++; @@ -2899,12 +3263,12 @@ memerr: M3D_LOG("Out of memory"); case m3dpf_float: m->prop[i].value.fnum = *((float*)data); data += 4; break; case m3dpf_map: - M3D_GETSTR(material); - m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, material); + M3D_GETSTR(name); + m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, name); if(model->errcode == M3D_ERR_ALLOC) goto memerr; if(m->prop[i].value.textureid == (M3D_INDEX)-1U) { M3D_LOG("Texture not found"); - M3D_LOG(material); + M3D_LOG(m->name); m->numprop--; } break; @@ -2924,10 +3288,10 @@ memerr: M3D_LOG("Out of memory"); /* face */ if(M3D_CHUNKMAGIC(data, 'P','R','O','C')) { /* procedural surface */ - M3D_GETSTR(material); + M3D_GETSTR(name); M3D_LOG("Procedural surface"); - M3D_LOG(material); - _m3d_getpr(model, readfilecb, freecb, material); + M3D_LOG(name); + _m3d_getpr(model, readfilecb, freecb, name); } else if(M3D_CHUNKMAGIC(data, 'M','E','S','H')) { M3D_LOG("Mesh data"); @@ -2942,10 +3306,10 @@ memerr: M3D_LOG("Out of memory"); if(!n) { /* use material */ mi = (M3D_INDEX)-1U; - M3D_GETSTR(material); - if(material) { + M3D_GETSTR(name); + if(name) { for(j = 0; j < model->nummaterial; j++) - if(!strcmp(material, model->material[j].name)) { + if(!strcmp(name, model->material[j].name)) { mi = (M3D_INDEX)j; break; } @@ -2975,6 +3339,117 @@ memerr: M3D_LOG("Out of memory"); } model->face = (m3df_t*)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t)); } else + if(M3D_CHUNKMAGIC(data, 'S','H','P','E')) { + /* mathematical shape */ + data += sizeof(m3dchunk_t); + M3D_GETSTR(name); + M3D_LOG("Mathematical Shape"); + M3D_LOG(name); + i = model->numshape++; + model->shape = (m3dh_t*)M3D_REALLOC(model->shape, model->numshape * sizeof(m3dh_t)); + if(!model->shape) goto memerr; + h = &model->shape[i]; + h->numcmd = 0; + h->cmd = NULL; + h->name = name; + h->group = (M3D_INDEX)-1U; + data = _m3d_getidx(data, model->bi_s, &h->group); + if(h->group != (M3D_INDEX)-1U && h->group >= model->numbone) { + M3D_LOG("Unknown bone id as shape group in shape"); + M3D_LOG(name); + h->group = (M3D_INDEX)-1U; + model->errcode = M3D_ERR_SHPE; + } + while(data < chunk) { + i = h->numcmd++; + h->cmd = (m3dc_t*)M3D_REALLOC(h->cmd, h->numcmd * sizeof(m3dc_t)); + if(!h->cmd) goto memerr; + h->cmd[i].type = *data++; + if(h->cmd[i].type & 0x80) { + h->cmd[i].type &= 0x7F; + h->cmd[i].type |= (*data++ << 7); + } + if(h->cmd[i].type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0]))) { + M3D_LOG("Unknown shape command in"); + M3D_LOG(h->name); + model->errcode = M3D_ERR_UNKCMD; + break; + } + cd = &m3d_commandtypes[h->cmd[i].type]; + h->cmd[i].arg = (uint32_t*)M3D_MALLOC(cd->p * sizeof(uint32_t)); + if(!h->cmd[i].arg) goto memerr; + memset(h->cmd[i].arg, 0, cd->p * sizeof(uint32_t)); + for(k = n = 0, l = cd->p; k < l; k++) + switch(cd->a[((k - n) % (cd->p - n)) + n]) { + case m3dcp_mi_t: + h->cmd[i].arg[k] = -1U; + M3D_GETSTR(name); + if(name) { + for(n = 0; n < model->nummaterial; n++) + if(!strcmp(name, model->material[n].name)) { + h->cmd[i].arg[k] = n; + break; + } + if(h->cmd[i].arg[k] == -1U) model->errcode = M3D_ERR_MTRL; + } + break; + case m3dcp_vc_t: + f = 0.0f; + switch(model->vc_s) { + case 1: f = (float)((int8_t)data[0]) / 127; break; + case 2: f = (float)(*((int16_t*)(data+0))) / 32767; break; + case 4: f = (float)(*((float*)(data+0))); break; + case 8: f = (float)(*((double*)(data+0))); break; + } + h->cmd[i].arg[k] = *((uint32_t*)&f); + data += model->vc_s; + break; + case m3dcp_hi_t: data = _m3d_getidx(data, model->hi_s, &h->cmd[i].arg[k]); break; + case m3dcp_fi_t: data = _m3d_getidx(data, model->fi_s, &h->cmd[i].arg[k]); break; + case m3dcp_ti_t: data = _m3d_getidx(data, model->ti_s, &h->cmd[i].arg[k]); break; + case m3dcp_qi_t: + case m3dcp_vi_t: data = _m3d_getidx(data, model->vi_s, &h->cmd[i].arg[k]); break; + case m3dcp_i1_t: data = _m3d_getidx(data, 1, &h->cmd[i].arg[k]); break; + case m3dcp_i2_t: data = _m3d_getidx(data, 2, &h->cmd[i].arg[k]); break; + case m3dcp_i4_t: data = _m3d_getidx(data, 4, &h->cmd[i].arg[k]); break; + case m3dcp_va_t: data = _m3d_getidx(data, 4, &h->cmd[i].arg[k]); + n = k + 1; l += (h->cmd[i].arg[k] - 1) * (cd->p - k - 1); + h->cmd[i].arg = (uint32_t*)M3D_REALLOC(h->cmd[i].arg, l * sizeof(uint32_t)); + if(!h->cmd[i].arg) goto memerr; + memset(&h->cmd[i].arg[k + 1], 0, (l - k - 1) * sizeof(uint32_t)); + break; + } + } + } else + /* annotation label list */ + if(M3D_CHUNKMAGIC(data, 'L','B','L','S')) { + data += sizeof(m3dchunk_t); + M3D_GETSTR(name); + M3D_GETSTR(lang); + M3D_LOG("Label list"); + if(name) { M3D_LOG(name); } + if(lang) { M3D_LOG(lang); } + if(model->ci_s && model->ci_s < 4 && !model->cmap) model->errcode = M3D_ERR_CMAP; + k = 0; + switch(model->ci_s) { + case 1: k = model->cmap ? model->cmap[data[0]] : 0; data++; break; + case 2: k = model->cmap ? model->cmap[*((uint16_t*)data)] : 0; data += 2; break; + case 4: k = *((uint32_t*)data); data += 4; break; + /* case 8: break; */ + } + reclen = model->vi_s + model->si_s; + i = model->numlabel; model->numlabel += len / reclen; + model->label = (m3dl_t*)M3D_REALLOC(model->label, model->numlabel * sizeof(m3dl_t)); + if(!model->label) goto memerr; + memset(&model->label[i], 0, (model->numlabel - i) * sizeof(m3dl_t)); + for(; data < chunk && i < model->numlabel; i++) { + model->label[i].name = name; + model->label[i].lang = lang; + model->label[i].color = k; + data = _m3d_getidx(data, model->vi_s, &model->label[i].vertexid); + M3D_GETSTR(model->label[i].text); + } + } else /* action */ if(M3D_CHUNKMAGIC(data, 'A','C','T','N')) { M3D_LOG("Action"); @@ -2995,7 +3470,7 @@ memerr: M3D_LOG("Out of memory"); for(i = 0; data < chunk && i < a->numframe; i++) { a->frame[i].msec = *((uint32_t*)data); data += 4; a->frame[i].numtransform = 0; a->frame[i].transform = NULL; - data = _m3d_getidx(data, model->fi_s, &a->frame[i].numtransform); + data = _m3d_getidx(data, model->fc_s, &a->frame[i].numtransform); if(a->frame[i].numtransform > 0) { a->frame[i].transform = (m3dtr_t*)M3D_MALLOC(a->frame[i].numtransform * sizeof(m3dtr_t)); for(j = 0; j < a->frame[i].numtransform; j++) { @@ -3007,10 +3482,10 @@ memerr: M3D_LOG("Out of memory"); } } } else { - i = model->numunknown++; - model->unknown = (m3dchunk_t**)M3D_REALLOC(model->unknown, model->numunknown * sizeof(m3dchunk_t*)); - if(!model->unknown) goto memerr; - model->unknown[i] = (m3dchunk_t*)data; + i = model->numextra++; + model->extra = (m3dchunk_t**)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t*)); + if(!model->extra) goto memerr; + model->extra[i] = (m3dchunk_t*)data; } } /* calculate normals, normalize skin weights, create bone/vertex cross-references and calculate transform matrices */ @@ -3018,59 +3493,61 @@ memerr: M3D_LOG("Out of memory"); postprocess: #endif if(model) { + M3D_LOG("Post-process"); #ifndef M3D_NONORMALS if(model->numface && model->face) { - memset(&vn, 0, sizeof(m3dv_t)); /* if they are missing, calculate triangle normals into a temporary buffer */ - for(i = numnorm = 0; i < model->numface; i++) + for(i = 0, n = model->numvertex; i < model->numface; i++) if(model->face[i].normal[0] == -1U) { - v0 = &model->vertex[model->face[i].vertex[0]]; v1 = &model->vertex[model->face[i].vertex[1]]; + v0 = &model->vertex[model->face[i].vertex[0]]; + v1 = &model->vertex[model->face[i].vertex[1]]; v2 = &model->vertex[model->face[i].vertex[2]]; va.x = v1->x - v0->x; va.y = v1->y - v0->y; va.z = v1->z - v0->z; vb.x = v2->x - v0->x; vb.y = v2->y - v0->y; vb.z = v2->z - v0->z; - vn.x = (va.y * vb.z) - (va.z * vb.y); - vn.y = (va.z * vb.x) - (va.x * vb.z); - vn.z = (va.x * vb.y) - (va.y * vb.x); - w = _m3d_rsq((vn.x * vn.x) + (vn.y * vn.y) + (vn.z * vn.z)); - vn.x *= w; vn.y *= w; vn.z *= w; - norm = _m3d_addnorm(norm, &numnorm, &vn, &j); - if(!ni) { - ni = (M3D_INDEX*)M3D_MALLOC(model->numface * sizeof(M3D_INDEX)); - if(!ni) goto memerr; + if(!norm) { + norm = (m3dv_t*)M3D_MALLOC(model->numface * sizeof(m3dv_t)); + if(!norm) goto memerr; } - ni[i] = j; + v0 = &norm[i]; + v0->x = (va.y * vb.z) - (va.z * vb.y); + v0->y = (va.z * vb.x) - (va.x * vb.z); + v0->z = (va.x * vb.y) - (va.y * vb.x); + w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z)); + v0->x *= w; v0->y *= w; v0->z *= w; + model->face[i].normal[0] = model->face[i].vertex[0] + n; + model->face[i].normal[1] = model->face[i].vertex[1] + n; + model->face[i].normal[2] = model->face[i].vertex[2] + n; } - if(ni && norm) { - vi = (M3D_INDEX*)M3D_MALLOC(model->numvertex * sizeof(M3D_INDEX)); - if(!vi) goto memerr; + /* this is the fast way, we don't care if a normal is repeated in model->vertex */ + if(norm) { + M3D_LOG("Generating normals"); + model->flags |= M3D_FLG_GENNORM; + model->numvertex <<= 1; + model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t)); + if(!model->vertex) goto memerr; + memset(&model->vertex[n], 0, n * sizeof(m3dv_t)); + for(i = 0; i < model->numface; i++) + for(j = 0; j < 3; j++) { + v0 = &model->vertex[model->face[i].vertex[j] + n]; + v0->x += norm[i].x; + v0->y += norm[i].y; + v0->z += norm[i].z; + } /* for each vertex, take the average of the temporary normals and use that */ - for(i = 0, n = model->numvertex; i < n; i++) { - memset(&vn, 0, sizeof(m3dv_t)); - for(j = 0; j < model->numface; j++) - for(k = 0; k < 3; k++) - if(model->face[j].vertex[k] == i) { - vn.x += norm[ni[j]].x; - vn.y += norm[ni[j]].y; - vn.z += norm[ni[j]].z; - } - w = _m3d_rsq((vn.x * vn.x) + (vn.y * vn.y) + (vn.z * vn.z)); - vn.x *= w; vn.y *= w; vn.z *= w; - vn.skinid = -1U; - model->vertex = _m3d_addnorm(model->vertex, &model->numvertex, &vn, &vi[i]); + for(i = 0, v0 = &model->vertex[n]; i < n; i++, v0++) { + w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z)); + v0->x *= w; v0->y *= w; v0->z *= w; + v0->skinid = -1U; } - for(j = 0; j < model->numface; j++) - for(k = 0; k < 3; k++) - model->face[j].normal[k] = vi[model->face[j].vertex[k]]; M3D_FREE(norm); - M3D_FREE(ni); - M3D_FREE(vi); } } #endif if(model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) { #ifndef M3D_NOWEIGHTS + M3D_LOG("Generating weight cross-reference"); for(i = 0; i < model->numvertex; i++) { - if(model->vertex[i].skinid < M3D_INDEXMAX) { + if(model->vertex[i].skinid < model->numskin) { sk = &model->skin[model->vertex[i].skinid]; w = (M3D_FLOAT)0.0; for(j = 0; j < M3D_NUMBONE && sk->boneid[j] != (M3D_INDEX)-1U && sk->weight[j] > (M3D_FLOAT)0.0; j++) @@ -3088,6 +3565,7 @@ postprocess: } #endif #ifndef M3D_NOANIMATION + M3D_LOG("Calculating bone transformation matrices"); for(i = 0; i < model->numbone; i++) { b = &model->bone[i]; if(model->bone[i].parent == (M3D_INDEX)-1U) { @@ -3155,7 +3633,7 @@ gen: s = 0; m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) { unsigned int i, j, l; - M3D_FLOAT r[16], t, d; + M3D_FLOAT r[16], t, c, d, s; m3db_t *ret; m3dv_t *v, *p, *f; m3dtr_t *tmp; @@ -3208,7 +3686,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) tmp[fr->transform[i].boneid].ori = fr->transform[i].ori; } for(i = 0, j = model->numvertex; i < model->numbone; i++) { - /* LERP interpolation of position */ + /* interpolation of position */ if(ret[i].pos != tmp[i].pos) { p = &model->vertex[ret[i].pos]; f = &model->vertex[tmp[i].pos]; @@ -3218,18 +3696,33 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) v->z = p->z + t * (f->z - p->z); ret[i].pos = j++; } - /* NLERP interpolation of orientation (could have used SLERP, that's nicer, but slower) */ + /* interpolation of orientation */ if(ret[i].ori != tmp[i].ori) { p = &model->vertex[ret[i].ori]; f = &model->vertex[tmp[i].ori]; v = &model->vertex[j]; - d = (p->w * f->w + p->x * f->x + p->y * f->y + p->z * f->z < 0) ? (M3D_FLOAT)-1.0 : (M3D_FLOAT)1.0; - v->x = p->x + t * (d*f->x - p->x); - v->y = p->y + t * (d*f->y - p->y); - v->z = p->z + t * (d*f->z - p->z); - v->w = p->w + t * (d*f->w - p->w); + d = p->w * f->w + p->x * f->x + p->y * f->y + p->z * f->z; + if(d < 0) { d = -d; s = (M3D_FLOAT)-1.0; } else s = (M3D_FLOAT)1.0; +#if 0 + /* don't use SLERP, requires two more variables, libm linkage and it is slow (but nice) */ + a = (M3D_FLOAT)1.0 - t; b = t; + if(d < (M3D_FLOAT)0.999999) { c = acosf(d); b = 1 / sinf(c); a = sinf(a * c) * b; b *= sinf(t * c) * s; } + v->x = p->x * a + f->x * b; + v->y = p->y * a + f->y * b; + v->z = p->z * a + f->z * b; + v->w = p->w * a + f->w * b; +#else + /* approximated NLERP, original approximation by Arseny Kapoulkine, heavily optimized by me */ + c = t - (M3D_FLOAT)0.5; t += t * c * (t - (M3D_FLOAT)1.0) * (((M3D_FLOAT)1.0904 + d * ((M3D_FLOAT)-3.2452 + + d * ((M3D_FLOAT)3.55645 - d * (M3D_FLOAT)1.43519))) * c * c + ((M3D_FLOAT)0.848013 + d * + ((M3D_FLOAT)-1.06021 + d * (M3D_FLOAT)0.215638))); + v->x = p->x + t * (s * f->x - p->x); + v->y = p->y + t * (s * f->y - p->y); + v->z = p->z + t * (s * f->z - p->z); + v->w = p->w + t * (s * f->w - p->w); d = _m3d_rsq(v->w * v->w + v->x * v->x + v->y * v->y + v->z * v->z); v->x *= d; v->y *= d; v->z *= d; v->w *= d; +#endif ret[i].ori = j++; } } @@ -3271,6 +3764,10 @@ void m3d_free(m3d_t *model) for(i = 0; i < model->numbone; i++) if(model->bone[i].name) M3D_FREE(model->bone[i].name); + if(model->shape) + for(i = 0; i < model->numshape; i++) + if(model->shape[i].name) + M3D_FREE(model->shape[i].name); if(model->material) for(i = 0; i < model->nummaterial; i++) if(model->material[i].name) @@ -3283,10 +3780,36 @@ void m3d_free(m3d_t *model) for(i = 0; i < model->numtexture; i++) if(model->texture[i].name) M3D_FREE(model->texture[i].name); - if(model->unknown) - for(i = 0; i < model->numunknown; i++) - if(model->unknown[i]) - M3D_FREE(model->unknown[i]); + if(model->inlined) + for(i = 0; i < model->numinlined; i++) { + if(model->inlined[i].name) + M3D_FREE(model->inlined[i].name); + if(model->inlined[i].data) + M3D_FREE(model->inlined[i].data); + } + if(model->extra) + for(i = 0; i < model->numextra; i++) + if(model->extra[i]) + M3D_FREE(model->extra[i]); + if(model->label) + for(i = 0; i < model->numlabel; i++) { + if(model->label[i].name) { + for(j = i + 1; j < model->numlabel; j++) + if(model->label[j].name == model->label[i].name) + model->label[j].name = NULL; + M3D_FREE(model->label[i].name); + } + if(model->label[i].lang) { + for(j = i + 1; j < model->numlabel; j++) + if(model->label[j].lang == model->label[i].lang) + model->label[j].lang = NULL; + M3D_FREE(model->label[i].lang); + } + if(model->label[i].text) + M3D_FREE(model->label[i].text); + } + if(model->preview.data) + M3D_FREE(model->preview.data); } #endif if(model->flags & M3D_FLG_FREERAW) M3D_FREE(model->raw); @@ -3301,6 +3824,16 @@ void m3d_free(m3d_t *model) if(model->skin) M3D_FREE(model->skin); if(model->vertex) M3D_FREE(model->vertex); if(model->face) M3D_FREE(model->face); + if(model->shape) { + for(i = 0; i < model->numshape; i++) { + if(model->shape[i].cmd) { + for(j = 0; j < model->shape[i].numcmd; j++) + if(model->shape[i].cmd[j].arg) M3D_FREE(model->shape[i].cmd[j].arg); + M3D_FREE(model->shape[i].cmd); + } + } + M3D_FREE(model->shape); + } if(model->material && !(model->flags & M3D_FLG_MTLLIB)) { for(i = 0; i < model->nummaterial; i++) if(model->material[i].prop) M3D_FREE(model->material[i].prop); @@ -3321,8 +3854,9 @@ void m3d_free(m3d_t *model) } M3D_FREE(model->action); } + if(model->label) M3D_FREE(model->label); if(model->inlined) M3D_FREE(model->inlined); - if(model->unknown) M3D_FREE(model->unknown); + if(model->extra) M3D_FREE(model->extra); free(model); } #endif @@ -3333,6 +3867,31 @@ typedef struct { uint32_t offs; } m3dstr_t; +typedef struct { + m3dti_t data; + M3D_INDEX oldidx; + M3D_INDEX newidx; +} m3dtisave_t; + +typedef struct { + m3dv_t data; + M3D_INDEX oldidx; + M3D_INDEX newidx; + unsigned char norm; +} m3dvsave_t; + +typedef struct { + m3ds_t data; + M3D_INDEX oldidx; + M3D_INDEX newidx; +} m3dssave_t; + +typedef struct { + m3df_t data; + int group; + uint8_t opacity; +} m3dfsave_t; + /* create unique list of strings */ static m3dstr_t *_m3d_addstr(m3dstr_t *str, uint32_t *numstr, char *s) { @@ -3387,6 +3946,41 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s) return 0; } +/* compare to faces by their material */ +static int _m3d_facecmp(const void *a, const void *b) { + const m3dfsave_t *A = (const m3dfsave_t*)a, *B = (const m3dfsave_t*)b; + return A->group != B->group ? A->group - B->group : (A->opacity != B->opacity ? (int)B->opacity - (int)A->opacity : + (int)A->data.materialid - (int)B->data.materialid); +} +/* compare face groups */ +static int _m3d_grpcmp(const void *a, const void *b) { return *((uint32_t*)a) - *((uint32_t*)b); } +/* compare UVs */ +static int _m3d_ticmp(const void *a, const void *b) { return memcmp(a, b, sizeof(m3dti_t)); } +/* compare skin groups */ +static int _m3d_skincmp(const void *a, const void *b) { return memcmp(a, b, sizeof(m3ds_t)); } +/* compare vertices */ +static int _m3d_vrtxcmp(const void *a, const void *b) { + int c = memcmp(a, b, 3 * sizeof(M3D_FLOAT)); + if(c) return c; + c = ((m3dvsave_t*)a)->norm - ((m3dvsave_t*)b)->norm; + if(c) return c; + return memcmp(a, b, sizeof(m3dv_t)); +} +/* compare labels */ +_inline int _m3d_strcmp(char *a, char *b) +{ + if(a == NULL && b != NULL) return -1; + if(a != NULL && b == NULL) return 1; + if(a == NULL && b == NULL) return 0; + return strcmp(a, b); +} +static int _m3d_lblcmp(const void *a, const void *b) { + const m3dl_t *A = (const m3dl_t*)a, *B = (const m3dl_t*)b; + int c = _m3d_strcmp(A->lang, B->lang); + if(!c) c = _m3d_strcmp(A->name, B->name); + if(!c) c = _m3d_strcmp(A->text, B->text); + return c; +} /* compare two colors by HSV value */ _inline static int _m3d_cmapcmp(const void *a, const void *b) { @@ -3421,60 +4015,13 @@ static uint32_t *_m3d_addcmap(uint32_t *cmap, uint32_t *numcmap, uint32_t color) static uint32_t _m3d_cmapidx(uint32_t *cmap, uint32_t numcmap, uint32_t color) { uint32_t i; + if(numcmap >= 65536) + return color; for(i = 0; i < numcmap; i++) if(cmap[i] == color) return i; return 0; } -/* add vertex to list */ -static m3dv_t *_m3d_addvrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) -{ - uint32_t i; - if(v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0; - if(v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0; - if(v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0; - if(v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0; - if(vrtx) { - for(i = 0; i < *numvrtx; i++) - if(!memcmp(&vrtx[i], v, sizeof(m3dv_t))) { *idx = i; return vrtx; } - } - vrtx = (m3dv_t*)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t)); - memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t)); - *idx = *numvrtx; - (*numvrtx)++; - return vrtx; -} - -/* add texture map to list */ -static m3dti_t *_m3d_addtmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *t, uint32_t *idx) -{ - uint32_t i; - if(tmap) { - for(i = 0; i < *numtmap; i++) - if(!memcmp(&tmap[i], t, sizeof(m3dti_t))) { *idx = i; return tmap; } - } - tmap = (m3dti_t*)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t)); - memcpy(&tmap[*numtmap], t, sizeof(m3dti_t)); - *idx = *numtmap; - (*numtmap)++; - return tmap; -} - -/* add material to list */ -static m3dm_t **_m3d_addmtrl(m3dm_t **mtrl, uint32_t *nummtrl, m3dm_t *m, uint32_t *idx) -{ - uint32_t i; - if(mtrl) { - for(i = 0; i < *nummtrl; i++) - if(mtrl[i]->name == m->name || !strcmp(mtrl[i]->name, m->name)) { *idx = i; return mtrl; } - } - mtrl = (m3dm_t**)M3D_REALLOC(mtrl, ((*nummtrl) + 1) * sizeof(m3dm_t*)); - mtrl[*nummtrl] = m; - *idx = *nummtrl; - (*nummtrl)++; - return mtrl; -} - /* add index to output */ static unsigned char *_m3d_addidx(unsigned char *out, char type, uint32_t idx) { switch(type) { @@ -3495,23 +4042,27 @@ static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) /* round according to quality */ switch(quality) { case M3D_EXP_INT8: - t = src->x * 127; dst->x = (M3D_FLOAT)t / 127; - t = src->y * 127; dst->y = (M3D_FLOAT)t / 127; - t = src->z * 127; dst->z = (M3D_FLOAT)t / 127; - t = src->w * 127; dst->w = (M3D_FLOAT)t / 127; + t = src->x * 127 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / 127; + t = src->y * 127 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / 127; + t = src->z * 127 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / 127; + t = src->w * 127 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / 127; break; case M3D_EXP_INT16: - t = src->x * 32767; dst->x = (M3D_FLOAT)t / 32767; - t = src->y * 32767; dst->y = (M3D_FLOAT)t / 32767; - t = src->z * 32767; dst->z = (M3D_FLOAT)t / 32767; - t = src->w * 32767; dst->w = (M3D_FLOAT)t / 32767; + t = src->x * 32767 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / 32767; + t = src->y * 32767 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / 32767; + t = src->z * 32767 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / 32767; + t = src->w * 32767 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / 32767; break; } + if(dst->x == (M3D_FLOAT)-0.0) dst->x = (M3D_FLOAT)0.0; + if(dst->y == (M3D_FLOAT)-0.0) dst->y = (M3D_FLOAT)0.0; + if(dst->z == (M3D_FLOAT)-0.0) dst->z = (M3D_FLOAT)0.0; + if(dst->w == (M3D_FLOAT)-0.0) dst->w = (M3D_FLOAT)0.0; } #ifdef M3D_ASCII /* add a bone to ascii output */ -static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX parent, uint32_t level) +static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX parent, uint32_t level, M3D_INDEX *vrtxidx) { uint32_t i, j; char *sn; @@ -3521,9 +4072,9 @@ static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX if(bone[i].parent == parent) { for(j = 0; j < level; j++) *ptr++ = '/'; sn = _m3d_safestr(bone[i].name, 0); - ptr += sprintf(ptr, "%d %d %s\r\n", bone[i].pos, bone[i].ori, sn); + ptr += sprintf(ptr, "%d %d %s\r\n", vrtxidx[bone[i].pos], vrtxidx[bone[i].ori], sn); M3D_FREE(sn); - ptr = _m3d_prtbone(ptr, bone, numbone, i, level + 1); + ptr = _m3d_prtbone(ptr, bone, numbone, i, level + 1, vrtxidx); } } return ptr; @@ -3539,23 +4090,25 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size const char *ol; char *ptr; #endif - char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fi_s; + char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s, fi_s; char *sn = NULL, *sl = NULL, *sa = NULL, *sd = NULL; - unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE]; - unsigned int i, j, k, l, len, chunklen, *length; - float scale = 0.0f, min_x, max_x, min_y, max_y, min_z, max_z; - uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, numtmap = 0, numbone = 0; - uint32_t numskin = 0, numactn = 0, *actn = NULL, numstr = 0, nummtrl = 0, maxt = 0; + unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE], *norm = NULL; + unsigned int i, j, k, l, n, len, chunklen, *length; + M3D_FLOAT scale = (M3D_FLOAT)0.0, min_x, max_x, min_y, max_y, min_z, max_z; + M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL; + uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0; + uint32_t numskin = 0, maxskin = 0, numstr = 0, maxt = 0, maxbone = 0, numgrp = 0, maxgrp = 0, *grpidx = NULL; + uint8_t *opa; + m3dcd_t *cd; + m3dc_t *cmd; m3dstr_t *str = NULL; - m3dv_t *vrtx = NULL, vertex; - m3dti_t *tmap = NULL, tcoord; - m3db_t *bone = NULL; - m3ds_t *skin = NULL; - m3df_t *face = NULL; + m3dvsave_t *vrtx = NULL, vertex; + m3dtisave_t *tmap = NULL, tcoord; + m3dssave_t *skin = NULL, sk; + m3dfsave_t *face = NULL; m3dhdr_t *h = NULL; - m3dm_t *m, **mtrl = NULL; + m3dm_t *m; m3da_t *a; - M3D_INDEX last; if(!model) { if(size) *size = 0; @@ -3565,235 +4118,417 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size #ifdef M3D_ASCII if(flags & M3D_EXP_ASCII) quality = M3D_EXP_DOUBLE; #endif - /* collect array elements that are actually referenced */ - if(model->numface && model->face && !(flags & M3D_EXP_NOFACE)) { - face = (m3df_t*)M3D_MALLOC(model->numface * sizeof(m3df_t)); - if(!face) goto memerr; - memset(face, 255, model->numface * sizeof(m3df_t)); - last = (M3D_INDEX)-1U; - for(i = 0; i < model->numface; i++) { - face[i].materialid = (M3D_INDEX)-1U; - if(!(flags & M3D_EXP_NOMATERIAL) && model->face[i].materialid != last) { - last = model->face[i].materialid; - if(last < model->nummaterial) { - mtrl = _m3d_addmtrl(mtrl, &nummtrl, &model->material[last], &face[i].materialid); - if(!mtrl) goto memerr; + vrtxidx = (M3D_INDEX*)M3D_MALLOC(model->numvertex * sizeof(M3D_INDEX)); + if(!vrtxidx) goto memerr; + memset(vrtxidx, 255, model->numvertex * sizeof(M3D_INDEX)); + if(model->numvertex && !(flags & M3D_EXP_NONORMAL)){ + norm = (unsigned char*)M3D_MALLOC(model->numvertex * sizeof(unsigned char)); + if(!norm) goto memerr; + memset(norm, 0, model->numvertex * sizeof(unsigned char)); + } + if(model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) { + mtrlidx = (M3D_INDEX*)M3D_MALLOC(model->nummaterial * sizeof(M3D_INDEX)); + if(!mtrlidx) goto memerr; + memset(mtrlidx, 255, model->nummaterial * sizeof(M3D_INDEX)); + opa = (uint8_t*)M3D_MALLOC(model->nummaterial * 2 * sizeof(M3D_INDEX)); + if(!opa) goto memerr; + memset(opa, 255, model->nummaterial * 2 * sizeof(M3D_INDEX)); + } + if(model->numtmap && !(flags & M3D_EXP_NOTXTCRD)) { + tmapidx = (M3D_INDEX*)M3D_MALLOC(model->numtmap * sizeof(M3D_INDEX)); + if(!tmapidx) goto memerr; + memset(tmapidx, 255, model->numtmap * sizeof(M3D_INDEX)); + } + /** collect array elements that are actually referenced **/ + if(!(flags & M3D_EXP_NOFACE)) { + /* face */ + if(model->numface && model->face) { + M3D_LOG("Processing mesh face"); + face = (m3dfsave_t*)M3D_MALLOC(model->numface * sizeof(m3dfsave_t)); + if(!face) goto memerr; + for(i = 0; i < model->numface; i++) { + memcpy(&face[i].data, &model->face[i], sizeof(m3df_t)); + face[i].group = 0; + face[i].opacity = 255; + if(!(flags & M3D_EXP_NOMATERIAL) && model->face[i].materialid < model->nummaterial) { + if(model->material[model->face[i].materialid].numprop) { + mtrlidx[model->face[i].materialid] = 0; + if(opa[model->face[i].materialid * 2]) { + m = &model->material[model->face[i].materialid]; + for(j = 0; j < m->numprop; j++) + if(m->prop[j].type == m3dp_Kd) { + opa[model->face[i].materialid * 2 + 1] = ((uint8_t*)&m->prop[j].value.color)[3]; + break; + } + for(j = 0; j < m->numprop; j++) + if(m->prop[j].type == m3dp_d) { + opa[model->face[i].materialid * 2 + 1] = (uint8_t)(m->prop[j].value.fnum * 255); + break; + } + opa[model->face[i].materialid * 2] = 0; + } + face[i].opacity = opa[model->face[i].materialid * 2 + 1]; + } else + face[i].data.materialid = (M3D_INDEX)-1U; + } + for(j = 0; j < 3; j++) { + k = model->face[i].vertex[j]; + if(k < model->numvertex) + vrtxidx[k] = 0; + if(!(flags & M3D_EXP_NOCMAP)) { + cmap = _m3d_addcmap(cmap, &numcmap, model->vertex[k].color); + if(!cmap) goto memerr; + } + k = model->face[i].normal[j]; + if(k < model->numvertex && !(flags & M3D_EXP_NONORMAL)) { + vrtxidx[k] = 0; + norm[k] = 1; + } + k = model->face[i].texcoord[j]; + if(k < model->numtmap && !(flags & M3D_EXP_NOTXTCRD)) + tmapidx[k] = 0; + } + /* convert from CW to CCW */ + if(flags & M3D_EXP_IDOSUCK) { + j = face[i].data.vertex[1]; + face[i].data.vertex[1] = face[i].data.vertex[2]; + face[i].data.vertex[2] = face[i].data.vertex[1]; + j = face[i].data.normal[1]; + face[i].data.normal[1] = face[i].data.normal[2]; + face[i].data.normal[2] = face[i].data.normal[1]; + j = face[i].data.texcoord[1]; + face[i].data.texcoord[1] = face[i].data.texcoord[2]; + face[i].data.texcoord[2] = face[i].data.texcoord[1]; } } - for(j = 0; j < 3; j++) { - k = model->face[i].vertex[j]; - if(quality < M3D_EXP_FLOAT) { - _m3d_round(quality, &model->vertex[k], &vertex); - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &idx); - } else - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[k], &idx); - if(!vrtx) goto memerr; - face[i].vertex[j] = (M3D_INDEX)idx; + } + if(model->numshape && model->shape) { + M3D_LOG("Processing shape face"); + for(i = 0; i < model->numshape; i++) { + if(!model->shape[i].numcmd) continue; + str = _m3d_addstr(str, &numstr, model->shape[i].name); + if(!str) goto memerr; + for(j = 0; j < model->shape[i].numcmd; j++) { + cmd = &model->shape[i].cmd[j]; + if(cmd->type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])) || !cmd->arg) + continue; + if(cmd->type == m3dc_mesh) { + if(numgrp + 2 < maxgrp) { + maxgrp += 1024; + grpidx = (uint32_t*)realloc(grpidx, maxgrp * sizeof(uint32_t)); + if(!grpidx) goto memerr; + if(!numgrp) { + grpidx[0] = 0; + grpidx[1] = model->numface; + numgrp += 2; + } + } + grpidx[numgrp + 0] = cmd->arg[0]; + grpidx[numgrp + 1] = cmd->arg[0] + cmd->arg[1]; + numgrp += 2; + } + cd = &m3d_commandtypes[cmd->type]; + for(k = n = 0, l = cd->p; k < l; k++) + switch(cd->a[((k - n) % (cd->p - n)) + n]) { + case m3dcp_mi_t: + if(!(flags & M3D_EXP_NOMATERIAL) && cmd->arg[k] < model->nummaterial) + mtrlidx[cmd->arg[k]] = 0; + break; + case m3dcp_ti_t: + if(!(flags & M3D_EXP_NOTXTCRD) && cmd->arg[k] < model->numtmap) + tmapidx[cmd->arg[k]] = 0; + break; + case m3dcp_qi_t: + case m3dcp_vi_t: + if(cmd->arg[k] < model->numvertex) + vrtxidx[cmd->arg[k]] = 0; + break; + case m3dcp_va_t: + n = k + 1; l += (cmd->arg[k] - 1) * (cd->p - k - 1); + break; + } + } + } + } + if(model->numface && face) { + if(numgrp && grpidx) { + qsort(grpidx, numgrp, sizeof(uint32_t), _m3d_grpcmp); + for(i = j = 0; i < model->numface && j < numgrp; i++) { + while(j < numgrp && grpidx[j] < i) j++; + face[i].group = j; + } + } + qsort(face, model->numface, sizeof(m3dfsave_t), _m3d_facecmp); + } + if(grpidx) { M3D_FREE(grpidx); grpidx = NULL; } + if(model->numlabel && model->label) { + M3D_LOG("Processing annotation labels"); + for(i = 0; i < model->numlabel; i++) { + str = _m3d_addstr(str, &numstr, model->label[i].name); + str = _m3d_addstr(str, &numstr, model->label[i].lang); + str = _m3d_addstr(str, &numstr, model->label[i].text); if(!(flags & M3D_EXP_NOCMAP)) { - cmap = _m3d_addcmap(cmap, &numcmap, model->vertex[k].color); + cmap = _m3d_addcmap(cmap, &numcmap, model->label[i].color); if(!cmap) goto memerr; } - k = model->face[i].normal[j]; - if(k < model->numvertex && !(flags & M3D_EXP_NONORMAL)) { - if(quality < M3D_EXP_FLOAT) { - _m3d_round(quality, &model->vertex[k], &vertex); - vrtx = _m3d_addnorm(vrtx, &numvrtx, &vertex, &idx); - } else - vrtx = _m3d_addnorm(vrtx, &numvrtx, &model->vertex[k], &idx); - if(!vrtx) goto memerr; - face[i].normal[j] = (M3D_INDEX)idx; - } - k = model->face[i].texcoord[j]; - if(k < model->numtmap) { - switch(quality) { - case M3D_EXP_INT8: - l = model->tmap[k].u * 255; tcoord.u = (M3D_FLOAT)l / 255; - l = model->tmap[k].v * 255; tcoord.v = (M3D_FLOAT)l / 255; - break; - case M3D_EXP_INT16: - l = model->tmap[k].u * 65535; tcoord.u = (M3D_FLOAT)l / 65535; - l = model->tmap[k].v * 65535; tcoord.v = (M3D_FLOAT)l / 65535; - break; - default: - tcoord.u = model->tmap[k].u; - tcoord.v = model->tmap[k].v; - break; - } - if(flags & M3D_EXP_FLIPTXTCRD) - tcoord.v = (M3D_FLOAT)1.0 - tcoord.v; - tmap = _m3d_addtmap(tmap, &numtmap, &tcoord, &idx); - if(!tmap) goto memerr; - face[i].texcoord[j] = (M3D_INDEX)idx; - } - } - /* convert from CW to CCW */ - if(flags & M3D_EXP_IDOSUCK) { - j = face[i].vertex[1]; - face[i].vertex[1] = face[i].vertex[2]; - face[i].vertex[2] = face[i].vertex[1]; - j = face[i].normal[1]; - face[i].normal[1] = face[i].normal[2]; - face[i].normal[2] = face[i].normal[1]; - j = face[i].texcoord[1]; - face[i].texcoord[1] = face[i].texcoord[2]; - face[i].texcoord[2] = face[i].texcoord[1]; + if(model->label[i].vertexid < model->numvertex) + vrtxidx[model->label[i].vertexid] = 0; } + qsort(model->label, model->numlabel, sizeof(m3dl_t), _m3d_lblcmp); } } else if(!(flags & M3D_EXP_NOMATERIAL)) { /* without a face, simply add all materials, because it can be an mtllib */ - nummtrl = model->nummaterial; + for(i = 0; i < model->nummaterial; i++) + mtrlidx[i] = i; } - /* add colors to color map and texture names to string table */ - for(i = 0; i < nummtrl; i++) { - m = !mtrl ? &model->material[i] : mtrl[i]; - str = _m3d_addstr(str, &numstr, m->name); - if(!str) goto memerr; - for(j = 0; j < mtrl[i]->numprop; j++) { - if(!(flags & M3D_EXP_NOCMAP) && m->prop[j].type < 128) { - for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) { - if(m->prop[j].type == m3d_propertytypes[l].id && m3d_propertytypes[l].format == m3dpf_color) { - cmap = _m3d_addcmap(cmap, &numcmap, m->prop[j].value.color); - if(!cmap) goto memerr; - break; - } - } - } - if(m->prop[j].type >= 128 && m->prop[j].value.textureid < model->numtexture && - model->texture[m->prop[j].value.textureid].name) { - str = _m3d_addstr(str, &numstr, model->texture[m->prop[j].value.textureid].name); - if(!str) goto memerr; - } - } - } - /* get bind-pose skeleton and skin */ + /* bind-pose skeleton */ if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) { - numbone = model->numbone; - bone = (m3db_t*)M3D_MALLOC(model->numbone * sizeof(m3db_t)); - if(!bone) goto memerr; - memset(bone, 0, model->numbone * sizeof(m3db_t)); + M3D_LOG("Processing bones"); for(i = 0; i < model->numbone; i++) { - bone[i].parent = model->bone[i].parent; - bone[i].name = model->bone[i].name; - str = _m3d_addstr(str, &numstr, bone[i].name); + str = _m3d_addstr(str, &numstr, model->bone[i].name); if(!str) goto memerr; - if(quality < M3D_EXP_FLOAT) { - _m3d_round(quality, &model->vertex[model->bone[i].pos], &vertex); - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &k); - } else - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[model->bone[i].pos], &k); - if(!vrtx) goto memerr; - bone[i].pos = (M3D_INDEX)k; - if(quality < M3D_EXP_FLOAT) { - _m3d_round(quality, &model->vertex[model->bone[i].ori], &vertex); - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &k); - } else - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[model->bone[i].ori], &k); - if(!vrtx) goto memerr; - bone[i].ori = (M3D_INDEX)k; + k = model->bone[i].pos; + if(k < model->numvertex) + vrtxidx[k] = 0; + k = model->bone[i].ori; + if(k < model->numvertex) + vrtxidx[k] = 0; } } /* actions, animated skeleton poses */ if(model->numaction && model->action && !(flags & M3D_EXP_NOACTION)) { + M3D_LOG("Processing action list"); for(j = 0; j < model->numaction; j++) { a = &model->action[j]; str = _m3d_addstr(str, &numstr, a->name); if(!str) goto memerr; if(a->numframe > 65535) a->numframe = 65535; for(i = 0; i < a->numframe; i++) { - l = numactn; - numactn += (a->frame[i].numtransform * 2); - if(a->frame[i].numtransform > maxt) - maxt = a->frame[i].numtransform; - actn = (uint32_t*)M3D_REALLOC(actn, numactn * sizeof(uint32_t)); - if(!actn) goto memerr; - for(k = 0; k < a->frame[i].numtransform; k++) { - if(quality < M3D_EXP_FLOAT) { - _m3d_round(quality, &model->vertex[a->frame[i].transform[k].pos], &vertex); - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &actn[l++]); - if(!vrtx) goto memerr; - _m3d_round(quality, &model->vertex[a->frame[i].transform[k].ori], &vertex); - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &vertex, &actn[l++]); - } else { - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[a->frame[i].transform[k].pos], &actn[l++]); - if(!vrtx) goto memerr; - vrtx = _m3d_addvrtx(vrtx, &numvrtx, &model->vertex[a->frame[i].transform[k].ori], &actn[l++]); - } - if(!vrtx) goto memerr; + for(l = 0; l < a->frame[i].numtransform; l++) { + k = a->frame[i].transform[l].pos; + if(k < model->numvertex) + vrtxidx[k] = 0; + k = a->frame[i].transform[l].ori; + if(k < model->numvertex) + vrtxidx[k] = 0; } + if(l > maxt) maxt = l; } } } - /* normalize bounding cube and collect referenced skin records */ - if(numvrtx) { - min_x = min_y = min_z = 1e10; - max_x = max_y = max_z = -1e10; - j = model->numskin && model->skin && !(flags & M3D_EXP_NOBONE); - for(i = 0; i < numvrtx; i++) { - if(j && model->numskin && model->skin && vrtx[i].skinid < M3D_INDEXMAX) { - skin = _m3d_addskin(skin, &numskin, &model->skin[vrtx[i].skinid], &idx); - if(!skin) goto memerr; - vrtx[i].skinid = idx; - } - if(vrtx[i].skinid == (M3D_INDEX)-2U) continue; - if(vrtx[i].x > max_x) max_x = vrtx[i].x; - if(vrtx[i].x < min_x) min_x = vrtx[i].x; - if(vrtx[i].y > max_y) max_y = vrtx[i].y; - if(vrtx[i].y < min_y) min_y = vrtx[i].y; - if(vrtx[i].z > max_z) max_z = vrtx[i].z; - if(vrtx[i].z < min_z) min_z = vrtx[i].z; + /* add colors to color map and texture names to string table */ + if(!(flags & M3D_EXP_NOMATERIAL)) { + M3D_LOG("Processing materials"); + for(i = k = 0; i < model->nummaterial; i++) { + if(mtrlidx[i] == (M3D_INDEX)-1U || !model->material[i].numprop) continue; + mtrlidx[i] = k++; + m = &model->material[i]; + str = _m3d_addstr(str, &numstr, m->name); + if(!str) goto memerr; + if(m->prop) + for(j = 0; j < m->numprop; j++) { + if(!(flags & M3D_EXP_NOCMAP) && m->prop[j].type < 128) { + for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) { + if(m->prop[j].type == m3d_propertytypes[l].id && m3d_propertytypes[l].format == m3dpf_color) { + ((uint8_t*)&m->prop[j].value.color)[3] = opa[i * 2 + 1]; + cmap = _m3d_addcmap(cmap, &numcmap, m->prop[j].value.color); + if(!cmap) goto memerr; + break; + } + } + } + if(m->prop[j].type >= 128 && m->prop[j].value.textureid < model->numtexture && + model->texture[m->prop[j].value.textureid].name) { + str = _m3d_addstr(str, &numstr, model->texture[m->prop[j].value.textureid].name); + if(!str) goto memerr; + } + } } - if(min_x < 0.0f) min_x = -min_x; - if(max_x < 0.0f) max_x = -max_x; - if(min_y < 0.0f) min_y = -min_y; - if(max_y < 0.0f) max_y = -max_y; - if(min_z < 0.0f) min_z = -min_z; - if(max_z < 0.0f) max_z = -max_z; + } + /* if there's only one black color, don't store it */ + if(numcmap == 1 && cmap && !cmap[0]) numcmap = 0; + + /** compress lists **/ + if(model->numtmap && !(flags & M3D_EXP_NOTXTCRD)) { + M3D_LOG("Compressing tmap"); + tmap = (m3dtisave_t*)M3D_MALLOC(model->numtmap * sizeof(m3dtisave_t)); + if(!tmap) goto memerr; + for(i = 0; i < model->numtmap; i++) { + if(tmapidx[i] == (M3D_INDEX)-1U) continue; + switch(quality) { + case M3D_EXP_INT8: + l = model->tmap[i].u * 255; tcoord.data.u = (M3D_FLOAT)l / 255; + l = model->tmap[i].v * 255; tcoord.data.v = (M3D_FLOAT)l / 255; + break; + case M3D_EXP_INT16: + l = model->tmap[i].u * 65535; tcoord.data.u = (M3D_FLOAT)l / 65535; + l = model->tmap[i].v * 65535; tcoord.data.v = (M3D_FLOAT)l / 65535; + break; + default: + tcoord.data.u = model->tmap[i].u; + tcoord.data.v = model->tmap[i].v; + break; + } + if(flags & M3D_EXP_FLIPTXTCRD) + tcoord.data.v = (M3D_FLOAT)1.0 - tcoord.data.v; + tcoord.oldidx = i; + memcpy(&tmap[numtmap++], &tcoord, sizeof(m3dtisave_t)); + } + if(numtmap) { + qsort(tmap, numtmap, sizeof(m3dtisave_t), _m3d_ticmp); + memcpy(&tcoord.data, &tmap[0], sizeof(m3dti_t)); + for(i = 0; i < numtmap; i++) { + if(memcmp(&tcoord.data, &tmap[i].data, sizeof(m3dti_t))) { + memcpy(&tcoord.data, &tmap[i].data, sizeof(m3dti_t)); + maxtmap++; + } + tmap[i].newidx = maxtmap; + tmapidx[tmap[i].oldidx] = maxtmap; + } + maxtmap++; + } + } + if(model->numskin && model->skin && !(flags & M3D_EXP_NOBONE)) { + M3D_LOG("Compressing skin"); + skinidx = (M3D_INDEX*)M3D_MALLOC(model->numskin * sizeof(M3D_INDEX)); + if(!skinidx) goto memerr; + skin = (m3dssave_t*)M3D_MALLOC(model->numskin * sizeof(m3dssave_t)); + if(!skin) goto memerr; + memset(skinidx, 255, model->numskin * sizeof(M3D_INDEX)); + for(i = 0; i < model->numvertex; i++) { + if(vrtxidx[i] != (M3D_INDEX)-1U && model->vertex[i].skinid < model->numskin) + skinidx[model->vertex[i].skinid] = 0; + } + for(i = 0; i < model->numskin; i++) { + if(skinidx[i] == (M3D_INDEX)-1U) continue; + memset(&sk, 0, sizeof(m3dssave_t)); + for(j = 0, min_x = (M3D_FLOAT)0.0; j < M3D_NUMBONE && model->skin[i].boneid[j] != (M3D_INDEX)-1U && + model->skin[i].weight[j] > (M3D_FLOAT)0.0; j++) { + sk.data.boneid[j] = model->skin[i].boneid[j]; + sk.data.weight[j] = model->skin[i].weight[j]; + min_x += sk.data.weight[j]; + } + if(j > maxbone) maxbone = j; + if(min_x != (M3D_FLOAT)1.0 && min_x != (M3D_FLOAT)0.0) + for(j = 0; j < M3D_NUMBONE && sk.data.weight[j] > (M3D_FLOAT)0.0; j++) + sk.data.weight[j] /= min_x; + sk.oldidx = i; + memcpy(&skin[numskin++], &sk, sizeof(m3dssave_t)); + } + if(numskin) { + qsort(skin, numskin, sizeof(m3dssave_t), _m3d_skincmp); + memcpy(&sk.data, &skin[0].data, sizeof(m3ds_t)); + for(i = 0; i < numskin; i++) { + if(memcmp(&sk.data, &skin[i].data, sizeof(m3ds_t))) { + memcpy(&sk.data, &skin[i].data, sizeof(m3ds_t)); + maxskin++; + } + skin[i].newidx = maxskin; + skinidx[skin[i].oldidx] = maxskin; + } + maxskin++; + } + } + + M3D_LOG("Compressing vertex list"); + min_x = min_y = min_z = (M3D_FLOAT)1e10; + max_x = max_y = max_z = (M3D_FLOAT)-1e10; + if(vrtxidx) { + vrtx = (m3dvsave_t*)M3D_MALLOC(model->numvertex * sizeof(m3dvsave_t)); + if(!vrtx) goto memerr; + for(i = numvrtx = 0; i < model->numvertex; i++) { + if(vrtxidx[i] == (M3D_INDEX)-1U) continue; + _m3d_round(quality, &model->vertex[i], &vertex.data); + vertex.norm = norm ? norm[i] : 0; + if(vertex.data.skinid != (M3D_INDEX)-2U && !vertex.norm) { + vertex.data.skinid = vertex.data.skinid != (M3D_INDEX)-1U && skinidx ? skinidx[vertex.data.skinid] : (M3D_INDEX)-1U; + if(vertex.data.x > max_x) max_x = vertex.data.x; + if(vertex.data.x < min_x) min_x = vertex.data.x; + if(vertex.data.y > max_y) max_y = vertex.data.y; + if(vertex.data.y < min_y) min_y = vertex.data.y; + if(vertex.data.z > max_z) max_z = vertex.data.z; + if(vertex.data.z < min_z) min_z = vertex.data.z; + } +#ifdef M3D_VERTEXTYPE + vertex.data.type = 0; +#endif + vertex.oldidx = i; + memcpy(&vrtx[numvrtx++], &vertex, sizeof(m3dvsave_t)); + } + if(numvrtx) { + qsort(vrtx, numvrtx, sizeof(m3dvsave_t), _m3d_vrtxcmp); + memcpy(&vertex.data, &vrtx[0].data, sizeof(m3dv_t)); + for(i = 0; i < numvrtx; i++) { + if(memcmp(&vertex.data, &vrtx[i].data, vrtx[i].norm ? 3 * sizeof(M3D_FLOAT) : sizeof(m3dv_t))) { + memcpy(&vertex.data, &vrtx[i].data, sizeof(m3dv_t)); + maxvrtx++; + } + vrtx[i].newidx = maxvrtx; + vrtxidx[vrtx[i].oldidx] = maxvrtx; + } + maxvrtx++; + } + } + if(skinidx) { M3D_FREE(skinidx); skinidx = NULL; } + if(norm) { M3D_FREE(norm); norm = NULL; } + + /* normalize to bounding cube */ + if(numvrtx && !(flags & M3D_EXP_NORECALC)) { + M3D_LOG("Normalizing coordinates"); + if(min_x < (M3D_FLOAT)0.0) min_x = -min_x; + if(max_x < (M3D_FLOAT)0.0) max_x = -max_x; + if(min_y < (M3D_FLOAT)0.0) min_y = -min_y; + if(max_y < (M3D_FLOAT)0.0) max_y = -max_y; + if(min_z < (M3D_FLOAT)0.0) min_z = -min_z; + if(max_z < (M3D_FLOAT)0.0) max_z = -max_z; scale = min_x; if(max_x > scale) scale = max_x; if(min_y > scale) scale = min_y; if(max_y > scale) scale = max_y; if(min_z > scale) scale = min_z; if(max_z > scale) scale = max_z; - if(scale == 0.0f) scale = 1.0f; - if(scale != 1.0f && !(flags & M3D_EXP_NORECALC)) { + if(scale == (M3D_FLOAT)0.0) scale = (M3D_FLOAT)1.0; + if(scale != (M3D_FLOAT)1.0) { for(i = 0; i < numvrtx; i++) { - if(vrtx[i].skinid == (M3D_INDEX)-2U) continue; - vrtx[i].x /= scale; - vrtx[i].y /= scale; - vrtx[i].z /= scale; + if(vrtx[i].data.skinid == (M3D_INDEX)-2U) continue; + vrtx[i].data.x /= scale; + vrtx[i].data.y /= scale; + vrtx[i].data.z /= scale; } } } - /* if there's only one black color, don't store it */ - if(numcmap == 1 && cmap && !cmap[0]) numcmap = 0; - /* at least 3 UV coordinate required for texture mapping */ - if(numtmap < 3 && tmap) numtmap = 0; + if(model->scale > (M3D_FLOAT)0.0) scale = model->scale; + if(scale <= (M3D_FLOAT)0.0) scale = (M3D_FLOAT)1.0; + /* meta info */ sn = _m3d_safestr(model->name && *model->name ? model->name : (char*)"(noname)", 2); sl = _m3d_safestr(model->license ? model->license : (char*)"MIT", 2); sa = _m3d_safestr(model->author ? model->author : getenv("LOGNAME"), 2); if(!sn || !sl || !sa) { -memerr: if(face) M3D_FREE(face); +memerr: if(vrtxidx) M3D_FREE(vrtxidx); + if(mtrlidx) M3D_FREE(mtrlidx); + if(tmapidx) M3D_FREE(tmapidx); + if(skinidx) M3D_FREE(skinidx); + if(grpidx) M3D_FREE(grpidx); + if(norm) M3D_FREE(norm); + if(face) M3D_FREE(face); if(cmap) M3D_FREE(cmap); if(tmap) M3D_FREE(tmap); - if(mtrl) M3D_FREE(mtrl); - if(vrtx) M3D_FREE(vrtx); - if(bone) M3D_FREE(bone); if(skin) M3D_FREE(skin); - if(actn) M3D_FREE(actn); + if(str) M3D_FREE(str); + if(vrtx) M3D_FREE(vrtx); if(sn) M3D_FREE(sn); if(sl) M3D_FREE(sl); if(sa) M3D_FREE(sa); if(sd) M3D_FREE(sd); if(out) M3D_FREE(out); - if(str) M3D_FREE(str); if(h) M3D_FREE(h); M3D_LOG("Out of memory"); model->errcode = M3D_ERR_ALLOC; return NULL; } - if(model->scale > (M3D_FLOAT)0.0) scale = (float)model->scale; - if(scale <= 0.0f) scale = 1.0f; + + M3D_LOG("Serializing model"); #ifdef M3D_ASCII if(flags & M3D_EXP_ASCII) { /* use CRLF to make model creators on Win happy... */ @@ -3808,58 +4543,77 @@ memerr: if(face) M3D_FREE(face); ptr = (char*)out; ptr += sprintf(ptr, "3dmodel %g\r\n%s\r\n%s\r\n%s\r\n%s\r\n\r\n", scale, sn, sl, sa, sd); - M3D_FREE(sn); M3D_FREE(sl); M3D_FREE(sa); M3D_FREE(sd); - sn = sl = sa = sd = NULL; + M3D_FREE(sl); M3D_FREE(sa); M3D_FREE(sd); + sl = sa = sd = NULL; + /* preview chunk */ + if(model->preview.data && model->preview.length) { + sl = _m3d_safestr(sn, 0); + if(sl) { + ptr -= (uint64_t)out; len = (uint64_t)ptr + 20; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl); + M3D_FREE(sl); sl = NULL; + } + } + M3D_FREE(sn); sn = NULL; /* texture map */ if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + numtmap * 32 + 12; + ptr -= (uint64_t)out; len = (uint64_t)ptr + maxtmap * 32 + 12; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Textmap\r\n"); - for(i = 0; i < numtmap; i++) - ptr += sprintf(ptr, "%g %g\r\n", tmap[i].u, tmap[i].v); + last = (M3D_INDEX)-1U; + for(i = 0; i < numtmap; i++) { + if(tmap[i].newidx == last) continue; + last = tmap[i].newidx; + ptr += sprintf(ptr, "%g %g\r\n", tmap[i].data.u, tmap[i].data.v); + } ptr += sprintf(ptr, "\r\n"); } /* vertex chunk */ if(numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + numvrtx * 128 + 10; + ptr -= (uint64_t)out; len = (uint64_t)ptr + maxvrtx * 128 + 10; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Vertex\r\n"); + last = (M3D_INDEX)-1U; for(i = 0; i < numvrtx; i++) { - ptr += sprintf(ptr, "%g %g %g %g", vrtx[i].x, vrtx[i].y, vrtx[i].z, vrtx[i].w); - if(!(flags & M3D_EXP_NOCMAP) && vrtx[i].color) - ptr += sprintf(ptr, " #%08x", vrtx[i].color); - if(!(flags & M3D_EXP_NOBONE) && numbone && numskin && vrtx[i].skinid != (M3D_INDEX)-1U && - vrtx[i].skinid != (M3D_INDEX)-2U) { - if(skin[vrtx[i].skinid].weight[0] == (M3D_FLOAT)1.0) - ptr += sprintf(ptr, " %d", skin[vrtx[i].skinid].boneid[0]); + if(vrtx[i].newidx == last) continue; + last = vrtx[i].newidx; + ptr += sprintf(ptr, "%g %g %g %g", vrtx[i].data.x, vrtx[i].data.y, vrtx[i].data.z, vrtx[i].data.w); + if(!(flags & M3D_EXP_NOCMAP) && vrtx[i].data.color) + ptr += sprintf(ptr, " #%08x", vrtx[i].data.color); + if(!(flags & M3D_EXP_NOBONE) && model->numbone && maxskin && vrtx[i].data.skinid < M3D_INDEXMAX) { + if(skin[vrtx[i].data.skinid].data.weight[0] == (M3D_FLOAT)1.0) + ptr += sprintf(ptr, " %d", skin[vrtx[i].data.skinid].data.boneid[0]); else - for(j = 0; j < M3D_NUMBONE && skin[vrtx[i].skinid].boneid[j] != (M3D_INDEX)-1U && - skin[vrtx[i].skinid].weight[j] > (M3D_FLOAT)0.0; j++) - ptr += sprintf(ptr, " %d:%g", skin[vrtx[i].skinid].boneid[j], - skin[vrtx[i].skinid].weight[j]); + for(j = 0; j < M3D_NUMBONE && skin[vrtx[i].data.skinid].data.boneid[j] != (M3D_INDEX)-1U && + skin[vrtx[i].data.skinid].data.weight[j] > (M3D_FLOAT)0.0; j++) + ptr += sprintf(ptr, " %d:%g", skin[vrtx[i].data.skinid].data.boneid[j], + skin[vrtx[i].data.skinid].data.weight[j]); } ptr += sprintf(ptr, "\r\n"); } ptr += sprintf(ptr, "\r\n"); } /* bones chunk */ - if(numbone && bone && !(flags & M3D_EXP_NOBONE)) { + if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) { ptr -= (uint64_t)out; len = (uint64_t)ptr + 9; - for(i = 0; i < numbone; i++) { - len += strlen(bone[i].name) + 128; + for(i = 0; i < model->numbone; i++) { + len += strlen(model->bone[i].name) + 128; } out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Bones\r\n"); - ptr = _m3d_prtbone(ptr, bone, numbone, (M3D_INDEX)-1U, 0); + ptr = _m3d_prtbone(ptr, model->bone, model->numbone, (M3D_INDEX)-1U, 0, vrtxidx); ptr += sprintf(ptr, "\r\n"); } /* materials */ - if(nummtrl && !(flags & M3D_EXP_NOMATERIAL)) { - for(j = 0; j < nummtrl; j++) { - m = !mtrl ? &model->material[j] : mtrl[j]; + if(model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) { + for(j = 0; j < model->nummaterial; j++) { + if(mtrlidx[j] == (M3D_INDEX)-1U || !model->material[j].numprop || !model->material[j].prop) continue; + m = &model->material[j]; sn = _m3d_safestr(m->name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 12; @@ -3918,16 +4672,37 @@ memerr: if(face) M3D_FREE(face); ptr += sprintf(ptr, "\r\n"); } } + /* procedural face */ + if(model->numinlined && model->inlined && !(flags & M3D_EXP_NOFACE)) { + /* all inlined assets which are not textures should be procedural surfaces */ + for(j = 0; j < model->numinlined; j++) { + if(!model->inlined[j].name || !*model->inlined[j].name || !model->inlined[j].length || !model->inlined[j].data || + (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G')) + continue; + for(i = k = 0; i < model->numtexture; i++) { + if(!strcmp(model->inlined[j].name, model->texture[i].name)) { k = 1; break; } + } + if(k) continue; + sn = _m3d_safestr(model->inlined[j].name, 0); + if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 18; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Procedural\r\n%s\r\n\r\n", sn); + M3D_FREE(sn); sn = NULL; + } + } /* mesh face */ if(model->numface && face && !(flags & M3D_EXP_NOFACE)) { ptr -= (uint64_t)out; len = (uint64_t)ptr + model->numface * 128 + 6; last = (M3D_INDEX)-1U; if(!(flags & M3D_EXP_NOMATERIAL)) for(i = 0; i < model->numface; i++) { - if(face[i].materialid != last) { - last = face[i].materialid; - if(last < nummtrl) - len += strlen(mtrl[last]->name); + j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : (M3D_INDEX)-1U; + if(j != last) { + last = j; + if(last < model->nummaterial) + len += strlen(model->material[last].name); len += 6; } } @@ -3936,10 +4711,11 @@ memerr: if(face) M3D_FREE(face); ptr += sprintf(ptr, "Mesh\r\n"); last = (M3D_INDEX)-1U; for(i = 0; i < model->numface; i++) { - if(!(flags & M3D_EXP_NOMATERIAL) && face[i].materialid != last) { - last = face[i].materialid; - if(last < nummtrl) { - sn = _m3d_safestr(mtrl[last]->name, 0); + j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : (M3D_INDEX)-1U; + if(!(flags & M3D_EXP_NOMATERIAL) && j != last) { + last = j; + if(last < model->nummaterial) { + sn = _m3d_safestr(model->material[last].name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "use %s\r\n", sn); M3D_FREE(sn); sn = NULL; @@ -3948,21 +4724,108 @@ memerr: if(face) M3D_FREE(face); } /* hardcoded triangles. Should be repeated as many times as the number of edges in polygon */ for(j = 0; j < 3; j++) { - ptr += sprintf(ptr, "%s%d", j?" ":"", face[i].vertex[j]); - if(!(flags & M3D_EXP_NOTXTCRD) && (face[i].texcoord[j] != (M3D_INDEX)-1U)) - ptr += sprintf(ptr, "/%d", face[i].texcoord[j]); - if(!(flags & M3D_EXP_NONORMAL) && (face[i].normal[j] != (M3D_INDEX)-1U)) - ptr += sprintf(ptr, "%s/%d", - (flags & M3D_EXP_NOTXTCRD) || (face[i].texcoord[j] == (M3D_INDEX)-1U)? "/" : "", - face[i].normal[j]); + ptr += sprintf(ptr, "%s%d", j?" ":"", vrtxidx[face[i].data.vertex[j]]); + k = -1U; + if(!(flags & M3D_EXP_NOTXTCRD) && (face[i].data.texcoord[j] != (M3D_INDEX)-1U) && + (tmapidx[face[i].data.texcoord[j]] != (M3D_INDEX)-1U)) { + k = tmapidx[face[i].data.texcoord[j]]; + ptr += sprintf(ptr, "/%d", k); + } + if(!(flags & M3D_EXP_NONORMAL) && (face[i].data.normal[j] != (M3D_INDEX)-1U)) + ptr += sprintf(ptr, "%s/%d", k == -1U? "/" : "", vrtxidx[face[i].data.normal[j]]); } ptr += sprintf(ptr, "\r\n"); } ptr += sprintf(ptr, "\r\n"); } + /* mathematical shapes face */ + if(model->numshape && model->numshape && !(flags & M3D_EXP_NOFACE)) { + for(j = 0; j < model->numshape; j++) { + sn = _m3d_safestr(model->shape[j].name, 0); + if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 33; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Shape %s\r\n", sn); + M3D_FREE(sn); sn = NULL; + if(model->shape[j].group != (M3D_INDEX)-1U && !(flags & M3D_EXP_NOBONE)) + ptr += sprintf(ptr, "group %d\r\n", model->shape[j].group); + for(i = 0; i < model->shape[j].numcmd; i++) { + cmd = &model->shape[j].cmd[i]; + if(cmd->type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])) || !cmd->arg) + continue; + cd = &m3d_commandtypes[cmd->type]; + ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(cd->key) + 3; + for(k = 0; k < cd->p; k++) + switch(cd->a[k]) { + case m3dcp_mi_t: if(cmd->arg[k] != -1U) { len += strlen(model->material[cmd->arg[k]].name) + 1; } break; + case m3dcp_va_t: len += cmd->arg[k] * (cd->p - k - 1) * 16; k = cd->p; break; + default: len += 16; break; + } + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "%s", cd->key); + for(k = n = 0, l = cd->p; k < l; k++) { + switch(cd->a[((k - n) % (cd->p - n)) + n]) { + case m3dcp_mi_t: + if(cmd->arg[k] != -1U) { + sn = _m3d_safestr(model->material[cmd->arg[k]].name, 0); + if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, " %s", sn); + M3D_FREE(sn); sn = NULL; + } + break; + case m3dcp_vc_t: ptr += sprintf(ptr, " %g", *((float*)&cmd->arg[k])); break; + case m3dcp_va_t: ptr += sprintf(ptr, " %d[", cmd->arg[k]); + n = k + 1; l += (cmd->arg[k] - 1) * (cd->p - k - 1); + break; + default: ptr += sprintf(ptr, " %d", cmd->arg[k]); break; + } + } + ptr += sprintf(ptr, "%s\r\n", l > cd->p ? " ]" : ""); + } + ptr += sprintf(ptr, "\r\n"); + } + } + /* annotation labels */ + if(model->numlabel && model->label && !(flags & M3D_EXP_NOFACE)) { + for(i = 0, j = 3, length = NULL; i < model->numlabel; i++) { + if(model->label[i].name) j += strlen(model->label[i].name); + if(model->label[i].lang) j += strlen(model->label[i].lang); + if(model->label[i].text) j += strlen(model->label[i].text); + j += 40; + } + ptr -= (uint64_t)out; len = (uint64_t)ptr + j; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + for(i = 0; i < model->numlabel; i++) { + if(!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) { + sl = model->label[i].lang; + sn = model->label[i].name; + sd = _m3d_safestr(sn, 0); + if(!sd) { setlocale(LC_NUMERIC, ol); sn = sl = NULL; goto memerr; } + if(i) ptr += sprintf(ptr, "\r\n"); + ptr += sprintf(ptr, "Labels %s\r\n", sd); + M3D_FREE(sd); sd = NULL; + if(model->label[i].color) + ptr += sprintf(ptr, "color #0x%08x\r\n", model->label[i].color); + if(sl && *sl) { + sd = _m3d_safestr(sl, 0); + if(!sd) { setlocale(LC_NUMERIC, ol); sn = sl = NULL; goto memerr; } + ptr += sprintf(ptr, "lang %s\r\n", sd); + M3D_FREE(sd); sd = NULL; + } + } + sd = _m3d_safestr(model->label[i].text, 2); + if(!sd) { setlocale(LC_NUMERIC, ol); sn = sl = NULL; goto memerr; } + ptr += sprintf(ptr, "%d %s\r\n", model->label[i].vertexid, sd); + M3D_FREE(sd); sd = NULL; + } + ptr += sprintf(ptr, "\r\n"); + sn = sl = NULL; + } /* actions */ - if(model->numaction && model->action && numactn && actn && !(flags & M3D_EXP_NOACTION)) { - l = 0; + if(model->numaction && model->action && !(flags & M3D_EXP_NOACTION)) { for(j = 0; j < model->numaction; j++) { a = &model->action[j]; sn = _m3d_safestr(a->name, 0); @@ -3974,31 +4837,46 @@ memerr: if(face) M3D_FREE(face); if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Action %d %s\r\n", a->durationmsec, sn); M3D_FREE(sn); sn = NULL; - if(a->numframe > 65535) a->numframe = 65535; for(i = 0; i < a->numframe; i++) { ptr += sprintf(ptr, "frame %d\r\n", a->frame[i].msec); for(k = 0; k < a->frame[i].numtransform; k++) { - ptr += sprintf(ptr, "%d %d %d\r\n", a->frame[i].transform[k].boneid, actn[l], actn[l + 1]); - l += 2; + ptr += sprintf(ptr, "%d %d %d\r\n", a->frame[i].transform[k].boneid, + vrtxidx[a->frame[i].transform[k].pos], vrtxidx[a->frame[i].transform[k].ori]); } } ptr += sprintf(ptr, "\r\n"); } } + /* inlined assets */ + if(model->numinlined && model->inlined) { + for(i = j = 0; i < model->numinlined; i++) + if(model->inlined[i].name) + j += strlen(model->inlined[i].name) + 6; + if(j > 0) { + ptr -= (uint64_t)out; len = (uint64_t)ptr + j + 16; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } + ptr += sprintf(ptr, "Assets\r\n"); + for(i = 0; i < model->numinlined; i++) + if(model->inlined[i].name) + ptr += sprintf(ptr, "%s%s\r\n", model->inlined[i].name, strrchr(model->inlined[i].name, '.') ? "" : ".png"); + ptr += sprintf(ptr, "\r\n"); + } + } /* extra info */ - if(model->numunknown && (flags & M3D_EXP_EXTRA)) { - for(i = 0; i < model->numunknown; i++) { - if(model->unknown[i]->length < 9) continue; - ptr -= (uint64_t)out; len = (uint64_t)ptr + 17 + model->unknown[i]->length * 3; + if(model->numextra && (flags & M3D_EXP_EXTRA)) { + for(i = 0; i < model->numextra; i++) { + if(model->extra[i]->length < 9) continue; + ptr -= (uint64_t)out; len = (uint64_t)ptr + 17 + model->extra[i]->length * 3; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Extra %c%c%c%c\r\n", - model->unknown[i]->magic[0] > ' ' ? model->unknown[i]->magic[0] : '_', - model->unknown[i]->magic[1] > ' ' ? model->unknown[i]->magic[1] : '_', - model->unknown[i]->magic[2] > ' ' ? model->unknown[i]->magic[2] : '_', - model->unknown[i]->magic[3] > ' ' ? model->unknown[i]->magic[3] : '_'); - for(j = 0; j < model->unknown[i]->length; j++) - ptr += sprintf(ptr, "%02x ", *((unsigned char *)model->unknown + sizeof(m3dchunk_t) + j)); + model->extra[i]->magic[0] > ' ' ? model->extra[i]->magic[0] : '_', + model->extra[i]->magic[1] > ' ' ? model->extra[i]->magic[1] : '_', + model->extra[i]->magic[2] > ' ' ? model->extra[i]->magic[2] : '_', + model->extra[i]->magic[3] > ' ' ? model->extra[i]->magic[3] : '_'); + for(j = 0; j < model->extra[i]->length; j++) + ptr += sprintf(ptr, "%02x ", *((unsigned char *)model->extra + sizeof(m3dchunk_t) + j)); ptr--; ptr += sprintf(ptr, "\r\n\r\n"); } @@ -4025,16 +4903,6 @@ memerr: if(face) M3D_FREE(face); i = strlen(sa); memcpy((uint8_t*)h + h->length, sa, i+1); h->length += i+1; M3D_FREE(sa); i = strlen(sd); memcpy((uint8_t*)h + h->length, sd, i+1); h->length += i+1; M3D_FREE(sd); sn = sl = sa = sd = NULL; - len = 0; - if(!bone) numbone = 0; - if(skin) - for(i = 0; i < numskin; i++) { - for(j = k = 0; j < M3D_NUMBONE; j++) - if(skin[i].boneid[j] != (M3D_INDEX)-1U && skin[i].weight[j] > (M3D_FLOAT)0.0) k++; - if(k > len) len = k; - } - else - numskin = 0; if(model->inlined) for(i = 0; i < model->numinlined; i++) { if(model->inlined[i].name && *model->inlined[i].name && model->inlined[i].length > 0) { @@ -4048,14 +4916,19 @@ memerr: if(face) M3D_FREE(face); if(!h) goto memerr; } vc_s = quality == M3D_EXP_INT8? 1 : (quality == M3D_EXP_INT16? 2 : (quality == M3D_EXP_DOUBLE? 8 : 4)); - vi_s = numvrtx < 254 ? 1 : (numvrtx < 65534 ? 2 : 4); + vi_s = maxvrtx < 254 ? 1 : (maxvrtx < 65534 ? 2 : 4); si_s = h->length - 16 < 254 ? 1 : (h->length - 16 < 65534 ? 2 : 4); ci_s = !numcmap || !cmap ? 0 : (numcmap < 254 ? 1 : (numcmap < 65534 ? 2 : 4)); - ti_s = !numtmap || !tmap ? 0 : (numtmap < 254 ? 1 : (numtmap < 65534 ? 2 : 4)); - bi_s = !numbone || !bone ? 0 : (numbone < 254 ? 1 : (numbone < 65534 ? 2 : 4)); - nb_s = len < 2 ? 1 : (len == 2 ? 2 : (len <= 4 ? 4 : 8)); - sk_s = !numbone || !numskin ? 0 : (numskin < 254 ? 1 : (numskin < 65534 ? 2 : 4)); - fi_s = maxt < 254 ? 1 : (maxt < 65534 ? 2 : 4); + ti_s = !maxtmap || !tmap ? 0 : (maxtmap < 254 ? 1 : (maxtmap < 65534 ? 2 : 4)); + bi_s = !model->numbone || !model->bone || (flags & M3D_EXP_NOBONE)? 0 : (model->numbone < 254 ? 1 : + (model->numbone < 65534 ? 2 : 4)); + nb_s = maxbone < 2 ? 1 : (maxbone == 2 ? 2 : (maxbone <= 4 ? 4 : 8)); + sk_s = !bi_s || !maxskin || !skin ? 0 : (maxskin < 254 ? 1 : (maxskin < 65534 ? 2 : 4)); + fc_s = maxt < 254 ? 1 : (maxt < 65534 ? 2 : 4); + hi_s = !model->numshape || !model->shape || (flags & M3D_EXP_NOFACE)? 0 : (model->numshape < 254 ? 1 : + (model->numshape < 65534 ? 2 : 4)); + fi_s = !model->numface || !model->face || (flags & M3D_EXP_NOFACE)? 0 : (model->numface < 254 ? 1 : + (model->numface < 65534 ? 2 : 4)); h->types = (vc_s == 8 ? (3<<0) : (vc_s == 2 ? (1<<0) : (vc_s == 1 ? (0<<0) : (2<<0)))) | (vi_s == 2 ? (1<<2) : (vi_s == 1 ? (0<<2) : (2<<2))) | (si_s == 2 ? (1<<4) : (si_s == 1 ? (0<<4) : (2<<4))) | @@ -4064,8 +4937,20 @@ memerr: if(face) M3D_FREE(face); (bi_s == 2 ? (1<<10): (bi_s == 1 ? (0<<10): (bi_s == 4 ? (2<<10) : (3<<10)))) | (nb_s == 2 ? (1<<12): (nb_s == 1 ? (0<<12): (2<<12))) | (sk_s == 2 ? (1<<14): (sk_s == 1 ? (0<<14): (sk_s == 4 ? (2<<14) : (3<<14)))) | - (fi_s == 2 ? (1<<16): (fi_s == 1 ? (0<<16): (2<<16))) ; + (fc_s == 2 ? (1<<16): (fc_s == 1 ? (0<<16): (2<<16))) | + (hi_s == 2 ? (1<<18): (hi_s == 1 ? (0<<18): (hi_s == 4 ? (2<<18) : (3<<18)))) | + (fi_s == 2 ? (1<<20): (fi_s == 1 ? (0<<20): (fi_s == 4 ? (2<<20) : (3<<20)))); len = h->length; + /* preview image chunk, must be the first if exists */ + if(model->preview.data && model->preview.length) { + chunklen = 8 + model->preview.length; + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "PRVW", 4); + *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + memcpy((uint8_t*)h + len + 8, model->preview.data, model->preview.length); + len += chunklen; + } /* color map */ if(numcmap && cmap && ci_s < 4 && !(flags & M3D_EXP_NOCMAP)) { chunklen = 8 + numcmap * sizeof(uint32_t); @@ -4078,104 +4963,114 @@ memerr: if(face) M3D_FREE(face); } else numcmap = 0; /* texture map */ if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) { - chunklen = 8 + numtmap * vc_s * 2; + chunklen = 8 + maxtmap * vc_s * 2; h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); if(!h) goto memerr; memcpy((uint8_t*)h + len, "TMAP", 4); - *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + length = (uint32_t*)((uint8_t*)h + len + 4); out = (uint8_t*)h + len + 8; + last = (M3D_INDEX)-1U; for(i = 0; i < numtmap; i++) { + if(tmap[i].newidx == last) continue; + last = tmap[i].newidx; switch(vc_s) { - case 1: *out++ = (uint8_t)(tmap[i].u * 255); *out++ = (uint8_t)(tmap[i].v * 255); break; + case 1: *out++ = (uint8_t)(tmap[i].data.u * 255); *out++ = (uint8_t)(tmap[i].data.v * 255); break; case 2: - *((uint16_t*)out) = (uint16_t)(tmap[i].u * 65535); out += 2; - *((uint16_t*)out) = (uint16_t)(tmap[i].v * 65535); out += 2; + *((uint16_t*)out) = (uint16_t)(tmap[i].data.u * 65535); out += 2; + *((uint16_t*)out) = (uint16_t)(tmap[i].data.v * 65535); out += 2; break; - case 4: *((float*)out) = tmap[i].u; out += 4; *((float*)out) = tmap[i].v; out += 4; break; - case 8: *((double*)out) = tmap[i].u; out += 8; *((double*)out) = tmap[i].v; out += 8; break; + case 4: *((float*)out) = tmap[i].data.u; out += 4; *((float*)out) = tmap[i].data.v; out += 4; break; + case 8: *((double*)out) = tmap[i].data.u; out += 8; *((double*)out) = tmap[i].data.v; out += 8; break; } } + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); out = NULL; - len += chunklen; + len += *length; } /* vertex */ if(numvrtx && vrtx) { - chunklen = 8 + numvrtx * (ci_s + sk_s + 4 * vc_s); + chunklen = 8 + maxvrtx * (ci_s + sk_s + 4 * vc_s); h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); if(!h) goto memerr; memcpy((uint8_t*)h + len, "VRTS", 4); - *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + length = (uint32_t*)((uint8_t*)h + len + 4); out = (uint8_t*)h + len + 8; + last = (M3D_INDEX)-1U; for(i = 0; i < numvrtx; i++) { + if(vrtx[i].newidx == last) continue; + last = vrtx[i].newidx; switch(vc_s) { case 1: - *out++ = (int8_t)(vrtx[i].x * 127); - *out++ = (int8_t)(vrtx[i].y * 127); - *out++ = (int8_t)(vrtx[i].z * 127); - *out++ = (int8_t)(vrtx[i].w * 127); + *out++ = (int8_t)(vrtx[i].data.x * 127); + *out++ = (int8_t)(vrtx[i].data.y * 127); + *out++ = (int8_t)(vrtx[i].data.z * 127); + *out++ = (int8_t)(vrtx[i].data.w * 127); break; case 2: - *((int16_t*)out) = (int16_t)(vrtx[i].x * 32767); out += 2; - *((int16_t*)out) = (int16_t)(vrtx[i].y * 32767); out += 2; - *((int16_t*)out) = (int16_t)(vrtx[i].z * 32767); out += 2; - *((int16_t*)out) = (int16_t)(vrtx[i].w * 32767); out += 2; + *((int16_t*)out) = (int16_t)(vrtx[i].data.x * 32767); out += 2; + *((int16_t*)out) = (int16_t)(vrtx[i].data.y * 32767); out += 2; + *((int16_t*)out) = (int16_t)(vrtx[i].data.z * 32767); out += 2; + *((int16_t*)out) = (int16_t)(vrtx[i].data.w * 32767); out += 2; break; case 4: - *((float*)out) = vrtx[i].x; out += 4; - *((float*)out) = vrtx[i].y; out += 4; - *((float*)out) = vrtx[i].z; out += 4; - *((float*)out) = vrtx[i].w; out += 4; + *((float*)out) = vrtx[i].data.x; out += 4; + *((float*)out) = vrtx[i].data.y; out += 4; + *((float*)out) = vrtx[i].data.z; out += 4; + *((float*)out) = vrtx[i].data.w; out += 4; break; case 8: - *((double*)out) = vrtx[i].x; out += 8; - *((double*)out) = vrtx[i].y; out += 8; - *((double*)out) = vrtx[i].z; out += 8; - *((double*)out) = vrtx[i].w; out += 8; + *((double*)out) = vrtx[i].data.x; out += 8; + *((double*)out) = vrtx[i].data.y; out += 8; + *((double*)out) = vrtx[i].data.z; out += 8; + *((double*)out) = vrtx[i].data.w; out += 8; break; } - idx = _m3d_cmapidx(cmap, numcmap, vrtx[i].color); + idx = _m3d_cmapidx(cmap, numcmap, vrtx[i].data.color); switch(ci_s) { case 1: *out++ = (uint8_t)(idx); break; case 2: *((uint16_t*)out) = (uint16_t)(idx); out += 2; break; - case 4: *((uint32_t*)out) = vrtx[i].color; out += 4; break; + case 4: *((uint32_t*)out) = vrtx[i].data.color; out += 4; break; } - out = _m3d_addidx(out, sk_s, numbone && numskin ? vrtx[i].skinid : -1U); + out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid); } + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); out = NULL; - len += chunklen; + len += *length; } /* bones chunk */ - if(numbone && bone && !(flags & M3D_EXP_NOBONE)) { - i = 8 + bi_s + sk_s + numbone * (bi_s + si_s + 2*vi_s); + if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) { + i = 8 + bi_s + sk_s + model->numbone * (bi_s + si_s + 2*vi_s); chunklen = i + numskin * nb_s * (bi_s + 1); h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); if(!h) goto memerr; memcpy((uint8_t*)h + len, "BONE", 4); length = (uint32_t*)((uint8_t*)h + len + 4); out = (uint8_t*)h + len + 8; - out = _m3d_addidx(out, bi_s, numbone); - out = _m3d_addidx(out, sk_s, numskin); - for(i = 0; i < numbone; i++) { - out = _m3d_addidx(out, bi_s, bone[i].parent); - out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, bone[i].name)); - out = _m3d_addidx(out, vi_s, bone[i].pos); - out = _m3d_addidx(out, vi_s, bone[i].ori); + out = _m3d_addidx(out, bi_s, model->numbone); + out = _m3d_addidx(out, sk_s, maxskin); + for(i = 0; i < model->numbone; i++) { + out = _m3d_addidx(out, bi_s, model->bone[i].parent); + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->bone[i].name)); + out = _m3d_addidx(out, vi_s, vrtxidx[model->bone[i].pos]); + out = _m3d_addidx(out, vi_s, vrtxidx[model->bone[i].ori]); } if(numskin && skin && sk_s) { + last = (M3D_INDEX)-1U; for(i = 0; i < numskin; i++) { + if(skin[i].newidx == last) continue; + last = skin[i].newidx; memset(&weights, 0, nb_s); - for(j = 0; j < (uint32_t)nb_s && skin[i].boneid[j] != (M3D_INDEX)-1U && - skin[i].weight[j] > (M3D_FLOAT)0.0; j++) - weights[j] = (uint8_t)(skin[i].weight[j] * 255); + for(j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != (M3D_INDEX)-1U && + skin[i].data.weight[j] > (M3D_FLOAT)0.0; j++) + weights[j] = (uint8_t)(skin[i].data.weight[j] * 255); switch(nb_s) { case 1: weights[0] = 255; break; case 2: *((uint16_t*)out) = *((uint16_t*)&weights[0]); out += 2; break; case 4: *((uint32_t*)out) = *((uint32_t*)&weights[0]); out += 4; break; case 8: *((uint64_t*)out) = *((uint64_t*)&weights[0]); out += 8; break; } - for(j = 0; j < (uint32_t)nb_s && skin[i].boneid[j] != (M3D_INDEX)-1U && - skin[i].weight[j] > (M3D_FLOAT)0.0; j++) { - out = _m3d_addidx(out, bi_s, skin[i].boneid[j]); + for(j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != (M3D_INDEX)-1U && weights[j]; j++) { + out = _m3d_addidx(out, bi_s, skin[i].data.boneid[j]); *length += bi_s; } } @@ -4185,9 +5080,10 @@ memerr: if(face) M3D_FREE(face); len += *length; } /* materials */ - if(nummtrl && !(flags & M3D_EXP_NOMATERIAL)) { - for(j = 0; j < nummtrl; j++) { - m = !mtrl ? &model->material[j] : mtrl[j]; + if(model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) { + for(j = 0; j < model->nummaterial; j++) { + if(mtrlidx[j] == (M3D_INDEX)-1U || !model->material[j].numprop || !model->material[j].prop) continue; + m = &model->material[j]; chunklen = 12 + si_s + m->numprop * 5; h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); if(!h) goto memerr; @@ -4233,6 +5129,30 @@ memerr: if(face) M3D_FREE(face); out = NULL; } } + /* procedural face */ + if(model->numinlined && model->inlined && !(flags & M3D_EXP_NOFACE)) { + /* all inlined assets which are not textures should be procedural surfaces */ + for(j = 0; j < model->numinlined; j++) { + if(!model->inlined[j].name || !model->inlined[j].name[0] || model->inlined[j].length < 4 || + !model->inlined[j].data || (model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && + model->inlined[j].data[3] == 'G')) + continue; + for(i = k = 0; i < model->numtexture; i++) { + if(!strcmp(model->inlined[j].name, model->texture[i].name)) { k = 1; break; } + } + if(k) continue; + numproc++; + chunklen = 8 + si_s; + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "PROC", 4); + *((uint32_t*)((uint8_t*)h + len + 4)) = chunklen; + out = (uint8_t*)h + len + 8; + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->inlined[j].name)); + out = NULL; + len += chunklen; + } + } /* mesh face */ if(model->numface && face && !(flags & M3D_EXP_NOFACE)) { chunklen = 8 + si_s + model->numface * (6 * vi_s + 3 * ti_s + si_s + 1); @@ -4243,41 +5163,123 @@ memerr: if(face) M3D_FREE(face); out = (uint8_t*)h + len + 8; last = (M3D_INDEX)-1U; for(i = 0; i < model->numface; i++) { - if(!(flags & M3D_EXP_NOMATERIAL) && face[i].materialid != last) { - last = face[i].materialid; - if(last < nummtrl) { - idx = _m3d_stridx(str, numstr, !mtrl ? model->material[last].name : mtrl[last]->name); - if(idx) { - *out++ = 0; - out = _m3d_addidx(out, si_s, idx); - } - } + if(!(flags & M3D_EXP_NOMATERIAL) && face[i].data.materialid != last) { + last = face[i].data.materialid; + idx = last < model->nummaterial ? _m3d_stridx(str, numstr, model->material[last].name) : 0; + *out++ = 0; + out = _m3d_addidx(out, si_s, idx); } /* hardcoded triangles. */ k = (3 << 4) | - (((flags & M3D_EXP_NOTXTCRD) || ti_s == 8 || (face[i].texcoord[0] == (M3D_INDEX)-1U && - face[i].texcoord[1] == (M3D_INDEX)-1U && face[i].texcoord[2] == (M3D_INDEX)-1U)) ? 0 : 1) | - (((flags & M3D_EXP_NONORMAL) || (face[i].normal[0] == (M3D_INDEX)-1U && - face[i].normal[1] == (M3D_INDEX)-1U && face[i].normal[2] == (M3D_INDEX)-1U)) ? 0 : 2); + (((flags & M3D_EXP_NOTXTCRD) || !ti_s || face[i].data.texcoord[0] == (M3D_INDEX)-1U || + face[i].data.texcoord[1] == (M3D_INDEX)-1U || face[i].data.texcoord[2] == (M3D_INDEX)-1U) ? 0 : 1) | + (((flags & M3D_EXP_NONORMAL) || face[i].data.normal[0] == (M3D_INDEX)-1U || + face[i].data.normal[1] == (M3D_INDEX)-1U || face[i].data.normal[2] == (M3D_INDEX)-1U) ? 0 : 2); *out++ = k; for(j = 0; j < 3; j++) { - out = _m3d_addidx(out, vi_s, face[i].vertex[j]); + out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.vertex[j]]); if(k & 1) - out = _m3d_addidx(out, ti_s, face[i].texcoord[j]); + out = _m3d_addidx(out, ti_s, tmapidx[face[i].data.texcoord[j]]); if(k & 2) - out = _m3d_addidx(out, vi_s, face[i].normal[j]); + out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]); } } *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); len += *length; out = NULL; } + /* mathematical shapes face */ + if(model->numshape && model->shape && !(flags & M3D_EXP_NOFACE)) { + for(j = 0; j < model->numshape; j++) { + chunklen = 12 + si_s + model->shape[j].numcmd * (M3D_CMDMAXARG + 1) * 4; + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) goto memerr; + memcpy((uint8_t*)h + len, "SHPE", 4); + length = (uint32_t*)((uint8_t*)h + len + 4); + out = (uint8_t*)h + len + 8; + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->shape[j].name)); + out = _m3d_addidx(out, bi_s, model->shape[j].group); + for(i = 0; i < model->shape[j].numcmd; i++) { + cmd = &model->shape[j].cmd[i]; + if(cmd->type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])) || !cmd->arg) + continue; + cd = &m3d_commandtypes[cmd->type]; + *out++ = (cmd->type & 0x7F) | (cmd->type > 127 ? 0x80 : 0); + if(cmd->type > 127) *out++ = (cmd->type >> 7) & 0xff; + for(k = n = 0, l = cd->p; k < l; k++) { + switch(cd->a[((k - n) % (cd->p - n)) + n]) { + case m3dcp_mi_t: + out = _m3d_addidx(out, si_s, cmd->arg[k] < model->nummaterial ? + _m3d_stridx(str, numstr, model->material[cmd->arg[k]].name) : 0); + break; + case m3dcp_vc_t: + min_x = *((float*)&cmd->arg[k]); + switch(vc_s) { + case 1: *out++ = (int8_t)(min_x * 127); break; + case 2: *((int16_t*)out) = (int16_t)(min_x * 32767); out += 2; break; + case 4: *((float*)out) = min_x; out += 4; break; + case 8: *((double*)out) = min_x; out += 8; break; + } + break; + case m3dcp_hi_t: out = _m3d_addidx(out, hi_s, cmd->arg[k]); break; + case m3dcp_fi_t: out = _m3d_addidx(out, fi_s, cmd->arg[k]); break; + case m3dcp_ti_t: out = _m3d_addidx(out, ti_s, cmd->arg[k]); break; + case m3dcp_qi_t: + case m3dcp_vi_t: out = _m3d_addidx(out, vi_s, cmd->arg[k]); break; + case m3dcp_i1_t: out = _m3d_addidx(out, 1, cmd->arg[k]); break; + case m3dcp_i2_t: out = _m3d_addidx(out, 2, cmd->arg[k]); break; + case m3dcp_i4_t: out = _m3d_addidx(out, 4, cmd->arg[k]); break; + case m3dcp_va_t: out = _m3d_addidx(out, 4, cmd->arg[k]); + n = k + 1; l += (cmd->arg[k] - 1) * (cd->p - k - 1); + break; + } + } + } + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + len += *length; + out = NULL; + } + } + /* annotation labels */ + if(model->numlabel && model->label) { + for(i = 0, length = NULL; i < model->numlabel; i++) { + if(!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) { + sl = model->label[i].lang; + sn = model->label[i].name; + if(length) { + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + len += *length; + } + chunklen = 8 + 2 * si_s + ci_s + model->numlabel * (vi_s + si_s); + h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); + if(!h) { sn = NULL; sl = NULL; goto memerr; } + memcpy((uint8_t*)h + len, "LBLS", 4); + length = (uint32_t*)((uint8_t*)h + len + 4); + out = (uint8_t*)h + len + 8; + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].name)); + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].lang)); + idx = _m3d_cmapidx(cmap, numcmap, model->label[i].color); + switch(ci_s) { + case 1: *out++ = (uint8_t)(idx); break; + case 2: *((uint16_t*)out) = (uint16_t)(idx); out += 2; break; + case 4: *((uint32_t*)out) = model->label[i].color; out += 4; break; + } + } + out = _m3d_addidx(out, vi_s, vrtxidx[model->label[i].vertexid]); + out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text)); + } + if(length) { + *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + len += *length; + } + out = NULL; + sn = sl = NULL; + } /* actions */ - if(model->numaction && model->action && numactn && actn && numbone && bone && !(flags & M3D_EXP_NOACTION)) { - l = 0; + if(model->numaction && model->action && model->numbone && model->bone && !(flags & M3D_EXP_NOACTION)) { for(j = 0; j < model->numaction; j++) { a = &model->action[j]; - chunklen = 14 + si_s + a->numframe * (4 + fi_s + maxt * (bi_s + 2 * vi_s)); + chunklen = 14 + si_s + a->numframe * (4 + fc_s + maxt * (bi_s + 2 * vi_s)); h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); if(!h) goto memerr; memcpy((uint8_t*)h + len, "ACTN", 4); @@ -4288,11 +5290,11 @@ memerr: if(face) M3D_FREE(face); *((uint32_t*)out) = (uint32_t)(a->durationmsec); out += 4; for(i = 0; i < a->numframe; i++) { *((uint32_t*)out) = (uint32_t)(a->frame[i].msec); out += 4; - out = _m3d_addidx(out, fi_s, a->frame[i].numtransform); + out = _m3d_addidx(out, fc_s, a->frame[i].numtransform); for(k = 0; k < a->frame[i].numtransform; k++) { out = _m3d_addidx(out, bi_s, a->frame[i].transform[k].boneid); - out = _m3d_addidx(out, vi_s, actn[l++]); - out = _m3d_addidx(out, vi_s, actn[l++]); + out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].pos]); + out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]); } } *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); @@ -4301,10 +5303,18 @@ memerr: if(face) M3D_FREE(face); } } /* inlined assets */ - if(model->numinlined && model->inlined && (flags & M3D_EXP_INLINE)) { + if(model->numinlined && model->inlined && (numproc || (flags & M3D_EXP_INLINE))) { for(j = 0; j < model->numinlined; j++) { - if(!model->inlined[j].name || !*model->inlined[j].name || !model->inlined[j].length) + if(!model->inlined[j].name || !model->inlined[j].name[0] || model->inlined[j].length<4 || !model->inlined[j].data) continue; + if(!(flags & M3D_EXP_INLINE)) { + if(model->inlined[j].data[1] == 'P' && model->inlined[j].data[2] == 'N' && model->inlined[j].data[3] == 'G') + continue; + for(i = k = 0; i < model->numtexture; i++) { + if(!strcmp(model->inlined[j].name, model->texture[i].name)) { k = 1; break; } + } + if(k) continue; + } chunklen = 8 + si_s + model->inlined[j].length; h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); if(!h) goto memerr; @@ -4318,14 +5328,14 @@ memerr: if(face) M3D_FREE(face); } } /* extra chunks */ - if(model->numunknown && model->unknown && (flags & M3D_EXP_EXTRA)) { - for(j = 0; j < model->numunknown; j++) { - if(!model->unknown[j] || model->unknown[j]->length < 8) + if(model->numextra && model->extra && (flags & M3D_EXP_EXTRA)) { + for(j = 0; j < model->numextra; j++) { + if(!model->extra[j] || model->extra[j]->length < 8) continue; - chunklen = model->unknown[j]->length; + chunklen = model->extra[j]->length; h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); if(!h) goto memerr; - memcpy((uint8_t*)h + len, model->unknown[j], chunklen); + memcpy((uint8_t*)h + len, model->extra[j], chunklen); len += chunklen; } } @@ -4336,6 +5346,7 @@ memerr: if(face) M3D_FREE(face); len += 4; /* zlib compress */ if(!(flags & M3D_EXP_NOZLIB)) { + M3D_LOG("Deflating chunks"); z = stbi_zlib_compress((unsigned char *)h, len, (int*)&l, 9); if(z && l > 0 && l < len) { len = l; M3D_FREE(h); h = (m3dhdr_t*)z; } } @@ -4348,15 +5359,17 @@ memerr: if(face) M3D_FREE(face); memcpy(out + 8, h, len - 8); } if(size) *size = out ? len : 0; + if(vrtxidx) M3D_FREE(vrtxidx); + if(mtrlidx) M3D_FREE(mtrlidx); + if(tmapidx) M3D_FREE(tmapidx); + if(skinidx) M3D_FREE(skinidx); + if(norm) M3D_FREE(norm); if(face) M3D_FREE(face); if(cmap) M3D_FREE(cmap); if(tmap) M3D_FREE(tmap); - if(mtrl) M3D_FREE(mtrl); - if(vrtx) M3D_FREE(vrtx); - if(bone) M3D_FREE(bone); if(skin) M3D_FREE(skin); - if(actn) M3D_FREE(actn); if(str) M3D_FREE(str); + if(vrtx) M3D_FREE(vrtx); if(h) M3D_FREE(h); return out; } @@ -4397,6 +5410,14 @@ namespace M3D { this->model = m3d_load((unsigned char *)&data[0], ReadFileCB, FreeCB, mtllib.model); #else Model(); +#endif + } + Model(_unused const unsigned char *data, _unused m3dread_t ReadFileCB, + _unused m3dfree_t FreeCB, _unused M3D::Model mtllib) { +#ifndef M3D_NOIMPORTER + this->model = m3d_load((unsigned char*)data, ReadFileCB, FreeCB, mtllib.model); +#else + Model(); #endif } ~Model() { m3d_free(this->model); } @@ -4413,6 +5434,9 @@ namespace M3D { void setDescription(std::string desc) { this->model->desc = (char*)desc.c_str(); } float getScale() { return this->model->scale; } void setScale(float scale) { this->model->scale = scale; } + std::vector getPreview() { return this->model->preview.data ? + std::vector(this->model->preview.data, this->model->preview.data + this->model->preview.length) : + std::vector(); } std::vector getColorMap() { return this->model->cmap ? std::vector(this->model->cmap, this->model->cmap + this->model->numcmap) : std::vector(); } std::vector getTextureMap() { return this->model->tmap ? std::vector(this->model->tmap, @@ -4462,6 +5486,18 @@ namespace M3D { this->model->vertex + this->model->numvertex) : std::vector(); } std::vector getFace() { return this->model->face ? std::vector(this->model->face, this->model->face + this->model->numface) : std::vector(); } + std::vector getShape() { return this->model->shape ? std::vector(this->model->shape, + this->model->shape + this->model->numshape) : std::vector(); } + std::string getShapeName(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape && + this->model->shape[idx].name && this->model->shape[idx].name[0] ? + std::string(this->model->shape[idx].name) : nullptr; } + unsigned int getShapeGroup(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape ? + this->model->shape[idx].group : 0xFFFFFFFF; } + std::vector getShapeCommands(int idx) { return idx >= 0 && (unsigned int)idx < this->model->numshape && + this->model->shape[idx].cmd ? std::vector(this->model->shape[idx].cmd, this->model->shape[idx].cmd + + this->model->shape[idx].numcmd) : std::vector(); } + std::vector getAnnotationLabels() { return this->model->label ? std::vector(this->model->label, + this->model->label + this->model->numlabel) : std::vector(); } std::vector getSkin() { return this->model->skin ? std::vector(this->model->skin, this->model->skin + this->model->numskin) : std::vector(); } std::vector getActions() { return this->model->action ? std::vector(this->model->action, @@ -4491,9 +5527,9 @@ namespace M3D { return std::vector(pose, pose + this->model->numbone); } std::vector getInlinedAssets() { return this->model->inlined ? std::vector(this->model->inlined, this->model->inlined + this->model->numinlined) : std::vector(); } - std::vector> getUnknowns() { return this->model->unknown ? - std::vector>(this->model->unknown, - this->model->unknown + this->model->numunknown) : std::vector>(); } + std::vector> getExtras() { return this->model->extra ? + std::vector>(this->model->extra, + this->model->extra + this->model->numextra) : std::vector>(); } std::vector Save(_unused int quality, _unused int flags) { #ifdef M3D_EXPORTER unsigned int size; @@ -4513,6 +5549,7 @@ namespace M3D { public: Model(const std::string &data, m3dread_t ReadFileCB, m3dfree_t FreeCB); Model(const std::vector data, m3dread_t ReadFileCB, m3dfree_t FreeCB); + Model(const unsigned char *data, m3dread_t ReadFileCB, m3dfree_t FreeCB); Model(); ~Model(); @@ -4528,6 +5565,7 @@ namespace M3D { void setDescription(std::string desc); float getScale(); void setScale(float scale); + std::vector getPreview(); std::vector getColorMap(); std::vector getTextureMap(); std::vector getTextures(); @@ -4542,6 +5580,11 @@ namespace M3D { m3dtx_t* getMaterialPropertyMap(int idx, int type); std::vector getVertices(); std::vector getFace(); + std::vector getShape(); + std::string getShapeName(int idx); + unsigned int getShapeGroup(int idx); + std::vector getShapeCommands(int idx); + std::vector getAnnotationLabels(); std::vector getSkin(); std::vector getActions(); std::string getActionName(int aidx); @@ -4552,7 +5595,7 @@ namespace M3D { std::vector getActionFrame(int aidx, int fidx, std::vector skeleton); std::vector getActionPose(int aidx, unsigned int msec); std::vector getInlinedAssets(); - std::vector> getUnknowns(); + std::vector> getExtras(); std::vector Save(int quality, int flags); }; diff --git a/test/unit/utM3DImportExport.cpp b/test/unit/utM3DImportExport.cpp index c3a0fb08c..048d3770d 100644 --- a/test/unit/utM3DImportExport.cpp +++ b/test/unit/utM3DImportExport.cpp @@ -54,7 +54,7 @@ class utM3DImportExport : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/WusonBlitz0.m3d", aiProcess_ValidateDataStructure ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/cube_usemtl.m3d", aiProcess_ValidateDataStructure ); #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER return nullptr != scene; #else From e9df0259bba4330774a8e4522f7ac493f9825e96 Mon Sep 17 00:00:00 2001 From: bzt Date: Mon, 18 Nov 2019 03:07:57 +0100 Subject: [PATCH 082/170] Link to the new homepage --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index f02a3b617..272bd4a3f 100644 --- a/Readme.md +++ b/Readme.md @@ -67,7 +67,7 @@ __Importers__: - [LWO](https://en.wikipedia.org/wiki/LightWave_3D) - LWS - LXO -- [M3D](https://gitlab.com/bztsrc/model3d) +- [M3D](https://bztsrc.gitlab.io/model3d) - MD2 - MD3 - MD5 From 2b252bb9a54fb14f6417c56f248abb808f24c457 Mon Sep 17 00:00:00 2001 From: bzt Date: Mon, 18 Nov 2019 06:23:41 +0100 Subject: [PATCH 083/170] My mistake, fixed --- code/M3D/M3DImporter.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 0156950c3..9371e2228 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -396,9 +396,14 @@ void M3DImporter::importMeshes() // we must switch mesh if material changes if(lastMat != m3d->face[i].materialid) { lastMat = m3d->face[i].materialid; - if(pMesh && vertices->size() && faces->size()) { + if(pMesh && vertices && vertices->size() && faces && faces->size()) { populateMesh(pMesh, faces, vertices, normals, texcoords, colors, vertexids); meshes->push_back(pMesh); + delete faces; + delete vertices; + delete normals; + delete texcoords; + delete colors; delete vertexids; // this is not stored in pMesh, just to collect bone vertices } pMesh = new aiMesh; From 301748be6ab91e3d72198a190b7f9b7aa5dc95ce Mon Sep 17 00:00:00 2001 From: bzt Date: Mon, 18 Nov 2019 15:22:15 +0100 Subject: [PATCH 084/170] Make Clang happy --- code/M3D/m3d.h | 2 ++ test/unit/utM3DImportExport.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 767e15d5a..1b88c9559 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -339,6 +339,7 @@ enum { m3dc_cylinder, m3dc_shpere, m3dc_torus, + m3dc_cone, m3dc_cube }; @@ -602,6 +603,7 @@ static m3dcd_t m3d_commandtypes[] = { M3D_CMDDEF(m3dc_cylinder,"cylinder",6, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, 0, 0), M3D_CMDDEF(m3dc_shpere, "shpere", 2, m3dcp_vi_t, m3dcp_vc_t, 0, 0, 0, 0, 0, 0), M3D_CMDDEF(m3dc_torus, "torus", 4, m3dcp_vi_t, m3dcp_qi_t, m3dcp_vc_t, m3dcp_vc_t, 0, 0, 0, 0), + M3D_CMDDEF(m3dc_cone, "cone", 3, m3dcp_vi_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0), M3D_CMDDEF(m3dc_cube, "cube", 3, m3dcp_vi_t, m3dcp_vi_t, m3dcp_vi_t, 0, 0, 0, 0, 0) }; #endif diff --git a/test/unit/utM3DImportExport.cpp b/test/unit/utM3DImportExport.cpp index 048d3770d..31028235d 100644 --- a/test/unit/utM3DImportExport.cpp +++ b/test/unit/utM3DImportExport.cpp @@ -54,7 +54,7 @@ class utM3DImportExport : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/cube_usemtl.m3d", aiProcess_ValidateDataStructure ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/cube_normals.m3d", aiProcess_ValidateDataStructure ); #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER return nullptr != scene; #else From 80f5283b2fd3fac7dc612e2163b38786ebe1125e Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Mon, 18 Nov 2019 16:57:01 +0000 Subject: [PATCH 085/170] Error string of Importer should contain a message in case of an exception --- code/Common/Importer.cpp | 4 +- include/assimp/Exceptional.h | 10 + test/models/glTF2/MissingBin/BoxTextured.gltf | 181 ++++++++++++++++++ test/unit/utglTF2ImportExport.cpp | 9 + 4 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 test/models/glTF2/MissingBin/BoxTextured.gltf diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index 91b50859a..880b8e83d 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -493,7 +493,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, ReadFile(fbuff,pFlags); SetIOHandler(io); - ASSIMP_END_EXCEPTION_REGION(const aiScene*); + ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString); return pimpl->mScene; } @@ -710,7 +710,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS // either successful or failure - the pointer expresses it anyways - ASSIMP_END_EXCEPTION_REGION(const aiScene*); + ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString); return pimpl->mScene; } diff --git a/include/assimp/Exceptional.h b/include/assimp/Exceptional.h index 6bb6ce1e3..f0d23d0f3 100644 --- a/include/assimp/Exceptional.h +++ b/include/assimp/Exceptional.h @@ -119,6 +119,16 @@ struct ExceptionSwallower { {\ try { +#define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString)\ + } catch(const DeadlyImportError& e) {\ + ASSIMP_END_EXCEPTION_REGION_errorString = e.what();\ + return ExceptionSwallower()();\ + } catch(...) {\ + ASSIMP_END_EXCEPTION_REGION_errorString = "Unknown exception";\ + return ExceptionSwallower()();\ + }\ +} + #define ASSIMP_END_EXCEPTION_REGION(type)\ } catch(...) {\ return ExceptionSwallower()();\ diff --git a/test/models/glTF2/MissingBin/BoxTextured.gltf b/test/models/glTF2/MissingBin/BoxTextured.gltf new file mode 100644 index 000000000..88d65391e --- /dev/null +++ b/test/models/glTF2/MissingBin/BoxTextured.gltf @@ -0,0 +1,181 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6.0, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "name": "Texture" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "CesiumLogoFlat.png" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 33648, + "wrapT": 33071 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 768, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 840, + "uri": "BoxTextured0.bin" + } + ] +} diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 6925098b9..3c1f6fea6 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -419,4 +419,13 @@ TEST_F( utglTF2ImportExport, crash_in_anim_mesh_destructor ) { ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Sample-Models/AnimatedMorphCube-glTF/AnimatedMorphCube_out.glTF")); } +TEST_F(utglTF2ImportExport, error_string_preserved) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/MissingBin/BoxTextured.gltf", + aiProcess_ValidateDataStructure); + ASSERT_EQ(nullptr, scene); + std::string error = importer.GetErrorString(); + ASSERT_NE(error.find("BoxTextured0.bin"), std::string::npos) << "Error string should contain an error about missing .bin file"; +} + #endif // ASSIMP_BUILD_NO_EXPORT From 83e9c551f5d1476a44833d82db8f960282479803 Mon Sep 17 00:00:00 2001 From: bzt Date: Mon, 18 Nov 2019 18:31:53 +0100 Subject: [PATCH 086/170] stbi functions prefixed for those who do not know how to use inlcude --- code/M3D/m3d.h | 822 +++++++++++++++++++++++-------------------------- 1 file changed, 390 insertions(+), 432 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 1b88c9559..a73e7a02c 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -616,7 +616,7 @@ static m3dcd_t m3d_commandtypes[] = { stb_image - v2.23 - public domain image loader - http://nothings.org/stb_image.h */ -static const char *stbi__g_failure_reason; +static const char *_m3dstbi__g_failure_reason; enum { @@ -635,57 +635,56 @@ enum STBI__SCAN_header }; -typedef unsigned char stbi_uc; -typedef unsigned short stbi_us; +typedef unsigned short _m3dstbi_us; -typedef uint16_t stbi__uint16; -typedef int16_t stbi__int16; -typedef uint32_t stbi__uint32; -typedef int32_t stbi__int32; +typedef uint16_t _m3dstbi__uint16; +typedef int16_t _m3dstbi__int16; +typedef uint32_t _m3dstbi__uint32; +typedef int32_t _m3dstbi__int32; typedef struct { - stbi__uint32 img_x, img_y; + _m3dstbi__uint32 img_x, img_y; int img_n, img_out_n; void *io_user_data; int read_from_callbacks; int buflen; - stbi_uc buffer_start[128]; + unsigned char buffer_start[128]; - stbi_uc *img_buffer, *img_buffer_end; - stbi_uc *img_buffer_original, *img_buffer_original_end; -} stbi__context; + unsigned char *img_buffer, *img_buffer_end; + unsigned char *img_buffer_original, *img_buffer_original_end; +} _m3dstbi__context; typedef struct { int bits_per_channel; int num_channels; int channel_order; -} stbi__result_info; +} _m3dstbi__result_info; #define STBI_ASSERT(v) #define STBI_NOTUSED(v) (void)sizeof(v) -#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) +#define STBI__BYTECAST(x) ((unsigned char) ((x) & 255)) #define STBI_MALLOC(sz) M3D_MALLOC(sz) #define STBI_REALLOC(p,newsz) M3D_REALLOC(p,newsz) #define STBI_FREE(p) M3D_FREE(p) #define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) -_inline static stbi_uc stbi__get8(stbi__context *s) +_inline static unsigned char _m3dstbi__get8(_m3dstbi__context *s) { if (s->img_buffer < s->img_buffer_end) return *s->img_buffer++; return 0; } -_inline static int stbi__at_eof(stbi__context *s) +_inline static int _m3dstbi__at_eof(_m3dstbi__context *s) { return s->img_buffer >= s->img_buffer_end; } -static void stbi__skip(stbi__context *s, int n) +static void _m3dstbi__skip(_m3dstbi__context *s, int n) { if (n < 0) { s->img_buffer = s->img_buffer_end; @@ -694,7 +693,7 @@ static void stbi__skip(stbi__context *s, int n) s->img_buffer += n; } -static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +static int _m3dstbi__getn(_m3dstbi__context *s, unsigned char *buffer, int n) { if (s->img_buffer+n <= s->img_buffer_end) { memcpy(buffer, s->img_buffer, n); @@ -704,72 +703,72 @@ static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) return 0; } -static int stbi__get16be(stbi__context *s) +static int _m3dstbi__get16be(_m3dstbi__context *s) { - int z = stbi__get8(s); - return (z << 8) + stbi__get8(s); + int z = _m3dstbi__get8(s); + return (z << 8) + _m3dstbi__get8(s); } -static stbi__uint32 stbi__get32be(stbi__context *s) +static _m3dstbi__uint32 _m3dstbi__get32be(_m3dstbi__context *s) { - stbi__uint32 z = stbi__get16be(s); - return (z << 16) + stbi__get16be(s); + _m3dstbi__uint32 z = _m3dstbi__get16be(s); + return (z << 16) + _m3dstbi__get16be(s); } -#define stbi__err(x,y) stbi__errstr(y) -static int stbi__errstr(const char *str) +#define _m3dstbi__err(x,y) _m3dstbi__errstr(y) +static int _m3dstbi__errstr(const char *str) { - stbi__g_failure_reason = str; + _m3dstbi__g_failure_reason = str; return 0; } -_inline static void *stbi__malloc(size_t size) +_inline static void *_m3dstbi__malloc(size_t size) { return STBI_MALLOC(size); } -static int stbi__addsizes_valid(int a, int b) +static int _m3dstbi__addsizes_valid(int a, int b) { if (b < 0) return 0; return a <= 2147483647 - b; } -static int stbi__mul2sizes_valid(int a, int b) +static int _m3dstbi__mul2sizes_valid(int a, int b) { if (a < 0 || b < 0) return 0; if (b == 0) return 1; return a <= 2147483647/b; } -static int stbi__mad2sizes_valid(int a, int b, int add) +static int _m3dstbi__mad2sizes_valid(int a, int b, int add) { - return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); + return _m3dstbi__mul2sizes_valid(a, b) && _m3dstbi__addsizes_valid(a*b, add); } -static int stbi__mad3sizes_valid(int a, int b, int c, int add) +static int _m3dstbi__mad3sizes_valid(int a, int b, int c, int add) { - return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && - stbi__addsizes_valid(a*b*c, add); + return _m3dstbi__mul2sizes_valid(a, b) && _m3dstbi__mul2sizes_valid(a*b, c) && + _m3dstbi__addsizes_valid(a*b*c, add); } -static void *stbi__malloc_mad2(int a, int b, int add) +static void *_m3dstbi__malloc_mad2(int a, int b, int add) { - if (!stbi__mad2sizes_valid(a, b, add)) return NULL; - return stbi__malloc(a*b + add); + if (!_m3dstbi__mad2sizes_valid(a, b, add)) return NULL; + return _m3dstbi__malloc(a*b + add); } -static void *stbi__malloc_mad3(int a, int b, int c, int add) +static void *_m3dstbi__malloc_mad3(int a, int b, int c, int add) { - if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; - return stbi__malloc(a*b*c + add); + if (!_m3dstbi__mad3sizes_valid(a, b, c, add)) return NULL; + return _m3dstbi__malloc(a*b*c + add); } -static stbi_uc stbi__compute_y(int r, int g, int b) +static unsigned char _m3dstbi__compute_y(int r, int g, int b) { - return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); + return (unsigned char) (((r*77) + (g*150) + (29*b)) >> 8); } -static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +static unsigned char *_m3dstbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; unsigned char *good; @@ -777,10 +776,10 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + good = (unsigned char *) _m3dstbi__malloc_mad3(req_comp, x, y, 0); if (good == NULL) { STBI_FREE(data); - stbi__err("outofmem", "Out of memory"); + _m3dstbi__err("outofmem", "Out of memory"); return NULL; } @@ -798,10 +797,10 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break; - STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; - STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; - STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; - STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(3,1) { dest[0]=_m3dstbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=_m3dstbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=_m3dstbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=_m3dstbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; default: STBI_ASSERT(0); } @@ -812,29 +811,29 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r return good; } -static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +static _m3dstbi__uint16 _m3dstbi__compute_y_16(int r, int g, int b) { - return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); + return (_m3dstbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); } -static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +static _m3dstbi__uint16 *_m3dstbi__convert_format16(_m3dstbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; - stbi__uint16 *good; + _m3dstbi__uint16 *good; if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + good = (_m3dstbi__uint16 *) _m3dstbi__malloc(req_comp * x * y * 2); if (good == NULL) { STBI_FREE(data); - stbi__err("outofmem", "Out of memory"); + _m3dstbi__err("outofmem", "Out of memory"); return NULL; } for (j=0; j < (int) y; ++j) { - stbi__uint16 *src = data + j * x * img_n ; - stbi__uint16 *dest = good + j * x * req_comp; + _m3dstbi__uint16 *src = data + j * x * img_n ; + _m3dstbi__uint16 *dest = good + j * x * req_comp; #define STBI__COMBO(a,b) ((a)*8+(b)) #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) @@ -846,10 +845,10 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break; - STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; - STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; - STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; - STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(3,1) { dest[0]=_m3dstbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=_m3dstbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=_m3dstbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=_m3dstbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; default: STBI_ASSERT(0); } @@ -865,15 +864,15 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r typedef struct { - stbi__uint16 fast[1 << STBI__ZFAST_BITS]; - stbi__uint16 firstcode[16]; + _m3dstbi__uint16 fast[1 << STBI__ZFAST_BITS]; + _m3dstbi__uint16 firstcode[16]; int maxcode[17]; - stbi__uint16 firstsymbol[16]; - stbi_uc size[288]; - stbi__uint16 value[288]; -} stbi__zhuffman; + _m3dstbi__uint16 firstsymbol[16]; + unsigned char size[288]; + _m3dstbi__uint16 value[288]; +} _m3dstbi__zhuffman; -_inline static int stbi__bitreverse16(int n) +_inline static int _m3dstbi__bitreverse16(int n) { n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); @@ -882,13 +881,13 @@ _inline static int stbi__bitreverse16(int n) return n; } -_inline static int stbi__bit_reverse(int v, int bits) +_inline static int _m3dstbi__bit_reverse(int v, int bits) { STBI_ASSERT(bits <= 16); - return stbi__bitreverse16(v) >> (16-bits); + return _m3dstbi__bitreverse16(v) >> (16-bits); } -static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +static int _m3dstbi__zbuild_huffman(_m3dstbi__zhuffman *z, unsigned char *sizelist, int num) { int i,k=0; int code, next_code[16], sizes[17]; @@ -900,15 +899,15 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) sizes[0] = 0; for (i=1; i < 16; ++i) if (sizes[i] > (1 << i)) - return stbi__err("bad sizes", "Corrupt PNG"); + return _m3dstbi__err("bad sizes", "Corrupt PNG"); code = 0; for (i=1; i < 16; ++i) { next_code[i] = code; - z->firstcode[i] = (stbi__uint16) code; - z->firstsymbol[i] = (stbi__uint16) k; + z->firstcode[i] = (_m3dstbi__uint16) code; + z->firstsymbol[i] = (_m3dstbi__uint16) k; code = (code + sizes[i]); if (sizes[i]) - if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + if (code-1 >= (1 << i)) return _m3dstbi__err("bad codelengths","Corrupt PNG"); z->maxcode[i] = code << (16-i); code <<= 1; k += sizes[i]; @@ -918,11 +917,11 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) int s = sizelist[i]; if (s) { int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; - stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); - z->size [c] = (stbi_uc ) s; - z->value[c] = (stbi__uint16) i; + _m3dstbi__uint16 fastv = (_m3dstbi__uint16) ((s << 9) | i); + z->size [c] = (unsigned char ) s; + z->value[c] = (_m3dstbi__uint16) i; if (s <= STBI__ZFAST_BITS) { - int j = stbi__bit_reverse(next_code[s],s); + int j = _m3dstbi__bit_reverse(next_code[s],s); while (j < (1 << STBI__ZFAST_BITS)) { z->fast[j] = fastv; j += (1 << s); @@ -936,47 +935,47 @@ static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) typedef struct { - stbi_uc *zbuffer, *zbuffer_end; + unsigned char *zbuffer, *zbuffer_end; int num_bits; - stbi__uint32 code_buffer; + _m3dstbi__uint32 code_buffer; char *zout; char *zout_start; char *zout_end; int z_expandable; - stbi__zhuffman z_length, z_distance; -} stbi__zbuf; + _m3dstbi__zhuffman z_length, z_distance; +} _m3dstbi__zbuf; -_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +_inline static unsigned char _m3dstbi__zget8(_m3dstbi__zbuf *z) { if (z->zbuffer >= z->zbuffer_end) return 0; return *z->zbuffer++; } -static void stbi__fill_bits(stbi__zbuf *z) +static void _m3dstbi__fill_bits(_m3dstbi__zbuf *z) { do { STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); - z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->code_buffer |= (unsigned int) _m3dstbi__zget8(z) << z->num_bits; z->num_bits += 8; } while (z->num_bits <= 24); } -_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +_inline static unsigned int _m3dstbi__zreceive(_m3dstbi__zbuf *z, int n) { unsigned int k; - if (z->num_bits < n) stbi__fill_bits(z); + if (z->num_bits < n) _m3dstbi__fill_bits(z); k = z->code_buffer & ((1 << n) - 1); z->code_buffer >>= n; z->num_bits -= n; return k; } -static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +static int _m3dstbi__zhuffman_decode_slowpath(_m3dstbi__zbuf *a, _m3dstbi__zhuffman *z) { int b,s,k; - k = stbi__bit_reverse(a->code_buffer, 16); + k = _m3dstbi__bit_reverse(a->code_buffer, 16); for (s=STBI__ZFAST_BITS+1; ; ++s) if (k < z->maxcode[s]) break; @@ -988,10 +987,10 @@ static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) return z->value[b]; } -_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +_inline static int _m3dstbi__zhuffman_decode(_m3dstbi__zbuf *a, _m3dstbi__zhuffman *z) { int b,s; - if (a->num_bits < 16) stbi__fill_bits(a); + if (a->num_bits < 16) _m3dstbi__fill_bits(a); b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b) { s = b >> 9; @@ -999,76 +998,76 @@ _inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) a->num_bits -= s; return b & 511; } - return stbi__zhuffman_decode_slowpath(a, z); + return _m3dstbi__zhuffman_decode_slowpath(a, z); } -static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) +static int _m3dstbi__zexpand(_m3dstbi__zbuf *z, char *zout, int n) { char *q; int cur, limit, old_limit; z->zout = zout; - if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + if (!z->z_expandable) return _m3dstbi__err("output buffer limit","Corrupt PNG"); cur = (int) (z->zout - z->zout_start); limit = old_limit = (int) (z->zout_end - z->zout_start); while (cur + n > limit) limit *= 2; q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); STBI_NOTUSED(old_limit); - if (q == NULL) return stbi__err("outofmem", "Out of memory"); + if (q == NULL) return _m3dstbi__err("outofmem", "Out of memory"); z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit; return 1; } -static int stbi__zlength_base[31] = { +static int _m3dstbi__zlength_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; -static int stbi__zlength_extra[31]= +static int _m3dstbi__zlength_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; -static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +static int _m3dstbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; -static int stbi__zdist_extra[32] = +static int _m3dstbi__zdist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; -static int stbi__parse_huffman_block(stbi__zbuf *a) +static int _m3dstbi__parse_huffman_block(_m3dstbi__zbuf *a) { char *zout = a->zout; for(;;) { - int z = stbi__zhuffman_decode(a, &a->z_length); + int z = _m3dstbi__zhuffman_decode(a, &a->z_length); if (z < 256) { - if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + if (z < 0) return _m3dstbi__err("bad huffman code","Corrupt PNG"); if (zout >= a->zout_end) { - if (!stbi__zexpand(a, zout, 1)) return 0; + if (!_m3dstbi__zexpand(a, zout, 1)) return 0; zout = a->zout; } *zout++ = (char) z; } else { - stbi_uc *p; + unsigned char *p; int len,dist; if (z == 256) { a->zout = zout; return 1; } z -= 257; - len = stbi__zlength_base[z]; - if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); - z = stbi__zhuffman_decode(a, &a->z_distance); - if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); - dist = stbi__zdist_base[z]; - if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); - if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + len = _m3dstbi__zlength_base[z]; + if (_m3dstbi__zlength_extra[z]) len += _m3dstbi__zreceive(a, _m3dstbi__zlength_extra[z]); + z = _m3dstbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return _m3dstbi__err("bad huffman code","Corrupt PNG"); + dist = _m3dstbi__zdist_base[z]; + if (_m3dstbi__zdist_extra[z]) dist += _m3dstbi__zreceive(a, _m3dstbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return _m3dstbi__err("bad dist","Corrupt PNG"); if (zout + len > a->zout_end) { - if (!stbi__zexpand(a, zout, len)) return 0; + if (!_m3dstbi__zexpand(a, zout, len)) return 0; zout = a->zout; } - p = (stbi_uc *) (zout - dist); + p = (unsigned char *) (zout - dist); if (dist == 1) { - stbi_uc v = *p; + unsigned char v = *p; if (len) { do *zout++ = v; while (--len); } } else { if (len) { do *zout++ = *p++; while (--len); } @@ -1077,152 +1076,152 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) } } -static int stbi__compute_huffman_codes(stbi__zbuf *a) +static int _m3dstbi__compute_huffman_codes(_m3dstbi__zbuf *a) { - static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - stbi__zhuffman z_codelength; - stbi_uc lencodes[286+32+137]; - stbi_uc codelength_sizes[19]; + static unsigned char length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + _m3dstbi__zhuffman z_codelength; + unsigned char lencodes[286+32+137]; + unsigned char codelength_sizes[19]; int i,n; - int hlit = stbi__zreceive(a,5) + 257; - int hdist = stbi__zreceive(a,5) + 1; - int hclen = stbi__zreceive(a,4) + 4; + int hlit = _m3dstbi__zreceive(a,5) + 257; + int hdist = _m3dstbi__zreceive(a,5) + 1; + int hclen = _m3dstbi__zreceive(a,4) + 4; int ntot = hlit + hdist; memset(codelength_sizes, 0, sizeof(codelength_sizes)); for (i=0; i < hclen; ++i) { - int s = stbi__zreceive(a,3); - codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + int s = _m3dstbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (unsigned char) s; } - if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + if (!_m3dstbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; n = 0; while (n < ntot) { - int c = stbi__zhuffman_decode(a, &z_codelength); - if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + int c = _m3dstbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return _m3dstbi__err("bad codelengths", "Corrupt PNG"); if (c < 16) - lencodes[n++] = (stbi_uc) c; + lencodes[n++] = (unsigned char) c; else { - stbi_uc fill = 0; + unsigned char fill = 0; if (c == 16) { - c = stbi__zreceive(a,2)+3; - if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + c = _m3dstbi__zreceive(a,2)+3; + if (n == 0) return _m3dstbi__err("bad codelengths", "Corrupt PNG"); fill = lencodes[n-1]; } else if (c == 17) - c = stbi__zreceive(a,3)+3; + c = _m3dstbi__zreceive(a,3)+3; else { STBI_ASSERT(c == 18); - c = stbi__zreceive(a,7)+11; + c = _m3dstbi__zreceive(a,7)+11; } - if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + if (ntot - n < c) return _m3dstbi__err("bad codelengths", "Corrupt PNG"); memset(lencodes+n, fill, c); n += c; } } - if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); - if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; - if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + if (n != ntot) return _m3dstbi__err("bad codelengths","Corrupt PNG"); + if (!_m3dstbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!_m3dstbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; return 1; } -_inline static int stbi__parse_uncompressed_block(stbi__zbuf *a) +_inline static int _m3dstbi__parse_uncompressed_block(_m3dstbi__zbuf *a) { - stbi_uc header[4]; + unsigned char header[4]; int len,nlen,k; if (a->num_bits & 7) - stbi__zreceive(a, a->num_bits & 7); + _m3dstbi__zreceive(a, a->num_bits & 7); k = 0; while (a->num_bits > 0) { - header[k++] = (stbi_uc) (a->code_buffer & 255); + header[k++] = (unsigned char) (a->code_buffer & 255); a->code_buffer >>= 8; a->num_bits -= 8; } STBI_ASSERT(a->num_bits == 0); while (k < 4) - header[k++] = stbi__zget8(a); + header[k++] = _m3dstbi__zget8(a); len = header[1] * 256 + header[0]; nlen = header[3] * 256 + header[2]; - if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); - if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (nlen != (len ^ 0xffff)) return _m3dstbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return _m3dstbi__err("read past buffer","Corrupt PNG"); if (a->zout + len > a->zout_end) - if (!stbi__zexpand(a, a->zout, len)) return 0; + if (!_m3dstbi__zexpand(a, a->zout, len)) return 0; memcpy(a->zout, a->zbuffer, len); a->zbuffer += len; a->zout += len; return 1; } -static int stbi__parse_zlib_header(stbi__zbuf *a) +static int _m3dstbi__parse_zlib_header(_m3dstbi__zbuf *a) { - int cmf = stbi__zget8(a); + int cmf = _m3dstbi__zget8(a); int cm = cmf & 15; /* int cinfo = cmf >> 4; */ - int flg = stbi__zget8(a); - if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); - if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); - if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); + int flg = _m3dstbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return _m3dstbi__err("bad zlib header","Corrupt PNG"); + if (flg & 32) return _m3dstbi__err("no preset dict","Corrupt PNG"); + if (cm != 8) return _m3dstbi__err("bad compression","Corrupt PNG"); return 1; } -static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; -static void stbi__init_zdefaults(void) +static unsigned char _m3dstbi__zdefault_length[288], _m3dstbi__zdefault_distance[32]; +static void _m3dstbi__init_zdefaults(void) { int i; - for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; - for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; - for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; - for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + for (i=0; i <= 143; ++i) _m3dstbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) _m3dstbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) _m3dstbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) _m3dstbi__zdefault_length[i] = 8; - for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; + for (i=0; i <= 31; ++i) _m3dstbi__zdefault_distance[i] = 5; } -static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +static int _m3dstbi__parse_zlib(_m3dstbi__zbuf *a, int parse_header) { int final, type; if (parse_header) - if (!stbi__parse_zlib_header(a)) return 0; + if (!_m3dstbi__parse_zlib_header(a)) return 0; a->num_bits = 0; a->code_buffer = 0; do { - final = stbi__zreceive(a,1); - type = stbi__zreceive(a,2); + final = _m3dstbi__zreceive(a,1); + type = _m3dstbi__zreceive(a,2); if (type == 0) { - if (!stbi__parse_uncompressed_block(a)) return 0; + if (!_m3dstbi__parse_uncompressed_block(a)) return 0; } else if (type == 3) { return 0; } else { if (type == 1) { - if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); - if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; - if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + _m3dstbi__init_zdefaults(); + if (!_m3dstbi__zbuild_huffman(&a->z_length , _m3dstbi__zdefault_length , 288)) return 0; + if (!_m3dstbi__zbuild_huffman(&a->z_distance, _m3dstbi__zdefault_distance, 32)) return 0; } else { - if (!stbi__compute_huffman_codes(a)) return 0; + if (!_m3dstbi__compute_huffman_codes(a)) return 0; } - if (!stbi__parse_huffman_block(a)) return 0; + if (!_m3dstbi__parse_huffman_block(a)) return 0; } } while (!final); return 1; } -static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +static int _m3dstbi__do_zlib(_m3dstbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) { a->zout_start = obuf; a->zout = obuf; a->zout_end = obuf + olen; a->z_expandable = exp; - return stbi__parse_zlib(a, parse_header); + return _m3dstbi__parse_zlib(a, parse_header); } -char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +char *_m3dstbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) { - stbi__zbuf a; - char *p = (char *) stbi__malloc(initial_size); + _m3dstbi__zbuf a; + char *p = (char *) _m3dstbi__malloc(initial_size); if (p == NULL) return NULL; - a.zbuffer = (stbi_uc *) buffer; - a.zbuffer_end = (stbi_uc *) buffer + len; - if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + a.zbuffer = (unsigned char *) buffer; + a.zbuffer_end = (unsigned char *) buffer + len; + if (_m3dstbi__do_zlib(&a, p, initial_size, 1, parse_header)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; } else { @@ -1233,33 +1232,33 @@ char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, typedef struct { - stbi__uint32 length; - stbi__uint32 type; -} stbi__pngchunk; + _m3dstbi__uint32 length; + _m3dstbi__uint32 type; +} _m3dstbi__pngchunk; -static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +static _m3dstbi__pngchunk _m3dstbi__get_chunk_header(_m3dstbi__context *s) { - stbi__pngchunk c; - c.length = stbi__get32be(s); - c.type = stbi__get32be(s); + _m3dstbi__pngchunk c; + c.length = _m3dstbi__get32be(s); + c.type = _m3dstbi__get32be(s); return c; } -_inline static int stbi__check_png_header(stbi__context *s) +_inline static int _m3dstbi__check_png_header(_m3dstbi__context *s) { - static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + static unsigned char png_sig[8] = { 137,80,78,71,13,10,26,10 }; int i; for (i=0; i < 8; ++i) - if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + if (_m3dstbi__get8(s) != png_sig[i]) return _m3dstbi__err("bad png sig","Not a PNG"); return 1; } typedef struct { - stbi__context *s; - stbi_uc *idata, *expanded, *out; + _m3dstbi__context *s; + unsigned char *idata, *expanded, *out; int depth; -} stbi__png; +} _m3dstbi__png; enum { @@ -1272,7 +1271,7 @@ enum { STBI__F_paeth_first }; -static stbi_uc first_row_filter[5] = +static unsigned char first_row_filter[5] = { STBI__F_none, STBI__F_sub, @@ -1281,7 +1280,7 @@ static stbi_uc first_row_filter[5] = STBI__F_paeth_first }; -static int stbi__paeth(int a, int b, int c) +static int _m3dstbi__paeth(int a, int b, int c) { int p = a + b - c; int pa = abs(p-a); @@ -1292,14 +1291,14 @@ static int stbi__paeth(int a, int b, int c) return c; } -static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; +static unsigned char _m3dstbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; -static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +static int _m3dstbi__create_png_image_raw(_m3dstbi__png *a, unsigned char *raw, _m3dstbi__uint32 raw_len, int out_n, _m3dstbi__uint32 x, _m3dstbi__uint32 y, int depth, int color) { int bytes = (depth == 16? 2 : 1); - stbi__context *s = a->s; - stbi__uint32 i,j,stride = x*out_n*bytes; - stbi__uint32 img_len, img_width_bytes; + _m3dstbi__context *s = a->s; + _m3dstbi__uint32 i,j,stride = x*out_n*bytes; + _m3dstbi__uint32 img_len, img_width_bytes; int k; int img_n = s->img_n; @@ -1308,24 +1307,25 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r int width = x; STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); - if (!a->out) return stbi__err("outofmem", "Out of memory"); + a->out = (unsigned char *) _m3dstbi__malloc_mad3(x, y, output_bytes, 0); + if (!a->out) return _m3dstbi__err("outofmem", "Out of memory"); + if (!_m3dstbi__mad3sizes_valid(img_n, x, depth, 7)) return _m3dstbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_len = (img_width_bytes + 1) * y; if (s->img_x == x && s->img_y == y) { - if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); + if (raw_len != img_len) return _m3dstbi__err("not enough pixels","Corrupt PNG"); } else { - if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + if (raw_len < img_len) return _m3dstbi__err("not enough pixels","Corrupt PNG"); } for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *prior = cur - stride; + unsigned char *cur = a->out + stride*j; + unsigned char *prior = cur - stride; int filter = *raw++; if (filter > 4) - return stbi__err("invalid filter","Corrupt PNG"); + return _m3dstbi__err("invalid filter","Corrupt PNG"); if (depth < 8) { STBI_ASSERT(img_width_bytes <= x); @@ -1333,6 +1333,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r filter_bytes = 1; width = img_width_bytes; } + prior = cur - stride; if (j == 0) filter = first_row_filter[filter]; @@ -1342,7 +1343,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r case STBI__F_sub : cur[k] = raw[k]; break; case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; - case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(0,prior[k],0)); break; case STBI__F_avg_first : cur[k] = raw[k]; break; case STBI__F_paeth_first: cur[k] = raw[k]; break; } @@ -1378,9 +1379,9 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k-filter_bytes],0,0)); } break; } #undef STBI__CASE raw += nk; @@ -1395,9 +1396,9 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; - STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; - STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + _m3dstbi__paeth(cur[k- output_bytes],0,0)); } break; } #undef STBI__CASE @@ -1412,9 +1413,9 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r if (depth < 8) { for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; - stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; + unsigned char *cur = a->out + stride*j; + unsigned char *in = a->out + stride*j + x*out_n - img_width_bytes; + unsigned char scale = (color == 0) ? _m3dstbi__depth_scale_table[depth] : 1; if (depth == 4) { for (k=x*img_n; k >= 2; k-=2, ++in) { @@ -1471,8 +1472,8 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r } } } else if (depth == 16) { - stbi_uc *cur = a->out; - stbi__uint16 *cur16 = (stbi__uint16*)cur; + unsigned char *cur = a->out; + _m3dstbi__uint16 *cur16 = (_m3dstbi__uint16*)cur; for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { *cur16 = (cur[0] << 8) | cur[1]; @@ -1482,16 +1483,16 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r return 1; } -static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +static int _m3dstbi__create_png_image(_m3dstbi__png *a, unsigned char *image_data, _m3dstbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) { int bytes = (depth == 16 ? 2 : 1); int out_bytes = out_n * bytes; - stbi_uc *final; + unsigned char *final; int p; if (!interlaced) - return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + return _m3dstbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); - final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + final = (unsigned char *) _m3dstbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; @@ -1501,8 +1502,8 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3 x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; if (x && y) { - stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; - if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + _m3dstbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!_m3dstbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { STBI_FREE(final); return 0; } @@ -1524,11 +1525,11 @@ static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint3 return 1; } -static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char tc[3], int out_n) { - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; + _m3dstbi__context *s = z->s; + _m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y; + unsigned char *p = z->out; STBI_ASSERT(out_n == 2 || out_n == 4); @@ -1547,11 +1548,11 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) return 1; } -static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +static int _m3dstbi__compute_transparency16(_m3dstbi__png *z, _m3dstbi__uint16 tc[3], int out_n) { - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi__uint16 *p = (stbi__uint16*) z->out; + _m3dstbi__context *s = z->s; + _m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y; + _m3dstbi__uint16 *p = (_m3dstbi__uint16*) z->out; STBI_ASSERT(out_n == 2 || out_n == 4); @@ -1570,13 +1571,13 @@ static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int ou return 1; } -static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +static int _m3dstbi__expand_png_palette(_m3dstbi__png *a, unsigned char *palette, int len, int pal_img_n) { - stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; - stbi_uc *p, *temp_out, *orig = a->out; + _m3dstbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + unsigned char *p, *temp_out, *orig = a->out; - p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); - if (p == NULL) return stbi__err("outofmem", "Out of memory"); + p = (unsigned char *) _m3dstbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return _m3dstbi__err("outofmem", "Out of memory"); temp_out = p; @@ -1606,228 +1607,177 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int return 1; } -static int stbi__unpremultiply_on_load = 0; -static int stbi__de_iphone_flag = 0; +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) -void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +static int _m3dstbi__parse_png_file(_m3dstbi__png *z, int scan, int req_comp) { - stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; -} - -void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) -{ - stbi__de_iphone_flag = flag_true_if_should_convert; -} - -static void stbi__de_iphone(stbi__png *z) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; - - if (s->img_out_n == 3) { - for (i=0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 3; - } - } else { - STBI_ASSERT(s->img_out_n == 4); - if (stbi__unpremultiply_on_load) { - for (i=0; i < pixel_count; ++i) { - stbi_uc a = p[3]; - stbi_uc t = p[0]; - if (a) { - p[0] = p[2] * 255 / a; - p[1] = p[1] * 255 / a; - p[2] = t * 255 / a; - } else { - p[0] = p[2]; - p[2] = t; - } - p += 4; - } - } else { - for (i=0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 4; - } - } - } -} - -#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) - -static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) -{ - stbi_uc palette[1024], pal_img_n=0; - stbi_uc has_trans=0, tc[3]; - stbi__uint16 tc16[3]; - stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; - int first=1,k,interlace=0, color=0, is_iphone=0; - stbi__context *s = z->s; + unsigned char palette[1024], pal_img_n=0; + unsigned char has_trans=0, tc[3]; + _m3dstbi__uint16 tc16[3]; + _m3dstbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0; + _m3dstbi__context *s = z->s; z->expanded = NULL; z->idata = NULL; z->out = NULL; - if (!stbi__check_png_header(s)) return 0; + if (!_m3dstbi__check_png_header(s)) return 0; if (scan == STBI__SCAN_type) return 1; for (;;) { - stbi__pngchunk c = stbi__get_chunk_header(s); + _m3dstbi__pngchunk c = _m3dstbi__get_chunk_header(s); switch (c.type) { case STBI__PNG_TYPE('C','g','B','I'): - is_iphone = 1; - stbi__skip(s, c.length); + _m3dstbi__skip(s, c.length); break; case STBI__PNG_TYPE('I','H','D','R'): { int comp,filter; - if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + if (!first) return _m3dstbi__err("multiple IHDR","Corrupt PNG"); first = 0; - if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); - s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); - s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); - z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); - color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); - comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); - filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); - interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); - if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (c.length != 13) return _m3dstbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = _m3dstbi__get32be(s); if (s->img_x > (1 << 24)) return _m3dstbi__err("too large","Very large image (corrupt?)"); + s->img_y = _m3dstbi__get32be(s); if (s->img_y > (1 << 24)) return _m3dstbi__err("too large","Very large image (corrupt?)"); + z->depth = _m3dstbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return _m3dstbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = _m3dstbi__get8(s); if (color > 6) return _m3dstbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return _m3dstbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return _m3dstbi__err("bad ctype","Corrupt PNG"); + comp = _m3dstbi__get8(s); if (comp) return _m3dstbi__err("bad comp method","Corrupt PNG"); + filter= _m3dstbi__get8(s); if (filter) return _m3dstbi__err("bad filter method","Corrupt PNG"); + interlace = _m3dstbi__get8(s); if (interlace>1) return _m3dstbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return _m3dstbi__err("0-pixel image","Corrupt PNG"); if (!pal_img_n) { s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return _m3dstbi__err("too large", "Image too large to decode"); if (scan == STBI__SCAN_header) return 1; } else { s->img_n = 1; - if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + if ((1 << 30) / s->img_x / 4 < s->img_y) return _m3dstbi__err("too large","Corrupt PNG"); } break; } case STBI__PNG_TYPE('P','L','T','E'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return _m3dstbi__err("invalid PLTE","Corrupt PNG"); pal_len = c.length / 3; - if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + if (pal_len * 3 != c.length) return _m3dstbi__err("invalid PLTE","Corrupt PNG"); for (i=0; i < pal_len; ++i) { - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); + palette[i*4+0] = _m3dstbi__get8(s); + palette[i*4+1] = _m3dstbi__get8(s); + palette[i*4+2] = _m3dstbi__get8(s); palette[i*4+3] = 255; } break; } case STBI__PNG_TYPE('t','R','N','S'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return _m3dstbi__err("tRNS after IDAT","Corrupt PNG"); if (pal_img_n) { if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } - if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); - if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + if (pal_len == 0) return _m3dstbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return _m3dstbi__err("bad tRNS len","Corrupt PNG"); pal_img_n = 4; for (i=0; i < c.length; ++i) - palette[i*4+3] = stbi__get8(s); + palette[i*4+3] = _m3dstbi__get8(s); } else { - if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); - if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + if (!(s->img_n & 1)) return _m3dstbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (_m3dstbi__uint32) s->img_n*2) return _m3dstbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; if (z->depth == 16) { - for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); + for (k = 0; k < s->img_n; ++k) tc16[k] = (_m3dstbi__uint16)_m3dstbi__get16be(s); } else { - for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; + for (k = 0; k < s->img_n; ++k) tc[k] = (unsigned char)(_m3dstbi__get16be(s) & 255) * _m3dstbi__depth_scale_table[z->depth]; } } break; } case STBI__PNG_TYPE('I','D','A','T'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return _m3dstbi__err("no PLTE","Corrupt PNG"); if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } if ((int)(ioff + c.length) < (int)ioff) return 0; if (ioff + c.length > idata_limit) { - stbi__uint32 idata_limit_old = idata_limit; - stbi_uc *p; + _m3dstbi__uint32 idata_limit_old = idata_limit; + unsigned char *p; if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; STBI_NOTUSED(idata_limit_old); - p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + p = (unsigned char *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return _m3dstbi__err("outofmem", "Out of memory"); z->idata = p; } - if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + if (!_m3dstbi__getn(s, z->idata+ioff,c.length)) return _m3dstbi__err("outofdata","Corrupt PNG"); ioff += c.length; break; } case STBI__PNG_TYPE('I','E','N','D'): { - stbi__uint32 raw_len, bpl; - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + _m3dstbi__uint32 raw_len, bpl; + if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG"); if (scan != STBI__SCAN_load) return 1; - if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + if (z->idata == NULL) return _m3dstbi__err("no IDAT","Corrupt PNG"); bpl = (s->img_x * z->depth + 7) / 8; raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; - z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + z->expanded = (unsigned char *) _m3dstbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, 1); if (z->expanded == NULL) return 0; STBI_FREE(z->idata); z->idata = NULL; if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) s->img_out_n = s->img_n+1; else s->img_out_n = s->img_n; - if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (!_m3dstbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; if (has_trans) { if (z->depth == 16) { - if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + if (!_m3dstbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; } else { - if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + if (!_m3dstbi__compute_transparency(z, tc, s->img_out_n)) return 0; } } - if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) - stbi__de_iphone(z); if (pal_img_n) { s->img_n = pal_img_n; s->img_out_n = pal_img_n; if (req_comp >= 3) s->img_out_n = req_comp; - if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + if (!_m3dstbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) return 0; + } else if (has_trans) { + ++s->img_n; } STBI_FREE(z->expanded); z->expanded = NULL; return 1; } default: - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (first) return _m3dstbi__err("first not IHDR", "Corrupt PNG"); if ((c.type & (1 << 29)) == 0) { - return stbi__err("invalid_chunk", "PNG not supported: unknown PNG chunk type"); + return _m3dstbi__err("invalid_chunk", "PNG not supported: unknown PNG chunk type"); } - stbi__skip(s, c.length); + _m3dstbi__skip(s, c.length); break; } - stbi__get32be(s); + _m3dstbi__get32be(s); } } -static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +static void *_m3dstbi__do_png(_m3dstbi__png *p, int *x, int *y, int *n, int req_comp, _m3dstbi__result_info *ri) { void *result=NULL; - if (req_comp < 0 || req_comp > 4) { stbi__err("bad req_comp", "Internal error"); return NULL; } - if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - ri->bits_per_channel = p->depth; + if (req_comp < 0 || req_comp > 4) { _m3dstbi__err("bad req_comp", "Internal error"); return NULL; } + if (_m3dstbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { if (ri->bits_per_channel == 8) - result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + result = _m3dstbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); else - result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + result = _m3dstbi__convert_format16((_m3dstbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); p->s->img_out_n = req_comp; if (result == NULL) return result; } @@ -1842,12 +1792,16 @@ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, st return result; } -static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +static void *_m3dstbi__png_load(_m3dstbi__context *s, int *x, int *y, int *comp, int req_comp, _m3dstbi__result_info *ri) { - stbi__png p; + _m3dstbi__png p; p.s = s; - return stbi__do_png(&p, x,y,comp,req_comp, ri); + return _m3dstbi__do_png(&p, x,y,comp,req_comp, ri); } +#define stbi__context _m3dstbi__context +#define stbi__result_info _m3dstbi__result_info +#define stbi__png_load _m3dstbi__png_load +#define stbi_zlib_decode_malloc_guesssize_headerflag _m3dstbi_zlib_decode_malloc_guesssize_headerflag #endif #if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H) @@ -1855,13 +1809,13 @@ static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req stb_image_write - v1.13 - public domain - http://nothings.org/stb/stb_image_write.h */ -typedef unsigned char stbiw_uc; -typedef unsigned short stbiw_us; +typedef unsigned char _m3dstbiw__uc; +typedef unsigned short _m3dstbiw__us; -typedef uint16_t stbiw_uint16; -typedef int16_t stbiw_int16; -typedef uint32_t stbiw_uint32; -typedef int32_t stbiw_int32; +typedef uint16_t _m3dstbiw__uint16; +typedef int16_t _m3dstbiw__int16; +typedef uint32_t _m3dstbiw__uint32; +typedef int32_t _m3dstbiw__int32; #define STBIW_MALLOC(s) M3D_MALLOC(s) #define STBIW_REALLOC(p,ns) M3D_REALLOC(p,ns) @@ -1870,42 +1824,42 @@ typedef int32_t stbiw_int32; #define STBIW_MEMMOVE memmove #define STBIW_UCHAR (uint8_t) #define STBIW_ASSERT(x) -#define stbiw__sbraw(a) ((int *) (a) - 2) -#define stbiw__sbm(a) stbiw__sbraw(a)[0] -#define stbiw__sbn(a) stbiw__sbraw(a)[1] +#define _m3dstbiw___sbraw(a) ((int *) (a) - 2) +#define _m3dstbiw___sbm(a) _m3dstbiw___sbraw(a)[0] +#define _m3dstbiw___sbn(a) _m3dstbiw___sbraw(a)[1] -#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) -#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) -#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) +#define _m3dstbiw___sbneedgrow(a,n) ((a)==0 || _m3dstbiw___sbn(a)+n >= _m3dstbiw___sbm(a)) +#define _m3dstbiw___sbmaybegrow(a,n) (_m3dstbiw___sbneedgrow(a,(n)) ? _m3dstbiw___sbgrow(a,n) : 0) +#define _m3dstbiw___sbgrow(a,n) _m3dstbiw___sbgrowf((void **) &(a), (n), sizeof(*(a))) -#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) -#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) -#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) +#define _m3dstbiw___sbpush(a, v) (_m3dstbiw___sbmaybegrow(a,1), (a)[_m3dstbiw___sbn(a)++] = (v)) +#define _m3dstbiw___sbcount(a) ((a) ? _m3dstbiw___sbn(a) : 0) +#define _m3dstbiw___sbfree(a) ((a) ? STBIW_FREE(_m3dstbiw___sbraw(a)),0 : 0) -static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +static void *_m3dstbiw___sbgrowf(void **arr, int increment, int itemsize) { - int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; - void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + int m = *arr ? 2*_m3dstbiw___sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? _m3dstbiw___sbraw(*arr) : 0, *arr ? (_m3dstbiw___sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); STBIW_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; *arr = (void *) ((int *) p + 2); - stbiw__sbm(*arr) = m; + _m3dstbiw___sbm(*arr) = m; } return *arr; } -static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +static unsigned char *_m3dstbiw___zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) { while (*bitcount >= 8) { - stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + _m3dstbiw___sbpush(data, STBIW_UCHAR(*bitbuffer)); *bitbuffer >>= 8; *bitcount -= 8; } return data; } -static int stbiw__zlib_bitrev(int code, int codebits) +static int _m3dstbiw___zlib_bitrev(int code, int codebits) { int res=0; while (codebits--) { @@ -1915,7 +1869,7 @@ static int stbiw__zlib_bitrev(int code, int codebits) return res; } -static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +static unsigned int _m3dstbiw___zlib_countm(unsigned char *a, unsigned char *b, int limit) { int i; for (i=0; i < limit && i < 258; ++i) @@ -1923,9 +1877,9 @@ static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int l return i; } -static unsigned int stbiw__zhash(unsigned char *data) +static unsigned int _m3dstbiw___zhash(unsigned char *data) { - stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + _m3dstbiw__uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4; @@ -1935,20 +1889,20 @@ static unsigned int stbiw__zhash(unsigned char *data) return hash; } -#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) -#define stbiw__zlib_add(code,codebits) \ - (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) -#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) -#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) -#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) -#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) -#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) -#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) -#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) +#define _m3dstbiw___zlib_flush() (out = _m3dstbiw___zlib_flushf(out, &bitbuf, &bitcount)) +#define _m3dstbiw___zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), _m3dstbiw___zlib_flush()) +#define _m3dstbiw___zlib_huffa(b,c) _m3dstbiw___zlib_add(_m3dstbiw___zlib_bitrev(b,c),c) +#define _m3dstbiw___zlib_huff1(n) _m3dstbiw___zlib_huffa(0x30 + (n), 8) +#define _m3dstbiw___zlib_huff2(n) _m3dstbiw___zlib_huffa(0x190 + (n)-144, 9) +#define _m3dstbiw___zlib_huff3(n) _m3dstbiw___zlib_huffa(0 + (n)-256,7) +#define _m3dstbiw___zlib_huff4(n) _m3dstbiw___zlib_huffa(0xc0 + (n)-280,8) +#define _m3dstbiw___zlib_huff(n) ((n) <= 143 ? _m3dstbiw___zlib_huff1(n) : (n) <= 255 ? _m3dstbiw___zlib_huff2(n) : (n) <= 279 ? _m3dstbiw___zlib_huff3(n) : _m3dstbiw___zlib_huff4(n)) +#define _m3dstbiw___zlib_huffb(n) ((n) <= 143 ? _m3dstbiw___zlib_huff1(n) : _m3dstbiw___zlib_huff2(n)) -#define stbiw__ZHASH 16384 +#define _m3dstbiw___ZHASH 16384 -unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +unsigned char * _m3dstbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) { static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; @@ -1957,42 +1911,44 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l unsigned int bitbuf=0; int i,j, bitcount=0; unsigned char *out = NULL; - unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(_m3dstbiw___ZHASH * sizeof(char**)); + if (hash_table == NULL) + return NULL; if (quality < 5) quality = 5; - stbiw__sbpush(out, 0x78); - stbiw__sbpush(out, 0x5e); - stbiw__zlib_add(1,1); - stbiw__zlib_add(1,2); + _m3dstbiw___sbpush(out, 0x78); + _m3dstbiw___sbpush(out, 0x5e); + _m3dstbiw___zlib_add(1,1); + _m3dstbiw___zlib_add(1,2); - for (i=0; i < stbiw__ZHASH; ++i) + for (i=0; i < _m3dstbiw___ZHASH; ++i) hash_table[i] = NULL; i=0; while (i < data_len-3) { - int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + int h = _m3dstbiw___zhash(data+i)&(_m3dstbiw___ZHASH-1), best=3; unsigned char *bestloc = 0; unsigned char **hlist = hash_table[h]; - int n = stbiw__sbcount(hlist); + int n = _m3dstbiw___sbcount(hlist); for (j=0; j < n; ++j) { if (hlist[j]-data > i-32768) { - int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + int d = _m3dstbiw___zlib_countm(hlist[j], data+i, data_len-i); if (d >= best) best=d,bestloc=hlist[j]; } } - if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + if (hash_table[h] && _m3dstbiw___sbn(hash_table[h]) == 2*quality) { STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); - stbiw__sbn(hash_table[h]) = quality; + _m3dstbiw___sbn(hash_table[h]) = quality; } - stbiw__sbpush(hash_table[h],data+i); + _m3dstbiw___sbpush(hash_table[h],data+i); if (bestloc) { - h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + h = _m3dstbiw___zhash(data+i+1)&(_m3dstbiw___ZHASH-1); hlist = hash_table[h]; - n = stbiw__sbcount(hlist); + n = _m3dstbiw___sbcount(hlist); for (j=0; j < n; ++j) { if (hlist[j]-data > i-32767) { - int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + int e = _m3dstbiw___zlib_countm(hlist[j], data+i+1, data_len-i-1); if (e > best) { bestloc = NULL; break; @@ -2005,25 +1961,25 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l int d = (int) (data+i - bestloc); STBIW_ASSERT(d <= 32767 && best <= 258); for (j=0; best > lengthc[j+1]-1; ++j); - stbiw__zlib_huff(j+257); - if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + _m3dstbiw___zlib_huff(j+257); + if (lengtheb[j]) _m3dstbiw___zlib_add(best - lengthc[j], lengtheb[j]); for (j=0; d > distc[j+1]-1; ++j); - stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); - if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + _m3dstbiw___zlib_add(_m3dstbiw___zlib_bitrev(j,5),5); + if (disteb[j]) _m3dstbiw___zlib_add(d - distc[j], disteb[j]); i += best; } else { - stbiw__zlib_huffb(data[i]); + _m3dstbiw___zlib_huffb(data[i]); ++i; } } for (;i < data_len; ++i) - stbiw__zlib_huffb(data[i]); - stbiw__zlib_huff(256); + _m3dstbiw___zlib_huffb(data[i]); + _m3dstbiw___zlib_huff(256); while (bitcount) - stbiw__zlib_add(0,1); + _m3dstbiw___zlib_add(0,1); - for (i=0; i < stbiw__ZHASH; ++i) - (void) stbiw__sbfree(hash_table[i]); + for (i=0; i < _m3dstbiw___ZHASH; ++i) + (void) _m3dstbiw___sbfree(hash_table[i]); STBIW_FREE(hash_table); { @@ -2036,15 +1992,18 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l j += blocklen; blocklen = 5552; } - stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); - stbiw__sbpush(out, STBIW_UCHAR(s2)); - stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); - stbiw__sbpush(out, STBIW_UCHAR(s1)); + _m3dstbiw___sbpush(out, STBIW_UCHAR(s2 >> 8)); + _m3dstbiw___sbpush(out, STBIW_UCHAR(s2)); + _m3dstbiw___sbpush(out, STBIW_UCHAR(s1 >> 8)); + _m3dstbiw___sbpush(out, STBIW_UCHAR(s1)); } - *out_len = stbiw__sbn(out); - STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); - return (unsigned char *) stbiw__sbraw(out); + *out_len = _m3dstbiw___sbn(out); + STBIW_MEMMOVE(_m3dstbiw___sbraw(out), out, *out_len); + return (unsigned char *) _m3dstbiw___sbraw(out); } +#define stbi_zlib_compress _m3dstbi_zlib_compress +#else +unsigned char * _m3dstbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality); #endif #define M3D_CHUNKMAGIC(m, a,b,c,d) ((m)[0]==(a) && (m)[1]==(b) && (m)[2]==(c) && (m)[3]==(d)) @@ -2138,10 +2097,11 @@ char *_m3d_safestr(char *in, int morelines) /* helper function to load and decode/generate a texture */ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char *fn) { - unsigned int i, len = 0, w, h; + unsigned int i, len = 0; unsigned char *buff = NULL; char *fn2; #ifdef STBI__PNG_TYPE + unsigned int w, h; stbi__context s; stbi__result_info ri; #endif @@ -2187,8 +2147,8 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') { #ifdef STBI__PNG_TYPE s.read_from_callbacks = 0; - s.img_buffer = s.img_buffer_original = (stbi_uc *) buff; - s.img_buffer_end = s.img_buffer_original_end = (stbi_uc *) buff+len; + s.img_buffer = s.img_buffer_original = (unsigned char *) buff; + s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len; /* don't use model->texture[i].w directly, it's a uint16_t */ w = h = len = 0; ri.bits_per_channel = 8; @@ -2935,11 +2895,9 @@ asciiend: /* Binary variant */ #endif if(!M3D_CHUNKMAGIC(data + 8, 'H','E','A','D')) { - stbi__g_failure_reason = "Corrupt file"; buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data+8, ((m3dchunk_t*)data)->length-8, 4096, (int*)&len, 1); if(!buff || !len || !M3D_CHUNKMAGIC(buff, 'H','E','A','D')) { - M3D_LOG(stbi__g_failure_reason); if(buff) M3D_FREE(buff); M3D_FREE(model); return NULL; @@ -3969,7 +3927,7 @@ static int _m3d_vrtxcmp(const void *a, const void *b) { return memcmp(a, b, sizeof(m3dv_t)); } /* compare labels */ -_inline int _m3d_strcmp(char *a, char *b) +static _inline int _m3d_strcmp(char *a, char *b) { if(a == NULL && b != NULL) return -1; if(a != NULL && b == NULL) return 1; From 7e222f0730253b93f2348cd6874d62478668f54f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 18 Nov 2019 18:43:28 +0100 Subject: [PATCH 087/170] fix invalid cast. --- code/PostProcessing/ValidateDataStructure.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index b7f56a582..1dc217663 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -637,7 +637,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, ReportError("Material property %s%i is expected to be 5 floats large (size is %i)", prop->mKey.data,prop->mIndex, prop->mDataLength); } - mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData); + //mappings[prop->mIndex] = ((aiUVTransform*)prop->mData); } else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) { if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength) From b93c360b877b6cd73f10cc0b1bf5f670dd92a4b7 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Tue, 19 Nov 2019 16:10:34 +0000 Subject: [PATCH 088/170] memory leak fix --- code/glTF2/glTF2Asset.inl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 6b47b1607..3c98a8150 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -270,13 +270,14 @@ Ref LazyDict::Retrieve(unsigned int i) throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); } - T* inst = new T(); + // In case Read method throws an exception this will not leak + auto inst = std::make_unique(); inst->id = std::string(mDictId) + "_" + to_string(i); inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); - return Add(inst); + return Add(inst.release()); } template From 6f7cb6af06a92e9d8404d4cf41f31e5bf67799af Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Tue, 19 Nov 2019 16:58:48 +0000 Subject: [PATCH 089/170] revert memory leak fix --- code/glTF2/glTF2Asset.inl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 3c98a8150..6b47b1607 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -270,14 +270,13 @@ Ref LazyDict::Retrieve(unsigned int i) throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); } - // In case Read method throws an exception this will not leak - auto inst = std::make_unique(); + T* inst = new T(); inst->id = std::string(mDictId) + "_" + to_string(i); inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); - return Add(inst.release()); + return Add(inst); } template From 12f184867e514e393c9e4eaa78d8cf421759476e Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Tue, 19 Nov 2019 17:05:24 +0000 Subject: [PATCH 090/170] Fix for memory leak in glTF2 Importer if an exception has been thrown --- code/glTF2/glTF2Asset.inl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 6b47b1607..0d4de11f2 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -270,13 +270,14 @@ Ref LazyDict::Retrieve(unsigned int i) throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); } - T* inst = new T(); + // Unique ptr prevents memory leak in case of Read throws an exception + auto inst = std::unique_ptr(); inst->id = std::string(mDictId) + "_" + to_string(i); inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); - return Add(inst); + return Add(inst.release()); } template From 91af4b7476fb9ecd86cdf1c7ae0829aa4e219dc1 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Tue, 19 Nov 2019 17:43:31 +0000 Subject: [PATCH 091/170] fix the crash --- code/glTF2/glTF2Asset.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 0d4de11f2..4cd0f65c0 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -271,7 +271,7 @@ Ref LazyDict::Retrieve(unsigned int i) } // Unique ptr prevents memory leak in case of Read throws an exception - auto inst = std::unique_ptr(); + auto inst = std::unique_ptr(new T()); inst->id = std::string(mDictId) + "_" + to_string(i); inst->oIndex = i; ReadMember(obj, "name", inst->name); From f78446b14aff46db2ef27d062a275b6a01fd68b1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 19 Nov 2019 20:30:40 +0100 Subject: [PATCH 092/170] closes https://github.com/assimp/assimp/issues/2733: update of zlip to fix gcc build for v9.2.0 32 bit --- contrib/zip/.gitignore | 2 + contrib/zip/CMakeLists.txt | 83 +++++- contrib/zip/README.md | 12 +- contrib/zip/appveyor.yml | 2 +- contrib/zip/src/miniz.h | 459 ++++++++++++++++++++++++++++---- contrib/zip/src/zip.c | 62 +++-- contrib/zip/src/zip.h | 455 ++++++++++++++++--------------- contrib/zip/test/CMakeLists.txt | 27 +- contrib/zip/test/test.c | 38 ++- contrib/zip/test/test_miniz.c | 25 +- 10 files changed, 821 insertions(+), 344 deletions(-) diff --git a/contrib/zip/.gitignore b/contrib/zip/.gitignore index a7904a1ef..49b2cb2fd 100644 --- a/contrib/zip/.gitignore +++ b/contrib/zip/.gitignore @@ -1,6 +1,7 @@ /build/ /test/build/ /xcodeproj/ +.vscode/ # Object files *.o @@ -54,3 +55,4 @@ zip.dir/ test/test.exe.vcxproj.filters test/test.exe.vcxproj test/test.exe.dir/ + diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt index b46dbb1db..77916d2e1 100644 --- a/contrib/zip/CMakeLists.txt +++ b/contrib/zip/CMakeLists.txt @@ -1,10 +1,14 @@ -cmake_minimum_required(VERSION 2.8) -project(zip) -enable_language(C) +cmake_minimum_required(VERSION 3.0) + +project(zip + LANGUAGES C + VERSION "0.1.15") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) + if (MSVC) - # Use secure functions by defaualt and suppress warnings about "deprecated" functions + # Use secure functions by default and suppress warnings about "deprecated" functions set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") @@ -12,28 +16,80 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic") + if(ENABLE_COVERAGE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") + endif() endif (MSVC) # zip set(SRC src/miniz.h src/zip.h src/zip.c) add_library(${PROJECT_NAME} ${SRC}) -target_include_directories(${PROJECT_NAME} INTERFACE src) +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ +) # test if (NOT CMAKE_DISABLE_TESTING) enable_testing() add_subdirectory(test) find_package(Sanitizers) - add_sanitizers(${PROJECT_NAME} test.exe) - add_sanitizers(${PROJECT_NAME} test_miniz.exe) + add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out}) endif() +#### +# Installation (https://github.com/forexample/package-example) { + +set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") +set(INCLUDE_INSTALL_DIR "include") + +set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") + +# Configuration +set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") +set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") +set(NAMESPACE "${PROJECT_NAME}::") + +# Include module with fuction 'write_basic_package_version_file' +include(CMakePackageConfigHelpers) + +# Note: PROJECT_VERSION is used as a VERSION +write_basic_package_version_file( + "${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion +) + +# Use variables: +# * TARGETS_EXPORT_NAME +# * PROJECT_NAME +configure_package_config_file( + "cmake/Config.cmake.in" + "${PROJECT_CONFIG}" + INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" +) + +install( + FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" + DESTINATION "${CONFIG_INSTALL_DIR}" +) + +install( + EXPORT "${TARGETS_EXPORT_NAME}" + NAMESPACE "${NAMESPACE}" + DESTINATION "${CONFIG_INSTALL_DIR}" +) + +# } + install(TARGETS ${PROJECT_NAME} + EXPORT ${TARGETS_EXPORT_NAME} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib - COMPONENT library) -install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION include) + INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR} +) +install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION ${INCLUDE_INSTALL_DIR}/zip) # uninstall target (https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake) if(NOT TARGET uninstall) @@ -45,3 +101,12 @@ if(NOT TARGET uninstall) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake) endif() + +find_package(Doxygen) +if(DOXYGEN_FOUND) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM) +endif() diff --git a/contrib/zip/README.md b/contrib/zip/README.md index d5fb8cd20..14eb9a34c 100644 --- a/contrib/zip/README.md +++ b/contrib/zip/README.md @@ -71,7 +71,7 @@ int arg = 2; zip_extract("foo.zip", "/tmp", on_extract_entry, &arg); ``` -* Extract a zip entry into memory. +* Extract a zip entry into memory. ```c void *buf = NULL; size_t bufsize; @@ -89,7 +89,7 @@ zip_close(zip); free(buf); ``` -* Extract a zip entry into memory (no internal allocation). +* Extract a zip entry into memory (no internal allocation). ```c unsigned char *buf; size_t bufsize; @@ -110,7 +110,7 @@ zip_close(zip); free(buf); ``` -* Extract a zip entry into memory using callback. +* Extract a zip entry into memory using callback. ```c struct buffer_t { char *data; @@ -144,7 +144,7 @@ free(buf.data); ``` -* Extract a zip entry into a file. +* Extract a zip entry into a file. ```c struct zip_t *zip = zip_open("foo.zip", 0, 'r'); { @@ -157,7 +157,7 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r'); zip_close(zip); ``` -* List of all zip entries +* List of all zip entries ```c struct zip_t *zip = zip_open("foo.zip", 0, 'r'); int i, n = zip_total_entries(zip); @@ -174,7 +174,7 @@ for (i = 0; i < n; ++i) { zip_close(zip); ``` -## Bindings +# Bindings Compile zip library as a dynamic library. ```shell $ mkdir build diff --git a/contrib/zip/appveyor.yml b/contrib/zip/appveyor.yml index 0be6373ca..ea17f5de9 100644 --- a/contrib/zip/appveyor.yml +++ b/contrib/zip/appveyor.yml @@ -1,4 +1,4 @@ -version: zip-0.1.9.{build} +version: zip-0.1.15.{build} build_script: - cmd: >- cd c:\projects\zip diff --git a/contrib/zip/src/miniz.h b/contrib/zip/src/miniz.h index 2c27a94d8..c4fcfb83e 100644 --- a/contrib/zip/src/miniz.h +++ b/contrib/zip/src/miniz.h @@ -221,6 +221,7 @@ #ifndef MINIZ_HEADER_INCLUDED #define MINIZ_HEADER_INCLUDED +#include #include // Defines to completely disable specific portions of miniz.c: @@ -284,7 +285,8 @@ /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */ #if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES) #if MINIZ_X86_OR_X64_CPU -/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ +/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient + * integer loads and stores from unaligned addresses. */ #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define MINIZ_UNALIGNED_USE_MEMCPY #else @@ -354,6 +356,44 @@ enum { MZ_FIXED = 4 }; +/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or + * modify this enum. */ +typedef enum { + MZ_ZIP_NO_ERROR = 0, + MZ_ZIP_UNDEFINED_ERROR, + MZ_ZIP_TOO_MANY_FILES, + MZ_ZIP_FILE_TOO_LARGE, + MZ_ZIP_UNSUPPORTED_METHOD, + MZ_ZIP_UNSUPPORTED_ENCRYPTION, + MZ_ZIP_UNSUPPORTED_FEATURE, + MZ_ZIP_FAILED_FINDING_CENTRAL_DIR, + MZ_ZIP_NOT_AN_ARCHIVE, + MZ_ZIP_INVALID_HEADER_OR_CORRUPTED, + MZ_ZIP_UNSUPPORTED_MULTIDISK, + MZ_ZIP_DECOMPRESSION_FAILED, + MZ_ZIP_COMPRESSION_FAILED, + MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE, + MZ_ZIP_CRC_CHECK_FAILED, + MZ_ZIP_UNSUPPORTED_CDIR_SIZE, + MZ_ZIP_ALLOC_FAILED, + MZ_ZIP_FILE_OPEN_FAILED, + MZ_ZIP_FILE_CREATE_FAILED, + MZ_ZIP_FILE_WRITE_FAILED, + MZ_ZIP_FILE_READ_FAILED, + MZ_ZIP_FILE_CLOSE_FAILED, + MZ_ZIP_FILE_SEEK_FAILED, + MZ_ZIP_FILE_STAT_FAILED, + MZ_ZIP_INVALID_PARAMETER, + MZ_ZIP_INVALID_FILENAME, + MZ_ZIP_BUF_TOO_SMALL, + MZ_ZIP_INTERNAL_ERROR, + MZ_ZIP_FILE_NOT_FOUND, + MZ_ZIP_ARCHIVE_TOO_LARGE, + MZ_ZIP_VALIDATION_FAILED, + MZ_ZIP_WRITE_CALLBACK_FAILED, + MZ_ZIP_TOTAL_ERRORS +} mz_zip_error; + // Method #define MZ_DEFLATED 8 @@ -696,6 +736,7 @@ typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); +typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque); struct mz_zip_internal_state_tag; typedef struct mz_zip_internal_state_tag mz_zip_internal_state; @@ -707,13 +748,27 @@ typedef enum { MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 } mz_zip_mode; -typedef struct mz_zip_archive_tag { +typedef enum { + MZ_ZIP_TYPE_INVALID = 0, + MZ_ZIP_TYPE_USER, + MZ_ZIP_TYPE_MEMORY, + MZ_ZIP_TYPE_HEAP, + MZ_ZIP_TYPE_FILE, + MZ_ZIP_TYPE_CFILE, + MZ_ZIP_TOTAL_TYPES +} mz_zip_type; + +typedef struct { mz_uint64 m_archive_size; mz_uint64 m_central_directory_file_ofs; - mz_uint m_total_files; - mz_zip_mode m_zip_mode; - mz_uint m_file_offset_alignment; + /* We only support up to UINT32_MAX files in zip64 mode. */ + mz_uint32 m_total_files; + mz_zip_mode m_zip_mode; + mz_zip_type m_zip_type; + mz_zip_error m_last_error; + + mz_uint64 m_file_offset_alignment; mz_alloc_func m_pAlloc; mz_free_func m_pFree; @@ -722,6 +777,7 @@ typedef struct mz_zip_archive_tag { mz_file_read_func m_pRead; mz_file_write_func m_pWrite; + mz_file_needs_keepalive m_pNeeds_keepalive; void *m_pIO_opaque; mz_zip_internal_state *m_pState; @@ -1263,6 +1319,9 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); #endif // #ifndef MINIZ_NO_ZLIB_APIS +#define MZ_UINT16_MAX (0xFFFFU) +#define MZ_UINT32_MAX (0xFFFFFFFFU) + #ifdef __cplusplus } #endif @@ -1311,6 +1370,11 @@ typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1]; ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) #endif +#define MZ_READ_LE64(p) \ + (((mz_uint64)MZ_READ_LE32(p)) | \ + (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) \ + << 32U)) + #ifdef _MSC_VER #define MZ_FORCEINLINE __forceinline #elif defined(__GNUC__) @@ -4160,6 +4224,17 @@ enum { MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, + + /* ZIP64 archive identifier and record sizes */ + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50, + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50, + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56, + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20, + MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001, + MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50, + MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24, + MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16, + // Central directory header record offsets MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, @@ -4199,6 +4274,31 @@ enum { MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, + + /* ZIP64 End of central directory locator offsets */ + MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */ + MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */ + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */ + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */ + + /* ZIP64 End of central directory header offsets */ + MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */ + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */ + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */ + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */ + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */ + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */ + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */ + MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */ + MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0, + MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192, + MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11 }; typedef struct { @@ -4211,7 +4311,24 @@ struct mz_zip_internal_state_tag { mz_zip_array m_central_dir; mz_zip_array m_central_dir_offsets; mz_zip_array m_sorted_central_dir_offsets; + + /* The flags passed in when the archive is initially opened. */ + uint32_t m_init_flags; + + /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. + */ + mz_bool m_zip64; + + /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 + * will also be slammed to true too, even if we didn't find a zip64 end of + * central dir header, etc.) */ + mz_bool m_zip64_has_extended_info_fields; + + /* These fields are used by the file, FILE, memory, and memory/heap read/write + * helpers. */ MZ_FILE *m_pFile; + mz_uint64 m_file_archive_start_ofs; + void *m_pMem; size_t m_mem_size; size_t m_mem_capacity; @@ -4363,6 +4480,13 @@ static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, #endif /* #ifndef MINIZ_NO_STDIO */ #endif /* #ifndef MINIZ_NO_TIME */ +static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, + mz_zip_error err_num) { + if (pZip) + pZip->m_last_error = err_num; + return MZ_FALSE; +} + static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) { (void)flags; @@ -4480,127 +4604,346 @@ mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) { } } -static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, - mz_uint32 flags) { - mz_uint cdir_size, num_this_disk, cdir_disk_index; - mz_uint64 cdir_ofs; +static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, + mz_uint32 record_sig, + mz_uint32 record_size, + mz_int64 *pOfs) { mz_int64 cur_file_ofs; - const mz_uint8 *p; mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; - mz_bool sort_central_dir = - ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); - // Basic sanity checks - reject files which are too small, and check the first - // 4 bytes of the file to make sure a local header is there. - if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + + /* Basic sanity checks - reject files which are too small */ + if (pZip->m_archive_size < record_size) return MZ_FALSE; - // Find the end of central directory record by scanning the file from the end - // towards the beginning. + + /* Find the record by scanning the file from the end towards the beginning. */ cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); for (;;) { int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) return MZ_FALSE; - for (i = n - 4; i >= 0; --i) - if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) - break; + + for (i = n - 4; i >= 0; --i) { + mz_uint s = MZ_READ_LE32(pBuf + i); + if (s == record_sig) { + if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size) + break; + } + } + if (i >= 0) { cur_file_ofs += i; break; } + + /* Give up if we've searched the entire file, or we've gone back "too far" + * (~64kb) */ if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= - (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) + (MZ_UINT16_MAX + record_size))) return MZ_FALSE; + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); } - // Read and verify the end of central directory record. + + *pOfs = cur_file_ofs; + return MZ_TRUE; +} + +static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, + mz_uint flags) { + mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, + cdir_disk_index = 0; + mz_uint64 cdir_ofs = 0; + mz_int64 cur_file_ofs = 0; + const mz_uint8 *p; + + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; + mz_uint8 *pBuf = (mz_uint8 *)buf_u32; + mz_bool sort_central_dir = + ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); + mz_uint32 zip64_end_of_central_dir_locator_u32 + [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / + sizeof(mz_uint32)]; + mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32; + + mz_uint32 zip64_end_of_central_dir_header_u32 + [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / + sizeof(mz_uint32)]; + mz_uint8 *pZip64_end_of_central_dir = + (mz_uint8 *)zip64_end_of_central_dir_header_u32; + + mz_uint64 zip64_end_of_central_dir_ofs = 0; + + /* Basic sanity checks - reject files which are too small, and check the first + * 4 bytes of the file to make sure a local header is there. */ + if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (!mz_zip_reader_locate_header_sig( + pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs)) + return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR); + + /* Read and verify the end of central directory record. */ if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; - if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != - MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || - ((pZip->m_total_files = - MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != - MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) { + if (pZip->m_pRead(pZip->m_pIO_opaque, + cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, + pZip64_locator, + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) { + if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == + MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) { + zip64_end_of_central_dir_ofs = MZ_READ_LE64( + pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS); + if (zip64_end_of_central_dir_ofs > + (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) + return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); + + if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, + pZip64_end_of_central_dir, + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) { + if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) { + pZip->m_pState->m_zip64 = MZ_TRUE; + } + } + } + } + } + + pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS); + cdir_entries_on_this_disk = + MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); + cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS); + cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); + + if (pZip->m_pState->m_zip64) { + mz_uint32 zip64_total_num_of_disks = + MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS); + mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64( + pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS); + mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64( + pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS); + mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64( + pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS); + mz_uint64 zip64_size_of_central_directory = + MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS); + + if (zip64_size_of_end_of_central_dir_record < + (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + + if (zip64_total_num_of_disks != 1U) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + /* Check for miniz's practical limits */ + if (zip64_cdir_total_entries > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries; + + if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); + + cdir_entries_on_this_disk = + (mz_uint32)zip64_cdir_total_entries_on_this_disk; + + /* Check for miniz's current practical limits (sorry, this should be enough + * for millions of files) */ + if (zip64_size_of_central_directory > MZ_UINT32_MAX) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); + + cdir_size = (mz_uint32)zip64_size_of_central_directory; + + num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS); + + cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS); + + cdir_ofs = + MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS); + } + + if (pZip->m_total_files != cdir_entries_on_this_disk) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); - if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < - pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) - return MZ_FALSE; + if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); pZip->m_central_directory_file_ofs = cdir_ofs; if (pZip->m_total_files) { mz_uint i, n; - - // Read the entire central directory into a heap block, and allocate another - // heap block to hold the unsorted central dir file record offsets, and - // another to hold the sorted indices. + /* Read the entire central directory into a heap block, and allocate another + * heap block to hold the unsorted central dir file record offsets, and + * possibly another to hold the sorted indices. */ if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); if (sort_central_dir) { if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); } if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - // Now create an index into the central directory file records, do some - // basic sanity checking on each record, and check for zip64 entries (which - // are not yet supported). + /* Now create an index into the central directory file records, do some + * basic sanity checking on each record */ p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { - mz_uint total_header_size, comp_size, decomp_size, disk_index; + mz_uint total_header_size, disk_index, bit_flags, filename_size, + ext_data_size; + mz_uint64 comp_size, decomp_size, local_header_ofs; + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); + if (sort_central_dir) MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); - if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && - (decomp_size != comp_size)) || - (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || - (comp_size == 0xFFFFFFFF)) - return MZ_FALSE; + local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS); + + if ((!pZip->m_pState->m_zip64_has_extended_info_fields) && + (ext_data_size) && + (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == + MZ_UINT32_MAX)) { + /* Attempt to find zip64 extended information field in the entry's extra + * data */ + mz_uint32 extra_size_remaining = ext_data_size; + + if (extra_size_remaining) { + const mz_uint8 *pExtra_data; + void *buf = NULL; + + if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > + n) { + buf = MZ_MALLOC(ext_data_size); + if (buf == NULL) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (pZip->m_pRead(pZip->m_pIO_opaque, + cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + + filename_size, + buf, ext_data_size) != ext_data_size) { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + pExtra_data = (mz_uint8 *)buf; + } else { + pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; + } + + do { + mz_uint32 field_id; + mz_uint32 field_data_size; + + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + field_id = MZ_READ_LE16(pExtra_data); + field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); + + if ((field_data_size + sizeof(mz_uint16) * 2) > + extra_size_remaining) { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { + /* Ok, the archive didn't have any zip64 headers but it uses a + * zip64 extended information field so mark it as zip64 anyway + * (this can occur with infozip's zip util when it reads + * compresses files from stdin). */ + pZip->m_pState->m_zip64 = MZ_TRUE; + pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE; + break; + } + + pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; + extra_size_remaining = + extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; + } while (extra_size_remaining); + + MZ_FREE(buf); + } + } + + /* I've seen archives that aren't marked as zip64 that uses zip64 ext + * data, argh */ + if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) { + if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && + (decomp_size != comp_size)) || + (decomp_size && !comp_size)) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); - if ((disk_index != num_this_disk) && (disk_index != 1)) - return MZ_FALSE; - if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + - MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) - return MZ_FALSE; + if ((disk_index == MZ_UINT16_MAX) || + ((disk_index != num_this_disk) && (disk_index != 1))) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK); + + if (comp_size != MZ_UINT32_MAX) { + if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } + + bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED) + return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION); + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) - return MZ_FALSE; + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + n -= total_header_size; p += total_header_size; } diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c index ff3a8fe1e..1abcfd8fd 100644 --- a/contrib/zip/src/zip.c +++ b/contrib/zip/src/zip.c @@ -24,7 +24,6 @@ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \ (P)[1] == ':') #define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0) -#define ISSLASH(C) ((C) == '/' || (C) == '\\') #else @@ -48,7 +47,7 @@ int symlink(const char *target, const char *linkpath); // needed on Linux #endif #ifndef ISSLASH -#define ISSLASH(C) ((C) == '/') +#define ISSLASH(C) ((C) == '/' || (C) == '\\') #endif #define CLEANUP(ptr) \ @@ -78,26 +77,34 @@ static const char *base_name(const char *name) { return base; } -static int mkpath(const char *path) { - char const *p; +static int mkpath(char *path) { + char *p; char npath[MAX_PATH + 1]; int len = 0; int has_device = HAS_DEVICE(path); memset(npath, 0, MAX_PATH + 1); - -#ifdef _WIN32 - // only on windows fix the path - npath[0] = path[0]; - npath[1] = path[1]; - len = 2; -#endif // _WIN32 - + if (has_device) { + // only on windows + npath[0] = path[0]; + npath[1] = path[1]; + len = 2; + } for (p = path + len; *p && len < MAX_PATH; p++) { if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) { - if (MKDIR(npath) == -1) - if (errno != EEXIST) +#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \ + defined(__MINGW32__) +#else + if ('\\' == *p) { + *p = '/'; + } +#endif + + if (MKDIR(npath) == -1) { + if (errno != EEXIST) { return -1; + } + } } npath[len++] = *p; } @@ -279,7 +286,14 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { zip->entry.header_offset = zip->archive.m_archive_size; memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8)); zip->entry.method = 0; + + // UNIX or APPLE +#if MZ_PLATFORM == 3 || MZ_PLATFORM == 19 + // regular file with rw-r--r-- persmissions + zip->entry.external_attr = (mz_uint32)(0100644) << 16; +#else zip->entry.external_attr = 0; +#endif num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pzip); @@ -660,7 +674,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) { } if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index, - buf, bufsize, 0, NULL, 0)) { + buf, bufsize, 0, NULL, 0)) { return -1; } @@ -670,10 +684,7 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) { int zip_entry_fread(struct zip_t *zip, const char *filename) { mz_zip_archive *pzip = NULL; mz_uint idx; -#if defined(_MSC_VER) -#else mz_uint32 xattr = 0; -#endif mz_zip_archive_file_stat info; if (!zip) { @@ -875,12 +886,19 @@ int zip_extract(const char *zipname, const char *dir, goto out; } - if ((((info.m_version_made_by >> 8) == 3) || ((info.m_version_made_by >> 8) == 19)) // if zip is produced on Unix or macOS (3 and 19 from section 4.4.2.2 of zip standard) - && info.m_external_attr & (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 is directory) + if ((((info.m_version_made_by >> 8) == 3) || + ((info.m_version_made_by >> 8) == + 19)) // if zip is produced on Unix or macOS (3 and 19 from + // section 4.4.2.2 of zip standard) + && info.m_external_attr & + (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40 + // is directory) #if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \ defined(__MINGW32__) -#else - if (info.m_uncomp_size > MAX_PATH || !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to, MAX_PATH, 0, NULL, 0)) { +#else + if (info.m_uncomp_size > MAX_PATH || + !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to, + MAX_PATH, 0, NULL, 0)) { goto out; } symlink_to[info.m_uncomp_size] = '\0'; diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h index 5f39df50a..a48d64d6d 100644 --- a/contrib/zip/src/zip.h +++ b/contrib/zip/src/zip.h @@ -20,241 +20,240 @@ extern "C" { #endif #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \ - !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(__ssize_t_defined) -#define _SSIZE_T + !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \ + !defined(_SSIZE_T) && !defined(_SSIZE_T_) + // 64-bit Windows is the only mainstream platform // where sizeof(long) != sizeof(void*) #ifdef _WIN64 -typedef long long ssize_t; /* byte count or error */ +typedef long long ssize_t; /* byte count or error */ #else -typedef long ssize_t; /* byte count or error */ +typedef long ssize_t; /* byte count or error */ #endif + +#define _SSIZE_T_DEFINED +#define _SSIZE_T_DEFINED_ +#define __DEFINED_ssize_t +#define __ssize_t_defined +#define _SSIZE_T +#define _SSIZE_T_ + #endif #ifndef MAX_PATH #define MAX_PATH 32767 /* # chars in a path name including NULL */ #endif +/** + * @mainpage + * + * Documenation for @ref zip. + */ + +/** + * @addtogroup zip + * @{ + */ + +/** + * Default zip compression level. + */ + #define ZIP_DEFAULT_COMPRESSION_LEVEL 6 -/* - This data structure is used throughout the library to represent zip archive - - forward declaration. -*/ +/** + * @struct zip_t + * + * This data structure is used throughout the library to represent zip archive - + * forward declaration. + */ struct zip_t; -/* - Opens zip archive with compression level using the given mode. - - Args: - zipname: zip archive file name. - level: compression level (0-9 are the standard zlib-style levels). - mode: file access mode. - 'r': opens a file for reading/extracting (the file must exists). - 'w': creates an empty file for writing. - 'a': appends to an existing archive. - - Returns: - The zip archive handler or NULL on error -*/ +/** + * Opens zip archive with compression level using the given mode. + * + * @param zipname zip archive file name. + * @param level compression level (0-9 are the standard zlib-style levels). + * @param mode file access mode. + * - 'r': opens a file for reading/extracting (the file must exists). + * - 'w': creates an empty file for writing. + * - 'a': appends to an existing archive. + * + * @return the zip archive handler or NULL on error + */ extern struct zip_t *zip_open(const char *zipname, int level, char mode); -/* - Closes the zip archive, releases resources - always finalize. - - Args: - zip: zip archive handler. -*/ +/** + * Closes the zip archive, releases resources - always finalize. + * + * @param zip zip archive handler. + */ extern void zip_close(struct zip_t *zip); -/* - Opens an entry by name in the zip archive. - For zip archive opened in 'w' or 'a' mode the function will append - a new entry. In readonly mode the function tries to locate the entry - in global dictionary. - - Args: - zip: zip archive handler. - entryname: an entry name in local dictionary. - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Opens an entry by name in the zip archive. + * + * For zip archive opened in 'w' or 'a' mode the function will append + * a new entry. In readonly mode the function tries to locate the entry + * in global dictionary. + * + * @param zip zip archive handler. + * @param entryname an entry name in local dictionary. + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_entry_open(struct zip_t *zip, const char *entryname); -/* - Opens a new entry by index in the zip archive. - This function is only valid if zip archive was opened in 'r' (readonly) mode. - - Args: - zip: zip archive handler. - index: index in local dictionary. - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Opens a new entry by index in the zip archive. + * + * This function is only valid if zip archive was opened in 'r' (readonly) mode. + * + * @param zip zip archive handler. + * @param index index in local dictionary. + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_entry_openbyindex(struct zip_t *zip, int index); -/* - Closes a zip entry, flushes buffer and releases resources. - - Args: - zip: zip archive handler. - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Closes a zip entry, flushes buffer and releases resources. + * + * @param zip zip archive handler. + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_entry_close(struct zip_t *zip); -/* - Returns a local name of the current zip entry. - The main difference between user's entry name and local entry name - is optional relative path. - Following .ZIP File Format Specification - the path stored MUST not contain - a drive or device letter, or a leading slash. - All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' - for compatibility with Amiga and UNIX file systems etc. - - Args: - zip: zip archive handler. - - Returns: - The pointer to the current zip entry name, or NULL on error. -*/ +/** + * Returns a local name of the current zip entry. + * + * The main difference between user's entry name and local entry name + * is optional relative path. + * Following .ZIP File Format Specification - the path stored MUST not contain + * a drive or device letter, or a leading slash. + * All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' + * for compatibility with Amiga and UNIX file systems etc. + * + * @param zip: zip archive handler. + * + * @return the pointer to the current zip entry name, or NULL on error. + */ extern const char *zip_entry_name(struct zip_t *zip); -/* - Returns an index of the current zip entry. - - Args: - zip: zip archive handler. - - Returns: - The index on success, negative number (< 0) on error. -*/ +/** + * Returns an index of the current zip entry. + * + * @param zip zip archive handler. + * + * @return the index on success, negative number (< 0) on error. + */ extern int zip_entry_index(struct zip_t *zip); -/* - Determines if the current zip entry is a directory entry. - - Args: - zip: zip archive handler. - - Returns: - The return code - 1 (true), 0 (false), negative number (< 0) on error. -*/ +/** + * Determines if the current zip entry is a directory entry. + * + * @param zip zip archive handler. + * + * @return the return code - 1 (true), 0 (false), negative number (< 0) on + * error. + */ extern int zip_entry_isdir(struct zip_t *zip); -/* - Returns an uncompressed size of the current zip entry. - - Args: - zip: zip archive handler. - - Returns: - The uncompressed size in bytes. -*/ +/** + * Returns an uncompressed size of the current zip entry. + * + * @param zip zip archive handler. + * + * @return the uncompressed size in bytes. + */ extern unsigned long long zip_entry_size(struct zip_t *zip); -/* - Returns CRC-32 checksum of the current zip entry. - - Args: - zip: zip archive handler. - - Returns: - The CRC-32 checksum. -*/ +/** + * Returns CRC-32 checksum of the current zip entry. + * + * @param zip zip archive handler. + * + * @return the CRC-32 checksum. + */ extern unsigned int zip_entry_crc32(struct zip_t *zip); -/* - Compresses an input buffer for the current zip entry. - - Args: - zip: zip archive handler. - buf: input buffer. - bufsize: input buffer size (in bytes). - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Compresses an input buffer for the current zip entry. + * + * @param zip zip archive handler. + * @param buf input buffer. + * @param bufsize input buffer size (in bytes). + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize); -/* - Compresses a file for the current zip entry. - - Args: - zip: zip archive handler. - filename: input file. - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Compresses a file for the current zip entry. + * + * @param zip zip archive handler. + * @param filename input file. + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_entry_fwrite(struct zip_t *zip, const char *filename); -/* - Extracts the current zip entry into output buffer. - The function allocates sufficient memory for a output buffer. - - Args: - zip: zip archive handler. - buf: output buffer. - bufsize: output buffer size (in bytes). - - Note: - - remember to release memory allocated for a output buffer. - - for large entries, please take a look at zip_entry_extract function. - - Returns: - The return code - the number of bytes actually read on success. - Otherwise a -1 on error. -*/ +/** + * Extracts the current zip entry into output buffer. + * + * The function allocates sufficient memory for a output buffer. + * + * @param zip zip archive handler. + * @param buf output buffer. + * @param bufsize output buffer size (in bytes). + * + * @note remember to release memory allocated for a output buffer. + * for large entries, please take a look at zip_entry_extract function. + * + * @return the return code - the number of bytes actually read on success. + * Otherwise a -1 on error. + */ extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize); -/* - Extracts the current zip entry into a memory buffer using no memory - allocation. +/** + * Extracts the current zip entry into a memory buffer using no memory + * allocation. + * + * @param zip zip archive handler. + * @param buf preallocated output buffer. + * @param bufsize output buffer size (in bytes). + * + * @note ensure supplied output buffer is large enough. + * zip_entry_size function (returns uncompressed size for the current + * entry) can be handy to estimate how big buffer is needed. for large + * entries, please take a look at zip_entry_extract function. + * + * @return the return code - the number of bytes actually read on success. + * Otherwise a -1 on error (e.g. bufsize is not large enough). + */ +extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, + size_t bufsize); - Args: - zip: zip archive handler. - buf: preallocated output buffer. - bufsize: output buffer size (in bytes). - - Note: - - ensure supplied output buffer is large enough. - - zip_entry_size function (returns uncompressed size for the current entry) - can be handy to estimate how big buffer is needed. - - for large entries, please take a look at zip_entry_extract function. - - Returns: - The return code - the number of bytes actually read on success. - Otherwise a -1 on error (e.g. bufsize is not large enough). -*/ -extern ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize); - -/* - Extracts the current zip entry into output file. - - Args: - zip: zip archive handler. - filename: output file. - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Extracts the current zip entry into output file. + * + * @param zip zip archive handler. + * @param filename output file. + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_entry_fread(struct zip_t *zip, const char *filename); -/* - Extracts the current zip entry using a callback function (on_extract). - - Args: - zip: zip archive handler. - on_extract: callback function. - arg: opaque pointer (optional argument, - which you can pass to the on_extract callback) - - Returns: - The return code - 0 on success, negative number (< 0) on error. +/** + * Extracts the current zip entry using a callback function (on_extract). + * + * @param zip zip archive handler. + * @param on_extract callback function. + * @param arg opaque pointer (optional argument, which you can pass to the + * on_extract callback) + * + * @return the return code - 0 on success, negative number (< 0) on error. */ extern int zip_entry_extract(struct zip_t *zip, @@ -262,53 +261,49 @@ zip_entry_extract(struct zip_t *zip, const void *data, size_t size), void *arg); -/* - Returns the number of all entries (files and directories) in the zip archive. - - Args: - zip: zip archive handler. - - Returns: - The return code - the number of entries on success, - negative number (< 0) on error. -*/ +/** + * Returns the number of all entries (files and directories) in the zip archive. + * + * @param zip zip archive handler. + * + * @return the return code - the number of entries on success, negative number + * (< 0) on error. + */ extern int zip_total_entries(struct zip_t *zip); -/* - Creates a new archive and puts files into a single zip archive. - - Args: - zipname: zip archive file. - filenames: input files. - len: number of input files. - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Creates a new archive and puts files into a single zip archive. + * + * @param zipname zip archive file. + * @param filenames input files. + * @param len: number of input files. + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_create(const char *zipname, const char *filenames[], size_t len); -/* - Extracts a zip archive file into directory. - - If on_extract_entry is not NULL, the callback will be called after - successfully extracted each zip entry. - Returning a negative value from the callback will cause abort and return an - error. The last argument (void *arg) is optional, which you can use to pass - data to the on_extract_entry callback. - - Args: - zipname: zip archive file. - dir: output directory. - on_extract_entry: on extract callback. - arg: opaque pointer. - - Returns: - The return code - 0 on success, negative number (< 0) on error. -*/ +/** + * Extracts a zip archive file into directory. + * + * If on_extract_entry is not NULL, the callback will be called after + * successfully extracted each zip entry. + * Returning a negative value from the callback will cause abort and return an + * error. The last argument (void *arg) is optional, which you can use to pass + * data to the on_extract_entry callback. + * + * @param zipname zip archive file. + * @param dir output directory. + * @param on_extract_entry on extract callback. + * @param arg opaque pointer. + * + * @return the return code - 0 on success, negative number (< 0) on error. + */ extern int zip_extract(const char *zipname, const char *dir, int (*on_extract_entry)(const char *filename, void *arg), void *arg); +/** @} */ + #ifdef __cplusplus } #endif diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt index 9b2a8db10..cc060b00f 100644 --- a/contrib/zip/test/CMakeLists.txt +++ b/contrib/zip/test/CMakeLists.txt @@ -1,19 +1,16 @@ cmake_minimum_required(VERSION 2.8) -if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") - if(ENABLE_COVERAGE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g ") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") - endif() -endif () - # test -include_directories(../src) -add_executable(test.exe test.c ../src/zip.c) -add_executable(test_miniz.exe test_miniz.c) +set(test_out test.out) +set(test_miniz_out test_miniz.out) -add_test(NAME test COMMAND test.exe) -add_test(NAME test_miniz COMMAND test_miniz.exe) +add_executable(${test_out} test.c) +target_link_libraries(${test_out} zip) +add_executable(${test_miniz_out} test_miniz.c) +target_link_libraries(${test_miniz_out} zip) + +add_test(NAME ${test_out} COMMAND ${test_out}) +add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out}) + +set(test_out ${test_out} PARENT_SCOPE) +set(test_miniz_out ${test_miniz_out} PARENT_SCOPE) diff --git a/contrib/zip/test/test.c b/contrib/zip/test/test.c index 454430533..a9b2ddab1 100644 --- a/contrib/zip/test/test.c +++ b/contrib/zip/test/test.c @@ -29,6 +29,8 @@ #define XFILE "7.txt\0" #define XMODE 0100777 +#define UNIXMODE 0100644 + #define UNUSED(x) (void)x static int total_entries = 0; @@ -102,7 +104,8 @@ static void test_read(void) { assert(0 == zip_entry_close(zip)); free(buf); buf = NULL; - + bufsize = 0; + assert(0 == zip_entry_open(zip, "test/test-2.txt")); assert(strlen(TESTDATA2) == zip_entry_size(zip)); assert(CRC32DATA2 == zip_entry_crc32(zip)); @@ -131,7 +134,8 @@ static void test_read(void) { assert(0 == zip_entry_close(zip)); free(buf); buf = NULL; - + bufsize = 0; + buftmp = strlen(TESTDATA1); buf = calloc(buftmp, sizeof(char)); assert(0 == zip_entry_open(zip, "test/test-1.txt")); @@ -433,6 +437,35 @@ static void test_mtime(void) { remove(ZIPNAME); } +static void test_unix_permissions(void) { +#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__) +#else + // UNIX or APPLE + struct MZ_FILE_STAT_STRUCT file_stats; + + remove(ZIPNAME); + + struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); + assert(zip != NULL); + + assert(0 == zip_entry_open(zip, RFILE)); + assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); + assert(0 == zip_entry_close(zip)); + + zip_close(zip); + + remove(RFILE); + + assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); + + assert(0 == MZ_FILE_STAT(RFILE, &file_stats)); + assert(UNIXMODE == file_stats.st_mode); + + remove(RFILE); + remove(ZIPNAME); +#endif +} + int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); @@ -453,6 +486,7 @@ int main(int argc, char *argv[]) { test_write_permissions(); test_exe_permissions(); test_mtime(); + test_unix_permissions(); remove(ZIPNAME); return 0; diff --git a/contrib/zip/test/test_miniz.c b/contrib/zip/test/test_miniz.c index ebc0564dc..babcaecdb 100644 --- a/contrib/zip/test/test_miniz.c +++ b/contrib/zip/test/test_miniz.c @@ -23,16 +23,39 @@ int main(int argc, char *argv[]) { uint step = 0; int cmp_status; uLong src_len = (uLong)strlen(s_pStr); - uLong cmp_len = compressBound(src_len); uLong uncomp_len = src_len; + uLong cmp_len; uint8 *pCmp, *pUncomp; + size_t sz; uint total_succeeded = 0; (void)argc, (void)argv; printf("miniz.c version: %s\n", MZ_VERSION); do { + pCmp = (uint8 *)tdefl_compress_mem_to_heap(s_pStr, src_len, &cmp_len, 0); + if (!pCmp) { + printf("tdefl_compress_mem_to_heap failed\n"); + return EXIT_FAILURE; + } + if (src_len <= cmp_len) { + printf("tdefl_compress_mem_to_heap failed: from %u to %u bytes\n", + (mz_uint32)uncomp_len, (mz_uint32)cmp_len); + free(pCmp); + return EXIT_FAILURE; + } + + sz = tdefl_compress_mem_to_mem(pCmp, cmp_len, s_pStr, src_len, 0); + if (sz != cmp_len) { + printf("tdefl_compress_mem_to_mem failed: expected %u, got %u\n", + (mz_uint32)cmp_len, (mz_uint32)sz); + free(pCmp); + return EXIT_FAILURE; + } + // Allocate buffers to hold compressed and uncompressed data. + free(pCmp); + cmp_len = compressBound(src_len); pCmp = (mz_uint8 *)malloc((size_t)cmp_len); pUncomp = (mz_uint8 *)malloc((size_t)src_len); if ((!pCmp) || (!pUncomp)) { From 42fa22f85e20822fb5779fc8338bf7f0d86f4da2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 20 Nov 2019 21:26:36 +0100 Subject: [PATCH 093/170] Update Readme.md Add doc for glTF2.0 for supported extenstions --- Readme.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index f02a3b617..01c5fe33b 100644 --- a/Readme.md +++ b/Readme.md @@ -60,7 +60,12 @@ __Importers__: - ENFF - [FBX](https://en.wikipedia.org/wiki/FBX) - [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB -- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0) +- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0): + At the moment for glTF2.0 the following extensions are supported: + + KHR_lights_punctual ( 5.0 ) + + KHR_materials_pbrSpecularGlossiness ( 5.0 ) + + KHR_materials_unlit ( 5.0 ) + + KHR_texture_transform ( 5.1 under test ) - HMB - IFC-STEP - IRR / IRRMESH From 97dc0ce15d038feb47a2f054cb53745c869e07c8 Mon Sep 17 00:00:00 2001 From: Dylan Kenneally Date: Thu, 21 Nov 2019 12:04:53 +1100 Subject: [PATCH 094/170] Added CMake option to set the compiler warning to max (-Wall /W4). Off by default --- Build.md | 1 + CMakeLists.txt | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/Build.md b/Build.md index 2db47798d..4b7513313 100644 --- a/Build.md +++ b/Build.md @@ -77,6 +77,7 @@ The cmake-build-environment provides options to configure the build. The followi - **ASSIMP_BUILD_SAMPLES ( default OFF )**: If the official samples are built as well (needs Glut). - **ASSIMP_BUILD_TESTS ( default ON )**: If the test suite for Assimp is built in addition to the library. - **ASSIMP_COVERALLS ( default OFF )**: Enable this to measure test coverage. +- **ASSIMP_ERROR_MAX( default OFF)**: Enable all warnings. - **ASSIMP_WERROR( default OFF )**: Treat warnings as errors. - **ASSIMP_ASAN ( default OFF )**: Enable AddressSanitizer. - **ASSIMP_UBSAN ( default OFF )**: Enable Undefined Behavior sanitizer. diff --git a/CMakeLists.txt b/CMakeLists.txt index 693d6f16a..f69d2c9a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,10 @@ OPTION ( ASSIMP_COVERALLS "Enable this to measure test coverage." OFF ) +OPTION ( ASSIMP_ERROR_MAX + "Enable all warnings." + OFF +) OPTION ( ASSIMP_WERROR "Treat warnings as errors." OFF @@ -294,6 +298,16 @@ IF (ASSIMP_COVERALLS) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") ENDIF() +IF (ASSIMP_ERROR_MAX) + MESSAGE(STATUS "Turning on all warnings") + IF (MSVC) + ADD_COMPILE_OPTIONS(/W4) # NB: there is a /Wall option, pedantic mode + ELSE() + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") + ENDIF() +ENDIF() + IF (ASSIMP_WERROR) MESSAGE(STATUS "Treating warnings as errors") IF (MSVC) From 91e6d3abeb2b35861538c31e0b0927a42d4f830f Mon Sep 17 00:00:00 2001 From: Cory Fabre Date: Thu, 21 Nov 2019 23:46:14 -0600 Subject: [PATCH 095/170] Fix glTF Accessor min and max values --- code/glTF/glTFAsset.h | 4 +- code/glTF/glTFAssetWriter.inl | 26 ++++++++-- code/glTF/glTFExporter.cpp | 84 ++++++++++++++++++++++----------- code/glTF2/glTF2Asset.h | 4 +- code/glTF2/glTF2AssetWriter.inl | 31 +++++++++--- code/glTF2/glTF2Exporter.cpp | 84 ++++++++++++++++++++++----------- 6 files changed, 163 insertions(+), 70 deletions(-) diff --git a/code/glTF/glTFAsset.h b/code/glTF/glTFAsset.h index ddc7f086e..e7dd9c438 100644 --- a/code/glTF/glTFAsset.h +++ b/code/glTF/glTFAsset.h @@ -362,8 +362,8 @@ namespace glTF ComponentType componentType; //!< The datatype of components in the attribute. (required) unsigned int count; //!< The number of attributes referenced by this accessor. (required) AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) - std::vector max; //!< Maximum value of each component in this attribute. - std::vector min; //!< Minimum value of each component in this attribute. + std::vector max; //!< Maximum value of each component in this attribute. + std::vector min; //!< Minimum value of each component in this attribute. unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); diff --git a/code/glTF/glTFAssetWriter.inl b/code/glTF/glTFAssetWriter.inl index 1bbb8fd8c..a3c99a9a8 100644 --- a/code/glTF/glTFAssetWriter.inl +++ b/code/glTF/glTFAssetWriter.inl @@ -54,9 +54,9 @@ namespace glTF { namespace { - template + template inline - Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) { + Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) { val.SetArray(); val.Reserve(N, al); for (decltype(N) i = 0; i < N; ++i) { @@ -65,8 +65,9 @@ namespace glTF { return val; } + template inline - Value& MakeValue(Value& val, const std::vector & r, MemoryPoolAllocator<>& al) { + Value& MakeValue(Value& val, const std::vector & r, MemoryPoolAllocator<>& al) { val.SetArray(); val.Reserve(static_cast(r.size()), al); for (unsigned int i = 0; i < r.size(); ++i) { @@ -75,6 +76,16 @@ namespace glTF { return val; } + template + inline Value& MakeValueCast(Value& val, const std::vector & r, MemoryPoolAllocator<>& al) { + val.SetArray(); + val.Reserve(static_cast(r.size()), al); + for (unsigned int i = 0; i < r.size(); ++i) { + val.PushBack(static_cast(r[i]), al); + } + return val; + } + template inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref >& v, MemoryPoolAllocator<>& al) { if (v.empty()) return; @@ -100,8 +111,13 @@ namespace glTF { obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); Value vTmpMax, vTmpMin; - obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); - obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); + if (a.componentType == ComponentType_FLOAT) { + obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); + obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); + } else { + obj.AddMember("max", MakeValueCast(vTmpMax, a.max, w.mAl), w.mAl); + obj.AddMember("min", MakeValueCast(vTmpMin, a.min, w.mAl), w.mAl); + } } inline void Write(Value& obj, Animation& a, AssetWriter& w) diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 034f91f3b..676f8a83b 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -173,6 +173,62 @@ static void IdentityMatrix4(glTF::mat4& o) o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1; } +template +void SetAccessorRange(Ref acc, void* data, unsigned int count, + unsigned int numCompsIn, unsigned int numCompsOut) +{ + ai_assert(numCompsOut <= numCompsIn); + + // Allocate and initialize with large values. + for (unsigned int i = 0 ; i < numCompsOut ; i++) { + acc->min.push_back(DBL_MAX); + acc->max.push_back(DBL_MIN); + } + + size_t totalComps = count * numCompsIn; + T* buffer_ptr = static_cast(data); + T* buffer_end = buffer_ptr + totalComps; + + // Search and set extreme values. + for (; buffer_ptr < buffer_end ; buffer_ptr += numCompsIn) { + for (unsigned int j = 0 ; j < numCompsOut ; j++) { + double valueTmp = buffer_ptr[j]; + + if (valueTmp < acc->min[j]) { + acc->min[j] = valueTmp; + } + if (valueTmp > acc->max[j]) { + acc->max[j] = valueTmp; + } + } + } +} + +inline void SetAccessorRange(ComponentType compType, Ref acc, void* data, + unsigned int count, unsigned int numCompsIn, unsigned int numCompsOut) +{ + switch (compType) { + case ComponentType_SHORT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_UNSIGNED_SHORT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_UNSIGNED_INT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_FLOAT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_BYTE: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_UNSIGNED_BYTE: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + } +} + inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) { @@ -206,33 +262,7 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu acc->type = typeOut; // calculate min and max values - { - // Allocate and initialize with large values. - float float_MAX = 10000000000000.0f; - for (unsigned int i = 0 ; i < numCompsOut ; i++) { - acc->min.push_back( float_MAX); - acc->max.push_back(-float_MAX); - } - - // Search and set extreme values. - float valueTmp; - for (unsigned int i = 0 ; i < count ; i++) { - for (unsigned int j = 0 ; j < numCompsOut ; j++) { - if (numCompsOut == 1) { - valueTmp = static_cast(data)[i]; - } else { - valueTmp = static_cast(data)[i][j]; - } - - if (valueTmp < acc->min[j]) { - acc->min[j] = valueTmp; - } - if (valueTmp > acc->max[j]) { - acc->max[j] = valueTmp; - } - } - } - } + SetAccessorRange(compType, acc, data, count, numCompsIn, numCompsOut); // copy the data acc->WriteData(count, data, numCompsIn*bytesPerComp); diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index 15c4c44fa..201d87d6b 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -387,8 +387,8 @@ namespace glTF2 ComponentType componentType; //!< The datatype of components in the attribute. (required) size_t count; //!< The number of attributes referenced by this accessor. (required) AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) - std::vector max; //!< Maximum value of each component in this attribute. - std::vector min; //!< Minimum value of each component in this attribute. + std::vector max; //!< Maximum value of each component in this attribute. + std::vector min; //!< Minimum value of each component in this attribute. unsigned int GetNumComponents(); unsigned int GetBytesPerComponent(); diff --git a/code/glTF2/glTF2AssetWriter.inl b/code/glTF2/glTF2AssetWriter.inl index 5d1b22064..4f545ebc7 100644 --- a/code/glTF2/glTF2AssetWriter.inl +++ b/code/glTF2/glTF2AssetWriter.inl @@ -54,8 +54,8 @@ namespace glTF2 { namespace { - template - inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) { + template + inline Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) { val.SetArray(); val.Reserve(N, al); for (decltype(N) i = 0; i < N; ++i) { @@ -64,7 +64,8 @@ namespace glTF2 { return val; } - inline Value& MakeValue(Value& val, const std::vector & r, MemoryPoolAllocator<>& al) { + template + inline Value& MakeValue(Value& val, const std::vector & r, MemoryPoolAllocator<>& al) { val.SetArray(); val.Reserve(static_cast(r.size()), al); for (unsigned int i = 0; i < r.size(); ++i) { @@ -73,8 +74,19 @@ namespace glTF2 { return val; } - inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& /*al*/) { - val.SetDouble(r); + template + inline Value& MakeValueCast(Value& val, const std::vector & r, MemoryPoolAllocator<>& al) { + val.SetArray(); + val.Reserve(static_cast(r.size()), al); + for (unsigned int i = 0; i < r.size(); ++i) { + val.PushBack(static_cast(r[i]), al); + } + return val; + } + + template + inline Value& MakeValue(Value& val, T r, MemoryPoolAllocator<>& /*al*/) { + val.Set(r); return val; } @@ -104,8 +116,13 @@ namespace glTF2 { obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); Value vTmpMax, vTmpMin; - obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); - obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); + if (a.componentType == ComponentType_FLOAT) { + obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); + obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); + } else { + obj.AddMember("max", MakeValueCast(vTmpMax, a.max, w.mAl), w.mAl); + obj.AddMember("min", MakeValueCast(vTmpMin, a.min, w.mAl), w.mAl); + } } inline void Write(Value& obj, Animation& a, AssetWriter& w) diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index 4724c2ef4..cab02710f 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -152,6 +152,62 @@ static void IdentityMatrix4(mat4& o) { o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1; } +template +void SetAccessorRange(Ref acc, void* data, size_t count, + unsigned int numCompsIn, unsigned int numCompsOut) +{ + ai_assert(numCompsOut <= numCompsIn); + + // Allocate and initialize with large values. + for (unsigned int i = 0 ; i < numCompsOut ; i++) { + acc->min.push_back(DBL_MAX); + acc->max.push_back(DBL_MIN); + } + + size_t totalComps = count * numCompsIn; + T* buffer_ptr = static_cast(data); + T* buffer_end = buffer_ptr + totalComps; + + // Search and set extreme values. + for (; buffer_ptr < buffer_end ; buffer_ptr += numCompsIn) { + for (unsigned int j = 0 ; j < numCompsOut ; j++) { + double valueTmp = buffer_ptr[j]; + + if (valueTmp < acc->min[j]) { + acc->min[j] = valueTmp; + } + if (valueTmp > acc->max[j]) { + acc->max[j] = valueTmp; + } + } + } +} + +inline void SetAccessorRange(ComponentType compType, Ref acc, void* data, + size_t count, unsigned int numCompsIn, unsigned int numCompsOut) +{ + switch (compType) { + case ComponentType_SHORT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_UNSIGNED_SHORT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_UNSIGNED_INT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_FLOAT: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_BYTE: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + case ComponentType_UNSIGNED_BYTE: + SetAccessorRange(acc, data, count, numCompsIn, numCompsOut); + return; + } +} + inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) { @@ -187,33 +243,7 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu acc->type = typeOut; // calculate min and max values - { - // Allocate and initialize with large values. - float float_MAX = 10000000000000.0f; - for (unsigned int i = 0 ; i < numCompsOut ; i++) { - acc->min.push_back( float_MAX); - acc->max.push_back(-float_MAX); - } - - // Search and set extreme values. - float valueTmp; - for (unsigned int i = 0 ; i < count ; i++) { - for (unsigned int j = 0 ; j < numCompsOut ; j++) { - if (numCompsOut == 1) { - valueTmp = static_cast(data)[i]; - } else { - valueTmp = static_cast(data)[i][j]; - } - - if (valueTmp < acc->min[j]) { - acc->min[j] = valueTmp; - } - if (valueTmp > acc->max[j]) { - acc->max[j] = valueTmp; - } - } - } - } + SetAccessorRange(compType, acc, data, count, numCompsIn, numCompsOut); // copy the data acc->WriteData(count, data, numCompsIn*bytesPerComp); From 136996e1f674f964bfa55dd092ed3df5a2ad5f6c Mon Sep 17 00:00:00 2001 From: Cory Fabre Date: Fri, 22 Nov 2019 10:56:31 -0600 Subject: [PATCH 096/170] Use std::numeric_limits for double max --- code/glTF/glTFExporter.cpp | 5 +++-- code/glTF2/glTF2Exporter.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 676f8a83b..3faa1a84b 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Header files, standard library. #include +#include #include #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC @@ -181,8 +182,8 @@ void SetAccessorRange(Ref acc, void* data, unsigned int count, // Allocate and initialize with large values. for (unsigned int i = 0 ; i < numCompsOut ; i++) { - acc->min.push_back(DBL_MAX); - acc->max.push_back(DBL_MIN); + acc->min.push_back( std::numeric_limits::max()); + acc->max.push_back(-std::numeric_limits::max()); } size_t totalComps = count * numCompsIn; diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index 01ec1ba5a..f85803b52 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Header files, standard library. #include +#include #include using namespace rapidjson; @@ -160,8 +161,8 @@ void SetAccessorRange(Ref acc, void* data, size_t count, // Allocate and initialize with large values. for (unsigned int i = 0 ; i < numCompsOut ; i++) { - acc->min.push_back(DBL_MAX); - acc->max.push_back(DBL_MIN); + acc->min.push_back( std::numeric_limits::max()); + acc->max.push_back(-std::numeric_limits::max()); } size_t totalComps = count * numCompsIn; From 5cfb0fd633372bbbec87f08015139d71d330d4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc?= Date: Fri, 22 Nov 2019 18:27:34 +0100 Subject: [PATCH 097/170] Add function aiGetVersionPatch() to be able to display Assimp version as in Git tags --- code/Common/Version.cpp | 6 ++++++ include/assimp/version.h | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/code/Common/Version.cpp b/code/Common/Version.cpp index cf1da7d5b..ea4c996f0 100644 --- a/code/Common/Version.cpp +++ b/code/Common/Version.cpp @@ -66,6 +66,12 @@ ASSIMP_API const char* aiGetLegalString () { return LEGAL_INFORMATION; } +// ------------------------------------------------------------------------------------------------ +// Get Assimp patch version +ASSIMP_API unsigned int aiGetVersionPatch() { + return VER_PATCH; +} + // ------------------------------------------------------------------------------------------------ // Get Assimp minor version ASSIMP_API unsigned int aiGetVersionMinor () { diff --git a/include/assimp/version.h b/include/assimp/version.h index 2fdd37a43..90645a38f 100644 --- a/include/assimp/version.h +++ b/include/assimp/version.h @@ -62,6 +62,13 @@ extern "C" { */ ASSIMP_API const char* aiGetLegalString (void); +// --------------------------------------------------------------------------- +/** @brief Returns the current patch version number of Assimp. + * @return Patch version of the Assimp runtime the application was + * linked/built against + */ +ASSIMP_API unsigned int aiGetVersionPatch(void); + // --------------------------------------------------------------------------- /** @brief Returns the current minor version number of Assimp. * @return Minor version of the Assimp runtime the application was From 929d83398d686d7a7fbe8698413cf57f3e90223f Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Mon, 25 Nov 2019 13:51:33 +1100 Subject: [PATCH 098/170] Remove duplicate call to exporter. Fixes issue #2718. --- code/Common/Exporter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 8a95ceae5..b9bd0409b 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -445,8 +445,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties; - pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again); - exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); + pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again); exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); pimpl->mProgressHandler->UpdateFileWrite(4, 4); From 9ddeb4edadbd8fa52565f462b8f4d58bd1058ae6 Mon Sep 17 00:00:00 2001 From: bzt Date: Mon, 25 Nov 2019 05:03:10 +0100 Subject: [PATCH 099/170] MinGW support, profiling and signed error code --- code/M3D/m3d.h | 169 +++++++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 69 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index a73e7a02c..c1d690bcc 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -388,7 +388,7 @@ typedef struct { /* label entry */ typedef struct { - char *name; /* name of the annotation group or NULL */ + char *name; /* name of the annotation layer or NULL */ char *lang; /* language code or NULL */ char *text; /* the label text */ uint32_t color; /* color */ @@ -438,7 +438,7 @@ typedef struct { typedef struct { m3dhdr_t *raw; /* pointer to raw data */ char flags; /* internal flags */ - char errcode; /* returned error code */ + signed char errcode; /* returned error code */ char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s,fi_s; /* decoded sizes for types */ char *name; /* name of the model, like "Utah teapot" */ char *license; /* usage condition or license, like "MIT", "LGPL" or "BSD-3clause" */ @@ -1192,7 +1192,6 @@ static int _m3dstbi__parse_zlib(_m3dstbi__zbuf *a, int parse_header) return 0; } else { if (type == 1) { - _m3dstbi__init_zdefaults(); if (!_m3dstbi__zbuild_huffman(&a->z_length , _m3dstbi__zdefault_length , 288)) return 0; if (!_m3dstbi__zbuild_huffman(&a->z_distance, _m3dstbi__zdefault_distance, 32)) return 0; } else { @@ -1210,7 +1209,7 @@ static int _m3dstbi__do_zlib(_m3dstbi__zbuf *a, char *obuf, int olen, int exp, i a->zout = obuf; a->zout_end = obuf + olen; a->z_expandable = exp; - + _m3dstbi__init_zdefaults(); return _m3dstbi__parse_zlib(a, parse_header); } @@ -2012,6 +2011,9 @@ unsigned char * _m3dstbi_zlib_compress(unsigned char *data, int data_len, int *o #include /* get sprintf */ #include /* sprintf and strtod cares about number locale */ #endif +#ifdef M3D_PROFILING +#include +#endif #if !defined(M3D_NOIMPORTER) && defined(M3D_ASCII) /* helper functions for the ASCII parser */ @@ -2088,7 +2090,7 @@ char *_m3d_safestr(char *in, int morelines) } for(; o > out && (*(o-1) == ' ' || *(o-1) == '\t' || *(o-1) == '\r' || *(o-1) == '\n'); o--); *o = 0; - out = (char*)M3D_REALLOC(out, (uint64_t)o - (uint64_t)out + 1); + out = (char*)M3D_REALLOC(out, (uintptr_t)o - (uintptr_t)out + 1); } return out; } @@ -2322,6 +2324,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d m3da_t *a; m3di_t *t; #ifndef M3D_NONORMALS + char neednorm = 0; m3dv_t *norm = NULL, *v0, *v1, *v2, va, vb; #endif #ifndef M3D_NOANIMATION @@ -2339,6 +2342,10 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d const char *ol; char *ptr, *pe, *fn; #endif +#ifdef M3D_PROFILING + struct timeval tv0, tv1, tvd; + gettimeofday(&tv0, NULL); +#endif if(!data || (!M3D_CHUNKMAGIC(data, '3','D','M','O') #ifdef M3D_ASCII @@ -2647,6 +2654,9 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(!*ptr) goto asciiend; } } +#ifndef M3D_NONORMALS + if(model->face[i].normal[j] == (M3D_INDEX)-1U) neednorm = 1; +#endif ptr = _m3d_findarg(ptr); } } @@ -2870,7 +2880,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d pe = _m3d_findarg(pe); if(!*pe || *pe == '\r' || *pe == '\n') goto asciiend; buff = (unsigned char*)_m3d_findnl(ptr); - k = ((uint32_t)((uint64_t)buff - (uint64_t)ptr) / 3) + 1; + k = ((uint32_t)((uintptr_t)buff - (uintptr_t)ptr) / 3) + 1; i = model->numextra++; model->extra = (m3dchunk_t**)M3D_REALLOC(model->extra, model->numextra * sizeof(m3dchunk_t*)); if(!model->extra) goto memerr; @@ -2892,8 +2902,8 @@ asciiend: setlocale(LC_NUMERIC, ol); goto postprocess; } - /* Binary variant */ #endif + /* Binary variant */ if(!M3D_CHUNKMAGIC(data + 8, 'H','E','A','D')) { buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data+8, ((m3dchunk_t*)data)->length-8, 4096, (int*)&len, 1); @@ -2905,6 +2915,14 @@ asciiend: buff = (unsigned char*)M3D_REALLOC(buff, len); model->flags |= M3D_FLG_FREERAW; /* mark that we have to free the raw buffer */ data = buff; +#ifdef M3D_PROFILING + gettimeofday(&tv1, NULL); + tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; + tvd.tv_usec = tv1.tv_usec - tv0.tv_usec; + if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; } + printf(" Deflate model %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec); + memcpy(&tv0, &tv1, sizeof(struct timeval)); +#endif } else { len = ((m3dhdr_t*)data)->length; data += 8; @@ -2961,7 +2979,7 @@ asciiend: return NULL; } if(model->nb_s > M3D_NUMBONE) { - M3D_LOG("Model has more bones per vertex than what importer configured to support"); + M3D_LOG("Model has more bones per vertex than what importer was configured to support"); model->errcode = M3D_ERR_TRUNC; } @@ -3295,6 +3313,9 @@ memerr: M3D_LOG("Out of memory"); /* normal */ if(k & 2) data = _m3d_getidx(data, model->vi_s, &model->face[i].normal[j]); +#ifndef M3D_NONORMALS + if(model->face[i].normal[j] == (M3D_INDEX)-1U) neednorm = 1; +#endif } } model->face = (m3df_t*)M3D_REALLOC(model->face, model->numface * sizeof(m3df_t)); @@ -3454,9 +3475,18 @@ postprocess: #endif if(model) { M3D_LOG("Post-process"); +#ifdef M3D_PROFILING + gettimeofday(&tv1, NULL); + tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; + tvd.tv_usec = tv1.tv_usec - tv0.tv_usec; + if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; } + printf(" Parsing chunks %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec); +#endif #ifndef M3D_NONORMALS - if(model->numface && model->face) { + if(model->numface && model->face && neednorm) { /* if they are missing, calculate triangle normals into a temporary buffer */ + norm = (m3dv_t*)M3D_MALLOC(model->numface * sizeof(m3dv_t)); + if(!norm) goto memerr; for(i = 0, n = model->numvertex; i < model->numface; i++) if(model->face[i].normal[0] == -1U) { v0 = &model->vertex[model->face[i].vertex[0]]; @@ -3464,10 +3494,6 @@ postprocess: v2 = &model->vertex[model->face[i].vertex[2]]; va.x = v1->x - v0->x; va.y = v1->y - v0->y; va.z = v1->z - v0->z; vb.x = v2->x - v0->x; vb.y = v2->y - v0->y; vb.z = v2->z - v0->z; - if(!norm) { - norm = (m3dv_t*)M3D_MALLOC(model->numface * sizeof(m3dv_t)); - if(!norm) goto memerr; - } v0 = &norm[i]; v0->x = (va.y * vb.z) - (va.z * vb.y); v0->y = (va.z * vb.x) - (va.x * vb.z); @@ -3479,28 +3505,26 @@ postprocess: model->face[i].normal[2] = model->face[i].vertex[2] + n; } /* this is the fast way, we don't care if a normal is repeated in model->vertex */ - if(norm) { - M3D_LOG("Generating normals"); - model->flags |= M3D_FLG_GENNORM; - model->numvertex <<= 1; - model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t)); - if(!model->vertex) goto memerr; - memset(&model->vertex[n], 0, n * sizeof(m3dv_t)); - for(i = 0; i < model->numface; i++) - for(j = 0; j < 3; j++) { - v0 = &model->vertex[model->face[i].vertex[j] + n]; - v0->x += norm[i].x; - v0->y += norm[i].y; - v0->z += norm[i].z; - } - /* for each vertex, take the average of the temporary normals and use that */ - for(i = 0, v0 = &model->vertex[n]; i < n; i++, v0++) { - w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z)); - v0->x *= w; v0->y *= w; v0->z *= w; - v0->skinid = -1U; + M3D_LOG("Generating normals"); + model->flags |= M3D_FLG_GENNORM; + model->numvertex <<= 1; + model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t)); + if(!model->vertex) goto memerr; + memset(&model->vertex[n], 0, n * sizeof(m3dv_t)); + for(i = 0; i < model->numface; i++) + for(j = 0; j < 3; j++) { + v0 = &model->vertex[model->face[i].vertex[j] + n]; + v0->x += norm[i].x; + v0->y += norm[i].y; + v0->z += norm[i].z; } - M3D_FREE(norm); + /* for each vertex, take the average of the temporary normals and use that */ + for(i = 0, v0 = &model->vertex[n]; i < n; i++, v0++) { + w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z)); + v0->x *= w; v0->y *= w; v0->z *= w; + v0->skinid = -1U; } + M3D_FREE(norm); } #endif if(model->numbone && model->bone && model->numskin && model->skin && model->numvertex && model->vertex) { @@ -3539,6 +3563,13 @@ postprocess: _m3d_inv((M3D_FLOAT*)&model->bone[i].mat4); #endif } +#ifdef M3D_PROFILING + gettimeofday(&tv0, NULL); + tvd.tv_sec = tv0.tv_sec - tv1.tv_sec; + tvd.tv_usec = tv0.tv_usec - tv1.tv_usec; + if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; } + printf(" Post-process %ld.%06ld sec\n", tvd.tv_sec, tvd.tv_usec); +#endif } return model; } @@ -4509,8 +4540,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(model->preview.data && model->preview.length) { sl = _m3d_safestr(sn, 0); if(sl) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + 20; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 20; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl); M3D_FREE(sl); sl = NULL; @@ -4519,8 +4550,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); M3D_FREE(sn); sn = NULL; /* texture map */ if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + maxtmap * 32 + 12; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + maxtmap * 32 + 12; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Textmap\r\n"); last = (M3D_INDEX)-1U; @@ -4533,8 +4564,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } /* vertex chunk */ if(numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + maxvrtx * 128 + 10; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + maxvrtx * 128 + 10; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Vertex\r\n"); last = (M3D_INDEX)-1U; @@ -4559,11 +4590,11 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } /* bones chunk */ if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + 9; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 9; for(i = 0; i < model->numbone; i++) { len += strlen(model->bone[i].name) + 128; } - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Bones\r\n"); ptr = _m3d_prtbone(ptr, model->bone, model->numbone, (M3D_INDEX)-1U, 0, vrtxidx); @@ -4576,14 +4607,14 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); m = &model->material[j]; sn = _m3d_safestr(m->name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 12; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 12; for(i = 0; i < m->numprop; i++) { if(m->prop[i].type < 128) len += 32; else if(m->prop[i].value.textureid < model->numtexture && model->texture[m->prop[i].value.textureid].name) len += strlen(model->texture[m->prop[i].value.textureid].name) + 16; } - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Material %s\r\n", sn); M3D_FREE(sn); sn = NULL; @@ -4645,8 +4676,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(k) continue; sn = _m3d_safestr(model->inlined[j].name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 18; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 18; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Procedural\r\n%s\r\n\r\n", sn); M3D_FREE(sn); sn = NULL; @@ -4654,7 +4685,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } /* mesh face */ if(model->numface && face && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + model->numface * 128 + 6; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + model->numface * 128 + 6; last = (M3D_INDEX)-1U; if(!(flags & M3D_EXP_NOMATERIAL)) for(i = 0; i < model->numface; i++) { @@ -4666,7 +4697,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); len += 6; } } - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Mesh\r\n"); last = (M3D_INDEX)-1U; @@ -4703,8 +4734,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); for(j = 0; j < model->numshape; j++) { sn = _m3d_safestr(model->shape[j].name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 33; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 33; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Shape %s\r\n", sn); M3D_FREE(sn); sn = NULL; @@ -4715,14 +4746,14 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(cmd->type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])) || !cmd->arg) continue; cd = &m3d_commandtypes[cmd->type]; - ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(cd->key) + 3; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(cd->key) + 3; for(k = 0; k < cd->p; k++) switch(cd->a[k]) { case m3dcp_mi_t: if(cmd->arg[k] != -1U) { len += strlen(model->material[cmd->arg[k]].name) + 1; } break; case m3dcp_va_t: len += cmd->arg[k] * (cd->p - k - 1) * 16; k = cd->p; break; default: len += 16; break; } - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "%s", cd->key); for(k = n = 0, l = cd->p; k < l; k++) { @@ -4755,8 +4786,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(model->label[i].text) j += strlen(model->label[i].text); j += 40; } - ptr -= (uint64_t)out; len = (uint64_t)ptr + j; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + j; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } for(i = 0; i < model->numlabel; i++) { if(!i || _m3d_strcmp(sl, model->label[i].lang) || _m3d_strcmp(sn, model->label[i].name)) { @@ -4790,10 +4821,10 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); a = &model->action[j]; sn = _m3d_safestr(a->name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uint64_t)out; len = (uint64_t)ptr + strlen(sn) + 48; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 48; for(i = 0; i < a->numframe; i++) len += a->frame[i].numtransform * 128 + 8; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Action %d %s\r\n", a->durationmsec, sn); M3D_FREE(sn); sn = NULL; @@ -4813,8 +4844,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(model->inlined[i].name) j += strlen(model->inlined[i].name) + 6; if(j > 0) { - ptr -= (uint64_t)out; len = (uint64_t)ptr + j + 16; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + j + 16; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Assets\r\n"); for(i = 0; i < model->numinlined; i++) @@ -4827,8 +4858,8 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(model->numextra && (flags & M3D_EXP_EXTRA)) { for(i = 0; i < model->numextra; i++) { if(model->extra[i]->length < 9) continue; - ptr -= (uint64_t)out; len = (uint64_t)ptr + 17 + model->extra[i]->length * 3; - out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uint64_t)out; + ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 17 + model->extra[i]->length * 3; + out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Extra %c%c%c%c\r\n", model->extra[i]->magic[0] > ' ' ? model->extra[i]->magic[0] : '_', @@ -4842,7 +4873,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } } setlocale(LC_NUMERIC, ol); - len = (uint64_t)ptr - (uint64_t)out; + len = (uintptr_t)ptr - (uintptr_t)out; out = (unsigned char*)M3D_REALLOC(out, len + 1); if(!out) goto memerr; out[len] = 0; @@ -4943,7 +4974,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); case 8: *((double*)out) = tmap[i].data.u; out += 8; *((double*)out) = tmap[i].data.v; out += 8; break; } } - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); out = NULL; len += *length; } @@ -4993,7 +5024,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid); } - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); out = NULL; len += *length; } @@ -5035,7 +5066,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } } } - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); out = NULL; len += *length; } @@ -5084,7 +5115,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); break; } } - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); len += *length; out = NULL; } @@ -5144,7 +5175,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]); } } - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); len += *length; out = NULL; } @@ -5195,7 +5226,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } } } - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); len += *length; out = NULL; } @@ -5207,7 +5238,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); sl = model->label[i].lang; sn = model->label[i].name; if(length) { - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); len += *length; } chunklen = 8 + 2 * si_s + ci_s + model->numlabel * (vi_s + si_s); @@ -5229,7 +5260,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text)); } if(length) { - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); len += *length; } out = NULL; @@ -5257,7 +5288,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]); } } - *length = (uint64_t)out - (uint64_t)((uint8_t*)h + len); + *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); len += *length; out = NULL; } From 7230f32c143d656f365d628de1d7ad1f14dced61 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Mon, 25 Nov 2019 20:58:21 +1100 Subject: [PATCH 100/170] Fix issue with y UV translation. Fixes #2119. --- code/glTF2/glTF2Importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 43eabdab7..88345f98a 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -205,7 +205,7 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset if (prop.textureTransformSupported) { aiUVTransform transform; transform.mTranslation.x = prop.TextureTransformExt_t.offset[0]; - transform.mTranslation.y = prop.TextureTransformExt_t.offset[0]; + transform.mTranslation.y = prop.TextureTransformExt_t.offset[1]; transform.mRotation = prop.TextureTransformExt_t.rotation; transform.mScaling.x = prop.TextureTransformExt_t.scale[0]; transform.mScaling.y = prop.TextureTransformExt_t.scale[1]; From b4f778f53b11340facb26371d2e0ae3e6c12dda2 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Tue, 26 Nov 2019 18:17:35 +1100 Subject: [PATCH 101/170] Fix aiGetMaterialUVTransform which assumed the data was 4 floats when in fact it is 5 floats. Fixes and issue seen in #2119. --- code/Material/MaterialSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index fabd9415a..aa3df9ac2 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -273,14 +273,14 @@ aiReturn aiGetMaterialColor(const aiMaterial* pMat, } // ------------------------------------------------------------------------------------------------ -// Get a aiUVTransform (4 floats) from the material +// Get a aiUVTransform (5 floats) from the material aiReturn aiGetMaterialUVTransform(const aiMaterial* pMat, const char* pKey, unsigned int type, unsigned int index, aiUVTransform* pOut) { - unsigned int iMax = 4; + unsigned int iMax = 5; return aiGetMaterialFloatArray(pMat,pKey,type,index,(ai_real*)pOut,&iMax); } From e4f1b8e609d6957ea664e1759600a8b6600d1189 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Wed, 27 Nov 2019 11:05:31 +1100 Subject: [PATCH 102/170] Correctly change the coordinate system of the glTF UV transforms to match those used internally inside Assimp. This should now hopefully result in a complete implementation for issue #2119 --- code/glTF2/glTF2Importer.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 88345f98a..1868ec119 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -204,11 +204,21 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset if (prop.textureTransformSupported) { aiUVTransform transform; - transform.mTranslation.x = prop.TextureTransformExt_t.offset[0]; - transform.mTranslation.y = prop.TextureTransformExt_t.offset[1]; - transform.mRotation = prop.TextureTransformExt_t.rotation; transform.mScaling.x = prop.TextureTransformExt_t.scale[0]; transform.mScaling.y = prop.TextureTransformExt_t.scale[1]; + transform.mRotation = -prop.TextureTransformExt_t.rotation; // must be negated + + // A change of coordinates is required to map glTF UV transformations into the space used by + // Assimp. In glTF all UV origins are at 0,1 (top left of texture) in Assimp space. In Assimp + // rotation occurs around the image center (0.5,0.5) where as in glTF rotation is around the + // texture origin. All three can be corrected for solely by a change of the translation since + // the transformations available are shape preserving. Note the importer already flips the V + // coordinate of the actual meshes during import. + ai_real rcos(cos(-transform.mRotation)); + ai_real rsin(sin(-transform.mRotation)); + transform.mTranslation.x = (0.5 * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0]; + transform.mTranslation.y = ((0.5 * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];; + mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot); } From 30851b796faaac0bd7fcb74974a06dd411784a3a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 27 Nov 2019 17:18:12 +0100 Subject: [PATCH 103/170] Update glTF2Importer.cpp Make them const --- code/glTF2/glTF2Importer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 1868ec119..dd80aeba9 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -214,8 +214,8 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset // texture origin. All three can be corrected for solely by a change of the translation since // the transformations available are shape preserving. Note the importer already flips the V // coordinate of the actual meshes during import. - ai_real rcos(cos(-transform.mRotation)); - ai_real rsin(sin(-transform.mRotation)); + const ai_real rcos(cos(-transform.mRotation)); + const ai_real rsin(sin(-transform.mRotation)); transform.mTranslation.x = (0.5 * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0]; transform.mTranslation.y = ((0.5 * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];; From 4754d2dc6d13276a9e8b0586a83afd53840916c4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 27 Nov 2019 17:32:55 +0100 Subject: [PATCH 104/170] Update CMakeLists.txt - closes https://github.com/assimp/assimp/issues/2785 - Disable optimization in debug mode. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 693d6f16a..4caaaf4a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,7 +253,7 @@ ELSEIF(MSVC) IF(MSVC12) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() - SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /Zi") + SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /Zi /O0") ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) IF(NOT HUNTER_ENABLED) SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}") From 97b71dd03b6a4caafa1be137fa036d142846d1ce Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Thu, 28 Nov 2019 09:01:01 +1000 Subject: [PATCH 105/170] Add reading of extensionsRequired and explicit check to throw an error if Draco compression is required. Fixes issue #2791. --- code/glTF2/glTF2Asset.h | 8 ++++++++ code/glTF2/glTF2Asset.inl | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index 831a763cd..d13ebfd66 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -1034,6 +1034,12 @@ namespace glTF2 bool KHR_texture_transform; } extensionsUsed; + //! Keeps info about the required extensions + struct RequiredExtensions + { + bool KHR_draco_mesh_compression; + } extensionsRequired; + AssetMetadata asset; @@ -1076,6 +1082,7 @@ namespace glTF2 , textures (*this, "textures") { memset(&extensionsUsed, 0, sizeof(extensionsUsed)); + memset(&extensionsRequired, 0, sizeof(extensionsRequired)); } //! Main function @@ -1094,6 +1101,7 @@ namespace glTF2 void ReadBinaryHeader(IOStream& stream, std::vector& sceneData); void ReadExtensionsUsed(Document& doc); + void ReadExtensionsRequired(Document& doc); IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); }; diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 4259022e9..32bca88ce 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -1432,6 +1432,12 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) // Load the metadata asset.Read(doc); ReadExtensionsUsed(doc); + ReadExtensionsRequired(doc); + + // Currently Draco is not supported + if (extensionsRequired.KHR_draco_mesh_compression) { + throw DeadlyImportError("GLTF: Draco mesh compression not currently supported."); + } // Prepare the dictionaries for (size_t i = 0; i < mDicts.size(); ++i) { @@ -1478,6 +1484,28 @@ inline void Asset::SetAsBinary() } } +// As required extensions are only a concept in glTF 2.0, this is here +// instead of glTFCommon.h +#define CHECK_REQUIRED_EXT(EXT) \ + if (exts.find(#EXT) != exts.end()) extensionsRequired.EXT = true; + +inline void Asset::ReadExtensionsRequired(Document& doc) +{ + Value* extsRequired = FindArray(doc, "extensionsRequired"); + if (!extsRequired) return; + + std::gltf_unordered_map exts; + + for (unsigned int i = 0; i < extsRequired->Size(); ++i) { + if ((*extsRequired)[i].IsString()) { + exts[(*extsRequired)[i].GetString()] = true; + } + } + + CHECK_REQUIRED_EXT(KHR_draco_mesh_compression); + + #undef CHECK_REQUIRED_EXT +} inline void Asset::ReadExtensionsUsed(Document& doc) { From 7967deb06a7c549d16133330e3d383faa84f425f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Dec 2019 12:34:45 +0100 Subject: [PATCH 106/170] Update glTF2Asset.inl some minor review finding: use brackets and add a newline. --- code/glTF2/glTF2Asset.inl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 32bca88ce..99f8c876f 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -1492,10 +1492,11 @@ inline void Asset::SetAsBinary() inline void Asset::ReadExtensionsRequired(Document& doc) { Value* extsRequired = FindArray(doc, "extensionsRequired"); - if (!extsRequired) return; + if (nullptr == extsRequired) { + return; + } std::gltf_unordered_map exts; - for (unsigned int i = 0; i < extsRequired->Size(); ++i) { if ((*extsRequired)[i].IsString()) { exts[(*extsRequired)[i].GetString()] = true; From 4071fcd398e4a7cca0fbf5586c680f75dffb2006 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Dec 2019 22:46:48 +0100 Subject: [PATCH 107/170] Update Exporter.cpp Fix format. --- code/Common/Exporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 07f95fbb4..25a78114f 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -445,7 +445,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties; - pProp->SetPropertyBool("bJoinIdenticalVertices", pp & aiProcess_JoinIdenticalVertices); + pProp->SetPropertyBool("bJoinIdenticalVertices", pp & aiProcess_JoinIdenticalVertices); exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp); pimpl->mProgressHandler->UpdateFileWrite(4, 4); From 5297529bb156aec1b2812b5002a84ecaea57441e Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 2 Dec 2019 10:07:48 +0000 Subject: [PATCH 108/170] MSVC: Disable optimisations in debug build Fixes #2799 and #2785 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4caaaf4a4..7544d9255 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,7 +253,7 @@ ELSEIF(MSVC) IF(MSVC12) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() - SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /Zi /O0") + SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Zi /Od") ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) IF(NOT HUNTER_ENABLED) SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}") From 496382982ae7ded19d00155467b840ffe3842472 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 2 Dec 2019 11:56:55 +0000 Subject: [PATCH 109/170] Remove cout calls from FBX, LWO and B3D Fixes #2797 --- code/B3D/B3DImporter.cpp | 118 ++++++++++++++-------------------- code/FBX/FBXConverter.cpp | 7 +- code/LWO/LWOLoader.cpp | 2 - include/assimp/LineSplitter.h | 2 +- 4 files changed, 54 insertions(+), 75 deletions(-) diff --git a/code/B3D/B3DImporter.cpp b/code/B3D/B3DImporter.cpp index ba484ca00..b483ed752 100644 --- a/code/B3D/B3DImporter.cpp +++ b/code/B3D/B3DImporter.cpp @@ -117,20 +117,8 @@ const aiImporterDesc* B3DImporter::GetInfo () const return &desc; } -#ifdef DEBUG_B3D - extern "C"{ void _stdcall AllocConsole(); } -#endif // ------------------------------------------------------------------------------------------------ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){ - -#ifdef DEBUG_B3D - AllocConsole(); - freopen( "conin$","r",stdin ); - freopen( "conout$","w",stdout ); - freopen( "conout$","w",stderr ); - cout<<"Hello world from the B3DImporter!"< file( pIOHandler->Open( pFile)); // Check whether we can read from the file @@ -158,7 +146,7 @@ AI_WONT_RETURN void B3DImporter::Oops(){ // ------------------------------------------------------------------------------------------------ AI_WONT_RETURN void B3DImporter::Fail( string str ){ #ifdef DEBUG_B3D - cout<<"Error in B3D file data: "<=(int)_materials.size() ){ +void B3DImporter::ReadTRIS(int v0) { + int matid = ReadInt(); + if (matid == -1) { + matid = 0; + } else if (matid < 0 || matid >= (int)_materials.size()) { #ifdef DEBUG_B3D - cout<<"material id="< mesh(new aiMesh); + std::unique_ptr mesh(new aiMesh); - mesh->mMaterialIndex=matid; - mesh->mNumFaces=0; - mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE; + mesh->mMaterialIndex = matid; + mesh->mNumFaces = 0; + mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - int n_tris=ChunkSize()/12; - aiFace *face=mesh->mFaces=new aiFace[n_tris]; + int n_tris = ChunkSize() / 12; + aiFace *face = mesh->mFaces = new aiFace[n_tris]; - for( int i=0;i=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){ + for (int i = 0; i < n_tris; ++i) { + int i0 = ReadInt() + v0; + int i1 = ReadInt() + v0; + int i2 = ReadInt() + v0; + if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) { #ifdef DEBUG_B3D - cout<<"Bad triangle index: i0="<mNumIndices=3; - face->mIndices=new unsigned[3]; - face->mIndices[0]=i0; - face->mIndices[1]=i1; - face->mIndices[2]=i2; - ++mesh->mNumFaces; - ++face; - } + Fail("Bad triangle index"); + continue; + } + face->mNumIndices = 3; + face->mIndices = new unsigned[3]; + face->mIndices[0] = i0; + face->mIndices[1] = i1; + face->mIndices[2] = i2; + ++mesh->mNumFaces; + ++face; + } - _meshes.emplace_back( std::move(mesh) ); + _meshes.emplace_back(std::move(mesh)); } // ------------------------------------------------------------------------------------------------ @@ -453,29 +441,23 @@ void B3DImporter::ReadMESH(){ } // ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadBONE( int id ){ - while( ChunkSize() ){ - int vertex=ReadInt(); - float weight=ReadFloat(); - if( vertex<0 || vertex>=(int)_vertices.size() ){ - Fail( "Bad vertex index" ); - } +void B3DImporter::ReadBONE(int id) { + while (ChunkSize()) { + int vertex = ReadInt(); + float weight = ReadFloat(); + if (vertex < 0 || vertex >= (int)_vertices.size()) { + Fail("Bad vertex index"); + } - Vertex &v=_vertices[vertex]; - int i; - for( i=0;i<4;++i ){ - if( !v.weights[i] ){ - v.bones[i]=id; - v.weights[i]=weight; - break; - } - } -#ifdef DEBUG_B3D - if( i==4 ){ - cout<<"Too many bone weights"<mName = bone_name; @@ -1648,7 +1647,7 @@ namespace Assimp { bone_map.insert(std::pair(deformer_name, bone)); } - std::cout << "bone research: Indicies size: " << out_indices.size() << std::endl; + ASSIMP_LOG_DEBUG_F("bone research: Indicies size: %zu", out_indices.size()); // lookup must be populated in case something goes wrong // this also allocates bones to mesh instance outside diff --git a/code/LWO/LWOLoader.cpp b/code/LWO/LWOLoader.cpp index 1e5b92c32..242538056 100644 --- a/code/LWO/LWOLoader.cpp +++ b/code/LWO/LWOLoader.cpp @@ -586,7 +586,6 @@ void LWOImporter::GenerateNodeGraph(std::map& apcNodes) root->mName.Set(""); //Set parent of all children, inserting pivots - //std::cout << "Set parent of all children" << std::endl; std::map mapPivot; for (auto itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) { @@ -618,7 +617,6 @@ void LWOImporter::GenerateNodeGraph(std::map& apcNodes) } //Merge pivot map into node map - //std::cout << "Merge pivot map into node map" << std::endl; for (auto itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end(); ++itMapPivot) { apcNodes[itMapPivot->first] = itMapPivot->second; } diff --git a/include/assimp/LineSplitter.h b/include/assimp/LineSplitter.h index 6c1097bb6..271b321cc 100644 --- a/include/assimp/LineSplitter.h +++ b/include/assimp/LineSplitter.h @@ -72,7 +72,7 @@ for(LineSplitter splitter(stream);splitter;++splitter) { if (strtol(splitter[2]) > 5) { .. } } - std::cout << "Current line is: " << splitter.get_index() << std::endl; + ASSIMP_LOG_DEBUG_F("Current line is: %zu", splitter.get_index()); } @endcode */ From e668eead19778519c8e9a33bb17fb2cc4a8a14e7 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 3 Dec 2019 12:56:21 +0000 Subject: [PATCH 110/170] Some cleanup of M3D support Wrap the m3d.h header Note: C++11 support required to use in a threaded environment Fix export memory leak (although exporter apopears to be unused) Apply clangformat. --- code/CMakeLists.txt | 2 + code/M3D/M3DExporter.cpp | 640 +++++++++++----------- code/M3D/M3DExporter.h | 12 +- code/M3D/M3DImporter.cpp | 1102 +++++++++++++++++++------------------- code/M3D/M3DImporter.h | 53 +- code/M3D/M3DWrapper.cpp | 136 +++++ code/M3D/M3DWrapper.h | 96 ++++ 7 files changed, 1117 insertions(+), 924 deletions(-) create mode 100644 code/M3D/M3DWrapper.cpp create mode 100644 code/M3D/M3DWrapper.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 827f43333..85aa620d9 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -411,6 +411,8 @@ ADD_ASSIMP_IMPORTER( M3D M3D/M3DMaterials.h M3D/M3DImporter.h M3D/M3DImporter.cpp + M3D/M3DWrapper.h + M3D/M3DWrapper.cpp M3D/m3d.h ) diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index b1c7ebdba..0e84f6d4f 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -55,17 +55,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include // aiGetVersion -#include -#include -#include -#include // StreamWriterLE #include // DeadlyExportError +#include // StreamWriterLE #include // aiTextureType -#include #include +#include +#include // aiGetVersion +#include +#include +#include + #include "M3DExporter.h" #include "M3DMaterials.h" +#include "M3DWrapper.h" // RESOURCES: // https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md @@ -80,341 +82,331 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - aiAnimation -> m3d_action (frame with timestamp and list of bone id, position, orientation * triplets, instead of per bone timestamp + lists) */ -using namespace Assimp; - -namespace Assimp { - - // --------------------------------------------------------------------- - // Worker function for exporting a scene to binary M3D. - // Prototyped and registered in Exporter.cpp - void ExportSceneM3D ( - const char* pFile, - IOSystem* pIOSystem, - const aiScene* pScene, - const ExportProperties* pProperties - ){ - // initialize the exporter - M3DExporter exporter(pScene, pProperties); - - // perform binary export - exporter.doExport(pFile, pIOSystem, false); - } - - // --------------------------------------------------------------------- - // Worker function for exporting a scene to ASCII A3D. - // Prototyped and registered in Exporter.cpp - void ExportSceneA3D ( - const char* pFile, - IOSystem* pIOSystem, - const aiScene* pScene, - const ExportProperties* pProperties - - ){ - // initialize the exporter - M3DExporter exporter(pScene, pProperties); - - // perform ascii export - exporter.doExport(pFile, pIOSystem, true); - } - -} // end of namespace Assimp // ------------------------------------------------------------------------------------------------ -M3DExporter::M3DExporter ( const aiScene* pScene, const ExportProperties* pProperties ) -: mScene(pScene) -, mProperties(pProperties) -, outfile() -, m3d(nullptr) { } - -// ------------------------------------------------------------------------------------------------ -void M3DExporter::doExport ( - const char* pFile, - IOSystem* pIOSystem, - bool toAscii -){ - // TODO: convert mProperties into M3D_EXP_* flags - (void)mProperties; - - // open the indicated file for writing (in binary / ASCII mode) - outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb")); - if (!outfile) { - throw DeadlyExportError( "could not open output .m3d file: " + std::string(pFile) ); - } - - // use malloc() here because m3d_free() will call free() - m3d = (m3d_t*)calloc(1, sizeof(m3d_t)); - if(!m3d) { - throw DeadlyExportError( "memory allocation error" ); - } - m3d->name = _m3d_safestr((char*)&mScene->mRootNode->mName.data, 2); - - // Create a model from assimp structures - aiMatrix4x4 m; - NodeWalk(mScene->mRootNode, m); - - // serialize the structures - unsigned int size; - unsigned char *output = m3d_save(m3d, M3D_EXP_FLOAT, - M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), &size); - m3d_free(m3d); - if(!output || size < 8) { - throw DeadlyExportError( "unable to serialize into Model 3D" ); - } - - // Write out serialized model - outfile->Write(output, size, 1); - - // explicitly release file pointer, - // so we don't have to rely on class destruction. - outfile.reset(); -} - - +// Conversion functions // ------------------------------------------------------------------------------------------------ // helper to add a vertex (private to NodeWalk) -m3dv_t *M3DExporter::AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) -{ - if(v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0; - if(v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0; - if(v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0; - if(v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0; - vrtx = (m3dv_t*)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t)); - memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t)); - *idx = *numvrtx; - (*numvrtx)++; - return vrtx; +m3dv_t *AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx) { + if (v->x == (M3D_FLOAT)-0.0) v->x = (M3D_FLOAT)0.0; + if (v->y == (M3D_FLOAT)-0.0) v->y = (M3D_FLOAT)0.0; + if (v->z == (M3D_FLOAT)-0.0) v->z = (M3D_FLOAT)0.0; + if (v->w == (M3D_FLOAT)-0.0) v->w = (M3D_FLOAT)0.0; + vrtx = (m3dv_t *)M3D_REALLOC(vrtx, ((*numvrtx) + 1) * sizeof(m3dv_t)); + memcpy(&vrtx[*numvrtx], v, sizeof(m3dv_t)); + *idx = *numvrtx; + (*numvrtx)++; + return vrtx; } // ------------------------------------------------------------------------------------------------ // helper to add a tmap (private to NodeWalk) -m3dti_t *M3DExporter::AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx) -{ - tmap = (m3dti_t*)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t)); - memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t)); - *idx = *numtmap; - (*numtmap)++; - return tmap; -} - -// ------------------------------------------------------------------------------------------------ -// recursive node walker -void M3DExporter::NodeWalk(const aiNode* pNode, aiMatrix4x4 m) -{ - aiMatrix4x4 nm = m * pNode->mTransformation; - - for(unsigned int i = 0; i < pNode->mNumMeshes; i++) { - const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]]; - unsigned int mi = (M3D_INDEX)-1U; - if(mScene->mMaterials) { - // get the material for this mesh - mi = addMaterial(mScene->mMaterials[mesh->mMaterialIndex]); - } - // iterate through the mesh faces - for(unsigned int j = 0; j < mesh->mNumFaces; j++) { - unsigned int n; - const aiFace* face = &(mesh->mFaces[j]); - // only triangle meshes supported for now - if(face->mNumIndices != 3) { - throw DeadlyExportError( "use aiProcess_Triangulate before export" ); - } - // add triangle to the output - n = m3d->numface++; - m3d->face = (m3df_t*)M3D_REALLOC(m3d->face, - m3d->numface * sizeof(m3df_t)); - if(!m3d->face) { - throw DeadlyExportError( "memory allocation error" ); - } - /* set all index to -1 by default */ - m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] = - m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] = - m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = -1U; - m3d->face[n].materialid = mi; - for(unsigned int k = 0; k < face->mNumIndices; k++) { - // get the vertex's index - unsigned int l = face->mIndices[k]; - unsigned int idx; - m3dv_t vertex; - m3dti_t ti; - // multiply the position vector by the transformation matrix - aiVector3D v = mesh->mVertices[l]; - v *= nm; - vertex.x = v.x; - vertex.y = v.y; - vertex.z = v.z; - vertex.w = 1.0; - vertex.color = 0; - vertex.skinid = -1U; - // add color if defined - if(mesh->HasVertexColors(0)) - vertex.color = mkColor(&mesh->mColors[0][l]); - // save the vertex to the output - m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, - &vertex, &idx); - m3d->face[n].vertex[k] = (M3D_INDEX)idx; - // do we have texture coordinates? - if(mesh->HasTextureCoords(0)) { - ti.u = mesh->mTextureCoords[0][l].x; - ti.v = mesh->mTextureCoords[0][l].y; - m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx); - m3d->face[n].texcoord[k] = (M3D_INDEX)idx; - } - // do we have normal vectors? - if(mesh->HasNormals()) { - vertex.x = mesh->mNormals[l].x; - vertex.y = mesh->mNormals[l].y; - vertex.z = mesh->mNormals[l].z; - vertex.color = 0; - m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx); - m3d->face[n].normal[k] = (M3D_INDEX)idx; - } - } - } - } - // repeat for the children nodes - for (unsigned int i = 0; i < pNode->mNumChildren; i++) { - NodeWalk(pNode->mChildren[i], nm); - } +m3dti_t *AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx) { + tmap = (m3dti_t *)M3D_REALLOC(tmap, ((*numtmap) + 1) * sizeof(m3dti_t)); + memcpy(&tmap[*numtmap], ti, sizeof(m3dti_t)); + *idx = *numtmap; + (*numtmap)++; + return tmap; } // ------------------------------------------------------------------------------------------------ // convert aiColor4D into uint32_t -uint32_t M3DExporter::mkColor(aiColor4D* c) -{ - return ((uint8_t)(c->a*255) << 24L) | - ((uint8_t)(c->b*255) << 16L) | - ((uint8_t)(c->g*255) << 8L) | - ((uint8_t)(c->r*255) << 0L); -} - -// ------------------------------------------------------------------------------------------------ -// add a material to the output -M3D_INDEX M3DExporter::addMaterial(const aiMaterial *mat) -{ - unsigned int mi = -1U; - aiColor4D c; - aiString name; - ai_real f; - char *fn; - - if(mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length && - strcmp((char*)&name.data, AI_DEFAULT_MATERIAL_NAME)) { - // check if we have saved a material by this name. This has to be done - // because only the referenced materials should be added to the output - for(unsigned int i = 0; i < m3d->nummaterial; i++) - if(!strcmp((char*)&name.data, m3d->material[i].name)) { - mi = i; - break; - } - // if not found, add the material to the output - if(mi == -1U) { - unsigned int k; - mi = m3d->nummaterial++; - m3d->material = (m3dm_t*)M3D_REALLOC(m3d->material, m3d->nummaterial - * sizeof(m3dm_t)); - if(!m3d->material) { - throw DeadlyExportError( "memory allocation error" ); - } - m3d->material[mi].name = _m3d_safestr((char*)&name.data, 0); - m3d->material[mi].numprop = 0; - m3d->material[mi].prop = NULL; - // iterate through the material property table and see what we got - for(k = 0; k < 15; k++) { - unsigned int j; - if(m3d_propertytypes[k].format == m3dpf_map) - continue; - if(aiProps[k].pKey) { - switch(m3d_propertytypes[k].format) { - case m3dpf_color: - if(mat->Get(aiProps[k].pKey, aiProps[k].type, - aiProps[k].index, c) == AI_SUCCESS) - addProp(&m3d->material[mi], - m3d_propertytypes[k].id, mkColor(&c)); - break; - case m3dpf_float: - if(mat->Get(aiProps[k].pKey, aiProps[k].type, - aiProps[k].index, f) == AI_SUCCESS) - addProp(&m3d->material[mi], - m3d_propertytypes[k].id, - /* not (uint32_t)f, because we don't want to convert - * it, we want to see it as 32 bits of memory */ - *((uint32_t*)&f)); - break; - case m3dpf_uint8: - if(mat->Get(aiProps[k].pKey, aiProps[k].type, - aiProps[k].index, j) == AI_SUCCESS) { - // special conversion for illumination model property - if(m3d_propertytypes[k].id == m3dp_il) { - switch(j) { - case aiShadingMode_NoShading: j = 0; break; - case aiShadingMode_Phong: j = 2; break; - default: j = 1; break; - } - } - addProp(&m3d->material[mi], - m3d_propertytypes[k].id, j); - } - break; - default: - if(mat->Get(aiProps[k].pKey, aiProps[k].type, - aiProps[k].index, j) == AI_SUCCESS) - addProp(&m3d->material[mi], - m3d_propertytypes[k].id, j); - break; - } - } - if(aiTxProps[k].pKey && - mat->GetTexture((aiTextureType)aiTxProps[k].type, - aiTxProps[k].index, &name, NULL, NULL, NULL, - NULL, NULL) == AI_SUCCESS) { - unsigned int i; - for(j = name.length-1; j > 0 && name.data[j]!='.'; j++); - if(j && name.data[j]=='.' && - (name.data[j+1]=='p' || name.data[j+1]=='P') && - (name.data[j+1]=='n' || name.data[j+1]=='N') && - (name.data[j+1]=='g' || name.data[j+1]=='G')) - name.data[j]=0; - // do we have this texture saved already? - fn = _m3d_safestr((char*)&name.data, 0); - for(j = 0, i = -1U; j < m3d->numtexture; j++) - if(!strcmp(fn, m3d->texture[j].name)) { - i = j; - free(fn); - break; - } - if(i == -1U) { - i = m3d->numtexture++; - m3d->texture = (m3dtx_t*)M3D_REALLOC( - m3d->texture, - m3d->numtexture * sizeof(m3dtx_t)); - if(!m3d->texture) { - throw DeadlyExportError( "memory allocation error" ); - } - // we don't need the texture itself, only its name - m3d->texture[i].name = fn; - m3d->texture[i].w = 0; - m3d->texture[i].h = 0; - m3d->texture[i].d = NULL; - } - addProp(&m3d->material[mi], - m3d_propertytypes[k].id + 128, i); - } - } - } - } - return mi; +uint32_t mkColor(aiColor4D *c) { + return ((uint8_t)(c->a * 255) << 24L) | + ((uint8_t)(c->b * 255) << 16L) | + ((uint8_t)(c->g * 255) << 8L) | + ((uint8_t)(c->r * 255) << 0L); } // ------------------------------------------------------------------------------------------------ // add a material property to the output -void M3DExporter::addProp(m3dm_t *m, uint8_t type, uint32_t value) -{ - unsigned int i; - i = m->numprop++; - m->prop = (m3dp_t*)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t)); - if(!m->prop) { throw DeadlyExportError( "memory allocation error" ); } - m->prop[i].type = type; - m->prop[i].value.num = value; +void addProp(m3dm_t *m, uint8_t type, uint32_t value) { + unsigned int i; + i = m->numprop++; + m->prop = (m3dp_t *)M3D_REALLOC(m->prop, m->numprop * sizeof(m3dp_t)); + if (!m->prop) { + throw DeadlyExportError("memory allocation error"); + } + m->prop[i].type = type; + m->prop[i].value.num = value; } +// ------------------------------------------------------------------------------------------------ +// add a material to the output +M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { + unsigned int mi = -1U; + aiColor4D c; + aiString name; + ai_real f; + char *fn; + + if (mat && mat->Get(AI_MATKEY_NAME, name) == AI_SUCCESS && name.length && + strcmp((char *)&name.data, AI_DEFAULT_MATERIAL_NAME)) { + // check if we have saved a material by this name. This has to be done + // because only the referenced materials should be added to the output + for (unsigned int i = 0; i < m3d->nummaterial; i++) + if (!strcmp((char *)&name.data, m3d->material[i].name)) { + mi = i; + break; + } + // if not found, add the material to the output + if (mi == -1U) { + unsigned int k; + mi = m3d->nummaterial++; + m3d->material = (m3dm_t *)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t)); + if (!m3d->material) { + throw DeadlyExportError("memory allocation error"); + } + m3d->material[mi].name = _m3d_safestr((char *)&name.data, 0); + m3d->material[mi].numprop = 0; + m3d->material[mi].prop = NULL; + // iterate through the material property table and see what we got + for (k = 0; k < 15; k++) { + unsigned int j; + if (m3d_propertytypes[k].format == m3dpf_map) + continue; + if (aiProps[k].pKey) { + switch (m3d_propertytypes[k].format) { + case m3dpf_color: + if (mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, c) == AI_SUCCESS) + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, mkColor(&c)); + break; + case m3dpf_float: + if (mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, f) == AI_SUCCESS) + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, + /* not (uint32_t)f, because we don't want to convert + * it, we want to see it as 32 bits of memory */ + *((uint32_t *)&f)); + break; + case m3dpf_uint8: + if (mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, j) == AI_SUCCESS) { + // special conversion for illumination model property + if (m3d_propertytypes[k].id == m3dp_il) { + switch (j) { + case aiShadingMode_NoShading: j = 0; break; + case aiShadingMode_Phong: j = 2; break; + default: j = 1; break; + } + } + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, j); + } + break; + default: + if (mat->Get(aiProps[k].pKey, aiProps[k].type, + aiProps[k].index, j) == AI_SUCCESS) + addProp(&m3d->material[mi], + m3d_propertytypes[k].id, j); + break; + } + } + if (aiTxProps[k].pKey && + mat->GetTexture((aiTextureType)aiTxProps[k].type, + aiTxProps[k].index, &name, NULL, NULL, NULL, + NULL, NULL) == AI_SUCCESS) { + unsigned int i; + for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++) + ; + if (j && name.data[j] == '.' && + (name.data[j + 1] == 'p' || name.data[j + 1] == 'P') && + (name.data[j + 1] == 'n' || name.data[j + 1] == 'N') && + (name.data[j + 1] == 'g' || name.data[j + 1] == 'G')) + name.data[j] = 0; + // do we have this texture saved already? + fn = _m3d_safestr((char *)&name.data, 0); + for (j = 0, i = -1U; j < m3d->numtexture; j++) + if (!strcmp(fn, m3d->texture[j].name)) { + i = j; + free(fn); + break; + } + if (i == -1U) { + i = m3d->numtexture++; + m3d->texture = (m3dtx_t *)M3D_REALLOC( + m3d->texture, + m3d->numtexture * sizeof(m3dtx_t)); + if (!m3d->texture) { + throw DeadlyExportError("memory allocation error"); + } + // we don't need the texture itself, only its name + m3d->texture[i].name = fn; + m3d->texture[i].w = 0; + m3d->texture[i].h = 0; + m3d->texture[i].d = NULL; + } + addProp(&m3d->material[mi], + m3d_propertytypes[k].id + 128, i); + } + } + } + } + return mi; +} + +namespace Assimp { + +// --------------------------------------------------------------------- +// Worker function for exporting a scene to binary M3D. +// Prototyped and registered in Exporter.cpp +void ExportSceneM3D( + const char *pFile, + IOSystem *pIOSystem, + const aiScene *pScene, + const ExportProperties *pProperties) { + // initialize the exporter + M3DExporter exporter(pScene, pProperties); + + // perform binary export + exporter.doExport(pFile, pIOSystem, false); +} + +// --------------------------------------------------------------------- +// Worker function for exporting a scene to ASCII A3D. +// Prototyped and registered in Exporter.cpp +void ExportSceneA3D( + const char *pFile, + IOSystem *pIOSystem, + const aiScene *pScene, + const ExportProperties *pProperties + +) { + // initialize the exporter + M3DExporter exporter(pScene, pProperties); + + // perform ascii export + exporter.doExport(pFile, pIOSystem, true); +} + +// ------------------------------------------------------------------------------------------------ +M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) : + mScene(pScene), + mProperties(pProperties), + outfile() {} + +// ------------------------------------------------------------------------------------------------ +void M3DExporter::doExport( + const char *pFile, + IOSystem *pIOSystem, + bool toAscii) { + // TODO: convert mProperties into M3D_EXP_* flags + (void)mProperties; + + // open the indicated file for writing (in binary / ASCII mode) + outfile.reset(pIOSystem->Open(pFile, toAscii ? "wt" : "wb")); + if (!outfile) { + throw DeadlyExportError("could not open output .m3d file: " + std::string(pFile)); + } + + M3DWrapper m3d; + if (!m3d) { + throw DeadlyExportError("memory allocation error"); + } + m3d->name = _m3d_safestr((char *)&mScene->mRootNode->mName.data, 2); + + // Create a model from assimp structures + aiMatrix4x4 m; + NodeWalk(m3d, mScene->mRootNode, m); + + // serialize the structures + unsigned int size; + unsigned char *output = m3d.Save(M3D_EXP_FLOAT, M3D_EXP_EXTRA | (toAscii ? M3D_EXP_ASCII : 0), size); + + if (!output || size < 8) { + throw DeadlyExportError("unable to serialize into Model 3D"); + } + + // Write out serialized model + outfile->Write(output, size, 1); + + // explicitly release file pointer, + // so we don't have to rely on class destruction. + outfile.reset(); +} + +// ------------------------------------------------------------------------------------------------ +// recursive node walker +void M3DExporter::NodeWalk(const M3DWrapper &m3d, const aiNode *pNode, aiMatrix4x4 m) { + aiMatrix4x4 nm = m * pNode->mTransformation; + + for (unsigned int i = 0; i < pNode->mNumMeshes; i++) { + const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]]; + unsigned int mi = (M3D_INDEX)-1U; + if (mScene->mMaterials) { + // get the material for this mesh + mi = addMaterial(m3d, mScene->mMaterials[mesh->mMaterialIndex]); + } + // iterate through the mesh faces + for (unsigned int j = 0; j < mesh->mNumFaces; j++) { + unsigned int n; + const aiFace *face = &(mesh->mFaces[j]); + // only triangle meshes supported for now + if (face->mNumIndices != 3) { + throw DeadlyExportError("use aiProcess_Triangulate before export"); + } + // add triangle to the output + n = m3d->numface++; + m3d->face = (m3df_t *)M3D_REALLOC(m3d->face, + m3d->numface * sizeof(m3df_t)); + if (!m3d->face) { + throw DeadlyExportError("memory allocation error"); + } + /* set all index to -1 by default */ + m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] = + m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] = + m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = -1U; + m3d->face[n].materialid = mi; + for (unsigned int k = 0; k < face->mNumIndices; k++) { + // get the vertex's index + unsigned int l = face->mIndices[k]; + unsigned int idx; + m3dv_t vertex; + m3dti_t ti; + // multiply the position vector by the transformation matrix + aiVector3D v = mesh->mVertices[l]; + v *= nm; + vertex.x = v.x; + vertex.y = v.y; + vertex.z = v.z; + vertex.w = 1.0; + vertex.color = 0; + vertex.skinid = -1U; + // add color if defined + if (mesh->HasVertexColors(0)) + vertex.color = mkColor(&mesh->mColors[0][l]); + // save the vertex to the output + m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, + &vertex, &idx); + m3d->face[n].vertex[k] = (M3D_INDEX)idx; + // do we have texture coordinates? + if (mesh->HasTextureCoords(0)) { + ti.u = mesh->mTextureCoords[0][l].x; + ti.v = mesh->mTextureCoords[0][l].y; + m3d->tmap = AddTmap(m3d->tmap, &m3d->numtmap, &ti, &idx); + m3d->face[n].texcoord[k] = (M3D_INDEX)idx; + } + // do we have normal vectors? + if (mesh->HasNormals()) { + vertex.x = mesh->mNormals[l].x; + vertex.y = mesh->mNormals[l].y; + vertex.z = mesh->mNormals[l].z; + vertex.color = 0; + m3d->vertex = AddVrtx(m3d->vertex, &m3d->numvertex, &vertex, &idx); + m3d->face[n].normal[k] = (M3D_INDEX)idx; + } + } + } + } + // repeat for the children nodes + for (unsigned int i = 0; i < pNode->mNumChildren; i++) { + NodeWalk(m3d, pNode->mChildren[i], nm); + } +} +} // namespace Assimp + #endif // ASSIMP_BUILD_NO_M3D_EXPORTER #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/M3D/M3DExporter.h b/code/M3D/M3DExporter.h index 58d8d597e..fce89b9de 100644 --- a/code/M3D/M3DExporter.h +++ b/code/M3D/M3DExporter.h @@ -48,8 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_M3D_EXPORTER -#include "m3d.h" - #include //#include #include // StreamWriterLE @@ -68,6 +66,8 @@ namespace Assimp class IOStream; class ExportProperties; + class M3DWrapper; + // --------------------------------------------------------------------- /** Helper class to export a given scene to an M3D file. */ // --------------------------------------------------------------------- @@ -83,15 +83,9 @@ namespace Assimp const aiScene* mScene; // the scene to export const ExportProperties* mProperties; // currently unused std::shared_ptr outfile; // file to write to - m3d_t *m3d; // model for the C library to convert to // helper to do the recursive walking - void NodeWalk(const aiNode* pNode, aiMatrix4x4 m); - m3dv_t *AddVrtx(m3dv_t *vrtx, uint32_t *numvrtx, m3dv_t *v, uint32_t *idx); - m3dti_t *AddTmap(m3dti_t *tmap, uint32_t *numtmap, m3dti_t *ti, uint32_t *idx); - uint32_t mkColor(aiColor4D* c); - M3D_INDEX addMaterial(const aiMaterial *mat); - void addProp(m3dm_t *m, uint8_t type, uint32_t value); + void NodeWalk(const M3DWrapper &m3d, const aiNode* pNode, aiMatrix4x4 m); }; } diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 9371e2228..5218dd9ed 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -44,20 +44,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define M3D_IMPLEMENTATION #define M3D_ASCII -#define M3D_NONORMALS /* leave the post-processing to Assimp */ +#define M3D_NONORMALS /* leave the post-processing to Assimp */ #define M3D_NOWEIGHTS #define M3D_NOANIMATION -#include -#include #include -#include -#include +#include #include -#include #include +#include +#include +#include +#include + #include "M3DImporter.h" #include "M3DMaterials.h" +#include "M3DWrapper.h" // RESOURCES: // https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md @@ -85,682 +87,656 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static const aiImporterDesc desc = { - "Model 3D Importer", - "", - "", - "", - aiImporterFlags_SupportBinaryFlavour, - 0, - 0, - 0, - 0, - "m3d a3d" + "Model 3D Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, + "m3d a3d" }; -// workaround: the SDK expects a C callback, but we want to use Assimp::IOSystem to implement that -extern "C" { - void* m3dimporter_pIOHandler; - - unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { - ai_assert( nullptr != fn ); - ai_assert( nullptr != size ); - std::string file(fn); - std::unique_ptr pStream( - (reinterpret_cast(m3dimporter_pIOHandler))->Open( file, "rb")); - size_t fileSize = 0; - unsigned char *data = NULL; - // sometimes pStream is nullptr for some reason (should be an empty object returning nothing I guess) - if(pStream) { - fileSize = pStream->FileSize(); - // should be allocated with malloc(), because the library will call free() to deallocate - data = (unsigned char*)malloc(fileSize); - if( !data || !pStream.get() || !fileSize || fileSize != pStream->Read(data,1,fileSize)) { - pStream.reset(); - *size = 0; - // don't throw a deadly exception, it's not fatal if we can't read an external asset - return nullptr; - } - pStream.reset(); - } - *size = (int)fileSize; - return data; - } -} - namespace Assimp { using namespace std; // ------------------------------------------------------------------------------------------------ // Default constructor -M3DImporter::M3DImporter() -: mScene(nullptr) -, m3d(nullptr) { } - -// ------------------------------------------------------------------------------------------------ -// Destructor. -M3DImporter::~M3DImporter() {} +M3DImporter::M3DImporter() : + mScene(nullptr) {} // ------------------------------------------------------------------------------------------------ // Returns true, if file is a binary or ASCII Model 3D file. -bool M3DImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler , bool checkSig) const { - const std::string extension = GetExtension(pFile); +bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { + const std::string extension = GetExtension(pFile); - if (extension == "m3d" || extension == "a3d") - return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) { - return true; - } - /* + if (extension == "m3d" || extension == "a3d") + return true; + else if (!extension.length() || checkSig) { + if (!pIOHandler) { + return true; + } + /* * don't use CheckMagicToken because that checks with swapped bytes too, leading to false * positives. This magic is not uint32_t, but char[4], so memcmp is the best way const char* tokens[] = {"3DMO", "3dmo"}; return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); */ - std::unique_ptr pStream (pIOHandler->Open(pFile, "rb")); - unsigned char data[4]; - if(4 != pStream->Read(data,1,4)) { - return false; - } - return !memcmp(data, "3DMO", 4) /* bin */ || !memcmp(data, "3dmo", 4) /* ASCII */; - } - return false; + std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); + unsigned char data[4]; + if (4 != pStream->Read(data, 1, 4)) { + return false; + } + return !memcmp(data, "3DMO", 4) /* bin */ || !memcmp(data, "3dmo", 4) /* ASCII */; + } + return false; } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* M3DImporter::GetInfo() const { - return &desc; +const aiImporterDesc *M3DImporter::GetInfo() const { + return &desc; } // ------------------------------------------------------------------------------------------------ // Model 3D import implementation -void M3DImporter::InternReadFile( const std::string &file, aiScene* pScene, IOSystem* pIOHandler) { - // Read file into memory - std::unique_ptr pStream( pIOHandler->Open( file, "rb")); - if( !pStream.get() ) { - throw DeadlyImportError( "Failed to open file " + file + "." ); - } +void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) { + // Read file into memory + std::unique_ptr pStream(pIOHandler->Open(file, "rb")); + if (!pStream.get()) { + throw DeadlyImportError("Failed to open file " + file + "."); + } - // Get the file-size and validate it, throwing an exception when fails - size_t fileSize = pStream->FileSize(); - if( fileSize < 8 ) { - throw DeadlyImportError( "M3D-file " + file + " is too small." ); - } - std::unique_ptr _buffer (new unsigned char[fileSize]); - unsigned char *data( _buffer.get() ); - if(fileSize != pStream->Read(data,1,fileSize)) { - throw DeadlyImportError( "Failed to read the file " + file + "." ); - } + // Get the file-size and validate it, throwing an exception when fails + size_t fileSize = pStream->FileSize(); + if (fileSize < 8) { + throw DeadlyImportError("M3D-file " + file + " is too small."); + } + std::vector buffer(fileSize); + if (fileSize != pStream->Read(buffer.data(), 1, fileSize)) { + throw DeadlyImportError("Failed to read the file " + file + "."); + } - // Get the path for external assets - std::string folderName( "./" ); - std::string::size_type pos = file.find_last_of( "\\/" ); - if ( pos != std::string::npos ) { - folderName = file.substr( 0, pos ); - if ( !folderName.empty() ) { - pIOHandler->PushDirectory( folderName ); - } - } - // pass this IOHandler to the C callback - m3dimporter_pIOHandler = pIOHandler; + // Get the path for external assets + std::string folderName("./"); + std::string::size_type pos = file.find_last_of("\\/"); + if (pos != std::string::npos) { + folderName = file.substr(0, pos); + if (!folderName.empty()) { + pIOHandler->PushDirectory(folderName); + } + } //DefaultLogger::create("/dev/stderr", Logger::VERBOSE); - ASSIMP_LOG_DEBUG_F("M3D: loading ", file); + ASSIMP_LOG_DEBUG_F("M3D: loading ", file); - // let the C SDK do the hard work for us - m3d = m3d_load(&data[0], m3dimporter_readfile, free, nullptr); - m3dimporter_pIOHandler = nullptr; - if( !m3d ) { - throw DeadlyImportError( "Unable to parse " + file + " as M3D." ); - } + // let the C SDK do the hard work for us + M3DWrapper m3d(pIOHandler, buffer); - // create the root node - pScene->mRootNode = new aiNode; - pScene->mRootNode->mName = aiString(std::string(std::string(m3d->name))); - pScene->mRootNode->mTransformation = aiMatrix4x4(); - pScene->mRootNode->mNumChildren = 0; - mScene = pScene; + + if (!m3d) { + throw DeadlyImportError("Unable to parse " + file + " as M3D."); + } - ASSIMP_LOG_DEBUG("M3D: root node " + std::string(m3d->name)); + // create the root node + pScene->mRootNode = new aiNode; + pScene->mRootNode->mName = aiString(m3d.Name()); + pScene->mRootNode->mTransformation = aiMatrix4x4(); + pScene->mRootNode->mNumChildren = 0; + mScene = pScene; - // now we just have to fill up the Assimp structures in pScene - importMaterials(); - importTextures(); - importBones(-1U, pScene->mRootNode); - importMeshes(); - importAnimations(); + ASSIMP_LOG_DEBUG("M3D: root node " + m3d.Name()); - // we don't need the SDK's version any more - m3d_free(m3d); + // now we just have to fill up the Assimp structures in pScene + importMaterials(m3d); + importTextures(m3d); + importBones(m3d, -1U, pScene->mRootNode); + importMeshes(m3d); + importAnimations(m3d); - // Pop directory stack - if ( pIOHandler->StackSize() > 0 ) { - pIOHandler->PopDirectory(); - } + // Pop directory stack + if (pIOHandler->StackSize() > 0) { + pIOHandler->PopDirectory(); + } } // ------------------------------------------------------------------------------------------------ // convert materials. properties are converted using a static table in M3DMaterials.h -void M3DImporter::importMaterials() -{ - unsigned int i, j, k, l, n; - m3dm_t *m; - aiString name = aiString(AI_DEFAULT_MATERIAL_NAME); - aiColor4D c; - ai_real f; +void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { + unsigned int i, j, k, l, n; + m3dm_t *m; + aiString name = aiString(AI_DEFAULT_MATERIAL_NAME); + aiColor4D c; + ai_real f; - ai_assert(mScene != nullptr); - ai_assert(m3d != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d_wrap); - mScene->mNumMaterials = m3d->nummaterial + 1; - mScene->mMaterials = new aiMaterial*[ m3d->nummaterial + 1 ]; + mScene->mNumMaterials = m3d_wrap->nummaterial + 1; + mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; - ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); + ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); - // add a default material as first - aiMaterial* mat = new aiMaterial; - mat->AddProperty( &name, AI_MATKEY_NAME ); - c.a = 1.0; c.b = c.g = c.r = 0.6; - mat->AddProperty( &c, 1, AI_MATKEY_COLOR_DIFFUSE); - mScene->mMaterials[0] = mat; + // add a default material as first + aiMaterial *mat = new aiMaterial; + mat->AddProperty(&name, AI_MATKEY_NAME); + c.a = 1.0f; + c.b = c.g = c.r = 0.6f; + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); + mScene->mMaterials[0] = mat; - for(i = 0; i < m3d->nummaterial; i++) { - m = &m3d->material[i]; - aiMaterial* mat = new aiMaterial; - name.Set(std::string(m->name)); - mat->AddProperty( &name, AI_MATKEY_NAME ); - for(j = 0; j < m->numprop; j++) { - // look up property type - // 0 - 127 scalar values, - // 128 - 255 the same properties but for texture maps - k = 256; - for(l = 0; l < sizeof(m3d_propertytypes)/sizeof(m3d_propertytypes[0]); l++) - if(m->prop[j].type == m3d_propertytypes[l].id || - m->prop[j].type == m3d_propertytypes[l].id + 128) { - k = l; - break; - } - // should never happen, but be safe than sorry - if(k == 256) continue; + for (i = 0; i < m3d_wrap->nummaterial; i++) { + m = &m3d_wrap->material[i]; + aiMaterial *mat = new aiMaterial; + name.Set(std::string(m->name)); + mat->AddProperty(&name, AI_MATKEY_NAME); + for (j = 0; j < m->numprop; j++) { + // look up property type + // 0 - 127 scalar values, + // 128 - 255 the same properties but for texture maps + k = 256; + for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) + if (m->prop[j].type == m3d_propertytypes[l].id || + m->prop[j].type == m3d_propertytypes[l].id + 128) { + k = l; + break; + } + // should never happen, but be safe than sorry + if (k == 256) continue; - // scalar properties - if(m->prop[j].type < 128 && aiProps[k].pKey) { - switch(m3d_propertytypes[k].format) { - case m3dpf_color: - c = mkColor(m->prop[j].value.color); - mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - case m3dpf_float: - f = m->prop[j].value.fnum; - mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - default: - n = m->prop[j].value.num; - if(m->prop[j].type == m3dp_il) { - switch(n) { - case 0: n = aiShadingMode_NoShading; break; - case 2: n = aiShadingMode_Phong; break; - default: n = aiShadingMode_Gouraud; break; - } - } - mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - } - } - // texture map properties - if(m->prop[j].type >= 128 && aiTxProps[k].pKey && - // extra check, should never happen, do we have the refered texture? - m->prop[j].value.textureid < m3d->numtexture && - m3d->texture[m->prop[j].value.textureid].name) { - name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); - mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index); - n = 0; - mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); - } - } - mScene->mMaterials[i + 1] = mat; - } + // scalar properties + if (m->prop[j].type < 128 && aiProps[k].pKey) { + switch (m3d_propertytypes[k].format) { + case m3dpf_color: + c = mkColor(m->prop[j].value.color); + mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + case m3dpf_float: + f = m->prop[j].value.fnum; + mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + default: + n = m->prop[j].value.num; + if (m->prop[j].type == m3dp_il) { + switch (n) { + case 0: n = aiShadingMode_NoShading; break; + case 2: n = aiShadingMode_Phong; break; + default: n = aiShadingMode_Gouraud; break; + } + } + mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + } + } + // texture map properties + if (m->prop[j].type >= 128 && aiTxProps[k].pKey && + // extra check, should never happen, do we have the refered texture? + m->prop[j].value.textureid < m3d_wrap->numtexture && + m3d_wrap->texture[m->prop[j].value.textureid].name) { + name.Set(std::string(std::string(m3d_wrap->texture[m->prop[j].value.textureid].name) + ".png")); + mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index); + n = 0; + mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); + } + } + mScene->mMaterials[i + 1] = mat; + } } // ------------------------------------------------------------------------------------------------ // import textures, this is the simplest of all -void M3DImporter::importTextures() -{ - unsigned int i; - const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" }; - m3dtx_t *t; +void M3DImporter::importTextures(const M3DWrapper &m3d) { + unsigned int i; + const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" }; + m3dtx_t *t; - ai_assert(mScene != nullptr); - ai_assert(m3d != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d); - mScene->mNumTextures = m3d->numtexture; - ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); + mScene->mNumTextures = m3d->numtexture; + ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); - if(!m3d->numtexture) - return; + if (!m3d->numtexture) + return; - mScene->mTextures = new aiTexture*[m3d->numtexture]; - for(i = 0; i < m3d->numtexture; i++) { - unsigned int j, k; - t = &m3d->texture[i]; - if(!t->w || !t->h || !t->f || !t->d) continue; - aiTexture *tx = new aiTexture; - strcpy(tx->achFormatHint, formatHint[t->f - 1]); - tx->mFilename = aiString(std::string(t->name) + ".png"); - tx->mWidth = t->w; - tx->mHeight = t->h; - tx->pcData = new aiTexel[ tx->mWidth*tx->mHeight ]; - for(j = k = 0; j < tx->mWidth*tx->mHeight; j++) { - switch(t->f) { - case 1: tx->pcData[j].g = t->d[k++]; break; - case 2: tx->pcData[j].g = t->d[k++]; tx->pcData[j].a = t->d[k++]; break; - case 3: - tx->pcData[j].r = t->d[k++]; tx->pcData[j].g = t->d[k++]; - tx->pcData[j].b = t->d[k++]; tx->pcData[j].a = 255; - break; - case 4: - tx->pcData[j].r = t->d[k++]; tx->pcData[j].g = t->d[k++]; - tx->pcData[j].b = t->d[k++]; tx->pcData[j].a = t->d[k++]; - break; - } - } - mScene->mTextures[i] = tx; - } + mScene->mTextures = new aiTexture *[m3d->numtexture]; + for (i = 0; i < m3d->numtexture; i++) { + unsigned int j, k; + t = &m3d->texture[i]; + if (!t->w || !t->h || !t->f || !t->d) continue; + aiTexture *tx = new aiTexture; + strcpy(tx->achFormatHint, formatHint[t->f - 1]); + tx->mFilename = aiString(std::string(t->name) + ".png"); + tx->mWidth = t->w; + tx->mHeight = t->h; + tx->pcData = new aiTexel[tx->mWidth * tx->mHeight]; + for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) { + switch (t->f) { + case 1: tx->pcData[j].g = t->d[k++]; break; + case 2: + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].a = t->d[k++]; + break; + case 3: + tx->pcData[j].r = t->d[k++]; + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; + tx->pcData[j].a = 255; + break; + case 4: + tx->pcData[j].r = t->d[k++]; + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; + tx->pcData[j].a = t->d[k++]; + break; + } + } + mScene->mTextures[i] = tx; + } } // ------------------------------------------------------------------------------------------------ // this is tricky. M3D has a global vertex and UV list, and faces are indexing them // individually. In assimp there're per mesh vertex and UV lists, and they must be // indexed simultaneously. -void M3DImporter::importMeshes() -{ - unsigned int i, j, k, l, numpoly = 3, lastMat = -2U; - std::vector *meshes = new std::vector(); - std::vector *faces = nullptr; - std::vector *vertices = nullptr; - std::vector *normals = nullptr; - std::vector *texcoords = nullptr; - std::vector *colors = nullptr; - std::vector *vertexids = nullptr; - aiMesh *pMesh = nullptr; +void M3DImporter::importMeshes(const M3DWrapper &m3d) { + unsigned int i, j, k, l, numpoly = 3, lastMat = -2U; + std::vector *meshes = new std::vector(); + std::vector *faces = nullptr; + std::vector *vertices = nullptr; + std::vector *normals = nullptr; + std::vector *texcoords = nullptr; + std::vector *colors = nullptr; + std::vector *vertexids = nullptr; + aiMesh *pMesh = nullptr; - ai_assert(mScene != nullptr); - ai_assert(m3d != nullptr); - ai_assert(mScene->mRootNode != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d); + ai_assert(mScene->mRootNode != nullptr); - ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); - for(i = 0; i < m3d->numface; i++) { - // we must switch mesh if material changes - if(lastMat != m3d->face[i].materialid) { - lastMat = m3d->face[i].materialid; - if(pMesh && vertices && vertices->size() && faces && faces->size()) { - populateMesh(pMesh, faces, vertices, normals, texcoords, colors, vertexids); - meshes->push_back(pMesh); - delete faces; - delete vertices; - delete normals; - delete texcoords; - delete colors; - delete vertexids; // this is not stored in pMesh, just to collect bone vertices - } - pMesh = new aiMesh; - pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - pMesh->mMaterialIndex = lastMat + 1; - faces = new std::vector(); - vertices = new std::vector(); - normals = new std::vector(); - texcoords = new std::vector(); - colors = new std::vector(); - vertexids = new std::vector(); - } - // add a face to temporary vector - aiFace *pFace = new aiFace; - pFace->mNumIndices = numpoly; - pFace->mIndices = new unsigned int[numpoly]; - for(j = 0; j < numpoly; j++) { - aiVector3D pos, uv, norm; - k = vertices->size(); - pFace->mIndices[j] = k; - l = m3d->face[i].vertex[j]; - pos.x = m3d->vertex[l].x; - pos.y = m3d->vertex[l].y; - pos.z = m3d->vertex[l].z; - vertices->push_back(pos); - colors->push_back(mkColor(m3d->vertex[l].color)); - // add a bone to temporary vector - if(m3d->vertex[l].skinid != -1U &&m3d->vertex[l].skinid != -2U && m3d->skin && m3d->bone) { - // this is complicated, because M3D stores a list of bone id / weight pairs per - // vertex but assimp uses lists of local vertex id/weight pairs per local bone list - vertexids->push_back(l); - } - l = m3d->face[i].texcoord[j]; - if(l != -1U) { - uv.x = m3d->tmap[l].u; - uv.y = m3d->tmap[l].v; - uv.z = 0.0; - texcoords->push_back(uv); - } - l = m3d->face[i].normal[j]; - if(l != -1U) { - norm.x = m3d->vertex[l].x; - norm.y = m3d->vertex[l].y; - norm.z = m3d->vertex[l].z; - normals->push_back(norm); - } - } - faces->push_back(*pFace); - delete pFace; - } - // if there's data left in the temporary vectors, flush them - if(pMesh && vertices->size() && faces->size()) { - populateMesh(pMesh, faces, vertices, normals, texcoords, colors, vertexids); - meshes->push_back(pMesh); - } + for (i = 0; i < m3d->numface; i++) { + // we must switch mesh if material changes + if (lastMat != m3d->face[i].materialid) { + lastMat = m3d->face[i].materialid; + if (pMesh && vertices && vertices->size() && faces && faces->size()) { + populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids); + meshes->push_back(pMesh); + delete faces; + delete vertices; + delete normals; + delete texcoords; + delete colors; + delete vertexids; // this is not stored in pMesh, just to collect bone vertices + } + pMesh = new aiMesh; + pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + pMesh->mMaterialIndex = lastMat + 1; + faces = new std::vector(); + vertices = new std::vector(); + normals = new std::vector(); + texcoords = new std::vector(); + colors = new std::vector(); + vertexids = new std::vector(); + } + // add a face to temporary vector + aiFace *pFace = new aiFace; + pFace->mNumIndices = numpoly; + pFace->mIndices = new unsigned int[numpoly]; + for (j = 0; j < numpoly; j++) { + aiVector3D pos, uv, norm; + k = static_cast(vertices->size()); + pFace->mIndices[j] = k; + l = m3d->face[i].vertex[j]; + pos.x = m3d->vertex[l].x; + pos.y = m3d->vertex[l].y; + pos.z = m3d->vertex[l].z; + vertices->push_back(pos); + colors->push_back(mkColor(m3d->vertex[l].color)); + // add a bone to temporary vector + if (m3d->vertex[l].skinid != -1U && m3d->vertex[l].skinid != -2U && m3d->skin && m3d->bone) { + // this is complicated, because M3D stores a list of bone id / weight pairs per + // vertex but assimp uses lists of local vertex id/weight pairs per local bone list + vertexids->push_back(l); + } + l = m3d->face[i].texcoord[j]; + if (l != -1U) { + uv.x = m3d->tmap[l].u; + uv.y = m3d->tmap[l].v; + uv.z = 0.0; + texcoords->push_back(uv); + } + l = m3d->face[i].normal[j]; + if (l != -1U) { + norm.x = m3d->vertex[l].x; + norm.y = m3d->vertex[l].y; + norm.z = m3d->vertex[l].z; + normals->push_back(norm); + } + } + faces->push_back(*pFace); + delete pFace; + } + // if there's data left in the temporary vectors, flush them + if (pMesh && vertices->size() && faces->size()) { + populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids); + meshes->push_back(pMesh); + } - // create global mesh list in scene - mScene->mNumMeshes = meshes->size(); - mScene->mMeshes = new aiMesh*[mScene->mNumMeshes]; - std::copy(meshes->begin(), meshes->end(), mScene->mMeshes); + // create global mesh list in scene + mScene->mNumMeshes = static_cast(meshes->size()); + mScene->mMeshes = new aiMesh *[mScene->mNumMeshes]; + std::copy(meshes->begin(), meshes->end(), mScene->mMeshes); - // create mesh indeces in root node - mScene->mRootNode->mNumMeshes = meshes->size(); - mScene->mRootNode->mMeshes = new unsigned int[meshes->size()]; - for(i = 0; i < meshes->size(); i++) { - mScene->mRootNode->mMeshes[i] = i; - } + // create mesh indeces in root node + mScene->mRootNode->mNumMeshes = static_cast(meshes->size()); + mScene->mRootNode->mMeshes = new unsigned int[meshes->size()]; + for (i = 0; i < meshes->size(); i++) { + mScene->mRootNode->mMeshes[i] = i; + } - delete meshes; - if(faces) delete faces; - if(vertices) delete vertices; - if(normals) delete normals; - if(texcoords) delete texcoords; - if(colors) delete colors; - if(vertexids) delete vertexids; + delete meshes; + if (faces) delete faces; + if (vertices) delete vertices; + if (normals) delete normals; + if (texcoords) delete texcoords; + if (colors) delete colors; + if (vertexids) delete vertexids; } // ------------------------------------------------------------------------------------------------ // a reentrant node parser. Otherwise this is simple -void M3DImporter::importBones(unsigned int parentid, aiNode *pParent) -{ - unsigned int i, n; +void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNode *pParent) { + unsigned int i, n; - ai_assert(pParent != nullptr); - ai_assert(mScene != nullptr); - ai_assert(m3d != nullptr); + ai_assert(pParent != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d); - ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); + ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); - for(n = 0, i = parentid + 1; i < m3d->numbone; i++) - if(m3d->bone[i].parent == parentid) n++; - pParent->mChildren = new aiNode*[n]; + for (n = 0, i = parentid + 1; i < m3d->numbone; i++) + if (m3d->bone[i].parent == parentid) n++; + pParent->mChildren = new aiNode *[n]; - for(i = parentid + 1; i < m3d->numbone; i++) { - if(m3d->bone[i].parent == parentid) { - aiNode *pChild = new aiNode; - pChild->mParent = pParent; - pChild->mName = aiString(std::string(m3d->bone[i].name)); - convertPose(&pChild->mTransformation, m3d->bone[i].pos, m3d->bone[i].ori); - pChild->mNumChildren = 0; - pParent->mChildren[pParent->mNumChildren] = pChild; - pParent->mNumChildren++; - importBones(i, pChild); - } - } + for (i = parentid + 1; i < m3d->numbone; i++) { + if (m3d->bone[i].parent == parentid) { + aiNode *pChild = new aiNode; + pChild->mParent = pParent; + pChild->mName = aiString(std::string(m3d->bone[i].name)); + convertPose(m3d, &pChild->mTransformation, m3d->bone[i].pos, m3d->bone[i].ori); + pChild->mNumChildren = 0; + pParent->mChildren[pParent->mNumChildren] = pChild; + pParent->mNumChildren++; + importBones(m3d, i, pChild); + } + } } // ------------------------------------------------------------------------------------------------ // this is another headache. M3D stores list of changed bone id/position/orientation triplets and // a timestamp per frame, but assimp needs timestamp and lists of position, orientation lists per // bone, so we have to convert between the two conceptually different representation forms -void M3DImporter::importAnimations() -{ - unsigned int i, j, k, l, pos, ori; - double t; - m3da_t *a; +void M3DImporter::importAnimations(const M3DWrapper &m3d) { + unsigned int i, j, k, l, pos, ori; + double t; + m3da_t *a; - ai_assert(mScene != nullptr); - ai_assert(m3d != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d); - mScene->mNumAnimations = m3d->numaction; + mScene->mNumAnimations = m3d->numaction; - ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); + ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); - if(!m3d->numaction || !m3d->numbone) - return; + if (!m3d->numaction || !m3d->numbone) + return; - mScene->mAnimations = new aiAnimation*[m3d->numaction]; - for(i = 0; i < m3d->numaction; i++) { - a = &m3d->action[i]; - aiAnimation *pAnim = new aiAnimation; - pAnim->mName = aiString(std::string(a->name)); - pAnim->mDuration = ((double)a->durationmsec) / 10; - pAnim->mTicksPerSecond = 100; - // now we know how many bones are referenced in this animation - pAnim->mNumChannels = m3d->numbone; - pAnim->mChannels = new aiNodeAnim*[pAnim->mNumChannels]; - for(l = 0; l < m3d->numbone; l++) { - unsigned int n; - pAnim->mChannels[l] = new aiNodeAnim; - pAnim->mChannels[l]->mNodeName = aiString(std::string(m3d->bone[l].name)); - // now n is the size of positions / orientations arrays - pAnim->mChannels[l]->mNumPositionKeys = pAnim->mChannels[l]->mNumRotationKeys = a->numframe; - pAnim->mChannels[l]->mPositionKeys = new aiVectorKey[a->numframe]; - pAnim->mChannels[l]->mRotationKeys = new aiQuatKey[a->numframe]; - pos = m3d->bone[l].pos; - ori = m3d->bone[l].ori; - for(j = n = 0; j < a->numframe; j++) { - t = ((double)a->frame[j].msec) / 10; - for(k = 0; k < a->frame[j].numtransform; k++) { - if(a->frame[j].transform[k].boneid == l) { - pos = a->frame[j].transform[k].pos; - ori = a->frame[j].transform[k].ori; - } - } - m3dv_t *v = &m3d->vertex[pos]; - m3dv_t *q = &m3d->vertex[ori]; - pAnim->mChannels[l]->mPositionKeys[j].mTime = t; - pAnim->mChannels[l]->mPositionKeys[j].mValue.x = v->x; - pAnim->mChannels[l]->mPositionKeys[j].mValue.y = v->y; - pAnim->mChannels[l]->mPositionKeys[j].mValue.z = v->z; - pAnim->mChannels[l]->mRotationKeys[j].mTime = t; - pAnim->mChannels[l]->mRotationKeys[j].mValue.w = q->w; - pAnim->mChannels[l]->mRotationKeys[j].mValue.x = q->x; - pAnim->mChannels[l]->mRotationKeys[j].mValue.y = q->y; - pAnim->mChannels[l]->mRotationKeys[j].mValue.z = q->z; - }// foreach frame - }// foreach bones - mScene->mAnimations[i] = pAnim; - } + mScene->mAnimations = new aiAnimation *[m3d->numaction]; + for (i = 0; i < m3d->numaction; i++) { + a = &m3d->action[i]; + aiAnimation *pAnim = new aiAnimation; + pAnim->mName = aiString(std::string(a->name)); + pAnim->mDuration = ((double)a->durationmsec) / 10; + pAnim->mTicksPerSecond = 100; + // now we know how many bones are referenced in this animation + pAnim->mNumChannels = m3d->numbone; + pAnim->mChannels = new aiNodeAnim *[pAnim->mNumChannels]; + for (l = 0; l < m3d->numbone; l++) { + unsigned int n; + pAnim->mChannels[l] = new aiNodeAnim; + pAnim->mChannels[l]->mNodeName = aiString(std::string(m3d->bone[l].name)); + // now n is the size of positions / orientations arrays + pAnim->mChannels[l]->mNumPositionKeys = pAnim->mChannels[l]->mNumRotationKeys = a->numframe; + pAnim->mChannels[l]->mPositionKeys = new aiVectorKey[a->numframe]; + pAnim->mChannels[l]->mRotationKeys = new aiQuatKey[a->numframe]; + pos = m3d->bone[l].pos; + ori = m3d->bone[l].ori; + for (j = n = 0; j < a->numframe; j++) { + t = ((double)a->frame[j].msec) / 10; + for (k = 0; k < a->frame[j].numtransform; k++) { + if (a->frame[j].transform[k].boneid == l) { + pos = a->frame[j].transform[k].pos; + ori = a->frame[j].transform[k].ori; + } + } + m3dv_t *v = &m3d->vertex[pos]; + m3dv_t *q = &m3d->vertex[ori]; + pAnim->mChannels[l]->mPositionKeys[j].mTime = t; + pAnim->mChannels[l]->mPositionKeys[j].mValue.x = v->x; + pAnim->mChannels[l]->mPositionKeys[j].mValue.y = v->y; + pAnim->mChannels[l]->mPositionKeys[j].mValue.z = v->z; + pAnim->mChannels[l]->mRotationKeys[j].mTime = t; + pAnim->mChannels[l]->mRotationKeys[j].mValue.w = q->w; + pAnim->mChannels[l]->mRotationKeys[j].mValue.x = q->x; + pAnim->mChannels[l]->mRotationKeys[j].mValue.y = q->y; + pAnim->mChannels[l]->mRotationKeys[j].mValue.z = q->z; + } // foreach frame + } // foreach bones + mScene->mAnimations[i] = pAnim; + } } // ------------------------------------------------------------------------------------------------ // convert uint32_t into aiColor4D aiColor4D M3DImporter::mkColor(uint32_t c) { - aiColor4D color; - color.a = ((float)((c >> 24)&0xff)) / 255; - color.b = ((float)((c >> 16)&0xff)) / 255; - color.g = ((float)((c >> 8)&0xff)) / 255; - color.r = ((float)((c >> 0)&0xff)) / 255; - return color; + aiColor4D color; + color.a = ((float)((c >> 24) & 0xff)) / 255; + color.b = ((float)((c >> 16) & 0xff)) / 255; + color.g = ((float)((c >> 8) & 0xff)) / 255; + color.r = ((float)((c >> 0) & 0xff)) / 255; + return color; } // ------------------------------------------------------------------------------------------------ // convert a position id and orientation id into a 4 x 4 transformation matrix -void M3DImporter::convertPose(aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) -{ - ai_assert(m != nullptr); - ai_assert(m3d != nullptr); - ai_assert(posid != -1U && posid < m3d->numvertex); - ai_assert(orientid != -1U && orientid < m3d->numvertex); - m3dv_t *p = &m3d->vertex[posid]; - m3dv_t *q = &m3d->vertex[orientid]; +void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) { + ai_assert(m != nullptr); + ai_assert(m3d); + ai_assert(posid != -1U && posid < m3d->numvertex); + ai_assert(orientid != -1U && orientid < m3d->numvertex); + m3dv_t *p = &m3d->vertex[posid]; + m3dv_t *q = &m3d->vertex[orientid]; - /* quaternion to matrix. Do NOT use aiQuaternion to aiMatrix3x3, gives bad results */ - if(q->x == 0.0 && q->y == 0.0 && q->z >= 0.7071065 && q->z <= 0.7071075 && q->w == 0.0) { - m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0; - m->a1 = m->b2 = m->c3 = -1.0; - } else { - m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); if(m->a1 > -M3D_EPSILON && m->a1 < M3D_EPSILON) m->a1 = 0.0; - m->a2 = 2 * (q->x * q->y - q->z * q->w); if(m->a2 > -M3D_EPSILON && m->a2 < M3D_EPSILON) m->a2 = 0.0; - m->a3 = 2 * (q->x * q->z + q->y * q->w); if(m->a3 > -M3D_EPSILON && m->a3 < M3D_EPSILON) m->a3 = 0.0; - m->b1 = 2 * (q->x * q->y + q->z * q->w); if(m->b1 > -M3D_EPSILON && m->b1 < M3D_EPSILON) m->b1 = 0.0; - m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); if(m->b2 > -M3D_EPSILON && m->b2 < M3D_EPSILON) m->b2 = 0.0; - m->b3 = 2 * (q->y * q->z - q->x * q->w); if(m->b3 > -M3D_EPSILON && m->b3 < M3D_EPSILON) m->b3 = 0.0; - m->c1 = 2 * (q->x * q->z - q->y * q->w); if(m->c1 > -M3D_EPSILON && m->c1 < M3D_EPSILON) m->c1 = 0.0; - m->c2 = 2 * (q->y * q->z + q->x * q->w); if(m->c2 > -M3D_EPSILON && m->c2 < M3D_EPSILON) m->c2 = 0.0; - m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); if(m->c3 > -M3D_EPSILON && m->c3 < M3D_EPSILON) m->c3 = 0.0; - } + /* quaternion to matrix. Do NOT use aiQuaternion to aiMatrix3x3, gives bad results */ + if (q->x == 0.0 && q->y == 0.0 && q->z >= 0.7071065 && q->z <= 0.7071075 && q->w == 0.0) { + m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0; + m->a1 = m->b2 = m->c3 = -1.0; + } else { + m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); + if (m->a1 > -M3D_EPSILON && m->a1 < M3D_EPSILON) m->a1 = 0.0; + m->a2 = 2 * (q->x * q->y - q->z * q->w); + if (m->a2 > -M3D_EPSILON && m->a2 < M3D_EPSILON) m->a2 = 0.0; + m->a3 = 2 * (q->x * q->z + q->y * q->w); + if (m->a3 > -M3D_EPSILON && m->a3 < M3D_EPSILON) m->a3 = 0.0; + m->b1 = 2 * (q->x * q->y + q->z * q->w); + if (m->b1 > -M3D_EPSILON && m->b1 < M3D_EPSILON) m->b1 = 0.0; + m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); + if (m->b2 > -M3D_EPSILON && m->b2 < M3D_EPSILON) m->b2 = 0.0; + m->b3 = 2 * (q->y * q->z - q->x * q->w); + if (m->b3 > -M3D_EPSILON && m->b3 < M3D_EPSILON) m->b3 = 0.0; + m->c1 = 2 * (q->x * q->z - q->y * q->w); + if (m->c1 > -M3D_EPSILON && m->c1 < M3D_EPSILON) m->c1 = 0.0; + m->c2 = 2 * (q->y * q->z + q->x * q->w); + if (m->c2 > -M3D_EPSILON && m->c2 < M3D_EPSILON) m->c2 = 0.0; + m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); + if (m->c3 > -M3D_EPSILON && m->c3 < M3D_EPSILON) m->c3 = 0.0; + } - /* set translation */ - m->a4 = p->x; m->b4 = p->y; m->c4 = p->z; + /* set translation */ + m->a4 = p->x; + m->b4 = p->y; + m->c4 = p->z; - m->d1 = 0; m->d2 = 0; m->d3 = 0; m->d4 = 1; + m->d1 = 0; + m->d2 = 0; + m->d3 = 0; + m->d4 = 1; } // ------------------------------------------------------------------------------------------------ // find a node by name -aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) -{ - unsigned int i; +aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { + unsigned int i; - ai_assert(pNode != nullptr); - ai_assert(mScene != nullptr); + ai_assert(pNode != nullptr); + ai_assert(mScene != nullptr); - if(pNode->mName == name) - return pNode; - for(i = 0; i < pNode->mNumChildren; i++) { - aiNode *pChild = findNode(pNode->mChildren[i], name); - if(pChild) return pChild; - } - return nullptr; + if (pNode->mName == name) + return pNode; + for (i = 0; i < pNode->mNumChildren; i++) { + aiNode *pChild = findNode(pNode->mChildren[i], name); + if (pChild) return pChild; + } + return nullptr; } // ------------------------------------------------------------------------------------------------ // fills up offsetmatrix in mBones -void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) -{ - ai_assert(pNode != nullptr); - ai_assert(mScene != nullptr); +void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) { + ai_assert(pNode != nullptr); + ai_assert(mScene != nullptr); - if(pNode->mParent) { - calculateOffsetMatrix(pNode->mParent, m); - *m *= pNode->mTransformation; - } else { - *m = pNode->mTransformation; - } + if (pNode->mParent) { + calculateOffsetMatrix(pNode->mParent, m); + *m *= pNode->mTransformation; + } else { + *m = pNode->mTransformation; + } } // ------------------------------------------------------------------------------------------------ // because M3D has a global mesh, global vertex ids and stores materialid on the face, we need // temporary lists to collect data for an aiMesh, which requires local arrays and local indeces // this function fills up an aiMesh with those temporary lists -void M3DImporter::populateMesh(aiMesh *pMesh, std::vector *faces, std::vector *vertices, - std::vector *normals, std::vector *texcoords, std::vector *colors, - std::vector *vertexids) { +void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector *faces, std::vector *vertices, + std::vector *normals, std::vector *texcoords, std::vector *colors, + std::vector *vertexids) { - ai_assert(pMesh != nullptr); - ai_assert(faces != nullptr); - ai_assert(vertices != nullptr); - ai_assert(normals != nullptr); - ai_assert(texcoords != nullptr); - ai_assert(colors != nullptr); - ai_assert(vertexids != nullptr); - ai_assert(m3d != nullptr); + ai_assert(pMesh != nullptr); + ai_assert(faces != nullptr); + ai_assert(vertices != nullptr); + ai_assert(normals != nullptr); + ai_assert(texcoords != nullptr); + ai_assert(colors != nullptr); + ai_assert(vertexids != nullptr); + ai_assert(m3d); - ASSIMP_LOG_DEBUG_F("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), - " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); + ASSIMP_LOG_DEBUG_F("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), + " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); - if(vertices->size() && faces->size()) { - pMesh->mNumFaces = faces->size(); - pMesh->mFaces = new aiFace[pMesh->mNumFaces]; - std::copy(faces->begin(), faces->end(), pMesh->mFaces); - pMesh->mNumVertices = vertices->size(); - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - std::copy(vertices->begin(), vertices->end(), pMesh->mVertices); - if(normals->size() == vertices->size()) { - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - std::copy(normals->begin(), normals->end(), pMesh->mNormals); - } - if(texcoords->size() == vertices->size()) { - pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices]; - std::copy(texcoords->begin(), texcoords->end(), pMesh->mTextureCoords[0]); - pMesh->mNumUVComponents[0] = 2; - } - if(colors->size() == vertices->size()) { - pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices]; - std::copy(colors->begin(), colors->end(), pMesh->mColors[0]); - } - // this is complicated, because M3D stores a list of bone id / weight pairs per - // vertex but assimp uses lists of local vertex id/weight pairs per local bone list - pMesh->mNumBones = m3d->numbone; - /* we need aiBone with mOffsetMatrix for bones without weights as well */ - if(pMesh->mNumBones) { - pMesh->mBones = new aiBone*[pMesh->mNumBones]; - for(unsigned int i = 0; i < m3d->numbone; i++) { - aiNode *pNode; - pMesh->mBones[i] = new aiBone; - pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name)); - pMesh->mBones[i]->mNumWeights = 0; - pNode = findNode(mScene->mRootNode, pMesh->mBones[i]->mName); - if(pNode) { - calculateOffsetMatrix(pNode, &pMesh->mBones[i]->mOffsetMatrix); - pMesh->mBones[i]->mOffsetMatrix.Inverse(); - } else - pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); - } - if(vertexids->size()) { - unsigned int i, j; - // first count how many vertices we have per bone - for(i = 0; i < vertexids->size(); i++) { - unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if(s != -1U && s!= -2U) { - for(unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { - aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for(j = 0; j < pMesh->mNumBones; j++) { - if(pMesh->mBones[j]->mName == name) { - pMesh->mBones[j]->mNumWeights++; - break; - } - } - } - } - } - // allocate mWeights - for(j = 0; j < pMesh->mNumBones; j++) { - aiBone *pBone = pMesh->mBones[j]; - if(pBone->mNumWeights) { - pBone->mWeights = new aiVertexWeight[pBone->mNumWeights]; - pBone->mNumWeights = 0; - } - } - // fill up with data - for(i = 0; i < vertexids->size(); i++) { - unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if(s != -1U && s!= -2U) { - for(unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { - aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for(j = 0; j < pMesh->mNumBones; j++) { - if(pMesh->mBones[j]->mName == name) { - aiBone *pBone = pMesh->mBones[j]; - pBone->mWeights[pBone->mNumWeights].mVertexId = i; - pBone->mWeights[pBone->mNumWeights].mWeight = m3d->skin[s].weight[k]; - pBone->mNumWeights++; - break; - } - } - } // foreach skin - } - } // foreach vertexids - } - } - } + if (vertices->size() && faces->size()) { + pMesh->mNumFaces = static_cast(faces->size()); + pMesh->mFaces = new aiFace[pMesh->mNumFaces]; + std::copy(faces->begin(), faces->end(), pMesh->mFaces); + pMesh->mNumVertices = static_cast(vertices->size()); + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + std::copy(vertices->begin(), vertices->end(), pMesh->mVertices); + if (normals->size() == vertices->size()) { + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + std::copy(normals->begin(), normals->end(), pMesh->mNormals); + } + if (texcoords->size() == vertices->size()) { + pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices]; + std::copy(texcoords->begin(), texcoords->end(), pMesh->mTextureCoords[0]); + pMesh->mNumUVComponents[0] = 2; + } + if (colors->size() == vertices->size()) { + pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices]; + std::copy(colors->begin(), colors->end(), pMesh->mColors[0]); + } + // this is complicated, because M3D stores a list of bone id / weight pairs per + // vertex but assimp uses lists of local vertex id/weight pairs per local bone list + pMesh->mNumBones = m3d->numbone; + /* we need aiBone with mOffsetMatrix for bones without weights as well */ + if (pMesh->mNumBones) { + pMesh->mBones = new aiBone *[pMesh->mNumBones]; + for (unsigned int i = 0; i < m3d->numbone; i++) { + aiNode *pNode; + pMesh->mBones[i] = new aiBone; + pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name)); + pMesh->mBones[i]->mNumWeights = 0; + pNode = findNode(mScene->mRootNode, pMesh->mBones[i]->mName); + if (pNode) { + calculateOffsetMatrix(pNode, &pMesh->mBones[i]->mOffsetMatrix); + pMesh->mBones[i]->mOffsetMatrix.Inverse(); + } else + pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); + } + if (vertexids->size()) { + unsigned int i, j; + // first count how many vertices we have per bone + for (i = 0; i < vertexids->size(); i++) { + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; + if (s != -1U && s != -2U) { + for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); + for (j = 0; j < pMesh->mNumBones; j++) { + if (pMesh->mBones[j]->mName == name) { + pMesh->mBones[j]->mNumWeights++; + break; + } + } + } + } + } + // allocate mWeights + for (j = 0; j < pMesh->mNumBones; j++) { + aiBone *pBone = pMesh->mBones[j]; + if (pBone->mNumWeights) { + pBone->mWeights = new aiVertexWeight[pBone->mNumWeights]; + pBone->mNumWeights = 0; + } + } + // fill up with data + for (i = 0; i < vertexids->size(); i++) { + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; + if (s != -1U && s != -2U) { + for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); + for (j = 0; j < pMesh->mNumBones; j++) { + if (pMesh->mBones[j]->mName == name) { + aiBone *pBone = pMesh->mBones[j]; + pBone->mWeights[pBone->mNumWeights].mVertexId = i; + pBone->mWeights[pBone->mNumWeights].mWeight = m3d->skin[s].weight[k]; + pBone->mNumWeights++; + break; + } + } + } // foreach skin + } + } // foreach vertexids + } + } + } } // ------------------------------------------------------------------------------------------------ -} // Namespace Assimp +} // Namespace Assimp #endif // !! ASSIMP_BUILD_NO_M3D_IMPORTER diff --git a/code/M3D/M3DImporter.h b/code/M3D/M3DImporter.h index 06cc757b6..e8e3a65ed 100644 --- a/code/M3D/M3DImporter.h +++ b/code/M3D/M3DImporter.h @@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER -#include "m3d.h" #include #include #include @@ -60,43 +59,41 @@ struct aiFace; namespace Assimp { +class M3DWrapper; + class M3DImporter : public BaseImporter { public: - /// \brief Default constructor - M3DImporter(); - - /// \brief Destructor - ~M3DImporter(); + /// \brief Default constructor + M3DImporter(); public: - /// \brief Returns whether the class can handle the format of the given file. - /// \remark See BaseImporter::CanRead() for details. - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; + /// \brief Returns whether the class can handle the format of the given file. + /// \remark See BaseImporter::CanRead() for details. + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const; private: - aiScene* mScene; // the scene to import to - m3d_t *m3d; // model for the C library to convert from + aiScene *mScene = nullptr; // the scene to import to - //! \brief Appends the supported extension. - const aiImporterDesc* GetInfo () const; + //! \brief Appends the supported extension. + const aiImporterDesc *GetInfo() const; - //! \brief File import implementation. - void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); + //! \brief File import implementation. + void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); - void importMaterials(); - void importTextures(); - void importMeshes(); - void importBones(unsigned int parentid, aiNode *pParent); - void importAnimations(); + void importMaterials(const M3DWrapper &m3d); + void importTextures(const M3DWrapper &m3d); + void importMeshes(const M3DWrapper &m3d); + void importBones(const M3DWrapper &m3d, unsigned int parentid, aiNode *pParent); + void importAnimations(const M3DWrapper &m3d); - // helper functions - aiColor4D mkColor(uint32_t c); - void convertPose(aiMatrix4x4 *m, unsigned int posid, unsigned int orientid); - aiNode *findNode(aiNode *pNode, aiString name); - void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m); - void populateMesh(aiMesh *pMesh, std::vector *faces, std::vector *verteces, - std::vector *normals, std::vector *texcoords, std::vector *colors, - std::vector *vertexids); + // helper functions + aiColor4D mkColor(uint32_t c); + void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid); + aiNode *findNode(aiNode *pNode, aiString name); + void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m); + void populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector *faces, std::vector *verteces, + std::vector *normals, std::vector *texcoords, std::vector *colors, + std::vector *vertexids); }; } // Namespace Assimp diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp new file mode 100644 index 000000000..a610ff2de --- /dev/null +++ b/code/M3D/M3DWrapper.cpp @@ -0,0 +1,136 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team +Copyright (c) 2019 bzt + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) && !ASSIMP_BUILD_NO_M3D_IMPORTER + +#include "M3DWrapper.h" + +#include +#include +#include + +#if (__cplusplus >= 201103L) || (_MSC_VER >= 1915) || defined(AI_M3D_USE_STDMUTEX) // C++11 and MSVC that mostly supports it +#define AI_M3D_USE_STDMUTEX +#include +#endif + +// workaround: the M3D SDK expects a C callback, but we want to use Assimp::IOSystem to implement that +// This makes it non-rentrant so lock a mutex (requires C++11) + +std::mutex file_mutex; + +extern "C" { +void *m3dimporter_pIOHandler; + +unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { + ai_assert(nullptr != fn); + ai_assert(nullptr != size); + std::string file(fn); + std::unique_ptr pStream( + (reinterpret_cast(m3dimporter_pIOHandler))->Open(file, "rb")); + size_t fileSize = 0; + unsigned char *data = NULL; + // sometimes pStream is nullptr for some reason (should be an empty object returning nothing I guess) + if (pStream) { + fileSize = pStream->FileSize(); + // should be allocated with malloc(), because the library will call free() to deallocate + data = (unsigned char *)malloc(fileSize); + if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) { + pStream.reset(); + *size = 0; + // don't throw a deadly exception, it's not fatal if we can't read an external asset + return nullptr; + } + pStream.reset(); + } + *size = (int)fileSize; + return data; +} +} + +namespace Assimp { +M3DWrapper::M3DWrapper() { + // use malloc() here because m3d_free() will call free() + m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t)); +} + +M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector &buffer) { +#ifdef AI_M3D_USE_STDMUTEX + // M3D is NOT thread-safe, so lock the global mutex + const std::lock_guard lock(file_mutex); +#endif + // pass this IOHandler to the C callback + m3dimporter_pIOHandler = pIOHandler; + m3d_ = m3d_load(const_cast(buffer.data()), m3dimporter_readfile, free, nullptr); + // Clear the C callback + m3dimporter_pIOHandler = nullptr; +} + +M3DWrapper::~M3DWrapper() { + reset(); +} + +void M3DWrapper::reset() { + ClearSave(); + if (m3d_) + m3d_free(m3d_); + m3d_ = nullptr; +} + +unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) { +#if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)) + ClearSave(); + saved_output_ = m3d_save(m3d_, quality, flags, &size); + return saved_output_; +#else + return nullptr; +#endif +} + +void M3DWrapper::ClearSave() { + if (saved_output_) + M3D_FREE(saved_output_); + saved_output_ = nullptr; +} +} // namespace Assimp + +#endif diff --git a/code/M3D/M3DWrapper.h b/code/M3D/M3DWrapper.h new file mode 100644 index 000000000..622ab96c4 --- /dev/null +++ b/code/M3D/M3DWrapper.h @@ -0,0 +1,96 @@ +#pragma once +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team +Copyright (c) 2019 bzt + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file M3DWrapper.h +* @brief Declares a class to wrap the C m3d SDK +*/ +#ifndef AI_M3DWRAPPER_H_INC +#define AI_M3DWRAPPER_H_INC +#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) && !ASSIMP_BUILD_NO_M3D_IMPORTER + +#include +#include + +#include "m3d.h" + +namespace Assimp { +class IOSystem; + +class M3DWrapper { + m3d_t *m3d_ = nullptr; + unsigned char *saved_output_ = nullptr; + +public: + // Construct an empty M3D model + explicit M3DWrapper(); + + // Construct an M3D model from provided buffer + // NOTE: The m3d.h SDK function does not mark the data as const. Have assumed it does not write. + // BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN + explicit M3DWrapper(IOSystem *pIOHandler, const std::vector &buffer); + + ~M3DWrapper(); + + void reset(); + + // Name + inline std::string Name() const { + if (m3d_) return std::string(m3d_->name); + return std::string(); + } + + // Execute a save + unsigned char *Save(int quality, int flags, unsigned int &size); + void ClearSave(); + + inline explicit operator bool() const { return m3d_ != nullptr; } + + // Allow direct access to M3D API + inline m3d_t *operator->() const { return m3d_; } + inline m3d_t *M3D() const { return m3d_; } +}; +} // namespace Assimp + +#endif + +#endif // AI_M3DWRAPPER_H_INC From ee537b70ad5f6b67f52a8181f4e5bb42bc13aa41 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 3 Dec 2019 13:18:59 +0000 Subject: [PATCH 111/170] Correct M3DWrapper ifdef guards M3DWrapper should also compile if M3D Importer is enabled --- code/M3D/M3DWrapper.cpp | 2 +- code/M3D/M3DWrapper.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp index a610ff2de..291c28d20 100644 --- a/code/M3D/M3DWrapper.cpp +++ b/code/M3D/M3DWrapper.cpp @@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ -#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) && !ASSIMP_BUILD_NO_M3D_IMPORTER +#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER #include "M3DWrapper.h" diff --git a/code/M3D/M3DWrapper.h b/code/M3D/M3DWrapper.h index 622ab96c4..ffd9e233e 100644 --- a/code/M3D/M3DWrapper.h +++ b/code/M3D/M3DWrapper.h @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef AI_M3DWRAPPER_H_INC #define AI_M3DWRAPPER_H_INC -#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) && !ASSIMP_BUILD_NO_M3D_IMPORTER +#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER) || !ASSIMP_BUILD_NO_M3D_IMPORTER #include #include From e5b065da3ed8594427f1eb031a50325963953252 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 3 Dec 2019 13:35:53 +0000 Subject: [PATCH 112/170] Formatter is a stringstream Used wrong API. Sorry about that. --- code/B3D/B3DImporter.cpp | 8 ++++---- code/FBX/FBXConverter.cpp | 12 ++++++------ include/assimp/LineSplitter.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/B3D/B3DImporter.cpp b/code/B3D/B3DImporter.cpp index b483ed752..f887da8d8 100644 --- a/code/B3D/B3DImporter.cpp +++ b/code/B3D/B3DImporter.cpp @@ -146,7 +146,7 @@ AI_WONT_RETURN void B3DImporter::Oops(){ // ------------------------------------------------------------------------------------------------ AI_WONT_RETURN void B3DImporter::Fail( string str ){ #ifdef DEBUG_B3D - ASSIMP_LOG_ERROR_F("Error in B3D file data: %s", str.c_str()); + ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str); #endif throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str ); } @@ -226,7 +226,7 @@ string B3DImporter::ReadChunk(){ tag+=char( ReadByte() ); } #ifdef DEBUG_B3D - ASSIMP_LOG_DEBUG_F("ReadChunk: %s", tag.c_str()); + ASSIMP_LOG_DEBUG_F("ReadChunk: ", tag); #endif unsigned sz=(unsigned)ReadInt(); _stack.push_back( _pos+sz ); @@ -386,7 +386,7 @@ void B3DImporter::ReadTRIS(int v0) { matid = 0; } else if (matid < 0 || matid >= (int)_materials.size()) { #ifdef DEBUG_B3D - ASSIMP_LOG_ERROR_F("material id=%d", matid); + ASSIMP_LOG_ERROR_F("material id=", matid); #endif Fail("Bad material id"); } @@ -406,7 +406,7 @@ void B3DImporter::ReadTRIS(int v0) { int i2 = ReadInt() + v0; if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) { #ifdef DEBUG_B3D - ASSIMP_LOG_ERROR_F("Bad triangle index: i0=%d, i1=%d, i2=%d", i0, i1, i2); + ASSIMP_LOG_ERROR_F("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2); #endif Fail("Bad triangle index"); continue; diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 1956c3fb4..268988f82 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -1597,11 +1597,11 @@ namespace Assimp { aiBone *bone = nullptr; if (bone_map.count(deformer_name)) { - ASSIMP_LOG_DEBUG_F("retrieved bone from lookup %s. Deformer:%s", bone_name.C_Str(), deformer_name.c_str()); - bone = bone_map[deformer_name]; - } else { - ASSIMP_LOG_DEBUG_F("created new bone %s. Deformer: %s", bone_name.C_Str(), deformer_name.c_str()); - bone = new aiBone(); + ASSIMP_LOG_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); + bone = bone_map[deformer_name]; + } else { + ASSIMP_LOG_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); + bone = new aiBone(); bone->mName = bone_name; // store local transform link for post processing @@ -1647,7 +1647,7 @@ namespace Assimp { bone_map.insert(std::pair(deformer_name, bone)); } - ASSIMP_LOG_DEBUG_F("bone research: Indicies size: %zu", out_indices.size()); + ASSIMP_LOG_DEBUG_F("bone research: Indicies size: ", out_indices.size()); // lookup must be populated in case something goes wrong // this also allocates bones to mesh instance outside diff --git a/include/assimp/LineSplitter.h b/include/assimp/LineSplitter.h index 271b321cc..2fa61cba7 100644 --- a/include/assimp/LineSplitter.h +++ b/include/assimp/LineSplitter.h @@ -72,7 +72,7 @@ for(LineSplitter splitter(stream);splitter;++splitter) { if (strtol(splitter[2]) > 5) { .. } } - ASSIMP_LOG_DEBUG_F("Current line is: %zu", splitter.get_index()); + ASSIMP_LOG_DEBUG_F("Current line is: ", splitter.get_index()); } @endcode */ From 45a96af9ac76c7b4e3f794346326c0307303b7ee Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 3 Dec 2019 14:15:50 +0000 Subject: [PATCH 113/170] Fix typo in M3DWrapper.cpp Don't use std::mutex if not supported. Allow override to force it to be used if does in fact exist Thank you CI --- code/M3D/M3DWrapper.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp index 291c28d20..0060c894e 100644 --- a/code/M3D/M3DWrapper.cpp +++ b/code/M3D/M3DWrapper.cpp @@ -48,16 +48,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#if (__cplusplus >= 201103L) || (_MSC_VER >= 1915) || defined(AI_M3D_USE_STDMUTEX) // C++11 and MSVC that mostly supports it -#define AI_M3D_USE_STDMUTEX +#ifndef AI_M3D_USE_STDMUTEX +#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards +#define AI_M3D_USE_STDMUTEX 1 +#else +#define AI_M3D_USE_STDMUTEX 0 +#endif +#endif + +#if AI_M3D_USE_STDMUTEX #include +std::mutex file_mutex; #endif // workaround: the M3D SDK expects a C callback, but we want to use Assimp::IOSystem to implement that // This makes it non-rentrant so lock a mutex (requires C++11) -std::mutex file_mutex; - extern "C" { void *m3dimporter_pIOHandler; @@ -94,7 +100,7 @@ M3DWrapper::M3DWrapper() { } M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector &buffer) { -#ifdef AI_M3D_USE_STDMUTEX +#if AI_M3D_USE_STDMUTEX // M3D is NOT thread-safe, so lock the global mutex const std::lock_guard lock(file_mutex); #endif From fadf4a3ee22ab72067f1dd74e2d2e4595a1d872c Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Wed, 4 Dec 2019 14:05:46 +0000 Subject: [PATCH 114/170] Update M3DWrapper.h Add missing include. Odd that MSVC2013-2017, GCC and Clang were ok with this. --- code/M3D/M3DWrapper.h | 1 + 1 file changed, 1 insertion(+) diff --git a/code/M3D/M3DWrapper.h b/code/M3D/M3DWrapper.h index ffd9e233e..f404d3d4b 100644 --- a/code/M3D/M3DWrapper.h +++ b/code/M3D/M3DWrapper.h @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include "m3d.h" From a29e4078532621011123594f3f1eccf96f570f51 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 4 Dec 2019 21:25:17 +0100 Subject: [PATCH 115/170] Update B3DImporter.cpp some minor format changes: add brackets for one-liner if statement. --- code/B3D/B3DImporter.cpp | 65 ++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/code/B3D/B3DImporter.cpp b/code/B3D/B3DImporter.cpp index f887da8d8..c9eb89ebc 100644 --- a/code/B3D/B3DImporter.cpp +++ b/code/B3D/B3DImporter.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -78,7 +76,6 @@ static const aiImporterDesc desc = { "b3d" }; -// (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings #ifdef _MSC_VER # pragma warning (disable: 4018) #endif @@ -86,10 +83,8 @@ static const aiImporterDesc desc = { //#define DEBUG_B3D template -void DeleteAllBarePointers(std::vector& x) -{ - for(auto p : x) - { +void DeleteAllBarePointers(std::vector& x) { + for(auto p : x) { delete p; } } @@ -102,10 +97,14 @@ B3DImporter::~B3DImporter() bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{ size_t pos=pFile.find_last_of( '.' ); - if( pos==string::npos ) return false; + if( pos==string::npos ) { + return false; + } string ext=pFile.substr( pos+1 ); - if( ext.size()!=3 ) return false; + if( ext.size()!=3 ) { + return false; + } return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D'); } @@ -122,13 +121,16 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS std::unique_ptr file( pIOHandler->Open( pFile)); // Check whether we can read from the file - if( file.get() == NULL) + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open B3D file " + pFile + "."); + } // check whether the .b3d file is large enough to contain // at least one chunk. size_t fileSize = file->FileSize(); - if( fileSize<8 ) throw DeadlyImportError( "B3D File is too small."); + if( fileSize<8 ) { + throw DeadlyImportError( "B3D File is too small."); + } _pos=0; _buf.resize( fileSize ); @@ -153,7 +155,10 @@ AI_WONT_RETURN void B3DImporter::Fail( string str ){ // ------------------------------------------------------------------------------------------------ int B3DImporter::ReadByte(){ - if( _pos<_buf.size() ) return _buf[_pos++]; + if( _pos<_buf.size() ) { + return _buf[_pos++]; + } + Fail( "EOF" ); return 0; } @@ -212,7 +217,9 @@ string B3DImporter::ReadString(){ string str; while( _pos<_buf.size() ){ char c=(char)ReadByte(); - if( !c ) return str; + if( !c ) { + return str; + } str+=c; } Fail( "EOF" ); @@ -257,7 +264,6 @@ T *B3DImporter::to_array( const vector &v ){ return p; } - // ------------------------------------------------------------------------------------------------ template T **unique_to_array( vector > &v ){ @@ -271,7 +277,6 @@ T **unique_to_array( vector > &v ){ return p; } - // ------------------------------------------------------------------------------------------------ void B3DImporter::ReadTEXS(){ while( ChunkSize() ){ @@ -364,9 +369,13 @@ void B3DImporter::ReadVRTS(){ v.vertex=ReadVec3(); - if( _vflags & 1 ) v.normal=ReadVec3(); + if( _vflags & 1 ) { + v.normal=ReadVec3(); + } - if( _vflags & 2 ) ReadQuat(); //skip v 4bytes... + if( _vflags & 2 ) { + ReadQuat(); //skip v 4bytes... + } for( int i=0;i<_tcsets;++i ){ float t[4]={0,0,0,0}; @@ -374,7 +383,9 @@ void B3DImporter::ReadVRTS(){ t[j]=ReadFloat(); } t[1]=1-t[1]; - if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] ); + if( !i ) { + v.texcoords=aiVector3D( t[0],t[1],t[2] ); + } } } } @@ -615,11 +626,15 @@ void B3DImporter::ReadBB3D( aiScene *scene ){ } ExitChunk(); - if( !_nodes.size() ) Fail( "No nodes" ); + if( !_nodes.size() ) { + Fail( "No nodes" ); + } - if( !_meshes.size() ) Fail( "No meshes" ); + if( !_meshes.size() ) { + Fail( "No meshes" ); + } - //Fix nodes/meshes/bones + // Fix nodes/meshes/bones for(size_t i=0;i<_nodes.size();++i ){ aiNode *node=_nodes[i]; @@ -630,8 +645,12 @@ void B3DImporter::ReadBB3D( aiScene *scene ){ int n_verts=mesh->mNumVertices=n_tris * 3; aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0; - if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ]; - if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ]; + if( _vflags & 1 ) { + mn=mesh->mNormals=new aiVector3D[ n_verts ]; + } + if( _tcsets ) { + mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ]; + } aiFace *face=mesh->mFaces; From 894b8e3519444ad86d4de3371a13fd0583894c09 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 5 Dec 2019 11:25:12 +0000 Subject: [PATCH 116/170] Initial version --- code/Common/Importer.cpp | 5 +++ code/FBX/FBXConverter.cpp | 5 ++- code/FBX/FBXConverter.h | 2 ++ code/glTF/glTFImporter.cpp | 9 +++++ code/glTF/glTFImporter.h | 2 +- code/glTF2/glTF2Importer.cpp | 10 ++++++ code/glTF2/glTF2Importer.h | 1 + include/assimp/commonMetaData.h | 61 +++++++++++++++++++++++++++++++++ include/assimp/metadata.h | 14 ++++++++ 9 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 include/assimp/commonMetaData.h diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index 880b8e83d..d7ca88545 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -78,6 +78,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include @@ -654,6 +655,10 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // If successful, apply all active post processing steps to the imported data if( pimpl->mScene) { + if (!pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) + { + pimpl->mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT, aiString(ext)); + } #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called. diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index d8a22d9f7..f50688bea 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -60,6 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include @@ -3604,7 +3605,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa return; } - out->mMetaData = aiMetadata::Alloc(15); + out->mMetaData = aiMetadata::Alloc(17); out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis()); out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign()); out->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis()); @@ -3620,6 +3621,8 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa out->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart()); out->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop()); out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); + out->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(std::to_string(doc.FBXVersion()))); + out->mMetaData->Set(16, AI_METADATA_SOURCE_GENERATOR, aiString(doc.Creator())); } void FBXConverter::TransferDataToScene() diff --git a/code/FBX/FBXConverter.h b/code/FBX/FBXConverter.h index 46693bdca..b89816127 100644 --- a/code/FBX/FBXConverter.h +++ b/code/FBX/FBXConverter.h @@ -421,6 +421,8 @@ private: double& minTime, Model::RotOrder order); + // ------------------------------------------------------------------------------------------------ + // Copy information about the source of the document into scene metadata. void ConvertGlobalSettings(); // ------------------------------------------------------------------------------------------------ diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index 9ec13ea69..50ae7541d 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -697,6 +698,14 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) } } +void glTFImporter::ImportCommonMetadata(glTF::Asset& a) +{ + ai_assert(mScene->mMetaData == nullptr); + mScene->mMetaData = aiMetadata::Alloc(2); + mScene->mMetaData->Set(0, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); + mScene->mMetaData->Set(1, AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); +} + void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { // clean all member arrays diff --git a/code/glTF/glTFImporter.h b/code/glTF/glTFImporter.h index ce8a000dc..84d74009b 100644 --- a/code/glTF/glTFImporter.h +++ b/code/glTF/glTFImporter.h @@ -83,7 +83,7 @@ private: void ImportCameras(glTF::Asset& a); void ImportLights(glTF::Asset& a); void ImportNodes(glTF::Asset& a); - + void ImportCommonMetadata(glTF::Asset& a); }; } // Namespace assimp diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index dd80aeba9..70b6ddd70 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -1301,6 +1302,13 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { } } +void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { + ai_assert(mScene->mMetaData == nullptr); + mScene->mMetaData = aiMetadata::Alloc(2); + mScene->mMetaData->Set(0, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); + mScene->mMetaData->Set(1, AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); +} + void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { // clean all member arrays meshOffsets.clear(); @@ -1328,6 +1336,8 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO ImportAnimations(asset); + ImportCommonMetadata(asset); + if (pScene->mNumMeshes == 0) { pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } diff --git a/code/glTF2/glTF2Importer.h b/code/glTF2/glTF2Importer.h index 091b61ee6..e62c38d21 100644 --- a/code/glTF2/glTF2Importer.h +++ b/code/glTF2/glTF2Importer.h @@ -84,6 +84,7 @@ private: void ImportLights(glTF2::Asset& a); void ImportNodes(glTF2::Asset& a); void ImportAnimations(glTF2::Asset& a); + void ImportCommonMetadata(glTF2::Asset& a); }; } // Namespace assimp diff --git a/include/assimp/commonMetaData.h b/include/assimp/commonMetaData.h new file mode 100644 index 000000000..f33ab8bee --- /dev/null +++ b/include/assimp/commonMetaData.h @@ -0,0 +1,61 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file commonMetaData.h + * @brief Defines a set of common scene metadata keys. + */ +#pragma once +#ifndef AI_COMMONMETADATA_H_INC +#define AI_COMMONMETADATA_H_INC + +/// Scene metadata holding the name of the importer which loaded the source asset. +/// This is always present if the scene was created from an imported asset. +#define AI_METADATA_SOURCE_FORMAT "SourceAsset_Format" + +/// Scene metadata holding the version of the source asset as a string, if available. +#define AI_METADATA_SOURCE_FORMAT_VERSION "SourceAsset_FormatVersion" + +/// Scene metadata holding the name of the software which generated the source asset, if available. +#define AI_METADATA_SOURCE_GENERATOR "SourceAsset_Generator" + +#endif diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 849d90f48..419027100 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -377,6 +377,20 @@ struct aiMetadata { return true; } + /// Check whether there is a metadata entry for the given key. + /// \param [in] Key - the key value value to check for. + inline + bool HasKey(const char* key) + { + // Search for the given key + for (unsigned int i = 0; i < mNumProperties; ++i) { + if (strcmp(mKeys[i].C_Str(), key) == 0) { + return true; + } + } + return false; + } + #endif // __cplusplus }; From fabfcf3cb0fa5308626907a58313a69ca27f360a Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 5 Dec 2019 11:37:22 +0000 Subject: [PATCH 117/170] More checking --- code/Common/Importer.cpp | 6 +++++- code/FBX/FBXConverter.cpp | 12 +++++++++--- code/glTF/glTFImporter.cpp | 17 ++++++++++++++--- code/glTF2/glTF2Importer.cpp | 17 ++++++++++++++--- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index d7ca88545..bf5cb2bf6 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -655,8 +655,12 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // If successful, apply all active post processing steps to the imported data if( pimpl->mScene) { - if (!pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) + if (!pimpl->mScene->mMetaData || !pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) { + if (!pimpl->mScene->mMetaData) + { + pimpl->mScene->mMetaData = new aiMetadata; + } pimpl->mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT, aiString(ext)); } diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index f50688bea..46b899810 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -61,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include @@ -3605,7 +3606,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa return; } - out->mMetaData = aiMetadata::Alloc(17); + const bool hasGenerator = !doc.Creator().empty(); + + out->mMetaData = aiMetadata::Alloc(16 + (hasGenerator ? 1 : 0)); out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis()); out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign()); out->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis()); @@ -3621,8 +3624,11 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa out->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart()); out->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop()); out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); - out->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(std::to_string(doc.FBXVersion()))); - out->mMetaData->Set(16, AI_METADATA_SOURCE_GENERATOR, aiString(doc.Creator())); + out->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(to_string(doc.FBXVersion()))); + if (hasGenerator) + { + out->mMetaData->Set(16, AI_METADATA_SOURCE_GENERATOR, aiString(doc.Creator())); + } } void FBXConverter::TransferDataToScene() diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index 50ae7541d..25691b2c9 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -701,9 +701,20 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) void glTFImporter::ImportCommonMetadata(glTF::Asset& a) { ai_assert(mScene->mMetaData == nullptr); - mScene->mMetaData = aiMetadata::Alloc(2); - mScene->mMetaData->Set(0, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); - mScene->mMetaData->Set(1, AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); + const bool hasVersion = !a.asset.version.empty(); + const bool hasGenerator = !a.asset.generator.empty(); + if (hasVersion || hasGenerator) + { + mScene->mMetaData = new aiMetadata; + if (hasVersion) + { + mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); + } + if (hasGenerator) + { + mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); + } + } } void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 70b6ddd70..b14d68c27 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -1304,9 +1304,20 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { ai_assert(mScene->mMetaData == nullptr); - mScene->mMetaData = aiMetadata::Alloc(2); - mScene->mMetaData->Set(0, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); - mScene->mMetaData->Set(1, AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); + const bool hasVersion = !a.asset.version.empty(); + const bool hasGenerator = !a.asset.generator.empty(); + if (hasVersion || hasGenerator) + { + mScene->mMetaData = new aiMetadata; + if (hasVersion) + { + mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); + } + if (hasGenerator) + { + mScene->mMetaData->Add(AI_METADATA_SOURCE_GENERATOR, aiString(a.asset.generator)); + } + } } void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { From 81984002d35bc0e51f33beb0178125d13db35a37 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 5 Dec 2019 13:52:34 +0000 Subject: [PATCH 118/170] Fix and test for GLTF. --- code/glTF/glTFImporter.cpp | 2 +- test/unit/utglTFImportExport.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index 25691b2c9..59e7d9b92 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -743,7 +743,7 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS ImportLights(asset); ImportNodes(asset); - + ImportCommonMetadata(asset); if (pScene->mNumMeshes == 0) { pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; diff --git a/test/unit/utglTFImportExport.cpp b/test/unit/utglTFImportExport.cpp index 90f0758bb..20953de8d 100644 --- a/test/unit/utglTFImportExport.cpp +++ b/test/unit/utglTFImportExport.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include using namespace Assimp; @@ -63,6 +64,31 @@ TEST_F( utglTFImportExport, importglTFFromFileTest ) { EXPECT_TRUE( importerTest() ); } +TEST_F(utglTFImportExport, sceneMetadata) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF/TwoBoxes/TwoBoxes.gltf", aiProcess_ValidateDataStructure); + ASSERT_TRUE(scene); + ASSERT_TRUE(scene->mMetaData); + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)); + aiString format; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, format)); + ASSERT_EQ(strcmp(format.C_Str(), "glTF Importer"), 0); + } + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT_VERSION)); + aiString version; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, version)); + ASSERT_EQ(strcmp(version.C_Str(), "1.0"), 0); + } + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_GENERATOR)); + aiString generator; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, generator)); + ASSERT_EQ(strncmp(generator.C_Str(), "collada2gltf", 12), 0); + } +} + TEST_F(utglTFImportExport, incorrect_vertex_arrays) { Assimp::Importer importer; const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF/IncorrectVertexArrays/Cube_v1.gltf", From 6639d5180bef39c521c4981cc89f820afd00d7d5 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 5 Dec 2019 14:05:49 +0000 Subject: [PATCH 119/170] Add a test for gltf2 and FBX metadata. --- test/unit/utFBXImporterExporter.cpp | 27 +++++++++++++++++ test/unit/utglTF2ImportExport.cpp | 28 ++++++++++++++++++ test/unit/utglTFImportExport.cpp | 46 ++++++++++++++--------------- 3 files changed, 78 insertions(+), 23 deletions(-) diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index 43dc40e88..fd350850f 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; @@ -283,3 +284,29 @@ TEST_F(utFBXImporterExporter, importOrphantEmbeddedTextureTest) { ASSERT_TRUE(scene->mTextures[0]->pcData); ASSERT_EQ(9026u, scene->mTextures[0]->mWidth) << "FBX ASCII base64 compression used for a texture."; } + +TEST_F(utFBXImporterExporter, sceneMetadata) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/global_settings.fbx", + aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + ASSERT_NE(scene->mMetaData, nullptr); + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)); + aiString format; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, format)); + ASSERT_EQ(strcmp(format.C_Str(), "Autodesk FBX Importer"), 0); + } + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT_VERSION)); + aiString version; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, version)); + ASSERT_EQ(strcmp(version.C_Str(), "7400"), 0); + } + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_GENERATOR)); + aiString generator; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, generator)); + ASSERT_EQ(strncmp(generator.C_Str(), "Blender", 7), 0); + } +} diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index ef1316fb7..6443d740f 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include + #include using namespace Assimp; @@ -436,3 +438,29 @@ TEST_F(utglTF2ImportExport, error_string_preserved) { } #endif // ASSIMP_BUILD_NO_EXPORT + +TEST_F(utglTF2ImportExport, sceneMetadata) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", + aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + ASSERT_NE(scene->mMetaData, nullptr); + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)); + aiString format; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, format)); + ASSERT_EQ(strcmp(format.C_Str(), "glTF2 Importer"), 0); + } + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT_VERSION)); + aiString version; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, version)); + ASSERT_EQ(strcmp(version.C_Str(), "2.0"), 0); + } + { + ASSERT_TRUE(scene->mMetaData->HasKey(AI_METADATA_SOURCE_GENERATOR)); + aiString generator; + ASSERT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, generator)); + ASSERT_EQ(strcmp(generator.C_Str(), "COLLADA2GLTF"), 0); + } +} diff --git a/test/unit/utglTFImportExport.cpp b/test/unit/utglTFImportExport.cpp index 20953de8d..321d58354 100644 --- a/test/unit/utglTFImportExport.cpp +++ b/test/unit/utglTFImportExport.cpp @@ -64,6 +64,29 @@ TEST_F( utglTFImportExport, importglTFFromFileTest ) { EXPECT_TRUE( importerTest() ); } +TEST_F(utglTFImportExport, incorrect_vertex_arrays) { + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF/IncorrectVertexArrays/Cube_v1.gltf", + aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 12u); + EXPECT_EQ(scene->mMeshes[1]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[1]->mNumFaces, 11u); + EXPECT_EQ(scene->mMeshes[2]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[2]->mNumFaces, 18u); + EXPECT_EQ(scene->mMeshes[3]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[3]->mNumFaces, 17u); + EXPECT_EQ(scene->mMeshes[4]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[4]->mNumFaces, 12u); + EXPECT_EQ(scene->mMeshes[5]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[5]->mNumFaces, 11u); + EXPECT_EQ(scene->mMeshes[6]->mNumVertices, 36u); + EXPECT_EQ(scene->mMeshes[6]->mNumFaces, 18u); + EXPECT_EQ(scene->mMeshes[7]->mNumVertices, 35u); + EXPECT_EQ(scene->mMeshes[7]->mNumFaces, 17u); +} + TEST_F(utglTFImportExport, sceneMetadata) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF/TwoBoxes/TwoBoxes.gltf", aiProcess_ValidateDataStructure); @@ -88,26 +111,3 @@ TEST_F(utglTFImportExport, sceneMetadata) { ASSERT_EQ(strncmp(generator.C_Str(), "collada2gltf", 12), 0); } } - -TEST_F(utglTFImportExport, incorrect_vertex_arrays) { - Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF/IncorrectVertexArrays/Cube_v1.gltf", - aiProcess_ValidateDataStructure); - EXPECT_NE(nullptr, scene); - EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 36u); - EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 12u); - EXPECT_EQ(scene->mMeshes[1]->mNumVertices, 35u); - EXPECT_EQ(scene->mMeshes[1]->mNumFaces, 11u); - EXPECT_EQ(scene->mMeshes[2]->mNumVertices, 36u); - EXPECT_EQ(scene->mMeshes[2]->mNumFaces, 18u); - EXPECT_EQ(scene->mMeshes[3]->mNumVertices, 35u); - EXPECT_EQ(scene->mMeshes[3]->mNumFaces, 17u); - EXPECT_EQ(scene->mMeshes[4]->mNumVertices, 36u); - EXPECT_EQ(scene->mMeshes[4]->mNumFaces, 12u); - EXPECT_EQ(scene->mMeshes[5]->mNumVertices, 35u); - EXPECT_EQ(scene->mMeshes[5]->mNumFaces, 11u); - EXPECT_EQ(scene->mMeshes[6]->mNumVertices, 36u); - EXPECT_EQ(scene->mMeshes[6]->mNumFaces, 18u); - EXPECT_EQ(scene->mMeshes[7]->mNumVertices, 35u); - EXPECT_EQ(scene->mMeshes[7]->mNumFaces, 17u); -} From 8956e567b27c2b5c4741d806c77ba865824c7505 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 5 Dec 2019 14:09:36 +0000 Subject: [PATCH 120/170] Better comment. --- code/FBX/FBXConverter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBX/FBXConverter.h b/code/FBX/FBXConverter.h index b89816127..d47416223 100644 --- a/code/FBX/FBXConverter.h +++ b/code/FBX/FBXConverter.h @@ -422,7 +422,7 @@ private: Model::RotOrder order); // ------------------------------------------------------------------------------------------------ - // Copy information about the source of the document into scene metadata. + // Copy global geometric data and some information about the source asset into scene metadata. void ConvertGlobalSettings(); // ------------------------------------------------------------------------------------------------ From 24f0a400b7e3afdf0c44a61eaa916db5d9dbc3e1 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 5 Dec 2019 15:11:46 +0000 Subject: [PATCH 121/170] Extra comments. --- include/assimp/commonMetaData.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/assimp/commonMetaData.h b/include/assimp/commonMetaData.h index f33ab8bee..1e176725e 100644 --- a/include/assimp/commonMetaData.h +++ b/include/assimp/commonMetaData.h @@ -53,9 +53,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_METADATA_SOURCE_FORMAT "SourceAsset_Format" /// Scene metadata holding the version of the source asset as a string, if available. +/// Not all formats add this metadata. #define AI_METADATA_SOURCE_FORMAT_VERSION "SourceAsset_FormatVersion" /// Scene metadata holding the name of the software which generated the source asset, if available. +/// Not all formats add this metadata. #define AI_METADATA_SOURCE_GENERATOR "SourceAsset_Generator" #endif From a2f8c84c6c71e8d64e99f8b03c619c33e04623e6 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 5 Dec 2019 17:06:28 +0000 Subject: [PATCH 122/170] Fix deletion issue in aiMetadata::Add. --- include/assimp/metadata.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 419027100..a01ecf933 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -286,8 +286,8 @@ struct aiMetadata { new_values[i] = mValues[i]; } - delete mKeys; - delete mValues; + delete[] mKeys; + delete[] mValues; mKeys = new_keys; mValues = new_values; From c1706d9bf8614390eeb743f98281daaeb3395360 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Dec 2019 21:24:04 +0100 Subject: [PATCH 123/170] Update metadata.h Fix possible crashes. --- include/assimp/metadata.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index a01ecf933..f3a5321d3 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -380,11 +380,14 @@ struct aiMetadata { /// Check whether there is a metadata entry for the given key. /// \param [in] Key - the key value value to check for. inline - bool HasKey(const char* key) - { + bool HasKey(const char* key) { + if ( nullptr == key ) { + return false; + } + // Search for the given key for (unsigned int i = 0; i < mNumProperties; ++i) { - if (strcmp(mKeys[i].C_Str(), key) == 0) { + if ( 0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length ) ) { return true; } } From ef13fb2ddd997230d477c6b4968bed49c3d3cd0c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 6 Dec 2019 21:38:07 +0100 Subject: [PATCH 124/170] Update Importer.cpp Fix minor review findings. --- code/Common/Importer.cpp | 284 +++++++++++++++++++++------------------ 1 file changed, 155 insertions(+), 129 deletions(-) diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index bf5cb2bf6..a42398406 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -79,6 +77,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include + #include #include #include @@ -120,7 +119,7 @@ void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothro return AllocateFromAssimpHeap::operator new( num_bytes ); } catch( ... ) { - return NULL; + return nullptr; } } @@ -135,9 +134,8 @@ void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes) { void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() { try { return AllocateFromAssimpHeap::operator new[]( num_bytes ); - } - catch( ... ) { - return NULL; + } catch( ... ) { + return nullptr; } } @@ -149,7 +147,7 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data) { // Importer constructor. Importer::Importer() : pimpl( new ImporterPimpl ) { - pimpl->mScene = NULL; + pimpl->mScene = nullptr; pimpl->mErrorString = ""; // Allocate a default IO handler @@ -175,14 +173,14 @@ Importer::Importer() // ------------------------------------------------------------------------------------------------ // Destructor of Importer -Importer::~Importer() -{ +Importer::~Importer() { // Delete all import plugins DeleteImporterInstanceList(pimpl->mImporter); // Delete all post-processing plug-ins - for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) + for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); ++a ) { delete pimpl->mPostProcessingSteps[a]; + } // Delete the assigned IO and progress handler delete pimpl->mIOHandler; @@ -200,9 +198,9 @@ Importer::~Importer() // ------------------------------------------------------------------------------------------------ // Register a custom post-processing step -aiReturn Importer::RegisterPPStep(BaseProcess* pImp) -{ - ai_assert(NULL != pImp); +aiReturn Importer::RegisterPPStep(BaseProcess* pImp) { + ai_assert( nullptr != pImp ); + ASSIMP_BEGIN_EXCEPTION_REGION(); pimpl->mPostProcessingSteps.push_back(pImp); @@ -214,9 +212,9 @@ aiReturn Importer::RegisterPPStep(BaseProcess* pImp) // ------------------------------------------------------------------------------------------------ // Register a custom loader plugin -aiReturn Importer::RegisterLoader(BaseImporter* pImp) -{ - ai_assert(NULL != pImp); +aiReturn Importer::RegisterLoader(BaseImporter* pImp) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); // -------------------------------------------------------------------- @@ -243,13 +241,13 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) pimpl->mImporter.push_back(pImp); ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked); ASSIMP_END_EXCEPTION_REGION(aiReturn); + return AI_SUCCESS; } // ------------------------------------------------------------------------------------------------ // Unregister a custom loader plugin -aiReturn Importer::UnregisterLoader(BaseImporter* pImp) -{ +aiReturn Importer::UnregisterLoader(BaseImporter* pImp) { if(!pImp) { // unregistering a NULL importer is no problem for us ... really! return AI_SUCCESS; @@ -266,13 +264,13 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp) } ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ..."); ASSIMP_END_EXCEPTION_REGION(aiReturn); + return AI_FAILURE; } // ------------------------------------------------------------------------------------------------ // Unregister a custom loader plugin -aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) -{ +aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) { if(!pImp) { // unregistering a NULL ppstep is no problem for us ... really! return AI_SUCCESS; @@ -289,24 +287,22 @@ aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) } ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you .."); ASSIMP_END_EXCEPTION_REGION(aiReturn); + return AI_FAILURE; } // ------------------------------------------------------------------------------------------------ // Supplies a custom IO handler to the importer to open and access files. -void Importer::SetIOHandler( IOSystem* pIOHandler) -{ +void Importer::SetIOHandler( IOSystem* pIOHandler) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); // If the new handler is zero, allocate a default IO implementation. - if (!pIOHandler) - { + if (!pIOHandler) { // Release pointer in the possession of the caller pimpl->mIOHandler = new DefaultIOSystem(); pimpl->mIsDefaultHandler = true; - } - // Otherwise register the custom handler - else if (pimpl->mIOHandler != pIOHandler) - { + } else if (pimpl->mIOHandler != pIOHandler) { // Otherwise register the custom handler delete pimpl->mIOHandler; pimpl->mIOHandler = pIOHandler; pimpl->mIsDefaultHandler = false; @@ -317,29 +313,32 @@ void Importer::SetIOHandler( IOSystem* pIOHandler) // ------------------------------------------------------------------------------------------------ // Get the currently set IO handler IOSystem* Importer::GetIOHandler() const { + ai_assert(nullptr != pImp); + return pimpl->mIOHandler; } // ------------------------------------------------------------------------------------------------ // Check whether a custom IO handler is currently set bool Importer::IsDefaultIOHandler() const { + ai_assert(nullptr != pImp); + return pimpl->mIsDefaultHandler; } // ------------------------------------------------------------------------------------------------ // Supplies a custom progress handler to get regular callbacks during importing void Importer::SetProgressHandler ( ProgressHandler* pHandler ) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); + // If the new handler is zero, allocate a default implementation. - if (!pHandler) - { + if (!pHandler) { // Release pointer in the possession of the caller pimpl->mProgressHandler = new DefaultProgressHandler(); pimpl->mIsDefaultProgressHandler = true; - } - // Otherwise register the custom handler - else if (pimpl->mProgressHandler != pHandler) - { + } else if (pimpl->mProgressHandler != pHandler) { // Otherwise register the custom handler delete pimpl->mProgressHandler; pimpl->mProgressHandler = pHandler; pimpl->mIsDefaultProgressHandler = false; @@ -350,19 +349,24 @@ void Importer::SetProgressHandler ( ProgressHandler* pHandler ) { // ------------------------------------------------------------------------------------------------ // Get the currently set progress handler ProgressHandler* Importer::GetProgressHandler() const { + ai_assert(nullptr != pImp); + return pimpl->mProgressHandler; } // ------------------------------------------------------------------------------------------------ // Check whether a custom progress handler is currently set bool Importer::IsDefaultProgressHandler() const { + ai_assert(nullptr != pImp); + return pimpl->mIsDefaultProgressHandler; } // ------------------------------------------------------------------------------------------------ // Validate post process step flags -bool _ValidateFlags(unsigned int pFlags) -{ +bool _ValidateFlags(unsigned int pFlags) { + ai_assert(nullptr != pImp); + if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) { ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible"); return false; @@ -376,12 +380,13 @@ bool _ValidateFlags(unsigned int pFlags) // ------------------------------------------------------------------------------------------------ // Free the current scene -void Importer::FreeScene( ) -{ +void Importer::FreeScene( ) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); delete pimpl->mScene; - pimpl->mScene = NULL; + pimpl->mScene = nullptr; pimpl->mErrorString = ""; ASSIMP_END_EXCEPTION_REGION(void); @@ -389,44 +394,48 @@ void Importer::FreeScene( ) // ------------------------------------------------------------------------------------------------ // Get the current error string, if any -const char* Importer::GetErrorString() const -{ - /* Must remain valid as long as ReadFile() or FreeFile() are not called */ +const char* Importer::GetErrorString() const { + ai_assert(nullptr != pImp); + + // Must remain valid as long as ReadFile() or FreeFile() are not called return pimpl->mErrorString.c_str(); } // ------------------------------------------------------------------------------------------------ // Enable extra-verbose mode -void Importer::SetExtraVerbose(bool bDo) -{ +void Importer::SetExtraVerbose(bool bDo) { + ai_assert(nullptr != pImp); + pimpl->bExtraVerbose = bDo; } // ------------------------------------------------------------------------------------------------ // Get the current scene -const aiScene* Importer::GetScene() const -{ +const aiScene* Importer::GetScene() const { + ai_assert(nullptr != pImp); + return pimpl->mScene; } // ------------------------------------------------------------------------------------------------ // Orphan the current scene and return it. -aiScene* Importer::GetOrphanedScene() -{ +aiScene* Importer::GetOrphanedScene() { + ai_assert(nullptr != pImp); + aiScene* s = pimpl->mScene; ASSIMP_BEGIN_EXCEPTION_REGION(); - pimpl->mScene = NULL; + pimpl->mScene = nullptr; - pimpl->mErrorString = ""; /* reset error string */ + pimpl->mErrorString = ""; // reset error string ASSIMP_END_EXCEPTION_REGION(aiScene*); + return s; } // ------------------------------------------------------------------------------------------------ // Validate post-processing flags -bool Importer::ValidateFlags(unsigned int pFlags) const -{ +bool Importer::ValidateFlags(unsigned int pFlags) const { ASSIMP_BEGIN_EXCEPTION_REGION(); // run basic checks for mutually exclusive flags if(!_ValidateFlags(pFlags)) { @@ -468,8 +477,9 @@ bool Importer::ValidateFlags(unsigned int pFlags) const const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, size_t pLength, unsigned int pFlags, - const char* pHint /*= ""*/) -{ + const char* pHint /*= ""*/) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); if (!pHint) { pHint = ""; @@ -477,12 +487,12 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) { pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()"; - return NULL; + return nullptr; } // prevent deletion of the previous IOHandler IOSystem* io = pimpl->mIOHandler; - pimpl->mIOHandler = NULL; + pimpl->mIOHandler = nullptr; SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io)); @@ -499,8 +509,9 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, } // ------------------------------------------------------------------------------------------------ -void WriteLogOpening(const std::string& file) -{ +void WriteLogOpening(const std::string& file) { + ai_assert(nullptr != pImp); + ASSIMP_LOG_INFO_F("Load ", file); // print a full version dump. This is nice because we don't @@ -551,8 +562,9 @@ void WriteLogOpening(const std::string& file) // ------------------------------------------------------------------------------------------------ // Reads the given file and returns its contents if successful. -const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) -{ +const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); const std::string pFile(_pFile); @@ -581,7 +593,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) pimpl->mErrorString = "Unable to open file \"" + pFile + "\"."; ASSIMP_LOG_ERROR(pimpl->mErrorString); - return NULL; + return nullptr; } std::unique_ptr profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL); @@ -590,7 +602,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) } // Find an worker class which can handle the file - BaseImporter* imp = NULL; + BaseImporter* imp = nullptr; SetPropertyInteger("importerIndex", -1); for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { @@ -618,7 +630,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) if( !imp) { pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\"."; ASSIMP_LOG_ERROR(pimpl->mErrorString); - return NULL; + return nullptr; } } @@ -634,7 +646,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // Dispatch the reading to the worker class for this format const aiImporterDesc *desc( imp->GetInfo() ); std::string ext( "unknown" ); - if ( NULL != desc ) { + if ( nullptr != desc ) { ext = desc->mName; } ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." ); @@ -655,10 +667,8 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) // If successful, apply all active post processing steps to the imported data if( pimpl->mScene) { - if (!pimpl->mScene->mMetaData || !pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) - { - if (!pimpl->mScene->mMetaData) - { + if (!pimpl->mScene->mMetaData || !pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) { + if (!pimpl->mScene->mMetaData) { pimpl->mScene->mMetaData = new aiMetadata; } pimpl->mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT, aiString(ext)); @@ -666,12 +676,11 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called. - if (pFlags & aiProcess_ValidateDataStructure) - { + if (pFlags & aiProcess_ValidateDataStructure) { ValidateDSProcess ds; ds.ExecuteOnScene (this); if (!pimpl->mScene) { - return NULL; + return nullptr; } } #endif // no validation @@ -704,8 +713,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) } } #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS - catch (std::exception &e) - { + catch (std::exception &e) { #if (defined _MSC_VER) && (defined _CPPRTTI) // if we have RTTI get the full name of the exception that occurred pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what(); @@ -714,24 +722,26 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) #endif ASSIMP_LOG_ERROR(pimpl->mErrorString); - delete pimpl->mScene; pimpl->mScene = NULL; + delete pimpl->mScene; pimpl->mScene = nullptr; } #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS // either successful or failure - the pointer expresses it anyways ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString); + return pimpl->mScene; } // ------------------------------------------------------------------------------------------------ // Apply post-processing to the currently bound scene -const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) -{ +const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); // Return immediately if no scene is active if (!pimpl->mScene) { - return NULL; + return nullptr; } // If no flags are given, return the current scene with no further action @@ -746,12 +756,11 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS // The ValidateDS process plays an exceptional role. It isn't contained in the global // list of post-processing steps, so we need to call it manually. - if (pFlags & aiProcess_ValidateDataStructure) - { + if (pFlags & aiProcess_ValidateDataStructure) { ValidateDSProcess ds; ds.ExecuteOnScene (this); if (!pimpl->mScene) { - return NULL; + return nullptr; } } #endif // no validation @@ -771,11 +780,9 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) std::unique_ptr profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL); for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { - BaseProcess* process = pimpl->mPostProcessingSteps[a]; pimpl->mProgressHandler->UpdatePostProcess(static_cast(a), static_cast(pimpl->mPostProcessingSteps.size()) ); if( process->IsActive( pFlags)) { - if (profiler) { profiler->BeginRegion("postprocess"); } @@ -812,24 +819,28 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) static_cast(pimpl->mPostProcessingSteps.size()) ); // update private scene flags - if( pimpl->mScene ) + if( pimpl->mScene ) { ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags; + } // clear any data allocated by post-process steps pimpl->mPPShared->Clean(); ASSIMP_LOG_INFO("Leaving post processing pipeline"); ASSIMP_END_EXCEPTION_REGION(const aiScene*); + return pimpl->mScene; } // ------------------------------------------------------------------------------------------------ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation ) { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); // Return immediately if no scene is active - if ( NULL == pimpl->mScene ) { - return NULL; + if ( nullptr == pimpl->mScene ) { + return nullptr; } // If no flags are given, return the current scene with no further action @@ -848,7 +859,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess ValidateDSProcess ds; ds.ExecuteOnScene( this ); if ( !pimpl->mScene ) { - return NULL; + return nullptr; } } #endif // no validation @@ -899,46 +910,50 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess // ------------------------------------------------------------------------------------------------ // Helper function to check whether an extension is supported by ASSIMP -bool Importer::IsExtensionSupported(const char* szExtension) const -{ +bool Importer::IsExtensionSupported(const char* szExtension) const { return nullptr != GetImporter(szExtension); } // ------------------------------------------------------------------------------------------------ -size_t Importer::GetImporterCount() const -{ +size_t Importer::GetImporterCount() const { + ai_assert(nullptr != pImp); + return pimpl->mImporter.size(); } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* Importer::GetImporterInfo(size_t index) const -{ +const aiImporterDesc* Importer::GetImporterInfo(size_t index) const { + ai_assert(nullptr != pImp); + if (index >= pimpl->mImporter.size()) { - return NULL; + return nullptr; } return pimpl->mImporter[index]->GetInfo(); } // ------------------------------------------------------------------------------------------------ -BaseImporter* Importer::GetImporter (size_t index) const -{ +BaseImporter* Importer::GetImporter (size_t index) const { + ai_assert(nullptr != pImp); + if (index >= pimpl->mImporter.size()) { - return NULL; + return nullptr; } return pimpl->mImporter[index]; } // ------------------------------------------------------------------------------------------------ // Find a loader plugin for a given file extension -BaseImporter* Importer::GetImporter (const char* szExtension) const -{ +BaseImporter* Importer::GetImporter (const char* szExtension) const { + ai_assert(nullptr != pImp); + return GetImporter(GetImporterIndex(szExtension)); } // ------------------------------------------------------------------------------------------------ // Find a loader plugin for a given file extension size_t Importer::GetImporterIndex (const char* szExtension) const { + ai_assert(nullptr != pImp); ai_assert(nullptr != szExtension); ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -969,8 +984,9 @@ size_t Importer::GetImporterIndex (const char* szExtension) const { // ------------------------------------------------------------------------------------------------ // Helper function to build a list of all file extensions supported by ASSIMP -void Importer::GetExtensionList(aiString& szOut) const -{ +void Importer::GetExtensionList(aiString& szOut) const { + ai_assert(nullptr != pImp); + ASSIMP_BEGIN_EXCEPTION_REGION(); std::set str; for (std::vector::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) { @@ -994,8 +1010,9 @@ void Importer::GetExtensionList(aiString& szOut) const // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool Importer::SetPropertyInteger(const char* szName, int iValue) -{ +bool Importer::SetPropertyInteger(const char* szName, int iValue) { + ai_assert(nullptr != pImp); + bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); existing = SetGenericProperty(pimpl->mIntProperties, szName,iValue); @@ -1005,8 +1022,9 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue) // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) -{ +bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) { + ai_assert(nullptr != pImp); + bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); existing = SetGenericProperty(pimpl->mFloatProperties, szName,iValue); @@ -1016,8 +1034,9 @@ bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool Importer::SetPropertyString(const char* szName, const std::string& value) -{ +bool Importer::SetPropertyString(const char* szName, const std::string& value) { + ai_assert(nullptr != pImp); + bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); existing = SetGenericProperty(pimpl->mStringProperties, szName,value); @@ -1027,8 +1046,9 @@ bool Importer::SetPropertyString(const char* szName, const std::string& value) // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) -{ +bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) { + ai_assert(nullptr != pImp); + bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); existing = SetGenericProperty(pimpl->mMatrixProperties, szName,value); @@ -1038,40 +1058,43 @@ bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) // ------------------------------------------------------------------------------------------------ // Get a configuration property -int Importer::GetPropertyInteger(const char* szName, - int iErrorReturn /*= 0xffffffff*/) const -{ +int Importer::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const { + ai_assert(nullptr != pImp); + return GetGenericProperty(pimpl->mIntProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Get a configuration property -ai_real Importer::GetPropertyFloat(const char* szName, - ai_real iErrorReturn /*= 10e10*/) const -{ +ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const { + ai_assert(nullptr != pImp); + return GetGenericProperty(pimpl->mFloatProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Get a configuration property -const std::string Importer::GetPropertyString(const char* szName, - const std::string& iErrorReturn /*= ""*/) const -{ +const std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const { + ai_assert(nullptr != pImp); + return GetGenericProperty(pimpl->mStringProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Get a configuration property -const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, - const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const -{ +const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const { + ai_assert(nullptr != pImp); + return GetGenericProperty(pimpl->mMatrixProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Get the memory requirements of a single node -inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) -{ +inline +void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) { + if ( nullptr == pcNode ) { + return; + } iScene += sizeof(aiNode); iScene += sizeof(unsigned int) * pcNode->mNumMeshes; iScene += sizeof(void*) * pcNode->mNumChildren; @@ -1083,8 +1106,9 @@ inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) // ------------------------------------------------------------------------------------------------ // Get the memory requirements of the scene -void Importer::GetMemoryRequirements(aiMemoryInfo& in) const -{ +void Importer::GetMemoryRequirements(aiMemoryInfo& in) const { + ai_assert(nullptr != pImp); + in = aiMemoryInfo(); aiScene* mScene = pimpl->mScene; @@ -1096,8 +1120,7 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const in.total = sizeof(aiScene); // add all meshes - for (unsigned int i = 0; i < mScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < mScene->mNumMeshes;++i) { in.meshes += sizeof(aiMesh); if (mScene->mMeshes[i]->HasPositions()) { in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices; @@ -1114,14 +1137,16 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) { if (mScene->mMeshes[i]->HasVertexColors(a)) { in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices; + } else { + break; } - else break; } for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { if (mScene->mMeshes[i]->HasTextureCoords(a)) { in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices; + } else { + break; } - else break; } if (mScene->mMeshes[i]->HasBones()) { in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones; @@ -1140,8 +1165,9 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const in.textures += sizeof(aiTexture); if (pc->mHeight) { in.textures += 4 * pc->mHeight * pc->mWidth; + } else { + in.textures += pc->mWidth; } - else in.textures += pc->mWidth; } in.total += in.textures; From 26f6e5ad307d802c148f1e33380e3d344ac721e3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 7 Dec 2019 08:58:47 +0100 Subject: [PATCH 125/170] Update Importer.cpp fix typo --- code/Common/Importer.cpp | 60 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index a42398406..aa70e3287 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -294,7 +294,7 @@ aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) { // ------------------------------------------------------------------------------------------------ // Supplies a custom IO handler to the importer to open and access files. void Importer::SetIOHandler( IOSystem* pIOHandler) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); // If the new handler is zero, allocate a default IO implementation. @@ -313,7 +313,7 @@ void Importer::SetIOHandler( IOSystem* pIOHandler) { // ------------------------------------------------------------------------------------------------ // Get the currently set IO handler IOSystem* Importer::GetIOHandler() const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return pimpl->mIOHandler; } @@ -321,7 +321,7 @@ IOSystem* Importer::GetIOHandler() const { // ------------------------------------------------------------------------------------------------ // Check whether a custom IO handler is currently set bool Importer::IsDefaultIOHandler() const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return pimpl->mIsDefaultHandler; } @@ -329,7 +329,7 @@ bool Importer::IsDefaultIOHandler() const { // ------------------------------------------------------------------------------------------------ // Supplies a custom progress handler to get regular callbacks during importing void Importer::SetProgressHandler ( ProgressHandler* pHandler ) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -349,7 +349,7 @@ void Importer::SetProgressHandler ( ProgressHandler* pHandler ) { // ------------------------------------------------------------------------------------------------ // Get the currently set progress handler ProgressHandler* Importer::GetProgressHandler() const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return pimpl->mProgressHandler; } @@ -357,7 +357,7 @@ ProgressHandler* Importer::GetProgressHandler() const { // ------------------------------------------------------------------------------------------------ // Check whether a custom progress handler is currently set bool Importer::IsDefaultProgressHandler() const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return pimpl->mIsDefaultProgressHandler; } @@ -365,7 +365,7 @@ bool Importer::IsDefaultProgressHandler() const { // ------------------------------------------------------------------------------------------------ // Validate post process step flags bool _ValidateFlags(unsigned int pFlags) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) { ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible"); @@ -381,7 +381,7 @@ bool _ValidateFlags(unsigned int pFlags) { // ------------------------------------------------------------------------------------------------ // Free the current scene void Importer::FreeScene( ) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -395,7 +395,7 @@ void Importer::FreeScene( ) { // ------------------------------------------------------------------------------------------------ // Get the current error string, if any const char* Importer::GetErrorString() const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); // Must remain valid as long as ReadFile() or FreeFile() are not called return pimpl->mErrorString.c_str(); @@ -404,7 +404,7 @@ const char* Importer::GetErrorString() const { // ------------------------------------------------------------------------------------------------ // Enable extra-verbose mode void Importer::SetExtraVerbose(bool bDo) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); pimpl->bExtraVerbose = bDo; } @@ -412,7 +412,7 @@ void Importer::SetExtraVerbose(bool bDo) { // ------------------------------------------------------------------------------------------------ // Get the current scene const aiScene* Importer::GetScene() const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return pimpl->mScene; } @@ -420,7 +420,7 @@ const aiScene* Importer::GetScene() const { // ------------------------------------------------------------------------------------------------ // Orphan the current scene and return it. aiScene* Importer::GetOrphanedScene() { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); aiScene* s = pimpl->mScene; @@ -478,7 +478,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, size_t pLength, unsigned int pFlags, const char* pHint /*= ""*/) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); if (!pHint) { @@ -510,7 +510,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, // ------------------------------------------------------------------------------------------------ void WriteLogOpening(const std::string& file) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_LOG_INFO_F("Load ", file); @@ -563,7 +563,7 @@ void WriteLogOpening(const std::string& file) { // ------------------------------------------------------------------------------------------------ // Reads the given file and returns its contents if successful. const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); const std::string pFile(_pFile); @@ -736,7 +736,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { // ------------------------------------------------------------------------------------------------ // Apply post-processing to the currently bound scene const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); // Return immediately if no scene is active @@ -834,7 +834,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) { // ------------------------------------------------------------------------------------------------ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation ) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -916,14 +916,14 @@ bool Importer::IsExtensionSupported(const char* szExtension) const { // ------------------------------------------------------------------------------------------------ size_t Importer::GetImporterCount() const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return pimpl->mImporter.size(); } // ------------------------------------------------------------------------------------------------ const aiImporterDesc* Importer::GetImporterInfo(size_t index) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); if (index >= pimpl->mImporter.size()) { return nullptr; @@ -934,7 +934,7 @@ const aiImporterDesc* Importer::GetImporterInfo(size_t index) const { // ------------------------------------------------------------------------------------------------ BaseImporter* Importer::GetImporter (size_t index) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); if (index >= pimpl->mImporter.size()) { return nullptr; @@ -945,7 +945,7 @@ BaseImporter* Importer::GetImporter (size_t index) const { // ------------------------------------------------------------------------------------------------ // Find a loader plugin for a given file extension BaseImporter* Importer::GetImporter (const char* szExtension) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return GetImporter(GetImporterIndex(szExtension)); } @@ -953,7 +953,7 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const { // ------------------------------------------------------------------------------------------------ // Find a loader plugin for a given file extension size_t Importer::GetImporterIndex (const char* szExtension) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ai_assert(nullptr != szExtension); ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -985,7 +985,7 @@ size_t Importer::GetImporterIndex (const char* szExtension) const { // ------------------------------------------------------------------------------------------------ // Helper function to build a list of all file extensions supported by ASSIMP void Importer::GetExtensionList(aiString& szOut) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); ASSIMP_BEGIN_EXCEPTION_REGION(); std::set str; @@ -1011,7 +1011,7 @@ void Importer::GetExtensionList(aiString& szOut) const { // ------------------------------------------------------------------------------------------------ // Set a configuration property bool Importer::SetPropertyInteger(const char* szName, int iValue) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -1035,7 +1035,7 @@ bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) { // ------------------------------------------------------------------------------------------------ // Set a configuration property bool Importer::SetPropertyString(const char* szName, const std::string& value) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -1047,7 +1047,7 @@ bool Importer::SetPropertyString(const char* szName, const std::string& value) { // ------------------------------------------------------------------------------------------------ // Set a configuration property bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); @@ -1059,7 +1059,7 @@ bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) { // ------------------------------------------------------------------------------------------------ // Get a configuration property int Importer::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return GetGenericProperty(pimpl->mIntProperties,szName,iErrorReturn); } @@ -1067,7 +1067,7 @@ int Importer::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffff // ------------------------------------------------------------------------------------------------ // Get a configuration property ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return GetGenericProperty(pimpl->mFloatProperties,szName,iErrorReturn); } @@ -1075,7 +1075,7 @@ ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= // ------------------------------------------------------------------------------------------------ // Get a configuration property const std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return GetGenericProperty(pimpl->mStringProperties,szName,iErrorReturn); } @@ -1107,7 +1107,7 @@ void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) { // ------------------------------------------------------------------------------------------------ // Get the memory requirements of the scene void Importer::GetMemoryRequirements(aiMemoryInfo& in) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); in = aiMemoryInfo(); aiScene* mScene = pimpl->mScene; From 7648c438cae7e9b473a0b055fc6eeb79f510268b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 7 Dec 2019 09:08:15 +0100 Subject: [PATCH 126/170] Update Importer.cpp fix more typos. --- code/Common/Importer.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index aa70e3287..86b0eb28a 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -365,8 +365,6 @@ bool Importer::IsDefaultProgressHandler() const { // ------------------------------------------------------------------------------------------------ // Validate post process step flags bool _ValidateFlags(unsigned int pFlags) { - ai_assert(nullptr != pimpl); - if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) { ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible"); return false; @@ -510,7 +508,6 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, // ------------------------------------------------------------------------------------------------ void WriteLogOpening(const std::string& file) { - ai_assert(nullptr != pimpl); ASSIMP_LOG_INFO_F("Load ", file); @@ -1023,7 +1020,7 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue) { // ------------------------------------------------------------------------------------------------ // Set a configuration property bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); bool existing; ASSIMP_BEGIN_EXCEPTION_REGION(); From 9f3c26dbd85893970b73a28b35bcb93a956ece66 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 7 Dec 2019 09:18:45 +0100 Subject: [PATCH 127/170] Update Importer.cpp fix typo --- code/Common/Importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index 86b0eb28a..9564f6ab7 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -1080,7 +1080,7 @@ const std::string Importer::GetPropertyString(const char* szName, const std::str // ------------------------------------------------------------------------------------------------ // Get a configuration property const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const { - ai_assert(nullptr != pImp); + ai_assert(nullptr != pimpl); return GetGenericProperty(pimpl->mMatrixProperties,szName,iErrorReturn); } From 71cac7ab8dca879958bc09b9efb62510feb2de3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Sat, 7 Dec 2019 22:04:04 +0100 Subject: [PATCH 128/170] lower-case PEP263 encoding declaration so emacs likes it... --- port/PyAssimp/pyassimp/structs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index d478b861b..bd90586ff 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -1,4 +1,4 @@ -#-*- coding: UTF-8 -*- +#-*- coding: utf-8 -*- from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t, c_uint32 From 298a89b4eedcd8b18a178bc399f3262220122841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Sat, 7 Dec 2019 22:06:14 +0100 Subject: [PATCH 129/170] remove trailing whitespace --- port/PyAssimp/pyassimp/structs.py | 264 +++++++++++++++--------------- 1 file changed, 132 insertions(+), 132 deletions(-) diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index bd90586ff..b93aae68c 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -6,7 +6,7 @@ from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_char class Vector2D(Structure): """ See 'vector2.h' for details. - """ + """ _fields_ = [ @@ -16,7 +16,7 @@ class Vector2D(Structure): class Matrix3x3(Structure): """ See 'matrix3x3.h' for details. - """ + """ _fields_ = [ @@ -28,7 +28,7 @@ class Matrix3x3(Structure): class Texel(Structure): """ See 'texture.h' for details. - """ + """ _fields_ = [ ("b", c_ubyte),("g", c_ubyte),("r", c_ubyte),("a", c_ubyte), @@ -37,7 +37,7 @@ class Texel(Structure): class Color4D(Structure): """ See 'color4.h' for details. - """ + """ _fields_ = [ @@ -48,7 +48,7 @@ class Color4D(Structure): class Plane(Structure): """ See 'types.h' for details. - """ + """ _fields_ = [ # Plane equation @@ -58,7 +58,7 @@ class Plane(Structure): class Color3D(Structure): """ See 'types.h' for details. - """ + """ _fields_ = [ # Red, green and blue color values @@ -68,7 +68,7 @@ class Color3D(Structure): class String(Structure): """ See 'types.h' for details. - """ + """ MAXLEN = 1024 @@ -77,7 +77,7 @@ class String(Structure): # logical length of strings containing UTF-8 multibyte sequences! It's # the number of bytes from the beginning of the string to its end. ("length", c_size_t), - + # String buffer. Size limit is MAXLEN ("data", c_char*MAXLEN), ] @@ -85,7 +85,7 @@ class String(Structure): class MaterialPropertyString(Structure): """ See 'MaterialSystem.cpp' for details. - + The size of length is truncated to 4 bytes on 64-bit platforms when used as a material property (see MaterialSystem.cpp aiMaterial::AddProperty() for details). """ @@ -97,7 +97,7 @@ class MaterialPropertyString(Structure): # logical length of strings containing UTF-8 multibyte sequences! It's # the number of bytes from the beginning of the string to its end. ("length", c_uint32), - + # String buffer. Size limit is MAXLEN ("data", c_char*MAXLEN), ] @@ -105,30 +105,30 @@ class MaterialPropertyString(Structure): class MemoryInfo(Structure): """ See 'types.h' for details. - """ + """ _fields_ = [ # Storage allocated for texture data ("textures", c_uint), - + # Storage allocated for material data ("materials", c_uint), - + # Storage allocated for mesh data ("meshes", c_uint), - + # Storage allocated for node data ("nodes", c_uint), - + # Storage allocated for animation data ("animations", c_uint), - + # Storage allocated for camera data ("cameras", c_uint), - + # Storage allocated for light data ("lights", c_uint), - + # Total storage allocated for the full import. ("total", c_uint), ] @@ -136,7 +136,7 @@ class MemoryInfo(Structure): class Quaternion(Structure): """ See 'quaternion.h' for details. - """ + """ _fields_ = [ @@ -147,14 +147,14 @@ class Quaternion(Structure): class Face(Structure): """ See 'mesh.h' for details. - """ + """ _fields_ = [ # Number of indices defining this face. # The maximum value for this member is #AI_MAX_FACE_INDICES. ("mNumIndices", c_uint), - + # Pointer to the indices array. Size of the array is given in numIndices. ("mIndices", POINTER(c_uint)), ] @@ -162,12 +162,12 @@ class Face(Structure): class VertexWeight(Structure): """ See 'mesh.h' for details. - """ + """ _fields_ = [ # Index of the vertex which is influenced by the bone. ("mVertexId", c_uint), - + # The strength of the influence in the range (0...1). # The influence from all bones at one vertex amounts to 1. ("mWeight", c_float), @@ -176,7 +176,7 @@ class VertexWeight(Structure): class Matrix4x4(Structure): """ See 'matrix4x4.h' for details. - """ + """ _fields_ = [ @@ -189,7 +189,7 @@ class Matrix4x4(Structure): class Vector3D(Structure): """ See 'vector3.h' for details. - """ + """ _fields_ = [ @@ -199,12 +199,12 @@ class Vector3D(Structure): class MeshKey(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # The time of this key ("mTime", c_double), - + # Index into the aiMesh::mAnimMeshes array of the # mesh corresponding to the #aiMeshAnim hosting this @@ -252,7 +252,7 @@ class Metadata(Structure): class Node(Structure): """ See 'scene.h' for details. - """ + """ Node._fields_ = [ @@ -270,22 +270,22 @@ Node._fields_ = [ # this text. You should be able to handle stuff like whitespace, tabs, # linefeeds, quotation marks, ampersands, ... . ("mName", String), - + # The transformation relative to the node's parent. ("mTransformation", Matrix4x4), - + # Parent node. NULL if this node is the root node. ("mParent", POINTER(Node)), - + # The number of child nodes of this node. ("mNumChildren", c_uint), - + # The child nodes of this node. NULL if mNumChildren is 0. ("mChildren", POINTER(POINTER(Node))), - + # The number of meshes of this node. ("mNumMeshes", c_uint), - + # The meshes of this node. Each entry is an index into the mesh ("mMeshes", POINTER(c_uint)), @@ -297,7 +297,7 @@ Node._fields_ = [ class Light(Structure): """ See 'light.h' for details. - """ + """ _fields_ = [ @@ -306,22 +306,22 @@ class Light(Structure): # This node specifies the position of the light in the scene # hierarchy and can be animated. ("mName", String), - + # The type of the light source. # aiLightSource_UNDEFINED is not a valid value for this member. ("mType", c_uint), - + # Position of the light source in space. Relative to the # transformation of the node corresponding to the light. # The position is undefined for directional lights. ("mPosition", Vector3D), - + # Direction of the light source in space. Relative to the # transformation of the node corresponding to the light. # The direction is undefined for point lights. The vector # may be normalized, but it needn't. ("mDirection", Vector3D), - + # Up direction of the light source in space. Relative to the # transformation of the node corresponding to the light. # @@ -340,7 +340,7 @@ class Light(Structure): # This member corresponds to the att0 variable in the equation. # Naturally undefined for directional lights. ("mAttenuationConstant", c_float), - + # Linear light attenuation factor. # The intensity of the light source at a given distance 'd' from # the light's position is @@ -352,7 +352,7 @@ class Light(Structure): # This member corresponds to the att1 variable in the equation. # Naturally undefined for directional lights. ("mAttenuationLinear", c_float), - + # Quadratic light attenuation factor. # The intensity of the light source at a given distance 'd' from # the light's position is @@ -364,19 +364,19 @@ class Light(Structure): # This member corresponds to the att2 variable in the equation. # Naturally undefined for directional lights. ("mAttenuationQuadratic", c_float), - + # Diffuse color of the light source # The diffuse light color is multiplied with the diffuse # material color to obtain the final color that contributes # to the diffuse shading term. ("mColorDiffuse", Color3D), - + # Specular color of the light source # The specular light color is multiplied with the specular # material color to obtain the final color that contributes # to the specular shading term. ("mColorSpecular", Color3D), - + # Ambient color of the light source # The ambient light color is multiplied with the ambient # material color to obtain the final color that contributes @@ -384,13 +384,13 @@ class Light(Structure): # this value it, is just a remaining of the fixed-function pipeline # that is still supported by quite many file formats. ("mColorAmbient", Color3D), - + # Inner angle of a spot light's light cone. # The spot light has maximum influence on objects inside this # angle. The angle is given in radians. It is 2PI for point # lights and undefined for directional lights. ("mAngleInnerCone", c_float), - + # Outer angle of a spot light's light cone. # The spot light does not affect objects outside this angle. # The angle is given in radians. It is 2PI for point lights and @@ -408,7 +408,7 @@ class Light(Structure): class Texture(Structure): """ See 'texture.h' for details. - """ + """ _fields_ = [ @@ -417,15 +417,15 @@ class Texture(Structure): # like JPEG. In this case mWidth specifies the size of the # memory area pcData is pointing to, in bytes. ("mWidth", c_uint), - + # Height of the texture, in pixels # If this value is zero, pcData points to an compressed texture # in any format (e.g. JPEG). ("mHeight", c_uint), - + # A hint from the loader to make it easier for applications # to determine the type of embedded textures. - # + # # If mHeight != 0 this member is show how data is packed. Hint will consist of # two parts: channel order and channel bitness (count of the bits for every # color channel). For simple parsing by the viewer it's better to not omit @@ -443,7 +443,7 @@ class Texture(Structure): # E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case. # The fourth character will always be '\\0'. ("achFormatHint", c_char*9), - + # Data of the texture. # Points to an array of mWidth # mHeight aiTexel's. @@ -462,7 +462,7 @@ class Texture(Structure): class Ray(Structure): """ See 'types.h' for details. - """ + """ _fields_ = [ # Position and direction of the ray @@ -472,17 +472,17 @@ class Ray(Structure): class UVTransform(Structure): """ See 'material.h' for details. - """ + """ _fields_ = [ # Translation on the u and v axes. # The default value is (0|0). ("mTranslation", Vector2D), - + # Scaling on the u and v axes. # The default value is (1|1). ("mScaling", Vector2D), - + # Rotation - in counter-clockwise direction. # The rotation angle is specified in radians. The # rotation center is 0.5f|0.5f. The default value @@ -493,34 +493,34 @@ class UVTransform(Structure): class MaterialProperty(Structure): """ See 'material.h' for details. - """ + """ _fields_ = [ # Specifies the name of the property (key) # Keys are generally case insensitive. ("mKey", String), - + # Textures: Specifies their exact usage semantic. # For non-texture properties, this member is always 0 # (or, better-said, #aiTextureType_NONE). ("mSemantic", c_uint), - + # Textures: Specifies the index of the texture. # For non-texture properties, this member is always 0. ("mIndex", c_uint), - + # Size of the buffer mData is pointing to, in bytes. # This value may not be 0. ("mDataLength", c_uint), - + # Type information for the property. # Defines the data layout inside the data buffer. This is used # by the library internally to perform debug checks and to # utilize proper type conversions. # (It's probably a hacky solution, but it works.) ("mType", c_uint), - + # Binary buffer to hold the property's value. # The size of the buffer is always mDataLength. ("mData", POINTER(c_char)), @@ -529,15 +529,15 @@ class MaterialProperty(Structure): class Material(Structure): """ See 'material.h' for details. - """ + """ _fields_ = [ # List of all material properties loaded. ("mProperties", POINTER(POINTER(MaterialProperty))), - + # Number of properties in the data base ("mNumProperties", c_uint), - + # Storage allocated ("mNumAllocated", c_uint), ] @@ -545,20 +545,20 @@ class Material(Structure): class Bone(Structure): """ See 'mesh.h' for details. - """ + """ _fields_ = [ # The name of the bone. ("mName", String), - + # The number of vertices affected by this bone # The maximum value for this member is #AI_MAX_BONE_WEIGHTS. ("mNumWeights", c_uint), - + # The vertices affected by this bone ("mWeights", POINTER(VertexWeight)), - + # Matrix that transforms from mesh space to bone space in bind pose ("mOffsetMatrix", Matrix4x4), ] @@ -567,7 +567,7 @@ class Bone(Structure): class AnimMesh(Structure): """ See 'mesh.h' for details. - """ + """ AI_MAX_NUMBER_OF_TEXTURECOORDS = 0x8 AI_MAX_NUMBER_OF_COLOR_SETS = 0x8 @@ -613,7 +613,7 @@ class AnimMesh(Structure): class Mesh(Structure): """ See 'mesh.h' for details. - """ + """ AI_MAX_FACE_INDICES = 0x7fff AI_MAX_BONE_WEIGHTS = 0x7fffffff @@ -628,24 +628,24 @@ class Mesh(Structure): # The "SortByPrimitiveType"-Step can be used to make sure the # output meshes consist of one primitive type each. ("mPrimitiveTypes", c_uint), - + # The number of vertices in this mesh. # This is also the size of all of the per-vertex data arrays. # The maximum value for this member is #AI_MAX_VERTICES. ("mNumVertices", c_uint), - + # The number of primitives (triangles, polygons, lines) in this mesh. # This is also the size of the mFaces array. # The maximum value for this member is #AI_MAX_FACES. ("mNumFaces", c_uint), - + # Vertex positions. # This array is always present in a mesh. The array is # mNumVertices in size. ("mVertices", POINTER(Vector3D)), - + # Vertex normals. # The array contains normalized vectors, NULL if not present. # The array is mNumVertices in size. Normals are undefined for @@ -666,7 +666,7 @@ class Mesh(Structure): # However, this needn't apply for normals that have been taken # directly from the model file. ("mNormals", POINTER(Vector3D)), - + # Vertex tangents. # The tangent of a vertex points in the direction of the positive # X texture axis. The array contains normalized vectors, NULL if @@ -681,7 +681,7 @@ class Mesh(Structure): # contains bitangents (the bitangent is just the cross product of # tangent and normal vectors). ("mTangents", POINTER(Vector3D)), - + # Vertex bitangents. # The bitangent of a vertex points in the direction of the positive # Y texture axis. The array contains normalized vectors, NULL if not @@ -689,19 +689,19 @@ class Mesh(Structure): # @note If the mesh contains tangents, it automatically also contains # bitangents. ("mBitangents", POINTER(Vector3D)), - + # Vertex color sets. # A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex # colors per vertex. NULL if not present. Each array is # mNumVertices in size if present. ("mColors", POINTER(Color4D)*AI_MAX_NUMBER_OF_COLOR_SETS), - + # Vertex texture coords, also known as UV channels. # A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per # vertex. NULL if not present. The array is mNumVertices in size. ("mTextureCoords", POINTER(Vector3D)*AI_MAX_NUMBER_OF_TEXTURECOORDS), - + # Specifies the number of components for a given UV channel. # Up to three channels are supported (UVW, for accessing volume # or cube maps). If the value is 2 for a given channel n, the @@ -709,7 +709,7 @@ class Mesh(Structure): # If the value is 1 for a given channel, p.y is set to 0.0f, too. # @note 4D coords are not supported ("mNumUVComponents", c_uint*AI_MAX_NUMBER_OF_TEXTURECOORDS), - + # The faces the mesh is constructed from. # Each face refers to a number of vertices by their indices. # This array is always present in a mesh, its size is given @@ -717,22 +717,22 @@ class Mesh(Structure): #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT # is NOT set each face references an unique set of vertices. ("mFaces", POINTER(Face)), - + # The number of bones this mesh contains. # Can be 0, in which case the mBones array is NULL. ("mNumBones", c_uint), - + # The bones of this mesh. # A bone consists of a name by which it can be found in the # frame hierarchy and a set of vertex weights. ("mBones", POINTER(POINTER(Bone))), - + # The material used by this mesh. # A mesh does use only a single material. If an imported model uses # multiple materials, the import splits up the mesh. Use this value # as index into the scene's material list. ("mMaterialIndex", c_uint), - + # Name of the mesh. Meshes can be named, but this is not a # requirement and leaving this field empty is totally fine. # There are mainly three uses for mesh names: @@ -744,10 +744,10 @@ class Mesh(Structure): # partitioning. # - Vertex animations refer to meshes by their names. ("mName", String), - + # The number of attachment meshes. Note! Currently only works with Collada loader. ("mNumAnimMeshes", c_uint), - + # Attachment meshes for this mesh, for vertex-based animation. # Attachment meshes carry replacement data for some of the # mesh'es vertex components (usually positions, normals). @@ -762,7 +762,7 @@ class Mesh(Structure): class Camera(Structure): """ See 'camera.h' for details. - """ + """ _fields_ = [ @@ -771,12 +771,12 @@ class Camera(Structure): # This node specifies the position of the camera in the scene # hierarchy and can be animated. ("mName", String), - + # Position of the camera relative to the coordinate space # defined by the corresponding node. # The default value is 0|0|0. ("mPosition", Vector3D), - + # 'Up' - vector of the camera coordinate system relative to # the coordinate space defined by the corresponding node. # The 'right' vector of the camera coordinate system is @@ -784,25 +784,25 @@ class Camera(Structure): # The default value is 0|1|0. The vector # may be normalized, but it needn't. ("mUp", Vector3D), - + # 'LookAt' - vector of the camera coordinate system relative to # the coordinate space defined by the corresponding node. # This is the viewing direction of the user. # The default value is 0|0|1. The vector # may be normalized, but it needn't. ("mLookAt", Vector3D), - + # Half horizontal field of view angle, in radians. # The field of view angle is the angle between the center # line of the screen and the left or right border. # The default value is 1/4PI. ("mHorizontalFOV", c_float), - + # Distance of the near clipping plane from the camera. # The value may not be 0.f (for arithmetic reasons to prevent # a division through zero). The default value is 0.1f. ("mClipPlaneNear", c_float), - + # Distance of the far clipping plane from the camera. # The far clipping plane must, of course, be further away than the # near clipping plane. The default value is 1000.f. The ratio @@ -810,7 +810,7 @@ class Camera(Structure): # large (between 1000-10000 should be ok) to avoid floating-point # inaccuracies which could lead to z-fighting. ("mClipPlaneFar", c_float), - + # Screen aspect ratio. # This is the ration between the width and the height of the # screen. Typical values are 4/3, 1/2 or 1/1. This value is @@ -822,12 +822,12 @@ class Camera(Structure): class VectorKey(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # The time of this key ("mTime", c_double), - + # The value of this key ("mValue", Vector3D), ] @@ -835,12 +835,12 @@ class VectorKey(Structure): class QuatKey(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # The time of this key ("mTime", c_double), - + # The value of this key ("mValue", Quaternion), ] @@ -848,7 +848,7 @@ class QuatKey(Structure): class MeshMorphKey(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # The time of this key @@ -866,47 +866,47 @@ class MeshMorphKey(Structure): class NodeAnim(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # The name of the node affected by this animation. The node # must exist and it must be unique. ("mNodeName", String), - + # The number of position keys ("mNumPositionKeys", c_uint), - + # The position keys of this animation channel. Positions are # specified as 3D vector. The array is mNumPositionKeys in size. # If there are position keys, there will also be at least one # scaling and one rotation key. ("mPositionKeys", POINTER(VectorKey)), - + # The number of rotation keys ("mNumRotationKeys", c_uint), - + # The rotation keys of this animation channel. Rotations are # given as quaternions, which are 4D vectors. The array is # mNumRotationKeys in size. # If there are rotation keys, there will also be at least one # scaling and one position key. ("mRotationKeys", POINTER(QuatKey)), - + # The number of scaling keys ("mNumScalingKeys", c_uint), - + # The scaling keys of this animation channel. Scalings are # specified as 3D vector. The array is mNumScalingKeys in size. # If there are scaling keys, there will also be at least one # position and one rotation key. ("mScalingKeys", POINTER(VectorKey)), - + # Defines how the animation behaves before the first # key is encountered. # The default value is aiAnimBehaviour_DEFAULT (the original # transformation matrix of the affected node is used). ("mPreState", c_uint), - + # Defines how the animation behaves after the last # key was processed. # The default value is aiAnimBehaviour_DEFAULT (the original @@ -917,7 +917,7 @@ class NodeAnim(Structure): class MeshAnim(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # Name of the mesh to be animated. An empty string is not allowed, @@ -936,7 +936,7 @@ class MeshAnim(Structure): class MeshMorphAnim(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # Name of the mesh to be animated. An empty string is not allowed, @@ -956,32 +956,32 @@ class MeshMorphAnim(Structure): class Animation(Structure): """ See 'anim.h' for details. - """ + """ _fields_ = [ # The name of the animation. If the modeling package this data was # exported from does support only a single animation channel, this # name is usually empty (length is zero). ("mName", String), - + # Duration of the animation in ticks. ("mDuration", c_double), - + # Ticks per second. 0 if not specified in the imported file ("mTicksPerSecond", c_double), - + # The number of bone animation channels. Each channel affects # a single node. ("mNumChannels", c_uint), - + # The node animation channels. Each channel affects a single node. # The array is mNumChannels in size. ("mChannels", POINTER(POINTER(NodeAnim))), - + # The number of mesh animation channels. Each channel affects # a single mesh and defines vertex-based animation. ("mNumMeshChannels", c_uint), - + # The mesh animation channels. Each channel affects a single mesh. # The array is mNumMeshChannels in size. ("mMeshChannels", POINTER(POINTER(MeshAnim))), @@ -991,7 +991,7 @@ class Animation(Structure): ("mNumMorphMeshChannels", c_uint), # The morph mesh animation channels. Each channel affects a single mesh. - # The array is mNumMorphMeshChannels in size. + # The array is mNumMorphMeshChannels in size. ("mMorphMeshChannels", POINTER(POINTER(MeshMorphAnim))), ] @@ -1032,7 +1032,7 @@ ExportDataBlob._fields_ = [ class Scene(Structure): """ See 'aiScene.h' for details. - """ + """ AI_SCENE_FLAGS_INCOMPLETE = 0x1 AI_SCENE_FLAGS_VALIDATED = 0x2 @@ -1047,64 +1047,64 @@ class Scene(Structure): # want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE # bit set. ("mFlags", c_uint), - + # The root node of the hierarchy. # There will always be at least the root node if the import # was successful (and no special flags have been set). # Presence of further nodes depends on the format and content # of the imported file. ("mRootNode", POINTER(Node)), - + # The number of meshes in the scene. ("mNumMeshes", c_uint), - + # The array of meshes. # Use the indices given in the aiNode structure to access # this array. The array is mNumMeshes in size. If the # AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always # be at least ONE material. ("mMeshes", POINTER(POINTER(Mesh))), - + # The number of materials in the scene. ("mNumMaterials", c_uint), - + # The array of materials. # Use the index given in each aiMesh structure to access this # array. The array is mNumMaterials in size. If the # AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always # be at least ONE material. ("mMaterials", POINTER(POINTER(Material))), - + # The number of animations in the scene. ("mNumAnimations", c_uint), - + # The array of animations. # All animations imported from the given file are listed here. # The array is mNumAnimations in size. ("mAnimations", POINTER(POINTER(Animation))), - + # The number of textures embedded into the file ("mNumTextures", c_uint), - + # The array of embedded textures. # Not many file formats embed their textures into the file. # An example is Quake's MDL format (which is also used by # some GameStudio versions) ("mTextures", POINTER(POINTER(Texture))), - + # The number of light sources in the scene. Light sources # are fully optional, in most cases this attribute will be 0 ("mNumLights", c_uint), - + # The array of light sources. # All light sources imported from the given file are # listed here. The array is mNumLights in size. ("mLights", POINTER(POINTER(Light))), - + # The number of cameras in the scene. Cameras # are fully optional, in most cases this attribute will be 0 ("mNumCameras", c_uint), - + # The array of cameras. # All cameras imported from the given file are listed here. # The array is mNumCameras in size. The first camera in the From d24adbd32c2b9aeb1a40c1bb99c19e9a8e84ad71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Sat, 7 Dec 2019 22:09:03 +0100 Subject: [PATCH 130/170] aiString.length is really of type "ai_uint32" which corresponds to "c_uint32" and not to "c_size_t" (which is different on 64bit systems and 32bit systems!) Closes: https://github.com/assimp/assimp/issues/2788 --- port/PyAssimp/pyassimp/structs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index b93aae68c..b506bc036 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -76,7 +76,7 @@ class String(Structure): # Binary length of the string excluding the terminal 0. This is NOT the # logical length of strings containing UTF-8 multibyte sequences! It's # the number of bytes from the beginning of the string to its end. - ("length", c_size_t), + ("length", c_uint32), # String buffer. Size limit is MAXLEN ("data", c_char*MAXLEN), From 630f013a5e70834f6e02cf1489b633c8b2325734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Sat, 7 Dec 2019 22:10:26 +0100 Subject: [PATCH 131/170] fix field name "Mesh.mAnimMesh" -> "Mesh.mAnimMeshes" to match the name in mesh.h: aiMesh.mAnimMeshes --- port/PyAssimp/pyassimp/structs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index b506bc036..0ac498a44 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -752,7 +752,7 @@ class Mesh(Structure): # Attachment meshes carry replacement data for some of the # mesh'es vertex components (usually positions, normals). # Note! Currently only works with Collada loader. - ("mAnimMesh", POINTER(POINTER(AnimMesh))), + ("mAnimMeshes", POINTER(POINTER(AnimMesh))), # Method of morphing when animeshes are specified. ("mMethod", c_uint), From e3da92f7d3ae5f1a783b140a984f8c73b20aa8fe Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 8 Dec 2019 10:12:14 +0100 Subject: [PATCH 132/170] closes https://github.com/assimp/assimp/issues/2809: fix crash for special ifc file. --- code/Importer/IFC/IFCGeometry.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/Importer/IFC/IFCGeometry.cpp b/code/Importer/IFC/IFCGeometry.cpp index d1c7aee19..7949f9a58 100644 --- a/code/Importer/IFC/IFCGeometry.cpp +++ b/code/Importer/IFC/IFCGeometry.cpp @@ -138,8 +138,9 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m } } } - - ai_assert(outer_polygon_it != end); + if (outer_polygon_it == end) { + return; + } const size_t outer_polygon_size = *outer_polygon_it; const IfcVector3& master_normal = normals[std::distance(begin, outer_polygon_it)]; From 463573c771288e935403af3ff465a622bc56a087 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 9 Dec 2019 09:56:01 +0000 Subject: [PATCH 133/170] Apply clangformat --- code/PostProcessing/OptimizeGraph.cpp | 419 +++++++++++++------------- 1 file changed, 208 insertions(+), 211 deletions(-) diff --git a/code/PostProcessing/OptimizeGraph.cpp b/code/PostProcessing/OptimizeGraph.cpp index 5db51f58b..709f465e2 100644 --- a/code/PostProcessing/OptimizeGraph.cpp +++ b/code/PostProcessing/OptimizeGraph.cpp @@ -43,13 +43,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the aiProcess_OptimizGraph step */ - #ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS #include "OptimizeGraph.h" #include "ProcessHelper.h" -#include #include +#include #include using namespace Assimp; @@ -60,292 +59,290 @@ using namespace Assimp; * The unhashed variant should be faster, except for *very* large data sets */ #ifdef AI_OG_USE_HASHING - // Use our standard hashing function to compute the hash -# define AI_OG_GETKEY(str) SuperFastHash(str.data,str.length) +// Use our standard hashing function to compute the hash +#define AI_OG_GETKEY(str) SuperFastHash(str.data, str.length) #else - // Otherwise hope that std::string will utilize a static buffer - // for shorter node names. This would avoid endless heap copying. -# define AI_OG_GETKEY(str) std::string(str.data) +// Otherwise hope that std::string will utilize a static buffer +// for shorter node names. This would avoid endless heap copying. +#define AI_OG_GETKEY(str) std::string(str.data) #endif // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -OptimizeGraphProcess::OptimizeGraphProcess() -: mScene() -, nodes_in() -, nodes_out() -, count_merged() { - // empty +OptimizeGraphProcess::OptimizeGraphProcess() : + mScene(), + nodes_in(), + nodes_out(), + count_merged() { + // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well OptimizeGraphProcess::~OptimizeGraphProcess() { - // empty + // empty } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const { - return (0 != (pFlags & aiProcess_OptimizeGraph)); +bool OptimizeGraphProcess::IsActive(unsigned int pFlags) const { + return (0 != (pFlags & aiProcess_OptimizeGraph)); } // ------------------------------------------------------------------------------------------------ // Setup properties for the post-processing step -void OptimizeGraphProcess::SetupProperties(const Importer* pImp) { - // Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST - std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST,""); - AddLockedNodeList(tmp); +void OptimizeGraphProcess::SetupProperties(const Importer *pImp) { + // Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST + std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST, ""); + AddLockedNodeList(tmp); } // ------------------------------------------------------------------------------------------------ // Collect new children -void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& nodes) { - nodes_in += nd->mNumChildren; +void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &nodes) { + nodes_in += nd->mNumChildren; - // Process children - std::list child_nodes; - for (unsigned int i = 0; i < nd->mNumChildren; ++i) { - CollectNewChildren(nd->mChildren[i],child_nodes); - nd->mChildren[i] = nullptr; - } + // Process children + std::list child_nodes; + for (unsigned int i = 0; i < nd->mNumChildren; ++i) { + CollectNewChildren(nd->mChildren[i], child_nodes); + nd->mChildren[i] = nullptr; + } - // Check whether we need this node; if not we can replace it by our own children (warn, danger of incest). - if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end() ) { - for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end();) { + // Check whether we need this node; if not we can replace it by our own children (warn, danger of incest). + if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end()) { + for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end();) { - if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) { - (*it)->mTransformation = nd->mTransformation * (*it)->mTransformation; - nodes.push_back(*it); + if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) { + (*it)->mTransformation = nd->mTransformation * (*it)->mTransformation; + nodes.push_back(*it); - it = child_nodes.erase(it); - continue; - } - ++it; - } + it = child_nodes.erase(it); + continue; + } + ++it; + } - if (nd->mNumMeshes || !child_nodes.empty()) { - nodes.push_back(nd); - } else { - delete nd; /* bye, node */ - return; - } - } else { + if (nd->mNumMeshes || !child_nodes.empty()) { + nodes.push_back(nd); + } else { + delete nd; /* bye, node */ + return; + } + } else { - // Retain our current position in the hierarchy - nodes.push_back(nd); + // Retain our current position in the hierarchy + nodes.push_back(nd); - // Now check for possible optimizations in our list of child nodes. join as many as possible - aiNode* join_master = NULL; - aiMatrix4x4 inv; + // Now check for possible optimizations in our list of child nodes. join as many as possible + aiNode *join_master = NULL; + aiMatrix4x4 inv; - const LockedSetType::const_iterator end = locked.end(); + const LockedSetType::const_iterator end = locked.end(); - std::list join; - for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end();) { - aiNode* child = *it; - if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) { + std::list join; + for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end();) { + aiNode *child = *it; + if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) { - // There may be no instanced meshes - unsigned int n = 0; - for (; n < child->mNumMeshes;++n) { - if (meshes[child->mMeshes[n]] > 1) { - break; - } - } - if (n == child->mNumMeshes) { - if (!join_master) { - join_master = child; - inv = join_master->mTransformation; - inv.Inverse(); - } else { - child->mTransformation = inv * child->mTransformation ; + // There may be no instanced meshes + unsigned int n = 0; + for (; n < child->mNumMeshes; ++n) { + if (meshes[child->mMeshes[n]] > 1) { + break; + } + } + if (n == child->mNumMeshes) { + if (!join_master) { + join_master = child; + inv = join_master->mTransformation; + inv.Inverse(); + } else { + child->mTransformation = inv * child->mTransformation; - join.push_back(child); - it = child_nodes.erase(it); - continue; - } - } - } - ++it; - } - if (join_master && !join.empty()) { - join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i",count_merged++); + join.push_back(child); + it = child_nodes.erase(it); + continue; + } + } + } + ++it; + } + if (join_master && !join.empty()) { + join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i", count_merged++); - unsigned int out_meshes = 0; - for (std::list::iterator it = join.begin(); it != join.end(); ++it) { - out_meshes += (*it)->mNumMeshes; - } + unsigned int out_meshes = 0; + for (std::list::iterator it = join.begin(); it != join.end(); ++it) { + out_meshes += (*it)->mNumMeshes; + } - // copy all mesh references in one array - if (out_meshes) { - unsigned int* meshes = new unsigned int[out_meshes+join_master->mNumMeshes], *tmp = meshes; - for (unsigned int n = 0; n < join_master->mNumMeshes;++n) { - *tmp++ = join_master->mMeshes[n]; - } + // copy all mesh references in one array + if (out_meshes) { + unsigned int *meshes = new unsigned int[out_meshes + join_master->mNumMeshes], *tmp = meshes; + for (unsigned int n = 0; n < join_master->mNumMeshes; ++n) { + *tmp++ = join_master->mMeshes[n]; + } - for (std::list::iterator it = join.begin(); it != join.end(); ++it) { - for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) { + for (std::list::iterator it = join.begin(); it != join.end(); ++it) { + for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) { - *tmp = (*it)->mMeshes[n]; - aiMesh* mesh = mScene->mMeshes[*tmp++]; + *tmp = (*it)->mMeshes[n]; + aiMesh *mesh = mScene->mMeshes[*tmp++]; - // manually move the mesh into the right coordinate system - const aiMatrix3x3 IT = aiMatrix3x3( (*it)->mTransformation ).Inverse().Transpose(); - for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { + // manually move the mesh into the right coordinate system + const aiMatrix3x3 IT = aiMatrix3x3((*it)->mTransformation).Inverse().Transpose(); + for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { - mesh->mVertices[a] *= (*it)->mTransformation; + mesh->mVertices[a] *= (*it)->mTransformation; - if (mesh->HasNormals()) - mesh->mNormals[a] *= IT; + if (mesh->HasNormals()) + mesh->mNormals[a] *= IT; - if (mesh->HasTangentsAndBitangents()) { - mesh->mTangents[a] *= IT; - mesh->mBitangents[a] *= IT; - } - } - } - delete *it; // bye, node - } - delete[] join_master->mMeshes; - join_master->mMeshes = meshes; - join_master->mNumMeshes += out_meshes; - } - } - } - // reassign children if something changed - if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) { + if (mesh->HasTangentsAndBitangents()) { + mesh->mTangents[a] *= IT; + mesh->mBitangents[a] *= IT; + } + } + } + delete *it; // bye, node + } + delete[] join_master->mMeshes; + join_master->mMeshes = meshes; + join_master->mNumMeshes += out_meshes; + } + } + } + // reassign children if something changed + if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) { - delete[] nd->mChildren; + delete[] nd->mChildren; - if (!child_nodes.empty()) { - nd->mChildren = new aiNode*[child_nodes.size()]; - } - else nd->mChildren = nullptr; - } + if (!child_nodes.empty()) { + nd->mChildren = new aiNode *[child_nodes.size()]; + } else + nd->mChildren = nullptr; + } - nd->mNumChildren = static_cast(child_nodes.size()); + nd->mNumChildren = static_cast(child_nodes.size()); - if (nd->mChildren) { - aiNode** tmp = nd->mChildren; - for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) { - aiNode* node = *tmp++ = *it; - node->mParent = nd; - } - } + if (nd->mChildren) { + aiNode **tmp = nd->mChildren; + for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) { + aiNode *node = *tmp++ = *it; + node->mParent = nd; + } + } - nodes_out += static_cast(child_nodes.size()); + nodes_out += static_cast(child_nodes.size()); } // ------------------------------------------------------------------------------------------------ // Execute the post-processing step on the given scene -void OptimizeGraphProcess::Execute( aiScene* pScene) { - ASSIMP_LOG_DEBUG("OptimizeGraphProcess begin"); - nodes_in = nodes_out = count_merged = 0; - mScene = pScene; +void OptimizeGraphProcess::Execute(aiScene *pScene) { + ASSIMP_LOG_DEBUG("OptimizeGraphProcess begin"); + nodes_in = nodes_out = count_merged = 0; + mScene = pScene; - meshes.resize(pScene->mNumMeshes,0); - FindInstancedMeshes(pScene->mRootNode); + meshes.resize(pScene->mNumMeshes, 0); + FindInstancedMeshes(pScene->mRootNode); - // build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it - locked.clear(); - for (std::list::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) { + // build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it + locked.clear(); + for (std::list::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) { #ifdef AI_OG_USE_HASHING - locked.insert(SuperFastHash((*it).c_str())); + locked.insert(SuperFastHash((*it).c_str())); #else - locked.insert(*it); + locked.insert(*it); #endif - } + } - for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) { - for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) { - aiNodeAnim* anim = pScene->mAnimations[i]->mChannels[a]; - locked.insert(AI_OG_GETKEY(anim->mNodeName)); - } - } + for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) { + for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) { + aiNodeAnim *anim = pScene->mAnimations[i]->mChannels[a]; + locked.insert(AI_OG_GETKEY(anim->mNodeName)); + } + } - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) { + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) { - aiBone* bone = pScene->mMeshes[i]->mBones[a]; - locked.insert(AI_OG_GETKEY(bone->mName)); + aiBone *bone = pScene->mMeshes[i]->mBones[a]; + locked.insert(AI_OG_GETKEY(bone->mName)); - // HACK: Meshes referencing bones may not be transformed; we need to look them. - // The easiest way to do this is to increase their reference counters ... - meshes[i] += 2; - } - } + // HACK: Meshes referencing bones may not be transformed; we need to look them. + // The easiest way to do this is to increase their reference counters ... + meshes[i] += 2; + } + } - for (unsigned int i = 0; i < pScene->mNumCameras; ++i) { - aiCamera* cam = pScene->mCameras[i]; - locked.insert(AI_OG_GETKEY(cam->mName)); - } + for (unsigned int i = 0; i < pScene->mNumCameras; ++i) { + aiCamera *cam = pScene->mCameras[i]; + locked.insert(AI_OG_GETKEY(cam->mName)); + } - for (unsigned int i = 0; i < pScene->mNumLights; ++i) { - aiLight* lgh = pScene->mLights[i]; - locked.insert(AI_OG_GETKEY(lgh->mName)); - } + for (unsigned int i = 0; i < pScene->mNumLights; ++i) { + aiLight *lgh = pScene->mLights[i]; + locked.insert(AI_OG_GETKEY(lgh->mName)); + } - // Insert a dummy master node and make it read-only - aiNode* dummy_root = new aiNode(AI_RESERVED_NODE_NAME); - locked.insert(AI_OG_GETKEY(dummy_root->mName)); + // Insert a dummy master node and make it read-only + aiNode *dummy_root = new aiNode(AI_RESERVED_NODE_NAME); + locked.insert(AI_OG_GETKEY(dummy_root->mName)); - const aiString prev = pScene->mRootNode->mName; - pScene->mRootNode->mParent = dummy_root; + const aiString prev = pScene->mRootNode->mName; + pScene->mRootNode->mParent = dummy_root; - dummy_root->mChildren = new aiNode*[dummy_root->mNumChildren = 1]; - dummy_root->mChildren[0] = pScene->mRootNode; + dummy_root->mChildren = new aiNode *[dummy_root->mNumChildren = 1]; + dummy_root->mChildren[0] = pScene->mRootNode; - // Do our recursive processing of scenegraph nodes. For each node collect - // a fully new list of children and allow their children to place themselves - // on the same hierarchy layer as their parents. - std::list nodes; - CollectNewChildren (dummy_root,nodes); + // Do our recursive processing of scenegraph nodes. For each node collect + // a fully new list of children and allow their children to place themselves + // on the same hierarchy layer as their parents. + std::list nodes; + CollectNewChildren(dummy_root, nodes); - ai_assert(nodes.size() == 1); + ai_assert(nodes.size() == 1); - if (dummy_root->mNumChildren == 0) { - pScene->mRootNode = NULL; - throw DeadlyImportError("After optimizing the scene graph, no data remains"); - } + if (dummy_root->mNumChildren == 0) { + pScene->mRootNode = NULL; + throw DeadlyImportError("After optimizing the scene graph, no data remains"); + } - if (dummy_root->mNumChildren > 1) { - pScene->mRootNode = dummy_root; + if (dummy_root->mNumChildren > 1) { + pScene->mRootNode = dummy_root; - // Keep the dummy node but assign the name of the old root node to it - pScene->mRootNode->mName = prev; - } - else { + // Keep the dummy node but assign the name of the old root node to it + pScene->mRootNode->mName = prev; + } else { - // Remove the dummy root node again. - pScene->mRootNode = dummy_root->mChildren[0]; + // Remove the dummy root node again. + pScene->mRootNode = dummy_root->mChildren[0]; - dummy_root->mChildren[0] = NULL; - delete dummy_root; - } + dummy_root->mChildren[0] = NULL; + delete dummy_root; + } - pScene->mRootNode->mParent = NULL; - if (!DefaultLogger::isNullLogger()) { - if ( nodes_in != nodes_out) { - ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out); - } else { - ASSIMP_LOG_DEBUG("OptimizeGraphProcess finished"); - } - } - meshes.clear(); - locked.clear(); + pScene->mRootNode->mParent = NULL; + if (!DefaultLogger::isNullLogger()) { + if (nodes_in != nodes_out) { + ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out); + } else { + ASSIMP_LOG_DEBUG("OptimizeGraphProcess finished"); + } + } + meshes.clear(); + locked.clear(); } // ------------------------------------------------------------------------------------------------ // Build a LUT of all instanced meshes -void OptimizeGraphProcess::FindInstancedMeshes (aiNode* pNode) -{ - for (unsigned int i = 0; i < pNode->mNumMeshes;++i) { - ++meshes[pNode->mMeshes[i]]; - } +void OptimizeGraphProcess::FindInstancedMeshes(aiNode *pNode) { + for (unsigned int i = 0; i < pNode->mNumMeshes; ++i) { + ++meshes[pNode->mMeshes[i]]; + } - for (unsigned int i = 0; i < pNode->mNumChildren; ++i) - FindInstancedMeshes(pNode->mChildren[i]); + for (unsigned int i = 0; i < pNode->mNumChildren; ++i) + FindInstancedMeshes(pNode->mChildren[i]); } #endif // !! ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS From 193b02cdac6cf38ad87d57c20e8e19da33157e0f Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 9 Dec 2019 10:42:50 +0000 Subject: [PATCH 134/170] Odd negative scale: OptimizeGraph OptimizeGraph postprocessing now reverses face order when node scale is mirroring. Fixes flip to backfacing in models that mirrored some nodes. (Odd count of negative scale components, negative determinant) --- code/PostProcessing/ConvertToLHProcess.h | 5 ++-- code/PostProcessing/OptimizeGraph.cpp | 32 ++++++++++++++++-------- code/PostProcessing/OptimizeGraph.h | 6 ++--- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/code/PostProcessing/ConvertToLHProcess.h b/code/PostProcessing/ConvertToLHProcess.h index f32b91fc3..0c4a3a091 100644 --- a/code/PostProcessing/ConvertToLHProcess.h +++ b/code/PostProcessing/ConvertToLHProcess.h @@ -137,8 +137,9 @@ public: // ------------------------------------------------------------------- void Execute( aiScene* pScene); -protected: - void ProcessMesh( aiMesh* pMesh); +public: + /** Some other types of post-processing require winding order flips */ + static void ProcessMesh( aiMesh* pMesh); }; // --------------------------------------------------------------------------- diff --git a/code/PostProcessing/OptimizeGraph.cpp b/code/PostProcessing/OptimizeGraph.cpp index 709f465e2..43bd7a3ee 100644 --- a/code/PostProcessing/OptimizeGraph.cpp +++ b/code/PostProcessing/OptimizeGraph.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "OptimizeGraph.h" #include "ProcessHelper.h" +#include "ConvertToLHProcess.h" #include #include #include @@ -135,7 +136,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n nodes.push_back(nd); // Now check for possible optimizations in our list of child nodes. join as many as possible - aiNode *join_master = NULL; + aiNode *join_master = nullptr; aiMatrix4x4 inv; const LockedSetType::const_iterator end = locked.end(); @@ -172,7 +173,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n join_master->mName.length = ::ai_snprintf(join_master->mName.data, MAXLEN, "$MergedNode_%i", count_merged++); unsigned int out_meshes = 0; - for (std::list::iterator it = join.begin(); it != join.end(); ++it) { + for (std::list::const_iterator it = join.cbegin(); it != join.cend(); ++it) { out_meshes += (*it)->mNumMeshes; } @@ -183,17 +184,26 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n *tmp++ = join_master->mMeshes[n]; } - for (std::list::iterator it = join.begin(); it != join.end(); ++it) { - for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) { + for (const aiNode *join_node : join) { + for (unsigned int n = 0; n < join_node->mNumMeshes; ++n) { - *tmp = (*it)->mMeshes[n]; + *tmp = join_node->mMeshes[n]; aiMesh *mesh = mScene->mMeshes[*tmp++]; + // Assume the transformation is affine // manually move the mesh into the right coordinate system - const aiMatrix3x3 IT = aiMatrix3x3((*it)->mTransformation).Inverse().Transpose(); + + // Check for odd negative scale (mirror) + if (join_node->mTransformation.Determinant() < 0) { + // Reverse the mesh face winding order + FlipWindingOrderProcess::ProcessMesh(mesh); + } + + // Update positions, normals and tangents + const aiMatrix3x3 IT = aiMatrix3x3(join_node->mTransformation).Inverse().Transpose(); for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { - mesh->mVertices[a] *= (*it)->mTransformation; + mesh->mVertices[a] *= join_node->mTransformation; if (mesh->HasNormals()) mesh->mNormals[a] *= IT; @@ -204,7 +214,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n } } } - delete *it; // bye, node + delete join_node; // bye, node } delete[] join_master->mMeshes; join_master->mMeshes = meshes; @@ -304,7 +314,7 @@ void OptimizeGraphProcess::Execute(aiScene *pScene) { ai_assert(nodes.size() == 1); if (dummy_root->mNumChildren == 0) { - pScene->mRootNode = NULL; + pScene->mRootNode = nullptr; throw DeadlyImportError("After optimizing the scene graph, no data remains"); } @@ -318,11 +328,11 @@ void OptimizeGraphProcess::Execute(aiScene *pScene) { // Remove the dummy root node again. pScene->mRootNode = dummy_root->mChildren[0]; - dummy_root->mChildren[0] = NULL; + dummy_root->mChildren[0] = nullptr; delete dummy_root; } - pScene->mRootNode->mParent = NULL; + pScene->mRootNode->mParent = nullptr; if (!DefaultLogger::isNullLogger()) { if (nodes_in != nodes_out) { ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out); diff --git a/code/PostProcessing/OptimizeGraph.h b/code/PostProcessing/OptimizeGraph.h index 82cc5db3f..d2a6de9a2 100644 --- a/code/PostProcessing/OptimizeGraph.h +++ b/code/PostProcessing/OptimizeGraph.h @@ -75,13 +75,13 @@ public: ~OptimizeGraphProcess(); // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; + bool IsActive( unsigned int pFlags) const override; // ------------------------------------------------------------------- - void Execute( aiScene* pScene); + void Execute( aiScene* pScene) override; // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); + void SetupProperties(const Importer* pImp) override; // ------------------------------------------------------------------- /** @brief Add a list of node names to be locked and not modified. From 9cabeddf4f85c12df950673c29115e3a1a299099 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 9 Dec 2019 11:07:13 +0000 Subject: [PATCH 135/170] Odd Negative Scale: PretransformVertices PretransformVertices postprocessing now reverses face order when transform is mirroring. Fixes flip to backfacing in models that mirrored some nodes. (Odd count of negative scale components, negative determinant) --- code/PostProcessing/PretransformVertices.cpp | 1038 +++++++++--------- code/PostProcessing/PretransformVertices.h | 142 +-- 2 files changed, 570 insertions(+), 610 deletions(-) diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index 52001a057..fb6b458d8 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -45,11 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the "PretransformVertices" post processing step */ - #include "PretransformVertices.h" +#include "ConvertToLHProcess.h" #include "ProcessHelper.h" -#include #include +#include using namespace Assimp; @@ -59,670 +59,630 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -PretransformVertices::PretransformVertices() -: configKeepHierarchy (false) -, configNormalize(false) -, configTransform(false) -, configTransformation() -, mConfigPointCloud( false ) { - // empty +PretransformVertices::PretransformVertices() : + configKeepHierarchy(false), + configNormalize(false), + configTransform(false), + configTransformation(), + mConfigPointCloud(false) { + // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well PretransformVertices::~PretransformVertices() { - // nothing to do here + // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool PretransformVertices::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_PreTransformVertices) != 0; +bool PretransformVertices::IsActive(unsigned int pFlags) const { + return (pFlags & aiProcess_PreTransformVertices) != 0; } // ------------------------------------------------------------------------------------------------ // Setup import configuration -void PretransformVertices::SetupProperties(const Importer* pImp) -{ - // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE, - // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION - configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0)); - configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE,0)); - configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0)); +void PretransformVertices::SetupProperties(const Importer *pImp) { + // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY, AI_CONFIG_PP_PTV_NORMALIZE, + // AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION and AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION + configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY, 0)); + configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE, 0)); + configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION, 0)); - configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); + configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); - mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); + mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS); } // ------------------------------------------------------------------------------------------------ // Count the number of nodes -unsigned int PretransformVertices::CountNodes( aiNode* pcNode ) -{ - unsigned int iRet = 1; - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) - { - iRet += CountNodes(pcNode->mChildren[i]); - } - return iRet; +unsigned int PretransformVertices::CountNodes(const aiNode *pcNode) const { + unsigned int iRet = 1; + for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) { + iRet += CountNodes(pcNode->mChildren[i]); + } + return iRet; } // ------------------------------------------------------------------------------------------------ // Get a bitwise combination identifying the vertex format of a mesh -unsigned int PretransformVertices::GetMeshVFormat( aiMesh* pcMesh ) -{ - // the vertex format is stored in aiMesh::mBones for later retrieval. - // there isn't a good reason to compute it a few hundred times - // from scratch. The pointer is unused as animations are lost - // during PretransformVertices. - if (pcMesh->mBones) - return (unsigned int)(uint64_t)pcMesh->mBones; +unsigned int PretransformVertices::GetMeshVFormat(aiMesh *pcMesh) const { + // the vertex format is stored in aiMesh::mBones for later retrieval. + // there isn't a good reason to compute it a few hundred times + // from scratch. The pointer is unused as animations are lost + // during PretransformVertices. + if (pcMesh->mBones) + return (unsigned int)(uint64_t)pcMesh->mBones; + const unsigned int iRet = GetMeshVFormatUnique(pcMesh); - const unsigned int iRet = GetMeshVFormatUnique(pcMesh); - - // store the value for later use - pcMesh->mBones = (aiBone**)(uint64_t)iRet; - return iRet; + // store the value for later use + pcMesh->mBones = (aiBone **)(uint64_t)iRet; + return iRet; } // ------------------------------------------------------------------------------------------------ // Count the number of vertices in the whole scene and a given // material index -void PretransformVertices::CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat, - unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices) -{ - for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) - { - aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; - if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) - { - *piVertices += pcMesh->mNumVertices; - *piFaces += pcMesh->mNumFaces; - } - } - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) - { - CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat, - iVFormat,piFaces,piVertices); - } +void PretransformVertices::CountVerticesAndFaces(const aiScene *pcScene, const aiNode *pcNode, unsigned int iMat, + unsigned int iVFormat, unsigned int *piFaces, unsigned int *piVertices) const { + for (unsigned int i = 0; i < pcNode->mNumMeshes; ++i) { + aiMesh *pcMesh = pcScene->mMeshes[pcNode->mMeshes[i]]; + if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) { + *piVertices += pcMesh->mNumVertices; + *piFaces += pcMesh->mNumFaces; + } + } + for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) { + CountVerticesAndFaces(pcScene, pcNode->mChildren[i], iMat, + iVFormat, piFaces, piVertices); + } } // ------------------------------------------------------------------------------------------------ // Collect vertex/face data -void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat, - unsigned int iVFormat, aiMesh* pcMeshOut, - unsigned int aiCurrent[2], unsigned int* num_refs) -{ - // No need to multiply if there's no transformation - const bool identity = pcNode->mTransformation.IsIdentity(); - for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) - { - aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; - if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) - { - // Decrement mesh reference counter - unsigned int& num_ref = num_refs[pcNode->mMeshes[i]]; - ai_assert(0 != num_ref); - --num_ref; - // Save the name of the last mesh - if (num_ref==0) - { - pcMeshOut->mName = pcMesh->mName; - } +void PretransformVertices::CollectData(const aiScene *pcScene, const aiNode *pcNode, unsigned int iMat, + unsigned int iVFormat, aiMesh *pcMeshOut, + unsigned int aiCurrent[2], unsigned int *num_refs) const { + // No need to multiply if there's no transformation + const bool identity = pcNode->mTransformation.IsIdentity(); + for (unsigned int i = 0; i < pcNode->mNumMeshes; ++i) { + aiMesh *pcMesh = pcScene->mMeshes[pcNode->mMeshes[i]]; + if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) { + // Decrement mesh reference counter + unsigned int &num_ref = num_refs[pcNode->mMeshes[i]]; + ai_assert(0 != num_ref); + --num_ref; + // Save the name of the last mesh + if (num_ref == 0) { + pcMeshOut->mName = pcMesh->mName; + } - if (identity) { - // copy positions without modifying them - ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mVertices, - pcMesh->mNumVertices * sizeof(aiVector3D)); + if (identity) { + // copy positions without modifying them + ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX], + pcMesh->mVertices, + pcMesh->mNumVertices * sizeof(aiVector3D)); - if (iVFormat & 0x2) { - // copy normals without modifying them - ::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mNormals, - pcMesh->mNumVertices * sizeof(aiVector3D)); - } - if (iVFormat & 0x4) - { - // copy tangents without modifying them - ::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mTangents, - pcMesh->mNumVertices * sizeof(aiVector3D)); - // copy bitangents without modifying them - ::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mBitangents, - pcMesh->mNumVertices * sizeof(aiVector3D)); - } - } - else - { - // copy positions, transform them to worldspace - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n]; - } - aiMatrix4x4 mWorldIT = pcNode->mTransformation; - mWorldIT.Inverse().Transpose(); + if (iVFormat & 0x2) { + // copy normals without modifying them + ::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX], + pcMesh->mNormals, + pcMesh->mNumVertices * sizeof(aiVector3D)); + } + if (iVFormat & 0x4) { + // copy tangents without modifying them + ::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX], + pcMesh->mTangents, + pcMesh->mNumVertices * sizeof(aiVector3D)); + // copy bitangents without modifying them + ::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX], + pcMesh->mBitangents, + pcMesh->mNumVertices * sizeof(aiVector3D)); + } + } else { + // copy positions, transform them to worldspace + for (unsigned int n = 0; n < pcMesh->mNumVertices; ++n) { + pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX] + n] = pcNode->mTransformation * pcMesh->mVertices[n]; + } + aiMatrix4x4 mWorldIT = pcNode->mTransformation; + mWorldIT.Inverse().Transpose(); - // TODO: implement Inverse() for aiMatrix3x3 - aiMatrix3x3 m = aiMatrix3x3(mWorldIT); + // TODO: implement Inverse() for aiMatrix3x3 + aiMatrix3x3 m = aiMatrix3x3(mWorldIT); - if (iVFormat & 0x2) - { - // copy normals, transform them to worldspace - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] = - (m * pcMesh->mNormals[n]).Normalize(); - } - } - if (iVFormat & 0x4) - { - // copy tangents and bitangents, transform them to worldspace - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mTangents[n]).Normalize(); - pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = (m * pcMesh->mBitangents[n]).Normalize(); - } - } - } - unsigned int p = 0; - while (iVFormat & (0x100 << p)) - { - // copy texture coordinates - memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mTextureCoords[p], - pcMesh->mNumVertices * sizeof(aiVector3D)); - ++p; - } - p = 0; - while (iVFormat & (0x1000000 << p)) - { - // copy vertex colors - memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mColors[p], - pcMesh->mNumVertices * sizeof(aiColor4D)); - ++p; - } - // now we need to copy all faces. since we will delete the source mesh afterwards, - // we don't need to reallocate the array of indices except if this mesh is - // referenced multiple times. - for (unsigned int planck = 0;planck < pcMesh->mNumFaces;++planck) - { - aiFace& f_src = pcMesh->mFaces[planck]; - aiFace& f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck]; + if (iVFormat & 0x2) { + // copy normals, transform them to worldspace + for (unsigned int n = 0; n < pcMesh->mNumVertices; ++n) { + pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX] + n] = + (m * pcMesh->mNormals[n]).Normalize(); + } + } + if (iVFormat & 0x4) { + // copy tangents and bitangents, transform them to worldspace + for (unsigned int n = 0; n < pcMesh->mNumVertices; ++n) { + pcMeshOut->mTangents[aiCurrent[AI_PTVS_VERTEX] + n] = (m * pcMesh->mTangents[n]).Normalize(); + pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX] + n] = (m * pcMesh->mBitangents[n]).Normalize(); + } + } + } + unsigned int p = 0; + while (iVFormat & (0x100 << p)) { + // copy texture coordinates + memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX], + pcMesh->mTextureCoords[p], + pcMesh->mNumVertices * sizeof(aiVector3D)); + ++p; + } + p = 0; + while (iVFormat & (0x1000000 << p)) { + // copy vertex colors + memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX], + pcMesh->mColors[p], + pcMesh->mNumVertices * sizeof(aiColor4D)); + ++p; + } + // now we need to copy all faces. since we will delete the source mesh afterwards, + // we don't need to reallocate the array of indices except if this mesh is + // referenced multiple times. + for (unsigned int planck = 0; planck < pcMesh->mNumFaces; ++planck) { + aiFace &f_src = pcMesh->mFaces[planck]; + aiFace &f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE] + planck]; - const unsigned int num_idx = f_src.mNumIndices; + const unsigned int num_idx = f_src.mNumIndices; - f_dst.mNumIndices = num_idx; + f_dst.mNumIndices = num_idx; - unsigned int* pi; - if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */ - pi = f_dst.mIndices = f_src.mIndices; + unsigned int *pi; + if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */ + pi = f_dst.mIndices = f_src.mIndices; - // offset all vertex indices - for (unsigned int hahn = 0; hahn < num_idx;++hahn){ - pi[hahn] += aiCurrent[AI_PTVS_VERTEX]; - } - } - else { - pi = f_dst.mIndices = new unsigned int[num_idx]; + // offset all vertex indices + for (unsigned int hahn = 0; hahn < num_idx; ++hahn) { + pi[hahn] += aiCurrent[AI_PTVS_VERTEX]; + } + } else { + pi = f_dst.mIndices = new unsigned int[num_idx]; - // copy and offset all vertex indices - for (unsigned int hahn = 0; hahn < num_idx;++hahn){ - pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX]; - } - } + // copy and offset all vertex indices + for (unsigned int hahn = 0; hahn < num_idx; ++hahn) { + pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX]; + } + } - // Update the mPrimitiveTypes member of the mesh - switch (pcMesh->mFaces[planck].mNumIndices) - { - case 0x1: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 0x2: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 0x3: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - }; - } - aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices; - aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces; - } - } + // Update the mPrimitiveTypes member of the mesh + switch (pcMesh->mFaces[planck].mNumIndices) { + case 0x1: + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 0x2: + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 0x3: + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + break; + }; + } + aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices; + aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces; + } + } - // append all children of us - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) { - CollectData(pcScene,pcNode->mChildren[i],iMat, - iVFormat,pcMeshOut,aiCurrent,num_refs); - } + // append all children of us + for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) { + CollectData(pcScene, pcNode->mChildren[i], iMat, + iVFormat, pcMeshOut, aiCurrent, num_refs); + } } // ------------------------------------------------------------------------------------------------ // Get a list of all vertex formats that occur for a given material index // The output list contains duplicate elements -void PretransformVertices::GetVFormatList( aiScene* pcScene, unsigned int iMat, - std::list& aiOut) -{ - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { - aiMesh* pcMesh = pcScene->mMeshes[ i ]; - if (iMat == pcMesh->mMaterialIndex) { - aiOut.push_back(GetMeshVFormat(pcMesh)); - } - } +void PretransformVertices::GetVFormatList(const aiScene *pcScene, unsigned int iMat, + std::list &aiOut) const { + for (unsigned int i = 0; i < pcScene->mNumMeshes; ++i) { + aiMesh *pcMesh = pcScene->mMeshes[i]; + if (iMat == pcMesh->mMaterialIndex) { + aiOut.push_back(GetMeshVFormat(pcMesh)); + } + } } // ------------------------------------------------------------------------------------------------ // Compute the absolute transformation matrices of each node -void PretransformVertices::ComputeAbsoluteTransform( aiNode* pcNode ) -{ - if (pcNode->mParent) { - pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation; - } +void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) { + if (pcNode->mParent) { + pcNode->mTransformation = pcNode->mParent->mTransformation * pcNode->mTransformation; + } - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) { - ComputeAbsoluteTransform(pcNode->mChildren[i]); - } + for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) { + ComputeAbsoluteTransform(pcNode->mChildren[i]); + } } // ------------------------------------------------------------------------------------------------ // Apply the node transformation to a mesh -void PretransformVertices::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat) -{ - // Check whether we need to transform the coordinates at all - if (!mat.IsIdentity()) { +void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const { + // Check whether we need to transform the coordinates at all + if (!mat.IsIdentity()) { - if (mesh->HasPositions()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mVertices[i] = mat * mesh->mVertices[i]; - } - } - if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { - aiMatrix4x4 mWorldIT = mat; - mWorldIT.Inverse().Transpose(); + // Check for odd negative scale (mirror) + if (mesh->HasFaces() && mat.Determinant() < 0) { + // Reverse the mesh face winding order + FlipWindingOrderProcess::ProcessMesh(mesh); + } - // TODO: implement Inverse() for aiMatrix3x3 - aiMatrix3x3 m = aiMatrix3x3(mWorldIT); + // Update positions + if (mesh->HasPositions()) { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mVertices[i] = mat * mesh->mVertices[i]; + } + } - if (mesh->HasNormals()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize(); - } - } - if (mesh->HasTangentsAndBitangents()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); - mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); - } - } - } - } + // Update normals and tangents + if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { + const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose(); + + if (mesh->HasNormals()) { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize(); + } + } + if (mesh->HasTangentsAndBitangents()) { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); + mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); + } + } + } + } } // ------------------------------------------------------------------------------------------------ // Simple routine to build meshes in worldspace, no further optimization -void PretransformVertices::BuildWCSMeshes(std::vector& out, aiMesh** in, - unsigned int numIn, aiNode* node) -{ - // NOTE: - // aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy - // aiMesh::mBones store reference to abs. transform we multiplied with +void PretransformVertices::BuildWCSMeshes(std::vector &out, aiMesh **in, + unsigned int numIn, aiNode *node) const { + // NOTE: + // aiMesh::mNumBones store original source mesh, or UINT_MAX if not a copy + // aiMesh::mBones store reference to abs. transform we multiplied with - // process meshes - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - aiMesh* mesh = in[node->mMeshes[i]]; + // process meshes + for (unsigned int i = 0; i < node->mNumMeshes; ++i) { + aiMesh *mesh = in[node->mMeshes[i]]; - // check whether we can operate on this mesh - if (!mesh->mBones || *reinterpret_cast(mesh->mBones) == node->mTransformation) { - // yes, we can. - mesh->mBones = reinterpret_cast (&node->mTransformation); - mesh->mNumBones = UINT_MAX; - } - else { + // check whether we can operate on this mesh + if (!mesh->mBones || *reinterpret_cast(mesh->mBones) == node->mTransformation) { + // yes, we can. + mesh->mBones = reinterpret_cast(&node->mTransformation); + mesh->mNumBones = UINT_MAX; + } else { - // try to find us in the list of newly created meshes - for (unsigned int n = 0; n < out.size(); ++n) { - aiMesh* ctz = out[n]; - if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast(ctz->mBones) == node->mTransformation) { + // try to find us in the list of newly created meshes + for (unsigned int n = 0; n < out.size(); ++n) { + aiMesh *ctz = out[n]; + if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast(ctz->mBones) == node->mTransformation) { - // ok, use this one. Update node mesh index - node->mMeshes[i] = numIn + n; - } - } - if (node->mMeshes[i] < numIn) { - // Worst case. Need to operate on a full copy of the mesh - ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms"); - aiMesh* ntz; + // ok, use this one. Update node mesh index + node->mMeshes[i] = numIn + n; + } + } + if (node->mMeshes[i] < numIn) { + // Worst case. Need to operate on a full copy of the mesh + ASSIMP_LOG_INFO("PretransformVertices: Copying mesh due to mismatching transforms"); + aiMesh *ntz; - const unsigned int tmp = mesh->mNumBones; // - mesh->mNumBones = 0; - SceneCombiner::Copy(&ntz,mesh); - mesh->mNumBones = tmp; + const unsigned int tmp = mesh->mNumBones; // + mesh->mNumBones = 0; + SceneCombiner::Copy(&ntz, mesh); + mesh->mNumBones = tmp; - ntz->mNumBones = node->mMeshes[i]; - ntz->mBones = reinterpret_cast (&node->mTransformation); + ntz->mNumBones = node->mMeshes[i]; + ntz->mBones = reinterpret_cast(&node->mTransformation); - out.push_back(ntz); + out.push_back(ntz); - node->mMeshes[i] = static_cast(numIn + out.size() - 1); - } - } - } + node->mMeshes[i] = static_cast(numIn + out.size() - 1); + } + } + } - // call children - for (unsigned int i = 0; i < node->mNumChildren;++i) - BuildWCSMeshes(out,in,numIn,node->mChildren[i]); + // call children + for (unsigned int i = 0; i < node->mNumChildren; ++i) + BuildWCSMeshes(out, in, numIn, node->mChildren[i]); } // ------------------------------------------------------------------------------------------------ // Reset transformation matrices to identity -void PretransformVertices::MakeIdentityTransform(aiNode* nd) -{ - nd->mTransformation = aiMatrix4x4(); +void PretransformVertices::MakeIdentityTransform(aiNode *nd) const { + nd->mTransformation = aiMatrix4x4(); - // call children - for (unsigned int i = 0; i < nd->mNumChildren;++i) - MakeIdentityTransform(nd->mChildren[i]); + // call children + for (unsigned int i = 0; i < nd->mNumChildren; ++i) + MakeIdentityTransform(nd->mChildren[i]); } // ------------------------------------------------------------------------------------------------ // Build reference counters for all meshes -void PretransformVertices::BuildMeshRefCountArray(aiNode* nd, unsigned int * refs) -{ - for (unsigned int i = 0; i< nd->mNumMeshes;++i) - refs[nd->mMeshes[i]]++; +void PretransformVertices::BuildMeshRefCountArray(const aiNode *nd, unsigned int *refs) const { + for (unsigned int i = 0; i < nd->mNumMeshes; ++i) + refs[nd->mMeshes[i]]++; - // call children - for (unsigned int i = 0; i < nd->mNumChildren;++i) - BuildMeshRefCountArray(nd->mChildren[i],refs); + // call children + for (unsigned int i = 0; i < nd->mNumChildren; ++i) + BuildMeshRefCountArray(nd->mChildren[i], refs); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void PretransformVertices::Execute( aiScene* pScene) -{ - ASSIMP_LOG_DEBUG("PretransformVerticesProcess begin"); +void PretransformVertices::Execute(aiScene *pScene) { + ASSIMP_LOG_DEBUG("PretransformVerticesProcess begin"); - // Return immediately if we have no meshes - if (!pScene->mNumMeshes) - return; + // Return immediately if we have no meshes + if (!pScene->mNumMeshes) + return; - const unsigned int iOldMeshes = pScene->mNumMeshes; - const unsigned int iOldAnimationChannels = pScene->mNumAnimations; - const unsigned int iOldNodes = CountNodes(pScene->mRootNode); + const unsigned int iOldMeshes = pScene->mNumMeshes; + const unsigned int iOldAnimationChannels = pScene->mNumAnimations; + const unsigned int iOldNodes = CountNodes(pScene->mRootNode); - if(configTransform) { - pScene->mRootNode->mTransformation = configTransformation; - } + if (configTransform) { + pScene->mRootNode->mTransformation = configTransformation; + } - // first compute absolute transformation matrices for all nodes - ComputeAbsoluteTransform(pScene->mRootNode); + // first compute absolute transformation matrices for all nodes + ComputeAbsoluteTransform(pScene->mRootNode); - // Delete aiMesh::mBones for all meshes. The bones are - // removed during this step and we need the pointer as - // temporary storage - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { - aiMesh* mesh = pScene->mMeshes[i]; + // Delete aiMesh::mBones for all meshes. The bones are + // removed during this step and we need the pointer as + // temporary storage + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + aiMesh *mesh = pScene->mMeshes[i]; - for (unsigned int a = 0; a < mesh->mNumBones;++a) - delete mesh->mBones[a]; + for (unsigned int a = 0; a < mesh->mNumBones; ++a) + delete mesh->mBones[a]; - delete[] mesh->mBones; - mesh->mBones = NULL; - } + delete[] mesh->mBones; + mesh->mBones = NULL; + } - // now build a list of output meshes - std::vector apcOutMeshes; + // now build a list of output meshes + std::vector apcOutMeshes; - // Keep scene hierarchy? It's an easy job in this case ... - // we go on and transform all meshes, if one is referenced by nodes - // with different absolute transformations a depth copy of the mesh - // is required. - if( configKeepHierarchy ) { + // Keep scene hierarchy? It's an easy job in this case ... + // we go on and transform all meshes, if one is referenced by nodes + // with different absolute transformations a depth copy of the mesh + // is required. + if (configKeepHierarchy) { - // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones - BuildWCSMeshes(apcOutMeshes,pScene->mMeshes,pScene->mNumMeshes, pScene->mRootNode); + // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones + BuildWCSMeshes(apcOutMeshes, pScene->mMeshes, pScene->mNumMeshes, pScene->mRootNode); - // ... if new meshes have been generated, append them to the end of the scene - if (apcOutMeshes.size() > 0) { - aiMesh** npp = new aiMesh*[pScene->mNumMeshes + apcOutMeshes.size()]; + // ... if new meshes have been generated, append them to the end of the scene + if (apcOutMeshes.size() > 0) { + aiMesh **npp = new aiMesh *[pScene->mNumMeshes + apcOutMeshes.size()]; - memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes); - memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size()); + memcpy(npp, pScene->mMeshes, sizeof(aiMesh *) * pScene->mNumMeshes); + memcpy(npp + pScene->mNumMeshes, &apcOutMeshes[0], sizeof(aiMesh *) * apcOutMeshes.size()); - pScene->mNumMeshes += static_cast(apcOutMeshes.size()); - delete[] pScene->mMeshes; pScene->mMeshes = npp; - } + pScene->mNumMeshes += static_cast(apcOutMeshes.size()); + delete[] pScene->mMeshes; + pScene->mMeshes = npp; + } - // now iterate through all meshes and transform them to worldspace - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - ApplyTransform(pScene->mMeshes[i],*reinterpret_cast( pScene->mMeshes[i]->mBones )); + // now iterate through all meshes and transform them to worldspace + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + ApplyTransform(pScene->mMeshes[i], *reinterpret_cast(pScene->mMeshes[i]->mBones)); - // prevent improper destruction - pScene->mMeshes[i]->mBones = NULL; - pScene->mMeshes[i]->mNumBones = 0; - } - } else { - apcOutMeshes.reserve(pScene->mNumMaterials<<1u); - std::list aiVFormats; + // prevent improper destruction + pScene->mMeshes[i]->mBones = NULL; + pScene->mMeshes[i]->mNumBones = 0; + } + } else { + apcOutMeshes.reserve(pScene->mNumMaterials << 1u); + std::list aiVFormats; - std::vector s(pScene->mNumMeshes,0); - BuildMeshRefCountArray(pScene->mRootNode,&s[0]); + std::vector s(pScene->mNumMeshes, 0); + BuildMeshRefCountArray(pScene->mRootNode, &s[0]); - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { - // get the list of all vertex formats for this material - aiVFormats.clear(); - GetVFormatList(pScene,i,aiVFormats); - aiVFormats.sort(); - aiVFormats.unique(); - for (std::list::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) { - unsigned int iVertices = 0; - unsigned int iFaces = 0; - CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices); - if (0 != iFaces && 0 != iVertices) - { - apcOutMeshes.push_back(new aiMesh()); - aiMesh* pcMesh = apcOutMeshes.back(); - pcMesh->mNumFaces = iFaces; - pcMesh->mNumVertices = iVertices; - pcMesh->mFaces = new aiFace[iFaces]; - pcMesh->mVertices = new aiVector3D[iVertices]; - pcMesh->mMaterialIndex = i; - if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices]; - if ((*j) & 0x4) - { - pcMesh->mTangents = new aiVector3D[iVertices]; - pcMesh->mBitangents = new aiVector3D[iVertices]; - } - iFaces = 0; - while ((*j) & (0x100 << iFaces)) - { - pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices]; - if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3; - else pcMesh->mNumUVComponents[iFaces] = 2; - iFaces++; - } - iFaces = 0; - while ((*j) & (0x1000000 << iFaces)) - pcMesh->mColors[iFaces++] = new aiColor4D[iVertices]; + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { + // get the list of all vertex formats for this material + aiVFormats.clear(); + GetVFormatList(pScene, i, aiVFormats); + aiVFormats.sort(); + aiVFormats.unique(); + for (std::list::const_iterator j = aiVFormats.begin(); j != aiVFormats.end(); ++j) { + unsigned int iVertices = 0; + unsigned int iFaces = 0; + CountVerticesAndFaces(pScene, pScene->mRootNode, i, *j, &iFaces, &iVertices); + if (0 != iFaces && 0 != iVertices) { + apcOutMeshes.push_back(new aiMesh()); + aiMesh *pcMesh = apcOutMeshes.back(); + pcMesh->mNumFaces = iFaces; + pcMesh->mNumVertices = iVertices; + pcMesh->mFaces = new aiFace[iFaces]; + pcMesh->mVertices = new aiVector3D[iVertices]; + pcMesh->mMaterialIndex = i; + if ((*j) & 0x2) pcMesh->mNormals = new aiVector3D[iVertices]; + if ((*j) & 0x4) { + pcMesh->mTangents = new aiVector3D[iVertices]; + pcMesh->mBitangents = new aiVector3D[iVertices]; + } + iFaces = 0; + while ((*j) & (0x100 << iFaces)) { + pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices]; + if ((*j) & (0x10000 << iFaces)) + pcMesh->mNumUVComponents[iFaces] = 3; + else + pcMesh->mNumUVComponents[iFaces] = 2; + iFaces++; + } + iFaces = 0; + while ((*j) & (0x1000000 << iFaces)) + pcMesh->mColors[iFaces++] = new aiColor4D[iVertices]; - // fill the mesh ... - unsigned int aiTemp[2] = {0,0}; - CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp,&s[0]); - } - } - } + // fill the mesh ... + unsigned int aiTemp[2] = { 0, 0 }; + CollectData(pScene, pScene->mRootNode, i, *j, pcMesh, aiTemp, &s[0]); + } + } + } - // If no meshes are referenced in the node graph it is possible that we get no output meshes. - if (apcOutMeshes.empty()) { - - throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes"); - } - else - { - // now delete all meshes in the scene and build a new mesh list - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - aiMesh* mesh = pScene->mMeshes[i]; - mesh->mNumBones = 0; - mesh->mBones = NULL; + // If no meshes are referenced in the node graph it is possible that we get no output meshes. + if (apcOutMeshes.empty()) { - // we're reusing the face index arrays. avoid destruction - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { - mesh->mFaces[a].mNumIndices = 0; - mesh->mFaces[a].mIndices = NULL; - } + throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes"); + } else { + // now delete all meshes in the scene and build a new mesh list + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + aiMesh *mesh = pScene->mMeshes[i]; + mesh->mNumBones = 0; + mesh->mBones = NULL; - delete mesh; + // we're reusing the face index arrays. avoid destruction + for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { + mesh->mFaces[a].mNumIndices = 0; + mesh->mFaces[a].mIndices = NULL; + } - // Invalidate the contents of the old mesh array. We will most - // likely have less output meshes now, so the last entries of - // the mesh array are not overridden. We set them to NULL to - // make sure the developer gets notified when his application - // attempts to access these fields ... - mesh = NULL; - } + delete mesh; - // It is impossible that we have more output meshes than - // input meshes, so we can easily reuse the old mesh array - pScene->mNumMeshes = (unsigned int)apcOutMeshes.size(); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { - pScene->mMeshes[i] = apcOutMeshes[i]; - } - } - } + // Invalidate the contents of the old mesh array. We will most + // likely have less output meshes now, so the last entries of + // the mesh array are not overridden. We set them to NULL to + // make sure the developer gets notified when his application + // attempts to access these fields ... + mesh = NULL; + } - // remove all animations from the scene - for (unsigned int i = 0; i < pScene->mNumAnimations;++i) - delete pScene->mAnimations[i]; - delete[] pScene->mAnimations; + // It is impossible that we have more output meshes than + // input meshes, so we can easily reuse the old mesh array + pScene->mNumMeshes = (unsigned int)apcOutMeshes.size(); + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + pScene->mMeshes[i] = apcOutMeshes[i]; + } + } + } - pScene->mAnimations = NULL; - pScene->mNumAnimations = 0; + // remove all animations from the scene + for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) + delete pScene->mAnimations[i]; + delete[] pScene->mAnimations; - // --- we need to keep all cameras and lights - for (unsigned int i = 0; i < pScene->mNumCameras;++i) - { - aiCamera* cam = pScene->mCameras[i]; - const aiNode* nd = pScene->mRootNode->FindNode(cam->mName); - ai_assert(NULL != nd); + pScene->mAnimations = NULL; + pScene->mNumAnimations = 0; - // multiply all properties of the camera with the absolute - // transformation of the corresponding node - cam->mPosition = nd->mTransformation * cam->mPosition; - cam->mLookAt = aiMatrix3x3( nd->mTransformation ) * cam->mLookAt; - cam->mUp = aiMatrix3x3( nd->mTransformation ) * cam->mUp; - } + // --- we need to keep all cameras and lights + for (unsigned int i = 0; i < pScene->mNumCameras; ++i) { + aiCamera *cam = pScene->mCameras[i]; + const aiNode *nd = pScene->mRootNode->FindNode(cam->mName); + ai_assert(NULL != nd); - for (unsigned int i = 0; i < pScene->mNumLights;++i) - { - aiLight* l = pScene->mLights[i]; - const aiNode* nd = pScene->mRootNode->FindNode(l->mName); - ai_assert(NULL != nd); + // multiply all properties of the camera with the absolute + // transformation of the corresponding node + cam->mPosition = nd->mTransformation * cam->mPosition; + cam->mLookAt = aiMatrix3x3(nd->mTransformation) * cam->mLookAt; + cam->mUp = aiMatrix3x3(nd->mTransformation) * cam->mUp; + } - // multiply all properties of the camera with the absolute - // transformation of the corresponding node - l->mPosition = nd->mTransformation * l->mPosition; - l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection; - l->mUp = aiMatrix3x3( nd->mTransformation ) * l->mUp; - } + for (unsigned int i = 0; i < pScene->mNumLights; ++i) { + aiLight *l = pScene->mLights[i]; + const aiNode *nd = pScene->mRootNode->FindNode(l->mName); + ai_assert(NULL != nd); - if( !configKeepHierarchy ) { + // multiply all properties of the camera with the absolute + // transformation of the corresponding node + l->mPosition = nd->mTransformation * l->mPosition; + l->mDirection = aiMatrix3x3(nd->mTransformation) * l->mDirection; + l->mUp = aiMatrix3x3(nd->mTransformation) * l->mUp; + } - // now delete all nodes in the scene and build a new - // flat node graph with a root node and some level 1 children - aiNode* newRoot = new aiNode(); - newRoot->mName = pScene->mRootNode->mName; - delete pScene->mRootNode; - pScene->mRootNode = newRoot; + if (!configKeepHierarchy) { - if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras) - { - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - } - else - { - pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras; - aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; + // now delete all nodes in the scene and build a new + // flat node graph with a root node and some level 1 children + aiNode *newRoot = new aiNode(); + newRoot->mName = pScene->mRootNode->mName; + delete pScene->mRootNode; + pScene->mRootNode = newRoot; - // generate mesh nodes - for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes) - { - aiNode* pcNode = new aiNode(); - *nodes = pcNode; - pcNode->mParent = pScene->mRootNode; - pcNode->mName = pScene->mMeshes[i]->mName; + if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras) { + pScene->mRootNode->mNumMeshes = 1; + pScene->mRootNode->mMeshes = new unsigned int[1]; + pScene->mRootNode->mMeshes[0] = 0; + } else { + pScene->mRootNode->mNumChildren = pScene->mNumMeshes + pScene->mNumLights + pScene->mNumCameras; + aiNode **nodes = pScene->mRootNode->mChildren = new aiNode *[pScene->mRootNode->mNumChildren]; - // setup mesh indices - pcNode->mNumMeshes = 1; - pcNode->mMeshes = new unsigned int[1]; - pcNode->mMeshes[0] = i; - } - // generate light nodes - for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes) - { - aiNode* pcNode = new aiNode(); - *nodes = pcNode; - pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "light_%u",i); - pScene->mLights[i]->mName = pcNode->mName; - } - // generate camera nodes - for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes) - { - aiNode* pcNode = new aiNode(); - *nodes = pcNode; - pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"cam_%u",i); - pScene->mCameras[i]->mName = pcNode->mName; - } - } - } - else { - // ... and finally set the transformation matrix of all nodes to identity - MakeIdentityTransform(pScene->mRootNode); - } + // generate mesh nodes + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++nodes) { + aiNode *pcNode = new aiNode(); + *nodes = pcNode; + pcNode->mParent = pScene->mRootNode; + pcNode->mName = pScene->mMeshes[i]->mName; - if (configNormalize) { - // compute the boundary of all meshes - aiVector3D min,max; - MinMaxChooser ()(min,max); + // setup mesh indices + pcNode->mNumMeshes = 1; + pcNode->mMeshes = new unsigned int[1]; + pcNode->mMeshes[0] = i; + } + // generate light nodes + for (unsigned int i = 0; i < pScene->mNumLights; ++i, ++nodes) { + aiNode *pcNode = new aiNode(); + *nodes = pcNode; + pcNode->mParent = pScene->mRootNode; + pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "light_%u", i); + pScene->mLights[i]->mName = pcNode->mName; + } + // generate camera nodes + for (unsigned int i = 0; i < pScene->mNumCameras; ++i, ++nodes) { + aiNode *pcNode = new aiNode(); + *nodes = pcNode; + pcNode->mParent = pScene->mRootNode; + pcNode->mName.length = ::ai_snprintf(pcNode->mName.data, MAXLEN, "cam_%u", i); + pScene->mCameras[i]->mName = pcNode->mName; + } + } + } else { + // ... and finally set the transformation matrix of all nodes to identity + MakeIdentityTransform(pScene->mRootNode); + } - for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { - aiMesh* m = pScene->mMeshes[a]; - for (unsigned int i = 0; i < m->mNumVertices;++i) { - min = std::min(m->mVertices[i],min); - max = std::max(m->mVertices[i],max); - } - } + if (configNormalize) { + // compute the boundary of all meshes + aiVector3D min, max; + MinMaxChooser()(min, max); - // find the dominant axis - aiVector3D d = max-min; - const ai_real div = std::max(d.x,std::max(d.y,d.z))*ai_real( 0.5); + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + aiMesh *m = pScene->mMeshes[a]; + for (unsigned int i = 0; i < m->mNumVertices; ++i) { + min = std::min(m->mVertices[i], min); + max = std::max(m->mVertices[i], max); + } + } - d = min + d * (ai_real)0.5; - for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { - aiMesh* m = pScene->mMeshes[a]; - for (unsigned int i = 0; i < m->mNumVertices;++i) { - m->mVertices[i] = (m->mVertices[i]-d)/div; - } - } - } + // find the dominant axis + aiVector3D d = max - min; + const ai_real div = std::max(d.x, std::max(d.y, d.z)) * ai_real(0.5); - // print statistics - if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished"); + d = min + d * (ai_real)0.5; + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + aiMesh *m = pScene->mMeshes[a]; + for (unsigned int i = 0; i < m->mNumVertices; ++i) { + m->mVertices[i] = (m->mVertices[i] - d) / div; + } + } + } - ASSIMP_LOG_INFO_F("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (", - CountNodes(pScene->mRootNode) ," output nodes)" ); - ASSIMP_LOG_INFO_F("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras." ); - ASSIMP_LOG_INFO_F("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); - } + // print statistics + if (!DefaultLogger::isNullLogger()) { + ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished"); + + ASSIMP_LOG_INFO_F("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (", + CountNodes(pScene->mRootNode), " output nodes)"); + ASSIMP_LOG_INFO_F("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras."); + ASSIMP_LOG_INFO_F("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); + } } diff --git a/code/PostProcessing/PretransformVertices.h b/code/PostProcessing/PretransformVertices.h index b2982951e..7898f6ae3 100644 --- a/code/PostProcessing/PretransformVertices.h +++ b/code/PostProcessing/PretransformVertices.h @@ -59,7 +59,7 @@ struct aiNode; class PretransformVerticesTest; -namespace Assimp { +namespace Assimp { // --------------------------------------------------------------------------- /** The PretransformVertices pre-transforms all vertices in the node tree @@ -68,97 +68,97 @@ namespace Assimp { */ class ASSIMP_API PretransformVertices : public BaseProcess { public: - PretransformVertices (); - ~PretransformVertices (); + PretransformVertices(); + ~PretransformVertices(); - // ------------------------------------------------------------------- - // Check whether step is active - bool IsActive( unsigned int pFlags) const; + // ------------------------------------------------------------------- + // Check whether step is active + bool IsActive(unsigned int pFlags) const override; - // ------------------------------------------------------------------- - // Execute step on a given scene - void Execute( aiScene* pScene); + // ------------------------------------------------------------------- + // Execute step on a given scene + void Execute(aiScene *pScene) override; - // ------------------------------------------------------------------- - // Setup import settings - void SetupProperties(const Importer* pImp); + // ------------------------------------------------------------------- + // Setup import settings + void SetupProperties(const Importer *pImp) override; - // ------------------------------------------------------------------- - /** @brief Toggle the 'keep hierarchy' option + // ------------------------------------------------------------------- + /** @brief Toggle the 'keep hierarchy' option * @param keep true for keep configuration. */ - void KeepHierarchy(bool keep) { - configKeepHierarchy = keep; - } + void KeepHierarchy(bool keep) { + configKeepHierarchy = keep; + } - // ------------------------------------------------------------------- - /** @brief Check whether 'keep hierarchy' is currently enabled. + // ------------------------------------------------------------------- + /** @brief Check whether 'keep hierarchy' is currently enabled. * @return ... */ - bool IsHierarchyKept() const { - return configKeepHierarchy; - } + bool IsHierarchyKept() const { + return configKeepHierarchy; + } private: - // ------------------------------------------------------------------- - // Count the number of nodes - unsigned int CountNodes( aiNode* pcNode ); + // ------------------------------------------------------------------- + // Count the number of nodes + unsigned int CountNodes(const aiNode *pcNode) const; - // ------------------------------------------------------------------- - // Get a bitwise combination identifying the vertex format of a mesh - unsigned int GetMeshVFormat(aiMesh* pcMesh); + // ------------------------------------------------------------------- + // Get a bitwise combination identifying the vertex format of a mesh + unsigned int GetMeshVFormat(aiMesh *pcMesh) const; - // ------------------------------------------------------------------- - // Count the number of vertices in the whole scene and a given - // material index - void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, - unsigned int iMat, - unsigned int iVFormat, - unsigned int* piFaces, - unsigned int* piVertices); + // ------------------------------------------------------------------- + // Count the number of vertices in the whole scene and a given + // material index + void CountVerticesAndFaces(const aiScene *pcScene, const aiNode *pcNode, + unsigned int iMat, + unsigned int iVFormat, + unsigned int *piFaces, + unsigned int *piVertices) const; - // ------------------------------------------------------------------- - // Collect vertex/face data - void CollectData( aiScene* pcScene, aiNode* pcNode, - unsigned int iMat, - unsigned int iVFormat, - aiMesh* pcMeshOut, - unsigned int aiCurrent[2], - unsigned int* num_refs); + // ------------------------------------------------------------------- + // Collect vertex/face data + void CollectData(const aiScene *pcScene, const aiNode *pcNode, + unsigned int iMat, + unsigned int iVFormat, + aiMesh *pcMeshOut, + unsigned int aiCurrent[2], + unsigned int *num_refs) const; - // ------------------------------------------------------------------- - // Get a list of all vertex formats that occur for a given material - // The output list contains duplicate elements - void GetVFormatList( aiScene* pcScene, unsigned int iMat, - std::list& aiOut); + // ------------------------------------------------------------------- + // Get a list of all vertex formats that occur for a given material + // The output list contains duplicate elements + void GetVFormatList(const aiScene *pcScene, unsigned int iMat, + std::list &aiOut) const; - // ------------------------------------------------------------------- - // Compute the absolute transformation matrices of each node - void ComputeAbsoluteTransform( aiNode* pcNode ); + // ------------------------------------------------------------------- + // Compute the absolute transformation matrices of each node + void ComputeAbsoluteTransform(aiNode *pcNode); - // ------------------------------------------------------------------- - // Simple routine to build meshes in worldspace, no further optimization - void BuildWCSMeshes(std::vector& out, aiMesh** in, - unsigned int numIn, aiNode* node); + // ------------------------------------------------------------------- + // Simple routine to build meshes in worldspace, no further optimization + void BuildWCSMeshes(std::vector &out, aiMesh **in, + unsigned int numIn, aiNode *node) const; - // ------------------------------------------------------------------- - // Apply the node transformation to a mesh - void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat); + // ------------------------------------------------------------------- + // Apply the node transformation to a mesh + void ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const; - // ------------------------------------------------------------------- - // Reset transformation matrices to identity - void MakeIdentityTransform(aiNode* nd); + // ------------------------------------------------------------------- + // Reset transformation matrices to identity + void MakeIdentityTransform(aiNode *nd) const; - // ------------------------------------------------------------------- - // Build reference counters for all meshes - void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs); + // ------------------------------------------------------------------- + // Build reference counters for all meshes + void BuildMeshRefCountArray(const aiNode *nd, unsigned int *refs) const; - //! Configuration option: keep scene hierarchy as long as possible - bool configKeepHierarchy; - bool configNormalize; - bool configTransform; - aiMatrix4x4 configTransformation; - bool mConfigPointCloud; + //! Configuration option: keep scene hierarchy as long as possible + bool configKeepHierarchy; + bool configNormalize; + bool configTransform; + aiMatrix4x4 configTransformation; + bool mConfigPointCloud; }; } // end of namespace Assimp From 4a8b7800ff402aec168f4c6a8ee37683e1ebe036 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Mon, 9 Dec 2019 11:23:57 +0000 Subject: [PATCH 136/170] Update M3D ASCII exporter ident and extension Changed to match existing Assimp style. Set extension as per: https://gitlab.com/bztsrc/model3d/blob/master/docs/a3d_format.md --- code/Common/Exporter.cpp | 4 ++-- code/M3D/M3DExporter.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 25a78114f..784c803b0 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -103,7 +103,7 @@ void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperti void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); -void ExportSceneA3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneM3DA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*); @@ -177,7 +177,7 @@ static void setupExporterArray(std::vector &exporte #ifndef ASSIMP_BUILD_NO_M3D_EXPORTER exporters.push_back(Exporter::ExportFormatEntry("m3d", "Model 3D (binary)", "m3d", &ExportSceneM3D, 0)); - exporters.push_back(Exporter::ExportFormatEntry("a3d", "Model 3D (ascii)", "m3d", &ExportSceneA3D, 0)); + exporters.push_back(Exporter::ExportFormatEntry("m3da", "Model 3D (ascii)", "a3d", &ExportSceneM3DA, 0)); #endif #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index 0e84f6d4f..1fe6e7f76 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -268,7 +268,7 @@ void ExportSceneM3D( // --------------------------------------------------------------------- // Worker function for exporting a scene to ASCII A3D. // Prototyped and registered in Exporter.cpp -void ExportSceneA3D( +void ExportSceneM3DA( const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, From 660f3571d8cc0dfb4ea573723938c16ca2c5506f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Dec 2019 17:23:52 +0100 Subject: [PATCH 137/170] added AnimMesh.mName member Closes: https://github.com/assimp/assimp/issues/2822 --- port/PyAssimp/pyassimp/structs.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index 0ac498a44..809afae54 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -573,6 +573,9 @@ class AnimMesh(Structure): AI_MAX_NUMBER_OF_COLOR_SETS = 0x8 _fields_ = [ + # Anim Mesh name + ("mName", String), + # Replacement for aiMesh::mVertices. If this array is non-NULL, # it *must* contain mNumVertices entries. The corresponding # array in the host mesh must be non-NULL as well - animation From 17aabc34ccd9958f2d67505cd8b290087d978036 Mon Sep 17 00:00:00 2001 From: bzt Date: Tue, 10 Dec 2019 06:30:41 +0100 Subject: [PATCH 138/170] MSVC workarounds --- code/M3D/M3DExporter.cpp | 14 +-- code/M3D/M3DImporter.cpp | 20 +-- code/M3D/m3d.h | 261 ++++++++++++++++++++------------------- 3 files changed, 149 insertions(+), 146 deletions(-) diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index 0e84f6d4f..faf5a9585 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -134,7 +134,7 @@ void addProp(m3dm_t *m, uint8_t type, uint32_t value) { // ------------------------------------------------------------------------------------------------ // add a material to the output M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { - unsigned int mi = -1U; + unsigned int mi = M3D_NOTDEFINED; aiColor4D c; aiString name; ai_real f; @@ -150,7 +150,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { break; } // if not found, add the material to the output - if (mi == -1U) { + if (mi == M3D_NOTDEFINED) { unsigned int k; mi = m3d->nummaterial++; m3d->material = (m3dm_t *)M3D_REALLOC(m3d->material, m3d->nummaterial * sizeof(m3dm_t)); @@ -219,13 +219,13 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { name.data[j] = 0; // do we have this texture saved already? fn = _m3d_safestr((char *)&name.data, 0); - for (j = 0, i = -1U; j < m3d->numtexture; j++) + for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++) if (!strcmp(fn, m3d->texture[j].name)) { i = j; free(fn); break; } - if (i == -1U) { + if (i == M3D_NOTDEFINED) { i = m3d->numtexture++; m3d->texture = (m3dtx_t *)M3D_REALLOC( m3d->texture, @@ -335,7 +335,7 @@ void M3DExporter::NodeWalk(const M3DWrapper &m3d, const aiNode *pNode, aiMatrix4 for (unsigned int i = 0; i < pNode->mNumMeshes; i++) { const aiMesh *mesh = mScene->mMeshes[pNode->mMeshes[i]]; - unsigned int mi = (M3D_INDEX)-1U; + unsigned int mi = M3D_NOTDEFINED; if (mScene->mMaterials) { // get the material for this mesh mi = addMaterial(m3d, mScene->mMaterials[mesh->mMaterialIndex]); @@ -358,7 +358,7 @@ void M3DExporter::NodeWalk(const M3DWrapper &m3d, const aiNode *pNode, aiMatrix4 /* set all index to -1 by default */ m3d->face[n].vertex[0] = m3d->face[n].vertex[1] = m3d->face[n].vertex[2] = m3d->face[n].normal[0] = m3d->face[n].normal[1] = m3d->face[n].normal[2] = - m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = -1U; + m3d->face[n].texcoord[0] = m3d->face[n].texcoord[1] = m3d->face[n].texcoord[2] = M3D_UNDEF; m3d->face[n].materialid = mi; for (unsigned int k = 0; k < face->mNumIndices; k++) { // get the vertex's index @@ -374,7 +374,7 @@ void M3DExporter::NodeWalk(const M3DWrapper &m3d, const aiNode *pNode, aiMatrix4 vertex.z = v.z; vertex.w = 1.0; vertex.color = 0; - vertex.skinid = -1U; + vertex.skinid = M3D_UNDEF; // add color if defined if (mesh->HasVertexColors(0)) vertex.color = mkColor(&mesh->mColors[0][l]); diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 5218dd9ed..6627d1f74 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -176,7 +176,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys // let the C SDK do the hard work for us M3DWrapper m3d(pIOHandler, buffer); - + if (!m3d) { throw DeadlyImportError("Unable to parse " + file + " as M3D."); } @@ -193,7 +193,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys // now we just have to fill up the Assimp structures in pScene importMaterials(m3d); importTextures(m3d); - importBones(m3d, -1U, pScene->mRootNode); + importBones(m3d, M3D_NOTDEFINED, pScene->mRootNode); importMeshes(m3d); importAnimations(m3d); @@ -343,7 +343,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { // individually. In assimp there're per mesh vertex and UV lists, and they must be // indexed simultaneously. void M3DImporter::importMeshes(const M3DWrapper &m3d) { - unsigned int i, j, k, l, numpoly = 3, lastMat = -2U; + unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX; std::vector *meshes = new std::vector(); std::vector *faces = nullptr; std::vector *vertices = nullptr; @@ -398,20 +398,20 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { vertices->push_back(pos); colors->push_back(mkColor(m3d->vertex[l].color)); // add a bone to temporary vector - if (m3d->vertex[l].skinid != -1U && m3d->vertex[l].skinid != -2U && m3d->skin && m3d->bone) { + if (m3d->vertex[l].skinid != M3D_UNDEF && m3d->vertex[l].skinid != M3D_INDEXMAX && m3d->skin && m3d->bone) { // this is complicated, because M3D stores a list of bone id / weight pairs per // vertex but assimp uses lists of local vertex id/weight pairs per local bone list vertexids->push_back(l); } l = m3d->face[i].texcoord[j]; - if (l != -1U) { + if (l != M3D_UNDEF) { uv.x = m3d->tmap[l].u; uv.y = m3d->tmap[l].v; uv.z = 0.0; texcoords->push_back(uv); } l = m3d->face[i].normal[j]; - if (l != -1U) { + if (l != M3D_UNDEF) { norm.x = m3d->vertex[l].x; norm.y = m3d->vertex[l].y; norm.z = m3d->vertex[l].z; @@ -557,8 +557,8 @@ aiColor4D M3DImporter::mkColor(uint32_t c) { void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) { ai_assert(m != nullptr); ai_assert(m3d); - ai_assert(posid != -1U && posid < m3d->numvertex); - ai_assert(orientid != -1U && orientid < m3d->numvertex); + ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex); + ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex); m3dv_t *p = &m3d->vertex[posid]; m3dv_t *q = &m3d->vertex[orientid]; @@ -692,7 +692,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // first count how many vertices we have per bone for (i = 0; i < vertexids->size(); i++) { unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if (s != -1U && s != -2U) { + if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); for (j = 0; j < pMesh->mNumBones; j++) { @@ -715,7 +715,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // fill up with data for (i = 0; i < vertexids->size(); i++) { unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if (s != -1U && s != -2U) { + if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); for (j = 0; j < pMesh->mNumBones; j++) { diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index c1d690bcc..d1fedc5b5 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -70,11 +70,14 @@ typedef double M3D_FLOAT; #endif #if !defined(M3D_SMALLINDEX) typedef uint32_t M3D_INDEX; +#define M3D_UNDEF 0xffffffff #define M3D_INDEXMAX 0xfffffffe #else typedef uint16_t M3D_INDEX; +#define M3D_UNDEF 0xffff #define M3D_INDEXMAX 0xfffe #endif +#define M3D_NOTDEFINED 0xffffffff #ifndef M3D_NUMBONE #define M3D_NUMBONE 4 #endif @@ -2123,10 +2126,10 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char } /* try to load from external source */ if(!buff && readfilecb) { - i = strlen(fn); + i = (unsigned int)strlen(fn); if(i < 5 || fn[i - 4] != '.') { fn2 = (char*)M3D_MALLOC(i + 5); - if(!fn2) { model->errcode = M3D_ERR_ALLOC; return (M3D_INDEX)-1U; } + if(!fn2) { model->errcode = M3D_ERR_ALLOC; return M3D_UNDEF; } memcpy(fn2, fn, i); memcpy(fn2+i, ".png", 5); buff = (*readfilecb)(fn2, &len); @@ -2135,14 +2138,14 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char if(!buff) buff = (*readfilecb)(fn, &len); } - if(!buff) return (M3D_INDEX)-1U; + if(!buff) return M3D_UNDEF; /* add to textures array */ i = model->numtexture++; model->texture = (m3dtx_t*)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t)); if(!model->texture) { if(freecb) (*freecb)(buff); model->errcode = M3D_ERR_ALLOC; - return (M3D_INDEX)-1U; + return M3D_UNDEF; } model->texture[i].name = fn; model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL; @@ -2434,7 +2437,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, model->numvertex * sizeof(m3dv_t)); if(!model->vertex) goto memerr; memset(&model->vertex[i], 0, sizeof(m3dv_t)); - model->vertex[i].skinid = (M3D_INDEX)-1U; + model->vertex[i].skinid = M3D_UNDEF; model->vertex[i].color = 0; model->vertex[i].w = (M3D_FLOAT)1.0; ptr = _m3d_getfloat(ptr, &model->vertex[i].x); @@ -2464,16 +2467,16 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d s.weight[j] = (M3D_FLOAT)1.0; if(!*ptr) goto asciiend; } - if(s.boneid[0] != (M3D_INDEX)-1U && s.weight[0] > (M3D_FLOAT)0.0) { + if(s.boneid[0] != M3D_UNDEF && s.weight[0] > (M3D_FLOAT)0.0) { if(w != (M3D_FLOAT)1.0 && w != (M3D_FLOAT)0.0) for(j = 0; j < M3D_NUMBONE && s.weight[j] > (M3D_FLOAT)0.0; j++) s.weight[j] /= w; - k = -1U; + k = M3D_NOTDEFINED; if(model->skin) { for(j = 0; j < model->numskin; j++) if(!memcmp(&model->skin[j], &s, sizeof(m3ds_t))) { k = j; break; } } - if(k == -1U) { + if(k == M3D_NOTDEFINED) { k = model->numskin++; model->skin = (m3ds_t*)M3D_REALLOC(model->skin, model->numskin * sizeof(m3ds_t)); memcpy(&model->skin[k], &s, sizeof(m3ds_t)); @@ -2486,7 +2489,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d /* Skeleton, bone hierarchy */ if(!memcmp(pe, "Bones", 5)) { if(model->bone) { M3D_LOG("More bones chunks, should be unique"); goto asciiend; } - bi[0] = (M3D_INDEX)-1U; + bi[0] = M3D_UNDEF; while(*ptr && *ptr != '\r' && *ptr != '\n') { i = model->numbone++; model->bone = (m3db_t*)M3D_REALLOC(model->bone, model->numbone * sizeof(m3db_t)); @@ -2505,7 +2508,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d ptr = _m3d_findarg(ptr); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; model->bone[i].ori = (M3D_INDEX)k; - model->vertex[k].skinid = (M3D_INDEX)-2U; + model->vertex[k].skinid = M3D_INDEXMAX; pe = _m3d_safestr(ptr, 0); if(!pe || !*pe) goto asciiend; model->bone[i].name = pe; @@ -2579,7 +2582,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(!pe || !*pe) goto asciiend; m->prop[j].value.textureid = _m3d_gettx(model, readfilecb, freecb, pe); if(model->errcode == M3D_ERR_ALLOC) { M3D_FREE(pe); goto memerr; } - if(m->prop[j].value.textureid == (M3D_INDEX)-1U) { + if(m->prop[j].value.textureid == M3D_UNDEF) { M3D_LOG("Texture not found"); M3D_LOG(pe); m->numprop--; @@ -2605,18 +2608,18 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d } else /* mesh */ if(!memcmp(pe, "Mesh", 4)) { - mi = (M3D_INDEX)-1U; + mi = M3D_UNDEF; while(*ptr && *ptr != '\r' && *ptr != '\n') { if(*ptr == 'u') { ptr = _m3d_findarg(ptr); if(!*ptr) goto asciiend; - mi = (M3D_INDEX)-1U; + mi = M3D_UNDEF; if(*ptr != '\r' && *ptr != '\n') { pe = _m3d_safestr(ptr, 0); if(!pe || !*pe) goto asciiend; for(j = 0; j < model->nummaterial; j++) if(!strcmp(pe, model->material[j].name)) { mi = (M3D_INDEX)j; break; } - if(mi == (M3D_INDEX)-1U && !(model->flags & M3D_FLG_MTLLIB)) { + if(mi == M3D_UNDEF && !(model->flags & M3D_FLG_MTLLIB)) { mi = model->nummaterial++; model->material = (m3dm_t*)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t)); if(!model->material) goto memerr; @@ -2655,7 +2658,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d } } #ifndef M3D_NONORMALS - if(model->face[i].normal[j] == (M3D_INDEX)-1U) neednorm = 1; + if(model->face[i].normal[j] == M3D_UNDEF) neednorm = 1; #endif ptr = _m3d_findarg(ptr); } @@ -2674,7 +2677,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(!model->shape) goto memerr; h = &model->shape[i]; h->name = pe; - h->group = (M3D_INDEX)-1U; + h->group = M3D_UNDEF; h->numcmd = 0; h->cmd = NULL; while(*ptr && *ptr != '\r' && *ptr != '\n') { @@ -2682,16 +2685,16 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d ptr = _m3d_findarg(ptr); ptr = _m3d_getint(ptr, &h->group); ptr = _m3d_findnl(ptr); - if(h->group != (M3D_INDEX)-1U && h->group >= model->numbone) { + if(h->group != M3D_UNDEF && h->group >= model->numbone) { M3D_LOG("Unknown bone id as shape group in shape"); M3D_LOG(pe); - h->group = (M3D_INDEX)-1U; + h->group = M3D_UNDEF; model->errcode = M3D_ERR_SHPE; } continue; } for(cd = NULL, k = 0; k < (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])); k++) { - j = strlen(m3d_commandtypes[k].key); + j = (unsigned int)strlen(m3d_commandtypes[k].key); if(!memcmp(ptr, m3d_commandtypes[k].key, j) && (ptr[j] == ' ' || ptr[j] == '\r' || ptr[j] == '\n')) { cd = &m3d_commandtypes[k]; break; } } @@ -2713,13 +2716,13 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(*ptr == ']' || *ptr == '\r' || *ptr == '\n') break; switch(cd->a[((k - n) % (cd->p - n)) + n]) { case m3dcp_mi_t: - mi = (M3D_INDEX)-1U; + mi = M3D_UNDEF; if(*ptr != '\r' && *ptr != '\n') { pe = _m3d_safestr(ptr, 0); if(!pe || !*pe) goto asciiend; for(n = 0; n < model->nummaterial; n++) if(!strcmp(pe, model->material[n].name)) { mi = (M3D_INDEX)n; break; } - if(mi == (M3D_INDEX)-1U && !(model->flags & M3D_FLG_MTLLIB)) { + if(mi == M3D_UNDEF && !(model->flags & M3D_FLG_MTLLIB)) { mi = model->nummaterial++; model->material = (m3dm_t*)M3D_REALLOC(model->material, model->nummaterial * sizeof(m3dm_t)); @@ -2745,7 +2748,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d break; case m3dcp_qi_t: ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]); - model->vertex[h->cmd[i].arg[k]].skinid = (M3D_INDEX)-2U; + model->vertex[h->cmd[i].arg[k]].skinid = M3D_INDEXMAX; break; default: ptr = _m3d_getint(ptr, &h->cmd[j].arg[k]); @@ -2844,7 +2847,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d ptr = _m3d_getint(ptr, &k); if(!*ptr || *ptr == '\r' || *ptr == '\n') goto asciiend; a->frame[i].transform[j].ori = (M3D_INDEX)k; - model->vertex[k].skinid = (M3D_INDEX)-2U; + model->vertex[k].skinid = M3D_INDEXMAX; } ptr = _m3d_findnl(ptr); } @@ -3116,7 +3119,7 @@ memerr: M3D_LOG("Out of memory"); case 4: model->vertex[i].color = *((uint32_t*)data); data += 4; break; /* case 8: break; */ } - model->vertex[i].skinid = (M3D_INDEX)-1U; + model->vertex[i].skinid = M3D_UNDEF; data = _m3d_getidx(data, model->sk_s, &model->vertex[i].skinid); } } else @@ -3150,7 +3153,7 @@ memerr: M3D_LOG("Out of memory"); if(!model->skin) goto memerr; for(i = 0; data < chunk && i < model->numskin; i++) { for(j = 0; j < M3D_NUMBONE; j++) { - model->skin[i].boneid[j] = (M3D_INDEX)-1U; + model->skin[i].boneid[j] = M3D_UNDEF; model->skin[i].weight[j] = (M3D_FLOAT)0.0; } memset(&weights, 0, sizeof(weights)); @@ -3244,7 +3247,7 @@ memerr: M3D_LOG("Out of memory"); M3D_GETSTR(name); m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, name); if(model->errcode == M3D_ERR_ALLOC) goto memerr; - if(m->prop[i].value.textureid == (M3D_INDEX)-1U) { + if(m->prop[i].value.textureid == M3D_UNDEF) { M3D_LOG("Texture not found"); M3D_LOG(m->name); m->numprop--; @@ -3275,7 +3278,7 @@ memerr: M3D_LOG("Out of memory"); M3D_LOG("Mesh data"); /* mesh */ data += sizeof(m3dchunk_t); - mi = (M3D_INDEX)-1U; + mi = M3D_UNDEF; am = model->numface; while(data < chunk) { k = *data++; @@ -3283,7 +3286,7 @@ memerr: M3D_LOG("Out of memory"); k &= 15; if(!n) { /* use material */ - mi = (M3D_INDEX)-1U; + mi = M3D_UNDEF; M3D_GETSTR(name); if(name) { for(j = 0; j < model->nummaterial; j++) @@ -3291,7 +3294,7 @@ memerr: M3D_LOG("Out of memory"); mi = (M3D_INDEX)j; break; } - if(mi == (M3D_INDEX)-1U) model->errcode = M3D_ERR_MTRL; + if(mi == M3D_UNDEF) model->errcode = M3D_ERR_MTRL; } continue; } @@ -3314,7 +3317,7 @@ memerr: M3D_LOG("Out of memory"); if(k & 2) data = _m3d_getidx(data, model->vi_s, &model->face[i].normal[j]); #ifndef M3D_NONORMALS - if(model->face[i].normal[j] == (M3D_INDEX)-1U) neednorm = 1; + if(model->face[i].normal[j] == M3D_UNDEF) neednorm = 1; #endif } } @@ -3333,12 +3336,12 @@ memerr: M3D_LOG("Out of memory"); h->numcmd = 0; h->cmd = NULL; h->name = name; - h->group = (M3D_INDEX)-1U; + h->group = M3D_UNDEF; data = _m3d_getidx(data, model->bi_s, &h->group); - if(h->group != (M3D_INDEX)-1U && h->group >= model->numbone) { + if(h->group != M3D_UNDEF && h->group >= model->numbone) { M3D_LOG("Unknown bone id as shape group in shape"); M3D_LOG(name); - h->group = (M3D_INDEX)-1U; + h->group = M3D_UNDEF; model->errcode = M3D_ERR_SHPE; } while(data < chunk) { @@ -3363,7 +3366,7 @@ memerr: M3D_LOG("Out of memory"); for(k = n = 0, l = cd->p; k < l; k++) switch(cd->a[((k - n) % (cd->p - n)) + n]) { case m3dcp_mi_t: - h->cmd[i].arg[k] = -1U; + h->cmd[i].arg[k] = M3D_NOTDEFINED; M3D_GETSTR(name); if(name) { for(n = 0; n < model->nummaterial; n++) @@ -3371,7 +3374,7 @@ memerr: M3D_LOG("Out of memory"); h->cmd[i].arg[k] = n; break; } - if(h->cmd[i].arg[k] == -1U) model->errcode = M3D_ERR_MTRL; + if(h->cmd[i].arg[k] == M3D_NOTDEFINED) model->errcode = M3D_ERR_MTRL; } break; case m3dcp_vc_t: @@ -3488,7 +3491,7 @@ postprocess: norm = (m3dv_t*)M3D_MALLOC(model->numface * sizeof(m3dv_t)); if(!norm) goto memerr; for(i = 0, n = model->numvertex; i < model->numface; i++) - if(model->face[i].normal[0] == -1U) { + if(model->face[i].normal[0] == M3D_UNDEF) { v0 = &model->vertex[model->face[i].vertex[0]]; v1 = &model->vertex[model->face[i].vertex[1]]; v2 = &model->vertex[model->face[i].vertex[2]]; @@ -3522,7 +3525,7 @@ postprocess: for(i = 0, v0 = &model->vertex[n]; i < n; i++, v0++) { w = _m3d_rsq((v0->x * v0->x) + (v0->y * v0->y) + (v0->z * v0->z)); v0->x *= w; v0->y *= w; v0->z *= w; - v0->skinid = -1U; + v0->skinid = M3D_UNDEF; } M3D_FREE(norm); } @@ -3534,9 +3537,9 @@ postprocess: if(model->vertex[i].skinid < model->numskin) { sk = &model->skin[model->vertex[i].skinid]; w = (M3D_FLOAT)0.0; - for(j = 0; j < M3D_NUMBONE && sk->boneid[j] != (M3D_INDEX)-1U && sk->weight[j] > (M3D_FLOAT)0.0; j++) + for(j = 0; j < M3D_NUMBONE && sk->boneid[j] != M3D_UNDEF && sk->weight[j] > (M3D_FLOAT)0.0; j++) w += sk->weight[j]; - for(j = 0; j < M3D_NUMBONE && sk->boneid[j] != (M3D_INDEX)-1U && sk->weight[j] > (M3D_FLOAT)0.0; j++) { + for(j = 0; j < M3D_NUMBONE && sk->boneid[j] != M3D_UNDEF && sk->weight[j] > (M3D_FLOAT)0.0; j++) { sk->weight[j] /= w; b = &model->bone[sk->boneid[j]]; k = b->numweight++; @@ -3552,7 +3555,7 @@ postprocess: M3D_LOG("Calculating bone transformation matrices"); for(i = 0; i < model->numbone; i++) { b = &model->bone[i]; - if(model->bone[i].parent == (M3D_INDEX)-1U) { + if(model->bone[i].parent == M3D_UNDEF) { _m3d_mat((M3D_FLOAT*)&b->mat4, &model->vertex[b->pos], &model->vertex[b->ori]); } else { _m3d_mat((M3D_FLOAT*)&r, &model->vertex[b->pos], &model->vertex[b->ori]); @@ -3583,7 +3586,7 @@ m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t M3D_INDEX s = frameid; m3dfr_t *fr; - if(!model || !model->numbone || !model->bone || (actionid != (M3D_INDEX)-1U && (!model->action || + if(!model || !model->numbone || !model->bone || (actionid != M3D_UNDEF && (!model->action || actionid >= model->numaction || frameid >= model->action[actionid].numframe))) { model->errcode = M3D_ERR_UNKFRAME; return skeleton; @@ -3597,7 +3600,7 @@ m3dtr_t *m3d_frame(m3d_t *model, M3D_INDEX actionid, M3D_INDEX frameid, m3dtr_t } goto gen; } - if(actionid == (M3D_INDEX)-1U || !frameid) { + if(actionid == M3D_UNDEF || !frameid) { gen: s = 0; for(i = 0; i < model->numbone; i++) { skeleton[i].boneid = i; @@ -3721,7 +3724,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec) } } for(i = 0; i < model->numbone; i++) { - if(ret[i].parent == (M3D_INDEX)-1U) { + if(ret[i].parent == M3D_UNDEF) { _m3d_mat((M3D_FLOAT*)&ret[i].mat4, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]); } else { _m3d_mat((M3D_FLOAT*)&r, &model->vertex[ret[i].pos], &model->vertex[ret[i].ori]); @@ -3904,7 +3907,7 @@ m3dhdr_t *_m3d_addhdr(m3dhdr_t *h, m3dstr_t *s) { int i; char *safe = _m3d_safestr(s->str, 0); - i = strlen(safe); + i = (int)strlen(safe); h = (m3dhdr_t*)M3D_REALLOC(h, h->length + i+1); if(!h) { M3D_FREE(safe); return NULL; } memcpy((uint8_t*)h + h->length, safe, i+1); @@ -4033,16 +4036,16 @@ static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) /* round according to quality */ switch(quality) { case M3D_EXP_INT8: - t = src->x * 127 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / 127; - t = src->y * 127 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / 127; - t = src->z * 127 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / 127; - t = src->w * 127 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / 127; + t = src->x * 127 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / (M3D_FLOAT)127.0; + t = src->y * 127 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / (M3D_FLOAT)127.0; + t = src->z * 127 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / (M3D_FLOAT)127.0; + t = src->w * 127 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / (M3D_FLOAT)127.0; break; case M3D_EXP_INT16: - t = src->x * 32767 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / 32767; - t = src->y * 32767 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / 32767; - t = src->z * 32767 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / 32767; - t = src->w * 32767 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / 32767; + t = src->x * 32767 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; + t = src->y * 32767 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; + t = src->z * 32767 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; + t = src->w * 32767 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; break; } if(dst->x == (M3D_FLOAT)-0.0) dst->x = (M3D_FLOAT)0.0; @@ -4160,7 +4163,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size } face[i].opacity = opa[model->face[i].materialid * 2 + 1]; } else - face[i].data.materialid = (M3D_INDEX)-1U; + face[i].data.materialid = M3D_UNDEF; } for(j = 0; j < 3; j++) { k = model->face[i].vertex[j]; @@ -4311,7 +4314,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size if(!(flags & M3D_EXP_NOMATERIAL)) { M3D_LOG("Processing materials"); for(i = k = 0; i < model->nummaterial; i++) { - if(mtrlidx[i] == (M3D_INDEX)-1U || !model->material[i].numprop) continue; + if(mtrlidx[i] == M3D_UNDEF || !model->material[i].numprop) continue; mtrlidx[i] = k++; m = &model->material[i]; str = _m3d_addstr(str, &numstr, m->name); @@ -4345,15 +4348,15 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size tmap = (m3dtisave_t*)M3D_MALLOC(model->numtmap * sizeof(m3dtisave_t)); if(!tmap) goto memerr; for(i = 0; i < model->numtmap; i++) { - if(tmapidx[i] == (M3D_INDEX)-1U) continue; + if(tmapidx[i] == M3D_UNDEF) continue; switch(quality) { case M3D_EXP_INT8: - l = model->tmap[i].u * 255; tcoord.data.u = (M3D_FLOAT)l / 255; - l = model->tmap[i].v * 255; tcoord.data.v = (M3D_FLOAT)l / 255; + l = model->tmap[i].u * 255; tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)255.0; + l = model->tmap[i].v * 255; tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)255.0; break; case M3D_EXP_INT16: - l = model->tmap[i].u * 65535; tcoord.data.u = (M3D_FLOAT)l / 65535; - l = model->tmap[i].v * 65535; tcoord.data.v = (M3D_FLOAT)l / 65535; + l = model->tmap[i].u * 65535; tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)65535.0; + l = model->tmap[i].v * 65535; tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)65535.0; break; default: tcoord.data.u = model->tmap[i].u; @@ -4387,13 +4390,13 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size if(!skin) goto memerr; memset(skinidx, 255, model->numskin * sizeof(M3D_INDEX)); for(i = 0; i < model->numvertex; i++) { - if(vrtxidx[i] != (M3D_INDEX)-1U && model->vertex[i].skinid < model->numskin) + if(vrtxidx[i] != M3D_UNDEF && model->vertex[i].skinid < model->numskin) skinidx[model->vertex[i].skinid] = 0; } for(i = 0; i < model->numskin; i++) { - if(skinidx[i] == (M3D_INDEX)-1U) continue; + if(skinidx[i] == M3D_UNDEF) continue; memset(&sk, 0, sizeof(m3dssave_t)); - for(j = 0, min_x = (M3D_FLOAT)0.0; j < M3D_NUMBONE && model->skin[i].boneid[j] != (M3D_INDEX)-1U && + for(j = 0, min_x = (M3D_FLOAT)0.0; j < M3D_NUMBONE && model->skin[i].boneid[j] != M3D_UNDEF && model->skin[i].weight[j] > (M3D_FLOAT)0.0; j++) { sk.data.boneid[j] = model->skin[i].boneid[j]; sk.data.weight[j] = model->skin[i].weight[j]; @@ -4428,11 +4431,11 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size vrtx = (m3dvsave_t*)M3D_MALLOC(model->numvertex * sizeof(m3dvsave_t)); if(!vrtx) goto memerr; for(i = numvrtx = 0; i < model->numvertex; i++) { - if(vrtxidx[i] == (M3D_INDEX)-1U) continue; + if(vrtxidx[i] == M3D_UNDEF) continue; _m3d_round(quality, &model->vertex[i], &vertex.data); vertex.norm = norm ? norm[i] : 0; - if(vertex.data.skinid != (M3D_INDEX)-2U && !vertex.norm) { - vertex.data.skinid = vertex.data.skinid != (M3D_INDEX)-1U && skinidx ? skinidx[vertex.data.skinid] : (M3D_INDEX)-1U; + if(vertex.data.skinid != M3D_INDEXMAX && !vertex.norm) { + vertex.data.skinid = vertex.data.skinid != M3D_UNDEF && skinidx ? skinidx[vertex.data.skinid] : M3D_UNDEF; if(vertex.data.x > max_x) max_x = vertex.data.x; if(vertex.data.x < min_x) min_x = vertex.data.x; if(vertex.data.y > max_y) max_y = vertex.data.y; @@ -4481,7 +4484,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size if(scale == (M3D_FLOAT)0.0) scale = (M3D_FLOAT)1.0; if(scale != (M3D_FLOAT)1.0) { for(i = 0; i < numvrtx; i++) { - if(vrtx[i].data.skinid == (M3D_INDEX)-2U) continue; + if(vrtx[i].data.skinid == M3D_INDEXMAX) continue; vrtx[i].data.x /= scale; vrtx[i].data.y /= scale; vrtx[i].data.z /= scale; @@ -4528,7 +4531,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); ol = setlocale(LC_NUMERIC, NULL); setlocale(LC_NUMERIC, "C"); /* header */ - len = 64 + strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd); + len = 64 + (unsigned int)(strlen(sn) + strlen(sl) + strlen(sa) + strlen(sd)); out = (unsigned char*)M3D_MALLOC(len); if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr = (char*)out; @@ -4540,7 +4543,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(model->preview.data && model->preview.length) { sl = _m3d_safestr(sn, 0); if(sl) { - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 20; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)20); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Preview\r\n%s.png\r\n\r\n", sl); @@ -4550,11 +4553,11 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); M3D_FREE(sn); sn = NULL; /* texture map */ if(numtmap && tmap && !(flags & M3D_EXP_NOTXTCRD) && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + maxtmap * 32 + 12; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(maxtmap * 32) + (uintptr_t)12); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Textmap\r\n"); - last = (M3D_INDEX)-1U; + last = M3D_UNDEF; for(i = 0; i < numtmap; i++) { if(tmap[i].newidx == last) continue; last = tmap[i].newidx; @@ -4564,11 +4567,11 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } /* vertex chunk */ if(numvrtx && vrtx && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + maxvrtx * 128 + 10; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(maxvrtx * 128) + (uintptr_t)10); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Vertex\r\n"); - last = (M3D_INDEX)-1U; + last = M3D_UNDEF; for(i = 0; i < numvrtx; i++) { if(vrtx[i].newidx == last) continue; last = vrtx[i].newidx; @@ -4579,7 +4582,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(skin[vrtx[i].data.skinid].data.weight[0] == (M3D_FLOAT)1.0) ptr += sprintf(ptr, " %d", skin[vrtx[i].data.skinid].data.boneid[0]); else - for(j = 0; j < M3D_NUMBONE && skin[vrtx[i].data.skinid].data.boneid[j] != (M3D_INDEX)-1U && + for(j = 0; j < M3D_NUMBONE && skin[vrtx[i].data.skinid].data.boneid[j] != M3D_UNDEF && skin[vrtx[i].data.skinid].data.weight[j] > (M3D_FLOAT)0.0; j++) ptr += sprintf(ptr, " %d:%g", skin[vrtx[i].data.skinid].data.boneid[j], skin[vrtx[i].data.skinid].data.weight[j]); @@ -4590,29 +4593,29 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } /* bones chunk */ if(model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) { - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 9; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)9); for(i = 0; i < model->numbone; i++) { - len += strlen(model->bone[i].name) + 128; + len += (unsigned int)strlen(model->bone[i].name) + 128; } out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Bones\r\n"); - ptr = _m3d_prtbone(ptr, model->bone, model->numbone, (M3D_INDEX)-1U, 0, vrtxidx); + ptr = _m3d_prtbone(ptr, model->bone, model->numbone, M3D_UNDEF, 0, vrtxidx); ptr += sprintf(ptr, "\r\n"); } /* materials */ if(model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) { for(j = 0; j < model->nummaterial; j++) { - if(mtrlidx[j] == (M3D_INDEX)-1U || !model->material[j].numprop || !model->material[j].prop) continue; + if(mtrlidx[j] == M3D_UNDEF || !model->material[j].numprop || !model->material[j].prop) continue; m = &model->material[j]; sn = _m3d_safestr(m->name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 12; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)12); for(i = 0; i < m->numprop; i++) { if(m->prop[i].type < 128) len += 32; else if(m->prop[i].value.textureid < model->numtexture && model->texture[m->prop[i].value.textureid].name) - len += strlen(model->texture[m->prop[i].value.textureid].name) + 16; + len += (unsigned int)strlen(model->texture[m->prop[i].value.textureid].name) + 16; } out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } @@ -4676,7 +4679,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(k) continue; sn = _m3d_safestr(model->inlined[j].name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 18; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)18); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Procedural\r\n%s\r\n\r\n", sn); @@ -4685,24 +4688,24 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } /* mesh face */ if(model->numface && face && !(flags & M3D_EXP_NOFACE)) { - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + model->numface * 128 + 6; - last = (M3D_INDEX)-1U; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)(model->numface * 128) + (uintptr_t)6); + last = M3D_UNDEF; if(!(flags & M3D_EXP_NOMATERIAL)) for(i = 0; i < model->numface; i++) { - j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : (M3D_INDEX)-1U; + j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : M3D_UNDEF; if(j != last) { last = j; if(last < model->nummaterial) - len += strlen(model->material[last].name); + len += (unsigned int)strlen(model->material[last].name); len += 6; } } out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Mesh\r\n"); - last = (M3D_INDEX)-1U; + last = M3D_UNDEF; for(i = 0; i < model->numface; i++) { - j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : (M3D_INDEX)-1U; + j = face[i].data.materialid < model->nummaterial ? face[i].data.materialid : M3D_UNDEF; if(!(flags & M3D_EXP_NOMATERIAL) && j != last) { last = j; if(last < model->nummaterial) { @@ -4716,14 +4719,14 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); /* hardcoded triangles. Should be repeated as many times as the number of edges in polygon */ for(j = 0; j < 3; j++) { ptr += sprintf(ptr, "%s%d", j?" ":"", vrtxidx[face[i].data.vertex[j]]); - k = -1U; - if(!(flags & M3D_EXP_NOTXTCRD) && (face[i].data.texcoord[j] != (M3D_INDEX)-1U) && - (tmapidx[face[i].data.texcoord[j]] != (M3D_INDEX)-1U)) { + k = M3D_NOTDEFINED; + if(!(flags & M3D_EXP_NOTXTCRD) && (face[i].data.texcoord[j] != M3D_UNDEF) && + (tmapidx[face[i].data.texcoord[j]] != M3D_UNDEF)) { k = tmapidx[face[i].data.texcoord[j]]; ptr += sprintf(ptr, "/%d", k); } - if(!(flags & M3D_EXP_NONORMAL) && (face[i].data.normal[j] != (M3D_INDEX)-1U)) - ptr += sprintf(ptr, "%s/%d", k == -1U? "/" : "", vrtxidx[face[i].data.normal[j]]); + if(!(flags & M3D_EXP_NONORMAL) && (face[i].data.normal[j] != M3D_UNDEF)) + ptr += sprintf(ptr, "%s/%d", k == M3D_NOTDEFINED? "/" : "", vrtxidx[face[i].data.normal[j]]); } ptr += sprintf(ptr, "\r\n"); } @@ -4734,22 +4737,22 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); for(j = 0; j < model->numshape; j++) { sn = _m3d_safestr(model->shape[j].name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 33; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)33); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Shape %s\r\n", sn); M3D_FREE(sn); sn = NULL; - if(model->shape[j].group != (M3D_INDEX)-1U && !(flags & M3D_EXP_NOBONE)) + if(model->shape[j].group != M3D_UNDEF && !(flags & M3D_EXP_NOBONE)) ptr += sprintf(ptr, "group %d\r\n", model->shape[j].group); for(i = 0; i < model->shape[j].numcmd; i++) { cmd = &model->shape[j].cmd[i]; if(cmd->type >= (unsigned int)(sizeof(m3d_commandtypes)/sizeof(m3d_commandtypes[0])) || !cmd->arg) continue; cd = &m3d_commandtypes[cmd->type]; - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(cd->key) + 3; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(cd->key) + (uintptr_t)3); for(k = 0; k < cd->p; k++) switch(cd->a[k]) { - case m3dcp_mi_t: if(cmd->arg[k] != -1U) { len += strlen(model->material[cmd->arg[k]].name) + 1; } break; + case m3dcp_mi_t: if(cmd->arg[k] != M3D_NOTDEFINED) { len += (unsigned int)strlen(model->material[cmd->arg[k]].name) + 1; } break; case m3dcp_va_t: len += cmd->arg[k] * (cd->p - k - 1) * 16; k = cd->p; break; default: len += 16; break; } @@ -4759,7 +4762,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); for(k = n = 0, l = cd->p; k < l; k++) { switch(cd->a[((k - n) % (cd->p - n)) + n]) { case m3dcp_mi_t: - if(cmd->arg[k] != -1U) { + if(cmd->arg[k] != M3D_NOTDEFINED) { sn = _m3d_safestr(model->material[cmd->arg[k]].name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, " %s", sn); @@ -4781,12 +4784,12 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); /* annotation labels */ if(model->numlabel && model->label && !(flags & M3D_EXP_NOFACE)) { for(i = 0, j = 3, length = NULL; i < model->numlabel; i++) { - if(model->label[i].name) j += strlen(model->label[i].name); - if(model->label[i].lang) j += strlen(model->label[i].lang); - if(model->label[i].text) j += strlen(model->label[i].text); + if(model->label[i].name) j += (unsigned int)strlen(model->label[i].name); + if(model->label[i].lang) j += (unsigned int)strlen(model->label[i].lang); + if(model->label[i].text) j += (unsigned int)strlen(model->label[i].text); j += 40; } - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + j; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)j); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } for(i = 0; i < model->numlabel; i++) { @@ -4821,7 +4824,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); a = &model->action[j]; sn = _m3d_safestr(a->name, 0); if(!sn) { setlocale(LC_NUMERIC, ol); goto memerr; } - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + strlen(sn) + 48; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)strlen(sn) + (uintptr_t)48); for(i = 0; i < a->numframe; i++) len += a->frame[i].numtransform * 128 + 8; out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; @@ -4842,9 +4845,9 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(model->numinlined && model->inlined) { for(i = j = 0; i < model->numinlined; i++) if(model->inlined[i].name) - j += strlen(model->inlined[i].name) + 6; + j += (unsigned int)strlen(model->inlined[i].name) + 6; if(j > 0) { - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + j + 16; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)j + (uintptr_t)16); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Assets\r\n"); @@ -4858,7 +4861,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); if(model->numextra && (flags & M3D_EXP_EXTRA)) { for(i = 0; i < model->numextra; i++) { if(model->extra[i]->length < 9) continue; - ptr -= (uintptr_t)out; len = (uintptr_t)ptr + 17 + model->extra[i]->length * 3; + ptr -= (uintptr_t)out; len = (unsigned int)((uintptr_t)ptr + (uintptr_t)17 + (uintptr_t)(model->extra[i]->length * 3)); out = (unsigned char*)M3D_REALLOC(out, len); ptr += (uintptr_t)out; if(!out) { setlocale(LC_NUMERIC, ol); goto memerr; } ptr += sprintf(ptr, "Extra %c%c%c%c\r\n", @@ -4873,7 +4876,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } } setlocale(LC_NUMERIC, ol); - len = (uintptr_t)ptr - (uintptr_t)out; + len = (unsigned int)((uintptr_t)ptr - (uintptr_t)out); out = (unsigned char*)M3D_REALLOC(out, len + 1); if(!out) goto memerr; out[len] = 0; @@ -4889,10 +4892,10 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); memcpy((uint8_t*)h, "HEAD", 4); h->length = sizeof(m3dhdr_t); h->scale = scale; - i = strlen(sn); memcpy((uint8_t*)h + h->length, sn, i+1); h->length += i+1; M3D_FREE(sn); - i = strlen(sl); memcpy((uint8_t*)h + h->length, sl, i+1); h->length += i+1; M3D_FREE(sl); - i = strlen(sa); memcpy((uint8_t*)h + h->length, sa, i+1); h->length += i+1; M3D_FREE(sa); - i = strlen(sd); memcpy((uint8_t*)h + h->length, sd, i+1); h->length += i+1; M3D_FREE(sd); + i = (unsigned int)strlen(sn); memcpy((uint8_t*)h + h->length, sn, i+1); h->length += i+1; M3D_FREE(sn); + i = (unsigned int)strlen(sl); memcpy((uint8_t*)h + h->length, sl, i+1); h->length += i+1; M3D_FREE(sl); + i = (unsigned int)strlen(sa); memcpy((uint8_t*)h + h->length, sa, i+1); h->length += i+1; M3D_FREE(sa); + i = (unsigned int)strlen(sd); memcpy((uint8_t*)h + h->length, sd, i+1); h->length += i+1; M3D_FREE(sd); sn = sl = sa = sd = NULL; if(model->inlined) for(i = 0; i < model->numinlined; i++) { @@ -4960,7 +4963,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); memcpy((uint8_t*)h + len, "TMAP", 4); length = (uint32_t*)((uint8_t*)h + len + 4); out = (uint8_t*)h + len + 8; - last = (M3D_INDEX)-1U; + last = M3D_UNDEF; for(i = 0; i < numtmap; i++) { if(tmap[i].newidx == last) continue; last = tmap[i].newidx; @@ -4974,7 +4977,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); case 8: *((double*)out) = tmap[i].data.u; out += 8; *((double*)out) = tmap[i].data.v; out += 8; break; } } - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); out = NULL; len += *length; } @@ -4986,7 +4989,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); memcpy((uint8_t*)h + len, "VRTS", 4); length = (uint32_t*)((uint8_t*)h + len + 4); out = (uint8_t*)h + len + 8; - last = (M3D_INDEX)-1U; + last = M3D_UNDEF; for(i = 0; i < numvrtx; i++) { if(vrtx[i].newidx == last) continue; last = vrtx[i].newidx; @@ -5024,7 +5027,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid); } - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); out = NULL; len += *length; } @@ -5046,12 +5049,12 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); out = _m3d_addidx(out, vi_s, vrtxidx[model->bone[i].ori]); } if(numskin && skin && sk_s) { - last = (M3D_INDEX)-1U; + last = M3D_UNDEF; for(i = 0; i < numskin; i++) { if(skin[i].newidx == last) continue; last = skin[i].newidx; memset(&weights, 0, nb_s); - for(j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != (M3D_INDEX)-1U && + for(j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != M3D_UNDEF && skin[i].data.weight[j] > (M3D_FLOAT)0.0; j++) weights[j] = (uint8_t)(skin[i].data.weight[j] * 255); switch(nb_s) { @@ -5060,20 +5063,20 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); case 4: *((uint32_t*)out) = *((uint32_t*)&weights[0]); out += 4; break; case 8: *((uint64_t*)out) = *((uint64_t*)&weights[0]); out += 8; break; } - for(j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != (M3D_INDEX)-1U && weights[j]; j++) { + for(j = 0; j < (uint32_t)nb_s && skin[i].data.boneid[j] != M3D_UNDEF && weights[j]; j++) { out = _m3d_addidx(out, bi_s, skin[i].data.boneid[j]); *length += bi_s; } } } - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); out = NULL; len += *length; } /* materials */ if(model->nummaterial && !(flags & M3D_EXP_NOMATERIAL)) { for(j = 0; j < model->nummaterial; j++) { - if(mtrlidx[j] == (M3D_INDEX)-1U || !model->material[j].numprop || !model->material[j].prop) continue; + if(mtrlidx[j] == M3D_UNDEF || !model->material[j].numprop || !model->material[j].prop) continue; m = &model->material[j]; chunklen = 12 + si_s + m->numprop * 5; h = (m3dhdr_t*)M3D_REALLOC(h, len + chunklen); @@ -5115,7 +5118,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); break; } } - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); len += *length; out = NULL; } @@ -5152,7 +5155,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); memcpy((uint8_t*)h + len, "MESH", 4); length = (uint32_t*)((uint8_t*)h + len + 4); out = (uint8_t*)h + len + 8; - last = (M3D_INDEX)-1U; + last = M3D_UNDEF; for(i = 0; i < model->numface; i++) { if(!(flags & M3D_EXP_NOMATERIAL) && face[i].data.materialid != last) { last = face[i].data.materialid; @@ -5162,10 +5165,10 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } /* hardcoded triangles. */ k = (3 << 4) | - (((flags & M3D_EXP_NOTXTCRD) || !ti_s || face[i].data.texcoord[0] == (M3D_INDEX)-1U || - face[i].data.texcoord[1] == (M3D_INDEX)-1U || face[i].data.texcoord[2] == (M3D_INDEX)-1U) ? 0 : 1) | - (((flags & M3D_EXP_NONORMAL) || face[i].data.normal[0] == (M3D_INDEX)-1U || - face[i].data.normal[1] == (M3D_INDEX)-1U || face[i].data.normal[2] == (M3D_INDEX)-1U) ? 0 : 2); + (((flags & M3D_EXP_NOTXTCRD) || !ti_s || face[i].data.texcoord[0] == M3D_UNDEF || + face[i].data.texcoord[1] == M3D_UNDEF || face[i].data.texcoord[2] == M3D_UNDEF) ? 0 : 1) | + (((flags & M3D_EXP_NONORMAL) || face[i].data.normal[0] == M3D_UNDEF || + face[i].data.normal[1] == M3D_UNDEF || face[i].data.normal[2] == M3D_UNDEF) ? 0 : 2); *out++ = k; for(j = 0; j < 3; j++) { out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.vertex[j]]); @@ -5175,7 +5178,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]); } } - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); len += *length; out = NULL; } @@ -5226,7 +5229,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); } } } - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); len += *length; out = NULL; } @@ -5238,7 +5241,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); sl = model->label[i].lang; sn = model->label[i].name; if(length) { - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); len += *length; } chunklen = 8 + 2 * si_s + ci_s + model->numlabel * (vi_s + si_s); @@ -5260,7 +5263,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text)); } if(length) { - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); len += *length; } out = NULL; @@ -5288,7 +5291,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx); out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]); } } - *length = (uintptr_t)out - (uintptr_t)((uint8_t*)h + len); + *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t*)h + len)); len += *length; out = NULL; } From 08c5fa37bfba822505abeb9b204f8621287cc5ef Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Tue, 10 Dec 2019 12:04:35 +0000 Subject: [PATCH 139/170] Add a support for 3DSMax Physically Based Materials for FBX format --- code/FBX/FBXConverter.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 26a3c4b99..5b34868ba 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -2088,7 +2088,14 @@ namespace Assimp { TrySetTextureProperties(out_mat, textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh); TrySetTextureProperties(out_mat, textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh); TrySetTextureProperties(out_mat, textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh); + + // 3DSMax PBR + TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh); + TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|bump_map", aiTextureType_NORMAL_CAMERA, mesh); + TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|emission_map", aiTextureType_EMISSION_COLOR, mesh); + TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|metalness_map", aiTextureType_METALNESS, mesh); + TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); } void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh) From fb95e4982453f276c8a1abc69b2088793a65fbde Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 11 Dec 2019 05:47:59 +0100 Subject: [PATCH 140/170] More MSVC workarounds --- code/M3D/m3d.h | 57 ++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index d1fedc5b5..1b79fb785 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -91,7 +91,7 @@ typedef uint16_t M3D_INDEX; #else #define _inline #define _pack -#define _unused +#define _unused __pragma(warning(suppress:4100)) #endif #ifndef __cplusplus #define _register register @@ -2202,6 +2202,9 @@ void _m3d_getpr(m3d_t *model, _unused m3dread_t readfilecb, _unused m3dfree_t f } if(freecb && buff) (*freecb)(buff); #else + (void)readfilecb; + (void)freecb; + (void)fn; M3D_LOG("Unimplemented interpreter"); M3D_LOG(fn); model->errcode = M3D_ERR_UNIMPL; @@ -2294,7 +2297,7 @@ void _m3d_mat(M3D_FLOAT *r, m3dv_t *p, m3dv_t *q) } #endif #if !defined(M3D_NOANIMATION) || !defined(M3D_NONORMALS) -/* fast inverse square root calculation. returns 1/sqrt(x) */ +/* portable fast inverse square root calculation. returns 1/sqrt(x) */ static M3D_FLOAT _m3d_rsq(M3D_FLOAT x) { #ifdef M3D_DOUBLE @@ -3053,12 +3056,12 @@ memerr: M3D_LOG("Out of memory"); for(i = 0, data += sizeof(m3dchunk_t); data < chunk; i++) { switch(model->vc_s) { case 1: - model->tmap[i].u = (M3D_FLOAT)(data[0]) / 255; - model->tmap[i].v = (M3D_FLOAT)(data[1]) / 255; + model->tmap[i].u = (M3D_FLOAT)(data[0]) / (M3D_FLOAT)255.0; + model->tmap[i].v = (M3D_FLOAT)(data[1]) / (M3D_FLOAT)255.0; break; case 2: - model->tmap[i].u = (M3D_FLOAT)(*((int16_t*)(data+0))) / 65535; - model->tmap[i].v = (M3D_FLOAT)(*((int16_t*)(data+2))) / 65535; + model->tmap[i].u = (M3D_FLOAT)(*((int16_t*)(data+0))) / (M3D_FLOAT)65535.0; + model->tmap[i].v = (M3D_FLOAT)(*((int16_t*)(data+2))) / (M3D_FLOAT)65535.0; break; case 4: model->tmap[i].u = (M3D_FLOAT)(*((float*)(data+0))); @@ -3085,17 +3088,17 @@ memerr: M3D_LOG("Out of memory"); for(i = 0, data += sizeof(m3dchunk_t); data < chunk && i < model->numvertex; i++) { switch(model->vc_s) { case 1: - model->vertex[i].x = (M3D_FLOAT)((int8_t)data[0]) / 127; - model->vertex[i].y = (M3D_FLOAT)((int8_t)data[1]) / 127; - model->vertex[i].z = (M3D_FLOAT)((int8_t)data[2]) / 127; - model->vertex[i].w = (M3D_FLOAT)((int8_t)data[3]) / 127; + model->vertex[i].x = (M3D_FLOAT)((int8_t)data[0]) / (M3D_FLOAT)127.0; + model->vertex[i].y = (M3D_FLOAT)((int8_t)data[1]) / (M3D_FLOAT)127.0; + model->vertex[i].z = (M3D_FLOAT)((int8_t)data[2]) / (M3D_FLOAT)127.0; + model->vertex[i].w = (M3D_FLOAT)((int8_t)data[3]) / (M3D_FLOAT)127.0; data += 4; break; case 2: - model->vertex[i].x = (M3D_FLOAT)(*((int16_t*)(data+0))) / 32767; - model->vertex[i].y = (M3D_FLOAT)(*((int16_t*)(data+2))) / 32767; - model->vertex[i].z = (M3D_FLOAT)(*((int16_t*)(data+4))) / 32767; - model->vertex[i].w = (M3D_FLOAT)(*((int16_t*)(data+6))) / 32767; + model->vertex[i].x = (M3D_FLOAT)(*((int16_t*)(data+0))) / (M3D_FLOAT)32767.0; + model->vertex[i].y = (M3D_FLOAT)(*((int16_t*)(data+2))) / (M3D_FLOAT)32767.0; + model->vertex[i].z = (M3D_FLOAT)(*((int16_t*)(data+4))) / (M3D_FLOAT)32767.0; + model->vertex[i].w = (M3D_FLOAT)(*((int16_t*)(data+6))) / (M3D_FLOAT)32767.0; data += 8; break; case 4: @@ -3167,7 +3170,7 @@ memerr: M3D_LOG("Out of memory"); if(j >= M3D_NUMBONE) data += model->bi_s; else { - model->skin[i].weight[j] = (M3D_FLOAT)(weights[j]) / 255; + model->skin[i].weight[j] = (M3D_FLOAT)(weights[j]) / (M3D_FLOAT)255.0; w += model->skin[i].weight[j]; data = _m3d_getidx(data, model->bi_s, &model->skin[i].boneid[j]); } @@ -4036,16 +4039,16 @@ static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) /* round according to quality */ switch(quality) { case M3D_EXP_INT8: - t = src->x * 127 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / (M3D_FLOAT)127.0; - t = src->y * 127 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / (M3D_FLOAT)127.0; - t = src->z * 127 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / (M3D_FLOAT)127.0; - t = src->w * 127 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / (M3D_FLOAT)127.0; + t = (int)(src->x * 127 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->x = (M3D_FLOAT)t / (M3D_FLOAT)127.0; + t = (int)(src->y * 127 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->y = (M3D_FLOAT)t / (M3D_FLOAT)127.0; + t = (int)(src->z * 127 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->z = (M3D_FLOAT)t / (M3D_FLOAT)127.0; + t = (int)(src->w * 127 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->w = (M3D_FLOAT)t / (M3D_FLOAT)127.0; break; case M3D_EXP_INT16: - t = src->x * 32767 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->x = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; - t = src->y * 32767 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->y = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; - t = src->z * 32767 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->z = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; - t = src->w * 32767 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5); dst->w = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; + t = (int)(src->x * 32767 + (src->x >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->x = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; + t = (int)(src->y * 32767 + (src->y >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->y = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; + t = (int)(src->z * 32767 + (src->z >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->z = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; + t = (int)(src->w * 32767 + (src->w >= 0 ? (M3D_FLOAT)0.5 : (M3D_FLOAT)-0.5)); dst->w = (M3D_FLOAT)t / (M3D_FLOAT)32767.0; break; } if(dst->x == (M3D_FLOAT)-0.0) dst->x = (M3D_FLOAT)0.0; @@ -4351,12 +4354,12 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size if(tmapidx[i] == M3D_UNDEF) continue; switch(quality) { case M3D_EXP_INT8: - l = model->tmap[i].u * 255; tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)255.0; - l = model->tmap[i].v * 255; tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)255.0; + l = (unsigned int)(model->tmap[i].u * 255); tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)255.0; + l = (unsigned int)(model->tmap[i].v * 255); tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)255.0; break; case M3D_EXP_INT16: - l = model->tmap[i].u * 65535; tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)65535.0; - l = model->tmap[i].v * 65535; tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)65535.0; + l = (unsigned int)(model->tmap[i].u * 65535); tcoord.data.u = (M3D_FLOAT)l / (M3D_FLOAT)65535.0; + l = (unsigned int)(model->tmap[i].v * 65535); tcoord.data.v = (M3D_FLOAT)l / (M3D_FLOAT)65535.0; break; default: tcoord.data.u = model->tmap[i].u; From e17431b993ec946587af4727a68edb617bf16653 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 11 Dec 2019 06:21:35 +0100 Subject: [PATCH 141/170] Added extra check for file size --- code/M3D/M3DImporter.cpp | 4 ++++ code/M3D/M3DWrapper.cpp | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 6627d1f74..a183f8bda 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -159,6 +159,10 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys if (fileSize != pStream->Read(buffer.data(), 1, fileSize)) { throw DeadlyImportError("Failed to read the file " + file + "."); } + // extra check for binary format's first 8 bytes. Not done for the ASCII variant + if(!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) { + throw DeadlyImportError("Bad binary header in file " + file + "."); + } // Get the path for external assets std::string folderName("./"); diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp index 0060c894e..d8fba4839 100644 --- a/code/M3D/M3DWrapper.cpp +++ b/code/M3D/M3DWrapper.cpp @@ -75,7 +75,8 @@ unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { (reinterpret_cast(m3dimporter_pIOHandler))->Open(file, "rb")); size_t fileSize = 0; unsigned char *data = NULL; - // sometimes pStream is nullptr for some reason (should be an empty object returning nothing I guess) + // sometimes pStream is nullptr in a single-threaded scenario too for some reason + // (should be an empty object returning nothing I guess) if (pStream) { fileSize = pStream->FileSize(); // should be allocated with malloc(), because the library will call free() to deallocate @@ -101,7 +102,7 @@ M3DWrapper::M3DWrapper() { M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector &buffer) { #if AI_M3D_USE_STDMUTEX - // M3D is NOT thread-safe, so lock the global mutex + // M3D is thread-safe, but pIOHandler is NOT, so lock the global mutex const std::lock_guard lock(file_mutex); #endif // pass this IOHandler to the C callback From b70c05b4e0bd38e034af81a7ec40cfd7d38d292d Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 12 Dec 2019 09:38:50 +0000 Subject: [PATCH 142/170] Fix texcoords. --- code/glTF2/glTF2Importer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index dd80aeba9..9b416850f 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -201,6 +201,7 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset } mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); + mat->AddProperty(&prop.texCoord, 1, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(texType, texSlot)); if (prop.textureTransformSupported) { aiUVTransform transform; From 2124da83406e6cbb5bcc3b5030702daa7173eec1 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 12 Dec 2019 12:06:36 +0000 Subject: [PATCH 143/170] Add a texcoord unit test. --- .../glTF2/BoxTexcoords-glTF/boxTexcoords.bin | Bin 0 -> 1032 bytes .../glTF2/BoxTexcoords-glTF/boxTexcoords.gltf | 172 ++++++++++++++++++ .../glTF2/BoxTexcoords-glTF/texture.png | Bin 0 -> 41302 bytes test/unit/utglTF2ImportExport.cpp | 29 +++ 4 files changed, 201 insertions(+) create mode 100644 test/models/glTF2/BoxTexcoords-glTF/boxTexcoords.bin create mode 100644 test/models/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf create mode 100644 test/models/glTF2/BoxTexcoords-glTF/texture.png diff --git a/test/models/glTF2/BoxTexcoords-glTF/boxTexcoords.bin b/test/models/glTF2/BoxTexcoords-glTF/boxTexcoords.bin new file mode 100644 index 0000000000000000000000000000000000000000..ae6a3f0d12d2a157502364f55961b4da73a3d7bb GIT binary patch literal 1032 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 N=jH?5${Y4k{|Du~q|yKY literal 0 HcmV?d00001 diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index ef1316fb7..006471436 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -47,6 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + using namespace Assimp; class utglTF2ImportExport : public AbstractImportExportBase { @@ -436,3 +438,30 @@ TEST_F(utglTF2ImportExport, error_string_preserved) { } #endif // ASSIMP_BUILD_NO_EXPORT + +TEST_F(utglTF2ImportExport, texcoords) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", + aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + + ASSERT_TRUE(scene->HasMaterials()); + const aiMaterial *material = scene->mMaterials[0]; + + aiString path; + aiTextureMapMode modes[2]; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, + nullptr, nullptr, modes)); + EXPECT_STREQ(path.C_Str(), "texture.png"); + + int uvIndex = -1; + EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_DIFFUSE, 0), &uvIndex), aiReturn_SUCCESS); + EXPECT_EQ(uvIndex, 0); + + // Using manual macro expansion of AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE here. + // The following works with some but not all compilers: + // #define APPLY(X, Y) X(Y) + // ..., APPLY(AI_MATKEY_GLTF_TEXTURE_TEXCOORD, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE), ... + EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_UNKNOWN, 0), &uvIndex), aiReturn_SUCCESS); + EXPECT_EQ(uvIndex, 1); +} From 30634ff56e4f9cfcab3af5fa7a523be7c2a6bca1 Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 13 Dec 2019 06:38:49 +0100 Subject: [PATCH 144/170] Be more tolerant to invalid input --- code/M3D/m3d.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 1b79fb785..25baacc24 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -2994,11 +2994,11 @@ asciiend: while(buff < end && !M3D_CHUNKMAGIC(buff, 'O','M','D','3')) { data = buff; len = ((m3dchunk_t*)data)->length; - if(len < sizeof(m3dchunk_t)) { + buff += len; + if(len < sizeof(m3dchunk_t) || buff >= end) { M3D_LOG("Invalid chunk size"); break; } - buff += len; len -= sizeof(m3dchunk_t) + model->si_s; /* inlined assets */ @@ -3024,11 +3024,11 @@ memerr: M3D_LOG("Out of memory"); while(chunk < end && !M3D_CHUNKMAGIC(chunk, 'O','M','D','3')) { data = chunk; len = ((m3dchunk_t*)chunk)->length; - if(len < sizeof(m3dchunk_t)) { + chunk += len; + if(len < sizeof(m3dchunk_t) || chunk >= end) { M3D_LOG("Invalid chunk size"); break; } - chunk += len; len -= sizeof(m3dchunk_t); /* preview chunk */ From 6b2fe41a3bdfe9f124caa964385c7047ae619f74 Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 13 Dec 2019 07:30:59 +0100 Subject: [PATCH 145/170] Replaced mutex with thread-local variable --- code/M3D/M3DWrapper.cpp | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp index d8fba4839..46f3278cb 100644 --- a/code/M3D/M3DWrapper.cpp +++ b/code/M3D/M3DWrapper.cpp @@ -48,24 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#ifndef AI_M3D_USE_STDMUTEX -#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards -#define AI_M3D_USE_STDMUTEX 1 -#else -#define AI_M3D_USE_STDMUTEX 0 -#endif -#endif - -#if AI_M3D_USE_STDMUTEX -#include -std::mutex file_mutex; -#endif - // workaround: the M3D SDK expects a C callback, but we want to use Assimp::IOSystem to implement that -// This makes it non-rentrant so lock a mutex (requires C++11) extern "C" { -void *m3dimporter_pIOHandler; +thread_local void *m3dimporter_pIOHandler; unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { ai_assert(nullptr != fn); @@ -101,11 +87,7 @@ M3DWrapper::M3DWrapper() { } M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector &buffer) { -#if AI_M3D_USE_STDMUTEX - // M3D is thread-safe, but pIOHandler is NOT, so lock the global mutex - const std::lock_guard lock(file_mutex); -#endif - // pass this IOHandler to the C callback + // pass this IOHandler to the C callback in a thread-local pointer m3dimporter_pIOHandler = pIOHandler; m3d_ = m3d_load(const_cast(buffer.data()), m3dimporter_readfile, free, nullptr); // Clear the C callback From 32835873f0bb34d440a07b2339fbb3e9f9e37faa Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 13 Dec 2019 08:19:39 +0100 Subject: [PATCH 146/170] Update m3d.h Fix review warning. --- code/M3D/m3d.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 25baacc24..5d78374f0 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -87,7 +87,11 @@ typedef uint16_t M3D_INDEX; #ifndef _MSC_VER #define _inline __inline__ #define _pack __attribute__((packed)) -#define _unused __attribute__((unused)) +# ifdef __cplusplus // only for c++ code +# define _unused __attribute__((unused)) +# else // or c code just use void +# define _unused (void) +# endif #else #define _inline #define _pack From 8be1060ec4eed9b498109e5cb922215e63c20f2f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 13 Dec 2019 08:21:45 +0100 Subject: [PATCH 147/170] Update m3d.h Fix vs-defines for unused define as well. --- code/M3D/m3d.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 5d78374f0..a36cc9613 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -95,7 +95,11 @@ typedef uint16_t M3D_INDEX; #else #define _inline #define _pack -#define _unused __pragma(warning(suppress:4100)) +# ifdef __cplusplus // only for c++ code +# define _unused __pragma(warning(suppress:4100)) +# else // or c code just use void +# define _unused (void) +# endif // ___cplusplus #endif #ifndef __cplusplus #define _register register From f151a5d11db0330cbbc7fbde3b4b76c328357b25 Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 13 Dec 2019 09:04:40 +0100 Subject: [PATCH 148/170] MSVC2013 alternative to thread_local --- code/M3D/M3DWrapper.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp index 46f3278cb..c0de1cf31 100644 --- a/code/M3D/M3DWrapper.cpp +++ b/code/M3D/M3DWrapper.cpp @@ -48,10 +48,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -// workaround: the M3D SDK expects a C callback, but we want to use Assimp::IOSystem to implement that +#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards +# define threadlocal thread_local +#else +# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013 +# define threadlocal __declspec(thread) +# else +# define threadlocal +# endif +#endif extern "C" { -thread_local void *m3dimporter_pIOHandler; + +// workaround: the M3D SDK expects a C callback, but we want to use Assimp::IOSystem to implement that +threadlocal void *m3dimporter_pIOHandler; unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { ai_assert(nullptr != fn); From 512e6dff4fd3ba597e90f2d727813c522561d723 Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 13 Dec 2019 09:16:41 +0100 Subject: [PATCH 149/170] Fixed ANSI C compiler issue --- code/M3D/m3d.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index a36cc9613..5ab9f14c0 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -87,19 +87,15 @@ typedef uint16_t M3D_INDEX; #ifndef _MSC_VER #define _inline __inline__ #define _pack __attribute__((packed)) -# ifdef __cplusplus // only for c++ code -# define _unused __attribute__((unused)) -# else // or c code just use void -# define _unused (void) -# endif +#define _unused __attribute__((unused)) #else #define _inline #define _pack -# ifdef __cplusplus // only for c++ code +# ifdef __cplusplus /* only for c++ code */ # define _unused __pragma(warning(suppress:4100)) -# else // or c code just use void +# else # define _unused (void) -# endif // ___cplusplus +# endif #endif #ifndef __cplusplus #define _register register From a10b0d4de3061e11d430898f0d7a14a2ee18246e Mon Sep 17 00:00:00 2001 From: bzt Date: Sat, 14 Dec 2019 08:52:48 +0100 Subject: [PATCH 150/170] Requested modifications --- code/M3D/M3DExporter.cpp | 35 ++++++++++++++--- code/M3D/M3DImporter.cpp | 82 ++++++++++++++++++++++++++-------------- code/M3D/M3DWrapper.cpp | 21 ++++++---- code/M3D/M3DWrapper.h | 4 ++ code/M3D/m3d.h | 57 ++++++++++++++-------------- 5 files changed, 130 insertions(+), 69 deletions(-) diff --git a/code/M3D/M3DExporter.cpp b/code/M3D/M3DExporter.cpp index faf5a9585..a3988db0b 100644 --- a/code/M3D/M3DExporter.cpp +++ b/code/M3D/M3DExporter.cpp @@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define M3D_IMPLEMENTATION #define M3D_NOIMPORTER #define M3D_EXPORTER -#define M3D_ASCII #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER #define M3D_NODUP #endif @@ -65,9 +64,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include "M3DWrapper.h" #include "M3DExporter.h" #include "M3DMaterials.h" -#include "M3DWrapper.h" // RESOURCES: // https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md @@ -131,6 +130,28 @@ void addProp(m3dm_t *m, uint8_t type, uint32_t value) { m->prop[i].value.num = value; } +// ------------------------------------------------------------------------------------------------ +// convert aiString to identifier safe C string. This is a duplication of _m3d_safestr +char *SafeStr(aiString str, bool isStrict) +{ + char *s = (char *)&str.data; + char *d, *ret; + int i, len; + + for(len = str.length + 1; *s && (*s == ' ' || *s == '\t'); s++, len--); + if(len > 255) len = 255; + ret = (char *)M3D_MALLOC(len + 1); + if (!ret) { + throw DeadlyExportError("memory allocation error"); + } + for(i = 0, d = ret; i < len && *s && *s != '\r' && *s != '\n'; s++, d++, i++) { + *d = isStrict && (*s == ' ' || *s == '\t' || *s == '/' || *s == '\\') ? '_' : (*s == '\t' ? ' ' : *s); + } + for(; d > ret && (*(d-1) == ' ' || *(d-1) == '\t'); d--); + *d = 0; + return ret; +} + // ------------------------------------------------------------------------------------------------ // add a material to the output M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { @@ -157,7 +178,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { if (!m3d->material) { throw DeadlyExportError("memory allocation error"); } - m3d->material[mi].name = _m3d_safestr((char *)&name.data, 0); + m3d->material[mi].name = SafeStr(name, true); m3d->material[mi].numprop = 0; m3d->material[mi].prop = NULL; // iterate through the material property table and see what we got @@ -218,7 +239,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) { (name.data[j + 1] == 'g' || name.data[j + 1] == 'G')) name.data[j] = 0; // do we have this texture saved already? - fn = _m3d_safestr((char *)&name.data, 0); + fn = SafeStr(name, true); for (j = 0, i = M3D_NOTDEFINED; j < m3d->numtexture; j++) if (!strcmp(fn, m3d->texture[j].name)) { i = j; @@ -275,11 +296,15 @@ void ExportSceneA3D( const ExportProperties *pProperties ) { +#ifdef M3D_ASCII // initialize the exporter M3DExporter exporter(pScene, pProperties); // perform ascii export exporter.doExport(pFile, pIOSystem, true); +#else + throw DeadlyExportError("Assimp configured without M3D_ASCII support"); +#endif } // ------------------------------------------------------------------------------------------------ @@ -306,7 +331,7 @@ void M3DExporter::doExport( if (!m3d) { throw DeadlyExportError("memory allocation error"); } - m3d->name = _m3d_safestr((char *)&mScene->mRootNode->mName.data, 2); + m3d->name = SafeStr(mScene->mRootNode->mName, false); // Create a model from assimp structures aiMatrix4x4 m; diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index a183f8bda..a77e75a27 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER #define M3D_IMPLEMENTATION -#define M3D_ASCII #define M3D_NONORMALS /* leave the post-processing to Assimp */ #define M3D_NOWEIGHTS #define M3D_NOANIMATION @@ -57,9 +56,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include "M3DWrapper.h" #include "M3DImporter.h" #include "M3DMaterials.h" -#include "M3DWrapper.h" // RESOURCES: // https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md @@ -96,7 +95,11 @@ static const aiImporterDesc desc = { 0, 0, 0, +#ifdef M3D_ASCII "m3d a3d" +#else + "m3d" +#endif }; namespace Assimp { @@ -113,7 +116,11 @@ M3DImporter::M3DImporter() : bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); - if (extension == "m3d" || extension == "a3d") + if (extension == "m3d" +#ifdef M3D_ASCII + || extension == "a3d" +#endif + ) return true; else if (!extension.length() || checkSig) { if (!pIOHandler) { @@ -131,7 +138,11 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c if (4 != pStream->Read(data, 1, 4)) { return false; } - return !memcmp(data, "3DMO", 4) /* bin */ || !memcmp(data, "3dmo", 4) /* ASCII */; + return !memcmp(data, "3DMO", 4) /* bin */ +#ifdef M3D_ASCII + || !memcmp(data, "3dmo", 4) /* ASCII */ +#endif + ; } return false; } @@ -163,6 +174,12 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys if(!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) { throw DeadlyImportError("Bad binary header in file " + file + "."); } +#ifdef M3D_ASCII + // make sure there's a terminator zero character, as input must be ASCIIZ + if(!memcmp(buffer.data(), "3dmo", 4)) { + buffer.push_back(0); + } +#endif // Get the path for external assets std::string folderName("./"); @@ -180,7 +197,6 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys // let the C SDK do the hard work for us M3DWrapper m3d(pIOHandler, buffer); - if (!m3d) { throw DeadlyImportError("Unable to parse " + file + " as M3D."); } @@ -310,32 +326,40 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { for (i = 0; i < m3d->numtexture; i++) { unsigned int j, k; t = &m3d->texture[i]; - if (!t->w || !t->h || !t->f || !t->d) continue; aiTexture *tx = new aiTexture; - strcpy(tx->achFormatHint, formatHint[t->f - 1]); tx->mFilename = aiString(std::string(t->name) + ".png"); - tx->mWidth = t->w; - tx->mHeight = t->h; - tx->pcData = new aiTexel[tx->mWidth * tx->mHeight]; - for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) { - switch (t->f) { - case 1: tx->pcData[j].g = t->d[k++]; break; - case 2: - tx->pcData[j].g = t->d[k++]; - tx->pcData[j].a = t->d[k++]; - break; - case 3: - tx->pcData[j].r = t->d[k++]; - tx->pcData[j].g = t->d[k++]; - tx->pcData[j].b = t->d[k++]; - tx->pcData[j].a = 255; - break; - case 4: - tx->pcData[j].r = t->d[k++]; - tx->pcData[j].g = t->d[k++]; - tx->pcData[j].b = t->d[k++]; - tx->pcData[j].a = t->d[k++]; - break; + if (!t->w || !t->h || !t->f || !t->d) { + /* without ASSIMP_USE_M3D_READFILECB, we only have the filename, but no texture data ever */ + tx->mWidth = 0; + tx->mHeight = 0; + memcpy(tx->achFormatHint, "png\000", 4); + tx->pcData = nullptr; + } else { + /* if we have the texture loaded, set format hint and pcData too */ + tx->mWidth = t->w; + tx->mHeight = t->h; + strcpy(tx->achFormatHint, formatHint[t->f - 1]); + tx->pcData = new aiTexel[tx->mWidth * tx->mHeight]; + for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) { + switch (t->f) { + case 1: tx->pcData[j].g = t->d[k++]; break; + case 2: + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].a = t->d[k++]; + break; + case 3: + tx->pcData[j].r = t->d[k++]; + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; + tx->pcData[j].a = 255; + break; + case 4: + tx->pcData[j].r = t->d[k++]; + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; + tx->pcData[j].a = t->d[k++]; + break; + } } } mScene->mTextures[i] = tx; diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp index c0de1cf31..28eda845f 100644 --- a/code/M3D/M3DWrapper.cpp +++ b/code/M3D/M3DWrapper.cpp @@ -48,15 +48,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards -# define threadlocal thread_local -#else -# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013 -# define threadlocal __declspec(thread) +#ifdef ASSIMP_USE_M3D_READFILECB + +# if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards +# define threadlocal thread_local # else -# define threadlocal +# if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013 +# define threadlocal __declspec(thread) +# else +# define threadlocal +# endif # endif -#endif extern "C" { @@ -89,6 +91,7 @@ unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) { return data; } } +#endif namespace Assimp { M3DWrapper::M3DWrapper() { @@ -97,11 +100,15 @@ M3DWrapper::M3DWrapper() { } M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector &buffer) { +#ifdef ASSIMP_USE_M3D_READFILECB // pass this IOHandler to the C callback in a thread-local pointer m3dimporter_pIOHandler = pIOHandler; m3d_ = m3d_load(const_cast(buffer.data()), m3dimporter_readfile, free, nullptr); // Clear the C callback m3dimporter_pIOHandler = nullptr; +#else + m3d_ = m3d_load(const_cast(buffer.data()), nullptr, nullptr, nullptr); +#endif } M3DWrapper::~M3DWrapper() { diff --git a/code/M3D/M3DWrapper.h b/code/M3D/M3DWrapper.h index f404d3d4b..4ceac12ad 100644 --- a/code/M3D/M3DWrapper.h +++ b/code/M3D/M3DWrapper.h @@ -52,6 +52,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +// Assimp specific M3D configuration. Comment out these defines to remove functionality +#define ASSIMP_USE_M3D_READFILECB +#define M3D_ASCII + #include "m3d.h" namespace Assimp { diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index 5ab9f14c0..edf5d9623 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -91,11 +91,7 @@ typedef uint16_t M3D_INDEX; #else #define _inline #define _pack -# ifdef __cplusplus /* only for c++ code */ -# define _unused __pragma(warning(suppress:4100)) -# else -# define _unused (void) -# endif +#define _unused __pragma(warning(suppress:4100)) #endif #ifndef __cplusplus #define _register register @@ -2064,7 +2060,7 @@ static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) return _m3d_findarg(e); } #endif -#if !defined(M3D_NODUP) && (defined(M3D_ASCII) || defined(M3D_EXPORTER)) +#if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_ASCII) || defined(M3D_EXPORTER)) /* helper function to create safe strings */ char *_m3d_safestr(char *in, int morelines) { @@ -2139,45 +2135,48 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char buff = (*readfilecb)(fn2, &len); M3D_FREE(fn2); } - if(!buff) + if(!buff) { buff = (*readfilecb)(fn, &len); + if(!buff) return M3D_UNDEF; + } } - if(!buff) return M3D_UNDEF; /* add to textures array */ i = model->numtexture++; model->texture = (m3dtx_t*)M3D_REALLOC(model->texture, model->numtexture * sizeof(m3dtx_t)); if(!model->texture) { - if(freecb) (*freecb)(buff); + if(buff && freecb) (*freecb)(buff); model->errcode = M3D_ERR_ALLOC; return M3D_UNDEF; } model->texture[i].name = fn; model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL; - if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') { + if(buff) { + if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') { #ifdef STBI__PNG_TYPE - s.read_from_callbacks = 0; - s.img_buffer = s.img_buffer_original = (unsigned char *) buff; - s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len; - /* don't use model->texture[i].w directly, it's a uint16_t */ - w = h = len = 0; - ri.bits_per_channel = 8; - model->texture[i].d = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, 0, &ri); - model->texture[i].w = w; - model->texture[i].h = h; - model->texture[i].f = (uint8_t)len; + s.read_from_callbacks = 0; + s.img_buffer = s.img_buffer_original = (unsigned char *) buff; + s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len; + /* don't use model->texture[i].w directly, it's a uint16_t */ + w = h = len = 0; + ri.bits_per_channel = 8; + model->texture[i].d = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, 0, &ri); + model->texture[i].w = w; + model->texture[i].h = h; + model->texture[i].f = (uint8_t)len; #endif - } else { + } else { #ifdef M3D_TX_INTERP - if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) { - M3D_LOG("Unable to generate texture"); - M3D_LOG(fn); - } + if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) { + M3D_LOG("Unable to generate texture"); + M3D_LOG(fn); + } #else - M3D_LOG("Unimplemented interpreter"); - M3D_LOG(fn); + M3D_LOG("Unimplemented interpreter"); + M3D_LOG(fn); #endif + } + if(freecb) (*freecb)(buff); } - if(freecb) (*freecb)(buff); if(!model->texture[i].d) model->errcode = M3D_ERR_UNKIMG; return i; @@ -2589,6 +2588,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d if(!pe || !*pe) goto asciiend; m->prop[j].value.textureid = _m3d_gettx(model, readfilecb, freecb, pe); if(model->errcode == M3D_ERR_ALLOC) { M3D_FREE(pe); goto memerr; } + /* this error code only returned if readfilecb was specified */ if(m->prop[j].value.textureid == M3D_UNDEF) { M3D_LOG("Texture not found"); M3D_LOG(pe); @@ -3254,6 +3254,7 @@ memerr: M3D_LOG("Out of memory"); M3D_GETSTR(name); m->prop[i].value.textureid = _m3d_gettx(model, readfilecb, freecb, name); if(model->errcode == M3D_ERR_ALLOC) goto memerr; + /* this error code only returned if readfilecb was specified */ if(m->prop[i].value.textureid == M3D_UNDEF) { M3D_LOG("Texture not found"); M3D_LOG(m->name); From 8a800e7aa5df8b18d815b1bab5722e48814e8999 Mon Sep 17 00:00:00 2001 From: bzt Date: Sun, 15 Dec 2019 12:25:34 +0100 Subject: [PATCH 151/170] Removed functionality and minor material-mapping fix --- code/M3D/M3DMaterials.h | 6 +++--- code/M3D/M3DWrapper.h | 4 ++-- code/M3D/m3d.h | 4 +++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/code/M3D/M3DMaterials.h b/code/M3D/M3DMaterials.h index 3d6fe246d..4aeba59e4 100644 --- a/code/M3D/M3DMaterials.h +++ b/code/M3D/M3DMaterials.h @@ -84,19 +84,19 @@ static const aiMatProp aiProps[] = { /* --- Texture Map Properties --- !!!!! must match m3d_propertytypes !!!!! */ static const aiMatProp aiTxProps[] = { { AI_MATKEY_TEXTURE_DIFFUSE(0) }, /* m3dp_map_Kd */ - { AI_MATKEY_TEXTURE_AMBIENT(0) }, /* m3dp_map_Ka */ + { AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION,0) },/* m3dp_map_Ka */ { AI_MATKEY_TEXTURE_SPECULAR(0) }, /* m3dp_map_Ks */ { AI_MATKEY_TEXTURE_SHININESS(0) }, /* m3dp_map_Ns */ { AI_MATKEY_TEXTURE_EMISSIVE(0) }, /* m3dp_map_Ke */ { NULL, 0, 0 }, /* m3dp_map_Tf */ { AI_MATKEY_TEXTURE_HEIGHT(0) }, /* m3dp_bump */ { AI_MATKEY_TEXTURE_OPACITY(0) }, /* m3dp_map_d */ - { AI_MATKEY_TEXTURE_REFLECTION(0) }, /* m3dp_refl */ + { AI_MATKEY_TEXTURE_NORMALS(0) }, /* m3dp_map_N */ { AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */ { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) }, /* m3dp_map_Pm */ { NULL, 0, 0 }, /* m3dp_map_Ps */ - { AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION,0) },/* m3dp_map_Ni */ + { AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,0) }, /* m3dp_map_Ni */ { NULL, 0, 0 }, /* m3dp_map_Nt */ { NULL, 0, 0 }, { NULL, 0, 0 }, diff --git a/code/M3D/M3DWrapper.h b/code/M3D/M3DWrapper.h index 4ceac12ad..b4f90ff1f 100644 --- a/code/M3D/M3DWrapper.h +++ b/code/M3D/M3DWrapper.h @@ -53,8 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include // Assimp specific M3D configuration. Comment out these defines to remove functionality -#define ASSIMP_USE_M3D_READFILECB -#define M3D_ASCII +//#define ASSIMP_USE_M3D_READFILECB +//#define M3D_ASCII #include "m3d.h" diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index edf5d9623..d09348497 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -256,7 +256,7 @@ enum { m3dp_map_Tf, m3dp_map_Km, /* bump map */ m3dp_map_D, - m3dp_map_il, /* reflection map */ + m3dp_map_N, /* normal map */ m3dp_map_Pr = 192, /* textured physical map properties */ m3dp_map_Pm, @@ -266,6 +266,7 @@ enum { }; enum { /* aliases */ m3dp_bump = m3dp_map_Km, + m3dp_map_il = m3dp_map_N, m3dp_refl = m3dp_map_Pm }; @@ -560,6 +561,7 @@ static m3dpd_t m3d_propertytypes[] = { /* aliases, note that "map_*" aliases are handled automatically */ M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Km, "bump"), + M3D_PROPERTYDEF(m3dpf_map, m3dp_map_N, "map_N"),/* as normal map has no scalar version, it's counterpart is 'il' */ M3D_PROPERTYDEF(m3dpf_map, m3dp_map_Pm, "refl") }; /* shape command definitions. if more commands start with the same string, the longer must come first */ From eed0bd3ef6fcb79d683fe9b2c0f65afd7d5c12c2 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Mon, 16 Dec 2019 10:26:46 -0500 Subject: [PATCH 152/170] Added support to load Half-Life 1 MDL files. Added code to use Half-Life 1 MDL loader in MDLLoader.cpp. Added Half-Life 1 MDL loader files to CMakeLists. Added new options in config.h to use with Half-Life 1 MDL loader. --- code/CMakeLists.txt | 10 + code/MDL/HalfLife/HL1FileData.h | 355 ++++++ code/MDL/HalfLife/HL1ImportDefinitions.h | 64 + code/MDL/HalfLife/HL1ImportSettings.h | 85 ++ code/MDL/HalfLife/HL1MDLLoader.cpp | 1331 +++++++++++++++++++++ code/MDL/HalfLife/HL1MDLLoader.h | 235 ++++ code/MDL/HalfLife/HL1MeshTrivert.h | 127 ++ code/MDL/HalfLife/HalfLifeMDLBaseHeader.h | 64 + code/MDL/HalfLife/LogFunctions.h | 95 ++ code/MDL/HalfLife/UniqueNameGenerator.cpp | 180 +++ code/MDL/HalfLife/UniqueNameGenerator.h | 81 ++ code/MDL/MDLLoader.cpp | 44 +- code/MDL/MDLLoader.h | 10 + include/assimp/config.h.in | 67 ++ 14 files changed, 2746 insertions(+), 2 deletions(-) create mode 100644 code/MDL/HalfLife/HL1FileData.h create mode 100644 code/MDL/HalfLife/HL1ImportDefinitions.h create mode 100644 code/MDL/HalfLife/HL1ImportSettings.h create mode 100644 code/MDL/HalfLife/HL1MDLLoader.cpp create mode 100644 code/MDL/HalfLife/HL1MDLLoader.h create mode 100644 code/MDL/HalfLife/HL1MeshTrivert.h create mode 100644 code/MDL/HalfLife/HalfLifeMDLBaseHeader.h create mode 100644 code/MDL/HalfLife/LogFunctions.h create mode 100644 code/MDL/HalfLife/UniqueNameGenerator.cpp create mode 100644 code/MDL/HalfLife/UniqueNameGenerator.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 85aa620d9..342433e46 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -454,6 +454,16 @@ ADD_ASSIMP_IMPORTER( MDL MDL/MDLLoader.cpp MDL/MDLLoader.h MDL/MDLMaterialLoader.cpp + MDL/HalfLife/HalfLifeMDLBaseHeader.h + MDL/HalfLife/HL1FileData.h + MDL/HalfLife/HL1MDLLoader.cpp + MDL/HalfLife/HL1MDLLoader.h + MDL/HalfLife/HL1ImportDefinitions.h + MDL/HalfLife/HL1ImportSettings.h + MDL/HalfLife/HL1MeshTrivert.h + MDL/HalfLife/LogFunctions.h + MDL/HalfLife/UniqueNameGenerator.cpp + MDL/HalfLife/UniqueNameGenerator.h ) SET( MaterialSystem_SRCS diff --git a/code/MDL/HalfLife/HL1FileData.h b/code/MDL/HalfLife/HL1FileData.h new file mode 100644 index 000000000..939687a8f --- /dev/null +++ b/code/MDL/HalfLife/HL1FileData.h @@ -0,0 +1,355 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file HL1FileData.h + * @brief Definition of in-memory structures for the + * Half-Life 1 MDL file format. + */ + +#ifndef AI_HL1FILEDATA_INCLUDED +#define AI_HL1FILEDATA_INCLUDED + +#include "HalfLifeMDLBaseHeader.h" + +#include +#include + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +using vec3_t = float[3]; + +struct Header_HL1 : HalfLifeMDLBaseHeader { + char name[64]; + int32_t length; + + vec3_t eyeposition; // ideal eye position + vec3_t min; // ideal movement hull size + vec3_t max; + + vec3_t bbmin; // clipping bounding box + vec3_t bbmax; + + int32_t unused; // was flags + + int32_t numbones; // bones + int32_t boneindex; + + int32_t numbonecontrollers; // bone controllers + int32_t bonecontrollerindex; + + int32_t numhitboxes; // complex bounding boxes + int32_t hitboxindex; + + int32_t numseq; // animation sequences + int32_t seqindex; + + int32_t numseqgroups; // demand loaded sequences + int32_t seqgroupindex; + + int32_t numtextures; // raw textures + int32_t textureindex; + int32_t texturedataindex; + + int32_t numskinref; // replaceable textures + int32_t numskinfamilies; + int32_t skinindex; + + int32_t numbodyparts; + int32_t bodypartindex; + + int32_t numattachments; // queryable attachable points + int32_t attachmentindex; + + int32_t unused2; // was "soundtable" + int32_t unused3; // was "soundindex" + int32_t unused4; // was "soundgroups" + int32_t unused5; // was "soundgroupindex" + + int32_t numtransitions; // animation node to animation node transition graph + int32_t transitionindex; +} PACK_STRUCT; + +// header for demand loaded sequence group data +struct SequenceHeader_HL1 : HalfLifeMDLBaseHeader { + char name[64]; + int32_t length; +} PACK_STRUCT; + +// bones +struct Bone_HL1 { + char name[32]; // bone name for symbolic links + int32_t parent; // parent bone + int32_t unused; // was "flags" -- ?? + int32_t bonecontroller[6]; // bone controller index, -1 == none + float value[6]; // default DoF values + float scale[6]; // scale for delta DoF values +} PACK_STRUCT; + +// bone controllers +struct BoneController_HL1 { + int32_t bone; // -1 == 0 + int32_t type; // X, Y, Z, XR, YR, ZR, M + float start; + float end; + int32_t unused; // was "rest" - byte index value at rest + int32_t index; // 0-3 user set controller, 4 mouth +} PACK_STRUCT; + +// intersection boxes +struct Hitbox_HL1 { + int32_t bone; + int32_t group; // intersection group + vec3_t bbmin; // bounding box + vec3_t bbmax; +} PACK_STRUCT; + +// +// demand loaded sequence groups +// +struct SequenceGroup_HL1 { + char label[32]; // textual name + char name[64]; // file name + int32_t unused; // was "cache" - index pointer + int32_t unused2; // was "data" - hack for group 0 +} PACK_STRUCT; + +// The type of blending for a sequence. +enum SequenceBlendMode_HL1 { + NoBlend = 1, + TwoWayBlending = 2, + FourWayBlending = 4, +}; + +// sequence descriptions +struct SequenceDesc_HL1 { + char label[32]; // sequence label + + float fps; // frames per second + int32_t flags; // looping/non-looping flags + + int32_t activity; + int32_t actweight; + + int32_t numevents; + int32_t eventindex; + + int32_t numframes; // number of frames per sequence + + int32_t unused; // was "numpivots" - number of foot pivots + int32_t unused2; // was "pivotindex" + + int32_t motiontype; + int32_t motionbone; + vec3_t linearmovement; + int32_t unused3; // was "automoveposindex" + int32_t unused4; // was "automoveangleindex" + + vec3_t bbmin; // per sequence bounding box + vec3_t bbmax; + + int32_t numblends; + int32_t animindex; // mstudioanim_t pointer relative to start of sequence group data + // [blend][bone][X, Y, Z, XR, YR, ZR] + + int32_t blendtype[2]; // X, Y, Z, XR, YR, ZR + float blendstart[2]; // starting value + float blendend[2]; // ending value + int32_t unused5; // was "blendparent" + + int32_t seqgroup; // sequence group for demand loading + + int32_t entrynode; // transition node at entry + int32_t exitnode; // transition node at exit + int32_t nodeflags; // transition rules + + int32_t unused6; // was "nextseq" - auto advancing sequences +} PACK_STRUCT; + +// events +struct AnimEvent_HL1 { + int32_t frame; + int32_t event; + int32_t unused; // was "type" + char options[64]; +} PACK_STRUCT; + +// attachment +struct Attachment_HL1 { + char unused[32]; // was "name" + int32_t unused2; // was "type" + int32_t bone; + vec3_t org; // attachment point + vec3_t unused3[3]; // was "vectors" +} PACK_STRUCT; + +struct AnimValueOffset_HL1 { + unsigned short offset[6]; +} PACK_STRUCT; + +// animation frames +union AnimValue_HL1 { + struct { + uint8_t valid; + uint8_t total; + } num PACK_STRUCT; + short value; +} PACK_STRUCT; + +// body part index +struct Bodypart_HL1 { + char name[64]; + int32_t nummodels; + int32_t base; + int32_t modelindex; // index into models array +} PACK_STRUCT; + +// skin info +struct Texture_HL1 { + char name[64]; + int32_t flags; + int32_t width; + int32_t height; + int32_t index; +} PACK_STRUCT; + +// studio models +struct Model_HL1 { + char name[64]; + + int32_t unused; // was "type" + + float unused2; // was "boundingradius" + + int32_t nummesh; + int32_t meshindex; + + int32_t numverts; // number of unique vertices + int32_t vertinfoindex; // vertex bone info + int32_t vertindex; // vertex vec3_t + int32_t numnorms; // number of unique surface normals + int32_t norminfoindex; // normal bone info + int32_t normindex; // normal vec3_t + + int32_t unused3; // was "numgroups" - deformation groups + int32_t unused4; // was "groupindex" +} PACK_STRUCT; + +// meshes +struct Mesh_HL1 { + int32_t numtris; + int32_t triindex; + int32_t skinref; + int32_t numnorms; // per mesh normals + int32_t unused; // was "normindex" - normal vec3_t +} PACK_STRUCT; + +struct Trivert { + short vertindex; // index into vertex array + short normindex; // index into normal array + short s, t; // s,t position on skin +} PACK_STRUCT; + +#include + +#if (!defined AI_MDL_HL1_VERSION) +#define AI_MDL_HL1_VERSION 10 +#endif +#if (!defined AI_MDL_HL1_MAX_TRIANGLES) +#define AI_MDL_HL1_MAX_TRIANGLES 20000 +#endif +#if (!defined AI_MDL_HL1_MAX_VERTICES) +#define AI_MDL_HL1_MAX_VERTICES 2048 +#endif +#if (!defined AI_MDL_HL1_MAX_SEQUENCES) +#define AI_MDL_HL1_MAX_SEQUENCES 2048 +#endif +#if (!defined AI_MDL_HL1_MAX_SEQUENCE_GROUPS) +#define AI_MDL_HL1_MAX_SEQUENCE_GROUPS 32 +#endif +#if (!defined AI_MDL_HL1_MAX_TEXTURES) +#define AI_MDL_HL1_MAX_TEXTURES 100 +#endif +#if (!defined AI_MDL_HL1_MAX_SKIN_FAMILIES) +#define AI_MDL_HL1_MAX_SKIN_FAMILIES 100 +#endif +#if (!defined AI_MDL_HL1_MAX_BONES) +#define AI_MDL_HL1_MAX_BONES 128 +#endif +#if (!defined AI_MDL_HL1_MAX_BODYPARTS) +#define AI_MDL_HL1_MAX_BODYPARTS 32 +#endif +#if (!defined AI_MDL_HL1_MAX_MODELS) +#define AI_MDL_HL1_MAX_MODELS 32 +#endif +#if (!defined AI_MDL_HL1_MAX_MESHES) +#define AI_MDL_HL1_MAX_MESHES 256 +#endif +#if (!defined AI_MDL_HL1_MAX_EVENTS) +#define AI_MDL_HL1_MAX_EVENTS 1024 +#endif +#if (!defined AI_MDL_HL1_MAX_BONE_CONTROLLERS) +#define AI_MDL_HL1_MAX_BONE_CONTROLLERS 8 +#endif +#if (!defined AI_MDL_HL1_MAX_ATTACHMENTS) +#define AI_MDL_HL1_MAX_ATTACHMENTS 512 +#endif + +// lighting options +#if (!defined AI_MDL_HL1_STUDIO_NF_FLATSHADE) +#define AI_MDL_HL1_STUDIO_NF_FLATSHADE 0x0001 +#endif +#if (!defined AI_MDL_HL1_STUDIO_NF_CHROME) +#define AI_MDL_HL1_STUDIO_NF_CHROME 0x0002 +#endif +#if (!defined AI_MDL_HL1_STUDIO_NF_ADDITIVE) +#define AI_MDL_HL1_STUDIO_NF_ADDITIVE 0x0020 +#endif +#if (!defined AI_MDL_HL1_STUDIO_NF_MASKED) +#define AI_MDL_HL1_STUDIO_NF_MASKED 0x0040 +#endif + +} // namespace HalfLife +} // namespace MDL +} // namespace Assimp + +#endif // AI_HL1FILEDATA_INCLUDED diff --git a/code/MDL/HalfLife/HL1ImportDefinitions.h b/code/MDL/HalfLife/HL1ImportDefinitions.h new file mode 100644 index 000000000..f70f40699 --- /dev/null +++ b/code/MDL/HalfLife/HL1ImportDefinitions.h @@ -0,0 +1,64 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file HL1ImportDefinitions.h + * @brief HL1 MDL loader specific definitions. + */ + +#ifndef AI_MDL_HL1_IMPORT_DEFINITIONS_INCLUDED +#define AI_MDL_HL1_IMPORT_DEFINITIONS_INCLUDED + +#define AI_MDL_HL1_NODE_ROOT "" +#define AI_MDL_HL1_NODE_BODYPARTS "" +#define AI_MDL_HL1_NODE_BONES "" +#define AI_MDL_HL1_NODE_BONE_CONTROLLERS "" +#define AI_MDL_HL1_NODE_SEQUENCE_INFOS "" +#define AI_MDL_HL1_NODE_SEQUENCE_GROUPS "" +#define AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH "" +#define AI_MDL_HL1_NODE_ATTACHMENTS "" +#define AI_MDL_HL1_NODE_HITBOXES "" +#define AI_MDL_HL1_NODE_GLOBAL_INFO "" +#define AI_MDL_HL1_NODE_ANIMATION_EVENTS "AnimationEvents" +#define AI_MDL_HL1_NODE_BLEND_CONTROLLERS "BlendControllers" + +#define AI_MDL_HL1_MATKEY_CHROME(type, N) "$mat.HL1.chrome", type, N + +#endif // AI_MDL_HL1_IMPORT_DEFINITIONS_INCLUDED diff --git a/code/MDL/HalfLife/HL1ImportSettings.h b/code/MDL/HalfLife/HL1ImportSettings.h new file mode 100644 index 000000000..229303e2c --- /dev/null +++ b/code/MDL/HalfLife/HL1ImportSettings.h @@ -0,0 +1,85 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file HL1ImportSettings.h + * @brief Half-Life 1 MDL loader configuration settings. + */ + +#ifndef AI_HL1IMPORTSETTINGS_INCLUDED +#define AI_HL1IMPORTSETTINGS_INCLUDED + +#include + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +struct HL1ImportSettings { + HL1ImportSettings() : + read_animations(false), + read_animation_events(false), + read_blend_controllers(false), + read_sequence_groups_info(false), + read_sequence_transitions(false), + read_attachments(false), + read_bone_controllers(false), + read_hitboxes(false), + read_textures(false), + read_misc_global_info(false) { + } + + bool read_animations; + bool read_animation_events; + bool read_blend_controllers; + bool read_sequence_groups_info; + bool read_sequence_transitions; + bool read_attachments; + bool read_bone_controllers; + bool read_hitboxes; + bool read_textures; + bool read_misc_global_info; +}; + +} // namespace HalfLife +} // namespace MDL +} // namespace Assimp + +#endif // AI_HL1IMPORTSETTINGS_INCLUDED diff --git a/code/MDL/HalfLife/HL1MDLLoader.cpp b/code/MDL/HalfLife/HL1MDLLoader.cpp new file mode 100644 index 000000000..a95f65060 --- /dev/null +++ b/code/MDL/HalfLife/HL1MDLLoader.cpp @@ -0,0 +1,1331 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file HL1MDLLoader.cpp + * @brief Implementation for the Half-Life 1 MDL loader. + */ + +#include "HL1MDLLoader.h" +#include "HL1ImportDefinitions.h" +#include "HL1MeshTrivert.h" +#include "UniqueNameGenerator.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef MDL_HALFLIFE_LOG_WARN_HEADER +#undef MDL_HALFLIFE_LOG_WARN_HEADER +#endif +#define MDL_HALFLIFE_LOG_HEADER "[Half-Life 1 MDL] " +#include "LogFunctions.h" + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +// ------------------------------------------------------------------------------------------------ +HL1MDLLoader::HL1MDLLoader( + aiScene *scene, + IOSystem *io, + const unsigned char *buffer, + const std::string &file_path, + const HL1ImportSettings &import_settings) : + scene_(scene), + io_(io), + buffer_(buffer), + file_path_(file_path), + import_settings_(import_settings), + texture_buffer_(nullptr), + anim_buffers_(nullptr), + anim_headers_(nullptr), + num_sequence_groups_(0), + rootnode_children_(), + unique_name_generator_(), + temp_bones_(), + num_blend_controllers_(0), + total_models_(0) { + load_file(); +} + +// ------------------------------------------------------------------------------------------------ +HL1MDLLoader::~HL1MDLLoader() { + release_resources(); +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::release_resources() { + if (buffer_ != texture_buffer_) { + delete[] texture_buffer_; + texture_buffer_ = nullptr; + } + + if (num_sequence_groups_ && anim_buffers_) { + for (int i = 1; i < num_sequence_groups_; ++i) { + if (anim_buffers_[i]) { + delete[] anim_buffers_[i]; + anim_buffers_[i] = nullptr; + } + } + + delete[] anim_buffers_; + anim_buffers_ = nullptr; + } + + if (anim_headers_) { + delete[] anim_headers_; + anim_headers_ = nullptr; + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::load_file() { + + try { + header_ = (const Header_HL1 *)buffer_; + validate_header(header_, false); + + // Create the root scene node. + scene_->mRootNode = new aiNode(AI_MDL_HL1_NODE_ROOT); + + load_texture_file(); + + if (import_settings_.read_animations) + load_sequence_groups_files(); + + read_textures(); + read_skins(); + + read_bones(); + read_meshes(); + + if (import_settings_.read_animations) { + read_sequence_groups_info(); + read_animations(); + read_sequence_infos(); + if (import_settings_.read_sequence_transitions) + read_sequence_transitions(); + } + + if (import_settings_.read_attachments) + read_attachments(); + + if (import_settings_.read_hitboxes) + read_hitboxes(); + + if (import_settings_.read_bone_controllers) + read_bone_controllers(); + + read_global_info(); + + // Append children to root node. + if (rootnode_children_.size()) { + scene_->mRootNode->addChildren( + static_cast(rootnode_children_.size()), + rootnode_children_.data()); + } + + release_resources(); + + } catch (const std::exception &e) { + release_resources(); + throw e; + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::validate_header(const Header_HL1 *header, bool is_texture_header) { + if (is_texture_header) { + // Every single Half-Life model is assumed to have at least one texture. + if (!header->numtextures) + throw DeadlyImportError(MDL_HALFLIFE_LOG_HEADER "There are no textures in the file"); + + if (header->numtextures > AI_MDL_HL1_MAX_TEXTURES) + log_warning_limit_exceeded(header->numtextures, "textures"); + + if (header->numskinfamilies > AI_MDL_HL1_MAX_SKIN_FAMILIES) + log_warning_limit_exceeded(header->numskinfamilies, "skin families"); + + } else { + // Every single Half-Life model is assumed to have at least one bodypart. + if (!header->numbodyparts) + throw DeadlyImportError(MDL_HALFLIFE_LOG_HEADER "Model has no bodyparts"); + + // Every single Half-Life model is assumed to have at least one bone. + if (!header->numbones) + throw DeadlyImportError(MDL_HALFLIFE_LOG_HEADER "Model has no bones"); + + // Every single Half-Life model is assumed to have at least one sequence group, + // which is the "default" sequence group. + if (!header->numseqgroups) + throw DeadlyImportError(MDL_HALFLIFE_LOG_HEADER "Model has no sequence groups"); + + if (header->numbodyparts > AI_MDL_HL1_MAX_BODYPARTS) + log_warning_limit_exceeded(header->numbodyparts, "bodyparts"); + + if (header->numbones > AI_MDL_HL1_MAX_BONES) + log_warning_limit_exceeded(header->numbones, "bones"); + + if (header->numbonecontrollers > AI_MDL_HL1_MAX_BONE_CONTROLLERS) + log_warning_limit_exceeded(header->numbonecontrollers, "bone controllers"); + + if (header->numseq > AI_MDL_HL1_MAX_SEQUENCES) + log_warning_limit_exceeded(header->numseq, "sequences"); + + if (header->numseqgroups > AI_MDL_HL1_MAX_SEQUENCE_GROUPS) + log_warning_limit_exceeded(header->numseqgroups, "sequence groups"); + + if (header->numattachments > AI_MDL_HL1_MAX_ATTACHMENTS) + log_warning_limit_exceeded(header->numattachments, "attachments"); + } +} + +// ------------------------------------------------------------------------------------------------ +/* + Load textures. + + There are two ways for textures to be stored in a Half-Life model: + + 1. Directly in the MDL file (filePath) or + 2. In an external MDL file. + + Due to the way StudioMDL works (tool used to compile SMDs into MDLs), + it is assumed that an external texture file follows the naming + convention: T.mdl. Note the extra (T) at the end of the + model name. + + .e.g For a given model named MyModel.mdl + + The external texture file name would be MyModelT.mdl +*/ +void HL1MDLLoader::load_texture_file() { + if (header_->numtextures == 0) { + // Load an external MDL texture file. + std::string texture_file_path = + DefaultIOSystem::absolutePath(file_path_) + io_->getOsSeparator() + + DefaultIOSystem::completeBaseName(file_path_) + "T." + + BaseImporter::GetExtension(file_path_); + + load_file_into_buffer(texture_file_path, texture_buffer_); + } else { + /* Model has no external texture file. This means the texture + is stored inside the main MDL file. */ + texture_buffer_ = const_cast(buffer_); + } + + texture_header_ = (const Header_HL1 *)texture_buffer_; + + // Validate texture header. + validate_header(texture_header_, true); +} + +// ------------------------------------------------------------------------------------------------ +/* + Load sequence group files if any. + + Due to the way StudioMDL works (tool used to compile SMDs into MDLs), + it is assumed that a sequence group file follows the naming + convention: 0X.mdl. Note the extra (0X) at the end of + the model name, where (X) is the sequence group. + + .e.g For a given model named MyModel.mdl + + Sequence group 1 => MyModel01.mdl + Sequence group 2 => MyModel02.mdl + Sequence group X => MyModel0X.mdl + +*/ +void HL1MDLLoader::load_sequence_groups_files() { + if (header_->numseqgroups <= 1) + return; + + num_sequence_groups_ = header_->numseqgroups; + + anim_buffers_ = new unsigned char *[num_sequence_groups_]; + anim_headers_ = new SequenceHeader_HL1 *[num_sequence_groups_]; + for (int i = 0; i < num_sequence_groups_; ++i) { + anim_buffers_[i] = NULL; + anim_headers_[i] = NULL; + } + + std::string file_path_without_extension = + DefaultIOSystem::absolutePath(file_path_) + + io_->getOsSeparator() + + DefaultIOSystem::completeBaseName(file_path_); + + for (int i = 1; i < num_sequence_groups_; ++i) { + std::stringstream ss; + ss << file_path_without_extension; + ss << std::setw(2) << std::setfill('0') << i; + ss << '.' << BaseImporter::GetExtension(file_path_); + + std::string sequence_file_path = ss.str(); + + load_file_into_buffer(sequence_file_path, anim_buffers_[i]); + + anim_headers_[i] = (SequenceHeader_HL1 *)anim_buffers_[i]; + } +} + +// ------------------------------------------------------------------------------------------------ +/** @brief Read an MDL texture. +* +* @note This method is taken from HL1 source code. +* source: file: studio_utils.c +* function(s): UploadTexture +*/ +void HL1MDLLoader::read_texture(const Texture_HL1 *ptexture, + uint8_t *data, uint8_t *pal, aiTexture *pResult, + aiColor3D &last_palette_color) { + int outwidth, outheight; + int i, j; + int row1[256], row2[256], col1[256], col2[256]; + unsigned char *pix1, *pix2, *pix3, *pix4; + + // convert texture to power of 2 + for (outwidth = 1; outwidth < ptexture->width; outwidth <<= 1) + ; + + if (outwidth > 256) + outwidth = 256; + + for (outheight = 1; outheight < ptexture->height; outheight <<= 1) + ; + + if (outheight > 256) + outheight = 256; + + pResult->mFilename = ptexture->name; + pResult->mWidth = outwidth; + pResult->mHeight = outheight; + strncpy(pResult->achFormatHint, "bgra8888", 8); + + aiTexel *out = pResult->pcData = new aiTexel[outwidth * outheight]; + + for (i = 0; i < outwidth; i++) { + col1[i] = (int)((i + 0.25) * (ptexture->width / (float)outwidth)); + col2[i] = (int)((i + 0.75) * (ptexture->width / (float)outwidth)); + } + + for (i = 0; i < outheight; i++) { + row1[i] = (int)((i + 0.25) * (ptexture->height / (float)outheight)) * ptexture->width; + row2[i] = (int)((i + 0.75) * (ptexture->height / (float)outheight)) * ptexture->width; + } + + // scale down and convert to 32bit RGB + for (i = 0; i < outheight; i++) { + for (j = 0; j < outwidth; j++, out++) { + pix1 = &pal[data[row1[i] + col1[j]] * 3]; + pix2 = &pal[data[row1[i] + col2[j]] * 3]; + pix3 = &pal[data[row2[i] + col1[j]] * 3]; + pix4 = &pal[data[row2[i] + col2[j]] * 3]; + + out->r = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2; + out->g = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2; + out->b = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2; + out->a = 0xFF; + } + } + + // Get the last palette color. + last_palette_color.r = pal[255 * 3]; + last_palette_color.g = pal[255 * 3 + 1]; + last_palette_color.b = pal[255 * 3 + 2]; +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_textures() { + const Texture_HL1 *ptexture = (const Texture_HL1 *)((uint8_t *)texture_header_ + texture_header_->textureindex); + unsigned char *pin = texture_buffer_; + + scene_->mNumTextures = scene_->mNumMaterials = texture_header_->numtextures; + scene_->mTextures = new aiTexture *[scene_->mNumTextures]; + scene_->mMaterials = new aiMaterial *[scene_->mNumMaterials]; + + for (int i = 0; i < texture_header_->numtextures; ++i) { + scene_->mTextures[i] = new aiTexture(); + + aiColor3D last_palette_color; + read_texture(&ptexture[i], + pin + ptexture[i].index, + pin + ptexture[i].width * ptexture[i].height + ptexture[i].index, + scene_->mTextures[i], + last_palette_color); + + aiMaterial *scene_material = scene_->mMaterials[i] = new aiMaterial(); + + const aiTextureType texture_type = aiTextureType_DIFFUSE; + aiString texture_name(ptexture[i].name); + scene_material->AddProperty(&texture_name, AI_MATKEY_TEXTURE(texture_type, 0)); + + // Is this a chrome texture? + int chrome = ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_CHROME ? 1 : 0; + scene_material->AddProperty(&chrome, 1, AI_MDL_HL1_MATKEY_CHROME(texture_type, 0)); + + if (ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_FLATSHADE) { + // Flat shading. + const aiShadingMode shading_mode = aiShadingMode_Flat; + scene_material->AddProperty(&shading_mode, 1, AI_MATKEY_SHADING_MODEL); + } + + if (ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_ADDITIVE) { + // Additive texture. + const aiBlendMode blend_mode = aiBlendMode_Additive; + scene_material->AddProperty(&blend_mode, 1, AI_MATKEY_BLEND_FUNC); + } else if (ptexture[i].flags & AI_MDL_HL1_STUDIO_NF_MASKED) { + // Texture with 1 bit alpha test. + const aiTextureFlags use_alpha = aiTextureFlags_UseAlpha; + scene_material->AddProperty(&use_alpha, 1, AI_MATKEY_TEXFLAGS(texture_type, 0)); + scene_material->AddProperty(&last_palette_color, 1, AI_MATKEY_COLOR_TRANSPARENT); + } + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_skins() { + // Read skins, if any. + if (texture_header_->numskinfamilies <= 1) + return; + + // Pointer to base texture index. + short *default_skin_ptr = (short *)((uint8_t *)texture_header_ + texture_header_->skinindex); + + // Start at first replacement skin. + short *replacement_skin_ptr = default_skin_ptr + texture_header_->numskinref; + + for (int i = 1; i < texture_header_->numskinfamilies; ++i, replacement_skin_ptr += texture_header_->numskinref) { + for (int j = 0; j < texture_header_->numskinref; ++j) { + if (default_skin_ptr[j] != replacement_skin_ptr[j]) { + // Save replacement textures. + aiString skinMaterialId(scene_->mTextures[replacement_skin_ptr[j]]->mFilename); + scene_->mMaterials[default_skin_ptr[j]]->AddProperty(&skinMaterialId, AI_MATKEY_TEXTURE_DIFFUSE(i)); + } + } + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_bones() { + const Bone_HL1 *pbone = (const Bone_HL1 *)((uint8_t *)header_ + header_->boneindex); + + std::vector unique_bones_names(header_->numbones); + for (int i = 0; i < header_->numbones; ++i) + unique_bones_names[i] = pbone[i].name; + + // Ensure bones have unique names. + unique_name_generator_.set_template_name("Bone"); + unique_name_generator_.make_unique(unique_bones_names); + + temp_bones_.resize(header_->numbones); + + aiNode *bones_node = new aiNode(AI_MDL_HL1_NODE_BONES); + rootnode_children_.push_back(bones_node); + bones_node->mNumChildren = static_cast(header_->numbones); + bones_node->mChildren = new aiNode *[bones_node->mNumChildren]; + + // Create bone matrices in local space. + for (int i = 0; i < header_->numbones; ++i) { + aiNode *bone_node = temp_bones_[i].node = bones_node->mChildren[i] = new aiNode(unique_bones_names[i]); + + aiVector3D angles(pbone[i].value[3], pbone[i].value[4], pbone[i].value[5]); + temp_bones_[i].absolute_transform = bone_node->mTransformation = + aiMatrix4x4(aiVector3D(1), aiQuaternion(angles.y, angles.z, angles.x), + aiVector3D(pbone[i].value[0], pbone[i].value[1], pbone[i].value[2])); + + if (pbone[i].parent == -1) { + bone_node->mParent = scene_->mRootNode; + } else { + bone_node->mParent = bones_node->mChildren[pbone[i].parent]; + + temp_bones_[i].absolute_transform = + temp_bones_[pbone[i].parent].absolute_transform * bone_node->mTransformation; + } + + temp_bones_[i].offset_matrix = temp_bones_[i].absolute_transform; + temp_bones_[i].offset_matrix.Inverse(); + } +} + +// ------------------------------------------------------------------------------------------------ +/* + Read meshes. + + Half-Life MDLs are structured such that each MDL + contains one or more 'bodypart(s)', which contain one + or more 'model(s)', which contains one or more mesh(es). + + * Bodyparts are used to group models that may be replaced + in the game .e.g a character could have a 'heads' group, + 'torso' group, 'shoes' group, with each group containing + different 'model(s)'. + + * Models, also called 'sub models', contain vertices as + well as a reference to each mesh used by the sub model. + + * Meshes contain a list of tris, also known as 'triverts'. + Each tris contains the following information: + + 1. The index of the position to use for the vertex. + 2. The index of the normal to use for the vertex. + 3. The S coordinate to use for the vertex UV. + 4. The T coordinate ^ + + These tris represent the way to represent the triangles + for each mesh. Depending on how the tool compiled the MDL, + those triangles were saved as strips and or fans. + + NOTE: Each tris is NOT unique. This means that you + might encounter the same vertex index but with a different + normal index, S coordinate, T coordinate. + + In addition, each mesh contains the texture's index. + + ------------------------------------------------------ + With the details above, there are several things to + take into consideration. + + * The Half-Life models store the vertices by sub model + rather than by mesh. Due to Assimp's structure, it + is necessary to remap each model vertex to be used + per mesh. Unfortunately, this has the consequence + to duplicate vertices. + + * Because the mesh triangles are comprised of strips and + fans, it is necessary to convert each primitive to + triangles, respectively (3 indices per face). +*/ +void HL1MDLLoader::read_meshes() { + + int total_verts = 0; + int total_triangles = 0; + total_models_ = 0; + + const Bodypart_HL1 *pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex); + const Model_HL1 *pmodel = nullptr; + const Mesh_HL1 *pmesh = nullptr; + + const Texture_HL1 *ptexture = (const Texture_HL1 *)((uint8_t *)texture_header_ + texture_header_->textureindex); + short *pskinref = (short *)((uint8_t *)texture_header_ + texture_header_->skinindex); + + scene_->mNumMeshes = 0; + + std::vector unique_bodyparts_names; + unique_bodyparts_names.resize(header_->numbodyparts); + + // Count the number of meshes. + + for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart) { + unique_bodyparts_names[i] = pbodypart->name; + + pmodel = (Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex); + for (int j = 0; j < pbodypart->nummodels; ++j, ++pmodel) { + scene_->mNumMeshes += pmodel->nummesh; + total_verts += pmodel->numverts; + } + + total_models_ += pbodypart->nummodels; + } + + // Display limit infos. + if (total_verts > AI_MDL_HL1_MAX_VERTICES) + log_warning_limit_exceeded(total_verts, "vertices"); + + if (scene_->mNumMeshes > AI_MDL_HL1_MAX_MESHES) + log_warning_limit_exceeded(scene_->mNumMeshes, "meshes"); + + if (total_models_ > AI_MDL_HL1_MAX_MODELS) + log_warning_limit_exceeded(total_models_, "models"); + + // Ensure bodyparts have unique names. + unique_name_generator_.set_template_name("Bodypart"); + unique_name_generator_.make_unique(unique_bodyparts_names); + + // Now do the same for each model. + pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex); + + // Prepare template name for bodypart models. + std::vector unique_models_names; + unique_models_names.resize(total_models_); + + unsigned int model_index = 0; + + for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart) { + pmodel = (Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex); + for (int j = 0; j < pbodypart->nummodels; ++j, ++pmodel, ++model_index) + unique_models_names[model_index] = pmodel->name; + } + + unique_name_generator_.set_template_name("Model"); + unique_name_generator_.make_unique(unique_models_names); + + unsigned int mesh_index = 0; + + scene_->mMeshes = new aiMesh *[scene_->mNumMeshes]; + + pbodypart = (const Bodypart_HL1 *)((uint8_t *)header_ + header_->bodypartindex); + + /* Create a node that will represent the mesh hierarchy. + + + | + +-- bodypart --+-- model -- [mesh index, mesh index, ...] + | | + | +-- model -- [mesh index, mesh index, ...] + | | + | ... + | + |-- bodypart -- ... + | + ... + */ + aiNode *bodyparts_node = new aiNode(AI_MDL_HL1_NODE_BODYPARTS); + rootnode_children_.push_back(bodyparts_node); + bodyparts_node->mNumChildren = static_cast(header_->numbodyparts); + bodyparts_node->mChildren = new aiNode *[bodyparts_node->mNumChildren]; + aiNode **bodyparts_node_ptr = bodyparts_node->mChildren; + + // The following variables are defined here so they don't have + // to be recreated every iteration. + + // Model_HL1 vertices, in bind pose space. + std::vector bind_pose_vertices; + + // Model_HL1 normals, in bind pose space. + std::vector bind_pose_normals; + + // Used to contain temporary information for building a mesh. + std::vector triverts; + + std::vector tricmds; + + // Which triverts to use for the mesh. + std::vector mesh_triverts_indices; + + std::vector mesh_faces; + + /* triverts that have the same vertindex, but have different normindex,s,t values. + Similar triverts are mapped from vertindex to a list of similar triverts. */ + std::map> triverts_similars; + + // triverts per bone. + std::map> bone_triverts; + + /** This function adds a trivert index to the list of triverts per bone. + * \param[in] bone The bone that affects the trivert at index \p trivert_index. + * \param[in] trivert_index The trivert index. + */ + auto AddTrivertToBone = [&](int bone, short trivert_index) { + if (bone_triverts.count(bone) == 0) + bone_triverts.insert_or_assign(bone, std::set{ trivert_index }); + else + bone_triverts[bone].insert(trivert_index); + }; + + /** This function creates and appends a new trivert to the list of triverts. + * \param[in] trivert The trivert to use as a prototype. + * \param[in] bone The bone that affects \p trivert. + */ + auto AddSimilarTrivert = [&](const Trivert &trivert, const int bone) { + HL1MeshTrivert new_trivert(trivert); + new_trivert.localindex = static_cast(mesh_triverts_indices.size()); + + short new_trivert_index = static_cast(triverts.size()); + + if (triverts_similars.count(trivert.vertindex) == 0) + triverts_similars.insert_or_assign(trivert.vertindex, std::set{ new_trivert_index }); + else + triverts_similars[trivert.vertindex].insert(new_trivert_index); + + triverts.push_back(new_trivert); + + mesh_triverts_indices.push_back(new_trivert_index); + tricmds.push_back(new_trivert.localindex); + AddTrivertToBone(bone, new_trivert.localindex); + }; + + model_index = 0; + + for (int i = 0; i < header_->numbodyparts; ++i, ++pbodypart, ++bodyparts_node_ptr) { + pmodel = (const Model_HL1 *)((uint8_t *)header_ + pbodypart->modelindex); + + // Create bodypart node for the mesh tree hierarchy. + aiNode *bodypart_node = (*bodyparts_node_ptr) = new aiNode(unique_bodyparts_names[i]); + bodypart_node->mParent = bodyparts_node; + bodypart_node->mMetaData = aiMetadata::Alloc(1); + bodypart_node->mMetaData->Set(0, "Base", pbodypart->base); + + bodypart_node->mNumChildren = static_cast(pbodypart->nummodels); + bodypart_node->mChildren = new aiNode *[bodypart_node->mNumChildren]; + aiNode **bodypart_models_ptr = bodypart_node->mChildren; + + for (int j = 0; j < pbodypart->nummodels; + ++j, ++pmodel, ++bodypart_models_ptr, ++model_index) { + + pmesh = (const Mesh_HL1 *)((uint8_t *)header_ + pmodel->meshindex); + + uint8_t *pvertbone = ((uint8_t *)header_ + pmodel->vertinfoindex); + uint8_t *pnormbone = ((uint8_t *)header_ + pmodel->norminfoindex); + vec3_t *pstudioverts = (vec3_t *)((uint8_t *)header_ + pmodel->vertindex); + vec3_t *pstudionorms = (vec3_t *)((uint8_t *)header_ + pmodel->normindex); + + // Each vertex and normal is in local space, so transform + // each of them to bring them in bind pose. + bind_pose_vertices.resize(pmodel->numverts); + bind_pose_normals.resize(pmodel->numnorms); + for (size_t k = 0; k < bind_pose_vertices.size(); ++k) { + const vec3_t &vert = pstudioverts[k]; + bind_pose_vertices[k] = temp_bones_[pvertbone[k]].absolute_transform * aiVector3D(vert[0], vert[1], vert[2]); + } + for (size_t k = 0; k < bind_pose_normals.size(); ++k) { + const vec3_t &norm = pstudionorms[k]; + // Compute the normal matrix to transform the normal into bind pose, + // without affecting its length. + const aiMatrix4x4 normal_matrix = aiMatrix4x4(temp_bones_[pnormbone[k]].absolute_transform).Inverse().Transpose(); + bind_pose_normals[k] = normal_matrix * aiVector3D(norm[0], norm[1], norm[2]); + } + + // Create model node for the mesh tree hierarchy. + aiNode *model_node = (*bodypart_models_ptr) = new aiNode(unique_models_names[model_index]); + model_node->mParent = bodypart_node; + model_node->mNumMeshes = static_cast(pmodel->nummesh); + model_node->mMeshes = new unsigned int[model_node->mNumMeshes]; + unsigned int *model_meshes_ptr = model_node->mMeshes; + + for (int k = 0; k < pmodel->nummesh; ++k, ++pmesh, ++mesh_index, ++model_meshes_ptr) { + *model_meshes_ptr = mesh_index; + + // Read triverts. + short *ptricmds = (short *)((uint8_t *)header_ + pmesh->triindex); + float texcoords_s_scale = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].width; + float texcoords_t_scale = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].height; + + // Reset the data for the upcoming mesh. + triverts.clear(); + triverts.resize(pmodel->numverts); + mesh_triverts_indices.clear(); + mesh_faces.clear(); + triverts_similars.clear(); + bone_triverts.clear(); + + int l; + while (l = *(ptricmds++)) { + bool is_triangle_fan = false; + + if (l < 0) { + l = -l; + is_triangle_fan = true; + } + + // Clear the list of tris for the upcoming tris. + tricmds.clear(); + + for (; l > 0; l--, ptricmds += 4) { + const Trivert *input_trivert = reinterpret_cast(ptricmds); + const int bone = pvertbone[input_trivert->vertindex]; + + HL1MeshTrivert *private_trivert = &triverts[input_trivert->vertindex]; + if (private_trivert->localindex == -1) { + // First time referenced. + *private_trivert = *input_trivert; + private_trivert->localindex = static_cast(mesh_triverts_indices.size()); + mesh_triverts_indices.push_back(input_trivert->vertindex); + tricmds.push_back(private_trivert->localindex); + AddTrivertToBone(bone, private_trivert->localindex); + } else if (*private_trivert == *input_trivert) { + // Exists and is the same. + tricmds.push_back(private_trivert->localindex); + } else { + // No similar trivert associated to the trivert currently processed. + if (triverts_similars.count(input_trivert->vertindex) == 0) + AddSimilarTrivert(*input_trivert, bone); + else { + // Search in the list of similar triverts to see if the + // trivert in process is already registered. + short similar_index = -1; + for (auto it = triverts_similars[input_trivert->vertindex].cbegin(); + similar_index == -1 && it != triverts_similars[input_trivert->vertindex].cend(); + ++it) { + if (triverts[*it] == *input_trivert) + similar_index = *it; + } + + // If a similar trivert has been found, reuse it. + // Otherwise, add it. + if (similar_index == -1) + AddSimilarTrivert(*input_trivert, bone); + else + tricmds.push_back(triverts[similar_index].localindex); + } + } + } + + // Build mesh faces. + const int num_faces = static_cast(tricmds.size() - 2); + mesh_faces.reserve(num_faces); + + if (is_triangle_fan) { + for (int i = 0; i < num_faces; ++i) { + mesh_faces.push_back(HL1MeshFace{ + tricmds[0], + tricmds[i + 1], + tricmds[i + 2] }); + } + } else { + for (int i = 0; i < num_faces; ++i) { + if (i & 1) { + // Preserve winding order. + mesh_faces.push_back(HL1MeshFace{ + tricmds[i + 1], + tricmds[i], + tricmds[i + 2] }); + } else { + mesh_faces.push_back(HL1MeshFace{ + tricmds[i], + tricmds[i + 1], + tricmds[i + 2] }); + } + } + } + + total_triangles += num_faces; + } + + // Create the scene mesh. + aiMesh *scene_mesh = scene_->mMeshes[mesh_index] = new aiMesh(); + scene_mesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_TRIANGLE; + scene_mesh->mMaterialIndex = pskinref[pmesh->skinref]; + + scene_mesh->mNumVertices = static_cast(mesh_triverts_indices.size()); + + if (scene_mesh->mNumVertices) { + scene_mesh->mVertices = new aiVector3D[scene_mesh->mNumVertices]; + scene_mesh->mNormals = new aiVector3D[scene_mesh->mNumVertices]; + + scene_mesh->mNumUVComponents[0] = 2; + scene_mesh->mTextureCoords[0] = new aiVector3D[scene_mesh->mNumVertices]; + + // Add vertices. + for (unsigned int v = 0; v < scene_mesh->mNumVertices; ++v) { + const HL1MeshTrivert *pTrivert = &triverts[mesh_triverts_indices[v]]; + scene_mesh->mVertices[v] = bind_pose_vertices[pTrivert->vertindex]; + scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex]; + scene_mesh->mTextureCoords[0][v] = aiVector3D( + pTrivert->s * texcoords_s_scale, + pTrivert->t * texcoords_t_scale, 0); + } + + // Add face and indices. + scene_mesh->mNumFaces = static_cast(mesh_faces.size()); + scene_mesh->mFaces = new aiFace[scene_mesh->mNumFaces]; + + for (unsigned int f = 0; f < scene_mesh->mNumFaces; ++f) { + aiFace *face = &scene_mesh->mFaces[f]; + face->mNumIndices = 3; + face->mIndices = new unsigned int[3]; + face->mIndices[0] = mesh_faces[f].v0; + face->mIndices[1] = mesh_faces[f].v1; + face->mIndices[2] = mesh_faces[f].v2; + } + + // Add mesh bones. + scene_mesh->mNumBones = static_cast(bone_triverts.size()); + scene_mesh->mBones = new aiBone *[scene_mesh->mNumBones]; + + aiBone **scene_bone_ptr = scene_mesh->mBones; + + for (auto bone_it = bone_triverts.cbegin(); + bone_it != bone_triverts.cend(); + ++bone_it, ++scene_bone_ptr) { + const int bone_index = bone_it->first; + + aiBone *scene_bone = (*scene_bone_ptr) = new aiBone(); + scene_bone->mName = temp_bones_[bone_index].node->mName; + + scene_bone->mOffsetMatrix = temp_bones_[bone_index].offset_matrix; + + auto vertex_ids = bone_triverts.at(bone_index); + + // Add vertex weight per bone. + scene_bone->mNumWeights = static_cast(vertex_ids.size()); + aiVertexWeight *vertex_weight_ptr = scene_bone->mWeights = new aiVertexWeight[scene_bone->mNumWeights]; + + for (auto vertex_it = vertex_ids.begin(); + vertex_it != vertex_ids.end(); + ++vertex_it, ++vertex_weight_ptr) { + vertex_weight_ptr->mVertexId = *vertex_it; + vertex_weight_ptr->mWeight = 1.0f; + } + } + } + } + } + } + + if (total_triangles > AI_MDL_HL1_MAX_TRIANGLES) + log_warning_limit_exceeded(total_triangles, "triangles"); +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_animations() { + if (!header_->numseq) + return; + + const SequenceDesc_HL1 *pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex); + const SequenceGroup_HL1 *pseqgroup = nullptr; + const AnimValueOffset_HL1 *panim = nullptr; + const AnimValue_HL1 *panimvalue = nullptr; + + unique_sequence_names_.resize(header_->numseq); + for (int i = 0; i < header_->numseq; ++i) + unique_sequence_names_[i] = pseqdesc[i].label; + + // Ensure sequences have unique names. + unique_name_generator_.set_template_name("Sequence"); + unique_name_generator_.make_unique(unique_sequence_names_); + + scene_->mNumAnimations = 0; + + int highest_num_blend_animations = SequenceBlendMode_HL1::NoBlend; + + // Count the total number of animations. + for (int i = 0; i < header_->numseq; ++i, ++pseqdesc) { + scene_->mNumAnimations += pseqdesc->numblends; + highest_num_blend_animations = std::max(pseqdesc->numblends, highest_num_blend_animations); + } + + // Get the number of available blend controllers for global info. + get_num_blend_controllers(highest_num_blend_animations, num_blend_controllers_); + + pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex); + + aiAnimation **scene_animations_ptr = scene_->mAnimations = new aiAnimation *[scene_->mNumAnimations]; + + for (int sequence = 0; sequence < header_->numseq; ++sequence, ++pseqdesc) { + pseqgroup = (const SequenceGroup_HL1 *)((uint8_t *)header_ + header_->seqgroupindex) + pseqdesc->seqgroup; + + if (pseqdesc->seqgroup == 0) + panim = (const AnimValueOffset_HL1 *)((uint8_t *)header_ + pseqgroup->unused2 + pseqdesc->animindex); + else + panim = (const AnimValueOffset_HL1 *)((uint8_t *)anim_headers_[pseqdesc->seqgroup] + pseqdesc->animindex); + + for (int blend = 0; blend < pseqdesc->numblends; ++blend, ++scene_animations_ptr) { + + const Bone_HL1 *pbone = (const Bone_HL1 *)((uint8_t *)header_ + header_->boneindex); + + aiAnimation *scene_animation = (*scene_animations_ptr) = new aiAnimation(); + + scene_animation->mName = unique_sequence_names_[sequence]; + scene_animation->mTicksPerSecond = pseqdesc->fps; + scene_animation->mDuration = static_cast(pseqdesc->fps) * pseqdesc->numframes; + scene_animation->mNumChannels = static_cast(header_->numbones); + scene_animation->mChannels = new aiNodeAnim *[scene_animation->mNumChannels]; + + for (int bone = 0; bone < header_->numbones; bone++, ++pbone, ++panim) { + aiNodeAnim *node_anim = scene_animation->mChannels[bone] = new aiNodeAnim(); + node_anim->mNodeName = temp_bones_[bone].node->mName; + + node_anim->mNumPositionKeys = pseqdesc->numframes; + node_anim->mNumRotationKeys = node_anim->mNumPositionKeys; + node_anim->mNumScalingKeys = 0; + + node_anim->mPositionKeys = new aiVectorKey[node_anim->mNumPositionKeys]; + node_anim->mRotationKeys = new aiQuatKey[node_anim->mNumRotationKeys]; + + for (int frame = 0; frame < pseqdesc->numframes; ++frame) { + aiVectorKey *position_key = &node_anim->mPositionKeys[frame]; + aiQuatKey *rotation_key = &node_anim->mRotationKeys[frame]; + + aiVector3D angle1; + for (int j = 0; j < 3; ++j) { + if (panim->offset[j + 3] != 0) { + // Read compressed rotation delta. + panimvalue = (const AnimValue_HL1 *)((uint8_t *)panim + panim->offset[j + 3]); + extract_anim_value(panimvalue, frame, pbone->scale[j + 3], angle1[j]); + } + + // Add the default rotation value. + angle1[j] += pbone->value[j + 3]; + + if (panim->offset[j] != 0) { + // Read compressed position delta. + panimvalue = (const AnimValue_HL1 *)((uint8_t *)panim + panim->offset[j]); + extract_anim_value(panimvalue, frame, pbone->scale[j], position_key->mValue[j]); + } + + // Add the default position value. + position_key->mValue[j] += pbone->value[j]; + } + + position_key->mTime = rotation_key->mTime = static_cast(frame); + /* The Half-Life engine uses X as forward, Y as left, Z as up. Therefore, + pitch,yaw,roll is represented as (YZX). */ + rotation_key->mValue = aiQuaternion(angle1.y, angle1.z, angle1.x); + rotation_key->mValue.Normalize(); + } + } + } + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_sequence_groups_info() { + + aiNode *sequence_groups_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_GROUPS); + rootnode_children_.push_back(sequence_groups_node); + + sequence_groups_node->mNumChildren = static_cast(header_->numseqgroups); + sequence_groups_node->mChildren = new aiNode *[sequence_groups_node->mNumChildren]; + + const SequenceGroup_HL1 *pseqgroup = (const SequenceGroup_HL1 *)((uint8_t *)header_ + header_->seqgroupindex); + + unique_sequence_groups_names_.resize(header_->numseqgroups); + for (int i = 0; i < header_->numseqgroups; ++i) + unique_sequence_groups_names_[i] = pseqgroup[i].label; + + // Ensure sequence groups have unique names. + unique_name_generator_.set_template_name("SequenceGroup"); + unique_name_generator_.make_unique(unique_sequence_groups_names_); + + for (int i = 0; i < header_->numseqgroups; ++i, ++pseqgroup) { + aiNode *sequence_group_node = sequence_groups_node->mChildren[i] = new aiNode(unique_sequence_groups_names_[i]); + sequence_group_node->mParent = sequence_groups_node; + + aiMetadata *md = sequence_group_node->mMetaData = aiMetadata::Alloc(1); + if (i == 0) { + /* StudioMDL does not write the file name for the default sequence group, + so we will write it. */ + md->Set(0, "File", aiString(file_path_)); + } else { + md->Set(0, "File", aiString(pseqgroup->name)); + } + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_sequence_infos() { + if (!header_->numseq) + return; + + const SequenceDesc_HL1 *pseqdesc = (const SequenceDesc_HL1 *)((uint8_t *)header_ + header_->seqindex); + + aiNode *sequence_infos_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_INFOS); + rootnode_children_.push_back(sequence_infos_node); + + sequence_infos_node->mNumChildren = static_cast(header_->numseq); + sequence_infos_node->mChildren = new aiNode *[sequence_infos_node->mNumChildren]; + + std::vector sequence_info_node_children; + + int animation_index = 0; + for (int i = 0; i < header_->numseq; ++i, ++pseqdesc) { + // Clear the list of children for the upcoming sequence info node. + sequence_info_node_children.clear(); + + aiNode *sequence_info_node = sequence_infos_node->mChildren[i] = new aiNode(unique_sequence_names_[i]); + sequence_info_node->mParent = sequence_infos_node; + + // Setup sequence info node Metadata. + aiMetadata *md = sequence_info_node->mMetaData = aiMetadata::Alloc(16); + md->Set(0, "AnimationIndex", animation_index); + animation_index += pseqdesc->numblends; + + // Reference the sequence group by name. This allows us to search a particular + // sequence group by name using aiNode(s). + md->Set(1, "SequenceGroup", aiString(unique_sequence_groups_names_[pseqdesc->seqgroup])); + md->Set(2, "FramesPerSecond", pseqdesc->fps); + md->Set(3, "NumFrames", pseqdesc->numframes); + md->Set(4, "NumBlends", pseqdesc->numblends); + md->Set(5, "Activity", pseqdesc->activity); + md->Set(6, "ActivityWeight", pseqdesc->actweight); + md->Set(7, "MotionFlags", pseqdesc->motiontype); + md->Set(8, "MotionBone", temp_bones_[pseqdesc->motionbone].node->mName); + md->Set(9, "LinearMovement", aiVector3D(pseqdesc->linearmovement[0], pseqdesc->linearmovement[1], pseqdesc->linearmovement[2])); + md->Set(10, "BBMin", aiVector3D(pseqdesc->bbmin[0], pseqdesc->bbmin[1], pseqdesc->bbmin[2])); + md->Set(11, "BBMax", aiVector3D(pseqdesc->bbmax[0], pseqdesc->bbmax[1], pseqdesc->bbmax[2])); + md->Set(12, "EntryNode", pseqdesc->entrynode); + md->Set(13, "ExitNode", pseqdesc->exitnode); + md->Set(14, "NodeFlags", pseqdesc->nodeflags); + md->Set(15, "Flags", pseqdesc->flags); + + if (import_settings_.read_blend_controllers) { + int num_blend_controllers; + if (get_num_blend_controllers(pseqdesc->numblends, num_blend_controllers) && num_blend_controllers) { + // Read blend controllers info. + aiNode *blend_controllers_node = new aiNode(AI_MDL_HL1_NODE_BLEND_CONTROLLERS); + sequence_info_node_children.push_back(blend_controllers_node); + blend_controllers_node->mParent = sequence_info_node; + blend_controllers_node->mNumChildren = static_cast(num_blend_controllers); + blend_controllers_node->mChildren = new aiNode *[blend_controllers_node->mNumChildren]; + + for (unsigned int j = 0; j < blend_controllers_node->mNumChildren; ++j) { + aiNode *blend_controller_node = blend_controllers_node->mChildren[j] = new aiNode(); + blend_controller_node->mParent = blend_controllers_node; + + aiMetadata *md = blend_controller_node->mMetaData = aiMetadata::Alloc(3); + md->Set(0, "Start", pseqdesc->blendstart[j]); + md->Set(1, "End", pseqdesc->blendend[j]); + md->Set(2, "MotionFlags", pseqdesc->blendtype[j]); + } + } + } + + if (import_settings_.read_animation_events && pseqdesc->numevents) { + // Read animation events. + + if (pseqdesc->numevents > AI_MDL_HL1_MAX_EVENTS) { + log_warning_limit_exceeded( + "Sequence " + std::string(pseqdesc->label), + pseqdesc->numevents, "animation events"); + } + + const AnimEvent_HL1 *pevent = (const AnimEvent_HL1 *)((uint8_t *)header_ + pseqdesc->eventindex); + + aiNode *pEventsNode = new aiNode(AI_MDL_HL1_NODE_ANIMATION_EVENTS); + sequence_info_node_children.push_back(pEventsNode); + pEventsNode->mParent = sequence_info_node; + pEventsNode->mNumChildren = static_cast(pseqdesc->numevents); + pEventsNode->mChildren = new aiNode *[pEventsNode->mNumChildren]; + + for (unsigned int j = 0; j < pEventsNode->mNumChildren; ++j, ++pevent) { + aiNode *pEvent = pEventsNode->mChildren[j] = new aiNode(); + pEvent->mParent = pEventsNode; + + aiMetadata *md = pEvent->mMetaData = aiMetadata::Alloc(3); + md->Set(0, "Frame", pevent->frame); + md->Set(1, "ScriptEvent", pevent->event); + md->Set(2, "Options", aiString(pevent->options)); + } + } + + if (sequence_info_node_children.size()) { + sequence_info_node->addChildren( + static_cast(sequence_info_node_children.size()), + sequence_info_node_children.data()); + } + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_sequence_transitions() { + if (!header_->numtransitions) + return; + + // Read sequence transition graph. + aiNode *transition_graph_node = new aiNode(AI_MDL_HL1_NODE_SEQUENCE_TRANSITION_GRAPH); + rootnode_children_.push_back(transition_graph_node); + + uint8_t *ptransitions = ((uint8_t *)header_ + header_->transitionindex); + aiMetadata *md = transition_graph_node->mMetaData = aiMetadata::Alloc(header_->numtransitions * header_->numtransitions); + for (unsigned int i = 0; i < md->mNumProperties; ++i) + md->Set(i, std::to_string(i), static_cast(ptransitions[i])); +} + +void HL1MDLLoader::read_attachments() { + if (!header_->numattachments) + return; + + const Attachment_HL1 *pattach = (const Attachment_HL1 *)((uint8_t *)header_ + header_->attachmentindex); + + aiNode *attachments_node = new aiNode(AI_MDL_HL1_NODE_ATTACHMENTS); + rootnode_children_.push_back(attachments_node); + attachments_node->mNumChildren = static_cast(header_->numattachments); + attachments_node->mChildren = new aiNode *[attachments_node->mNumChildren]; + + for (int i = 0; i < header_->numattachments; ++i, ++pattach) { + aiNode *attachment_node = attachments_node->mChildren[i] = new aiNode(); + attachment_node->mParent = attachments_node; + attachment_node->mMetaData = aiMetadata::Alloc(2); + attachment_node->mMetaData->Set(0, "Position", aiVector3D(pattach->org[0], pattach->org[1], pattach->org[2])); + // Reference the bone by name. This allows us to search a particular + // bone by name using aiNode(s). + attachment_node->mMetaData->Set(1, "Bone", temp_bones_[pattach->bone].node->mName); + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_hitboxes() { + if (!header_->numhitboxes) + return; + + const Hitbox_HL1 *phitbox = (const Hitbox_HL1 *)((uint8_t *)header_ + header_->hitboxindex); + + aiNode *hitboxes_node = new aiNode(AI_MDL_HL1_NODE_HITBOXES); + rootnode_children_.push_back(hitboxes_node); + hitboxes_node->mNumChildren = static_cast(header_->numhitboxes); + hitboxes_node->mChildren = new aiNode *[hitboxes_node->mNumChildren]; + + for (int i = 0; i < header_->numhitboxes; ++i, ++phitbox) { + aiNode *hitbox_node = hitboxes_node->mChildren[i] = new aiNode(); + hitbox_node->mParent = hitboxes_node; + + aiMetadata *md = hitbox_node->mMetaData = aiMetadata::Alloc(4); + // Reference the bone by name. This allows us to search a particular + // bone by name using aiNode(s). + md->Set(0, "Bone", temp_bones_[phitbox->bone].node->mName); + md->Set(1, "HitGroup", phitbox->group); + md->Set(2, "BBMin", aiVector3D(phitbox->bbmin[0], phitbox->bbmin[1], phitbox->bbmin[2])); + md->Set(3, "BBMax", aiVector3D(phitbox->bbmax[0], phitbox->bbmax[1], phitbox->bbmax[2])); + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_bone_controllers() { + if (!header_->numbonecontrollers) + return; + + const BoneController_HL1 *pbonecontroller = (const BoneController_HL1 *)((uint8_t *)header_ + header_->bonecontrollerindex); + + aiNode *bones_controller_node = new aiNode(AI_MDL_HL1_NODE_BONE_CONTROLLERS); + rootnode_children_.push_back(bones_controller_node); + bones_controller_node->mNumChildren = static_cast(header_->numbonecontrollers); + bones_controller_node->mChildren = new aiNode *[bones_controller_node->mNumChildren]; + + for (int i = 0; i < header_->numbonecontrollers; ++i, ++pbonecontroller) { + aiNode *bone_controller_node = bones_controller_node->mChildren[i] = new aiNode(); + bone_controller_node->mParent = bones_controller_node; + + aiMetadata *md = bone_controller_node->mMetaData = aiMetadata::Alloc(5); + // Reference the bone by name. This allows us to search a particular + // bone by name using aiNode(s). + md->Set(0, "Bone", temp_bones_[pbonecontroller->bone].node->mName); + md->Set(1, "MotionFlags", pbonecontroller->type); + md->Set(2, "Start", pbonecontroller->start); + md->Set(3, "End", pbonecontroller->end); + md->Set(4, "Channel", pbonecontroller->index); + } +} + +// ------------------------------------------------------------------------------------------------ +void HL1MDLLoader::read_global_info() { + aiNode *global_info_node = new aiNode(AI_MDL_HL1_NODE_GLOBAL_INFO); + rootnode_children_.push_back(global_info_node); + + aiMetadata *md = global_info_node->mMetaData = aiMetadata::Alloc(import_settings_.read_misc_global_info ? 16 : 11); + md->Set(0, "Version", AI_MDL_HL1_VERSION); + md->Set(1, "NumBodyparts", header_->numbodyparts); + md->Set(2, "NumModels", total_models_); + md->Set(3, "NumBones", header_->numbones); + md->Set(4, "NumAttachments", import_settings_.read_attachments ? header_->numattachments : 0); + md->Set(5, "NumSkinFamilies", texture_header_->numskinfamilies); + md->Set(6, "NumHitboxes", import_settings_.read_hitboxes ? header_->numhitboxes : 0); + md->Set(7, "NumBoneControllers", import_settings_.read_bone_controllers ? header_->numbonecontrollers : 0); + md->Set(8, "NumSequences", import_settings_.read_animations ? header_->numseq : 0); + md->Set(9, "NumBlendControllers", import_settings_.read_blend_controllers ? num_blend_controllers_ : 0); + md->Set(10, "NumTransitionNodes", import_settings_.read_sequence_transitions ? header_->numtransitions : 0); + + if (import_settings_.read_misc_global_info) { + md->Set(11, "EyePosition", aiVector3D(header_->eyeposition[0], header_->eyeposition[1], header_->eyeposition[2])); + md->Set(12, "HullMin", aiVector3D(header_->min[0], header_->min[1], header_->min[2])); + md->Set(13, "HullMax", aiVector3D(header_->max[0], header_->max[1], header_->max[2])); + md->Set(14, "CollisionMin", aiVector3D(header_->bbmin[0], header_->bbmin[1], header_->bbmin[2])); + md->Set(15, "CollisionMax", aiVector3D(header_->bbmax[0], header_->bbmax[1], header_->bbmax[2])); + } +} + +// ------------------------------------------------------------------------------------------------ +/** @brief This method reads a compressed anim value. +* +* @note The structure of this method is taken from HL2 source code. +* Although this is from HL2, it's implementation is almost identical +* to code found in HL1 SDK. See HL1 and HL2 SDKs for more info. +* +* source: +* HL1 source code. +* file: studio_render.cpp +* function(s): CalcBoneQuaternion and CalcBonePosition +* +* HL2 source code. +* file: bone_setup.cpp +* function(s): ExtractAnimValue +*/ +void HL1MDLLoader::extract_anim_value( + const AnimValue_HL1 *panimvalue, + int frame, float bone_scale, float &value) { + int k = frame; + + // find span of values that includes the frame we want + while (panimvalue->num.total <= k) { + k -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + } + + // Bah, missing blend! + if (panimvalue->num.valid > k) + value = panimvalue[k + 1].value * bone_scale; + else + value = panimvalue[panimvalue->num.valid].value * bone_scale; +} + +// ------------------------------------------------------------------------------------------------ +// Get the number of blend controllers. +bool HL1MDLLoader::get_num_blend_controllers(const int num_blend_animations, int &num_blend_controllers) { + + switch (num_blend_animations) { + case SequenceBlendMode_HL1::NoBlend: + num_blend_controllers = 0; + return true; + case SequenceBlendMode_HL1::TwoWayBlending: + num_blend_controllers = 1; + return true; + case SequenceBlendMode_HL1::FourWayBlending: + num_blend_controllers = 2; + return true; + default: + num_blend_controllers = 0; + ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER "Unsupported number of blend animations (" + std::to_string(num_blend_animations) + ")"); + return false; + } +} + +} // namespace HalfLife +} // namespace MDL +} // namespace Assimp diff --git a/code/MDL/HalfLife/HL1MDLLoader.h b/code/MDL/HalfLife/HL1MDLLoader.h new file mode 100644 index 000000000..f0b227b55 --- /dev/null +++ b/code/MDL/HalfLife/HL1MDLLoader.h @@ -0,0 +1,235 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file HL1MDLLoader.h + * @brief Declaration of the Half-Life 1 MDL loader. + */ + +#ifndef AI_HL1MDLLOADER_INCLUDED +#define AI_HL1MDLLOADER_INCLUDED + +#include "HL1FileData.h" +#include "HL1ImportSettings.h" +#include "UniqueNameGenerator.h" + +#include +#include +#include + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +class HL1MDLLoader { +public: + HL1MDLLoader() = delete; + HL1MDLLoader(const HL1MDLLoader &) = delete; + + /** See variables descriptions at the end for more details. */ + HL1MDLLoader( + aiScene *scene, + IOSystem *io, + const unsigned char *buffer, + const std::string &file_path, + const HL1ImportSettings &import_settings); + + ~HL1MDLLoader(); + + void load_file(); + +protected: + /** \brief Validate the header data structure of a Half-Life 1 MDL file. + * \param[in] header Input header to be validated. + * \param[in] is_texture_header Whether or not we are reading an MDL + * texture file. + */ + void validate_header(const Header_HL1 *header, bool is_texture_header); + + void load_texture_file(); + void load_sequence_groups_files(); + void read_textures(); + void read_skins(); + void read_bones(); + void read_meshes(); + void read_animations(); + void read_sequence_groups_info(); + void read_sequence_infos(); + void read_sequence_transitions(); + void read_attachments(); + void read_hitboxes(); + void read_bone_controllers(); + void read_global_info(); + +private: + void release_resources(); + + /** \brief Load a file and copy it's content to a buffer. + * \param file_path The path to the file to be loaded. + * \param buffer A pointer to a buffer to receive the data. + */ + template + void load_file_into_buffer(const std::string &file_path, unsigned char *&buffer); + + /** \brief Read an MDL texture. + * \param[in] ptexture A pointer to an MDL texture. + * \param[in] data A pointer to the data from \p ptexture. + * \param[in] pal A pointer to the texture palette from \p ptexture. + * \param[in,out] pResult A pointer to the output resulting Assimp texture. + * \param[in,out] last_palette_color The last color from the image palette. + */ + void read_texture(const Texture_HL1 *ptexture, + uint8_t *data, uint8_t *pal, aiTexture *pResult, + aiColor3D &last_palette_color); + + /** \brief This method reads a compressed anim value. + * \param[in] panimvalue A pointer to the animation data. + * \param[in] frame The frame to look for. + * \param[in] bone_scale The current bone scale to apply to the compressed value. + * \param[in,out] value The decompressed anim value at \p frame. + */ + void extract_anim_value(const AnimValue_HL1 *panimvalue, + int frame, float bone_scale, float &value); + + /** + * \brief Given the number of blend animations, determine the number of blend controllers. + * + * \param[in] num_blend_animations The number of blend animations. + * \param[out] num_blend_controllers The number of blend controllers. + * \return True if the number of blend controllers was determined. False otherwise. + */ + static bool get_num_blend_controllers(const int num_blend_animations, int &num_blend_controllers); + + /** Output scene to be filled */ + aiScene *scene_; + + /** Output I/O handler. Required for additional IO operations. */ + IOSystem *io_; + + /** Buffer from MDLLoader class. */ + const unsigned char *buffer_; + + /** The full file path to the MDL file we are trying to load. + * Used to locate other MDL files since MDL may store resources + * in external MDL files. */ + const std::string &file_path_; + + /** Configuration for HL1 MDL */ + const HL1ImportSettings &import_settings_; + + /** Main MDL header. */ + const Header_HL1 *header_; + + /** External MDL texture header. */ + const Header_HL1 *texture_header_; + + /** External MDL animation headers. + * One for each loaded animation file. */ + SequenceHeader_HL1 **anim_headers_; + + /** Texture file data. */ + unsigned char *texture_buffer_; + + /** Animation files data. */ + unsigned char **anim_buffers_; + + /** The number of sequence groups. */ + int num_sequence_groups_; + + /** The list of children to be appended to the scene's root node. */ + std::vector rootnode_children_; + + /** A unique name generator. Used to generate names for MDL values + * that may have empty/duplicate names. */ + UniqueNameGenerator unique_name_generator_; + + /** The list of unique sequence names. */ + std::vector unique_sequence_names_; + + /** The list of unique sequence groups names. */ + std::vector unique_sequence_groups_names_; + + /** Structure to store temporary bone information. */ + struct TempBone { + + TempBone() : + node(nullptr), + absolute_transform(), + offset_matrix() {} + + aiNode *node; + aiMatrix4x4 absolute_transform; + aiMatrix4x4 offset_matrix; + }; + + std::vector temp_bones_; + + /** The number of available bone controllers in the model. */ + int num_blend_controllers_; + + /** Self explanatory. */ + int total_models_; +}; + +// ------------------------------------------------------------------------------------------------ +template +void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned char *&buffer) { + if (!io_->Exists(file_path)) + throw DeadlyImportError("Missing file " + DefaultIOSystem::fileName(file_path) + "."); + + std::unique_ptr file(io_->Open(file_path)); + + if (file.get() == NULL) + throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + "."); + + const size_t file_size = file->FileSize(); + if (file_size < sizeof(MDLFileHeader)) + throw DeadlyImportError("MDL file is too small."); + + buffer = new unsigned char[1 + file_size]; + file->Read((void *)buffer, 1, file_size); + buffer[file_size] = '\0'; +} + +} // namespace HalfLife +} // namespace MDL +} // namespace Assimp + +#endif // AI_HL1MDLLOADER_INCLUDED diff --git a/code/MDL/HalfLife/HL1MeshTrivert.h b/code/MDL/HalfLife/HL1MeshTrivert.h new file mode 100644 index 000000000..38bd371a0 --- /dev/null +++ b/code/MDL/HalfLife/HL1MeshTrivert.h @@ -0,0 +1,127 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file HL1MeshTrivert.h + * @brief This file contains the class declaration for the + * HL1 mesh trivert class. + */ + +#ifndef AI_HL1MESHTRIVERT_INCLUDED +#define AI_HL1MESHTRIVERT_INCLUDED + +#include "HL1FileData.h" + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +/* A class to help map model triverts to mesh triverts. */ +struct HL1MeshTrivert { + HL1MeshTrivert() : + vertindex(-1), + normindex(-1), + s(0), + t(0), + localindex(-1) { + } + + HL1MeshTrivert(short vertindex, short normindex, short s, short t, short localindex) : + vertindex(vertindex), + normindex(normindex), + s(s), + t(t), + localindex() { + } + + HL1MeshTrivert(const Trivert &a) : + vertindex(a.vertindex), + normindex(a.normindex), + s(a.s), + t(a.t), + localindex(-1) { + } + + inline bool operator==(const Trivert &a) const { + return vertindex == a.vertindex && + normindex == a.normindex && + s == a.s && + t == a.t; + } + + inline bool operator!=(const Trivert &a) const { + return !(*this == a); + } + + inline bool operator==(const HL1MeshTrivert &a) const { + return localindex == a.localindex && + vertindex == a.vertindex && + normindex == a.normindex && + s == a.s && + t == a.t; + } + + inline bool operator!=(const HL1MeshTrivert &a) const { + return !(*this == a); + } + + inline HL1MeshTrivert &operator=(const Trivert &other) { + vertindex = other.vertindex; + normindex = other.normindex; + s = other.s; + t = other.t; + return *this; + } + + short vertindex; + short normindex; + short s, t; + short localindex; +}; + +struct HL1MeshFace { + short v0, v1, v2; +}; + +} // namespace HalfLife +} // namespace MDL +} // namespace Assimp + +#endif // AI_HL1MESHTRIVERT_INCLUDED diff --git a/code/MDL/HalfLife/HalfLifeMDLBaseHeader.h b/code/MDL/HalfLife/HalfLifeMDLBaseHeader.h new file mode 100644 index 000000000..496268512 --- /dev/null +++ b/code/MDL/HalfLife/HalfLifeMDLBaseHeader.h @@ -0,0 +1,64 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file HalfLifeMDLBaseHeader.h */ + +#ifndef AI_HALFLIFEMDLBASEHEADER_INCLUDED +#define AI_HALFLIFEMDLBASEHEADER_INCLUDED + +#include + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +/** Used to interface different Valve MDL formats. */ +struct HalfLifeMDLBaseHeader +{ + char ident[4]; + int32_t version; +}; + +} +} +} + +#endif // AI_HALFLIFEMDLBASEHEADER_INCLUDED diff --git a/code/MDL/HalfLife/LogFunctions.h b/code/MDL/HalfLife/LogFunctions.h new file mode 100644 index 000000000..db82a2604 --- /dev/null +++ b/code/MDL/HalfLife/LogFunctions.h @@ -0,0 +1,95 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file LogFunctions.h */ + +#ifndef AI_MDL_HALFLIFE_LOGFUNCTIONS_INCLUDED +#define AI_MDL_HALFLIFE_LOGFUNCTIONS_INCLUDED + +#include +#include + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +/** + * \brief A function to log precise messages regarding limits exceeded. + * + * \param[in] subject Subject. + * \param[in] current_amount Current amount. + * \param[in] direct_object Direct object. + * LIMIT Limit constant. + * + * Example: Model has 100 textures, which exceeds the limit (50) + * + * where \p subject is 'Model' + * \p current_amount is '100' + * \p direct_object is 'textures' + * LIMIT is '50' + */ +template +static inline void log_warning_limit_exceeded( + const std::string &subject, int current_amount, + const std::string &direct_object) { + + ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER + + subject + + " has " + + std::to_string(current_amount) + " " + + direct_object + + ", which exceeds the limit (" + + std::to_string(LIMIT) + + ")"); +} + +/** \brief Same as above, but uses 'Model' as the subject. */ +template +static inline void log_warning_limit_exceeded(int current_amount, + const std::string &direct_object) { + log_warning_limit_exceeded("Model", current_amount, direct_object); +} + +} // namespace HalfLife +} // namespace MDL +} // namespace Assimp + +#endif // AI_MDL_HALFLIFE_LOGFUNCTIONS_INCLUDED diff --git a/code/MDL/HalfLife/UniqueNameGenerator.cpp b/code/MDL/HalfLife/UniqueNameGenerator.cpp new file mode 100644 index 000000000..8c46b1078 --- /dev/null +++ b/code/MDL/HalfLife/UniqueNameGenerator.cpp @@ -0,0 +1,180 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file UniqueNameGenerator.cpp + * @brief Implementation for the unique name generator. + */ + +#include "UniqueNameGenerator.h" +#include +#include +#include +#include + +namespace Assimp { +namespace MDL { +namespace HalfLife { + +UniqueNameGenerator::UniqueNameGenerator() : + template_name_("unnamed"), + separator_("_") { +} + +UniqueNameGenerator::UniqueNameGenerator(const char *template_name) : + template_name_(template_name), + separator_("_") { +} + +UniqueNameGenerator::UniqueNameGenerator(const char *template_name, const char *separator) : + template_name_(template_name), + separator_(separator) { +} + +UniqueNameGenerator::~UniqueNameGenerator() { +} + +void UniqueNameGenerator::make_unique(std::vector &names) { + struct DuplicateInfo { + DuplicateInfo() : + indices(), + next_id(0) { + } + + std::list indices; + size_t next_id; + }; + + std::vector empty_names_indices; + std::vector template_name_duplicates; + std::map names_to_duplicates; + + const std::string template_name_with_separator(template_name_ + separator_); + + auto format_name = [&](const std::string &base_name, size_t id) -> std::string { + return base_name + separator_ + std::to_string(id); + }; + + auto generate_unique_name = [&](const std::string &base_name) -> std::string { + auto *duplicate_info = &names_to_duplicates[base_name]; + + std::string new_name = ""; + + bool found_identical_name; + bool tried_with_base_name_only = false; + do { + // Assume that no identical name exists. + found_identical_name = false; + + if (!tried_with_base_name_only) { + // First try with only the base name. + new_name = base_name; + } else { + // Create the name expected to be unique. + new_name = format_name(base_name, duplicate_info->next_id); + } + + // Check in the list of duplicates for an identical name. + for (size_t i = 0; + i < names.size() && + !found_identical_name; + ++i) { + if (new_name == names[i]) + found_identical_name = true; + } + + if (tried_with_base_name_only) + ++duplicate_info->next_id; + + tried_with_base_name_only = true; + + } while (found_identical_name); + + return new_name; + }; + + for (size_t i = 0; i < names.size(); ++i) { + // Check for empty names. + if (names[i].find_first_not_of(' ') == std::string::npos) { + empty_names_indices.push_back(i); + continue; + } + + /* Check for potential duplicate. + a) Either if this name is the same as the template name or + b)

;L>CQ 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�gJBLoIumiG%@$cC$*aGinDEx6;vsTTpMXXvG@E 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ⅆ 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

;L>CQ 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�gJBLoIumiG%@$cC$*aGinDEx6;vsTTpMXXvG@E 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ⅆ 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