From cd4ef0a2e90c06a30e7359c133f44a8cf232c65e Mon Sep 17 00:00:00 2001 From: Victor NG Date: Sat, 21 Oct 2017 18:15:46 +0800 Subject: [PATCH 01/78] Update ColladaExporter.h --- code/ColladaExporter.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index c78272726..e7a4a9b5d 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -114,7 +114,9 @@ protected: /// Writes the given mesh void WriteGeometry( size_t pIndex); - enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight }; + //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight }; + // customized to add animation related type + enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time }; /// Writes a float array of the given type void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount); @@ -122,6 +124,11 @@ protected: /// Writes the scene library void WriteSceneLibrary(); + // customized, Writes the animation library + void WriteAnimationsLibrary(); + void WriteAnimationLibrary( size_t pIndex); + std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call. + /// Recursively writes the given node void WriteNode( const aiScene* scene, aiNode* pNode); From 90ba199ad412aa07400fb55af25d87fd93a2d421 Mon Sep 17 00:00:00 2001 From: Victor NG Date: Sat, 21 Oct 2017 18:28:14 +0800 Subject: [PATCH 02/78] Update ColladaExporter.cpp --- code/ColladaExporter.cpp | 254 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 250 insertions(+), 4 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 06604bc8e..52562a9f7 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -137,6 +137,9 @@ void ColladaExporter::WriteFile() WriteControllerLibrary(); WriteSceneLibrary(); + + // customized, Writes the animation library + WriteAnimationsLibrary(); // useless Collada fu at the end, just in case we haven't had enough indirections, yet. mOutput << startstr << "" << endstr; @@ -1125,6 +1128,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy case FloatType_Color: floatsPerElement = 3; break; case FloatType_Mat4x4: floatsPerElement = 16; break; case FloatType_Weight: floatsPerElement = 1; break; + case FloatType_Time: floatsPerElement = 1; break; default: return; } @@ -1201,7 +1205,13 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy case FloatType_Weight: mOutput << startstr << "" << endstr; break; - } + + // customized, add animation related + case FloatType_Time: + mOutput << startstr << "" << endstr; + break; + + } PopTag(); mOutput << startstr << "" << endstr; @@ -1231,7 +1241,170 @@ void ColladaExporter::WriteSceneLibrary() PopTag(); mOutput << startstr << "" << endstr; } +// ------------------------------------------------------------------------------------------------ +void ColladaExporter::WriteAnimationLibrary(size_t pIndex) +{ + const aiAnimation * anim = mScene->mAnimations[pIndex]; + + if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) + return; + + const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() ); + std::string idstr = anim->mName.C_Str(); + std::string ending = std::string( "AnimId" ) + to_string(pIndex); + if (idstr.length() >= ending.length()) { + if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) { + idstr = idstr + ending; + } + } else { + idstr = idstr + ending; + } + const std::string idstrEscaped = XMLEscape(idstr); + + mOutput << startstr << "" << endstr; + PushTag(); + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim * nodeAnim = anim->mChannels[a]; + + // sanity check + if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue; + + { + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input"); + + std::vector frames; + for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + frames.push_back(nodeAnim->mPositionKeys[i].mTime); + } + + WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size()); + frames.clear(); + } + + { + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output"); + + std::vector keyframes; + keyframes.reserve(nodeAnim->mNumPositionKeys * 16); + for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + + aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; + aiMatrix4x4 ScalingM; // identity + ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z; + + aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue; + aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() ); + aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1); + + aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue; + aiMatrix4x4 TranslationM; // identity + TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z; + + // Combine the above transformations + aiMatrix4x4 mat = TranslationM * RotationM * ScalingM; + + for( uint j = 0; j < 4; ++j) + keyframes.insert(keyframes.end(), mat[j], mat[j] + 4); + } + + WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16); + } + + { + std::vector names; + for (int i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT + || nodeAnim->mPreState == aiAnimBehaviour_LINEAR + || nodeAnim->mPreState == aiAnimBehaviour_REPEAT + ) { + names.push_back( "LINEAR" ); + } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) { + names.push_back( "STEP" ); + } + } + + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); + std::string arrayId = node_idstr + "-array"; + + mOutput << startstr << "" << endstr; + PushTag(); + + // source array + mOutput << startstr << " "; + for( size_t a = 0; a < names.size(); ++a ) + mOutput << names[a] << " "; + mOutput << "" << endstr; + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + } + + } + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim * nodeAnim = anim->mChannels[a]; + + { + // samplers + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler"); + 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; + + PopTag(); + mOutput << startstr << "" << endstr; + } + } + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim * nodeAnim = anim->mChannels[a]; + + { + // channels + mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLEscape(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; + } + } + + PopTag(); + mOutput << startstr << "" << endstr; + +} +// ------------------------------------------------------------------------------------------------ +void ColladaExporter::WriteAnimationsLibrary() +{ + const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str()); + + if ( mScene->mNumAnimations > 0 ) { + mOutput << startstr << "" << endstr; + PushTag(); + + // start recursive write at the root node + for( size_t a = 0; a < mScene->mNumAnimations; ++a) + WriteAnimationLibrary( a ); + + PopTag(); + mOutput << startstr << "" << endstr; + } +} // ------------------------------------------------------------------------------------------------ // Helper to find a bone by name in the scene aiBone* findBone( const aiScene* scene, const char * name) { @@ -1247,6 +1420,59 @@ aiBone* findBone( const aiScene* scene, const char * name) { return NULL; } +// ------------------------------------------------------------------------------------------------ +const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone) +{ + if ( aNode && bone && aNode->mName == bone->mName ) { + return aNode; + } + + if ( aNode && bone ) { + for (unsigned int i=0; i < aNode->mNumChildren; ++i) { + aiNode * aChild = aNode->mChildren[i]; + const aiNode * foundFromChild = 0; + if ( aChild ) { + foundFromChild = findBoneNode( aChild, bone ); + if ( foundFromChild ) return foundFromChild; + } + } + } + + return NULL; +} + +const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) +{ + std::set topParentBoneNodes; + if ( mesh && mesh->mNumBones > 0 ) { + for (unsigned int i=0; i < mesh->mNumBones; ++i) { + aiBone * bone = mesh->mBones[i]; + + const aiNode * node = findBoneNode( scene->mRootNode, bone); + if ( node ) { + while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) { + node = node->mParent; + } + topParentBoneNodes.insert( node ); + } + } + } + + if ( !topParentBoneNodes.empty() ) { + const aiNode * parentBoneNode = *topParentBoneNodes.begin(); + if ( topParentBoneNodes.size() == 1 ) { + return parentBoneNode; + } else { + for (auto it : topParentBoneNodes) { + if ( it->mParent ) return it->mParent; + } + return parentBoneNode; + } + } + + return NULL; +} + // ------------------------------------------------------------------------------------------------ // Recursively writes the given node void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) @@ -1274,12 +1500,22 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) } const std::string node_name_escaped = XMLEscape(pNode->mName.data); + /* // customized, Note! the id field is crucial for inter-xml look up, it cannot be replaced with sid ?! mOutput << startstr << "" << endstr; PushTag(); @@ -1287,7 +1523,11 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // write transformation - we can directly put the matrix there // TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards const aiMatrix4x4& mat = pNode->mTransformation; - mOutput << startstr << ""; + + // customized, sid should be 'matrix' to match with loader code. + //mOutput << startstr << ""; + mOutput << startstr << ""; + mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " "; mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " "; @@ -1331,7 +1571,13 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) << endstr; PushTag(); - mOutput << startstr << "#skeleton_root" << endstr; + // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. + // use the first bone to find skeleton root + const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh ); + if ( skeletonRootBoneNode ) { + mFoundSkeletonRootNodeID = XMLEscape( skeletonRootBoneNode->mName.C_Str() ); + } + mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; } mOutput << startstr << "" << endstr; PushTag(); From aca8f068d048275db0ac5ec3e8a98118110fd0cf Mon Sep 17 00:00:00 2001 From: Victor NG Date: Mon, 30 Oct 2017 16:29:57 +0800 Subject: [PATCH 03/78] Update ColladaExporter.cpp --- code/ColladaExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 52562a9f7..dd3a9ed1d 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -1314,7 +1314,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { std::vector names; - for (int i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT || nodeAnim->mPreState == aiAnimBehaviour_LINEAR || nodeAnim->mPreState == aiAnimBehaviour_REPEAT From 711050de8a031c05d41aa19035de2a4ece94a0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20J=C3=B8rgen=20Solberg?= Date: Mon, 30 Oct 2017 19:08:51 +0100 Subject: [PATCH 04/78] fix frame pointer arithmetic --- code/MD2Loader.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index cb494d5b2..f0a5432bf 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -274,11 +274,9 @@ void MD2Importer::InternReadFile( const std::string& pFile, aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - // navigate to the begin of the frame data - BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetFrames); - - pcFrame += configFrameID; + // navigate to the begin of the current frame data + BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*) + m_pcHeader + m_pcHeader->offsetFrames + (m_pcHeader->frameSize * configFrameID)); // navigate to the begin of the triangle data MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*) From 4a4f3fddc7b1b6619e870502f3cd255148900b94 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 5 Nov 2017 22:52:07 +0100 Subject: [PATCH 05/78] closes https://github.com/assimp/assimp/issues/213: log an error instead of letting the fbx-importer crash. --- code/FBXConverter.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index a1121cc40..a1e3ae07c 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -645,7 +645,6 @@ void Converter::ConvertCameras( const Model& model ) } } - void Converter::ConvertLight( const Model& model, const Light& light ) { lights.push_back( new aiLight() ); @@ -783,7 +782,6 @@ const char* Converter::NameTransformationComp( TransformationComp comp ) return NULL; } - const char* Converter::NameTransformationCompProperty( TransformationComp comp ) { switch ( comp ) @@ -2239,9 +2237,17 @@ void Converter::ConvertAnimations() } } +void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) { + if ( node_names.find( fixed_name ) == node_names.end() ) { + FBXImporter::LogError( "Cannot rename node " + fixed_name + ", not existing."); + return; + } + + if ( node_names.find( new_name ) != node_names.end() ) { + FBXImporter::LogError( "Cannot rename node " + fixed_name + " to " + new_name +", name already existing." ); + return; + } -void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) -{ ai_assert( node_names.find( fixed_name ) != node_names.end() ); ai_assert( node_names.find( new_name ) == node_names.end() ); From 9a9f18bbed8938323548335d9225e480a0ea8ca6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 6 Nov 2017 22:30:07 +0100 Subject: [PATCH 06/78] closes https://github.com/assimp/assimp/issues/104: deal with more solids in one STL file. --- code/STLLoader.cpp | 86 ++++++++++++++++++++++++++++------------------ code/STLLoader.h | 60 ++++++++++++++++++-------------- 2 files changed, 86 insertions(+), 60 deletions(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index f4d6ddda7..6b71ba920 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -200,17 +200,17 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS if (IsBinarySTL(mBuffer, fileSize)) { bMatClr = LoadBinaryFile(); } else if (IsAsciiSTL(mBuffer, fileSize)) { - LoadASCIIFile(); + LoadASCIIFile( pScene->mRootNode ); } else { throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + "."); } // add all created meshes to the single node - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + /*pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; for (unsigned int i = 0; i < pScene->mNumMeshes; i++) pScene->mRootNode->mMeshes[i] = i; - + */ // create a single default material, using a white diffuse color for consistency with // other geometric types (e.g., PLY). aiMaterial* pcMat = new aiMaterial(); @@ -231,11 +231,12 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials[0] = pcMat; } + // ------------------------------------------------------------------------------------------------ // Read an ASCII STL file -void STLImporter::LoadASCIIFile() -{ +void STLImporter::LoadASCIIFile( aiNode *root ) { std::vector meshes; + std::vector nodes; const char* sz = mBuffer; const char* bufferEnd = mBuffer + fileSize; std::vector positionBuffer; @@ -247,12 +248,15 @@ void STLImporter::LoadASCIIFile() positionBuffer.reserve(sizeEstimate); normalBuffer.reserve(sizeEstimate); - while (IsAsciiSTL(sz, static_cast(bufferEnd - sz))) - { + while (IsAsciiSTL(sz, static_cast(bufferEnd - sz))) { + std::vector meshIndices; aiMesh* pMesh = new aiMesh(); pMesh->mMaterialIndex = 0; + meshIndices.push_back( meshes.size() ); meshes.push_back(pMesh); - + aiNode *node = new aiNode; + node->mParent = root; + nodes.push_back( node ); SkipSpaces(&sz); ai_assert(!IsLineEnd(sz)); @@ -265,20 +269,21 @@ void STLImporter::LoadASCIIFile() size_t temp; // setup the name of the node - if ((temp = (size_t)(sz-szMe))) { + if ((temp = (size_t)(sz-szMe))) { if (temp >= MAXLEN) { throw DeadlyImportError( "STL: Node name too long" ); } - - pScene->mRootNode->mName.length = temp; - memcpy(pScene->mRootNode->mName.data,szMe,temp); - pScene->mRootNode->mName.data[temp] = '\0'; + std::string name( szMe, temp ); + node->mName.Set( name.c_str() ); + //pScene->mRootNode->mName.length = temp; + //memcpy(pScene->mRootNode->mName.data,szMe,temp); + //pScene->mRootNode->mName.data[temp] = '\0'; + } else { + pScene->mRootNode->mName.Set(""); } - else pScene->mRootNode->mName.Set(""); unsigned int faceVertexCounter = 3; - for ( ;; ) - { + for ( ;; ) { // go to the next token if(!SkipSpacesAndLineEnd(&sz)) { @@ -300,9 +305,7 @@ void STLImporter::LoadASCIIFile() SkipSpaces(&sz); if (strncmp(sz,"normal",6)) { DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); - } - else - { + } else { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } @@ -316,16 +319,11 @@ void STLImporter::LoadASCIIFile() normalBuffer.push_back(*vn); normalBuffer.push_back(*vn); } - } - // vertex 1.50000 1.50000 0.00000 - else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) - { + } else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000 if (faceVertexCounter >= 3) { DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); ++sz; - } - else - { + } else { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } @@ -340,17 +338,14 @@ void STLImporter::LoadASCIIFile() sz = fast_atoreal_move(sz, (ai_real&)vn->z ); faceVertexCounter++; } - } - else if (!::strncmp(sz,"endsolid",8)) { + } else if (!::strncmp(sz,"endsolid",8)) { do { ++sz; } while (!::IsLineEnd(*sz)); SkipSpacesAndLineEnd(&sz); // finished! break; - } - // else skip the whole identifier - else { + } else { // else skip the whole identifier do { ++sz; } while (!::IsSpaceOrNewLine(*sz)); @@ -380,13 +375,22 @@ void STLImporter::LoadASCIIFile() // now copy faces addFacesToMesh(pMesh); + + // assign the meshes to the current node + pushMeshesToNode( meshIndices, node ); } + // now add the loaded meshes pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for (size_t i = 0; i < meshes.size(); i++) - { - pScene->mMeshes[i] = meshes[i]; + for (size_t i = 0; i < meshes.size(); i++) { + pScene->mMeshes[ i ] = meshes[i]; + } + + root->mNumChildren = nodes.size(); + root->mChildren = new aiNode*[ root->mNumChildren ]; + for ( size_t i=0; imChildren[ i ] = nodes[ i ]; } } @@ -513,4 +517,18 @@ bool STLImporter::LoadBinaryFile() return false; } +void STLImporter::pushMeshesToNode( std::vector &meshIndices, aiNode *node ) { + ai_assert( nullptr != node ); + if ( meshIndices.empty() ) { + return; + } + + node->mNumMeshes = static_cast( meshIndices.size() ); + node->mMeshes = new unsigned int[ meshIndices.size() ]; + for ( size_t i=0; imMeshes[ i ] = meshIndices[ i ]; + } + meshIndices.clear(); +} + #endif // !! ASSIMP_BUILD_NO_STL_IMPORTER diff --git a/code/STLLoader.h b/code/STLLoader.h index 87ed3288d..ff7b32a15 100644 --- a/code/STLLoader.h +++ b/code/STLLoader.h @@ -48,53 +48,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseImporter.h" #include -namespace Assimp { +// Forward declarations +class aiNode; + +namespace Assimp { + // --------------------------------------------------------------------------- -/** Importer class for the sterolithography STL file format -*/ -class STLImporter : public BaseImporter -{ +/** + * @brief Importer class for the sterolithography STL file format. + */ +class STLImporter : public BaseImporter { public: + /** + * @brief STLImporter, the class default constructor. + */ STLImporter(); + + /** + * @brief The class destructor. + */ ~STLImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. + /** + * @brief 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; + bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; protected: - // ------------------------------------------------------------------- - /** Return importer meta information. - * See #BaseImporter::GetInfo for the details + /** + * @brief Return importer meta information. + * See #BaseImporter::GetInfo for the details */ const aiImporterDesc* GetInfo () const; - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. + /** + * @brief Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Loads a binary .stl file + /** + * @brief Loads a binary .stl file * @return true if the default vertex color must be used as material color - */ + */ bool LoadBinaryFile(); - // ------------------------------------------------------------------- - /** Loads a ASCII text .stl file - */ - void LoadASCIIFile(); + /** + * @brief Loads a ASCII text .stl file + */ + void LoadASCIIFile( aiNode *root ); + + void pushMeshesToNode( std::vector &meshIndices, aiNode *node ); protected: From 26171a7949178d6b98140c749ccc9806792b4fa6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 6 Nov 2017 22:37:52 +0100 Subject: [PATCH 07/78] SLD: add test model and a unit test. --- test/CMakeLists.txt | 1 + test/models/STL/triangle_with_two_solids.stl | 18 ++++++ test/unit/utSTLImportExport.cpp | 68 ++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 test/models/STL/triangle_with_two_solids.stl create mode 100644 test/unit/utSTLImportExport.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 62270b935..e50e8a742 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -131,6 +131,7 @@ SET( TEST_SRCS unit/utXImporterExporter.cpp unit/utD3MFImportExport.cpp unit/utQ3DImportExport.cpp + unit/utSTLImportExport.cpp unit/utProfiler.cpp ) SET( POST_PROCESSES diff --git a/test/models/STL/triangle_with_two_solids.stl b/test/models/STL/triangle_with_two_solids.stl new file mode 100644 index 000000000..9af3841ae --- /dev/null +++ b/test/models/STL/triangle_with_two_solids.stl @@ -0,0 +1,18 @@ +solid testTriangle_1 + facet normal 0.0 0.0 1.0 + outer loop + vertex 1.0 1.0 0.0 + vertex -1.0 1.0 0.0 + vertex 0.0 -1.0 0.0 + endloop + endfacet +endsolid +solid testTriangle_2 + facet normal 0.0 0.0 1.0 + outer loop + vertex 3.0 3.0 0.0 + vertex 2.0 3.0 0.0 + vertex 0.0 2.0 0.0 + endloop + endfacet +endsolid diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp new file mode 100644 index 000000000..0ee3de955 --- /dev/null +++ b/test/unit/utSTLImportExport.cpp @@ -0,0 +1,68 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 + +using namespace Assimp; + +class utSTLImporterExporter : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", 0 ); + return nullptr != scene; + } +}; + +TEST_F( utSTLImporterExporter, importXFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} + +TEST_F( utSTLImporterExporter, test_with_two_solids ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", 0 ); + EXPECT_NE( nullptr, scene ); +} From 4ff2592747787eedca14e24ad1d088250eab86da Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 7 Nov 2017 00:31:09 +0100 Subject: [PATCH 08/78] Update STLLoader.h Fixed a typo. --- code/STLLoader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STLLoader.h b/code/STLLoader.h index ff7b32a15..c51604861 100644 --- a/code/STLLoader.h +++ b/code/STLLoader.h @@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include // Forward declarations -class aiNode; +struct aiNode; namespace Assimp { From b87e7643d2534a561301631bf87cdee3397bf366 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 7 Nov 2017 10:42:51 +0100 Subject: [PATCH 09/78] Update STLLoader.cpp Fix memory-alignment bug. --- code/STLLoader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 6b71ba920..a492d47e8 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -80,7 +80,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) { return false; } - const uint32_t faceCount = *reinterpret_cast(buffer + 80); + char *facecount_pos = buffer + 80; + uint32_t faceCount( 0 ); + ::memcpy( &faceCount, facecount_pos, sizeof( uint32_t ) ); const uint32_t expectedBinaryFileSize = faceCount * 50 + 84; return expectedBinaryFileSize == fileSize; From da7ce89ff23425b217194c3d1bde06d4d2a5936b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 7 Nov 2017 10:47:27 +0100 Subject: [PATCH 10/78] Update STLLoader.cpp add missing const. --- code/STLLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index a492d47e8..600c4275d 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -80,7 +80,7 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) { return false; } - char *facecount_pos = buffer + 80; + const char *facecount_pos = buffer + 80; uint32_t faceCount( 0 ); ::memcpy( &faceCount, facecount_pos, sizeof( uint32_t ) ); const uint32_t expectedBinaryFileSize = faceCount * 50 + 84; From f41ed2f41fd09e0680e72bbe84f8b899fd802540 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 8 Nov 2017 01:07:04 +0100 Subject: [PATCH 11/78] closes https://github.com/assimp/assimp/issues/1251: use correct lookup for utf32. --- code/STEPFileEncoding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STEPFileEncoding.cpp b/code/STEPFileEncoding.cpp index f9a9dd1ce..7204f802b 100644 --- a/code/STEPFileEncoding.cpp +++ b/code/STEPFileEncoding.cpp @@ -334,7 +334,7 @@ bool STEP::StringToUTF8(std::string& s) size_t j = basei, jend = s.size()-3; for (; j < jend; ++j) { - if (s[j] == '\\' && s[j] == 'X' && s[j] == '0' && s[j] == '\\') { + if (s[j] == '\\' && s[j+1] == 'X' && s[j+2] == '0' && s[j+3] == '\\') { break; } } From fe55bc9996a420ff52495ea7ab58d61c62a88937 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 8 Nov 2017 18:34:16 +0100 Subject: [PATCH 12/78] Update ColladaExporter.cpp fix build --- code/ColladaExporter.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 94a0b1539..aa4ea2fc5 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -1309,8 +1309,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) // Combine the above transformations aiMatrix4x4 mat = TranslationM * RotationM * ScalingM; - for( uint j = 0; j < 4; ++j) + for( size_t j = 0; j < 4; ++j) { keyframes.insert(keyframes.end(), mat[j], mat[j] + 4); + } } WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16); @@ -1337,8 +1338,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) // source array mOutput << startstr << " "; - for( size_t a = 0; a < names.size(); ++a ) + for( size_t a = 0; a < names.size(); ++a ) { mOutput << names[a] << " "; + } mOutput << "" << endstr; mOutput << startstr << "" << endstr; From cdfd4b9702ebf053d00321fe5b47ab8a35695866 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 8 Nov 2017 20:44:53 +0100 Subject: [PATCH 13/78] closes https://github.com/assimp/assimp/issues/1315: check in exporting against out-of-bounds-access . --- code/ObjExporter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index fffafa328..6dd68b8f5 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -258,7 +258,6 @@ void ObjExporter::WriteMaterialFile() } } -// ------------------------------------------------------------------------------------------------ void ObjExporter::WriteGeometryFile(bool noMtl) { WriteHeader(mOutput); if (!noMtl) @@ -280,8 +279,10 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { mOutput << "# " << vp.size() << " vertex positions and colors" << endl; size_t colIdx = 0; for ( const aiVector3D& v : vp ) { - mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl; - colIdx++; + if ( colIdx < vc.size() ) { + mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl; + } + ++colIdx; } } mOutput << endl; From 36475bf868feef74a8807e8f99edcd002878f8b0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 8 Nov 2017 20:50:16 +0100 Subject: [PATCH 14/78] closes https://github.com/assimp/assimp/issues/1292: export class subdivision --- code/Subdivision.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/code/Subdivision.h b/code/Subdivision.h index b8ce228d2..d06bc09d6 100644 --- a/code/Subdivision.h +++ b/code/Subdivision.h @@ -40,10 +40,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Defines a helper class to evaluate subdivision surfaces.*/ +#pragma once #ifndef AI_SUBDISIVION_H_INC #define AI_SUBDISIVION_H_INC #include +#include + struct aiMesh; namespace Assimp { @@ -52,8 +55,7 @@ namespace Assimp { /** Helper class to evaluate subdivision surfaces. Different algorithms * are provided for choice. */ // ------------------------------------------------------------------------------ -class Subdivider -{ +class ASSIMP_API Subdivider { public: /** Enumerates all supported subvidision algorithms */ @@ -61,12 +63,7 @@ public: CATMULL_CLARKE = 0x1 }; -public: - - virtual ~Subdivider() { - } - -public: + virtual ~Subdivider(); // --------------------------------------------------------------- /** Create a subdivider of a specific type @@ -119,9 +116,13 @@ public: unsigned int num, bool discard_input = false) = 0; -private: }; +inline +Subdivider::~Subdivider() { + // empty +} + } // end namespace Assimp From 9ec117d0bcd97b6e0fc21083c9d995ebc4309527 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 7 Nov 2017 15:13:01 -0500 Subject: [PATCH 15/78] Fix export of deleted meshes; Add LazyDict::Remove method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When I was merging a node’s multiple meshes into that node’s first mesh’s primitives, I was deleting the merged meshes from the node. However, I wasn’t deleting the merged meshes from the mAsset->meshes Dict, causing the gltf2 export to contain extra unreferenced meshes and duplicate primitives. This new code adds a new method to LazyDict, which removes the object from it, taking care to update indexes of the subsequent objects. This change also requires that `Ref`s of `Mesh`es (stored in node->meshes) have their indexes updated. --- code/glTF2Asset.h | 2 ++ code/glTF2Asset.inl | 44 ++++++++++++++++++++++++++++++++++++++++++ code/glTF2Exporter.cpp | 28 +++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index a98fe5ab2..c9390d8d4 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -971,6 +971,8 @@ namespace glTF2 Ref Create(const std::string& id) { return Create(id.c_str()); } + unsigned int Remove(const char* id); + inline unsigned int Size() const { return unsigned(mObjs.size()); } diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 8b50fa1d3..c7d0cdc54 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -193,6 +193,50 @@ inline void LazyDict::DetachFromDocument() mDict = 0; } +template +unsigned int LazyDict::Remove(const char* id) +{ + id = T::TranslateId(mAsset, id); + + typename IdDict::iterator it = mObjsById.find(id); + + if (it == mObjsById.end()) { + throw DeadlyExportError("GLTF: Object with id \"" + std::string(id) + "\" is not found"); + } + + const int index = it->second; + + mAsset.mUsedIds[id] = false; + mObjsById.erase(id); + mObjsByOIndex.erase(index); + mObjs.erase(mObjs.begin() + index); + + //update index of object in mObjs; + for (size_t i = index; i < mObjs.size(); ++i) { + T *obj = mObjs[i]; + + obj->index = i; + } + + for (IdDict::iterator it = mObjsById.begin(); it != mObjsById.end(); ++it) { + if (it->second <= index) { + continue; + } + + mObjsById[it->first] = it->second - 1; + } + + for (Dict::iterator it = mObjsByOIndex.begin(); it != mObjsByOIndex.end(); ++it) { + if (it->second <= index) { + continue; + } + + mObjsByOIndex[it->first] = it->second - 1; + } + + return index; +} + template Ref LazyDict::Retrieve(unsigned int i) { diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index d8cff897c..e71d949be 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -800,9 +800,33 @@ void glTF2Exporter::MergeMeshes() for (unsigned int m = nMeshes - 1; m >= 1; --m) { Ref mesh = node->meshes.at(m); - firstMesh->primitives.insert(firstMesh->primitives.end(), mesh->primitives.begin(), mesh->primitives.end()); + //append this mesh's primitives to the first mesh's primitives + firstMesh->primitives.insert( + firstMesh->primitives.end(), + mesh->primitives.begin(), + mesh->primitives.end() + ); - node->meshes.erase(node->meshes.begin() + m); + //remove the mesh from the list of meshes + unsigned int removedIndex = mAsset->meshes.Remove(mesh->id.c_str()); + + //find the presence of the removed mesh in other nodes + for (unsigned int nn = 0; nn < mAsset->nodes.Size(); ++nn) { + Ref node = mAsset->nodes.Get(nn); + + for (unsigned int mm = 0; mm < node->meshes.size(); ++mm) { + Ref& meshRef = node->meshes.at(mm); + unsigned int meshIndex = meshRef.GetIndex(); + + if (meshIndex == removedIndex) { + node->meshes.erase(node->meshes.begin() + mm); + } else if (meshIndex > removedIndex) { + Ref newMeshRef = mAsset->meshes.Get(meshIndex - 1); + + meshRef = newMeshRef; + } + } + } } //since we were looping backwards, reverse the order of merged primitives to their original order From 30e06f7437d3da72b38e452283e163890215fec4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 9 Nov 2017 21:31:16 +0100 Subject: [PATCH 16/78] closes https://github.com/assimp/assimp/issues/216: check the area of a triangle to check if its degenerated or not. --- code/FBXBinaryTokenizer.cpp | 1 - code/FindDegenerates.cpp | 101 ++++++++++++++++++++++++------------ code/STLLoader.cpp | 6 --- code/XFileImporter.h | 5 +- 4 files changed, 68 insertions(+), 45 deletions(-) diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index 9ae38386b..519f2e176 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -422,7 +422,6 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, return true; } - } // ------------------------------------------------------------------------------------------------ diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index 32a09f0c0..5b321312a 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -56,98 +56,131 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindDegeneratesProcess::FindDegeneratesProcess() -: configRemoveDegenerates (false) -{} +: configRemoveDegenerates (false) { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -FindDegeneratesProcess::~FindDegeneratesProcess() -{ +FindDegeneratesProcess::~FindDegeneratesProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const -{ +bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FindDegenerates); } // ------------------------------------------------------------------------------------------------ // Setup import configuration -void FindDegeneratesProcess::SetupProperties(const Importer* pImp) -{ +void FindDegeneratesProcess::SetupProperties(const Importer* pImp) { // Get the current value of AI_CONFIG_PP_FD_REMOVE configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FindDegeneratesProcess::Execute( aiScene* pScene) -{ +void FindDegeneratesProcess::Execute( aiScene* pScene) { DefaultLogger::get()->debug("FindDegeneratesProcess begin"); for (unsigned int i = 0; i < pScene->mNumMeshes;++i){ - ExecuteOnMesh( pScene->mMeshes[i]); + ExecuteOnMesh( pScene->mMeshes[ i ] ); } DefaultLogger::get()->debug("FindDegeneratesProcess finished"); } +static ai_real heron( ai_real a, ai_real b, ai_real c ) { + ai_real s = (a + b + c) / 2; + ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), 0.5 ); + return area; +} + +static ai_real distance3D( const aiVector3D &vA, aiVector3D &vB ) { + const ai_real lx = ( vB.x - vA.x ); + const ai_real ly = ( vB.y - vA.y ); + const ai_real lz = ( vB.z - vA.z ); + ai_real a = lx*lx + ly*ly + lz*lz; + ai_real d = pow( a, 0.5 ); + + return d; +} + +static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) { + ai_real area = 0; + + aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] ); + aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] ); + aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] ); + + ai_real a( distance3D( vA, vB ) ); + ai_real b( distance3D( vB, vC ) ); + ai_real c( distance3D( vC, vA ) ); + area = heron( a, b, c ); + + return area; +} + // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported mesh -void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) -{ +void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { mesh->mPrimitiveTypes = 0; std::vector remove_me; - if (configRemoveDegenerates) - remove_me.resize(mesh->mNumFaces,false); + if (configRemoveDegenerates) { + remove_me.resize( mesh->mNumFaces, false ); + } unsigned int deg = 0, limit; - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) - { + for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) { aiFace& face = mesh->mFaces[a]; bool first = true; // check whether the face contains degenerated entries - for (unsigned int i = 0; i < face.mNumIndices; ++i) - { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { // Polygons with more than 4 points are allowed to have double points, that is // simulating polygons with holes just with concave polygons. However, // double points may not come directly after another. limit = face.mNumIndices; - if (face.mNumIndices > 4) - limit = std::min(limit,i+2); + if (face.mNumIndices > 4) { + limit = std::min( limit, i+2 ); + } - for (unsigned int t = i+1; t < limit; ++t) - { - if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]]) - { + for (unsigned int t = i+1; t < limit; ++t) { + if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) { // we have found a matching vertex position // remove the corresponding index from the array - --face.mNumIndices;--limit; - for (unsigned int m = t; m < face.mNumIndices; ++m) - { - face.mIndices[m] = face.mIndices[m+1]; + --face.mNumIndices; + --limit; + for (unsigned int m = t; m < face.mNumIndices; ++m) { + face.mIndices[ m ] = face.mIndices[ m+1 ]; } --t; // NOTE: we set the removed vertex index to an unique value // to make sure the developer gets notified when his // application attemps to access this data. - face.mIndices[face.mNumIndices] = 0xdeadbeef; + face.mIndices[ face.mNumIndices ] = 0xdeadbeef; - if(first) - { + if(first) { ++deg; first = false; } - if (configRemoveDegenerates) { - remove_me[a] = true; + if ( configRemoveDegenerates ) { + remove_me[ a ] = true; goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby! } } } + ai_real area = calculateAreaOfTriangle( face, mesh ); + if ( area < 1e-6 ) { + if ( configRemoveDegenerates ) { + remove_me[ a ] = true; + goto evil_jump_outside; + } + + // todo: check for index which is corrupt. + } } // We need to update the primitive flags array of the mesh. diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 600c4275d..41f8aad03 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -207,12 +207,6 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + "."); } - // add all created meshes to the single node - /*pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes; i++) - pScene->mRootNode->mMeshes[i] = i; - */ // create a single default material, using a white diffuse color for consistency with // other geometric types (e.g., PLY). aiMaterial* pcMat = new aiMaterial(); diff --git a/code/XFileImporter.h b/code/XFileImporter.h index 528dcb851..0fa6b52eb 100644 --- a/code/XFileImporter.h +++ b/code/XFileImporter.h @@ -65,14 +65,11 @@ struct Node; /** The XFileImporter is a worker class capable of importing a scene from a * DirectX file .x */ -class XFileImporter : public BaseImporter -{ +class XFileImporter : public BaseImporter { public: XFileImporter(); ~XFileImporter(); - -public: // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ From ad2ff9fd713e9bf7a21bf552bec4fdd6e5cee9db Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 9 Nov 2017 21:40:10 +0100 Subject: [PATCH 17/78] check for area test if the face is a triangle. --- code/FindDegenerates.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index 5b321312a..83dce22ba 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -172,14 +172,16 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { } } } - ai_real area = calculateAreaOfTriangle( face, mesh ); - if ( area < 1e-6 ) { - if ( configRemoveDegenerates ) { - remove_me[ a ] = true; - goto evil_jump_outside; - } + if ( face.mNumIndices == 3 ) { + ai_real area = calculateAreaOfTriangle( face, mesh ); + if ( area < 1e-6 ) { + if ( configRemoveDegenerates ) { + remove_me[ a ] = true; + goto evil_jump_outside; + } - // todo: check for index which is corrupt. + // todo: check for index which is corrupt. + } } } From 12dbbd4ce99e0c8d000a6ee33603cbe1280c0166 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 9 Nov 2017 17:19:26 -0500 Subject: [PATCH 18/78] Misc. typos Some are doxy comments, some are just trivial source comment typos. Found using `codespell -q 3 --skip="./contrib" -I ../assimp-whitelist.txt` whereby whitelist contained: ``` childs iff lod nto ot whitespaces ``` --- cmake-modules/CoverallsGenerateGcov.cmake | 4 ++-- code/AMFImporter.hpp | 4 ++-- code/AMFImporter_Node.hpp | 2 +- code/ColladaExporter.cpp | 2 +- code/ColladaHelper.h | 2 +- code/ColladaLoader.cpp | 2 +- code/ColladaParser.cpp | 2 +- code/ColladaParser.h | 2 +- code/LWOMaterial.cpp | 2 +- code/LWSLoader.cpp | 2 +- code/ObjExporter.cpp | 2 +- code/OgreMaterial.cpp | 2 +- code/TextureTransform.cpp | 2 +- code/X3DExporter.hpp | 4 ++-- code/X3DImporter.hpp | 6 +++--- code/glTF2Exporter.cpp | 2 +- code/glTFExporter.cpp | 2 +- doc/Doxyfile.in | 2 +- doc/dox.h | 10 +++++----- include/assimp/config.h.in | 2 +- port/PyAssimp/pyassimp/structs.py | 2 +- port/PyAssimp/scripts/3d_viewer.py | 2 +- port/PyAssimp/scripts/3d_viewer_py3.py | 2 +- port/PyAssimp/scripts/transformations.py | 2 +- port/dAssimp/assimp/mesh.d | 2 +- port/jassimp/jassimp-native/src/jassimp.cpp | 2 +- port/swig/assimp.i | 2 +- samples/SimpleAssimpViewX/MyDocument.mm | 2 +- samples/glut/GL/glut.h | 4 ++-- test/models-nonbsd/BLEND/fleurOptonl.source.txt | 2 +- test/models/AMF/README | 2 +- tools/assimp_qt_viewer/glview.cpp | 2 +- tools/assimp_qt_viewer/glview.hpp | 6 +++--- tools/assimp_qt_viewer/mainwindow.cpp | 2 +- tools/assimp_qt_viewer/mainwindow.hpp | 8 ++++---- tools/assimp_view/assimp_view.rc | 2 +- 36 files changed, 51 insertions(+), 51 deletions(-) diff --git a/cmake-modules/CoverallsGenerateGcov.cmake b/cmake-modules/CoverallsGenerateGcov.cmake index ba506e3d4..104737164 100644 --- a/cmake-modules/CoverallsGenerateGcov.cmake +++ b/cmake-modules/CoverallsGenerateGcov.cmake @@ -310,7 +310,7 @@ foreach (GCOV_FILE ${GCOV_FILES}) message("MD5: ${GCOV_SRC_PATH} = ${GCOV_CONTENTS_MD5}") # Loads the gcov file as a list of lines. - # (We first open the file and replace all occurences of [] with _ + # (We first open the file and replace all occurrences of [] with _ # because CMake will fail to parse a line containing unmatched brackets... # also the \ to escaped \n in macros screws up things.) # https://public.kitware.com/Bug/view.php?id=15369 @@ -329,7 +329,7 @@ foreach (GCOV_FILE ${GCOV_FILES}) # Instead of trying to parse the source from the # gcov file, simply read the file contents from the source file. # (Parsing it from the gcov is hard because C-code uses ; in many places - # which also happens to be the same as the CMake list delimeter). + # which also happens to be the same as the CMake list delimiter). file(READ ${GCOV_SRC_PATH} GCOV_FILE_SOURCE) string(REPLACE "\\" "\\\\" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}") diff --git a/code/AMFImporter.hpp b/code/AMFImporter.hpp index 561ec3c8f..47ddc073b 100644 --- a/code/AMFImporter.hpp +++ b/code/AMFImporter.hpp @@ -249,7 +249,7 @@ private: /// \fn size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A) /// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new - /// converted texture will be returned. Convertion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it + /// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it /// to converted textures list. /// Any of source ID's can be absent(empty string) or even one ID only specified. But at least one ID must be specified. /// \param [in] pID_R - ID of source "red" texture. @@ -378,7 +378,7 @@ private: void XML_CheckNode_MustHaveChildren(); /// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName) - /// Chek if current node name is equal to pNodeName. + /// Check if current node name is equal to pNodeName. /// \param [in] pNodeName - name for checking. /// return true if current node name is equal to pNodeName, else - false. bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; } diff --git a/code/AMFImporter_Node.hpp b/code/AMFImporter_Node.hpp index cb8b0b66d..522e6ccca 100644 --- a/code/AMFImporter_Node.hpp +++ b/code/AMFImporter_Node.hpp @@ -137,7 +137,7 @@ struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement { /****************** Variables ******************/ - std::string ObjectID;///< ID of object for instanciation. + std::string ObjectID;///< ID of object for instantiation. /// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to /// create an instance of the object in the current constellation. aiVector3D Delta; diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index aa4ea2fc5..ffef6f067 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -1561,7 +1561,7 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) for( size_t a = 0; a < pNode->mNumMeshes; ++a ) { const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; - // do not instanciate mesh if empty. I wonder how this could happen + // do not instantiate mesh if empty. I wonder how this could happen if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) continue; diff --git a/code/ColladaHelper.h b/code/ColladaHelper.h index 8ccd6cafe..e691a6062 100644 --- a/code/ColladaHelper.h +++ b/code/ColladaHelper.h @@ -302,7 +302,7 @@ struct Accessor size_t mOffset; // in number of values size_t mStride; // Stride in number of values std::vector mParams; // names of the data streams in the accessors. Empty string tells to ignore. - size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on. + size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on. // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. std::string mSource; // URL of the source array mutable const Data* mData; // Pointer to the source array, if resolved. NULL else diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index ccf79ed62..d2141c374 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -1619,7 +1619,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce mat.AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI); // transparency, a very hard one. seemingly not all files are following the - // specification here (1.0 transparency => completly opaque)... + // specification here (1.0 transparency => completely opaque)... // therefore, we let the opportunity for the user to manually invert // the transparency if necessary and we add preliminary support for RGB_ZERO mode if(effect.mTransparency >= 0.f && effect.mTransparency <= 1.f) { diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 5ff581b91..2fe0f1e0a 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -224,7 +224,7 @@ void ColladaParser::ReadStructure() } // ------------------------------------------------------------------------------------------------ -// Reads asset informations such as coordinate system informations and legal blah +// Reads asset information such as coordinate system information and legal blah void ColladaParser::ReadAssetInfo() { if( mReader->isEmptyElement()) diff --git a/code/ColladaParser.h b/code/ColladaParser.h index b34974470..941ab8414 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -77,7 +77,7 @@ namespace Assimp /** Reads the structure of the file */ void ReadStructure(); - /** Reads asset informations such as coordinate system informations and legal blah */ + /** Reads asset information such as coordinate system information and legal blah */ void ReadAssetInfo(); /** Reads the animation library */ diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index e2ba894af..621a2edc6 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -483,7 +483,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte const LWO::VColorChannel& vc = layer.mVColorChannels[i]; if (surf.mVCMap == vc.name) { - // The vertex color map is explicitely requested by the surface so we need to take special care of it + // The vertex color map is explicitly requested by the surface so we need to take special care of it for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) { out[a+1] = out[a]; } diff --git a/code/LWSLoader.cpp b/code/LWSLoader.cpp index 302228556..2017cdb9d 100644 --- a/code/LWSLoader.cpp +++ b/code/LWSLoader.cpp @@ -471,7 +471,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/') { diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 6dd68b8f5..a8bf9935a 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -155,7 +155,7 @@ std::string ObjExporter :: GetMaterialLibName() // ------------------------------------------------------------------------------------------------ std::string ObjExporter::GetMaterialLibFileName() { - // Remove existing .obj file extention so that the final material file name will be fileName.mtl and not fileName.obj.mtl + // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl size_t lastdot = filename.find_last_of('.'); if (lastdot != std::string::npos) return filename.substr(0, lastdot) + MaterialExt; diff --git a/code/OgreMaterial.cpp b/code/OgreMaterial.cpp index dfb77ffef..1abca2cf1 100644 --- a/code/OgreMaterial.cpp +++ b/code/OgreMaterial.cpp @@ -258,7 +258,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste ReadTechnique(Trim(techniqueName), ss, material); } - // Read informations from a custom material + // Read information from a custom material /** @todo This "set $x y" does not seem to be a official Ogre material system feature. Materials can inherit other materials and override texture units by using the (unique) parent texture unit name in your cloned material. diff --git a/code/TextureTransform.cpp b/code/TextureTransform.cpp index 76f0ce58c..30953113e 100644 --- a/code/TextureTransform.cpp +++ b/code/TextureTransform.cpp @@ -317,7 +317,7 @@ void TextureTransformStep::Execute( aiScene* pScene) info.lockedPos = AI_TT_UV_IDX_LOCK_TBD; } - // Get all coresponding meshes + // Get all corresponding meshes for (unsigned int n = 0; n < pScene->mNumMeshes;++n) { aiMesh* mesh = pScene->mMeshes[n]; if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0]) diff --git a/code/X3DExporter.hpp b/code/X3DExporter.hpp index bf1e72218..45f302d8d 100644 --- a/code/X3DExporter.hpp +++ b/code/X3DExporter.hpp @@ -27,7 +27,7 @@ namespace Assimp /// /// Pay attention that X3D is format for interactive graphic and simulations for web browsers. aiScene can not contain all features of the X3D format. /// Also, aiScene contain rasterized-like data. For example, X3D can describe circle all cylinder with one tag, but aiScene contain result of tesselation: -/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but thats not good idea at all. +/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but that's not a good idea at all. /// /// Supported nodes: /// Core component: @@ -96,7 +96,7 @@ private: aiMatrix4x4 Matrix_GlobalToCurrent(const aiNode& pNode) const; /// \fn void AttrHelper_CommaToPoint(std::string& pStringWithComma) - /// Convert commas in string to points. Thats need because "std::to_string" result depend on locale (regional settings). + /// Convert commas in string to points. That's needed because "std::to_string" result depends on locale (regional settings). /// \param [in, out] pStringWithComma - reference to string, which must be modified. void AttrHelper_CommaToPoint(std::string& pStringWithComma) { for(char& c: pStringWithComma) { if(c == ',') c = '.'; } } diff --git a/code/X3DImporter.hpp b/code/X3DImporter.hpp index 2d2d41fdb..468db5f3e 100644 --- a/code/X3DImporter.hpp +++ b/code/X3DImporter.hpp @@ -176,7 +176,7 @@ namespace Assimp { /// Ignored attributes: "creaseAngle", "convex", "solid". /// /// Texture coordinates generating: only for Sphere, Cone, Cylinder. In all other case used PLANE mapping. -/// It's better that Assimp main code has powerfull texture coordinates generator. Then is not needed to +/// It's better that Assimp main code has powerful texture coordinates generator. Then is not needed to /// duplicate this code in every importer. /// /// Lighting limitations. @@ -401,10 +401,10 @@ private: /************** Functions: XML set *************/ /***********************************************/ - /// Chek if current node is empty: . If not then exception will throwed. + /// Check if current node is empty: . If not then exception will throwed. void XML_CheckNode_MustBeEmpty(); - /// Chek if current node name is equal to pNodeName. + /// Check if current node name is equal to pNodeName. /// \param [in] pNodeName - name for checking. /// return true if current node name is equal to pNodeName, else - false. bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; } diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index cd6ca4630..22e003a3f 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -// Header files, standart library. +// Header files, standard library. #include #include diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 39886aaad..d88081884 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -// Header files, standart library. +// Header files, standard library. #include #include diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index cb629a985..8d51259a8 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1742,7 +1742,7 @@ UML_LOOK = NO # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more -# managable. Set this to 0 for no limit. Note that the threshold may be +# manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 diff --git a/doc/dox.h b/doc/dox.h index 46ca23251..2672adcb5 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -60,7 +60,7 @@ that it has not been implemented yet and some (most ...) formats lack proper spe Stanford Ply ( *.ply )
TrueSpace ( *.cob, *.scn )2

-See the @link importer_notes Importer Notes Page @endlink for informations, what a specific importer can do and what not. +See the @link importer_notes Importer Notes Page @endlink for information, what a specific importer can do and what not. Note that although this paper claims to be the official documentation, http://assimp.sourceforge.net/main_features_formats.html
is usually the most up-to-date list of file formats supported by the library.
@@ -81,7 +81,7 @@ formats handle the required endian conversion correctly, so large parts of the l The assimp linker library and viewer application are provided under the BSD 3-clause license. This basically means that you are free to use it in open- or closed-source projects, for commercial or non-commercial purposes as you like -as long as you retain the license informations and take own responsibility for what you do with it. For details see +as long as you retain the license information and take own responsibility for what you do with it. For details see the LICENSE file. You can find test models for almost all formats in the /test/models directory. Beware, they're *free*, @@ -1420,7 +1420,7 @@ IFC file properties (IfcPropertySet) are kept as per-node metadata, see aiNode:: This section contains implementations notes for the OgreXML importer. @subsection overview Overview -Ogre importer is currently optimized for the Blender Ogre exporter, because thats the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922 +Ogre importer is currently optimized for the Blender Ogre exporter, because that's the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922 @subsection what What will be loaded? @@ -1434,7 +1434,7 @@ Skeleton: Skeleton with Bone hierarchy (Position and Rotation, but no Scaling in animations with rotation, translation and scaling keys. @subsection export_Blender How to export Files from Blender -You can find informations about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp +You can find information about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp importer will load everything correctly: - Use either "Rendering Material" or "Custom Material" see @ref material - do not use "Flip Up Axies to Y" @@ -1543,7 +1543,7 @@ Done! Please, share your loader that everyone can profit from it! @section properties Properties -You can use properties to chance the behavior of you importer. In order to do so, you have to overide BaseImporter::SetupProperties, and specify +You can use properties to chance the behavior of you importer. In order to do so, you have to override BaseImporter::SetupProperties, and specify you custom properties in config.h. Just have a look to the other AI_CONFIG_IMPORT_* defines and you will understand, how it works. The properties can be set with Importer::SetProperty***() and can be accessed in your SetupProperties function with Importer::GetProperty***(). You can diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index 29b9d5870..bafd96189 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -903,7 +903,7 @@ enum aiComponent /** @brief Set the tessellation for IFC cylindrical shapes. * * This is used by the IFC importer to determine the tessellation parameter - * for cylindrical shapes, i.e. the number of segments used to aproximate a circle. + * for cylindrical shapes, i.e. the number of segments used to approximate a circle. * @note The default value is AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION and the * accepted values are in range [3, 180]. * Property type: Integer. diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index 84fcfb7a0..edae77d8d 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -206,7 +206,7 @@ class MeshKey(Structure): ("mTime", c_double), # Index into the aiMesh::mAnimMeshes array of the - # mesh coresponding to the + # mesh corresponding to the #aiMeshAnim hosting this # key frame. The referenced anim mesh is evaluated # according to the rules defined in the docs for diff --git a/port/PyAssimp/scripts/3d_viewer.py b/port/PyAssimp/scripts/3d_viewer.py index 9aae25efe..08a62660b 100755 --- a/port/PyAssimp/scripts/3d_viewer.py +++ b/port/PyAssimp/scripts/3d_viewer.py @@ -895,7 +895,7 @@ class PyAssimp3DViewer: aspect = camera.aspect u = 0.1 # unit size (in m) - l = 3 * u # lenght of the camera cone + l = 3 * u # length of the camera cone f = 3 * u # aperture of the camera cone glPushMatrix() diff --git a/port/PyAssimp/scripts/3d_viewer_py3.py b/port/PyAssimp/scripts/3d_viewer_py3.py index 4e4ecebe8..4c88edc7b 100755 --- a/port/PyAssimp/scripts/3d_viewer_py3.py +++ b/port/PyAssimp/scripts/3d_viewer_py3.py @@ -897,7 +897,7 @@ class PyAssimp3DViewer: aspect = camera.aspect u = 0.1 # unit size (in m) - l = 3 * u # lenght of the camera cone + l = 3 * u # length of the camera cone f = 3 * u # aperture of the camera cone glPushMatrix() diff --git a/port/PyAssimp/scripts/transformations.py b/port/PyAssimp/scripts/transformations.py index 6d6f19e5b..bf0cac9e3 100644 --- a/port/PyAssimp/scripts/transformations.py +++ b/port/PyAssimp/scripts/transformations.py @@ -583,7 +583,7 @@ def clip_matrix(left, right, bottom, top, near, far, perspective=False): orthographic canonical view volume (a box). Homogeneous coordinates transformed by the perspective clip matrix - need to be dehomogenized (devided by w coordinate). + need to be dehomogenized (divided by w coordinate). >>> frustrum = numpy.random.rand(6) >>> frustrum[1] += frustrum[0] diff --git a/port/dAssimp/assimp/mesh.d b/port/dAssimp/assimp/mesh.d index 9f20c9a66..da6193631 100644 --- a/port/dAssimp/assimp/mesh.d +++ b/port/dAssimp/assimp/mesh.d @@ -51,7 +51,7 @@ import assimp.types; extern ( C ) { /* * These limits are required to match the settings Assimp was compiled - * against. Therfore, do not redefine them unless you build the library + * against. Therefore, do not redefine them unless you build the library * from source using the same definitions. */ diff --git a/port/jassimp/jassimp-native/src/jassimp.cpp b/port/jassimp/jassimp-native/src/jassimp.cpp index c2a893896..070dbc95d 100644 --- a/port/jassimp/jassimp-native/src/jassimp.cpp +++ b/port/jassimp/jassimp-native/src/jassimp.cpp @@ -1951,7 +1951,7 @@ error: if (NULL == exception) { - /* thats really a problem because we cannot throw in this case */ + /* that's really a problem because we cannot throw in this case */ env->FatalError("could not throw java.io.IOException"); } gLastErrorString = imp.GetErrorString(); diff --git a/port/swig/assimp.i b/port/swig/assimp.i index d1a078d49..58e1546e7 100644 --- a/port/swig/assimp.i +++ b/port/swig/assimp.i @@ -114,7 +114,7 @@ %include "interface/IOSystem.i" -// We have to "instanciate" the templates used by the ASSSIMP_*_ARRAY macros +// We have to "instantiate" the templates used by the ASSSIMP_*_ARRAY macros // here at the end to avoid running into forward reference issues (SWIG would // spit out the helper functions before the header includes for the element // types otherwise). diff --git a/samples/SimpleAssimpViewX/MyDocument.mm b/samples/SimpleAssimpViewX/MyDocument.mm index be688a6be..cbe034842 100644 --- a/samples/SimpleAssimpViewX/MyDocument.mm +++ b/samples/SimpleAssimpViewX/MyDocument.mm @@ -641,7 +641,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS { for(MeshHelper* helper in modelMeshes) { - // Set up meterial state. + // Set up material state. glCallList(helper.displayList); } } diff --git a/samples/glut/GL/glut.h b/samples/glut/GL/glut.h index 0e6ddfbfe..86aa5c423 100644 --- a/samples/glut/GL/glut.h +++ b/samples/glut/GL/glut.h @@ -179,7 +179,7 @@ extern void exit(int); glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). **/ -#ifndef GLUT_API_VERSION /* allow this to be overriden */ +#ifndef GLUT_API_VERSION /* allow this to be overridden */ #define GLUT_API_VERSION 3 #endif @@ -219,7 +219,7 @@ extern void exit(int); GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa **/ -#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overridden. */ #define GLUT_XLIB_IMPLEMENTATION 15 #endif diff --git a/test/models-nonbsd/BLEND/fleurOptonl.source.txt b/test/models-nonbsd/BLEND/fleurOptonl.source.txt index 13f54a108..b9c58b5d9 100644 --- a/test/models-nonbsd/BLEND/fleurOptonl.source.txt +++ b/test/models-nonbsd/BLEND/fleurOptonl.source.txt @@ -32,7 +32,7 @@ L'utilizzo della Creative Commons non influisce su questo diritto. ************************************************ This model is released under Creative Commons Licence, Attribution 2.0 -for informations see: +for information see: http://creativecommons.org http://creativecommons.org/licenses/by/2.0/ feel free to use and improve it. diff --git a/test/models/AMF/README b/test/models/AMF/README index a64a8508e..7de7cadb2 100644 --- a/test/models/AMF/README +++ b/test/models/AMF/README @@ -1 +1 @@ -Simple models for testing importer. No desription because models are simple and created by hands. +Simple models for testing importer. No description because models are simple and created by hand. diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index 429f2ca99..5b755d456 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -561,7 +561,7 @@ void CGLView::Enable_Textures(const bool pEnable) } /********************************************************************/ -/*********************** Overrided functions ************************/ +/*********************** Override functions ************************/ /********************************************************************/ void CGLView::initializeGL() diff --git a/tools/assimp_qt_viewer/glview.hpp b/tools/assimp_qt_viewer/glview.hpp index 49207a7ed..ecd7c6b0f 100644 --- a/tools/assimp_qt_viewer/glview.hpp +++ b/tools/assimp_qt_viewer/glview.hpp @@ -249,13 +249,13 @@ private: void Draw_BBox(const SBBox& pBBox); /********************************************************************/ - /*********************** Overrided functions ************************/ + /*********************** Override functions ************************/ /********************************************************************/ protected: void drawCoordSystem(); /// \fn void initializeGL() override - /// Overrided function for initialise OpenGL. + /// Override function to initialise OpenGL. void initializeGL() override; /// \fn void resizeGL(int pWidth, int pHeight) override @@ -264,7 +264,7 @@ protected: void resizeGL(int pWidth, int pHeight) override; /// \fn void paintGL() override - /// Overrided function for rendering. + /// Override function for rendering. void paintGL() override; public: diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index 9b6e231bd..82ddc7092 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -107,7 +107,7 @@ void MainWindow::LogError(const QString& pMessage) } /********************************************************************/ -/*********************** Overrided functions ************************/ +/*********************** Override functions ************************/ /********************************************************************/ void MainWindow::mousePressEvent(QMouseEvent* pEvent) diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index 940840aee..b20acb884 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -65,23 +65,23 @@ private: void LogError(const QString& pMessage); /********************************************************************/ - /*********************** Overrided functions ************************/ + /*********************** Override functions ************************/ /********************************************************************/ protected: /// \fn void mousePressEvent(QMouseEvent* pEvent) override - /// Overrided function which handle mouse event "button pressed". + /// Override function which handles mouse event "button pressed". /// \param [in] pEvent - pointer to event data. void mousePressEvent(QMouseEvent* pEvent) override; /// \fn void mouseMoveEvent(QMouseEvent* pEvent) override - /// Overrided function which handle mouse event "move". + /// Override function which handles mouse event "move". /// \param [in] pEvent - pointer to event data. void mouseMoveEvent(QMouseEvent* pEvent) override; /// \fn void keyPressEvent(QKeyEvent* pEvent) override - /// Overrided function which handle key event "key pressed". + /// Override function which handles key event "key pressed". /// \param [in] pEvent - pointer to event data. void keyPressEvent(QKeyEvent* pEvent) override; diff --git a/tools/assimp_view/assimp_view.rc b/tools/assimp_view/assimp_view.rc index 13b05b18c..aebb1e2d9 100644 --- a/tools/assimp_view/assimp_view.rc +++ b/tools/assimp_view/assimp_view.rc @@ -189,7 +189,7 @@ BEGIN LTEXT "Angle limit (in degrees):",IDC_STATIC,13,10,76,8 LTEXT "The angle limit defines the maximum angle that may be between two adjacent face normals that they're smoothed together.",IDC_STATIC,13,31,253,19 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,113,278,1 - LTEXT "This setting is also used during import, but it can be overriden by single model importers to match the original look of a model as closely as possible. Examples include 3DS, ASE and LWO, all of them relying on smoothing groups and their own angle limits. ",IDC_STATIC,13,51,254,33 + LTEXT "This setting is also used during import, but it can be overridden by single model importers to match the original look of a model as closely as possible. Examples include 3DS, ASE and LWO, all of them relying on smoothing groups and their own angle limits. ",IDC_STATIC,13,51,254,33 LTEXT "NOTE: New settings don't take effect immediately, use 'Smooth Normals' or 'Reload' to update the model.",IDC_STATIC,14,118,254,22 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,90,277,1 END From 005b537324e588a8356804c9928f0ed3937f5643 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 10 Nov 2017 20:40:00 +0100 Subject: [PATCH 19/78] unittests: add VS-based source groups for the unittests. --- code/FIReader.hpp | 13 ++++- test/CMakeLists.txt | 139 ++++++++++++++++++++++++-------------------- 2 files changed, 86 insertions(+), 66 deletions(-) diff --git a/code/FIReader.hpp b/code/FIReader.hpp index ebc12ae31..4e9f712a9 100644 --- a/code/FIReader.hpp +++ b/code/FIReader.hpp @@ -46,11 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FI_READER_H #define INCLUDED_AI_FI_READER_H -#include -#include #include +#include +#include +#include #include #include +#include namespace Assimp { @@ -154,7 +156,7 @@ class IOStream; class FIReader: public irr::io::IIrrXMLReader { public: - + virtual ~FIReader(); virtual std::shared_ptr getAttributeEncodedValue(int idx) const = 0; virtual std::shared_ptr getAttributeEncodedValue(const char *name) const = 0; @@ -167,6 +169,11 @@ public: };// class IFIReader +inline +FIReader::~FIReader() { + // empty +} + }// namespace Assimp #endif // INCLUDED_AI_FI_READER_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cc5d3f83c..eed18a347 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -52,24 +52,55 @@ INCLUDE_DIRECTORIES( # Assimp library can be found, even if it is not installed system-wide yet. LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib ) -SOURCE_GROUP( unit FILES - unit/CCompilerTest.c -) - -SET( TEST_SRCS +SET( COMMON + unit/utIOSystem.cpp + unit/utIOStreamBuffer.cpp + unit/utIssues.cpp + unit/utAnim.cpp + unit/AssimpAPITest.cpp + unit/utBatchLoader.cpp + unit/utDefaultIOStream.cpp + unit/utFastAtof.cpp + unit/utMetadata.cpp + unit/SceneDiffer.h + unit/SceneDiffer.cpp unit/UTLogStream.h unit/AbstractImportExportBase.cpp unit/TestIOSystem.h unit/TestModelFactory.h + unit/utTypes.cpp + unit/utVersion.cpp + unit/utProfiler.cpp + unit/utSharedPPData.cpp + unit/utStringUtils.cpp +) + +SET( IMPORTERS + unit/utLWSImportExport.cpp + unit/utSMDImportExport.cpp + unit/utglTFImportExport.cpp + unit/utglTF2ImportExport.cpp + unit/utHMPImportExport.cpp + unit/utIFCImportExport.cpp + unit/utFBXImporterExporter.cpp + unit/utImporter.cpp unit/ut3DImportExport.cpp unit/ut3DSImportExport.cpp unit/utACImportExport.cpp unit/utAMFImportExport.cpp unit/utASEImportExport.cpp - unit/utAnim.cpp - unit/AssimpAPITest.cpp - unit/utB3DImportExport.cpp - unit/utBatchLoader.cpp + unit/utD3MFImportExport.cpp + unit/utQ3DImportExport.cpp + unit/utSTLImportExport.cpp + unit/utXImporterExporter.cpp + unit/utX3DImportExport.cpp + unit/utDXFImporterExporter.cpp + unit/utPMXImporter.cpp + unit/utPLYImportExport.cpp + unit/utObjImportExport.cpp + unit/utObjTools.cpp + unit/utOpenGEXImportExport.cpp + unit/utSIBImporter.cpp unit/utBlenderIntermediate.cpp unit/utBlendImportAreaLight.cpp unit/utBlenderImportExport.cpp @@ -79,78 +110,60 @@ SET( TEST_SRCS unit/utColladaExportLight.cpp unit/utColladaImportExport.cpp unit/utCSMImportExport.cpp - unit/utDefaultIOStream.cpp - unit/utDXFImporterExporter.cpp - unit/utFastAtof.cpp - unit/utFBXImporterExporter.cpp - unit/utFindDegenerates.cpp - unit/utFindInvalidData.cpp - unit/utFixInfacingNormals.cpp - unit/utGenNormals.cpp - unit/utglTFImportExport.cpp - unit/utglTF2ImportExport.cpp - unit/utHMPImportExport.cpp - unit/utIFCImportExport.cpp - unit/utImporter.cpp - unit/utImproveCacheLocality.cpp - unit/utIOSystem.cpp - unit/utIOStreamBuffer.cpp - unit/utIssues.cpp - unit/utJoinVertices.cpp - unit/utLimitBoneWeights.cpp - unit/utLWSImportExport.cpp + unit/utB3DImportExport.cpp +) + +SET( MATERIAL unit/utMaterialSystem.cpp +) + +SET( MATH unit/utMatrix3x3.cpp unit/utMatrix4x4.cpp - unit/utMetadata.cpp - unit/SceneDiffer.h - unit/SceneDiffer.cpp - unit/utSIBImporter.cpp - unit/utObjImportExport.cpp - unit/utObjTools.cpp - unit/utOpenGEXImportExport.cpp - unit/utPretransformVertices.cpp - unit/utPLYImportExport.cpp - unit/utPMXImporter.cpp - unit/utRemoveComments.cpp - unit/utRemoveComponent.cpp - unit/utScenePreprocessor.cpp - unit/utSceneCombiner.cpp - unit/utSharedPPData.cpp - unit/utStringUtils.cpp - unit/utSMDImportExport.cpp - unit/utSortByPType.cpp - unit/utSplitLargeMeshes.cpp - unit/utTargetAnimation.cpp - unit/utTextureTransform.cpp - unit/utTriangulate.cpp - unit/utTypes.cpp - unit/utVertexTriangleAdjacency.cpp - unit/utVersion.cpp unit/utVector3.cpp - unit/utXImporterExporter.cpp - unit/utX3DImportExport.cpp - unit/utD3MFImportExport.cpp - unit/utQ3DImportExport.cpp - unit/utSTLImportExport.cpp - unit/utProfiler.cpp ) + SET( POST_PROCESSES + unit/utImproveCacheLocality.cpp + unit/utFixInfacingNormals.cpp + unit/utGenNormals.cpp + unit/utTriangulate.cpp + unit/utTextureTransform.cpp unit/utRemoveRedundantMaterials.cpp unit/utRemoveVCProcess.cpp unit/utScaleProcess.cpp unit/utJoinVertices.cpp + unit/utRemoveComments.cpp + unit/utRemoveComponent.cpp + unit/utVertexTriangleAdjacency.cpp + unit/utJoinVertices.cpp + unit/utSplitLargeMeshes.cpp + unit/utFindDegenerates.cpp + unit/utFindInvalidData.cpp + unit/utLimitBoneWeights.cpp + unit/utPretransformVertices.cpp + unit/utScenePreprocessor.cpp + unit/utTargetAnimation.cpp + unit/utSortByPType.cpp + unit/utSceneCombiner.cpp ) -SOURCE_GROUP( tests FILES ${TEST_SRCS} ) -SOURCE_GROUP( tests/PostProcess FILES ${POST_PROCESSES}) +SOURCE_GROUP( UnitTests\Compiler FILES unit/CCompilerTest.c ) +SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} ) +SOURCE_GROUP( UnitTests\\Importers FILES ${IMPORTERS} ) +SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} ) +SOURCE_GROUP( UnitTests\\Math FILES ${MATH} ) +SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES}) add_executable( unit ../contrib/gtest/src/gtest-all.cc unit/CCompilerTest.c unit/Main.cpp ../code/Version.cpp - ${TEST_SRCS} + ${COMMON} + ${IMPORTERS} + ${MATERIAL} + ${MATH} ${POST_PROCESSES} ) From d0ac06cbfdefdc7466170ae47cbf3fe642a591b8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 11 Nov 2017 21:16:26 +0100 Subject: [PATCH 20/78] fix buggy escape sequence. --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index eed18a347..1c5d593de 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -148,7 +148,7 @@ SET( POST_PROCESSES unit/utSceneCombiner.cpp ) -SOURCE_GROUP( UnitTests\Compiler FILES unit/CCompilerTest.c ) +SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c ) SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} ) SOURCE_GROUP( UnitTests\\Importers FILES ${IMPORTERS} ) SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} ) From 24b728b3ea20d795ad3299cc7884392b514fa69b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 12 Nov 2017 22:09:18 +0100 Subject: [PATCH 21/78] FindDegeneratives: adapt unittests and add configs --- code/FindDegenerates.cpp | 31 +++++++++-------- code/FindDegenerates.h | 59 ++++++++++++++++++++++----------- code/X3DExporter.cpp | 8 +++-- include/assimp/config.h.in | 9 +++++ include/assimp/vector3.h | 9 +++-- test/unit/utFindDegenerates.cpp | 23 +++++++------ 6 files changed, 89 insertions(+), 50 deletions(-) diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index 83dce22ba..5a4a132ef 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -56,7 +56,8 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindDegeneratesProcess::FindDegeneratesProcess() -: configRemoveDegenerates (false) { +: mConfigRemoveDegenerates( false ) +, mConfigCheckAreaOfTriangle( false ){ // empty } @@ -76,7 +77,8 @@ bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const { // Setup import configuration void FindDegeneratesProcess::SetupProperties(const Importer* pImp) { // Get the current value of AI_CONFIG_PP_FD_REMOVE - configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); + mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); + mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) ); } // ------------------------------------------------------------------------------------------------ @@ -126,7 +128,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { mesh->mPrimitiveTypes = 0; std::vector remove_me; - if (configRemoveDegenerates) { + if (mConfigRemoveDegenerates) { remove_me.resize( mesh->mNumFaces, false ); } @@ -166,21 +168,24 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { first = false; } - if ( configRemoveDegenerates ) { + if ( mConfigRemoveDegenerates ) { remove_me[ a ] = true; goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby! } } } - if ( face.mNumIndices == 3 ) { - ai_real area = calculateAreaOfTriangle( face, mesh ); - if ( area < 1e-6 ) { - if ( configRemoveDegenerates ) { - remove_me[ a ] = true; - goto evil_jump_outside; - } - // todo: check for index which is corrupt. + if ( mConfigCheckAreaOfTriangle ) { + if ( face.mNumIndices == 3 ) { + ai_real area = calculateAreaOfTriangle( face, mesh ); + if ( area < 1e-6 ) { + if ( mConfigRemoveDegenerates ) { + remove_me[ a ] = true; + goto evil_jump_outside; + } + + // todo: check for index which is corrupt. + } } } } @@ -206,7 +211,7 @@ evil_jump_outside: } // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import - if (configRemoveDegenerates && deg) { + if (mConfigRemoveDegenerates && deg) { unsigned int n = 0; for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { diff --git a/code/FindDegenerates.h b/code/FindDegenerates.h index 9bd410dcd..cf03a24bc 100644 --- a/code/FindDegenerates.h +++ b/code/FindDegenerates.h @@ -54,15 +54,11 @@ namespace Assimp { // --------------------------------------------------------------------------- /** FindDegeneratesProcess: Searches a mesh for degenerated triangles. */ -class ASSIMP_API FindDegeneratesProcess : public BaseProcess -{ +class ASSIMP_API FindDegeneratesProcess : public BaseProcess { public: - FindDegeneratesProcess(); ~FindDegeneratesProcess(); -public: - // ------------------------------------------------------------------- // Check whether step is active bool IsActive( unsigned int pFlags) const; @@ -79,28 +75,53 @@ public: // Execute step on a given mesh void ExecuteOnMesh( aiMesh* mesh); + // ------------------------------------------------------------------- + /// @brief Enable the instant removal of degenerated primitives + /// @param enabled true for enabled. + void EnableInstantRemoval(bool enabled); // ------------------------------------------------------------------- - /** @brief Enable the instant removal of degenerated primitives - * @param d hm ... difficult to guess what this means, hu!? - */ - void EnableInstantRemoval(bool d) { - configRemoveDegenerates = d; - } + /// @brief Check whether instant removal is currently enabled + /// @return The instant removal state. + bool IsInstantRemoval() const; // ------------------------------------------------------------------- - /** @brief Check whether instant removal is currently enabled - * @return ... - */ - bool IsInstantRemoval() const { - return configRemoveDegenerates; - } + /// @brief Enable the area check for triangles. + /// @param enabled true for enabled. + void EnableAreaCheck( bool enabled ); + + // ------------------------------------------------------------------- + /// @brief Check whether the area check is enabled. + /// @return The area check state. + bool isAreaCheckEnabled() const; private: - //! Configuration option: remove degenerates faces immediately - bool configRemoveDegenerates; + bool mConfigRemoveDegenerates; + //! Configuration option: check for area + bool mConfigCheckAreaOfTriangle; }; + +inline +void FindDegeneratesProcess::EnableInstantRemoval(bool enabled) { + mConfigRemoveDegenerates = enabled; } +inline +bool FindDegeneratesProcess::IsInstantRemoval() const { + return mConfigRemoveDegenerates; +} + +inline +void FindDegeneratesProcess::EnableAreaCheck( bool enabled ) { + mConfigCheckAreaOfTriangle = enabled; +} + +inline +bool FindDegeneratesProcess::isAreaCheckEnabled() const { + return mConfigCheckAreaOfTriangle; +} + +} // Namespace Assimp + #endif // !! AI_FINDDEGENERATESPROCESS_H_INC diff --git a/code/X3DExporter.cpp b/code/X3DExporter.cpp index df688fd79..b560855fb 100644 --- a/code/X3DExporter.cpp +++ b/code/X3DExporter.cpp @@ -240,8 +240,12 @@ list attr_list; if((rotate_angle != 0) && (rotate_axis.Length() > 0)) attr_list.push_back({"rotation", Rotation2String(rotate_axis, rotate_angle)}); - if(!scale.Equal({1, 1, 1})) attr_list.push_back({"scale", Vector2String(scale)}); - if(translate.Length() > 0) attr_list.push_back({"translation", Vector2String(translate)}); + if(!scale.Equal({1.0,1.0,1.0})) { + attr_list.push_back({"scale", Vector2String(scale)}); + } + if(translate.Length() > 0) { + attr_list.push_back({"translation", Vector2String(translate)}); + } } // Begin node if need. diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index bafd96189..1dabae7cf 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -266,6 +266,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_CONFIG_PP_FD_REMOVE \ "PP_FD_REMOVE" +// --------------------------------------------------------------------------- +/** + * @brief Configures the #aiProcess_FindDegenerates to check the area of a + * trinagle to be greates than e-6. If this is not the case the triangle will + * be removed if #AI_CONFIG_PP_FD_REMOVE is set to true. + */ +#define AI_CONFIG_PP_FD_CHECKAREA \ + "PP_FD_CHECKAREA" + // --------------------------------------------------------------------------- /** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes * matching a name in a given list. diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 946e36cc5..641dab795 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -65,11 +65,10 @@ template class aiVector3t { public: - - aiVector3t () : x(), y(), z() {} - aiVector3t (TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {} - explicit aiVector3t (TReal _xyz) : x(_xyz), y(_xyz), z(_xyz) {} - aiVector3t (const aiVector3t& o) : x(o.x), y(o.y), z(o.z) {} + aiVector3t() : x(), y(), z() {} + aiVector3t(TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {} + explicit aiVector3t (TReal _xyz ) : x(_xyz), y(_xyz), z(_xyz) {} + aiVector3t( const aiVector3t& o ) : x(o.x), y(o.y), z(o.z) {} public: diff --git a/test/unit/utFindDegenerates.cpp b/test/unit/utFindDegenerates.cpp index 8040a83a1..dce42732c 100644 --- a/test/unit/utFindDegenerates.cpp +++ b/test/unit/utFindDegenerates.cpp @@ -58,8 +58,7 @@ protected: }; // ------------------------------------------------------------------------------------------------ -void FindDegeneratesProcessTest::SetUp() -{ +void FindDegeneratesProcessTest::SetUp() { mesh = new aiMesh(); process = new FindDegeneratesProcess(); @@ -107,16 +106,12 @@ void FindDegeneratesProcessTest::SetUp() mesh->mNumUVComponents[1] = numFaces; } -// ------------------------------------------------------------------------------------------------ -void FindDegeneratesProcessTest::TearDown() -{ +void FindDegeneratesProcessTest::TearDown() { delete mesh; delete process; } -// ------------------------------------------------------------------------------------------------ -TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) -{ +TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) { process->EnableInstantRemoval(false); process->ExecuteOnMesh(mesh); @@ -135,12 +130,18 @@ TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) mesh->mPrimitiveTypes); } -// ------------------------------------------------------------------------------------------------ -TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) -{ +TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) { + process->EnableAreaCheck(false); process->EnableInstantRemoval(true); process->ExecuteOnMesh(mesh); EXPECT_EQ(mesh->mNumUVComponents[1], mesh->mNumFaces); } +TEST_F(FindDegeneratesProcessTest, testDegeneratesRemovalWithAreaCheck) { + process->EnableAreaCheck(true); + process->EnableInstantRemoval(true); + process->ExecuteOnMesh(mesh); + + EXPECT_EQ(mesh->mNumUVComponents[1]-100, mesh->mNumFaces); +} From c15c96ac76f590dbea2e8adab2e1efffe99a19f1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 14 Nov 2017 20:11:40 +0100 Subject: [PATCH 22/78] CMake: use define for D_FILE_OFFSET_BITS only for not-android systems. --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc3731bbb..79db04762 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,8 +183,11 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") IF( UNIX ) # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux - IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux - ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) + IF( ${OPERATING_SYSTEM} MATCHES "Android") + ELSE() + IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux + ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) + ENDIF() ENDIF() # Use GNUInstallDirs for Unix predefined directories From a15bfceb7e8365823e1d85abef254fe09b197c2d Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 17 Oct 2017 18:37:40 +0300 Subject: [PATCH 23/78] Travis: Add static analysis to build --- .travis.sh | 15 +++++++++++++++ .travis.yml | 8 +++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.travis.sh b/.travis.sh index 75f00ec60..cc981a453 100755 --- a/.travis.sh +++ b/.travis.sh @@ -43,9 +43,24 @@ if [ $ANDROID ]; then ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni fi if [ "$TRAVIS_OS_NAME" = "linux" ]; then + if [ $ANALYZE = "ON" ] ; then + if [ "$CC" = "clang" ]; then + scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF + scan-build --status-bugs make -j2 + else + cppcheck --version + generate \ + && cppcheck --error-exitcode=1 -j2 -Iinclude -Icode code 2> cppcheck.txt + if [ -s cppcheck.txt ]; then + cat cppcheck.txt + exit 1 + fi + fi + else generate \ && make -j4 \ && sudo make install \ && sudo ldconfig \ && (cd test/unit; ../../bin/unit) + fi fi diff --git a/.travis.yml b/.travis.yml index 95e2fc164..e5477a543 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ language: cpp cache: ccache before_install: - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake cppcheck && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi - 'if [ "$TRAVIS_OS_NAME" = "osx" ]; then if brew ls --versions cmake > /dev/null; then echo cmake already installed.; @@ -39,6 +39,12 @@ matrix: - os: linux compiler: gcc env: SHARED_BUILD=ON + - os: linux + compiler: gcc + env: ANALYZE=ON + - os: linux + compiler: clang + env: ANALYZE=ON - os: linux compiler: clang env: ASAN=ON From 76919e87eacf2f201ac8055ab002a7be5dc4d28b Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 17 Oct 2017 19:01:36 +0300 Subject: [PATCH 24/78] fast_atof: Silence some uninitialized variable warnings --- code/fast_atof.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/fast_atof.h b/code/fast_atof.h index be1e59221..058a7ff87 100644 --- a/code/fast_atof.h +++ b/code/fast_atof.h @@ -360,7 +360,7 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma // The same but more human. inline ai_real fast_atof(const char* c) { - ai_real ret; + ai_real ret(0.0); fast_atoreal_move(c, ret); return ret; } @@ -368,7 +368,7 @@ inline ai_real fast_atof(const char* c) inline ai_real fast_atof( const char* c, const char** cout) { - ai_real ret; + ai_real ret(0.0); *cout = fast_atoreal_move(c, ret); return ret; @@ -376,7 +376,7 @@ inline ai_real fast_atof( const char* c, const char** cout) inline ai_real fast_atof( const char** inout) { - ai_real ret; + ai_real ret(0.0); *inout = fast_atoreal_move(*inout, ret); return ret; From 59d1a1d8198fc25bb1f2a479fd5598d3cc28d629 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 17 Oct 2017 19:02:39 +0300 Subject: [PATCH 25/78] Travis: Move slower builds earlier to improve parallelization --- .travis.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index e5477a543..9265dfb38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,15 +33,6 @@ env: matrix: include: - - os: linux - compiler: gcc - env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON - - os: linux - compiler: gcc - env: SHARED_BUILD=ON - - os: linux - compiler: gcc - env: ANALYZE=ON - os: linux compiler: clang env: ANALYZE=ON @@ -54,6 +45,15 @@ matrix: - os: linux compiler: clang env: SHARED_BUILD=ON + - os: linux + compiler: gcc + env: ANALYZE=ON + - os: linux + compiler: gcc + env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON + - os: linux + compiler: gcc + env: SHARED_BUILD=ON install: - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi From 35907e344622d78a2073fd0214765365ba42473d Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 17 Oct 2017 19:29:54 +0300 Subject: [PATCH 26/78] Travis: Disable unit tests in scan-build config --- .travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.sh b/.travis.sh index cc981a453..fb42bd40d 100755 --- a/.travis.sh +++ b/.travis.sh @@ -45,7 +45,7 @@ fi if [ "$TRAVIS_OS_NAME" = "linux" ]; then if [ $ANALYZE = "ON" ] ; then if [ "$CC" = "clang" ]; then - scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF + scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_TESTS=OFF scan-build --status-bugs make -j2 else cppcheck --version From 266e3b29a85fb56665df51775b6b08443bb6fdad Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 17 Oct 2017 19:48:08 +0300 Subject: [PATCH 27/78] RemoveRedundantMaterials: Set pointer to nullptr after deleting it --- code/RemoveRedundantMaterials.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/RemoveRedundantMaterials.cpp b/code/RemoveRedundantMaterials.cpp index 154bf63ca..8ea699f3d 100644 --- a/code/RemoveRedundantMaterials.cpp +++ b/code/RemoveRedundantMaterials.cpp @@ -145,6 +145,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) if (!abReferenced[i]) { ++unreferencedRemoved; delete pScene->mMaterials[i]; + pScene->mMaterials[i] = nullptr; continue; } @@ -158,6 +159,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) me = 0; aiMappingTable[i] = aiMappingTable[a]; delete pScene->mMaterials[i]; + pScene->mMaterials[i] = nullptr; break; } } From c774e864a0a7c79eb6183ddf1b95b1ed33b8bb79 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 24 Oct 2017 18:39:05 +0300 Subject: [PATCH 28/78] Remove some dead assignments --- code/Bitmap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Bitmap.cpp b/code/Bitmap.cpp index b1cf8a409..76994513e 100644 --- a/code/Bitmap.cpp +++ b/code/Bitmap.cpp @@ -102,7 +102,7 @@ namespace Assimp { offset += Copy(&data[offset], header.size); offset += Copy(&data[offset], header.reserved1); offset += Copy(&data[offset], header.reserved2); - offset += Copy(&data[offset], header.offset); + Copy(&data[offset], header.offset); file->Write(data, Header::header_size, 1); } @@ -122,7 +122,7 @@ namespace Assimp { offset += Copy(&data[offset], dib.x_resolution); offset += Copy(&data[offset], dib.y_resolution); offset += Copy(&data[offset], dib.nb_colors); - offset += Copy(&data[offset], dib.nb_important_colors); + Copy(&data[offset], dib.nb_important_colors); file->Write(data, DIB::dib_size, 1); } From 95f2319b41b65ff6f1947780cd328b0e05089a14 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 24 Oct 2017 19:51:12 +0300 Subject: [PATCH 29/78] ImproveCacheLocality: Add assertion to silence a static analyzer warning --- code/ImproveCacheLocality.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp index 7f0727e8b..2ac32aa84 100644 --- a/code/ImproveCacheLocality.cpp +++ b/code/ImproveCacheLocality.cpp @@ -223,6 +223,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh iMaxRefTris = std::max(iMaxRefTris,*piCur); } } + ai_assert(iMaxRefTris > 0); unsigned int* piCandidates = new unsigned int[iMaxRefTris*3]; unsigned int iCacheMisses = 0; From c51b92cfa32adfd670a284c9b903441f09984fd4 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 24 Oct 2017 20:05:15 +0300 Subject: [PATCH 30/78] RemoveRedundantMaterials: Add assertion to silence a static analyzer warning --- code/RemoveRedundantMaterials.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/RemoveRedundantMaterials.cpp b/code/RemoveRedundantMaterials.cpp index 8ea699f3d..c6319f892 100644 --- a/code/RemoveRedundantMaterials.cpp +++ b/code/RemoveRedundantMaterials.cpp @@ -171,6 +171,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // If the new material count differs from the original, // we need to rebuild the material list and remap mesh material indexes. if (iNewNum != pScene->mNumMaterials) { + ai_assert(iNewNum > 0); aiMaterial** ppcMaterials = new aiMaterial*[iNewNum]; ::memset(ppcMaterials,0,sizeof(void*)*iNewNum); for (unsigned int p = 0; p < pScene->mNumMaterials;++p) From a7fccf8f3352bc3e20689a46d4a8d0ce30384cb8 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 18:18:01 +0200 Subject: [PATCH 31/78] OptimizeGraph: Fix possible null pointer dereference --- code/OptimizeGraph.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/OptimizeGraph.cpp b/code/OptimizeGraph.cpp index 04971af5e..0e510e5ea 100644 --- a/code/OptimizeGraph.cpp +++ b/code/OptimizeGraph.cpp @@ -233,11 +233,13 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no 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; } + } nodes_out += static_cast(child_nodes.size()); } From bd0d47c5fc85dd19aec48a2d993c43fd0f5b608f Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 18:18:34 +0200 Subject: [PATCH 32/78] Whitespace --- code/OptimizeGraph.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/code/OptimizeGraph.cpp b/code/OptimizeGraph.cpp index 0e510e5ea..11a6fcf65 100644 --- a/code/OptimizeGraph.cpp +++ b/code/OptimizeGraph.cpp @@ -234,11 +234,11 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no 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; - } + 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()); From 2c7770eed549bf3137c89c32e0f6012fa95b0c1e Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 18:38:24 +0200 Subject: [PATCH 33/78] AMFImporter: Add a block --- code/AMFImporter_Postprocess.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMFImporter_Postprocess.cpp index 0e639026c..3737116f2 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMFImporter_Postprocess.cpp @@ -281,8 +281,9 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& { if(!pID.empty()) { - for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) + for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) { converted_texture.Data[idx_target] = src_texture[pSrcTexNum]->Data.at(idx_src); + } } };// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void From 856d402b59725b99b9af21e3831c8cdb33383989 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 18:44:16 +0200 Subject: [PATCH 34/78] AMFImporter: Add assertion to silence a static analyzer warning --- code/AMFImporter_Postprocess.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMFImporter_Postprocess.cpp index 3737116f2..991eb97e7 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMFImporter_Postprocess.cpp @@ -282,7 +282,9 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& if(!pID.empty()) { for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) { - converted_texture.Data[idx_target] = src_texture[pSrcTexNum]->Data.at(idx_src); + CAMFImporter_NodeElement_Texture* tex = src_texture[pSrcTexNum]; + ai_assert(tex); + converted_texture.Data[idx_target] = tex->Data.at(idx_src); } } };// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void From 4c9f1691091b88a61e60f72b4365cf72ff4ea333 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 18:45:02 +0200 Subject: [PATCH 35/78] ASE: Add assertion to silence a static analyzer warning --- code/ASELoader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index 16b3c4ad9..65935f48f 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -1021,6 +1021,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh // convert bones, if existing if (!mesh.mBones.empty()) { + ai_assert(avOutputBones); // check whether there is a vertex weight for this vertex index if (iIndex2 < mesh.mBoneVertices.size()) { From 437816fc33d4e1ef60d5470c467d2300d2d67827 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 19:05:01 +0200 Subject: [PATCH 36/78] AssbinExporter: Add assertion to silence a static analyzer warning --- code/AssbinExporter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/AssbinExporter.cpp b/code/AssbinExporter.cpp index 6bee6d6d1..bcac2e08f 100644 --- a/code/AssbinExporter.cpp +++ b/code/AssbinExporter.cpp @@ -171,6 +171,7 @@ inline size_t Write(IOStream * stream, const aiQuaternion& v) t += Write(stream,v.x); t += Write(stream,v.y); t += Write(stream,v.z); + ai_assert(t == 16); return 16; } From a276a027263f8cd6eefc97d524bdab952ec04d6d Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 19:11:08 +0200 Subject: [PATCH 37/78] IRRLoader: Fix confusing boolean casting --- code/IRRLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index 5113ab70d..c29d5b072 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -394,7 +394,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector Date: Tue, 7 Nov 2017 19:12:12 +0200 Subject: [PATCH 38/78] LWO: Reduce scope of a variable --- code/LWOAnimation.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/LWOAnimation.cpp b/code/LWOAnimation.cpp index 61c696453..4b5338f7a 100644 --- a/code/LWOAnimation.cpp +++ b/code/LWOAnimation.cpp @@ -446,8 +446,6 @@ void AnimResolver::GetKeys(std::vector& out, // Iterate through all three arrays at once - it's tricky, but // rather interesting to implement. - double lasttime = std::min(envl_x->keys[0].time,std::min(envl_y->keys[0].time,envl_z->keys[0].time)); - cur_x = envl_x->keys.begin(); cur_y = envl_y->keys.begin(); cur_z = envl_z->keys.begin(); @@ -503,7 +501,7 @@ void AnimResolver::GetKeys(std::vector& out, InterpolateTrack(out,fill,(end_y ? (*cur_x) : (*cur_y)).time); } } - lasttime = fill.mTime; + double lasttime = fill.mTime; out.push_back(fill); if (lasttime >= (*cur_x).time) { From 2b93a210c9a0142599a19d61d547f47e93c76278 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 19:12:44 +0200 Subject: [PATCH 39/78] NFF: Reduce scope of a variable --- code/NFFLoader.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index fa005ede4..b6dd2fb33 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -243,8 +243,6 @@ void NFFImporter::InternReadFile( const std::string& pFile, if( !file.get()) throw DeadlyImportError( "Failed to open NFF file " + pFile + "."); - unsigned int m = (unsigned int)file->FileSize(); - // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) std::vector mBuffer2; @@ -469,7 +467,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, for (unsigned int a = 0; a < numIdx;++a) { SkipSpaces(sz,&sz); - m = ::strtoul10(sz,&sz); + unsigned int m = ::strtoul10(sz,&sz); if (m >= (unsigned int)tempPositions.size()) { DefaultLogger::get()->error("NFF2: Vertex index overflow"); @@ -635,7 +633,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, for (std::vector::const_iterator it = tempIdx.begin(), end = tempIdx.end(); it != end;++it) { - m = *it; + unsigned int m = *it; // copy colors -vertex color specifications override polygon color specifications if (hasColor) @@ -735,7 +733,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, sz = &line[1];out = currentMesh; } SkipSpaces(sz,&sz); - m = strtoul10(sz); + unsigned int m = strtoul10(sz); // ---- flip the face order out->vertices.resize(out->vertices.size()+m); @@ -1128,7 +1126,8 @@ void NFFImporter::InternReadFile( const std::string& pFile, if (!pScene->mNumMeshes)throw DeadlyImportError("NFF: No meshes loaded"); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes]; - for (it = meshes.begin(), m = 0; it != end;++it) + unsigned int m = 0; + for (it = meshes.begin(); it != end;++it) { if ((*it).faces.empty())continue; From d24e0d44b28b05f18498928dc0abb65f24fbdb09 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 19:15:06 +0200 Subject: [PATCH 40/78] Raw: Fix misleading indentation warning --- code/RawLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/RawLoader.cpp b/code/RawLoader.cpp index e14b5140d..2b76455d7 100644 --- a/code/RawLoader.cpp +++ b/code/RawLoader.cpp @@ -260,7 +260,7 @@ void RAWImporter::InternReadFile( const std::string& pFile, node = *cc = new aiNode(); node->mParent = pScene->mRootNode; } - else node = *cc;++cc; + else node = *cc; node->mName.Set(outGroup.name); // add all meshes From 3f299b2a2bf56d75bb3336bda19dab445be66fcd Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 19:32:33 +0200 Subject: [PATCH 41/78] NFF: Split up some complicated assignments --- code/NFFLoader.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index b6dd2fb33..396fb28bf 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -1079,7 +1079,8 @@ void NFFImporter::InternReadFile( const std::string& pFile, // generate the camera if (hasCam) { - aiNode* nd = *ppcChildren = new aiNode(); + aiNode* nd = new aiNode(); + *ppcChildren = nd; nd->mName.Set(""); nd->mParent = root; @@ -1109,7 +1110,8 @@ void NFFImporter::InternReadFile( const std::string& pFile, { const Light& l = lights[i]; - aiNode* nd = *ppcChildren = new aiNode(); + aiNode* nd = new aiNode(); + *ppcChildren = nd; nd->mParent = root; nd->mName.length = ::ai_snprintf(nd->mName.data,1024,"",i); From f90019bc1ee8a6283dff09dc02977aff42fee1bb Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 7 Nov 2017 19:38:31 +0200 Subject: [PATCH 42/78] NFF: Add assertions to silence static analyzer warnings --- code/NFFLoader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index 396fb28bf..a51c500f1 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -1079,6 +1079,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, // generate the camera if (hasCam) { + ai_assert(ppcChildren); aiNode* nd = new aiNode(); *ppcChildren = nd; nd->mName.Set(""); @@ -1104,6 +1105,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, // generate light sources if (!lights.empty()) { + ai_assert(ppcChildren); pScene->mNumLights = (unsigned int)lights.size(); pScene->mLights = new aiLight*[pScene->mNumLights]; for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren) From f470b8466fb52b13ff3e11c917072fc44d271ac4 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 18:42:04 +0200 Subject: [PATCH 43/78] GLTF2: Fix signed/unsigned warning --- code/glTF2Asset.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 37a8fc662..f37d592c1 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -204,7 +204,7 @@ unsigned int LazyDict::Remove(const char* id) throw DeadlyExportError("GLTF: Object with id \"" + std::string(id) + "\" is not found"); } - const int index = it->second; + const unsigned int index = it->second; mAsset.mUsedIds[id] = false; mObjsById.erase(id); From 97843f19d2301b489e4bd65eb7fa6c2f7ca4c5dc Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 18:46:27 +0200 Subject: [PATCH 44/78] OpenGEX: Add assertion to silence a static analyzer warning --- code/OpenGEXImporter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 52e9ce501..025356c1d 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -652,6 +652,8 @@ static void setMatrix( aiNode *node, DataArrayList *transformData ) { i++; } + ai_assert(i == 16); + node->mTransformation.a1 = m[ 0 ]; node->mTransformation.a2 = m[ 4 ]; node->mTransformation.a3 = m[ 8 ]; From b49a4e133884ba2ed73cd16cd07250b4d875dd70 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 18:48:07 +0200 Subject: [PATCH 45/78] PLY: Remove dead assignment and reduce scope of a variable --- code/PlyParser.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index 65de665ab..6321821d2 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -671,7 +671,6 @@ bool PLY::ElementInstanceList::ParseInstanceList( PLYImporter* loader) { ai_assert(NULL != pcElement); - const char* pCur = (const char*)&buffer[0]; // parse all elements if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty()) @@ -683,11 +682,11 @@ bool PLY::ElementInstanceList::ParseInstanceList( PLY::DOM::SkipComments(buffer); PLY::DOM::SkipLine(buffer); streamBuffer.getNextLine(buffer); - pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0]; } } else { + const char* pCur = (const char*)&buffer[0]; // be sure to have enough storage for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { From ef0af40f9005dae1017a5a44131e15a7c3322c1f Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 18:53:08 +0200 Subject: [PATCH 46/78] IFC: Remove dead code --- code/IFCOpenings.cpp | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/code/IFCOpenings.cpp b/code/IFCOpenings.cpp index 45e0d1b90..4d57cd473 100644 --- a/code/IFCOpenings.cpp +++ b/code/IFCOpenings.cpp @@ -1499,7 +1499,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: IfcVector3 wall_extrusion; - bool do_connections = false, first = true; + bool first = true; try { @@ -1527,7 +1527,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: if (first) { first = false; if (dot > 0.f) { - do_connections = true; wall_extrusion = t.extrusionDir; if (is_extruded_side) { wall_extrusion = - wall_extrusion; @@ -1607,44 +1606,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: old_verts.swap(curmesh.verts); old_vertcnt.swap(curmesh.vertcnt); - - // add connection geometry to close the adjacent 'holes' for the openings - // this should only be done from one side of the wall or the polygons - // would be emitted twice. - if (false && do_connections) { - - std::vector tmpvec; - for(ClipperLib::Polygon& opening : holes_union) { - - ai_assert(ClipperLib::Orientation(opening)); - - tmpvec.clear(); - - for(ClipperLib::IntPoint& point : opening) { - - tmpvec.push_back( minv * IfcVector3( - vmin.x + from_int64(point.X) * vmax.x, - vmin.y + from_int64(point.Y) * vmax.y, - coord)); - } - - for(size_t i = 0, size = tmpvec.size(); i < size; ++i) { - const size_t next = (i+1)%size; - - curmesh.vertcnt.push_back(4); - - const IfcVector3& in_world = tmpvec[i]; - const IfcVector3& next_world = tmpvec[next]; - - // Assumptions: no 'partial' openings, wall thickness roughly the same across the wall - curmesh.verts.push_back(in_world); - curmesh.verts.push_back(in_world+wall_extrusion); - curmesh.verts.push_back(next_world+wall_extrusion); - curmesh.verts.push_back(next_world); - } - } - } - std::vector< std::vector > contours; for(ClipperLib::ExPolygon& clip : clipped) { From 583d3f88b8cdb1719c47cb2bf84ed1074a659497 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 19:05:53 +0200 Subject: [PATCH 47/78] FBX: Remove dead assignment --- code/FBXConverter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index a1e3ae07c..a5e44a607 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -566,7 +566,6 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa if ( !name_carrier ) { nodes_chain.push_back( new aiNode( original_name ) ); - name_carrier = nodes_chain.back(); } //setup metadata on newest node From e47bf932e8b8a7780e996d9800a5414c3d3cbd17 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 19:08:41 +0200 Subject: [PATCH 48/78] SIBImporter: Add assertions to silence static analyzer warnings --- code/SIBImporter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/SIBImporter.cpp b/code/SIBImporter.cpp index e85c9bdcb..2127e2e0c 100644 --- a/code/SIBImporter.cpp +++ b/code/SIBImporter.cpp @@ -902,6 +902,7 @@ void SIBImporter::InternReadFile(const std::string& pFile, // Add nodes for each object. for (size_t n=0;nmChildren); SIBObject& obj = sib.objs[n]; aiNode* node = new aiNode; root->mChildren[childIdx++] = node; @@ -926,6 +927,7 @@ void SIBImporter::InternReadFile(const std::string& pFile, // (no transformation as the light is already in world space) for (size_t n=0;nmChildren); aiLight* light = sib.lights[n]; if ( nullptr != light ) { aiNode* node = new aiNode; From 66c18cc4062ff68ef1fc7dbe1deb333c2be1f0e2 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 19:13:14 +0200 Subject: [PATCH 49/78] TerragenLoader: Remove unused variable --- code/TerragenLoader.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/TerragenLoader.cpp b/code/TerragenLoader.cpp index ecf33aae9..0126229ac 100644 --- a/code/TerragenLoader.cpp +++ b/code/TerragenLoader.cpp @@ -141,9 +141,6 @@ void TerragenImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" ); unsigned int x = 0,y = 0,mode = 0; - float rad = 6370.f; - (void)rad; - aiNode* root = pScene->mRootNode = new aiNode(); root->mName.Set(""); @@ -187,7 +184,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile, // mapping == 1: earth radius else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4)) { - rad = reader.GetF4(); + reader.GetF4(); } // mapping mode else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4)) From f475803f931f45add900090d4b8f9d81b1a9c85e Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 19:24:34 +0200 Subject: [PATCH 50/78] X3DImporter: Add assertions to silence static analyzer warnings --- code/X3DImporter_Postprocess.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/X3DImporter_Postprocess.cpp b/code/X3DImporter_Postprocess.cpp index 0e3f3a8ae..390ef8995 100644 --- a/code/X3DImporter_Postprocess.cpp +++ b/code/X3DImporter_Postprocess.cpp @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "X3DImporter.hpp" // Header files, Assimp. +#include #include "StandardShapes.h" #include "StringUtils.h" @@ -357,6 +358,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -389,6 +391,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -446,6 +449,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -475,6 +479,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -550,6 +555,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -584,6 +590,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) From 9dadec77364816acfdabaa382a24bbc4b04d5ffa Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Tue, 14 Nov 2017 19:46:35 +0200 Subject: [PATCH 51/78] assimp_cmd: Add assertion to silence a static analyzer warning --- tools/assimp_cmd/WriteDumb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 3fe8b2c77..69d4efcc5 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -198,6 +198,7 @@ inline uint32_t Write(const aiQuaternion& v) t += Write(v.x); t += Write(v.y); t += Write(v.z); + ai_assert(t == 16); return 16; } From eb5f47f5c5b96af42c1633b371909b5c37ab6e90 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 11:58:13 +0200 Subject: [PATCH 52/78] OpenDDLParser: Fix potential memory leak --- contrib/openddlparser/code/OpenDDLParser.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index dab976fad..c42fc9d57 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #include #ifdef _WIN32 @@ -275,12 +276,12 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) { } delete id; - Name *name(ddl_nullptr); - in = OpenDDLParser::parseName(in, end, &name); + Name *name_(ddl_nullptr); + in = OpenDDLParser::parseName(in, end, &name_); + std::unique_ptr name(name_); if( ddl_nullptr != name && ddl_nullptr != node ) { const std::string nodeName( name->m_id->m_buffer ); node->setName( nodeName ); - delete name; } From 635a515e69af97793eec9f1b45a2e397cc3e2cfd Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:06:21 +0200 Subject: [PATCH 53/78] OpenDDLParser: Fix another potential memory leak --- contrib/openddlparser/code/OpenDDLParser.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index c42fc9d57..6e0e2322e 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -285,13 +285,15 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) { } - Property *first(ddl_nullptr); + std::unique_ptr first; in = lookForNextToken(in, end); if (*in == Grammar::OpenPropertyToken[0]) { in++; - Property *prop(ddl_nullptr), *prev(ddl_nullptr); + std::unique_ptr prop, prev; while (*in != Grammar::ClosePropertyToken[0] && in != end) { - in = OpenDDLParser::parseProperty(in, end, &prop); + Property *prop_(ddl_nullptr); + in = OpenDDLParser::parseProperty(in, end, &prop_); + prop.reset(prop_); in = lookForNextToken(in, end); if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) { @@ -301,20 +303,20 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) { if (ddl_nullptr != prop && *in != Grammar::CommaSeparator[0]) { if (ddl_nullptr == first) { - first = prop; + first = std::move(prop); } if (ddl_nullptr != prev) { - prev->m_next = prop; + prev->m_next = prop.release(); } - prev = prop; + prev = std::move(prop); } } ++in; } // set the properties - if (ddl_nullptr != first && ddl_nullptr != node) { - node->setProperties(first); + if (first && ddl_nullptr != node) { + node->setProperties(first.release()); } } From 58d5d04e82327d3884a2cdc2a9f45bc18beb9a46 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:06:30 +0200 Subject: [PATCH 54/78] OpenDDLParser: Remove dead assignment --- contrib/openddlparser/code/OpenDDLParser.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index 6e0e2322e..caa281364 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -342,7 +342,6 @@ char *OpenDDLParser::parseStructure( char *in, char *end ) { } else { ++in; logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback ); - error = true; return ddl_nullptr; } in = lookForNextToken( in, end ); From be1d346c28c1ca0e7db109368285f90303cd00d9 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:12:06 +0200 Subject: [PATCH 55/78] Open3DGC: Add assertions to silence static analyzer warnings --- contrib/Open3DGC/o3dgcArithmeticCodec.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/Open3DGC/o3dgcArithmeticCodec.cpp b/contrib/Open3DGC/o3dgcArithmeticCodec.cpp index 1d160ba95..3597ec39a 100644 --- a/contrib/Open3DGC/o3dgcArithmeticCodec.cpp +++ b/contrib/Open3DGC/o3dgcArithmeticCodec.cpp @@ -820,6 +820,7 @@ namespace o3dgc for (unsigned n = 0; n < data_symbols; n++) total_count += (symbol_count[n] = (symbol_count[n] + 1) >> 1); } + assert(total_count > 0); // compute cumulative distribution, decoder table unsigned k, sum = 0, s = 0; unsigned scale = 0x80000000U / total_count; @@ -830,6 +831,7 @@ namespace o3dgc sum += symbol_count[k]; } else { + assert(decoder_table); for (k = 0; k < data_symbols; k++) { distribution[k] = (scale * sum) >> (31 - DM__LengthShift); sum += symbol_count[k]; From ef91211231c0ad730682fc3f553e4462356f0660 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:14:56 +0200 Subject: [PATCH 56/78] OpenDDLExport: Remove dead variable --- contrib/openddlparser/code/OpenDDLExport.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contrib/openddlparser/code/OpenDDLExport.cpp b/contrib/openddlparser/code/OpenDDLExport.cpp index a85bc5676..bb6d5532f 100644 --- a/contrib/openddlparser/code/OpenDDLExport.cpp +++ b/contrib/openddlparser/code/OpenDDLExport.cpp @@ -135,10 +135,9 @@ bool OpenDDLExport::writeToStream( const std::string &statement ) { } bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) { - bool success( true ); writeNodeHeader( node, statement ); if (node->hasProperties()) { - success |= writeProperties( node, statement ); + writeProperties( node, statement ); } writeLineEnd( statement ); From fc59f190ae5e6ced9242cb711633f4709a315c02 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:15:53 +0200 Subject: [PATCH 57/78] OpenDDLExport: Reduce scope of a variable --- contrib/openddlparser/code/OpenDDLExport.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contrib/openddlparser/code/OpenDDLExport.cpp b/contrib/openddlparser/code/OpenDDLExport.cpp index bb6d5532f..e45fb041a 100644 --- a/contrib/openddlparser/code/OpenDDLExport.cpp +++ b/contrib/openddlparser/code/OpenDDLExport.cpp @@ -359,11 +359,10 @@ bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) } DataArrayList *nextDataArrayList = al ; - Value *nextValue( nextDataArrayList->m_dataList ); while (ddl_nullptr != nextDataArrayList) { if (ddl_nullptr != nextDataArrayList) { statement += "{ "; - nextValue = nextDataArrayList->m_dataList; + Value *nextValue( nextDataArrayList->m_dataList ); size_t idx( 0 ); while (ddl_nullptr != nextValue) { if (idx > 0) { From 11fdaa31bcadb05515bc9205eb5352f6f35e5a89 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:18:39 +0200 Subject: [PATCH 58/78] clipper: Add assertion to silence a static analyzer warning --- contrib/clipper/clipper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index 7d2af7d3a..d10cb1e5c 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -2365,6 +2366,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) //ok, so far it looks like we're still in range of the horizontal edge if ( e->xcurr == horzEdge->xtop && !eMaxPair ) { + assert(horzEdge->nextInLML); if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) { //if output polygons share an edge, they'll need joining later ... From 0bc259fd9541713e46810d0e0b1fe5ec79b6d3e6 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:30:18 +0200 Subject: [PATCH 59/78] unzip: Fix possibly uninitialized variables --- contrib/unzip/unzip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index 085d79a02..51a3d8b4e 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -204,7 +204,7 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); @@ -232,7 +232,7 @@ local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); From 9b887153610e6aa8ed0f50eab50aba9673968395 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:32:24 +0200 Subject: [PATCH 60/78] unzip: Bail on bad compression method --- contrib/unzip/unzip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index 51a3d8b4e..0fac0b29d 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -1129,7 +1129,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; + return UNZ_BADZIPFILE; pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; pfile_in_zip_read_info->crc32=0; From c248ae37974ed9eb9da0c780ddb54b2022b64e14 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:33:34 +0200 Subject: [PATCH 61/78] unzip: Remove dead assignments --- contrib/unzip/unzip.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index 0fac0b29d..2ab621a6f 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -733,11 +733,9 @@ local int unzlocal_GetCurrentFileInfoInternal (file, if ((file_info.size_file_comment>0) && (commentBufferSize>0)) if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; } else { - lSeek+=file_info.size_file_comment; } if ((err==UNZ_OK) && (pfile_info!=NULL)) From 76de3e08283afb1c16f1b6cb1af87eeb10aa1edf Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:35:06 +0200 Subject: [PATCH 62/78] clipper: Add assertion to silence a static analyzer warning --- contrib/clipper/clipper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index d10cb1e5c..074f22b21 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -2431,6 +2431,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) if ( horzEdge->outIdx >= 0 ) IntersectEdges( horzEdge, eMaxPair, IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); + assert(eMaxPair); if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); DeleteFromAEL(eMaxPair); DeleteFromAEL(horzEdge); From 983e52e308476a115fd410997839b6b0b510611f Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Wed, 15 Nov 2017 12:45:27 +0200 Subject: [PATCH 63/78] unzip: Remove dead assignment --- contrib/unzip/unzip.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index 2ab621a6f..e8b62e763 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -725,9 +725,7 @@ local int unzlocal_GetCurrentFileInfoInternal (file, if (lSeek!=0) { - if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else + if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)!=0) err=UNZ_ERRNO; } if ((file_info.size_file_comment>0) && (commentBufferSize>0)) From 7db10022e915905accdbd2de3ba47ea41a556b5f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 15 Nov 2017 21:26:25 +0100 Subject: [PATCH 64/78] closes https://github.com/assimp/assimp/issues/1513: fix assimp for cross compile for android --- code/DefaultIOSystem.cpp | 1 - code/glTF2Asset.h | 4 +- code/glTF2Asset.inl | 4 +- code/glTF2Exporter.cpp | 2 +- code/glTFAsset.inl | 2 +- contrib/android-cmake/AndroidNdkGdb.cmake | 96 + contrib/android-cmake/AndroidNdkModules.cmake | 58 + contrib/android-cmake/README.md | 240 +++ contrib/android-cmake/android.toolchain.cmake | 1693 +++++++++++++++++ contrib/android-cmake/ndk_links.md | 211 ++ contrib/zlib/zconf.h.included | 2 + scripts/android_crosscompile/make_android.bat | 28 + 12 files changed, 2335 insertions(+), 6 deletions(-) create mode 100644 contrib/android-cmake/AndroidNdkGdb.cmake create mode 100644 contrib/android-cmake/AndroidNdkModules.cmake create mode 100644 contrib/android-cmake/README.md create mode 100644 contrib/android-cmake/android.toolchain.cmake create mode 100644 contrib/android-cmake/ndk_links.md create mode 100644 scripts/android_crosscompile/make_android.bat diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index ca4ae4564..8687b0059 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - #ifdef __unix__ #include #include diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 7ebc5ba95..877b59ba3 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -88,6 +88,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # endif #endif +#include "StringUtils.h" + namespace glTF2 { #ifdef ASSIMP_API @@ -239,7 +241,7 @@ namespace glTF2 case ComponentType_UNSIGNED_BYTE: return 1; default: - throw DeadlyImportError("GLTF: Unsupported Component Type " + std::to_string(t)); + throw DeadlyImportError("GLTF: Unsupported Component Type " + to_string(t)); } } diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 37a8fc662..d0ad129e3 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -258,11 +258,11 @@ Ref LazyDict::Retrieve(unsigned int i) Value &obj = (*mDict)[i]; if (!obj.IsObject()) { - throw DeadlyImportError("GLTF: Object at index \"" + std::to_string(i) + "\" is not a JSON object"); + throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); } T* inst = new T(); - inst->id = std::string(mDictId) + "_" + std::to_string(i); + inst->id = std::string(mDictId) + "_" + to_string(i); inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index a7a640b5d..ed6814b7f 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -402,7 +402,7 @@ void glTF2Exporter::ExportMaterials() for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { const aiMaterial* mat = mScene->mMaterials[i]; - std::string id = "material_" + std::to_string(i); + std::string id = "material_" + to_string(i); Ref m = mAsset->materials.Create(id); diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index 6d328614e..a5d74f5a0 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -1282,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream) } AI_SWAP4(header.version); - asset.version = std::to_string(header.version); + asset.version = to_string(header.version); if (header.version != 1) { throw DeadlyImportError("GLTF: Unsupported binary glTF version"); } diff --git a/contrib/android-cmake/AndroidNdkGdb.cmake b/contrib/android-cmake/AndroidNdkGdb.cmake new file mode 100644 index 000000000..0677dcda9 --- /dev/null +++ b/contrib/android-cmake/AndroidNdkGdb.cmake @@ -0,0 +1,96 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. + +# ------------------------------------------------------------------------------ +# Usage: +# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH} +# 2. inside your project add +# +# include(AndroidNdkGdb) +# android_ndk_gdb_enable() +# # for each target +# add_library(MyLibrary ...) +# android_ndk_gdb_debuggable(MyLibrary) + + +# add gdbserver and general gdb configuration to project +# also create a mininal NDK skeleton so ndk-gdb finds the paths +# +# the optional parameter defines the path to the android project. +# uses PROJECT_SOURCE_DIR by default. +macro(android_ndk_gdb_enable) + if(ANDROID) + # create custom target that depends on the real target so it gets executed afterwards + add_custom_target(NDK_GDB ALL) + + if(${ARGC}) + set(ANDROID_PROJECT_DIR ${ARGV0}) + else() + set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR}) + endif() + + set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/) + file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH}) + + # 1. generate essential Android Makefiles + file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni) + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + + # 2. generate gdb.setup + get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES) + string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}") + file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n") + file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n") + + # 3. copy gdbserver executable + file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH}) + endif() +endmacro() + +# register a target for remote debugging +# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original +macro(android_ndk_gdb_debuggable TARGET_NAME) + if(ANDROID) + get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION) + + # create custom target that depends on the real target so it gets executed afterwards + add_dependencies(NDK_GDB ${TARGET_NAME}) + + # 4. copy lib to obj + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH}) + + # 5. strip symbols + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION}) + endif() +endmacro() diff --git a/contrib/android-cmake/AndroidNdkModules.cmake b/contrib/android-cmake/AndroidNdkModules.cmake new file mode 100644 index 000000000..64f37fdee --- /dev/null +++ b/contrib/android-cmake/AndroidNdkModules.cmake @@ -0,0 +1,58 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. + +macro(android_ndk_import_module_cpufeatures) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/cpufeatures) + add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) + target_link_libraries(cpufeatures dl) + endif() +endmacro() + +macro(android_ndk_import_module_native_app_glue) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/native_app_glue) + add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + target_link_libraries(native_app_glue log) + endif() +endmacro() + +macro(android_ndk_import_module_ndk_helper) + if(ANDROID) + android_ndk_import_module_cpufeatures() + android_ndk_import_module_native_app_glue() + + include_directories(${ANDROID_NDK}/sources/android/ndk_helper) + file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c) + add_library(ndk_helper ${_NDK_HELPER_SRCS}) + target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue) + + unset(_NDK_HELPER_SRCS) + endif() +endmacro() \ No newline at end of file diff --git a/contrib/android-cmake/README.md b/contrib/android-cmake/README.md new file mode 100644 index 000000000..ee6302128 --- /dev/null +++ b/contrib/android-cmake/README.md @@ -0,0 +1,240 @@ +# android-cmake + +CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html + +Main goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android. + +## TL;DR + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \ + -DANDROID_NDK= \ + -DCMAKE_BUILD_TYPE=Release \ + -DANDROID_ABI="armeabi-v7a with NEON" \ + + cmake --build . + +One-liner: + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK= -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" && cmake --build . + +_android-cmake_ will search for your NDK install in the following order: + +1. Value of `ANDROID_NDK` CMake variable; +1. Value of `ANDROID_NDK` environment variable; +1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable; +1. Search platform specific locations (home folder, Windows "Program Files", etc). + +So if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically. + +## Getting started + +To build a cmake-based C/C++ project for Android you need: + +* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html +* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download + +The _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with. + +## Difference from traditional CMake + +Folowing the _ndk-build_ the _android-cmake_ supports **only two build targets**: + +* `-DCMAKE_BUILD_TYPE=Release` +* `-DCMAKE_BUILD_TYPE=Debug` + +So don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default. + +## Difference from _ndk-build_ + +* Latest GCC available in NDK is used as the default compiler; +* `Release` builds with `-O3` instead of `-Os`; +* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target); +* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64; +* GCC's stack protector is not used neither in `Debug` nor `Release` configurations; +* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters); +* No file level Neon via `.neon` suffix; + +The following features of _ndk-build_ are not supported by the _android-cmake_ yet: + +* `armeabi-v7a-hard` ABI +* `libc++_static`/`libc++_shared` STL runtime + +## Basic options + +Similarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D=` or as environment variables: + +* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations; +* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are: + * `armeabi` - ARMv5TE based CPU with software floating point operations; + * **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16); + * `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit; + * `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit; + * `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP; + * `x86` - IA-32 instruction set + * `mips` - MIPS32 instruction set + * `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer + * `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer + * `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer +* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI: + * `android-8` for ARM; + * `android-9` for x86 and MIPS; + * `android-21` for 64-bit ABIs. + + Building for `android-L` is possible only when it is explicitly selected. +* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`. + + Example values are: + * `aarch64-linux-android-4.9` + * `aarch64-linux-android-clang3.5` + * `arm-linux-androideabi-4.8` + * `arm-linux-androideabi-4.9` + * `arm-linux-androideabi-clang3.5` + * `mips64el-linux-android-4.9` + * `mipsel-linux-android-4.8` + * `x86-4.9` + * `x86_64-4.9` + * etc. +* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`. + * `none` - do not configure the runtime. + * `system` - use the default minimal system C++ runtime library. + * Implies `-fno-rtti -fno-exceptions`. + * `system_re` - use the default minimal system C++ runtime library. + * Implies `-frtti -fexceptions`. + * `gabi++_static` - use the GAbi++ runtime as a static library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `gabi++_shared` - use the GAbi++ runtime as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `stlport_static` - use the STLport runtime as a static library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * `stlport_shared` - use the STLport runtime as a shared library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * **`gnustl_static`** - use the GNU STL as a static library. + * Implies `-frtti -fexceptions`. + * `gnustl_shared` - use the GNU STL as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7b and newer. + * Silently degrades to `gnustl_static` if not available. +* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable. + +## Advanced _android-cmake_ options + +Normally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues: + +* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`; +* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors; +* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries; + * actually it is turned `ON` by default for NDK older than `r7` +* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime; +* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are: + * `RELEASE` - public releases from Google; + * `LINARO` - NDK from Linaro project; + * `ANDROID` - NDK from AOSP. +* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`); +* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86); +* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`); +* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`); +* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product//obj/lib/libm.so`) to workaround unresolved `sincos`. + +## Fine-tuning `CMakeLists.txt` for _android-cmake_ + +### Recognizing Android build + +_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff: + + if (ANDROID) + message(STATUS "Hello from Android build!") + endif() + +The recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value: + +* `armv5te` - for `armeabi` ABI +* `armv6` - for `armeabi-v6 with VFP` ABI +* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs +* `aarch64` - for `arm64-v8a` ABI +* `i686` - for `x86` ABI +* `x86_64` - for `x86_64` ABI +* `mips` - for `mips` ABI +* `mips64` - for `mips64` ABI + +Other variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are: + +* `NEON` - set if target ABI supports Neon; +* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level) +* `ANDROID_NDK_RELEASE` - version of the Android NDK +* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform +* `ANDROID_RTTI` - set if rtti is enabled by the runtime +* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime + +### Finding packages + +When crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So + + find_package(ZLIB) + +will surely find libz.so within the Android NDK. + +However sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`: + + find_host_package(Doxygen) + find_host_program(PDFLATEX pdflatex) + +However this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command): + + # Search packages for host system instead of packages for target system + # in case of cross compilation these macro should be defined by toolchain file + if(NOT COMMAND find_host_package) + macro(find_host_package) + find_package(${ARGN}) + endmacro() + endif() + if(NOT COMMAND find_host_program) + macro(find_host_program) + find_program(${ARGN}) + endmacro() + endif() + +### Compiler flags recycling + +Make sure to do the following in your scripts: + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}") + +The flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags. + +## Troubleshooting + +### Building on Windows + +First of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead. + +To build with Ninja you need: + +* Ensure you are using CMake newer than 2.8.9; +* Download the latest Ninja from https://github.com/martine/ninja/releases; +* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable); +* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`). +* Enjoy the fast native multithreaded build :) + +But if you still want to stick to old make then: + +* Get a Windows port of GNU Make: + * Android NDK r7 (and newer) already has `make.exe` on board; + * `mingw-make` should work as fine; + * Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm. +* Add path to your `make.exe` to system PATH or always use full path; +* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="make.exe"` + * It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make. +* Run `make.exe` or `cmake --build .` for single-threaded build. + +### Projects with assembler files + +The _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5 + +## Copying + +_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) \ No newline at end of file diff --git a/contrib/android-cmake/android.toolchain.cmake b/contrib/android-cmake/android.toolchain.cmake new file mode 100644 index 000000000..ffa26126a --- /dev/null +++ b/contrib/android-cmake/android.toolchain.cmake @@ -0,0 +1,1693 @@ +# Copyright (c) 2010-2011, Ethan Rublee +# Copyright (c) 2011-2014, Andrey Kamaev +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. + +# ------------------------------------------------------------------------------ +# Android CMake toolchain file, for use with the Android NDK r5-r10d +# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended). +# See home page: https://github.com/taka-no-me/android-cmake +# +# Usage Linux: +# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Windows: +# You need native port of make to build your project. +# Android NDK r7 (and newer) already has make.exe on board. +# For older NDK you have to install it separately. +# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm +# +# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk +# $ mkdir build && cd build +# $ cmake.exe -G"MinGW Makefiles" +# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake +# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. +# $ cmake.exe --build . +# +# +# Options (can be set as cmake parameters: -D=): +# ANDROID_NDK=/opt/android-ndk - path to the NDK root. +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary +# Interface (ABI). This option nearly matches to the APP_ABI variable +# used by ndk-build tool from Android NDK. +# +# Possible targets are: +# "armeabi" - ARMv5TE based CPU with software floating point operations +# "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions +# this ABI target is used by default +# "armeabi-v7a with NEON" - same as armeabi-v7a, but +# sets NEON as floating-point unit +# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but +# sets VFPV3 as floating-point unit (has 32 registers instead of 16) +# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP +# "x86" - IA-32 instruction set +# "mips" - MIPS32 instruction set +# +# 64-bit ABIs for NDK r10 and newer: +# "arm64-v8a" - ARMv8 AArch64 instruction set +# "x86_64" - Intel64 instruction set (r1) +# "mips64" - MIPS64 instruction set (r6) +# +# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. +# Option is read-only when standalone toolchain is used. +# Note: building for "android-L" requires explicit configuration. +# +# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler +# toolchain to be used. The list of possible values depends on the NDK +# version. For NDK r10c the possible values are: +# +# * aarch64-linux-android-4.9 +# * aarch64-linux-android-clang3.4 +# * aarch64-linux-android-clang3.5 +# * arm-linux-androideabi-4.6 +# * arm-linux-androideabi-4.8 +# * arm-linux-androideabi-4.9 (default) +# * arm-linux-androideabi-clang3.4 +# * arm-linux-androideabi-clang3.5 +# * mips64el-linux-android-4.9 +# * mips64el-linux-android-clang3.4 +# * mips64el-linux-android-clang3.5 +# * mipsel-linux-android-4.6 +# * mipsel-linux-android-4.8 +# * mipsel-linux-android-4.9 +# * mipsel-linux-android-clang3.4 +# * mipsel-linux-android-clang3.5 +# * x86-4.6 +# * x86-4.8 +# * x86-4.9 +# * x86-clang3.4 +# * x86-clang3.5 +# * x86_64-4.9 +# * x86_64-clang3.4 +# * x86_64-clang3.5 +# +# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions +# instead of Thumb. Is not available for "armeabi-v6 with VFP" +# (is forced to be ON) ABI. +# +# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker +# errors even if they are not used. +# +# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared +# libraries. Automatically turned for NDK r5x and r6x due to GLESv2 +# problems. +# +# ANDROID_STL=gnustl_static - specify the runtime to use. +# +# Possible values are: +# none -> Do not configure the runtime. +# system -> Use the default minimal system C++ runtime library. +# Implies -fno-rtti -fno-exceptions. +# Is not available for standalone toolchain. +# system_re -> Use the default minimal system C++ runtime library. +# Implies -frtti -fexceptions. +# Is not available for standalone toolchain. +# gabi++_static -> Use the GAbi++ runtime as a static library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# gabi++_shared -> Use the GAbi++ runtime as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_static -> Use the STLport runtime as a static library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_shared -> Use the STLport runtime as a shared library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# gnustl_static -> Use the GNU STL as a static library. +# Implies -frtti -fexceptions. +# gnustl_shared -> Use the GNU STL as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7b and newer. +# Silently degrades to gnustl_static if not available. +# +# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on +# chosen runtime. If disabled, then the user is responsible for settings +# these options. +# +# What?: +# android-cmake toolchain searches for NDK/toolchain in the following order: +# ANDROID_NDK - cmake parameter +# ANDROID_NDK - environment variable +# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter +# ANDROID_STANDALONE_TOOLCHAIN - environment variable +# ANDROID_NDK - default locations +# ANDROID_STANDALONE_TOOLCHAIN - default locations +# +# Make sure to do the following in your scripts: +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) +# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) +# The flags will be prepopulated with critical flags, so don't loose them. +# Also be aware that toolchain also sets configuration-specific compiler +# flags and linker flags. +# +# ANDROID and BUILD_ANDROID will be set to true, you may test any of these +# variables to make necessary Android-specific configuration changes. +# +# Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64 +# will be set true, mutually exclusive. NEON option will be set true +# if VFP is set to NEON. +# +# ------------------------------------------------------------------------------ + +cmake_minimum_required( VERSION 2.6.3 ) + +if( DEFINED CMAKE_CROSSCOMPILING ) + # subsequent toolchain loading is not really needed + return() +endif() + +if( CMAKE_TOOLCHAIN_FILE ) + # touch toolchain variable to suppress "unused variable" warning +endif() + +# inherit settings in recursive loads +get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) +if( _CMAKE_IN_TRY_COMPILE ) + include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) +endif() + +# this one is important +if( CMAKE_VERSION VERSION_GREATER "3.0.99" ) + set( CMAKE_SYSTEM_NAME Android ) +else() + set( CMAKE_SYSTEM_NAME Linux ) +endif() + +# this one not so much +set( CMAKE_SYSTEM_VERSION 1 ) + +# rpath makes low sense for Android +set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" ) +set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) + +# NDK search paths +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) +if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS ) + if( CMAKE_HOST_WIN32 ) + file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" ) + else() + file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" ) + endif() +endif() +if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) +endif() + +# known ABIs +set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) +set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" ) +set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) +set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" ) +set( ANDROID_SUPPORTED_ABIS_mips "mips" ) +set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" ) + +# API level defaults +set( ANDROID_DEFAULT_NDK_API_LEVEL 8 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 ) + + +macro( __LIST_FILTER listvar regex ) + if( ${listvar} ) + foreach( __val ${${listvar}} ) + if( __val MATCHES "${regex}" ) + list( REMOVE_ITEM ${listvar} "${__val}" ) + endif() + endforeach() + endif() +endmacro() + +macro( __INIT_VARIABLE var_name ) + set( __test_path 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "PATH" ) + set( __test_path 1 ) + break() + endif() + endforeach() + + if( __test_path AND NOT EXISTS "${${var_name}}" ) + unset( ${var_name} CACHE ) + endif() + + if( " ${${var_name}}" STREQUAL " " ) + set( __values 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "VALUES" ) + set( __values 1 ) + elseif( NOT __var STREQUAL "PATH" ) + if( __var MATCHES "^ENV_.*$" ) + string( REPLACE "ENV_" "" __var "${__var}" ) + set( __value "$ENV{${__var}}" ) + elseif( DEFINED ${__var} ) + set( __value "${${__var}}" ) + elseif( __values ) + set( __value "${__var}" ) + else() + set( __value "" ) + endif() + + if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") ) + set( ${var_name} "${__value}" ) + break() + endif() + endif() + endforeach() + unset( __value ) + unset( __values ) + endif() + + if( __test_path ) + file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) + endif() + unset( __test_path ) +endmacro() + +macro( __DETECT_NATIVE_API_LEVEL _var _path ) + set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" ) + file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) + if( NOT __apiFileContent ) + message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) + endif() + string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) + unset( __apiFileContent ) + unset( __ndkApiLevelRegex ) +endmacro() + +macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) + if( EXISTS "${_root}" ) + file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) + __LIST_FILTER( __gccExePath "^[.].*" ) + list( LENGTH __gccExePath __gccExePathsCount ) + if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Could not determine machine name for compiler from ${_root}" ) + set( ${_var} "" ) + else() + get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) + string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) + endif() + unset( __gccExePath ) + unset( __gccExePathsCount ) + unset( __gccExeName ) + else() + set( ${_var} "" ) + endif() +endmacro() + + +# fight against cygwin +set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") +mark_as_advanced( ANDROID_FORBID_SYGWIN ) +if( ANDROID_FORBID_SYGWIN ) + if( CYGWIN ) + message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) + endif() + + if( CMAKE_HOST_WIN32 ) + # remove cygwin from PATH + set( __new_path "$ENV{PATH}") + __LIST_FILTER( __new_path "cygwin" ) + set(ENV{PATH} "${__new_path}") + unset(__new_path) + endif() +endif() + + +# detect current host platform +if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) ) + set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) + mark_as_advanced( ANDROID_NDK_HOST_X64 ) +endif() + +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) +elseif( CMAKE_HOST_WIN32 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) +elseif( CMAKE_HOST_UNIX ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +if( NOT ANDROID_NDK_HOST_X64 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) +endif() + +# see if we have path to Android NDK +if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN ) + __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) +endif() +if( NOT ANDROID_NDK ) + # see if we have path to Android standalone toolchain + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN ) + + if( NOT ANDROID_STANDALONE_TOOLCHAIN ) + #try to find Android NDK in one of the the default locations + set( __ndkSearchPaths ) + foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) + foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) + list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" ) + endforeach() + endforeach() + __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) + unset( __ndkSearchPaths ) + + if( ANDROID_NDK ) + message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) + message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) + else() + #try to find Android standalone toolchain in one of the the default locations + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + + if( ANDROID_STANDALONE_TOOLCHAIN ) + message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) + message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) + endif( ANDROID_STANDALONE_TOOLCHAIN ) + endif( ANDROID_NDK ) + endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) +endif( NOT ANDROID_NDK ) + +# remember found paths +if( ANDROID_NDK ) + get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) + set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) + set( BUILD_WITH_ANDROID_NDK True ) + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) + file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" ) + string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) + else() + set( ANDROID_NDK_RELEASE "r1x" ) + set( ANDROID_NDK_RELEASE_FULL "unreleased" ) + endif() + string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" ) + string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum ) + math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" ) +elseif( ANDROID_STANDALONE_TOOLCHAIN ) + get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) + if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) + message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) + endif() + unset( __androidStandaloneToolchainPreviousPath ) + unset( __length ) + endif() + set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) + set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) +else() + list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) + message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. + You should either set an environment variable: + export ANDROID_NDK=~/my-android-ndk + or + export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain + or put the toolchain or NDK in the default path: + sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk + sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) +endif() + +# android NDK layout +if( BUILD_WITH_ANDROID_NDK ) + if( NOT DEFINED ANDROID_NDK_LAYOUT ) + # try to automatically detect the layout + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") + set( ANDROID_NDK_LAYOUT "RELEASE" ) + elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) + set( ANDROID_NDK_LAYOUT "LINARO" ) + elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) + set( ANDROID_NDK_LAYOUT "ANDROID" ) + endif() + endif() + set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) + mark_as_advanced( ANDROID_NDK_LAYOUT ) + if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) + endif() + get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) + + # try to detect change of NDK + if( CMAKE_AR ) + string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) + if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) + message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. + " ) + endif() + unset( __androidNdkPreviousPath ) + unset( __length ) + endif() +endif() + + +# get all the details about standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) + set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + set( __availableToolchains "standalone" ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) + if( NOT __availableToolchainMachines ) + message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) + endif() + if( __availableToolchainMachines MATCHES x86_64 ) + set( __availableToolchainArchs "x86_64" ) + elseif( __availableToolchainMachines MATCHES i686 ) + set( __availableToolchainArchs "x86" ) + elseif( __availableToolchainMachines MATCHES aarch64 ) + set( __availableToolchainArchs "arm64" ) + elseif( __availableToolchainMachines MATCHES arm ) + set( __availableToolchainArchs "arm" ) + elseif( __availableToolchainMachines MATCHES mips64el ) + set( __availableToolchainArchs "mips64" ) + elseif( __availableToolchainMachines MATCHES mipsel ) + set( __availableToolchainArchs "mips" ) + endif() + execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion + OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) + if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) + list( APPEND __availableToolchains "standalone-clang" ) + list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) + list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) + list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) + endif() +endif() + +macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) + foreach( __toolchain ${${__availableToolchainsLst}} ) + if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) + SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" ) + FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" ) + if( __toolchainVersionStr ) + string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" ) + string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" ) + else() + string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) + endif() + unset( __toolchainVersionStr ) + unset( __toolchainVersionRegex ) + else() + set( __gcc_toolchain "${__toolchain}" ) + endif() + __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) + if( __machine ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) + if( __machine MATCHES x86_64 ) + set( __arch "x86_64" ) + elseif( __machine MATCHES i686 ) + set( __arch "x86" ) + elseif( __machine MATCHES aarch64 ) + set( __arch "arm64" ) + elseif( __machine MATCHES arm ) + set( __arch "arm" ) + elseif( __machine MATCHES mips64el ) + set( __arch "mips64" ) + elseif( __machine MATCHES mipsel ) + set( __arch "mips" ) + else() + set( __arch "" ) + endif() + #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n") + if (__arch) + list( APPEND __availableToolchainMachines "${__machine}" ) + list( APPEND __availableToolchainArchs "${__arch}" ) + list( APPEND __availableToolchainCompilerVersions "${__version}" ) + list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) + endif() + endif() + unset( __gcc_toolchain ) + endforeach() +endmacro() + +# get all the details about NDK +if( BUILD_WITH_ANDROID_NDK ) + file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) + string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) + set( __availableToolchains "" ) + set( __availableToolchainMachines "" ) + set( __availableToolchainArchs "" ) + set( __availableToolchainCompilerVersions "" ) + if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) + # do not go through all toolchains if we know the name + set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) + if( __availableToolchainsLst ) + list(SORT __availableToolchainsLst) # we need clang to go after gcc + endif() + __LIST_FILTER( __availableToolchainsLst "^[.]" ) + __LIST_FILTER( __availableToolchainsLst "llvm" ) + __LIST_FILTER( __availableToolchainsLst "renderscript" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) + endif() +endif() + +# build list of available ABIs +set( ANDROID_SUPPORTED_ABIS "" ) +set( __uniqToolchainArchNames ${__availableToolchainArchs} ) +list( REMOVE_DUPLICATES __uniqToolchainArchNames ) +list( SORT __uniqToolchainArchNames ) +foreach( __arch ${__uniqToolchainArchNames} ) + list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) +endforeach() +unset( __uniqToolchainArchNames ) +if( NOT ANDROID_SUPPORTED_ABIS ) + message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) +endif() + +# choose target ABI +__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} ) +# verify that target ABI is supported +list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) +if( __androidAbiIdx EQUAL -1 ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. + Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" + " ) +endif() +unset( __androidAbiIdx ) + +# set target ABI options +if( ANDROID_ABI STREQUAL "x86" ) + set( X86 true ) + set( ANDROID_NDK_ABI_NAME "x86" ) + set( ANDROID_ARCH_NAME "x86" ) + set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "i686" ) +elseif( ANDROID_ABI STREQUAL "x86_64" ) + set( X86 true ) + set( X86_64 true ) + set( ANDROID_NDK_ABI_NAME "x86_64" ) + set( ANDROID_ARCH_NAME "x86_64" ) + set( CMAKE_SYSTEM_PROCESSOR "x86_64" ) + set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" ) +elseif( ANDROID_ABI STREQUAL "mips64" ) + set( MIPS64 true ) + set( ANDROID_NDK_ABI_NAME "mips64" ) + set( ANDROID_ARCH_NAME "mips64" ) + set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips64" ) +elseif( ANDROID_ABI STREQUAL "mips" ) + set( MIPS true ) + set( ANDROID_NDK_ABI_NAME "mips" ) + set( ANDROID_ARCH_NAME "mips" ) + set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips" ) +elseif( ANDROID_ABI STREQUAL "arm64-v8a" ) + set( ARM64_V8A true ) + set( ANDROID_NDK_ABI_NAME "arm64-v8a" ) + set( ANDROID_ARCH_NAME "arm64" ) + set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "aarch64" ) + set( VFPV3 true ) + set( NEON true ) +elseif( ANDROID_ABI STREQUAL "armeabi" ) + set( ARMEABI true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) + set( ARMEABI_V6 true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv6" ) + # need always fallback to older platform + set( ARMEABI true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a") + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) + set( NEON true ) +else() + message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) +endif() + +if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) + # really dirty hack + # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... + file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) +endif() + +if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) + __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF ) + set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) + mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) +else() + unset( ANDROID_FORCE_ARM_BUILD CACHE ) +endif() + +# choose toolchain +if( ANDROID_TOOLCHAIN_NAME ) + list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) + if( __toolchainIdx EQUAL -1 ) + list( SORT __availableToolchains ) + string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) + set( toolchains_list " * ${toolchains_list}") + message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. +To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) + endif() + list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) + if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) + endif() +else() + set( __toolchainIdx -1 ) + set( __applicableToolchains "" ) + set( __toolchainMaxVersion "0.0.0" ) + list( LENGTH __availableToolchains __availableToolchainsCount ) + math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) + foreach( __idx RANGE ${__availableToolchainsCount} ) + list( GET __availableToolchainArchs ${__idx} __toolchainArch ) + if( __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) + string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") + if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) + set( __toolchainMaxVersion "${__toolchainVersion}" ) + set( __toolchainIdx ${__idx} ) + endif() + endif() + endforeach() + unset( __availableToolchainsCount ) + unset( __toolchainMaxVersion ) + unset( __toolchainVersion ) +endif() +unset( __toolchainArch ) +if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) +endif() +list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) +list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) +list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) + +unset( __toolchainIdx ) +unset( __availableToolchains ) +unset( __availableToolchainMachines ) +unset( __availableToolchainArchs ) +unset( __availableToolchainCompilerVersions ) + +# choose native API level +__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) +string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) +string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL ) +# adjust API level +set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) +foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level ) + set( __real_api_level ${__level} ) + endif() +endforeach() +if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level ) + message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") + set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) +endif() +unset(__real_api_level) +# validate +list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) +if( __levelIdx EQUAL -1 ) + message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) +else() + if( BUILD_WITH_ANDROID_NDK ) + __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) + if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 ) + message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) + endif() + unset( __realApiLevel ) + endif() + set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) + set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} ) + if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) + set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + endif() +endif() +unset( __levelIdx ) + + +# remember target ABI +set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} ) + set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} ) +endif() + + +# runtime choice (STL, rtti, exceptions) +if( NOT ANDROID_STL ) + set( ANDROID_STL gnustl_static ) +endif() +set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) +set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) +mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) + +if( BUILD_WITH_ANDROID_NDK ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + system -> Use the default minimal system C++ runtime library. + system_re -> Same as system but with rtti and exceptions. + gabi++_static -> Use the GAbi++ runtime as a static library. + gabi++_shared -> Use the GAbi++ runtime as a shared library. + stlport_static -> Use the STLport runtime as a static library. + stlport_shared -> Use the STLport runtime as a shared library. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +endif() + +unset( ANDROID_RTTI ) +unset( ANDROID_EXCEPTIONS ) +unset( ANDROID_STL_INCLUDE_DIRS ) +unset( __libstl ) +unset( __libsupcxx ) + +if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) + message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). +You are strongly recommended to switch to another NDK release. +" ) +endif() + +if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) + message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: +See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 + diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + index 5e28c64..65892a1 100644 + --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h + +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + @@ -51,7 +51,11 @@ typedef long int ssize_t; + #endif + #ifndef _PTRDIFF_T + #define _PTRDIFF_T + -typedef long ptrdiff_t; + +# ifdef __ANDROID__ + + typedef int ptrdiff_t; + +# else + + typedef long ptrdiff_t; + +# endif + #endif +" ) +endif() + + +# setup paths and STL for standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) + + if( NOT ANDROID_STL STREQUAL "none" ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" ) + if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" ) + # old location ( pre r8c ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) + endif() + if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) + else() + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) + endif() + # always search static GNU STL to get the location of libsupc++.a + if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) + elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) + endif() + if( __libstl ) + set( __libsupcxx "${__libstl}/libsupc++.a" ) + set( __libstl "${__libstl}/libstdc++.a" ) + endif() + if( NOT EXISTS "${__libsupcxx}" ) + message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. + Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. + You need to either upgrade to newer NDK or manually copy + $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a + to + ${__libsupcxx} + " ) + endif() + if( ANDROID_STL STREQUAL "gnustl_shared" ) + if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + endif() + endif() + endif() +endif() + +# clang +if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) + set( ANDROID_COMPILER_IS_CLANG 1 ) + execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") +elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) + string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") + string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) + message( FATAL_ERROR "Could not find the Clang compiler driver" ) + endif() + set( ANDROID_COMPILER_IS_CLANG 1 ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) +else() + set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + unset( ANDROID_COMPILER_IS_CLANG CACHE ) +endif() + +string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) +if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) + set( _clang_name "clang" ) +endif() + + +# setup paths and STL for NDK +if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) + + if( ANDROID_STL STREQUAL "none" ) + # do nothing + elseif( ANDROID_STL STREQUAL "system" ) + set( ANDROID_RTTI OFF ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL STREQUAL "system_re" ) + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL MATCHES "gabi" ) + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") + endif() + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) + elseif( ANDROID_STL MATCHES "stlport" ) + if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d + set( ANDROID_EXCEPTIONS ON ) + else() + set( ANDROID_EXCEPTIONS OFF ) + endif() + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + set( ANDROID_RTTI OFF ) + else() + set( ANDROID_RTTI ON ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) + elseif( ANDROID_STL MATCHES "gnustl" ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_RTTI ON ) + if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) + # gnustl binary for 4.7 compiler is buggy :( + # TODO: look for right fix + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + endif() + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" ) + if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + else() + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) + endif() + else() + message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) + endif() + # find libsupc++.a - rtti & exceptions + if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer + if( NOT EXISTS "${__libsupcxx}" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 + endif() + if( NOT EXISTS "${__libsupcxx}" ) # before r7 + if( ARMEABI_V7A ) + if( ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) + endif() + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) + endif() + endif() + if( NOT EXISTS "${__libsupcxx}") + message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") + endif() + endif() +endif() + + +# case of shared STL linkage +if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) + string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) + # TODO: check if .so file exists before the renaming +endif() + + +# ccache support +__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) +if( _ndk_ccache ) + if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) + unset( NDK_CCACHE CACHE ) + endif() + find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") +else() + unset( NDK_CCACHE CACHE ) +endif() +unset( _ndk_ccache ) + + +# setup the cross-compiler +if( NOT CMAKE_C_COMPILER ) + if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) + set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + endif() + else() + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) + set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) + endif() + endif() + set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) + set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) + if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" ) + # Use gcc-ar if we have it for better LTO support. + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + else() + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + endif() + set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) + set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) + set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) + set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) + set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) +endif() + +set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() +if( APPLE ) + find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) + if( NOT CMAKE_INSTALL_NAME_TOOL ) + message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) + endif() + mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +endif() + +# Force set compilers because standard identification works badly for us +include( CMakeForceCompiler ) +CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ID Clang ) +endif() +set( CMAKE_C_PLATFORM_ID Linux ) +if( X86_64 OR MIPS64 OR ARM64_V8A ) + set( CMAKE_C_SIZEOF_DATA_PTR 8 ) +else() + set( CMAKE_C_SIZEOF_DATA_PTR 4 ) +endif() +set( CMAKE_C_HAS_ISYSROOT 1 ) +set( CMAKE_C_COMPILER_ABI ELF ) +CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_CXX_COMPILER_ID Clang) +endif() +set( CMAKE_CXX_PLATFORM_ID Linux ) +set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} ) +set( CMAKE_CXX_HAS_ISYSROOT 1 ) +set( CMAKE_CXX_COMPILER_ABI ELF ) +set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) +# force ASM compiler (required for CMake < 2.8.5) +set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) +set( CMAKE_ASM_COMPILER_ID GNU ) +set( CMAKE_ASM_COMPILER_WORKS TRUE ) +set( CMAKE_ASM_COMPILER_FORCED TRUE ) +set( CMAKE_COMPILER_IS_GNUASM 1) +set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) + +foreach( lang C CXX ASM ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} ) + else() + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} ) + endif() +endforeach() + +# flags and definitions +remove_definitions( -DANDROID ) +add_definitions( -DANDROID ) + +if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) + if( CMAKE_HOST_WIN32 ) + # try to convert path to 8.3 form + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) + execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" + OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE __result ERROR_QUIET ) + if( __result EQUAL 0 ) + file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) + else() + set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) + endif() + else() + set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) + endif() + if( NOT _CMAKE_IN_TRY_COMPILE ) + # quotes can break try_compile and compiler identification + message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") + endif() +else() + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) +endif() + +# NDK flags +if (ARM64_V8A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif( ARMEABI OR ARMEABI_V7A) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) + endif() + else() + # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI + set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + endif() +elseif( X86 OR X86_64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) +elseif( MIPS OR MIPS64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif() + set( ANDROID_CXX_FLAGS_RELEASE "" ) + set( ANDROID_CXX_FLAGS_DEBUG "" ) +endif() + +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries + +if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) +endif() + +if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ +endif() + +# ABI-specific flags +if( ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) + if( NEON ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) + elseif( VFPV3 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + endif() +elseif( ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 +elseif( ARMEABI ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) +endif() + +if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +else() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +endif() + +# STL +if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) + if( EXISTS "${__libstl}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) + endif() + if( EXISTS "${__libsupcxx}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + # C objects: + set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_C_LINK_EXECUTABLE " -o " ) + set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + endif() + if( ANDROID_STL MATCHES "gnustl" ) + if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) + set( ANDROID_LIBM_PATH -lm ) + endif() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) + endif() +endif() + +# variables controlling optional build flags +if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. + # So this flag option is required for all projects using OpenGL from native. + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) +else() + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) +endif() +__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON ) +__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) +__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) +__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) +__INIT_VARIABLE( ANDROID_RELRO VALUES ON ) + +set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) +set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" ) +set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" ) +set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) +mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) + +# linker flags +set( ANDROID_LINKER_FLAGS "" ) + +if( ARMEABI_V7A ) + # this is *required* to use the following linker flags that routes around + # a CPU bug in some Cortex-A8 implementations: + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) +endif() + +if( ANDROID_NO_UNDEFINED ) + if( MIPS ) + # there is some sysroot-related problem in mips linker... + if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) + endif() + else() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) + endif() +endif() + +if( ANDROID_SO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) +endif() + +if( ANDROID_FUNCTION_LEVEL_LINKING ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) +endif() + +if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) + if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) + elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) + elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 + On Linux and OS X host platform you can workaround this problem using gold linker (default). + Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. +" ) + endif() +endif() # version 4.6 + +if( ANDROID_NOEXECSTACK ) + if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) + endif() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) +endif() + +if( ANDROID_RELRO ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) +endif() + +if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" ) + if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) + endif() +endif() + +# cache flags +set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) + +# put flags to cache (for debug purpose only) +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) +set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) +set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) + +# finish flags +set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) +set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) +set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) +set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) +set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) +set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) + +if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) + set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) +endif() + +# pie/pic +if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) ) + set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie") +else() + set( CMAKE_POSITION_INDEPENDENT_CODE FALSE ) + set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" ) +endif() + +# configure rtti +if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_RTTI ) + set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) + endif() +endif() + +# configure exceptios +if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_EXCEPTIONS ) + set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) + endif() +endif() + +# global includes and link directories +include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) +get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning +link_directories( "${__android_install_path}" ) + +# detect if need link crtbegin_so.o explicitly +if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) + set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) + string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "-shared" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) + string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + separate_arguments( __cmd ) + foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) + if( ${__var} ) + set( __tmp "${${__var}}" ) + separate_arguments( __tmp ) + string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") + endif() + endforeach() + string( REPLACE "'" "" __cmd "${__cmd}" ) + string( REPLACE "\"" "" __cmd "${__cmd}" ) + execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) + if( __cmd_result EQUAL 0 ) + set( ANDROID_EXPLICIT_CRT_LINK ON ) + else() + set( ANDROID_EXPLICIT_CRT_LINK OFF ) + endif() +endif() + +if( ANDROID_EXPLICIT_CRT_LINK ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) +endif() + +# setup output directories +set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if( DEFINED LIBRARY_OUTPUT_PATH_ROOT + OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml" + OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") ) + set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" ) + if( NOT _CMAKE_IN_TRY_COMPILE ) + if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) + else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) + endif() + set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" ) + endif() +endif() + +# copy shaed stl library to build directory +if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH ) + get_filename_component( __libstlname "${__libstl}" NAME ) + execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) + if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") + message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) + endif() + unset( __fileCopyProcess ) + unset( __libstlname ) +endif() + + +# set these global flags for cmake client scripts to change behavior +set( ANDROID True ) +set( BUILD_ANDROID True ) + +# where is the target environment +set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) + +# only search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + + +# macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# export toolchain settings for the try_compile() command +if( NOT _CMAKE_IN_TRY_COMPILE ) + set( __toolchain_config "") + foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN + ANDROID_NDK_HOST_X64 + ANDROID_NDK + ANDROID_NDK_LAYOUT + ANDROID_STANDALONE_TOOLCHAIN + ANDROID_TOOLCHAIN_NAME + ANDROID_ABI + ANDROID_NATIVE_API_LEVEL + ANDROID_STL + ANDROID_STL_FORCE_FEATURES + ANDROID_FORCE_ARM_BUILD + ANDROID_NO_UNDEFINED + ANDROID_SO_UNDEFINED + ANDROID_FUNCTION_LEVEL_LINKING + ANDROID_GOLD_LINKER + ANDROID_NOEXECSTACK + ANDROID_RELRO + ANDROID_LIBM_PATH + ANDROID_EXPLICIT_CRT_LINK + ANDROID_APP_PIE + ) + if( DEFINED ${__var} ) + if( ${__var} MATCHES " ") + set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) + else() + set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) + endif() + endif() + endforeach() + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) + unset( __toolchain_config ) +endif() + + +# force cmake to produce / instead of \ in build commands for Ninja generator +if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 ) + # it is a bad hack after all + # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW + set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW + set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion + enable_language( C ) + enable_language( CXX ) + # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it + unset( MINGW ) +endif() + + +# Variables controlling behavior or set by cmake toolchain: +# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64" +# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version) +# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none +# ANDROID_FORBID_SYGWIN : ON/OFF +# ANDROID_NO_UNDEFINED : ON/OFF +# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) +# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF +# ANDROID_GOLD_LINKER : ON/OFF +# ANDROID_NOEXECSTACK : ON/OFF +# ANDROID_RELRO : ON/OFF +# ANDROID_FORCE_ARM_BUILD : ON/OFF +# ANDROID_STL_FORCE_FEATURES : ON/OFF +# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` +# Can be set only at the first run: +# ANDROID_NDK : path to your NDK install +# NDK_CCACHE : path to your ccache executable +# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain +# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) +# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) +# LIBRARY_OUTPUT_PATH_ROOT : +# ANDROID_STANDALONE_TOOLCHAIN +# +# Primary read-only variables: +# ANDROID : always TRUE +# ARMEABI : TRUE for arm v6 and older devices +# ARMEABI_V6 : TRUE for arm v6 +# ARMEABI_V7A : TRUE for arm v7a +# ARM64_V8A : TRUE for arm64-v8a +# NEON : TRUE if NEON unit is enabled +# VFPV3 : TRUE if VFP version 3 is enabled +# X86 : TRUE if configured for x86 +# X86_64 : TRUE if configured for x86_64 +# MIPS : TRUE if configured for mips +# MIPS64 : TRUE if configured for mips64 +# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used +# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used +# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform +# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK +# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor) +# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_SYSROOT : path to the compiler sysroot +# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform +# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used +# +# Secondary (less stable) read-only variables: +# ANDROID_COMPILER_VERSION : GCC version used (not Clang version) +# ANDROID_CLANG_VERSION : version of clang compiler if clang is used +# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform +# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI +# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" +# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) +# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools +# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK +# ANDROID_STL_INCLUDE_DIRS : stl include paths +# ANDROID_RTTI : if rtti is enabled by the runtime +# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime +# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used +# +# Defaults: +# ANDROID_DEFAULT_NDK_API_LEVEL +# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} +# ANDROID_NDK_SEARCH_PATHS +# ANDROID_SUPPORTED_ABIS_${ARCH} +# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/contrib/android-cmake/ndk_links.md b/contrib/android-cmake/ndk_links.md new file mode 100644 index 000000000..6d93d61d2 --- /dev/null +++ b/contrib/android-cmake/ndk_links.md @@ -0,0 +1,211 @@ + +============== r1 ============== (dead links) + +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip + +============== r2 ============== + +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip + +============== r3 ============== + +* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip + +============== r4 ============== + +* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip + +============== r4b ============== + +* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip + +============== r5 ============== + +* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2 + +============== r5b ============== + +* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2 + +============== r5c ============== + +* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2 + +============== r6 ============== + +* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 + +============== r6b ============== + +* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2 + +============== r7 ============== + +* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2 + +============== r7b ============== + +* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2 + +============== r7c ============== + +* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2 + +============== r8 ============== + +* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2 + +============== r8b ============== + +* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2 + +============== r8c ============== + +* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2 + +============== r8d ============== + +* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2 + +============== r8e ============== + +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2 + +============== r9 ============== + +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9b ============== + +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9c ============== + +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip + +============== r9d ============== + +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip + +============== r10 ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip + +============== r10b ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip + +============== r10c ============== + +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin + +============== r10d ============== + +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin diff --git a/contrib/zlib/zconf.h.included b/contrib/zlib/zconf.h.included index 5e1d68a00..352f552b8 100644 --- a/contrib/zlib/zconf.h.included +++ b/contrib/zlib/zconf.h.included @@ -7,6 +7,8 @@ #ifndef ZCONF_H #define ZCONF_H +/* #undef Z_PREFIX */ +/* #undef Z_HAVE_UNISTD_H */ /* * If you *really* need a unique prefix for all types and library functions, diff --git a/scripts/android_crosscompile/make_android.bat b/scripts/android_crosscompile/make_android.bat new file mode 100644 index 000000000..a50695e16 --- /dev/null +++ b/scripts/android_crosscompile/make_android.bat @@ -0,0 +1,28 @@ +@echo off + +set ASSIMP_PATH=D:\projects\asset-importer-lib\assimp +set CMAKE_PATH="C:\Program Files\CMake\bin\cmake.exe" +set ANDROID_NDK_PATH=C:\Users\kimkulling\AppData\Local\Android\Sdk\ndk-bundle +set ANDROID_CMAKE_PATH=contrib\android-cmake + +pushd %ASSIMP_PATH% + +rmdir /s /q build +mkdir build +cd build + +%CMAKE_PATH% .. ^ + -G"MinGW Makefiles" ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DCMAKE_TOOLCHAIN_FILE=%ANDROID_CMAKE_PATH%\android.toolchain.cmake ^ + -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_PATH%\prebuilt\windows-x86_64\bin\make.exe ^ + -DANDROID_NDK=%ANDROID_NDK_PATH% ^ + -DANDROID_NATIVE_API_LEVEL=android-9 ^ + -DASSIMP_ANDROID_JNIIOSYSTEM=ON ^ + -DANDROID_ABI=arm64-v8a ^ + -DASSIMP_BUILD_ZLIB=ON ^ + -DASSIMP_BUILD_TESTS=OFF + +%CMAKE_PATH% --build . + +popd \ No newline at end of file From d9965f6220b500b35a2186bebd32b4b49b3e784a Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Thu, 16 Nov 2017 14:42:20 +0100 Subject: [PATCH 65/78] Update Importer.cpp --- code/Importer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index 379daab02..c6c6f0edd 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -274,10 +274,6 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp) if (it != pimpl->mImporter.end()) { pimpl->mImporter.erase(it); - - std::set st; - pImp->GetExtensionList(st); - DefaultLogger::get()->info("Unregistering custom importer: "); return AI_SUCCESS; } From fc360b9cc8c69f2817a9f65eb5f6acc8600b7175 Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Sat, 18 Nov 2017 00:05:17 +0100 Subject: [PATCH 66/78] Update ValidateDataStructure.h --- code/ValidateDataStructure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ValidateDataStructure.h b/code/ValidateDataStructure.h index 6daf9b87d..188950e0e 100644 --- a/code/ValidateDataStructure.h +++ b/code/ValidateDataStructure.h @@ -91,7 +91,7 @@ protected: // ------------------------------------------------------------------- /** Report a validation warning. This won't throw an exception, - * control will return to the callera. + * control will return to the caller. * @param msg Format string for sprintf().*/ void ReportWarning(const char* msg,...); From 703d046fd9baf6f70ce78c96a1567e9675a884eb Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Sat, 18 Nov 2017 00:34:00 +0100 Subject: [PATCH 67/78] Update ValidateDataStructure.cpp --- code/ValidateDataStructure.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index f1035e441..c036eac18 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -334,28 +334,28 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) case 1: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) { - ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimtiveTypes " + ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes " "does not report the POINT flag",i); } break; case 2: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE)) { - ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimtiveTypes " + ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimitiveTypes " "does not report the LINE flag",i); } break; case 3: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) { - ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimtiveTypes " + ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimitiveTypes " "does not report the TRIANGLE flag",i); } break; default: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) { - this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimtiveTypes " + this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimitiveTypes " "does not report the POLYGON flag",i); } break; From 40bb3f3d0f7998588273565d6eee1853f4593f9a Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Fri, 17 Nov 2017 13:56:53 +0200 Subject: [PATCH 68/78] Unit test: Fix signed/unsigned comparison warnings --- test/unit/utObjImportExport.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 6361813d0..d9df779ac 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -294,12 +294,12 @@ TEST_F(utObjImportExport, relative_indices_Test) { const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); - EXPECT_EQ(scene->mNumMeshes, 1); + EXPECT_EQ(scene->mNumMeshes, 1U); const aiMesh *mesh = scene->mMeshes[0]; - EXPECT_EQ(mesh->mNumVertices, 4); - EXPECT_EQ(mesh->mNumFaces, 1); + EXPECT_EQ(mesh->mNumVertices, 4U); + EXPECT_EQ(mesh->mNumFaces, 1U); const aiFace face = mesh->mFaces[0]; - EXPECT_EQ(face.mNumIndices, 4); + EXPECT_EQ(face.mNumIndices, 4U); for (unsigned int i = 0; i < face.mNumIndices; ++i) { EXPECT_EQ(face.mIndices[i], i); @@ -318,12 +318,12 @@ TEST_F(utObjImportExport, homogeneous_coordinates_Test) { const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); - EXPECT_EQ(scene->mNumMeshes, 1); + EXPECT_EQ(scene->mNumMeshes, 1U); const aiMesh *mesh = scene->mMeshes[0]; - EXPECT_EQ(mesh->mNumVertices, 3); - EXPECT_EQ(mesh->mNumFaces, 1); + EXPECT_EQ(mesh->mNumVertices, 3U); + EXPECT_EQ(mesh->mNumFaces, 1U); const aiFace face = mesh->mFaces[0]; - EXPECT_EQ(face.mNumIndices, 3); + EXPECT_EQ(face.mNumIndices, 3U); const aiVector3D vertice = mesh->mVertices[0]; EXPECT_EQ(vertice.x, -1.0f); EXPECT_EQ(vertice.y, 0.0f); From c1515db56f951cec82dbfa35265db35d7d8bfd71 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 18 Nov 2017 15:50:56 +0200 Subject: [PATCH 69/78] Blender: Fix strict-aliasing warnings --- code/BlenderScene.cpp | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/code/BlenderScene.cpp b/code/BlenderScene.cpp index b9068329b..0e1dec7f3 100644 --- a/code/BlenderScene.cpp +++ b/code/BlenderScene.cpp @@ -59,7 +59,9 @@ template <> void Structure :: Convert ( { ReadField(dest.id,"id",db); - ReadField((int&)dest.type,"type",db); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); ReadFieldArray2(dest.obmat,"obmat",db); ReadFieldArray2(dest.parentinv,"parentinv",db); ReadFieldArray(dest.parsubstr,"parsubstr",db); @@ -100,14 +102,21 @@ template <> void Structure :: Convert ( ) const { - ReadField((short&)dest.mapto,"mapto",db); - ReadField((int&)dest.blendtype,"blendtype",db); + int temp_short = 0; + ReadField(temp_short,"mapto",db); + dest.mapto = static_cast(temp_short); + int temp = 0; + ReadField(temp,"blendtype",db); + dest.blendtype = static_cast(temp); ReadFieldPtr(dest.object,"*object",db); ReadFieldPtr(dest.tex,"*tex",db); ReadFieldArray(dest.uvname,"uvname",db); - ReadField((int&)dest.projx,"projx",db); - ReadField((int&)dest.projy,"projy",db); - ReadField((int&)dest.projz,"projz",db); + ReadField(temp,"projx",db); + dest.projx = static_cast(temp); + ReadField(temp,"projy",db); + dest.projy = static_cast(temp); + ReadField(temp,"projz",db); + dest.projx = static_cast(temp); ReadField(dest.mapping,"mapping",db); ReadFieldArray(dest.ofs,"ofs",db); ReadFieldArray(dest.size,"size",db); @@ -190,7 +199,9 @@ template <> void Structure :: Convert ( { ReadField(dest.id,"id",db); - ReadField((int&)dest.type,"type",db); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); ReadField(dest.flags,"flags",db); ReadField(dest.colormodel,"colormodel",db); ReadField(dest.totex,"totex",db); @@ -204,7 +215,8 @@ template <> void Structure :: Convert ( ReadField(dest.spotblend,"spotblend",db); ReadField(dest.att1,"att1",db); ReadField(dest.att2,"att2",db); - ReadField((int&)dest.falloff_type,"falloff_type",db); + ReadField(temp,"falloff_type",db); + dest.falloff_type = static_cast(temp); ReadField(dest.sun_brightness,"sun_brightness",db); ReadField(dest.area_size,"area_size",db); ReadField(dest.area_sizey,"area_sizey",db); @@ -693,8 +705,12 @@ template <> void Structure :: Convert ( const FileDatabase& db ) const { - ReadField((short&)dest.imaflag,"imaflag",db); - ReadField((int&)dest.type,"type",db); + short temp_short = 0; + ReadField(temp_short,"imaflag",db); + dest.imaflag = static_cast(temp_short); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); ReadFieldPtr(dest.ima,"*ima",db); db.reader->IncPtr(size); @@ -708,8 +724,11 @@ template <> void Structure :: Convert ( { ReadField(dest.id,"id",db); - ReadField((int&)dest.type,"type",db); - ReadField((int&)dest.flag,"flag",db); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); + ReadField(temp,"flag",db); + dest.flag = static_cast(temp); ReadField(dest.lens,"lens",db); ReadField(dest.sensor_x,"sensor_x",db); ReadField(dest.clipsta,"clipsta",db); From 1067ae4bfa21bd27131f5a332b4f0c615477a97c Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 18 Nov 2017 15:54:40 +0200 Subject: [PATCH 70/78] FIReader: Fix strict-aliasing warnings --- code/FIReader.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/code/FIReader.cpp b/code/FIReader.cpp index fdf6b8a83..f3cf3cdb4 100755 --- a/code/FIReader.cpp +++ b/code/FIReader.cpp @@ -485,7 +485,9 @@ struct FIFloatDecoder: public FIDecoder { value.reserve(numFloats); for (size_t i = 0; i < numFloats; ++i) { int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; - value.push_back(*(float*)&v); + float f; + memcpy(&f, &v, 4); + value.push_back(f); data += 4; } return FIFloatValue::create(std::move(value)); @@ -503,7 +505,9 @@ struct FIDoubleDecoder: public FIDecoder { for (size_t i = 0; i < numDoubles; ++i) { long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7]; long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7; - value.push_back(*(double*)&v); + double f; + memcpy(&f, &v, 8); + value.push_back(f); data += 8; } return FIDoubleValue::create(std::move(value)); From 53119e74f81e06429d82e9ee2882322267af4a59 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 18 Nov 2017 15:59:30 +0200 Subject: [PATCH 71/78] Open3DGC: Fix strict-aliasing warnings --- contrib/Open3DGC/o3dgcBinaryStream.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contrib/Open3DGC/o3dgcBinaryStream.h b/contrib/Open3DGC/o3dgcBinaryStream.h index 19e3df973..b7b7678b7 100644 --- a/contrib/Open3DGC/o3dgcBinaryStream.h +++ b/contrib/Open3DGC/o3dgcBinaryStream.h @@ -231,7 +231,8 @@ namespace o3dgc float ReadFloat32Bin(unsigned long & position) const { unsigned long value = ReadUInt32Bin(position); - float fvalue = *((float *)(&value)); + float fvalue; + memcpy(&fvalue, &value, 4); return fvalue; } unsigned long ReadUInt32Bin(unsigned long & position) const @@ -261,7 +262,8 @@ namespace o3dgc void WriteFloat32ASCII(float value) { - unsigned long uiValue = *((unsigned long *)(&value)); + unsigned long uiValue; + memcpy(&uiValue, &value, 4); WriteUInt32ASCII(uiValue); } void WriteUInt32ASCII(unsigned long position, unsigned long value) @@ -314,7 +316,8 @@ namespace o3dgc float ReadFloat32ASCII(unsigned long & position) const { unsigned long value = ReadUInt32ASCII(position); - float fvalue = *((float *)(&value)); + float fvalue; + memcpy(&fvalue, &value, 4); return fvalue; } unsigned long ReadUInt32ASCII(unsigned long & position) const From 10f4b6f95c318e92b40e1e79ff09a2eca511f136 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 18 Nov 2017 16:02:53 +0200 Subject: [PATCH 72/78] assimp_cmd: Fix strict-aliasing warnings --- tools/assimp_cmd/WriteDumb.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 69d4efcc5..e1b104d40 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -177,6 +177,17 @@ inline uint32_t Write(const aiVector3D& v) return t; } +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline uint32_t Write(const aiColor3D& v) +{ + uint32_t t = Write(v.r); + t += Write(v.g); + t += Write(v.b); + return t; +} + // ----------------------------------------------------------------------------------- // Serialize a color value template <> @@ -566,9 +577,9 @@ uint32_t WriteBinaryLight(const aiLight* l) len += Write(l->mAttenuationQuadratic); } - len += Write((const aiVector3D&)l->mColorDiffuse); - len += Write((const aiVector3D&)l->mColorSpecular); - len += Write((const aiVector3D&)l->mColorAmbient); + len += Write(l->mColorDiffuse); + len += Write(l->mColorSpecular); + len += Write(l->mColorAmbient); if (l->mType == aiLightSource_SPOT) { len += Write(l->mAngleInnerCone); From bcffa28a336b4ce9350b2159649fe5258aedbca7 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 18 Nov 2017 16:39:43 +0200 Subject: [PATCH 73/78] MDLImporter: Don't take address of packed struct member --- code/MDLMaterialLoader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index 91dcb49cc..9086925aa 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -665,7 +665,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( if (0.0f != pcMatIn->Power) { iShadingMode = (int)aiShadingMode_Phong; - pcMatOut->AddProperty(&pcMatIn->Power,1,AI_MATKEY_SHININESS); + // pcMatIn is packed, we can't form pointers to its members + float power = pcMatIn->Power; + pcMatOut->AddProperty(&power,1,AI_MATKEY_SHININESS); } pcMatOut->AddProperty(&iShadingMode,1,AI_MATKEY_SHADING_MODEL); } From 2c8cc1f73249246d183d3e4d1aa84b4a3325f6ef Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 18 Nov 2017 16:49:03 +0200 Subject: [PATCH 74/78] BlenderDNA: Silence warning about uninitialized member --- code/BlenderDNA.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 4c7d0fc26..bac8d78bc 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -92,6 +92,12 @@ struct Error : DeadlyImportError { * descendents. It serves as base class for all data structure fields. */ // ------------------------------------------------------------------------------- struct ElemBase { + ElemBase() + : dna_type(nullptr) + { + // empty + } + virtual ~ElemBase() { // empty } From 8ae723165439087a6f45776b397fff03bcc550da Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 18 Nov 2017 16:50:45 +0200 Subject: [PATCH 75/78] Blender: Silence warning about uninitialized member --- code/BlenderScene.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/BlenderScene.h b/code/BlenderScene.h index 36094eabd..86ab1f30c 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -225,6 +225,14 @@ struct TFace : ElemBase { // ------------------------------------------------------------------------------- struct MTFace : ElemBase { + MTFace() + : flag(0) + , mode(0) + , tile(0) + , unwrap(0) + { + } + float uv[4][2] FAIL; char flag; short mode; From a8e65a1e8aff4a254453f26719df95f8cacdaadf Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 18 Nov 2017 18:32:16 +0100 Subject: [PATCH 76/78] Fix android build. --- CMakeLists.txt | 2 +- code/FIReader.cpp | 24 +++++++++++++----------- code/FIReader.hpp | 10 ++++++++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 79db04762..73a30e9d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,7 +186,7 @@ IF( UNIX ) IF( ${OPERATING_SYSTEM} MATCHES "Android") ELSE() IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux - ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) + #ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) ENDIF() ENDIF() diff --git a/code/FIReader.cpp b/code/FIReader.cpp index fdf6b8a83..e167db026 100755 --- a/code/FIReader.cpp +++ b/code/FIReader.cpp @@ -45,13 +45,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER +#include "FIReader.hpp" +#include "StringUtils.h" + // Workaround for issue #1361 // https://github.com/assimp/assimp/issues/1361 #ifdef __ANDROID__ -#define _GLIBCXX_USE_C99 1 +# define _GLIBCXX_USE_C99 1 #endif -#include "FIReader.hpp" #include "Exceptional.h" #include #include @@ -685,7 +687,7 @@ public: if (intValue) { return intValue->value.size() == 1 ? intValue->value.front() : 0; } - return stoi(attr->value->toString()); + return atoi(attr->value->toString().c_str()); } virtual int getAttributeValueAsInt(int idx) const /*override*/ { @@ -696,7 +698,7 @@ public: if (intValue) { return intValue->value.size() == 1 ? intValue->value.front() : 0; } - return stoi(attributes[idx].value->toString()); + return atoi(attributes[idx].value->toString().c_str()); } virtual float getAttributeValueAsFloat(const char* name) const /*override*/ { @@ -708,7 +710,7 @@ public: if (floatValue) { return floatValue->value.size() == 1 ? floatValue->value.front() : 0; } - return stof(attr->value->toString()); + return atof(attr->value->toString().c_str()); } virtual float getAttributeValueAsFloat(int idx) const /*override*/ { @@ -719,7 +721,7 @@ public: if (floatValue) { return floatValue->value.size() == 1 ? floatValue->value.front() : 0; } - return stof(attributes[idx].value->toString()); + return atof(attributes[idx].value->toString().c_str()); } virtual const char* getNodeName() const /*override*/ { @@ -984,13 +986,13 @@ private: if (index < 32) { FIDecoder *decoder = defaultDecoder[index]; if (!decoder) { - throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index)); + throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index)); } return decoder->decode(dataP, len); } else { if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) { - throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index)); + throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index)); } std::string uri = vocabulary.encodingAlgorithmTable[index - 32]; auto it = decoderMap.find(uri); @@ -1014,12 +1016,12 @@ private: alphabet = "0123456789-:TZ "; break; default: - throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index)); + throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index)); } } else { if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) { - throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index)); + throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index)); } alphabet = vocabulary.restrictedAlphabetTable[index - 16]; } @@ -1027,7 +1029,7 @@ private: utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32)); std::string::size_type alphabetLength = alphabetUTF32.size(); if (alphabetLength < 2) { - throw DeadlyImportError("Invalid restricted alphabet length " + std::to_string(alphabetLength)); + throw DeadlyImportError("Invalid restricted alphabet length " + to_string(alphabetLength)); } std::string::size_type bitsPerCharacter = 1; while ((1ull << bitsPerCharacter) <= alphabetLength) { diff --git a/code/FIReader.hpp b/code/FIReader.hpp index 4e9f712a9..5f4e5bb48 100644 --- a/code/FIReader.hpp +++ b/code/FIReader.hpp @@ -46,12 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FI_READER_H #define INCLUDED_AI_FI_READER_H +#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER + +//#include #include +#include #include #include -#include #include -#include +//#include +//#include #include namespace Assimp { @@ -176,4 +180,6 @@ FIReader::~FIReader() { }// namespace Assimp +#endif // #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER + #endif // INCLUDED_AI_FI_READER_H From 6cbfd5b977486fe419dcc218a3180d88c68f024a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20D=C3=A4hne?= Date: Mon, 20 Nov 2017 14:59:05 +0100 Subject: [PATCH 77/78] [glTF2] Implemented reading binary glTF2 (glb) files --- code/glTF2Asset.h | 29 +++++++++++-- code/glTF2Asset.inl | 99 ++++++++++++++++++++++++++++++++++++++---- code/glTF2Importer.cpp | 8 ++-- 3 files changed, 120 insertions(+), 16 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 877b59ba3..0283ea0d8 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -192,15 +192,31 @@ namespace glTF2 #include "./../include/assimp/Compiler/pushpack1.h" #endif + //! For binary .glb files + //! 12-byte header (+ the JSON + a "body" data section) + struct GLB_Header + { + uint8_t magic[4]; //!< Magic number: "glTF" + uint32_t version; //!< Version number (always 2 as of the last update) + uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes + } PACK_STRUCT; + + struct GLB_Chunk + { + uint32_t chunkLength; + uint32_t chunkType; + } PACK_STRUCT; + #ifdef ASSIMP_API #include "./../include/assimp/Compiler/poppack1.h" #endif - //! Values for the GLB_Header::sceneFormat field - enum SceneFormat + //! Values for the GLB_Chunk::chunkType field + enum ChunkType { - SceneFormat_JSON = 0 + ChunkType_JSON = 0x4E4F534A, + ChunkType_BIN = 0x004E4942 }; //! Values for the mesh primitive modes @@ -1086,7 +1102,10 @@ namespace glTF2 } //! Main function - void Load(const std::string& file); + void Load(const std::string& file, bool isBinary = false); + + //! Enables binary encoding on the asset + void SetAsBinary(); //! Search for an available name, starting from the given strings std::string FindUniqueID(const std::string& str, const char* suffix); @@ -1095,6 +1114,8 @@ namespace glTF2 { return mBodyBuffer; } private: + void ReadBinaryHeader(IOStream& stream, std::vector& sceneData); + void ReadExtensionsUsed(Document& doc); IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 09b049add..72fdf9580 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -1037,7 +1037,72 @@ inline void AssetMetadata::Read(Document& doc) // Asset methods implementation // -inline void Asset::Load(const std::string& pFile) +inline void Asset::ReadBinaryHeader(IOStream& stream, std::vector& sceneData) +{ + GLB_Header header; + if (stream.Read(&header, sizeof(header), 1) != 1) { + throw DeadlyImportError("GLTF: Unable to read the file header"); + } + + if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) { + throw DeadlyImportError("GLTF: Invalid binary glTF file"); + } + + AI_SWAP4(header.version); + asset.version = to_string(header.version); + if (header.version != 2) { + throw DeadlyImportError("GLTF: Unsupported binary glTF version"); + } + + GLB_Chunk chunk; + if (stream.Read(&chunk, sizeof(chunk), 1) != 1) { + throw DeadlyImportError("GLTF: Unable to read JSON chunk"); + } + + AI_SWAP4(chunk.chunkLength); + AI_SWAP4(chunk.chunkType); + + if (chunk.chunkType != ChunkType_JSON) { + throw DeadlyImportError("GLTF: JSON chunk missing"); + } + + // read the scene data + + mSceneLength = chunk.chunkLength; + sceneData.resize(mSceneLength + 1); + sceneData[mSceneLength] = '\0'; + + if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { + throw DeadlyImportError("GLTF: Could not read the file contents"); + } + + uint32_t padding = ((chunk.chunkLength + 3) & ~3) - chunk.chunkLength; + if (padding > 0) { + stream.Seek(padding, aiOrigin_CUR); + } + + AI_SWAP4(header.length); + mBodyOffset = 12 + 8 + chunk.chunkLength + padding + 8; + if (header.length >= mBodyOffset) { + if (stream.Read(&chunk, sizeof(chunk), 1) != 1) { + throw DeadlyImportError("GLTF: Unable to read BIN chunk"); + } + + AI_SWAP4(chunk.chunkLength); + AI_SWAP4(chunk.chunkType); + + if (chunk.chunkType != ChunkType_BIN) { + throw DeadlyImportError("GLTF: BIN chunk missing"); + } + + mBodyLength = chunk.chunkLength; + } + else { + mBodyOffset = mBodyLength = 0; + } +} + +inline void Asset::Load(const std::string& pFile, bool isBinary) { mCurrentAssetDir.clear(); int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); @@ -1048,16 +1113,25 @@ inline void Asset::Load(const std::string& pFile) throw DeadlyImportError("GLTF: Could not open file for reading"); } - mSceneLength = stream->FileSize(); - mBodyLength = 0; + // is binary? then read the header + std::vector sceneData; + if (isBinary) { + SetAsBinary(); // also creates the body buffer + ReadBinaryHeader(*stream, sceneData); + } + else { + mSceneLength = stream->FileSize(); + mBodyLength = 0; - // read the scene data - std::vector sceneData(mSceneLength + 1); - sceneData[mSceneLength] = '\0'; + // read the scene data - if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { - throw DeadlyImportError("GLTF: Could not read the file contents"); + sceneData.resize(mSceneLength + 1); + sceneData[mSceneLength] = '\0'; + + if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { + throw DeadlyImportError("GLTF: Could not read the file contents"); + } } @@ -1110,6 +1184,15 @@ inline void Asset::Load(const std::string& pFile) } } +inline void Asset::SetAsBinary() +{ + if (!mBodyBuffer) { + mBodyBuffer = buffers.Create("binary_glTF"); + mBodyBuffer->MarkAsSpecial(); + } +} + + inline void Asset::ReadExtensionsUsed(Document& doc) { Value* extsUsed = FindArray(doc, "extensionsUsed"); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 5d40d75bc..297f2bc72 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -74,7 +74,7 @@ static const aiImporterDesc desc = { "", "", "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, 0, 0, 0, @@ -103,13 +103,13 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool { const std::string &extension = GetExtension(pFile); - if (extension != "gltf") // We currently can't read glTF2 binary files (.glb), yet + if (extension != "gltf" && extension != "glb") return false; if (checkSig && pIOHandler) { glTF2::Asset asset(pIOHandler); try { - asset.Load(pFile); + asset.Load(pFile, extension == "glb"); std::string version = asset.asset.version; return !version.empty() && version[0] == '2'; } catch (...) { @@ -639,7 +639,7 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO // read the asset file glTF2::Asset asset(pIOHandler); - asset.Load(pFile); + asset.Load(pFile, GetExtension(pFile) == "glb"); // // Copy the data out From a05d74a281dd786b41e5ef9daf3c0ebea1988797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20D=C3=A4hne?= Date: Mon, 20 Nov 2017 19:01:28 +0100 Subject: [PATCH 78/78] [glTF2] Moved byteStride from accessor to bufferView --- code/glTF2Asset.h | 2 +- code/glTF2Asset.inl | 6 +++--- code/glTF2AssetWriter.inl | 7 +++---- code/glTF2Exporter.cpp | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 0283ea0d8..765f5e0f8 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -436,7 +436,6 @@ namespace glTF2 { Ref bufferView; //!< The ID of the bufferView. (required) unsigned int byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) - unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0) 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) @@ -627,6 +626,7 @@ namespace glTF2 Ref buffer; //! The ID of the buffer. (required) size_t byteOffset; //! The offset into the buffer in bytes. (required) size_t byteLength; //! The length of the bufferView in bytes. (default: 0) + unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0) BufferViewTarget target; //! The target that the WebGL buffer should be bound to. diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 72fdf9580..ca18e87e0 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -512,6 +512,7 @@ inline void BufferView::Read(Value& obj, Asset& r) byteOffset = MemberOrDefault(obj, "byteOffset", 0u); byteLength = MemberOrDefault(obj, "byteLength", 0u); + byteStride = MemberOrDefault(obj, "byteStride", 0u); } // @@ -526,7 +527,6 @@ inline void Accessor::Read(Value& obj, Asset& r) } byteOffset = MemberOrDefault(obj, "byteOffset", 0u); - byteStride = MemberOrDefault(obj, "byteStride", 0u); componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); count = MemberOrDefault(obj, "count", 0u); @@ -601,7 +601,7 @@ bool Accessor::ExtractData(T*& outData) const size_t elemSize = GetElementSize(); const size_t totalSize = elemSize * count; - const size_t stride = byteStride ? byteStride : elemSize; + const size_t stride = bufferView && bufferView->byteStride ? bufferView->byteStride : elemSize; const size_t targetElemSize = sizeof(T); ai_assert(elemSize <= targetElemSize); @@ -641,7 +641,7 @@ inline Accessor::Indexer::Indexer(Accessor& acc) : accessor(acc) , data(acc.GetPointer()) , elemSize(acc.GetElementSize()) - , stride(acc.byteStride ? acc.byteStride : elemSize) + , stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) { } diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 8583462ce..8b2769a37 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -98,10 +98,6 @@ namespace glTF2 { obj.AddMember("bufferView", a.bufferView->index, w.mAl); obj.AddMember("byteOffset", a.byteOffset, w.mAl); - if (a.byteStride != 0) { - obj.AddMember("byteStride", a.byteStride, w.mAl); - } - obj.AddMember("componentType", int(a.componentType), w.mAl); obj.AddMember("count", a.count, w.mAl); obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); @@ -168,6 +164,9 @@ namespace glTF2 { obj.AddMember("buffer", bv.buffer->index, w.mAl); obj.AddMember("byteOffset", static_cast(bv.byteOffset), w.mAl); obj.AddMember("byteLength", static_cast(bv.byteLength), w.mAl); + if (bv.byteStride != 0) { + obj.AddMember("byteStride", bv.byteStride, w.mAl); + } obj.AddMember("target", int(bv.target), w.mAl); } diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index ed6814b7f..e6d4d1a3b 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -170,13 +170,13 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu bv->buffer = buffer; bv->byteOffset = unsigned(offset); bv->byteLength = length; //! The target that the WebGL buffer should be bound to. + bv->byteStride = 0; bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER; // accessor Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); acc->bufferView = bv; acc->byteOffset = 0; - acc->byteStride = 0; acc->componentType = compType; acc->count = count; acc->type = typeOut;