diff --git a/code/BlenderLoader.cpp b/code/BlenderLoader.cpp index 30aafc705..d24fad180 100644 --- a/code/BlenderLoader.cpp +++ b/code/BlenderLoader.cpp @@ -1045,7 +1045,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co } } } - matTexUvMappings.insert(std::make_pair(m, texuv)); + if (texuv.size()) { + matTexUvMappings.insert(std::make_pair(m, texuv)); + } } // collect texture coordinates, they're stored in a separate per-face buffer diff --git a/code/BlenderScene.cpp b/code/BlenderScene.cpp index abad7affc..ad2d6fbba 100644 --- a/code/BlenderScene.cpp +++ b/code/BlenderScene.cpp @@ -800,7 +800,6 @@ template <> void Structure::Convert( ) const { ReadFieldArray(dest.typemap, "typemap", db); - ReadField(dest.pad_i1, "pad_i1", db); ReadField(dest.totlayer, "totlayer", db); ReadField(dest.maxlayer, "maxlayer", db); ReadField(dest.totsize, "totsize", db); diff --git a/code/BlenderScene.h b/code/BlenderScene.h index b52ec20b5..b74d7b198 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -432,7 +432,6 @@ CustomData 208 struct CustomData : ElemBase { vector > layers; int typemap[42]; // CD_NUMTYPES - int pad_i1; int totlayer; int maxlayer; int totsize; diff --git a/code/ColladaHelper.h b/code/ColladaHelper.h index 0c90a42e6..fe6674b93 100644 --- a/code/ColladaHelper.h +++ b/code/ColladaHelper.h @@ -272,12 +272,13 @@ struct Node /** Node instances at this node */ std::vector mNodeInstances; - /** Rootnodes: Name of primary camera, if any */ + /** Root-nodes: Name of primary camera, if any */ std::string mPrimaryCamera; //! Constructor. Begin with a zero parent - Node() { - mParent = NULL; + Node() + : mParent( nullptr ){ + // empty } //! Destructor: delete all children subsequently diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 54178295c..d86985a29 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -181,26 +181,27 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I // ... then fill the materials with the now adjusted settings FillMaterials(parser, pScene); - // Apply unitsize scale calculation - pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0, - 0, parser.mUnitSize, 0, 0, - 0, 0, parser.mUnitSize, 0, - 0, 0, 0, 1); - if( !ignoreUpDirection ) { - // Convert to Y_UP, if different orientation - if( parser.mUpDirection == ColladaParser::UP_X) - pScene->mRootNode->mTransformation *= aiMatrix4x4( - 0, -1, 0, 0, - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - else if( parser.mUpDirection == ColladaParser::UP_Z) - pScene->mRootNode->mTransformation *= aiMatrix4x4( - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, -1, 0, 0, - 0, 0, 0, 1); - } + // Apply unitsize scale calculation + pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0, + 0, parser.mUnitSize, 0, 0, + 0, 0, parser.mUnitSize, 0, + 0, 0, 0, 1); + if( !ignoreUpDirection ) { + // Convert to Y_UP, if different orientation + if( parser.mUpDirection == ColladaParser::UP_X) + pScene->mRootNode->mTransformation *= aiMatrix4x4( + 0, -1, 0, 0, + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + else if( parser.mUpDirection == ColladaParser::UP_Z) + pScene->mRootNode->mTransformation *= aiMatrix4x4( + 1, 0, 0, 0, + 0, 0, 1, 0, + 0, -1, 0, 0, + 0, 0, 0, 1); + } + // store all meshes StoreSceneMeshes( pScene); @@ -740,10 +741,6 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada:: // create bones if given if( pSrcController && pSrcController->mType == Collada::Skin) { - // refuse if the vertex count does not match -// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices) -// throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count"); - // resolve references - joint names const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource); const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource); @@ -971,7 +968,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars for( size_t b = a+1; b < mAnims.size(); ++b) { aiAnimation* other = mAnims[b]; - if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond ) + if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && + other->mTicksPerSecond == templateAnim->mTicksPerSecond ) collectedAnimIndices.push_back( b); } diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index fc283ff8c..052cd51c4 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -68,7 +68,7 @@ using namespace Assimp::Formatter; // Constructor to be privately used by Importer ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) : mFileName( pFile ) - , mReader( NULL ) + , mReader( nullptr ) , mDataLibrary() , mAccessorLibrary() , mMeshLibrary() @@ -79,20 +79,20 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) , mLightLibrary() , mCameraLibrary() , mControllerLibrary() - , mRootNode( NULL ) + , mRootNode( nullptr ) , mAnims() , mUnitSize( 1.0f ) , mUpDirection( UP_Y ) , mFormat(FV_1_5_n ) // We assume the newest file format by default { // validate io-handler instance - if ( NULL == pIOHandler ) { + if (nullptr == pIOHandler ) { throw DeadlyImportError("IOSystem is NULL." ); } // open the file std::unique_ptr file( pIOHandler->Open(pFile ) ); - if (file.get() == NULL) { + if (file.get() == nullptr) { throw DeadlyImportError( "Failed to open file " + pFile + "." ); } @@ -363,17 +363,17 @@ void ColladaParser::ReadAnimationClipLibrary() void ColladaParser::PostProcessControllers() { - for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) - { - std::string meshId = it->second.mMeshId; - ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId); - while(findItr != mControllerLibrary.end()) { - meshId = findItr->second.mMeshId; - findItr = mControllerLibrary.find(meshId); - } + std::string meshId; + for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) { + meshId = it->second.mMeshId; + ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId); + while(findItr != mControllerLibrary.end()) { + meshId = findItr->second.mMeshId; + findItr = mControllerLibrary.find(meshId); + } - it->second.mMeshId = meshId; - } + it->second.mMeshId = meshId; + } } // ------------------------------------------------------------------------------------------------ diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 894c00740..725d7bf5a 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -150,14 +150,14 @@ Exporter::ExportFormatEntry gExporters[] = #endif #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER - Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), - Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2, aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), + Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), + Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), #endif #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 1bdd6e694..7e55e6c3e 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +using namespace ::Assimp; static const aiImporterDesc desc = { "Stanford Polygon Library (PLY) Importer", @@ -73,22 +73,20 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Internal stuff -namespace -{ - // ------------------------------------------------------------------------------------------------ - // Checks that property index is within range - template - const T &GetProperty(const std::vector &props, int idx) - { - if (static_cast(idx) >= props.size()) { - throw DeadlyImportError("Invalid .ply file: Property index is out of range."); +namespace { + // ------------------------------------------------------------------------------------------------ + // Checks that property index is within range + template + inline + const T &GetProperty(const std::vector &props, int idx) { + if (static_cast(idx) >= props.size()) { + throw DeadlyImportError("Invalid .ply file: Property index is out of range."); + } + + return props[idx]; } - - return props[idx]; - } } - // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer PLYImporter::PLYImporter() @@ -129,7 +127,7 @@ const aiImporterDesc* PLYImporter::GetInfo() const { // ------------------------------------------------------------------------------------------------ static bool isBigEndian(const char* szMe) { - ai_assert(NULL != szMe); + ai_assert(nullptr != szMe); // binary_little_endian // binary_big_endian @@ -150,7 +148,7 @@ static bool isBigEndian(const char* szMe) { // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - static const std::string mode = "rb"; + const std::string mode = "rb"; std::unique_ptr fileStream(pIOHandler->Open(pFile, mode)); if (!fileStream.get()) { throw DeadlyImportError("Failed to open file " + pFile + "."); @@ -184,7 +182,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy char* szMe = (char*)&this->mBuffer[0]; SkipSpacesAndLineEnd(szMe, (const char**)&szMe); - // determine the format of the file data and construct the aimesh + // determine the format of the file data and construct the aiMesh PLY::DOM sPlyDom; this->pcDOM = &sPlyDom; @@ -192,7 +190,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy if (TokenMatch(szMe, "ascii", 5)) { SkipLine(szMe, (const char**)&szMe); if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) { - if (mGeneratedMesh != NULL) { + if (mGeneratedMesh != nullptr) { delete(mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -206,7 +204,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy // skip the line, parse the rest of the header and build the DOM if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) { - if (mGeneratedMesh != NULL) { + if (mGeneratedMesh != nullptr) { delete(mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -215,7 +213,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)"); } } else { - if (mGeneratedMesh != NULL) { + if (mGeneratedMesh != nullptr) { delete(mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -225,7 +223,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy } } else { AI_DEBUG_INVALIDATE_PTR(this->mBuffer); - if (mGeneratedMesh != NULL) { + if (mGeneratedMesh != nullptr) { delete(mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -237,13 +235,13 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy //free the file buffer streamedBuffer.close(); - if (mGeneratedMesh == NULL) { + if (mGeneratedMesh == nullptr) { throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data "); } // if no face list is existing we assume that the vertex // list is containing a list of points - bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false; + bool pointsOnly = mGeneratedMesh->mFaces == nullptr ? true : false; if (pointsOnly) { mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT; } @@ -277,8 +275,8 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy } void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) { - ai_assert(NULL != pcElement); - ai_assert(NULL != instElement); + ai_assert(nullptr != pcElement); + ai_assert(nullptr != instElement); ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; @@ -416,7 +414,7 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn haveColor = true; } - // assume 1.0 for the alpha channel ifit is not set + // assume 1.0 for the alpha channel if it is not set if (0xFFFFFFFF == aiColors[3]) { cOut.a = 1.0; } else { @@ -481,225 +479,205 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn // ------------------------------------------------------------------------------------------------ // Convert a color component to [0...1] ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) { - switch (eType) - { - case EDT_Float: - return val.fFloat; - case EDT_Double: - return (ai_real)val.fDouble; + switch (eType) { + case EDT_Float: + return val.fFloat; + case EDT_Double: + return (ai_real)val.fDouble; + case EDT_UChar: + return (ai_real)val.iUInt / (ai_real)0xFF; + case EDT_Char: + return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF; + case EDT_UShort: + return (ai_real)val.iUInt / (ai_real)0xFFFF; + case EDT_Short: + return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF; + case EDT_UInt: + return (ai_real)val.iUInt / (ai_real)0xFFFF; + case EDT_Int: + return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f; + default: + break; + } - case EDT_UChar: - return (ai_real)val.iUInt / (ai_real)0xFF; - case EDT_Char: - return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF; - case EDT_UShort: - return (ai_real)val.iUInt / (ai_real)0xFFFF; - case EDT_Short: - return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF; - case EDT_UInt: - return (ai_real)val.iUInt / (ai_real)0xFFFF; - case EDT_Int: - return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f; - default:; - }; - return 0.0f; + return 0.0f; } // ------------------------------------------------------------------------------------------------ // Try to extract proper faces from the PLY DOM -void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) -{ - ai_assert(NULL != pcElement); - ai_assert(NULL != instElement); +void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, + unsigned int pos) { + ai_assert(nullptr != pcElement); + ai_assert(nullptr != instElement); - if (mGeneratedMesh == NULL) - throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces"); - - bool bOne = false; - - // index of the vertex index list - unsigned int iProperty = 0xFFFFFFFF; - PLY::EDataType eType = EDT_Char; - bool bIsTriStrip = false; - - // index of the material index property - //unsigned int iMaterialIndex = 0xFFFFFFFF; - //PLY::EDataType eType2 = EDT_Char; - - // texture coordinates - unsigned int iTextureCoord = 0xFFFFFFFF; - PLY::EDataType eType3 = EDT_Char; - - // face = unique number of vertex indices - if (PLY::EEST_Face == pcElement->eSemantic) - { - unsigned int _a = 0; - for (std::vector::const_iterator a = pcElement->alProperties.begin(); - a != pcElement->alProperties.end(); ++a, ++_a) - { - if (PLY::EST_VertexIndex == (*a).Semantic) - { - // must be a dynamic list! - if (!(*a).bIsList) - continue; - - iProperty = _a; - bOne = true; - eType = (*a).eType; - } - /*else if (PLY::EST_MaterialIndex == (*a).Semantic) - { - if ((*a).bIsList) - continue; - iMaterialIndex = _a; - bOne = true; - eType2 = (*a).eType; - }*/ - else if (PLY::EST_TextureCoordinates == (*a).Semantic) - { - // must be a dynamic list! - if (!(*a).bIsList) - continue; - iTextureCoord = _a; - bOne = true; - eType3 = (*a).eType; - } - } - } - // triangle strip - // TODO: triangle strip and material index support??? - else if (PLY::EEST_TriStrip == pcElement->eSemantic) - { - unsigned int _a = 0; - for (std::vector::const_iterator a = pcElement->alProperties.begin(); - a != pcElement->alProperties.end(); ++a, ++_a) - { - // must be a dynamic list! - if (!(*a).bIsList) - continue; - iProperty = _a; - bOne = true; - bIsTriStrip = true; - eType = (*a).eType; - break; - } - } - - // check whether we have at least one per-face information set - if (bOne) - { - if (mGeneratedMesh->mFaces == NULL) - { - mGeneratedMesh->mNumFaces = pcElement->NumOccur; - mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; + if (mGeneratedMesh == nullptr) { + throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces"); } - if (!bIsTriStrip) - { - // parse the list of vertex indices - if (0xFFFFFFFF != iProperty) - { - const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size(); - mGeneratedMesh->mFaces[pos].mNumIndices = iNum; - mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; + bool bOne = false; - std::vector::const_iterator p = - GetProperty(instElement->alProperties, iProperty).avList.begin(); + // index of the vertex index list + unsigned int iProperty = 0xFFFFFFFF; + PLY::EDataType eType = EDT_Char; + bool bIsTriStrip = false; - for (unsigned int a = 0; a < iNum; ++a, ++p) - { - mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo(*p, eType); - } - } + // index of the material index property + //unsigned int iMaterialIndex = 0xFFFFFFFF; + //PLY::EDataType eType2 = EDT_Char; - // parse the material index - // cannot be handled without processing the whole file first - /*if (0xFFFFFFFF != iMaterialIndex) - { - mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2); - }*/ + // texture coordinates + unsigned int iTextureCoord = 0xFFFFFFFF; + PLY::EDataType eType3 = EDT_Char; - if (0xFFFFFFFF != iTextureCoord) - { - const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); + // face = unique number of vertex indices + if (PLY::EEST_Face == pcElement->eSemantic) { + unsigned int _a = 0; + for (std::vector::const_iterator a = pcElement->alProperties.begin(); + a != pcElement->alProperties.end(); ++a, ++_a) { + if (PLY::EST_VertexIndex == (*a).Semantic) { + // must be a dynamic list! + if (!(*a).bIsList) { + continue; + } - //should be 6 coords - std::vector::const_iterator p = - GetProperty(instElement->alProperties, iTextureCoord).avList.begin(); - - if ((iNum / 3) == 2) // X Y coord - { - for (unsigned int a = 0; a < iNum; ++a, ++p) - { - unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2]; - if (vindex < mGeneratedMesh->mNumVertices) - { - if (mGeneratedMesh->mTextureCoords[0] == NULL) - { - mGeneratedMesh->mNumUVComponents[0] = 2; - mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; - } - - if (a % 2 == 0) - mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo(*p, eType3); - else - mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo(*p, eType3); - - mGeneratedMesh->mTextureCoords[0][vindex].z = 0; + iProperty = _a; + bOne = true; + eType = (*a).eType; + } else if (PLY::EST_TextureCoordinates == (*a).Semantic) { + // must be a dynamic list! + if (!(*a).bIsList) { + continue; + } + iTextureCoord = _a; + bOne = true; + eType3 = (*a).eType; } - } } - } } - else // triangle strips - { - // normally we have only one triangle strip instance where - // a value of -1 indicates a restart of the strip - bool flip = false; - const std::vector& quak = GetProperty(instElement->alProperties, iProperty).avList; - //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption - - int aiTable[2] = { -1, -1 }; - for (std::vector::const_iterator a = quak.begin(); a != quak.end(); ++a) { - const int p = PLY::PropertyInstance::ConvertTo(*a, eType); - - if (-1 == p) { - // restart the strip ... - aiTable[0] = aiTable[1] = -1; - flip = false; - continue; + // triangle strip + // TODO: triangle strip and material index support??? + else if (PLY::EEST_TriStrip == pcElement->eSemantic) { + unsigned int _a = 0; + for (std::vector::const_iterator a = pcElement->alProperties.begin(); + a != pcElement->alProperties.end(); ++a, ++_a) { + // must be a dynamic list! + if (!(*a).bIsList) { + continue; + } + iProperty = _a; + bOne = true; + bIsTriStrip = true; + eType = (*a).eType; + break; } - if (-1 == aiTable[0]) { - aiTable[0] = p; - continue; - } - if (-1 == aiTable[1]) { - aiTable[1] = p; - continue; + } + + // check whether we have at least one per-face information set + if (bOne) { + if (mGeneratedMesh->mFaces == nullptr) { + mGeneratedMesh->mNumFaces = pcElement->NumOccur; + mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; } - if (mGeneratedMesh->mFaces == NULL) + if (!bIsTriStrip) { + // parse the list of vertex indices + if (0xFFFFFFFF != iProperty) { + const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size(); + mGeneratedMesh->mFaces[pos].mNumIndices = iNum; + mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; + + std::vector::const_iterator p = + GetProperty(instElement->alProperties, iProperty).avList.begin(); + + for (unsigned int a = 0; a < iNum; ++a, ++p) { + mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo(*p, eType); + } + } + + // parse the material index + // cannot be handled without processing the whole file first + /*if (0xFFFFFFFF != iMaterialIndex) { - mGeneratedMesh->mNumFaces = pcElement->NumOccur; - mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; + mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2); + }*/ + + if (0xFFFFFFFF != iTextureCoord) { + const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); + + //should be 6 coords + std::vector::const_iterator p = + GetProperty(instElement->alProperties, iTextureCoord).avList.begin(); + + if ((iNum / 3) == 2) // X Y coord + { + for (unsigned int a = 0; a < iNum; ++a, ++p) { + unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2]; + if (vindex < mGeneratedMesh->mNumVertices) { + if (mGeneratedMesh->mTextureCoords[0] == nullptr ) { + mGeneratedMesh->mNumUVComponents[0] = 2; + mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; + } + + if (a % 2 == 0) { + mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo(*p, eType3); + } else { + mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo(*p, eType3); + } + + mGeneratedMesh->mTextureCoords[0][vindex].z = 0; + } + } + } + } + } else { // triangle strips + // normally we have only one triangle strip instance where + // a value of -1 indicates a restart of the strip + bool flip = false; + const std::vector& quak = GetProperty(instElement->alProperties, iProperty).avList; + //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption + + int aiTable[2] = { -1, -1 }; + for (std::vector::const_iterator a = quak.begin(); a != quak.end(); ++a) { + const int p = PLY::PropertyInstance::ConvertTo(*a, eType); + + if (-1 == p) { + // restart the strip ... + aiTable[0] = aiTable[1] = -1; + flip = false; + continue; + } + if (-1 == aiTable[0]) { + aiTable[0] = p; + continue; + } + if (-1 == aiTable[1]) { + aiTable[1] = p; + continue; + } + + if (mGeneratedMesh->mFaces == nullptr) { + mGeneratedMesh->mNumFaces = pcElement->NumOccur; + mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; + } + + mGeneratedMesh->mFaces[pos].mNumIndices = 3; + mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3]; + mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0]; + mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1]; + mGeneratedMesh->mFaces[pos].mIndices[2] = p; + + // every second pass swap the indices. + flip = !flip; + if ( flip ) { + std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]); + } + + aiTable[0] = aiTable[1]; + aiTable[1] = p; + } } - - mGeneratedMesh->mFaces[pos].mNumIndices = 3; - mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3]; - mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0]; - mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1]; - mGeneratedMesh->mFaces[pos].mIndices[2] = p; - - if ((flip = !flip)) { - std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]); - } - - aiTable[0] = aiTable[1]; - aiTable[1] = p; - } } - } } // ------------------------------------------------------------------------------------------------ diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index 7d9282745..f9163de2a 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -27,7 +27,7 @@ additional_dirs, ext_whitelist = [],[] if os.name=='posix': additional_dirs.append('./') additional_dirs.append('/usr/lib/') - additional_dirs.append('/usr/lib/x86_64-linux-gnu') + additional_dirs.append('/usr/lib/x86_64-linux-gnu/') additional_dirs.append('/usr/local/lib/') if 'LD_LIBRARY_PATH' in os.environ: @@ -222,11 +222,17 @@ def search_library(): for filename in os.listdir(curfolder): # our minimum requirement for candidates is that # they should contain 'assimp' somewhere in - # their name - if filename.lower().find('assimp')==-1 or\ - os.path.splitext(filename)[-1].lower() not in ext_whitelist: + # their name + if filename.lower().find('assimp')==-1 : continue - + is_out=1 + for et in ext_whitelist: + if et in filename.lower(): + is_out=0 + break + if is_out: + continue + library_path = os.path.join(curfolder, filename) logger.debug('Try ' + library_path) try: diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7c5ff3706..d92b52b5a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -106,6 +106,7 @@ SET( IMPORTERS unit/utBlendImportAreaLight.cpp unit/utBlenderImportExport.cpp unit/utBlendImportMaterials.cpp + unit/utBlenderWork.cpp unit/utBVHImportExport.cpp unit/utColladaExportCamera.cpp unit/utColladaExportLight.cpp diff --git a/test/models/BLEND/test_279.blend b/test/models/BLEND/test_279.blend new file mode 100644 index 000000000..78d35485e Binary files /dev/null and b/test/models/BLEND/test_279.blend differ diff --git a/test/models/IRR/instancing.irr b/test/models/IRR/instancing.irr index f39ee1939..6687f4fdb 100644 Binary files a/test/models/IRR/instancing.irr and b/test/models/IRR/instancing.irr differ diff --git a/test/unit/utBlenderWork.cpp b/test/unit/utBlenderWork.cpp new file mode 100644 index 000000000..a17764673 --- /dev/null +++ b/test/unit/utBlenderWork.cpp @@ -0,0 +1,83 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, 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 +#include +#include +#include + +using namespace ::Assimp; + +class BlenderWorkTest : public ::testing::Test { +public: + virtual void SetUp() + { + im = new Assimp::Importer(); + } + + virtual void TearDown() + { + delete im; + } + +protected: + + Assimp::Importer* im; +}; + +TEST_F(BlenderWorkTest,work_279) { + const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/test_279.blend", aiProcess_ValidateDataStructure); + ASSERT_TRUE(pTest != NULL); + + // material has 2 diffuse textures + ASSERT_TRUE(pTest->HasMaterials()); + ASSERT_TRUE(pTest->HasMeshes()); + ASSERT_TRUE(pTest->mMeshes[0]->mNumVertices > 0); + ASSERT_EQ(44, pTest->mMeshes[0]->mNumFaces); + EXPECT_EQ(1, pTest->mNumMaterials); +} + + + + + diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index 85dbbbae1..fd12b8e7f 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -1261,9 +1261,10 @@ void CGLView::Camera_Set(const size_t pCameraNumber) gluLookAt(hcam.Position.x, hcam.Position.y, hcam.Position.z, hcam.Target.x, hcam.Target.y, hcam.Target.z, up.x, up.y, up.z); } -void CGLView::Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial) -{ -auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 180.0; }; +void CGLView::Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial) { + auto deg2rad = [](const GLfloat pDegree) -> GLfloat { + return pDegree * AI_MATH_PI / 180.0; + }; aiMatrix4x4 mat_rot; @@ -1276,7 +1277,7 @@ auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 18 void CGLView::Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial) { -auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 180.0; }; + auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * AI_MATH_PI / 180.0; }; aiMatrix4x4 mat_rot; @@ -1289,7 +1290,7 @@ auto deg2rad = [](const GLfloat pDegree) -> GLfloat { return pDegree * M_PI / 18 void CGLView::Camera_Translate(const GLfloat pTranslate_X, const GLfloat pTranslate_Y, const GLfloat pTranslate_Z) { -aiVector3D vect_tr(pTranslate_X, pTranslate_Y, pTranslate_Z); + aiVector3D vect_tr(pTranslate_X, pTranslate_Y, pTranslate_Z); vect_tr *= mHelper_Camera.Rotation_AroundCamera; mHelper_Camera.Translation_ToScene += vect_tr; diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index 85a70ba6b..57140b304 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -132,9 +132,8 @@ void MainWindow::LogError(const QString& pMessage) void MainWindow::mousePressEvent(QMouseEvent* pEvent) { -const QPoint ms_pt = pEvent->pos(); - -__unused aiVector3D temp_v3; + const QPoint ms_pt = pEvent->pos(); + aiVector3D temp_v3; // Check if GLView is pointed. if(childAt(ms_pt) == mGLView) @@ -305,30 +304,32 @@ void MainWindow::SceneObject_LightSource(const QString& pName) ui->lstLight->selectAll(); } -void MainWindow::on_butOpenFile_clicked() -{ -aiString filter_temp; -QString filename, filter; +void MainWindow::on_butOpenFile_clicked() { + aiString filter_temp; + mImporter.GetExtensionList( filter_temp ); - mImporter.GetExtensionList(filter_temp); - filter = filter_temp.C_Str(); + QString filename, filter; + filter = filter_temp.C_Str(); filter.replace(';', ' '); filter.append(" ;; All (*.*)"); filename = QFileDialog::getOpenFileName(this, "Choose the file", "", filter); - if(!filename.isEmpty()) ImportFile(filename); + if (!filename.isEmpty()) { + ImportFile( filename ); + } } void MainWindow::on_butExport_clicked() { -using namespace Assimp; + using namespace Assimp; -QString filename, filter, format_id; -Exporter exporter; -QTime time_begin; -aiReturn rv; -QStringList exportersList; -QMap exportersMap; +#ifndef ASSIMP_BUILD_NO_EXPORT + QString filename, filter, format_id; + Exporter exporter; + QTime time_begin; + aiReturn rv; + QStringList exportersList; + QMap exportersMap; if(mScene == nullptr) @@ -373,6 +374,7 @@ QMap exportersMap; LogError(errorMessage); QMessageBox::critical(this, "Export error", errorMessage); } +#endif } void MainWindow::on_cbxLighting_clicked(bool pChecked) @@ -382,11 +384,7 @@ void MainWindow::on_cbxLighting_clicked(bool pChecked) else mGLView->Lighting_Disable(); -#if ASSIMP_QT4_VIEWER - mGLView->updateGL(); -#else mGLView->update(); -#endif // ASSIMP_QT4_VIEWER } void MainWindow::on_lstLight_itemSelectionChanged() @@ -438,9 +436,5 @@ void MainWindow::on_cbxDrawAxes_clicked(bool checked) void MainWindow::on_cbxTextures_clicked(bool checked) { mGLView->Enable_Textures(checked); -#if ASSIMP_QT4_VIEWER - mGLView->updateGL(); -#else mGLView->update(); -#endif // ASSIMP_QT4_VIEWER } diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index e0d17181d..dd8f25332 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -6,7 +6,7 @@ #pragma once // Header files, Qt. -#if ASSIMP_QT4_VIEWER +#if defined ASSIMP_QT4_VIEWER # include #else # include